From a43e38e7bdc183709399bc49179b7137c6debe23 Mon Sep 17 00:00:00 2001 From: Gokul Singaraju Date: Thu, 21 Sep 2017 12:51:55 -0400 Subject: Adding C and Java VES Vendor libs Issue-Id: VNFRQTS-94 Change-Id: Iee0e154a94f3ef4ea43efcd474acacb0fa54c43f Signed-Off-by: Gokul Singaraju --- .../ves_clibrary/evel/evel-library/LICENSE.TXT | 22 + .../evel/evel-library/bldjobs/Makefile | 289 ++ .../evel-library/code/evel_library/double_list.c | 182 + .../evel-library/code/evel_library/double_list.h | 57 + .../evel/evel-library/code/evel_library/evel.c | 396 ++ .../evel/evel-library/code/evel_library/evel.h | 4494 ++++++++++++++++++++ .../evel-library/code/evel_library/evel_event.c | 755 ++++ .../code/evel_library/evel_event_mgr.c | 1050 +++++ .../evel-library/code/evel_library/evel_fault.c | 367 ++ .../code/evel_library/evel_heartbeat_fields.c | 269 ++ .../evel-library/code/evel_library/evel_internal.h | 858 ++++ .../code/evel_library/evel_internal_event.c | 113 + .../code/evel_library/evel_json_buffer.c | 870 ++++ .../code/evel_library/evel_jsonobject.c | 446 ++ .../evel-library/code/evel_library/evel_logging.c | 167 + .../code/evel_library/evel_mobile_flow.c | 2122 +++++++++ .../evel-library/code/evel_library/evel_option.c | 526 +++ .../evel-library/code/evel_library/evel_other.c | 492 +++ .../code/evel_library/evel_reporting_measurement.c | 437 ++ .../code/evel_library/evel_scaling_measurement.c | 3716 ++++++++++++++++ .../code/evel_library/evel_sipsignaling.c | 574 +++ .../code/evel_library/evel_state_change.c | 286 ++ .../evel-library/code/evel_library/evel_strings.c | 473 ++ .../evel-library/code/evel_library/evel_syslog.c | 505 +++ .../code/evel_library/evel_threshold_cross.c | 531 +++ .../evel-library/code/evel_library/evel_throttle.c | 2103 +++++++++ .../evel-library/code/evel_library/evel_throttle.h | 214 + .../code/evel_library/evel_voicequality.c | 640 +++ .../evel-library/code/evel_library/hashtable.c | 222 + .../evel-library/code/evel_library/hashtable.h | 97 + .../evel/evel-library/code/evel_library/jsmn.c | 328 ++ .../evel/evel-library/code/evel_library/jsmn.h | 93 + .../evel/evel-library/code/evel_library/license.md | 81 + .../evel/evel-library/code/evel_library/metadata.c | 592 +++ .../evel/evel-library/code/evel_library/metadata.h | 58 + .../evel-library/code/evel_library/quickstart.md | 445 ++ .../evel/evel-library/code/evel_library/readme.md | 236 + .../evel-library/code/evel_library/ring_buffer.c | 192 + .../evel-library/code/evel_library/ring_buffer.h | 96 + .../evel/evel-library/code/evel_unit/evel_unit.c | 3484 +++++++++++++++ .../evel/evel-library/docs/source/evel/README | 1 + .../evel/evel-library/libs/x86_64/README | 1 + .../evel/evel-library/output/x86_64/README | 1 + .../ves_clibrary/evel/evel-library/readme.md | 28 + .../evel/evel-test-collector/LICENSE.md | 18 + .../evel/evel-test-collector/README.md | 30 + .../evel-test-collector/code/collector/LICENSE.TXT | 22 + .../evel-test-collector/code/collector/__init__.py | 0 .../code/collector/collector.py | 643 +++ .../code/collector/rest_dispatcher.py | 92 + .../code/collector/test_control.py | 180 + .../evel/evel-test-collector/config/collector.conf | 99 + .../docs/att_interface_definition/LICENSE.TXT | 22 + .../docs/att_interface_definition/base_schema.json | 10 + .../event_format_updated.json | 1885 ++++++++ .../test_control_schema.json | 15 + .../att_interface_definition/throttle_schema.json | 9 + .../docs/test_collector_user_guide/LICENSE.TXT | 22 + .../images/architecture.png | Bin 0 -> 156511 bytes .../test_collector_user_guide.md | 294 ++ .../scripts/linux/go-collector.sh | 21 + .../scripts/windows/go-collector.bat | 22 + 62 files changed, 32293 insertions(+) create mode 100644 veslibrary/ves_clibrary/evel/evel-library/LICENSE.TXT create mode 100644 veslibrary/ves_clibrary/evel/evel-library/bldjobs/Makefile create mode 100644 veslibrary/ves_clibrary/evel/evel-library/code/evel_library/double_list.c create mode 100644 veslibrary/ves_clibrary/evel/evel-library/code/evel_library/double_list.h create mode 100644 veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel.c create mode 100644 veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel.h create mode 100644 veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_event.c create mode 100644 veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_event_mgr.c create mode 100644 veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_fault.c create mode 100644 veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_heartbeat_fields.c create mode 100644 veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_internal.h create mode 100644 veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_internal_event.c create mode 100644 veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_json_buffer.c create mode 100644 veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_jsonobject.c create mode 100644 veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_logging.c create mode 100644 veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_mobile_flow.c create mode 100644 veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_option.c create mode 100644 veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_other.c create mode 100644 veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_reporting_measurement.c create mode 100644 veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_scaling_measurement.c create mode 100644 veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_sipsignaling.c create mode 100644 veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_state_change.c create mode 100644 veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_strings.c create mode 100644 veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_syslog.c create mode 100644 veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_threshold_cross.c create mode 100644 veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_throttle.c create mode 100644 veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_throttle.h create mode 100644 veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_voicequality.c create mode 100644 veslibrary/ves_clibrary/evel/evel-library/code/evel_library/hashtable.c create mode 100644 veslibrary/ves_clibrary/evel/evel-library/code/evel_library/hashtable.h create mode 100644 veslibrary/ves_clibrary/evel/evel-library/code/evel_library/jsmn.c create mode 100644 veslibrary/ves_clibrary/evel/evel-library/code/evel_library/jsmn.h create mode 100644 veslibrary/ves_clibrary/evel/evel-library/code/evel_library/license.md create mode 100644 veslibrary/ves_clibrary/evel/evel-library/code/evel_library/metadata.c create mode 100644 veslibrary/ves_clibrary/evel/evel-library/code/evel_library/metadata.h create mode 100644 veslibrary/ves_clibrary/evel/evel-library/code/evel_library/quickstart.md create mode 100644 veslibrary/ves_clibrary/evel/evel-library/code/evel_library/readme.md create mode 100644 veslibrary/ves_clibrary/evel/evel-library/code/evel_library/ring_buffer.c create mode 100644 veslibrary/ves_clibrary/evel/evel-library/code/evel_library/ring_buffer.h create mode 100644 veslibrary/ves_clibrary/evel/evel-library/code/evel_unit/evel_unit.c create mode 100644 veslibrary/ves_clibrary/evel/evel-library/docs/source/evel/README create mode 100644 veslibrary/ves_clibrary/evel/evel-library/libs/x86_64/README create mode 100644 veslibrary/ves_clibrary/evel/evel-library/output/x86_64/README create mode 100644 veslibrary/ves_clibrary/evel/evel-library/readme.md create mode 100644 veslibrary/ves_clibrary/evel/evel-test-collector/LICENSE.md create mode 100644 veslibrary/ves_clibrary/evel/evel-test-collector/README.md create mode 100644 veslibrary/ves_clibrary/evel/evel-test-collector/code/collector/LICENSE.TXT create mode 100644 veslibrary/ves_clibrary/evel/evel-test-collector/code/collector/__init__.py create mode 100644 veslibrary/ves_clibrary/evel/evel-test-collector/code/collector/collector.py create mode 100644 veslibrary/ves_clibrary/evel/evel-test-collector/code/collector/rest_dispatcher.py create mode 100644 veslibrary/ves_clibrary/evel/evel-test-collector/code/collector/test_control.py create mode 100644 veslibrary/ves_clibrary/evel/evel-test-collector/config/collector.conf create mode 100644 veslibrary/ves_clibrary/evel/evel-test-collector/docs/att_interface_definition/LICENSE.TXT create mode 100644 veslibrary/ves_clibrary/evel/evel-test-collector/docs/att_interface_definition/base_schema.json create mode 100644 veslibrary/ves_clibrary/evel/evel-test-collector/docs/att_interface_definition/event_format_updated.json create mode 100644 veslibrary/ves_clibrary/evel/evel-test-collector/docs/att_interface_definition/test_control_schema.json create mode 100644 veslibrary/ves_clibrary/evel/evel-test-collector/docs/att_interface_definition/throttle_schema.json create mode 100644 veslibrary/ves_clibrary/evel/evel-test-collector/docs/test_collector_user_guide/LICENSE.TXT create mode 100644 veslibrary/ves_clibrary/evel/evel-test-collector/docs/test_collector_user_guide/images/architecture.png create mode 100644 veslibrary/ves_clibrary/evel/evel-test-collector/docs/test_collector_user_guide/test_collector_user_guide.md create mode 100644 veslibrary/ves_clibrary/evel/evel-test-collector/scripts/linux/go-collector.sh create mode 100644 veslibrary/ves_clibrary/evel/evel-test-collector/scripts/windows/go-collector.bat (limited to 'veslibrary/ves_clibrary/evel') diff --git a/veslibrary/ves_clibrary/evel/evel-library/LICENSE.TXT b/veslibrary/ves_clibrary/evel/evel-library/LICENSE.TXT new file mode 100644 index 0000000..ae12da2 --- /dev/null +++ b/veslibrary/ves_clibrary/evel/evel-library/LICENSE.TXT @@ -0,0 +1,22 @@ +/* + * ============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. + * + */ diff --git a/veslibrary/ves_clibrary/evel/evel-library/bldjobs/Makefile b/veslibrary/ves_clibrary/evel/evel-library/bldjobs/Makefile new file mode 100644 index 0000000..5a3a111 --- /dev/null +++ b/veslibrary/ves_clibrary/evel/evel-library/bldjobs/Makefile @@ -0,0 +1,289 @@ +#*************************************************************************//** +#* +#* 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) +CODE_ROOT=$(CURDIR)/.. +EVELLIB_ROOT=$(CODE_ROOT)/code/evel_library +EVELUNIT_ROOT=$(CODE_ROOT)/code/evel_unit +LIBS_DIR=$(CODE_ROOT)/libs/x86_$(ARCH) +OUTPUT_DIR=$(CODE_ROOT)/output/x86_$(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) +CFLAGS=-Wall -Wextra -m$(ARCH) -g -fPIC +LIBCFLAGS=-Wall -Wextra -m$(ARCH) -g -shared -fPIC + +#****************************************************************************** +# 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) $< + +all: api_library \ + +clean: api_library_clean \ + evel_unit_clean \ + +install: api_library + @echo Copying $(LIBS_DIR)/libevel.so + sudo cp $(LIBS_DIR)/libevel.so /usr/lib + sudo ldconfig -n -v /usr/lib + +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)/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/x86_$(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/x86_$(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/x86_64/README \ + output/x86_64/README \ + readme.md + +package_clean: + @echo Clean delivery packages + @$(RM) $(OUTPUTDIR)/*.tgz diff --git a/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/double_list.c b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/double_list.c new file mode 100644 index 0000000..6ce8a80 --- /dev/null +++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/double_list.c @@ -0,0 +1,182 @@ + +/*************************************************************************//** + * + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************/ + +/**************************************************************************//** + * @file + * A simple double-linked list. + * + * @note No thread protection so you will need to use appropriate + * synchronization if use spans multiple threads. + * + ****************************************************************************/ + +#include +#include + +#include "double_list.h" +#include "evel.h" + +/**************************************************************************//** + * List initialization. + * + * Initialize the list supplied to be empty. + * + * @param list Pointer to the list to be initialized. + + * @returns Nothing +******************************************************************************/ +void dlist_initialize(DLIST * list) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check assumptions. */ + /***************************************************************************/ + assert(list != NULL); + + /***************************************************************************/ + /* Initialize the list as empty. */ + /***************************************************************************/ + list->head = NULL; + list->tail = NULL; + + EVEL_EXIT(); +} + +void * dlist_pop_last(DLIST * list) +{ + void *item = NULL; + DLIST_ITEM *current_tail = NULL; + DLIST_ITEM *new_tail = NULL; + + assert(list != NULL); + + current_tail = list->tail; + if (current_tail != NULL) + { + item = current_tail->item; + new_tail = current_tail->previous; + if (new_tail == NULL) + { + list->head = NULL; + list->tail = NULL; + } + else + { + new_tail->next = NULL; + list->tail = new_tail; + } + free(current_tail); + } + + return item; +} + +void dlist_push_first(DLIST * list, void * item) +{ + DLIST_ITEM * new_element = NULL; + DLIST_ITEM * current_head = NULL; + + /***************************************************************************/ + /* Check assumptions. Note that we do allow putting NULL pointers into */ + /* the list - not sure you'd want to, but let it happen. */ + /***************************************************************************/ + assert(list != NULL); + + current_head = list->head; + + new_element = malloc(sizeof(DLIST_ITEM)); + assert(new_element != NULL); + new_element->next = current_head; + new_element->previous = NULL; + new_element->item = item; + list->head = new_element; + + if (current_head != NULL) + { + current_head->previous = new_element; + } + else + { + list->tail = new_element; + } +} + +void dlist_push_last(DLIST * list, void * item) +{ + DLIST_ITEM * new_element = NULL; + DLIST_ITEM * current_tail = NULL; + + /***************************************************************************/ + /* Check assumptions. Note that we do allow putting NULL pointers into */ + /* the list - not sure you'd want to, but let it happen. */ + /***************************************************************************/ + assert(list != NULL); + + current_tail = list->tail; + + new_element = malloc(sizeof(DLIST_ITEM)); + assert(new_element != NULL); + new_element->next = NULL; + new_element->previous = current_tail; + new_element->item = item; + list->tail = new_element; + + if (current_tail != NULL) + { + current_tail->next = new_element; + } + else + { + list->head = new_element; + } +} + +DLIST_ITEM * dlist_get_first(DLIST * list) +{ + return list->head; +} + +DLIST_ITEM * dlist_get_last(DLIST * list) +{ + return list->tail; +} + +DLIST_ITEM * dlist_get_next(DLIST_ITEM * item) +{ + return item->next; +} + +int dlist_is_empty(DLIST * list) +{ + return (list->head == NULL); +} + +int dlist_count(DLIST * list) +{ + int count = 0; + DLIST_ITEM * item = list->head; + + while (item != NULL) + { + count++; + item = item->next; + } + + return count; +} diff --git a/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/double_list.h b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/double_list.h new file mode 100644 index 0000000..5cf7e1a --- /dev/null +++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/double_list.h @@ -0,0 +1,57 @@ +/*************************************************************************//** + * + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************/ + +/**************************************************************************//** + * @file + * A simple double-linked list. + * + * @note No thread protection so you will need to use appropriate + * synchronization if use spans multiple threads. + * + ****************************************************************************/ + +#ifndef DOUBLE_LIST_INCLUDED +#define DOUBLE_LIST_INCLUDED + +typedef struct dlist_item +{ + struct dlist_item * previous; + struct dlist_item * next; + void * item; +} DLIST_ITEM; + +/**************************************************************************//** + * Double-linked list structure + *****************************************************************************/ +typedef struct dlist +{ + DLIST_ITEM * head; + DLIST_ITEM * tail; +} DLIST; + + +void dlist_initialize(DLIST * list); +void * dlist_pop_last(DLIST * list); +void dlist_push_first(DLIST * list, void * item); +void dlist_push_last(DLIST * list, void * item); +DLIST_ITEM * dlist_get_first(DLIST * list); +DLIST_ITEM * dlist_get_last(DLIST * list); +DLIST_ITEM * dlist_get_next(DLIST_ITEM * item); +int dlist_is_empty(DLIST * list); +int dlist_count(DLIST * list); + +#endif diff --git a/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel.c b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel.c new file mode 100644 index 0000000..20b386d --- /dev/null +++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel.c @@ -0,0 +1,396 @@ +/*************************************************************************//** + * + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************/ + +/**************************************************************************//** + * @file + * Source module isolating the ECOMP Vendor Event Listener (EVEL) API. + * + * This file implements the EVEL library which is intended to provide a + * simple wrapper around the complexity of AT&T's Vendor Event Listener API so + * that VNFs can use it without worrying about details of: + * + * * The API's encoding into JSON. + * * The API's transport over HTTP/HTTPS. + * + ****************************************************************************/ + +#include +#include +#include +#include +#include + +#include "evel.h" +#include "evel_internal.h" +#include "evel_throttle.h" +#include "metadata.h" + +/**************************************************************************//** + * The type of equipment represented by this VNF. + *****************************************************************************/ +EVEL_SOURCE_TYPES event_source_type = EVEL_SOURCE_OTHER; + +/**************************************************************************//** + * The Functional Role of the equipment represented by this VNF. + *****************************************************************************/ +char *functional_role = NULL; + +/**************************************************************************//** + * Library initialization. + * + * Initialize the EVEL library. + * + * @note This function initializes the cURL library. Applications making use + * of libcurl may need to pull the initialization out of here. Note + * also that this function is not threadsafe as a result - refer to + * libcurl's API documentation for relevant warnings. + * + * @sa Matching Term function. + * + * @param fqdn The API's FQDN or IP address. + * @param port The API's port. + * @param path The optional path (may be NULL). + * @param topic The optional topic part of the URL (may be NULL). + * @param secure Whether to use HTTPS (0=HTTP, 1=HTTPS) + * @param username Username for Basic Authentication of requests. + * @param password Password for Basic Authentication of requests. + * @param source_type The kind of node we represent. + * @param role The role this node undertakes. + * @param verbosity 0 for normal operation, positive values for chattier + * logs. + * + * @returns Status code + * @retval EVEL_SUCCESS On success + * @retval ::EVEL_ERR_CODES On failure. + *****************************************************************************/ +EVEL_ERR_CODES evel_initialize(const char * const fqdn, + int port, + const char * const path, + const char * const topic, + int secure, + const char * const username, + const char * const password, + EVEL_SOURCE_TYPES source_type, + const char * const role, + int verbosity + ) +{ + EVEL_ERR_CODES rc = EVEL_SUCCESS; + char base_api_url[EVEL_MAX_URL_LEN + 1] = {0}; + char event_api_url[EVEL_MAX_URL_LEN + 1] = {0}; + char throt_api_url[EVEL_MAX_URL_LEN + 1] = {0}; + char path_url[EVEL_MAX_URL_LEN + 1] = {0}; + char topic_url[EVEL_MAX_URL_LEN + 1] = {0}; + char version_string[10] = {0}; + int offset; + + /***************************************************************************/ + /* Check assumptions. */ + /***************************************************************************/ + assert(fqdn != NULL); + assert(port > 0 && port <= 65535); + assert(source_type < EVEL_MAX_SOURCE_TYPES); + assert(role != NULL); + + /***************************************************************************/ + /* Start logging so we can report on progress. */ + /***************************************************************************/ + log_initialize(verbosity == 0 ? EVEL_LOG_INFO : EVEL_LOG_DEBUG, "EVEL"); + EVEL_INFO("EVEL started"); + EVEL_INFO("API server is: %s", fqdn); + EVEL_INFO("API port is: %d", port); + + if (path != NULL) + { + EVEL_INFO("API path is: %s", path); + } + else + { + EVEL_INFO("No API path"); + } + + if (topic != NULL) + { + EVEL_INFO("API topic is: %s", topic); + } + else + { + EVEL_INFO("No API topic"); + } + + EVEL_INFO("API transport is: %s", secure ? "HTTPS" : "HTTP"); + EVEL_INFO("Event Source Type is: %d", source_type); + EVEL_INFO("Functional Role is: %s", role); + EVEL_INFO("Log verbosity is: %d", verbosity); + + /***************************************************************************/ + /* Initialize event throttling to the default state. */ + /***************************************************************************/ + evel_throttle_initialize(); + + /***************************************************************************/ + /* Save values we will need during operation. */ + /***************************************************************************/ + event_source_type = source_type; + functional_role = strdup(role); + + /***************************************************************************/ + /* Ensure there are no trailing zeroes and unnecessary decimal points in */ + /* the version. */ + /***************************************************************************/ + offset = sprintf(version_string, "%d", EVEL_API_MAJOR_VERSION); + + if (EVEL_API_MINOR_VERSION != 0) + { + sprintf(version_string + offset, ".%d", EVEL_API_MINOR_VERSION); + } + + /***************************************************************************/ + /* Build a common base of the API URLs. */ + /***************************************************************************/ + strcpy(path_url, "/"); + snprintf(base_api_url, + EVEL_MAX_URL_LEN, + "%s://%s:%d%s/eventListener/v%s", + secure ? "https" : "http", + fqdn, + port, + (((path != NULL) && (strlen(path) > 0)) ? + strncat(path_url, path, EVEL_MAX_URL_LEN) : ""), + version_string); + + /***************************************************************************/ + /* Build the URL to the event API. */ + /***************************************************************************/ + strcpy(topic_url, "/"); + snprintf(event_api_url, + EVEL_MAX_URL_LEN, + "%s%s", + base_api_url, + (((topic != NULL) && (strlen(topic) > 0)) ? + strncat(topic_url, topic, EVEL_MAX_URL_LEN) : "")); + EVEL_INFO("Vendor Event Listener API is located at: %s", event_api_url); + + /***************************************************************************/ + /* Build the URL to the throttling API. */ + /***************************************************************************/ + snprintf(throt_api_url, + EVEL_MAX_URL_LEN, + "%s/clientThrottlingState", + base_api_url); + EVEL_INFO("Vendor Event Throttling API is located at: %s", throt_api_url); + + /***************************************************************************/ + /* Spin-up the event-handler, which gets cURL readied for use. */ + /***************************************************************************/ + rc = event_handler_initialize(event_api_url, + throt_api_url, + username, + password, + verbosity); + if (rc != EVEL_SUCCESS) + { + log_error_state("Failed to initialize event handler (including cURL)"); + goto exit_label; + } + + /***************************************************************************/ + /* Extract the metadata from OpenStack. If we fail to extract it, we */ + /* record that in the logs, but carry on, assuming we're in a test */ + /* without a metadata service. */ + /***************************************************************************/ + rc = openstack_metadata(verbosity); + if (rc != EVEL_SUCCESS) + { + EVEL_INFO("Failed to load OpenStack metadata - assuming test environment"); + rc = EVEL_SUCCESS; + } + + /***************************************************************************/ + /* Start the event handler thread. */ + /***************************************************************************/ + rc = event_handler_run(); + if (rc != EVEL_SUCCESS) + { + log_error_state("Failed to start event handler thread. " + "Error code=%d", rc); + goto exit_label; + } + +exit_label: + return(rc); +} + +/**************************************************************************//** + * Clean up the EVEL library. + * + * @note that at present don't expect Init/Term cycling not to leak memory! + * + * @returns Status code + * @retval EVEL_SUCCESS On success + * @retval "One of ::EVEL_ERR_CODES" On failure. + *****************************************************************************/ +EVEL_ERR_CODES evel_terminate(void) +{ + int rc = EVEL_SUCCESS; + + /***************************************************************************/ + /* First terminate any pending transactions in the event-posting thread. */ + /***************************************************************************/ + rc = event_handler_terminate(); + if (rc != EVEL_SUCCESS) + { + log_error_state("Failed to terminate EVEL library cleanly!"); + } + + /***************************************************************************/ + /* Shut down the Event Handler library in a tidy manner. */ + /***************************************************************************/ + curl_global_cleanup(); + + /***************************************************************************/ + /* Clean up allocated memory. */ + /***************************************************************************/ + free(functional_role); + + /***************************************************************************/ + /* Clean up event throttling. */ + /***************************************************************************/ + evel_throttle_terminate(); + + EVEL_INFO("EVEL stopped"); + return(rc); +} + +/**************************************************************************//** + * Free an event. + * + * Free off the event supplied. Will free all the contained allocated memory. + * + * @note It is safe to free a NULL pointer. + *****************************************************************************/ +void evel_free_event(void * event) +{ + EVENT_HEADER * evt_ptr = event; + EVEL_ENTER(); + + if (event != NULL) + { + /*************************************************************************/ + /* Work out what kind of event we're dealing with so we can cast it */ + /* appropriately. */ + /*************************************************************************/ + switch (evt_ptr->event_domain) + { + case EVEL_DOMAIN_INTERNAL: + EVEL_DEBUG("Event is an Internal event at %lp", evt_ptr); + evel_free_internal_event((EVENT_INTERNAL *) evt_ptr); + memset(evt_ptr, 0, sizeof(EVENT_INTERNAL)); + free(evt_ptr); + break; + + case EVEL_DOMAIN_HEARTBEAT: + EVEL_DEBUG("Event is a Heartbeat at %lp", evt_ptr); + evel_free_header(evt_ptr); + memset(evt_ptr, 0, sizeof(EVENT_HEADER)); + free(evt_ptr); + break; + + case EVEL_DOMAIN_FAULT: + EVEL_DEBUG("Event is a Fault at %lp", evt_ptr); + evel_free_fault((EVENT_FAULT *)evt_ptr); + memset(evt_ptr, 0, sizeof(EVENT_FAULT)); + free(evt_ptr); + break; + + case EVEL_DOMAIN_MEASUREMENT: + EVEL_DEBUG("Event is a Measurement at %lp", evt_ptr); + evel_free_measurement((EVENT_MEASUREMENT *)evt_ptr); + memset(evt_ptr, 0, sizeof(EVENT_MEASUREMENT)); + free(evt_ptr); + break; + + case EVEL_DOMAIN_MOBILE_FLOW: + EVEL_DEBUG("Event is a Mobile Flow at %lp", evt_ptr); + evel_free_mobile_flow((EVENT_MOBILE_FLOW *)evt_ptr); + memset(evt_ptr, 0, sizeof(EVENT_MOBILE_FLOW)); + free(evt_ptr); + break; + + case EVEL_DOMAIN_REPORT: + EVEL_DEBUG("Event is a Report at %lp", evt_ptr); + evel_free_report((EVENT_REPORT *)evt_ptr); + memset(evt_ptr, 0, sizeof(EVENT_REPORT)); + free(evt_ptr); + break; + + case EVEL_DOMAIN_HEARTBEAT_FIELD: + EVEL_DEBUG("Event is a Heartbeat Field Event at %lp", evt_ptr); + evel_free_hrtbt_field((EVENT_HEARTBEAT_FIELD *)evt_ptr); + memset(evt_ptr, 0, sizeof(EVENT_HEARTBEAT_FIELD)); + free(evt_ptr); + break; + + case EVEL_DOMAIN_SIPSIGNALING: + EVEL_DEBUG("Event is a Signaling at %lp", evt_ptr); + evel_free_signaling((EVENT_SIGNALING *)evt_ptr); + memset(evt_ptr, 0, sizeof(EVENT_SIGNALING)); + free(evt_ptr); + break; + + case EVEL_DOMAIN_STATE_CHANGE: + EVEL_DEBUG("Event is a State Change at %lp", evt_ptr); + evel_free_state_change((EVENT_STATE_CHANGE *)evt_ptr); + memset(evt_ptr, 0, sizeof(EVENT_STATE_CHANGE)); + free(evt_ptr); + break; + + case EVEL_DOMAIN_SYSLOG: + EVEL_DEBUG("Event is a Syslog at %lp", evt_ptr); + evel_free_syslog((EVENT_SYSLOG *)evt_ptr); + memset(evt_ptr, 0, sizeof(EVENT_SYSLOG)); + free(evt_ptr); + break; + + case EVEL_DOMAIN_OTHER: + EVEL_DEBUG("Event is an Other at %lp", evt_ptr); + evel_free_other((EVENT_OTHER *)evt_ptr); + memset(evt_ptr, 0, sizeof(EVENT_OTHER)); + free(evt_ptr); + break; + + case EVEL_DOMAIN_VOICE_QUALITY: + EVEL_DEBUG("Event is an VoiceQuality at %lp", evt_ptr); + evel_free_voice_quality((EVENT_VOICE_QUALITY *)evt_ptr); + memset(evt_ptr, 0, sizeof(EVENT_VOICE_QUALITY)); + free(evt_ptr); + break; + + case EVEL_DOMAIN_THRESHOLD_CROSS: + EVEL_DEBUG("Event is a Threshold crossing at %lp", evt_ptr); + evel_free_threshold_cross((EVENT_THRESHOLD_CROSS *)evt_ptr); + memset(evt_ptr, 0, sizeof(EVENT_THRESHOLD_CROSS)); + free(evt_ptr); + break; + + default: + EVEL_ERROR("Unexpected event domain (%d)", evt_ptr->event_domain); + assert(0); + } + } + EVEL_EXIT(); +} diff --git a/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel.h b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel.h new file mode 100644 index 0000000..0ae1713 --- /dev/null +++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel.h @@ -0,0 +1,4494 @@ +#ifndef EVEL_INCLUDED +#define EVEL_INCLUDED +/*************************************************************************//** + * + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************/ + +/**************************************************************************//** + * @file + * Header for EVEL library + * + * This file implements the EVEL library which is intended to provide a + * simple wrapper around the complexity of AT&T's Vendor Event Listener API so + * that VNFs can use it without worrying about details of the API transport. + * + * Zero return value is success (::EVEL_SUCCESS), non-zero is failure and will + * be one of ::EVEL_ERR_CODES. + *****************************************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include + +#include "jsmn.h" +#include "double_list.h" +#include "hashtable.h" + +/*****************************************************************************/ +/* Supported API version. */ +/*****************************************************************************/ +#define EVEL_API_MAJOR_VERSION 5 +#define EVEL_API_MINOR_VERSION 0 + +/**************************************************************************//** + * Error codes + * + * Error codes for EVEL low level interface + *****************************************************************************/ +typedef enum { + EVEL_SUCCESS, /** The operation was successful. */ + EVEL_ERR_GEN_FAIL, /** Non-specific failure. */ + EVEL_CURL_LIBRARY_FAIL, /** A cURL library operation failed. */ + EVEL_PTHREAD_LIBRARY_FAIL, /** A Posix threads operation failed. */ + EVEL_OUT_OF_MEMORY, /** A memory allocation failure occurred. */ + EVEL_EVENT_BUFFER_FULL, /** Too many events in the ring-buffer. */ + EVEL_EVENT_HANDLER_INACTIVE, /** Attempt to raise event when inactive. */ + EVEL_NO_METADATA, /** Failed to retrieve OpenStack metadata. */ + EVEL_BAD_METADATA, /** OpenStack metadata invalid format. */ + EVEL_BAD_JSON_FORMAT, /** JSON failed to parse correctly. */ + EVEL_JSON_KEY_NOT_FOUND, /** Failed to find the specified JSON key. */ + EVEL_MAX_ERROR_CODES /** Maximum number of valid error codes. */ +} EVEL_ERR_CODES; + +/**************************************************************************//** + * Logging levels + * + * Variable levels of verbosity in the logging functions. + *****************************************************************************/ +typedef enum { + EVEL_LOG_MIN = 0, + EVEL_LOG_SPAMMY = 30, + EVEL_LOG_DEBUG = 40, + EVEL_LOG_INFO = 50, + EVEL_LOG_ERROR = 60, + EVEL_LOG_MAX = 101 +} EVEL_LOG_LEVELS; + +/*****************************************************************************/ +/* Maximum string lengths. */ +/*****************************************************************************/ +#define EVEL_MAX_STRING_LEN 4096 +#define EVEL_MAX_JSON_BODY 16000 +#define EVEL_MAX_ERROR_STRING_LEN 255 +#define EVEL_MAX_URL_LEN 511 + +/**************************************************************************//** + * This value represents there being no restriction on the reporting interval. + *****************************************************************************/ +static const int EVEL_MEASUREMENT_INTERVAL_UKNOWN = 0; + +/**************************************************************************//** + * How many events can be backed-up before we start dropping events on the + * floor. + * + * @note This value should be tuned in accordance with expected burstiness of + * the event load and the expected response time of the ECOMP event + * listener so that the probability of the buffer filling is suitably + * low. + *****************************************************************************/ +static const int EVEL_EVENT_BUFFER_DEPTH = 100; + +/*****************************************************************************/ +/* How many different IP Types-of-Service are supported. */ +/*****************************************************************************/ +#define EVEL_TOS_SUPPORTED 256 + +/**************************************************************************//** + * Event domains for the various events we support. + * JSON equivalent field: domain + *****************************************************************************/ +typedef enum { + EVEL_DOMAIN_INTERNAL, /** Internal event, not for external routing. */ + EVEL_DOMAIN_HEARTBEAT, /** A Heartbeat event (event header only). */ + EVEL_DOMAIN_FAULT, /** A Fault event. */ + EVEL_DOMAIN_MEASUREMENT, /** A Measurement for VF Scaling event. */ + EVEL_DOMAIN_MOBILE_FLOW, /** A Mobile Flow event. */ + EVEL_DOMAIN_REPORT, /** A Measurement for VF Reporting event. */ + EVEL_DOMAIN_HEARTBEAT_FIELD,/** A Heartbeat field event. */ + EVEL_DOMAIN_SIPSIGNALING, /** A Signaling event. */ + EVEL_DOMAIN_STATE_CHANGE, /** A State Change event. */ + EVEL_DOMAIN_SYSLOG, /** A Syslog event. */ + EVEL_DOMAIN_OTHER, /** Another event. */ + EVEL_DOMAIN_THRESHOLD_CROSS, /** A Threshold Crossing Event */ + EVEL_DOMAIN_VOICE_QUALITY, /** A Voice Quality Event */ + EVEL_MAX_DOMAINS /** Maximum number of recognized Event types. */ +} EVEL_EVENT_DOMAINS; + +/**************************************************************************//** + * Event priorities. + * JSON equivalent field: priority + *****************************************************************************/ +typedef enum { + EVEL_PRIORITY_HIGH, + EVEL_PRIORITY_MEDIUM, + EVEL_PRIORITY_NORMAL, + EVEL_PRIORITY_LOW, + EVEL_MAX_PRIORITIES +} EVEL_EVENT_PRIORITIES; + +/**************************************************************************//** + * Fault / Threshold severities. + * JSON equivalent field: eventSeverity + *****************************************************************************/ +typedef enum { + EVEL_SEVERITY_CRITICAL, + EVEL_SEVERITY_MAJOR, + EVEL_SEVERITY_MINOR, + EVEL_SEVERITY_WARNING, + EVEL_SEVERITY_NORMAL, + EVEL_MAX_SEVERITIES +} EVEL_SEVERITIES; + +/**************************************************************************//** + * Fault source types. + * JSON equivalent field: eventSourceType + *****************************************************************************/ +typedef enum { + EVEL_SOURCE_OTHER, + EVEL_SOURCE_ROUTER, + EVEL_SOURCE_SWITCH, + EVEL_SOURCE_HOST, + EVEL_SOURCE_CARD, + EVEL_SOURCE_PORT, + EVEL_SOURCE_SLOT_THRESHOLD, + EVEL_SOURCE_PORT_THRESHOLD, + EVEL_SOURCE_VIRTUAL_MACHINE, + EVEL_SOURCE_VIRTUAL_NETWORK_FUNCTION, + /***************************************************************************/ + /* START OF VENDOR-SPECIFIC VALUES */ + /* */ + /* Vendor-specific values should be added here, and handled appropriately */ + /* in evel_event.c. */ + /***************************************************************************/ + + /***************************************************************************/ + /* END OF VENDOR-SPECIFIC VALUES */ + /***************************************************************************/ + EVEL_MAX_SOURCE_TYPES +} EVEL_SOURCE_TYPES; + +/**************************************************************************//** + * Fault VNF Status. + * JSON equivalent field: vfStatus + *****************************************************************************/ +typedef enum { + EVEL_VF_STATUS_ACTIVE, + EVEL_VF_STATUS_IDLE, + EVEL_VF_STATUS_PREP_TERMINATE, + EVEL_VF_STATUS_READY_TERMINATE, + EVEL_VF_STATUS_REQ_TERMINATE, + EVEL_MAX_VF_STATUSES +} EVEL_VF_STATUSES; + +/**************************************************************************//** + * Counter criticalities. + * JSON equivalent field: criticality + *****************************************************************************/ +typedef enum { + EVEL_COUNTER_CRITICALITY_CRIT, + EVEL_COUNTER_CRITICALITY_MAJ, + EVEL_MAX_COUNTER_CRITICALITIES +} EVEL_COUNTER_CRITICALITIES; + +/**************************************************************************//** + * Alert actions. + * JSON equivalent field: alertAction + *****************************************************************************/ +typedef enum { + EVEL_ALERT_ACTION_CLEAR, + EVEL_ALERT_ACTION_CONT, + EVEL_ALERT_ACTION_SET, + EVEL_MAX_ALERT_ACTIONS +} EVEL_ALERT_ACTIONS; + +/**************************************************************************//** + * Alert types. + * JSON equivalent field: alertType + *****************************************************************************/ +typedef enum { + EVEL_ALERT_TYPE_CARD, + EVEL_ALERT_TYPE_ELEMENT, + EVEL_ALERT_TYPE_INTERFACE, + EVEL_ALERT_TYPE_SERVICE, + EVEL_MAX_ALERT_TYPES +} EVEL_ALERT_TYPES; + +/**************************************************************************//** + * Alert types. + * JSON equivalent fields: newState, oldState + *****************************************************************************/ +typedef enum { + EVEL_ENTITY_STATE_IN_SERVICE, + EVEL_ENTITY_STATE_MAINTENANCE, + EVEL_ENTITY_STATE_OUT_OF_SERVICE, + EVEL_MAX_ENTITY_STATES +} EVEL_ENTITY_STATE; + +/**************************************************************************//** + * Syslog facilities. + * JSON equivalent field: syslogFacility + *****************************************************************************/ +typedef enum { + EVEL_SYSLOG_FACILITY_KERNEL, + EVEL_SYSLOG_FACILITY_USER, + EVEL_SYSLOG_FACILITY_MAIL, + EVEL_SYSLOG_FACILITY_SYSTEM_DAEMON, + EVEL_SYSLOG_FACILITY_SECURITY_AUTH, + EVEL_SYSLOG_FACILITY_INTERNAL, + EVEL_SYSLOG_FACILITY_LINE_PRINTER, + EVEL_SYSLOG_FACILITY_NETWORK_NEWS, + EVEL_SYSLOG_FACILITY_UUCP, + EVEL_SYSLOG_FACILITY_CLOCK_DAEMON, + EVEL_SYSLOG_FACILITY_SECURITY_AUTH2, + EVEL_SYSLOG_FACILITY_FTP_DAEMON, + EVEL_SYSLOG_FACILITY_NTP, + EVEL_SYSLOG_FACILITY_LOG_AUDIT, + EVEL_SYSLOG_FACILITY_LOG_ALERT, + EVEL_SYSLOG_FACILITY_CLOCK_DAEMON2, + EVEL_SYSLOG_FACILITY_LOCAL0, + EVEL_SYSLOG_FACILITY_LOCAL1, + EVEL_SYSLOG_FACILITY_LOCAL2, + EVEL_SYSLOG_FACILITY_LOCAL3, + EVEL_SYSLOG_FACILITY_LOCAL4, + EVEL_SYSLOG_FACILITY_LOCAL5, + EVEL_SYSLOG_FACILITY_LOCAL6, + EVEL_SYSLOG_FACILITY_LOCAL7, + EVEL_MAX_SYSLOG_FACILITIES +} EVEL_SYSLOG_FACILITIES; + +/**************************************************************************//** + * TCP flags. + * JSON equivalent fields: tcpFlagCountList, tcpFlagList + *****************************************************************************/ +typedef enum { + EVEL_TCP_NS, + EVEL_TCP_CWR, + EVEL_TCP_ECE, + EVEL_TCP_URG, + EVEL_TCP_ACK, + EVEL_TCP_PSH, + EVEL_TCP_RST, + EVEL_TCP_SYN, + EVEL_TCP_FIN, + EVEL_MAX_TCP_FLAGS +} EVEL_TCP_FLAGS; + +/**************************************************************************//** + * Mobile QCI Classes of Service. + * JSON equivalent fields: mobileQciCosCountList, mobileQciCosList + *****************************************************************************/ +typedef enum { + + /***************************************************************************/ + /* UMTS Classes of Service. */ + /***************************************************************************/ + EVEL_QCI_COS_UMTS_CONVERSATIONAL, + EVEL_QCI_COS_UMTS_STREAMING, + EVEL_QCI_COS_UMTS_INTERACTIVE, + EVEL_QCI_COS_UMTS_BACKGROUND, + + /***************************************************************************/ + /* LTE Classes of Service. */ + /***************************************************************************/ + EVEL_QCI_COS_LTE_1, + EVEL_QCI_COS_LTE_2, + EVEL_QCI_COS_LTE_3, + EVEL_QCI_COS_LTE_4, + EVEL_QCI_COS_LTE_65, + EVEL_QCI_COS_LTE_66, + EVEL_QCI_COS_LTE_5, + EVEL_QCI_COS_LTE_6, + EVEL_QCI_COS_LTE_7, + EVEL_QCI_COS_LTE_8, + EVEL_QCI_COS_LTE_9, + EVEL_QCI_COS_LTE_69, + EVEL_QCI_COS_LTE_70, + EVEL_MAX_QCI_COS_TYPES +} EVEL_QCI_COS_TYPES; + +/**************************************************************************//** + * Service Event endpoint description + * JSON equivalent field: endpointDesc + *****************************************************************************/ +typedef enum { + EVEL_SERVICE_ENDPOINT_CALLEE, + EVEL_SERVICE_ENDPOINT_CALLER, + EVEL_MAX_SERVICE_ENDPOINT_DESC +} EVEL_SERVICE_ENDPOINT_DESC; + +/**************************************************************************//** + * Boolean type for EVEL library. + *****************************************************************************/ +typedef enum { + EVEL_FALSE, + EVEL_TRUE +} EVEL_BOOLEAN; + +/**************************************************************************//** + * Optional parameter holder for double. + *****************************************************************************/ +typedef struct evel_option_double +{ + double value; + EVEL_BOOLEAN is_set; +} EVEL_OPTION_DOUBLE; + +/**************************************************************************//** + * Optional parameter holder for string. + *****************************************************************************/ +typedef struct evel_option_string +{ + char * value; + EVEL_BOOLEAN is_set; +} EVEL_OPTION_STRING; + +/**************************************************************************//** + * Optional parameter holder for int. + *****************************************************************************/ +typedef struct evel_option_int +{ + int value; + EVEL_BOOLEAN is_set; +} EVEL_OPTION_INT; + +/**************************************************************************//** + * Optional parameter holder for unsigned long long. + *****************************************************************************/ +typedef struct evel_option_ull +{ + unsigned long long value; + EVEL_BOOLEAN is_set; +} EVEL_OPTION_ULL; + +/**************************************************************************//** + * Optional parameter holder for time_t. + *****************************************************************************/ +typedef struct evel_option_time +{ + time_t value; + EVEL_BOOLEAN is_set; +} EVEL_OPTION_TIME; + +/**************************************************************************//** + * enrichment fields for internal VES Event Listener service use only, + * not supplied by event sources + *****************************************************************************/ +typedef struct internal_header_fields +{ + void *object; + EVEL_BOOLEAN is_set; +} EVEL_OPTION_INTHEADER_FIELDS; + +/*****************************************************************************/ +/* Supported Common Event Header version. */ +/*****************************************************************************/ +#define EVEL_HEADER_MAJOR_VERSION 1 +#define EVEL_HEADER_MINOR_VERSION 2 + +/**************************************************************************//** + * Event header. + * JSON equivalent field: commonEventHeader + *****************************************************************************/ +typedef struct event_header { + /***************************************************************************/ + /* Version */ + /***************************************************************************/ + int major_version; + int minor_version; + + /***************************************************************************/ + /* Mandatory fields */ + /***************************************************************************/ + EVEL_EVENT_DOMAINS event_domain; + char * event_id; + char * event_name; + char * source_name; + char * reporting_entity_name; + EVEL_EVENT_PRIORITIES priority; + unsigned long long start_epoch_microsec; + unsigned long long last_epoch_microsec; + int sequence; + + /***************************************************************************/ + /* Optional fields */ + /***************************************************************************/ + EVEL_OPTION_STRING event_type; + EVEL_OPTION_STRING source_id; + EVEL_OPTION_STRING reporting_entity_id; + EVEL_OPTION_INTHEADER_FIELDS internal_field; + EVEL_OPTION_STRING nfcnaming_code; + EVEL_OPTION_STRING nfnaming_code; + +} EVENT_HEADER; + +/*****************************************************************************/ +/* Supported Fault version. */ +/*****************************************************************************/ +#define EVEL_FAULT_MAJOR_VERSION 2 +#define EVEL_FAULT_MINOR_VERSION 1 + +/**************************************************************************//** + * Fault. + * JSON equivalent field: faultFields + *****************************************************************************/ +typedef struct event_fault { + /***************************************************************************/ + /* Header and version */ + /***************************************************************************/ + EVENT_HEADER header; + int major_version; + int minor_version; + + /***************************************************************************/ + /* Mandatory fields */ + /***************************************************************************/ + EVEL_SEVERITIES event_severity; + EVEL_SOURCE_TYPES event_source_type; + char * alarm_condition; + char * specific_problem; + EVEL_VF_STATUSES vf_status; + + /***************************************************************************/ + /* Optional fields */ + /***************************************************************************/ + EVEL_OPTION_STRING category; + EVEL_OPTION_STRING alarm_interface_a; + DLIST additional_info; + +} EVENT_FAULT; + +/**************************************************************************//** + * Fault Additional Info. + * JSON equivalent field: alarmAdditionalInformation + *****************************************************************************/ +typedef struct fault_additional_info { + char * name; + char * value; +} FAULT_ADDL_INFO; + + +/**************************************************************************//** + * optional field block for fields specific to heartbeat events + *****************************************************************************/ +typedef struct event_heartbeat_fields +{ + /***************************************************************************/ + /* Header and version */ + /***************************************************************************/ + EVENT_HEADER header; + int major_version; + int minor_version; + + /***************************************************************************/ + /* Mandatory fields */ + /***************************************************************************/ + double heartbeat_version; + int heartbeat_interval; + + /***************************************************************************/ + /* Optional fields */ + /***************************************************************************/ + DLIST additional_info; + +} EVENT_HEARTBEAT_FIELD; + +/**************************************************************************//** + * tuple which provides the name of a key along with its value and + * relative order + *****************************************************************************/ +typedef struct internal_key +{ + char *keyname; + EVEL_OPTION_INT keyorder; + EVEL_OPTION_STRING keyvalue; +} EVEL_INTERNAL_KEY; + +/**************************************************************************//** + * meta-information about an instance of a jsonObject along with + * the actual object instance + *****************************************************************************/ +typedef struct json_object_instance +{ + + char *jsonstring; + unsigned long long objinst_epoch_microsec; + DLIST object_keys; /*EVEL_INTERNAL_KEY list */ + +} EVEL_JSON_OBJECT_INSTANCE; +#define MAX_JSON_TOKENS 128 +/**************************************************************************//** + * Create a new json object instance. + * + * @note The mandatory fields on the Other must be supplied to this factory + * function and are immutable once set. Optional fields have explicit + * setter functions, but again values may only be set once so that the + * Other has immutable properties. + * @param yourjson json string. + * @returns pointer to the newly manufactured ::EVEL_JSON_OBJECT_INSTANCE. + * not used (i.e. posted) it must be released using ::evel_free_jsonobjectinstance. + * @retval NULL Failed to create the json object instance. + *****************************************************************************/ +EVEL_JSON_OBJECT_INSTANCE * evel_new_jsonobjinstance(const char *const yourjson); +/**************************************************************************//** + * Free an json object instance. + * + * Free off the json object instance supplied. + * Will free all the contained allocated memory. + * + *****************************************************************************/ +void evel_free_jsonobjinst(EVEL_JSON_OBJECT_INSTANCE * objinst); + +/**************************************************************************//** + * enrichment fields for internal VES Event Listener service use only, + * not supplied by event sources + *****************************************************************************/ +typedef struct json_object +{ + + char *object_name; + EVEL_OPTION_STRING objectschema; + EVEL_OPTION_STRING objectschemaurl; + EVEL_OPTION_STRING nfsubscribedobjname; + EVEL_OPTION_STRING nfsubscriptionid; + DLIST jsonobjectinstances; /* EVEL_JSON_OBJECT_INSTANCE list */ + +} EVEL_JSON_OBJECT; + +/**************************************************************************//** + * Create a new json object. + * + * @note The mandatory fields on the Other must be supplied to this factory + * function and are immutable once set. Optional fields have explicit + * setter functions, but again values may only be set once so that the + * Other has immutable properties. + * @param name name of the object. + * @returns pointer to the newly manufactured ::EVEL_JSON_OBJECT. + * not used (i.e. posted) it must be released using ::evel_free_jsonobject. + * @retval NULL Failed to create the json object. + *****************************************************************************/ +EVEL_JSON_OBJECT * evel_new_jsonobject(const char *const name); +/**************************************************************************//** + * Free an json object. + * + * Free off the json object instance supplied. + * Will free all the contained allocated memory. + * + *****************************************************************************/ +void evel_free_jsonobject(EVEL_JSON_OBJECT * jsobj); +/*****************************************************************************/ +/* Supported Measurement version. */ +/*****************************************************************************/ +#define EVEL_MEASUREMENT_MAJOR_VERSION 2 +#define EVEL_MEASUREMENT_MINOR_VERSION 1 + +/**************************************************************************//** + * Errors. + * JSON equivalent field: errors + *****************************************************************************/ +typedef struct measurement_errors { + int receive_discards; + int receive_errors; + int transmit_discards; + int transmit_errors; +} MEASUREMENT_ERRORS; + +/**************************************************************************//** + * Measurement. + * JSON equivalent field: measurementsForVfScalingFields + *****************************************************************************/ +typedef struct event_measurement { + /***************************************************************************/ + /* Header and version */ + /***************************************************************************/ + EVENT_HEADER header; + int major_version; + int minor_version; + + /***************************************************************************/ + /* Mandatory fields */ + /***************************************************************************/ + double measurement_interval; + + /***************************************************************************/ + /* Optional fields */ + /***************************************************************************/ + DLIST additional_info; + DLIST additional_measurements; + DLIST additional_objects; + DLIST codec_usage; + EVEL_OPTION_INT concurrent_sessions; + EVEL_OPTION_INT configured_entities; + DLIST cpu_usage; + DLIST disk_usage; + MEASUREMENT_ERRORS * errors; + DLIST feature_usage; + DLIST filesystem_usage; + DLIST latency_distribution; + EVEL_OPTION_DOUBLE mean_request_latency; + DLIST mem_usage; + EVEL_OPTION_INT media_ports_in_use; + EVEL_OPTION_INT request_rate; + EVEL_OPTION_INT vnfc_scaling_metric; + DLIST vnic_usage; + +} EVENT_MEASUREMENT; + +/**************************************************************************//** + * CPU Usage. + * JSON equivalent field: cpuUsage + *****************************************************************************/ +typedef struct measurement_cpu_use { + char * id; + double usage; + EVEL_OPTION_DOUBLE idle; + EVEL_OPTION_DOUBLE intrpt; + EVEL_OPTION_DOUBLE nice; + EVEL_OPTION_DOUBLE softirq; + EVEL_OPTION_DOUBLE steal; + EVEL_OPTION_DOUBLE sys; + EVEL_OPTION_DOUBLE user; + EVEL_OPTION_DOUBLE wait; +} MEASUREMENT_CPU_USE; + + +/**************************************************************************//** + * Disk Usage. + * JSON equivalent field: diskUsage + *****************************************************************************/ +typedef struct measurement_disk_use { + char * id; + EVEL_OPTION_DOUBLE iotimeavg; + EVEL_OPTION_DOUBLE iotimelast; + EVEL_OPTION_DOUBLE iotimemax; + EVEL_OPTION_DOUBLE iotimemin; + EVEL_OPTION_DOUBLE mergereadavg; + EVEL_OPTION_DOUBLE mergereadlast; + EVEL_OPTION_DOUBLE mergereadmax; + EVEL_OPTION_DOUBLE mergereadmin; + EVEL_OPTION_DOUBLE mergewriteavg; + EVEL_OPTION_DOUBLE mergewritelast; + EVEL_OPTION_DOUBLE mergewritemax; + EVEL_OPTION_DOUBLE mergewritemin; + EVEL_OPTION_DOUBLE octetsreadavg; + EVEL_OPTION_DOUBLE octetsreadlast; + EVEL_OPTION_DOUBLE octetsreadmax; + EVEL_OPTION_DOUBLE octetsreadmin; + EVEL_OPTION_DOUBLE octetswriteavg; + EVEL_OPTION_DOUBLE octetswritelast; + EVEL_OPTION_DOUBLE octetswritemax; + EVEL_OPTION_DOUBLE octetswritemin; + EVEL_OPTION_DOUBLE opsreadavg; + EVEL_OPTION_DOUBLE opsreadlast; + EVEL_OPTION_DOUBLE opsreadmax; + EVEL_OPTION_DOUBLE opsreadmin; + EVEL_OPTION_DOUBLE opswriteavg; + EVEL_OPTION_DOUBLE opswritelast; + EVEL_OPTION_DOUBLE opswritemax; + EVEL_OPTION_DOUBLE opswritemin; + EVEL_OPTION_DOUBLE pendingopsavg; + EVEL_OPTION_DOUBLE pendingopslast; + EVEL_OPTION_DOUBLE pendingopsmax; + EVEL_OPTION_DOUBLE pendingopsmin; + EVEL_OPTION_DOUBLE timereadavg; + EVEL_OPTION_DOUBLE timereadlast; + EVEL_OPTION_DOUBLE timereadmax; + EVEL_OPTION_DOUBLE timereadmin; + EVEL_OPTION_DOUBLE timewriteavg; + EVEL_OPTION_DOUBLE timewritelast; + EVEL_OPTION_DOUBLE timewritemax; + EVEL_OPTION_DOUBLE timewritemin; + +} MEASUREMENT_DISK_USE; + +/**************************************************************************//** + * Add an additional Disk usage value name/value pair to the Measurement. + * + * The name and value are null delimited ASCII strings. The library takes + * a copy so the caller does not have to preserve values after the function + * returns. + * + * @param measurement Pointer to the measurement. + * @param id ASCIIZ string with the CPU's identifier. + * @param usage Disk utilization. + *****************************************************************************/ +MEASUREMENT_DISK_USE * evel_measurement_new_disk_use_add(EVENT_MEASUREMENT * measurement, char * id); + +/**************************************************************************//** + * Filesystem Usage. + * JSON equivalent field: filesystemUsage + *****************************************************************************/ +typedef struct measurement_fsys_use { + char * filesystem_name; + double block_configured; + double block_iops; + double block_used; + double ephemeral_configured; + double ephemeral_iops; + double ephemeral_used; +} MEASUREMENT_FSYS_USE; + +/**************************************************************************//** + * Memory Usage. + * JSON equivalent field: memoryUsage + *****************************************************************************/ +typedef struct measurement_mem_use { + char * id; + char * vmid; + double membuffsz; + EVEL_OPTION_DOUBLE memcache; + EVEL_OPTION_DOUBLE memconfig; + EVEL_OPTION_DOUBLE memfree; + EVEL_OPTION_DOUBLE slabrecl; + EVEL_OPTION_DOUBLE slabunrecl; + EVEL_OPTION_DOUBLE memused; +} MEASUREMENT_MEM_USE; + +/**************************************************************************//** + * Add an additional Memory usage value name/value pair to the Measurement. + * + * The name and value are null delimited ASCII strings. The library takes + * a copy so the caller does not have to preserve values after the function + * returns. + * + * @param measurement Pointer to the measurement. + * @param id ASCIIZ string with the Memory identifier. + * @param vmidentifier ASCIIZ string with the VM's identifier. + * @param membuffsz Memory Size. + * + * @return Returns pointer to memory use structure in measurements + *****************************************************************************/ +MEASUREMENT_MEM_USE * evel_measurement_new_mem_use_add(EVENT_MEASUREMENT * measurement, + char * id, char *vmidentifier, double membuffsz); + +/**************************************************************************//** + * Set kilobytes of memory used for cache + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param mem_use Pointer to the Memory Use. + * @param val double + *****************************************************************************/ +void evel_measurement_mem_use_memcache_set(MEASUREMENT_MEM_USE * const mem_use, + const double val); +/**************************************************************************//** + * Set kilobytes of memory configured in the virtual machine on which the VNFC reporting + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param mem_use Pointer to the Memory Use. + * @param val double + *****************************************************************************/ +void evel_measurement_mem_use_memconfig_set(MEASUREMENT_MEM_USE * const mem_use, + const double val); +/**************************************************************************//** + * Set kilobytes of physical RAM left unused by the system + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param mem_use Pointer to the Memory Use. + * @param val double + *****************************************************************************/ +void evel_measurement_mem_use_memfree_set(MEASUREMENT_MEM_USE * const mem_use, + const double val); +/**************************************************************************//** + * Set the part of the slab that can be reclaimed such as caches measured in kilobytes + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param mem_use Pointer to the Memory Use. + * @param val double + *****************************************************************************/ +void evel_measurement_mem_use_slab_reclaimed_set(MEASUREMENT_MEM_USE * const mem_use, + const double val); +/**************************************************************************//** + * Set the part of the slab that cannot be reclaimed such as caches measured in kilobytes + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param mem_use Pointer to the Memory Use. + * @param val double + *****************************************************************************/ +void evel_measurement_mem_use_slab_unreclaimable_set(MEASUREMENT_MEM_USE * const mem_use, + const double val); +/**************************************************************************//** + * Set the total memory minus the sum of free, buffered, cached and slab memory in kilobytes + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param mem_use Pointer to the Memory Use. + * @param val double + *****************************************************************************/ +void evel_measurement_mem_use_usedup_set(MEASUREMENT_MEM_USE * const mem_use, + const double val); +/**************************************************************************//** + * Latency Bucket. + * JSON equivalent field: latencyBucketMeasure + *****************************************************************************/ +typedef struct measurement_latency_bucket { + int count; + + /***************************************************************************/ + /* Optional fields */ + /***************************************************************************/ + EVEL_OPTION_DOUBLE high_end; + EVEL_OPTION_DOUBLE low_end; + +} MEASUREMENT_LATENCY_BUCKET; + +/**************************************************************************//** + * Virtual NIC usage. + * JSON equivalent field: vNicUsage + *****************************************************************************/ +typedef struct measurement_vnic_performance { + /***************************************************************************/ + /* Optional fields */ + /***************************************************************************/ + /*Cumulative count of broadcast packets received as read at the end of + the measurement interval*/ + EVEL_OPTION_DOUBLE recvd_bcast_packets_acc; + /*Count of broadcast packets received within the measurement interval*/ + EVEL_OPTION_DOUBLE recvd_bcast_packets_delta; + /*Cumulative count of discarded packets received as read at the end of + the measurement interval*/ + EVEL_OPTION_DOUBLE recvd_discarded_packets_acc; + /*Count of discarded packets received within the measurement interval*/ + EVEL_OPTION_DOUBLE recvd_discarded_packets_delta; + /*Cumulative count of error packets received as read at the end of + the measurement interval*/ + EVEL_OPTION_DOUBLE recvd_error_packets_acc; + /*Count of error packets received within the measurement interval*/ + EVEL_OPTION_DOUBLE recvd_error_packets_delta; + /*Cumulative count of multicast packets received as read at the end of + the measurement interval*/ + EVEL_OPTION_DOUBLE recvd_mcast_packets_acc; + /*Count of mcast packets received within the measurement interval*/ + EVEL_OPTION_DOUBLE recvd_mcast_packets_delta; + /*Cumulative count of octets received as read at the end of + the measurement interval*/ + EVEL_OPTION_DOUBLE recvd_octets_acc; + /*Count of octets received within the measurement interval*/ + EVEL_OPTION_DOUBLE recvd_octets_delta; + /*Cumulative count of all packets received as read at the end of + the measurement interval*/ + EVEL_OPTION_DOUBLE recvd_total_packets_acc; + /*Count of all packets received within the measurement interval*/ + EVEL_OPTION_DOUBLE recvd_total_packets_delta; + /*Cumulative count of unicast packets received as read at the end of + the measurement interval*/ + EVEL_OPTION_DOUBLE recvd_ucast_packets_acc; + /*Count of unicast packets received within the measurement interval*/ + EVEL_OPTION_DOUBLE recvd_ucast_packets_delta; + /*Cumulative count of transmitted broadcast packets at the end of + the measurement interval*/ + EVEL_OPTION_DOUBLE tx_bcast_packets_acc; + /*Count of transmitted broadcast packets within the measurement interval*/ + EVEL_OPTION_DOUBLE tx_bcast_packets_delta; + /*Cumulative count of transmit discarded packets at the end of + the measurement interval*/ + EVEL_OPTION_DOUBLE tx_discarded_packets_acc; + /*Count of transmit discarded packets within the measurement interval*/ + EVEL_OPTION_DOUBLE tx_discarded_packets_delta; + /*Cumulative count of transmit error packets at the end of + the measurement interval*/ + EVEL_OPTION_DOUBLE tx_error_packets_acc; + /*Count of transmit error packets within the measurement interval*/ + EVEL_OPTION_DOUBLE tx_error_packets_delta; + /*Cumulative count of transmit multicast packets at the end of + the measurement interval*/ + EVEL_OPTION_DOUBLE tx_mcast_packets_acc; + /*Count of transmit multicast packets within the measurement interval*/ + EVEL_OPTION_DOUBLE tx_mcast_packets_delta; + /*Cumulative count of transmit octets at the end of + the measurement interval*/ + EVEL_OPTION_DOUBLE tx_octets_acc; + /*Count of transmit octets received within the measurement interval*/ + EVEL_OPTION_DOUBLE tx_octets_delta; + /*Cumulative count of all transmit packets at the end of + the measurement interval*/ + EVEL_OPTION_DOUBLE tx_total_packets_acc; + /*Count of transmit packets within the measurement interval*/ + EVEL_OPTION_DOUBLE tx_total_packets_delta; + /*Cumulative count of all transmit unicast packets at the end of + the measurement interval*/ + EVEL_OPTION_DOUBLE tx_ucast_packets_acc; + /*Count of transmit unicast packets within the measurement interval*/ + EVEL_OPTION_DOUBLE tx_ucast_packets_delta; + /* Indicates whether vNicPerformance values are likely inaccurate + due to counter overflow or other condtions*/ + char *valuesaresuspect; + char *vnic_id; + +} MEASUREMENT_VNIC_PERFORMANCE; + +/**************************************************************************//** + * Codec Usage. + * JSON equivalent field: codecsInUse + *****************************************************************************/ +typedef struct measurement_codec_use { + char * codec_id; + int number_in_use; +} MEASUREMENT_CODEC_USE; + +/**************************************************************************//** + * Feature Usage. + * JSON equivalent field: featuresInUse + *****************************************************************************/ +typedef struct measurement_feature_use { + char * feature_id; + int feature_utilization; +} MEASUREMENT_FEATURE_USE; + +/**************************************************************************//** + * Measurement Group. + * JSON equivalent field: additionalMeasurements + *****************************************************************************/ +typedef struct measurement_group { + char * name; + DLIST measurements; +} MEASUREMENT_GROUP; + +/**************************************************************************//** + * Custom Defined Measurement. + * JSON equivalent field: measurements + *****************************************************************************/ +typedef struct custom_measurement { + char * name; + char * value; +} CUSTOM_MEASUREMENT; + +/*****************************************************************************/ +/* Supported Report version. */ +/*****************************************************************************/ +#define EVEL_REPORT_MAJOR_VERSION 1 +#define EVEL_REPORT_MINOR_VERSION 1 + +/**************************************************************************//** + * Report. + * JSON equivalent field: measurementsForVfReportingFields + * + * @note This is an experimental event type and is not currently a formal part + * of AT&T's specification. + *****************************************************************************/ +typedef struct event_report { + /***************************************************************************/ + /* Header and version */ + /***************************************************************************/ + EVENT_HEADER header; + int major_version; + int minor_version; + + /***************************************************************************/ + /* Mandatory fields */ + /***************************************************************************/ + double measurement_interval; + + /***************************************************************************/ + /* Optional fields */ + /***************************************************************************/ + DLIST feature_usage; + DLIST measurement_groups; + +} EVENT_REPORT; + +/**************************************************************************//** + * Mobile GTP Per Flow Metrics. + * JSON equivalent field: gtpPerFlowMetrics + *****************************************************************************/ +typedef struct mobile_gtp_per_flow_metrics { + double avg_bit_error_rate; + double avg_packet_delay_variation; + int avg_packet_latency; + int avg_receive_throughput; + int avg_transmit_throughput; + int flow_activation_epoch; + int flow_activation_microsec; + int flow_deactivation_epoch; + int flow_deactivation_microsec; + time_t flow_deactivation_time; + char * flow_status; + int max_packet_delay_variation; + int num_activation_failures; + int num_bit_errors; + int num_bytes_received; + int num_bytes_transmitted; + int num_dropped_packets; + int num_l7_bytes_received; + int num_l7_bytes_transmitted; + int num_lost_packets; + int num_out_of_order_packets; + int num_packet_errors; + int num_packets_received_excl_retrans; + int num_packets_received_incl_retrans; + int num_packets_transmitted_incl_retrans; + int num_retries; + int num_timeouts; + int num_tunneled_l7_bytes_received; + int round_trip_time; + int time_to_first_byte; + + /***************************************************************************/ + /* Optional fields */ + /***************************************************************************/ + EVEL_OPTION_INT ip_tos_counts[EVEL_TOS_SUPPORTED]; + EVEL_OPTION_INT tcp_flag_counts[EVEL_MAX_TCP_FLAGS]; + EVEL_OPTION_INT qci_cos_counts[EVEL_MAX_QCI_COS_TYPES]; + EVEL_OPTION_INT dur_connection_failed_status; + EVEL_OPTION_INT dur_tunnel_failed_status; + EVEL_OPTION_STRING flow_activated_by; + EVEL_OPTION_TIME flow_activation_time; + EVEL_OPTION_STRING flow_deactivated_by; + EVEL_OPTION_STRING gtp_connection_status; + EVEL_OPTION_STRING gtp_tunnel_status; + EVEL_OPTION_INT large_packet_rtt; + EVEL_OPTION_DOUBLE large_packet_threshold; + EVEL_OPTION_INT max_receive_bit_rate; + EVEL_OPTION_INT max_transmit_bit_rate; + EVEL_OPTION_INT num_gtp_echo_failures; + EVEL_OPTION_INT num_gtp_tunnel_errors; + EVEL_OPTION_INT num_http_errors; + +} MOBILE_GTP_PER_FLOW_METRICS; + +/*****************************************************************************/ +/* Supported Mobile Flow version. */ +/*****************************************************************************/ +#define EVEL_MOBILE_FLOW_MAJOR_VERSION 1 +#define EVEL_MOBILE_FLOW_MINOR_VERSION 2 + +/**************************************************************************//** + * Mobile Flow. + * JSON equivalent field: mobileFlow + *****************************************************************************/ +typedef struct event_mobile_flow { + /***************************************************************************/ + /* Header and version */ + /***************************************************************************/ + EVENT_HEADER header; + int major_version; + int minor_version; + + /***************************************************************************/ + /* Mandatory fields */ + /***************************************************************************/ + char * flow_direction; + MOBILE_GTP_PER_FLOW_METRICS * gtp_per_flow_metrics; + char * ip_protocol_type; + char * ip_version; + char * other_endpoint_ip_address; + int other_endpoint_port; + char * reporting_endpoint_ip_addr; + int reporting_endpoint_port; + DLIST additional_info; /* JSON: additionalFields */ + + /***************************************************************************/ + /* Optional fields */ + /***************************************************************************/ + EVEL_OPTION_STRING application_type; + EVEL_OPTION_STRING app_protocol_type; + EVEL_OPTION_STRING app_protocol_version; + EVEL_OPTION_STRING cid; + EVEL_OPTION_STRING connection_type; + EVEL_OPTION_STRING ecgi; + EVEL_OPTION_STRING gtp_protocol_type; + EVEL_OPTION_STRING gtp_version; + EVEL_OPTION_STRING http_header; + EVEL_OPTION_STRING imei; + EVEL_OPTION_STRING imsi; + EVEL_OPTION_STRING lac; + EVEL_OPTION_STRING mcc; + EVEL_OPTION_STRING mnc; + EVEL_OPTION_STRING msisdn; + EVEL_OPTION_STRING other_functional_role; + EVEL_OPTION_STRING rac; + EVEL_OPTION_STRING radio_access_technology; + EVEL_OPTION_STRING sac; + EVEL_OPTION_INT sampling_algorithm; + EVEL_OPTION_STRING tac; + EVEL_OPTION_STRING tunnel_id; + EVEL_OPTION_STRING vlan_id; + +} EVENT_MOBILE_FLOW; + +/*****************************************************************************/ +/* Supported Other field version. */ +/*****************************************************************************/ +#define EVEL_OTHER_EVENT_MAJOR_VERSION 1 +#define EVEL_OTHER_EVENT_MINOR_VERSION 1 + +/**************************************************************************//** + * Other. + * JSON equivalent field: otherFields + *****************************************************************************/ +typedef struct event_other { + EVENT_HEADER header; + int major_version; + int minor_version; + + HASHTABLE_T *namedarrays; /* HASHTABLE_T */ + DLIST jsonobjects; /* DLIST of EVEL_JSON_OBJECT */ + DLIST namedvalues; +} EVENT_OTHER; + +/**************************************************************************//** + * Other Field. + * JSON equivalent field: otherFields + *****************************************************************************/ +typedef struct other_field { + char * name; + char * value; +} OTHER_FIELD; + + +/*****************************************************************************/ +/* Supported Service Events version. */ +/*****************************************************************************/ +#define EVEL_HEARTBEAT_FIELD_MAJOR_VERSION 1 +#define EVEL_HEARTBEAT_FIELD_MINOR_VERSION 1 + + +/*****************************************************************************/ +/* Supported Signaling version. */ +/*****************************************************************************/ +#define EVEL_SIGNALING_MAJOR_VERSION 2 +#define EVEL_SIGNALING_MINOR_VERSION 1 + +/**************************************************************************//** + * Vendor VNF Name fields. + * JSON equivalent field: vendorVnfNameFields + *****************************************************************************/ +typedef struct vendor_vnfname_field { + char * vendorname; + EVEL_OPTION_STRING vfmodule; + EVEL_OPTION_STRING vnfname; +} VENDOR_VNFNAME_FIELD; + +/**************************************************************************//** + * Signaling. + * JSON equivalent field: signalingFields + *****************************************************************************/ +typedef struct event_signaling { + /***************************************************************************/ + /* Header and version */ + /***************************************************************************/ + EVENT_HEADER header; + int major_version; + int minor_version; + + /***************************************************************************/ + /* Mandatory fields */ + /***************************************************************************/ + VENDOR_VNFNAME_FIELD vnfname_field; + EVEL_OPTION_STRING correlator; /* JSON: correlator */ + EVEL_OPTION_STRING local_ip_address; /* JSON: localIpAddress */ + EVEL_OPTION_STRING local_port; /* JSON: localPort */ + EVEL_OPTION_STRING remote_ip_address; /* JSON: remoteIpAddress */ + EVEL_OPTION_STRING remote_port; /* JSON: remotePort */ + + /***************************************************************************/ + /* Optional fields */ + /***************************************************************************/ + EVEL_OPTION_STRING compressed_sip; /* JSON: compressedSip */ + EVEL_OPTION_STRING summary_sip; /* JSON: summarySip */ + DLIST additional_info; + +} EVENT_SIGNALING; + +/**************************************************************************//** + * Sgnaling Additional Field. + * JSON equivalent field: additionalFields + *****************************************************************************/ +typedef struct signaling_additional_field { + char * name; + char * value; +} SIGNALING_ADDL_FIELD; + +/*****************************************************************************/ +/* Supported State Change version. */ +/*****************************************************************************/ +#define EVEL_STATE_CHANGE_MAJOR_VERSION 1 +#define EVEL_STATE_CHANGE_MINOR_VERSION 2 + +/**************************************************************************//** + * State Change. + * JSON equivalent field: stateChangeFields + *****************************************************************************/ +typedef struct event_state_change { + /***************************************************************************/ + /* Header and version */ + /***************************************************************************/ + EVENT_HEADER header; + int major_version; + int minor_version; + + /***************************************************************************/ + /* Mandatory fields */ + /***************************************************************************/ + EVEL_ENTITY_STATE new_state; + EVEL_ENTITY_STATE old_state; + char * state_interface; + double version; + + /***************************************************************************/ + /* Optional fields */ + /***************************************************************************/ + DLIST additional_fields; + +} EVENT_STATE_CHANGE; + +/**************************************************************************//** + * State Change Additional Field. + * JSON equivalent field: additionalFields + *****************************************************************************/ +typedef struct state_change_additional_field { + char * name; + char * value; +} STATE_CHANGE_ADDL_FIELD; + +/*****************************************************************************/ +/* Supported Syslog version. */ +/*****************************************************************************/ +#define EVEL_SYSLOG_MAJOR_VERSION 1 +#define EVEL_SYSLOG_MINOR_VERSION 2 + +/**************************************************************************//** + * Syslog. + * JSON equivalent field: syslogFields + *****************************************************************************/ +typedef struct event_syslog { + /***************************************************************************/ + /* Header and version */ + /***************************************************************************/ + EVENT_HEADER header; + int major_version; + int minor_version; + + /***************************************************************************/ + /* Mandatory fields */ + /***************************************************************************/ + EVEL_SOURCE_TYPES event_source_type; + char * syslog_msg; + char * syslog_tag; + + /***************************************************************************/ + /* Optional fields */ + /***************************************************************************/ + EVEL_OPTION_STRING additional_filters; + EVEL_OPTION_STRING event_source_host; + EVEL_OPTION_INT syslog_facility; + EVEL_OPTION_INT syslog_priority; + EVEL_OPTION_STRING syslog_proc; + EVEL_OPTION_INT syslog_proc_id; + EVEL_OPTION_STRING syslog_s_data; + EVEL_OPTION_STRING syslog_sdid; + EVEL_OPTION_STRING syslog_severity; + double syslog_fver; + EVEL_OPTION_INT syslog_ver; + +} EVENT_SYSLOG; + +/**************************************************************************//** + * Copyright. + * JSON equivalent object: attCopyrightNotice + *****************************************************************************/ +typedef struct copyright { + char * useAndRedistribution; + char * condition1; + char * condition2; + char * condition3; + char * condition4; + char * disclaimerLine1; + char * disclaimerLine2; + char * disclaimerLine3; + char * disclaimerLine4; +} COPYRIGHT; + +/**************************************************************************//** + * Library initialization. + * + * Initialize the EVEL library. + * + * @note This function initializes the cURL library. Applications making use + * of libcurl may need to pull the initialization out of here. Note + * also that this function is not threadsafe as a result - refer to + * libcurl's API documentation for relevant warnings. + * + * @sa Matching Term function. + * + * @param fqdn The API's FQDN or IP address. + * @param port The API's port. + * @param path The optional path (may be NULL). + * @param topic The optional topic part of the URL (may be NULL). + * @param secure Whether to use HTTPS (0=HTTP, 1=HTTPS). + * @param username Username for Basic Authentication of requests. + * @param password Password for Basic Authentication of requests. + * @param source_type The kind of node we represent. + * @param role The role this node undertakes. + * @param verbosity 0 for normal operation, positive values for chattier + * logs. + * + * @returns Status code + * @retval EVEL_SUCCESS On success + * @retval ::EVEL_ERR_CODES On failure. + *****************************************************************************/ +EVEL_ERR_CODES evel_initialize(const char * const fqdn, + int port, + const char * const path, + const char * const topic, + int secure, + const char * const username, + const char * const password, + EVEL_SOURCE_TYPES source_type, + const char * const role, + int verbosity + ); + +/**************************************************************************//** + * Clean up the EVEL library. + * + * @note that at present don't expect Init/Term cycling not to leak memory! + * + * @returns Status code + * @retval EVEL_SUCCESS On success + * @retval "One of ::EVEL_ERR_CODES" On failure. + *****************************************************************************/ +EVEL_ERR_CODES evel_terminate(void); + +EVEL_ERR_CODES evel_post_event(EVENT_HEADER * event); +const char * evel_error_string(void); + + +/**************************************************************************//** + * Free an event. + * + * Free off the event supplied. Will free all the contained allocated memory. + * + * @note It is safe to free a NULL pointer. + *****************************************************************************/ +void evel_free_event(void * event); + +/**************************************************************************//** + * Encode the event as a JSON event object according to AT&T's schema. + * + * @param json Pointer to where to store the JSON encoded data. + * @param max_size Size of storage available in json_body. + * @param event Pointer to the ::EVENT_HEADER to encode. + * @returns Number of bytes actually written. + *****************************************************************************/ +int evel_json_encode_event(char * json, + int max_size, + EVENT_HEADER * event); + +/**************************************************************************//** + * Initialize an event instance id. + * + * @param vfield Pointer to the event vnfname field being initialized. + * @param vendor_id The vendor id to encode in the event instance id. + * @param event_id The event id to encode in the event instance id. + *****************************************************************************/ +void evel_init_vendor_field(VENDOR_VNFNAME_FIELD * const vfield, + const char * const vendor_name); + +/**************************************************************************//** + * Set the Vendor module property of the Vendor. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param vfield Pointer to the Vendor field. + * @param module_name The module name to be set. ASCIIZ string. The caller + * does not need to preserve the value once the function + * returns. + *****************************************************************************/ +void evel_vendor_field_module_set(VENDOR_VNFNAME_FIELD * const vfield, + const char * const module_name); +/**************************************************************************//** + * Set the Vendor module property of the Vendor. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param vfield Pointer to the Vendor field. + * @param module_name The module name to be set. ASCIIZ string. The caller + * does not need to preserve the value once the function + * returns. + *****************************************************************************/ +void evel_vendor_field_vnfname_set(VENDOR_VNFNAME_FIELD * const vfield, + const char * const vnfname); +/**************************************************************************//** + * Free an event instance id. + * + * @param vfield Pointer to the event vnfname_field being freed. + *****************************************************************************/ +void evel_free_event_vendor_field(VENDOR_VNFNAME_FIELD * const vfield); + +/**************************************************************************//** + * Callback function to provide returned data. + * + * Copy data into the supplied buffer, write_callback::ptr, checking size + * limits. + * + * @returns Number of bytes placed into write_callback::ptr. 0 for EOF. + *****************************************************************************/ +size_t evel_write_callback(void *contents, + size_t size, + size_t nmemb, + void *userp); + +/*****************************************************************************/ +/*****************************************************************************/ +/* */ +/* HEARTBEAT - (includes common header, too) */ +/* */ +/*****************************************************************************/ +/*****************************************************************************/ + +/**************************************************************************//** + * Create a new heartbeat event. + * + * @note that the heartbeat is just a "naked" commonEventHeader! + * + * @returns pointer to the newly manufactured ::EVENT_HEADER. If the event is + * not used it must be released using ::evel_free_event + * @retval NULL Failed to create the event. + *****************************************************************************/ +EVENT_HEADER * evel_new_heartbeat(void); + +/**************************************************************************//** + * Create a new heartbeat event of given name and type. + * + * @note that the heartbeat is just a "naked" commonEventHeader! + * + * @param event_name Unique Event Name confirming Domain AsdcModel Description + * @param event_id A universal identifier of the event for: troubleshooting correlation, analysis, etc + * + * @returns pointer to the newly manufactured ::EVENT_HEADER. If the event is + * not used it must be released using ::evel_free_event + * @retval NULL Failed to create the event. + *****************************************************************************/ +EVENT_HEADER * evel_new_heartbeat_nameid(const char* ev_name, const char *ev_id); + + +/**************************************************************************//** + * Free an event header. + * + * Free off the event header supplied. Will free all the contained allocated + * memory. + * + * @note It does not free the header itself, since that may be part of a + * larger structure. + *****************************************************************************/ +void evel_free_header(EVENT_HEADER * const event); + +/**************************************************************************//** + * Initialize a newly created event header. + * + * @param header Pointer to the header being initialized. + *****************************************************************************/ +void evel_init_header(EVENT_HEADER * const header,const char *const eventname); + +/**************************************************************************//** + * Set the Event Type property of the event header. + * + * @param header Pointer to the ::EVENT_HEADER. + * @param type The Event Type to be set. ASCIIZ string. The caller + * does not need to preserve the value once the function + * returns. + *****************************************************************************/ +void evel_header_type_set(EVENT_HEADER * const header, + const char * const type); + +/**************************************************************************//** + * Set the Start Epoch property of the event header. + * + * @note The Start Epoch defaults to the time of event creation. + * + * @param header Pointer to the ::EVENT_HEADER. + * @param start_epoch_microsec + * The start epoch to set, in microseconds. + *****************************************************************************/ +void evel_start_epoch_set(EVENT_HEADER * const header, + const unsigned long long start_epoch_microsec); + +/**************************************************************************//** + * Set the Last Epoch property of the event header. + * + * @note The Last Epoch defaults to the time of event creation. + * + * @param header Pointer to the ::EVENT_HEADER. + * @param last_epoch_microsec + * The last epoch to set, in microseconds. + *****************************************************************************/ +void evel_last_epoch_set(EVENT_HEADER * const header, + const unsigned long long last_epoch_microsec); + +/**************************************************************************//** + * Set the Reporting Entity Name property of the event header. + * + * @note The Reporting Entity Name defaults to the OpenStack VM Name. + * + * @param header Pointer to the ::EVENT_HEADER. + * @param entity_name The entity name to set. + *****************************************************************************/ +void evel_reporting_entity_name_set(EVENT_HEADER * const header, + const char * const entity_name); + +/**************************************************************************//** + * Set the Reporting Entity Id property of the event header. + * + * @note The Reporting Entity Id defaults to the OpenStack VM UUID. + * + * @param header Pointer to the ::EVENT_HEADER. + * @param entity_id The entity id to set. + *****************************************************************************/ +void evel_reporting_entity_id_set(EVENT_HEADER * const header, + const char * const entity_id); + +/**************************************************************************//** + * Set the NFC Naming code property of the event header. + * + * @param header Pointer to the ::EVENT_HEADER. + * @param nfcnamingcode String + *****************************************************************************/ +void evel_nfcnamingcode_set(EVENT_HEADER * const header, + const char * const nfcnam); +/**************************************************************************//** + * Set the NF Naming code property of the event header. + * + * @param header Pointer to the ::EVENT_HEADER. + * @param nfnamingcode String + *****************************************************************************/ +void evel_nfnamingcode_set(EVENT_HEADER * const header, + const char * const nfnam); + +/*****************************************************************************/ +/*****************************************************************************/ +/* */ +/* FAULT */ +/* */ +/*****************************************************************************/ +/*****************************************************************************/ + +/**************************************************************************//** + * Create a new fault event. + * + * @note The mandatory fields on the Fault must be supplied to this factory + * function and are immutable once set. Optional fields have explicit + * setter functions, but again values may only be set once so that the + * Fault has immutable properties. + * @param event_name Unique Event Name + * @param event_id A universal identifier of the event for analysis etc + * @param condition The condition indicated by the Fault. + * @param specific_problem The specific problem triggering the fault. + * @param priority The priority of the event. + * @param severity The severity of the Fault. + * @param ev_source_type Source of Alarm event + * @param version fault version + * @param status status of Virtual Function + * @returns pointer to the newly manufactured ::EVENT_FAULT. If the event is + * not used (i.e. posted) it must be released using ::evel_free_fault. + * @retval NULL Failed to create the event. + *****************************************************************************/ +EVENT_FAULT * evel_new_fault(const char* ev_name, const char *ev_id, + const char * const condition, + const char * const specific_problem, + EVEL_EVENT_PRIORITIES priority, + EVEL_SEVERITIES severity, + EVEL_SOURCE_TYPES ev_source_type, + EVEL_VF_STATUSES status); + +/**************************************************************************//** + * Free a Fault. + * + * Free off the Fault supplied. Will free all the contained allocated memory. + * + * @note It does not free the Fault itself, since that may be part of a + * larger structure. + *****************************************************************************/ +void evel_free_fault(EVENT_FAULT * event); + +/**************************************************************************//** + * Set the Fault Category property of the Fault. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param fault Pointer to the fault. + * @param category Category : license, link, routing, security, signaling. + * ASCIIZ string. The caller + * does not need to preserve the value once the function + * returns. + *****************************************************************************/ +void evel_fault_category_set(EVENT_FAULT * fault, + const char * const category); + +/**************************************************************************//** + * Set the Alarm Interface A property of the Fault. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param fault Pointer to the fault. + * @param interface The Alarm Interface A to be set. ASCIIZ string. The caller + * does not need to preserve the value once the function + * returns. + *****************************************************************************/ +void evel_fault_interface_set(EVENT_FAULT * fault, + const char * const interface); + +/**************************************************************************//** + * Add an additional value name/value pair to the Fault. + * + * The name and value are null delimited ASCII strings. The library takes + * a copy so the caller does not have to preserve values after the function + * returns. + * + * @param fault Pointer to the fault. + * @param name ASCIIZ string with the attribute's name. + * @param value ASCIIZ string with the attribute's value. + *****************************************************************************/ +void evel_fault_addl_info_add(EVENT_FAULT * fault, char * name, char * value); + +/**************************************************************************//** + * Set the Event Type property of the Fault. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param fault Pointer to the fault. + * @param type The Event Type to be set. ASCIIZ string. The caller + * does not need to preserve the value once the function + * returns. + *****************************************************************************/ +void evel_fault_type_set(EVENT_FAULT * fault, const char * const type); + +/*****************************************************************************/ +/*****************************************************************************/ +/* */ +/* MEASUREMENT */ +/* */ +/*****************************************************************************/ +/*****************************************************************************/ + +/**************************************************************************//** + * Create a new Measurement event. + * + * @note The mandatory fields on the Measurement must be supplied to this + * factory function and are immutable once set. Optional fields have + * explicit setter functions, but again values may only be set once so + * that the Measurement has immutable properties. + * + * @param measurement_interval + * @param event_name Unique Event Name + * @param event_id A universal identifier of the event for analysis etc + * + * @returns pointer to the newly manufactured ::EVENT_MEASUREMENT. If the + * event is not used (i.e. posted) it must be released using + * ::evel_free_event. + * @retval NULL Failed to create the event. + *****************************************************************************/ +EVENT_MEASUREMENT * evel_new_measurement(double measurement_interval,const char* ev_name, const char *ev_id); + +/**************************************************************************//** + * Free a Measurement. + * + * Free off the Measurement supplied. Will free all the contained allocated + * memory. + * + * @note It does not free the Measurement itself, since that may be part of a + * larger structure. + *****************************************************************************/ +void evel_free_measurement(EVENT_MEASUREMENT * event); + +/**************************************************************************//** + * Set the Event Type property of the Measurement. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param measurement Pointer to the Measurement. + * @param type The Event Type to be set. ASCIIZ string. The caller + * does not need to preserve the value once the function + * returns. + *****************************************************************************/ +void evel_measurement_type_set(EVENT_MEASUREMENT * measurement, + const char * const type); + +/**************************************************************************//** + * Set the Concurrent Sessions property of the Measurement. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param measurement Pointer to the Measurement. + * @param concurrent_sessions The Concurrent Sessions to be set. + *****************************************************************************/ +void evel_measurement_conc_sess_set(EVENT_MEASUREMENT * measurement, + int concurrent_sessions); + +/**************************************************************************//** + * Set the Configured Entities property of the Measurement. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param measurement Pointer to the Measurement. + * @param configured_entities The Configured Entities to be set. + *****************************************************************************/ +void evel_measurement_cfg_ents_set(EVENT_MEASUREMENT * measurement, + int configured_entities); + +/**************************************************************************//** + * Add an additional set of Errors to the Measurement. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param measurement Pointer to the measurement. + * @param receive_discards The number of receive discards. + * @param receive_errors The number of receive errors. + * @param transmit_discards The number of transmit discards. + * @param transmit_errors The number of transmit errors. + *****************************************************************************/ +void evel_measurement_errors_set(EVENT_MEASUREMENT * measurement, + int receive_discards, + int receive_errors, + int transmit_discards, + int transmit_errors); + +/**************************************************************************//** + * Set the Mean Request Latency property of the Measurement. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param measurement Pointer to the Measurement. + * @param mean_request_latency The Mean Request Latency to be set. + *****************************************************************************/ +void evel_measurement_mean_req_lat_set(EVENT_MEASUREMENT * measurement, + double mean_request_latency); + +/**************************************************************************//** + * Set the Request Rate property of the Measurement. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param measurement Pointer to the Measurement. + * @param request_rate The Request Rate to be set. + *****************************************************************************/ +void evel_measurement_request_rate_set(EVENT_MEASUREMENT * measurement, + int request_rate); + +/**************************************************************************//** + * Add an additional CPU usage value name/value pair to the Measurement. + * + * The name and value are null delimited ASCII strings. The library takes + * a copy so the caller does not have to preserve values after the function + * returns. + * + * @param measurement Pointer to the measurement. + * @param id ASCIIZ string with the CPU's identifier. + * @param usage CPU utilization. + *****************************************************************************/ +MEASUREMENT_CPU_USE * evel_measurement_new_cpu_use_add(EVENT_MEASUREMENT * measurement, char * id, double usage); + +/**************************************************************************//** + * Set the CPU Idle value in measurement interval + * percentage of CPU time spent in the idle task + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param cpu_use Pointer to the CPU Use. + * @param val double + *****************************************************************************/ +void evel_measurement_cpu_use_idle_set(MEASUREMENT_CPU_USE *const cpu_use, + const double val); + +/**************************************************************************//** + * Set the percentage of time spent servicing interrupts + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param cpu_use Pointer to the CPU Use. + * @param val double + *****************************************************************************/ +void evel_measurement_cpu_use_interrupt_set(MEASUREMENT_CPU_USE * const cpu_use, + const double val); + +/**************************************************************************//** + * Set the percentage of time spent running user space processes that have been niced + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param cpu_use Pointer to the CPU Use. + * @param val double + *****************************************************************************/ +void evel_measurement_cpu_use_nice_set(MEASUREMENT_CPU_USE * const cpu_use, + const double val); + +/**************************************************************************//** + * Set the percentage of time spent handling soft irq interrupts + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param cpu_use Pointer to the CPU Use. + * @param val double + *****************************************************************************/ +void evel_measurement_cpu_use_softirq_set(MEASUREMENT_CPU_USE * const cpu_use, + const double val); +/**************************************************************************//** + * Set the percentage of time spent in involuntary wait + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param cpu_use Pointer to the CPU Use. + * @param val double + *****************************************************************************/ +void evel_measurement_cpu_use_steal_set(MEASUREMENT_CPU_USE * const cpu_use, + const double val); +/**************************************************************************//** + * Set the percentage of time spent on system tasks running the kernel + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param cpu_use Pointer to the CPU Use. + * @param val double + *****************************************************************************/ +void evel_measurement_cpu_use_system_set(MEASUREMENT_CPU_USE * const cpu_use, + const double val); +/**************************************************************************//** + * Set the percentage of time spent running un-niced user space processes + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param cpu_use Pointer to the CPU Use. + * @param val double + *****************************************************************************/ +void evel_measurement_cpu_use_usageuser_set(MEASUREMENT_CPU_USE * const cpu_use, + const double val); +/**************************************************************************//** + * Set the percentage of CPU time spent waiting for I/O operations to complete + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param cpu_use Pointer to the CPU Use. + * @param val double + *****************************************************************************/ +void evel_measurement_cpu_use_wait_set(MEASUREMENT_CPU_USE * const cpu_use, + const double val); + +/**************************************************************************//** + * Add an additional File System usage value name/value pair to the + * Measurement. + * + * The filesystem_name is null delimited ASCII string. The library takes a + * copy so the caller does not have to preserve values after the function + * returns. + * + * @param measurement Pointer to the measurement. + * @param filesystem_name ASCIIZ string with the file-system's UUID. + * @param block_configured Block storage configured. + * @param block_used Block storage in use. + * @param block_iops Block storage IOPS. + * @param ephemeral_configured Ephemeral storage configured. + * @param ephemeral_used Ephemeral storage in use. + * @param ephemeral_iops Ephemeral storage IOPS. + *****************************************************************************/ +void evel_measurement_fsys_use_add(EVENT_MEASUREMENT * measurement, + char * filesystem_name, + double block_configured, + double block_used, + double block_iops, + double ephemeral_configured, + double ephemeral_used, + double ephemeral_iops); + +/**************************************************************************//** + * Add a Feature usage value name/value pair to the Measurement. + * + * The name is null delimited ASCII string. The library takes + * a copy so the caller does not have to preserve values after the function + * returns. + * + * @param measurement Pointer to the measurement. + * @param feature ASCIIZ string with the feature's name. + * @param utilization Utilization of the feature. + *****************************************************************************/ +void evel_measurement_feature_use_add(EVENT_MEASUREMENT * measurement, + char * feature, + int utilization); + +/**************************************************************************//** + * Add a Additional Measurement value name/value pair to the Measurement. + * + * The name is null delimited ASCII string. The library takes + * a copy so the caller does not have to preserve values after the function + * returns. + * + * @param measurement Pointer to the Measurement. + * @param group ASCIIZ string with the measurement group's name. + * @param name ASCIIZ string containing the measurement's name. + * @param name ASCIIZ string containing the measurement's value. + *****************************************************************************/ +void evel_measurement_custom_measurement_add(EVENT_MEASUREMENT * measurement, + const char * const group, + const char * const name, + const char * const value); + +/**************************************************************************//** + * Add a Codec usage value name/value pair to the Measurement. + * + * The name is null delimited ASCII string. The library takes + * a copy so the caller does not have to preserve values after the function + * returns. + * + * @param measurement Pointer to the measurement. + * @param codec ASCIIZ string with the codec's name. + * @param utilization Utilization of the feature. + *****************************************************************************/ +void evel_measurement_codec_use_add(EVENT_MEASUREMENT * measurement, + char * codec, + int utilization); + +/**************************************************************************//** + * Set the Media Ports in Use property of the Measurement. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param measurement Pointer to the measurement. + * @param media_ports_in_use The media port usage to set. + *****************************************************************************/ +void evel_measurement_media_port_use_set(EVENT_MEASUREMENT * measurement, + int media_ports_in_use); + +/**************************************************************************//** + * Set the VNFC Scaling Metric property of the Measurement. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param measurement Pointer to the measurement. + * @param scaling_metric The scaling metric to set. + *****************************************************************************/ +void evel_measurement_vnfc_scaling_metric_set(EVENT_MEASUREMENT * measurement, + int scaling_metric); + +/**************************************************************************//** + * Create a new Latency Bucket to be added to a Measurement event. + * + * @note The mandatory fields on the ::MEASUREMENT_LATENCY_BUCKET must be + * supplied to this factory function and are immutable once set. + * Optional fields have explicit setter functions, but again values + * may only be set once so that the ::MEASUREMENT_LATENCY_BUCKET has + * immutable properties. + * + * @param count Count of events in this bucket. + * + * @returns pointer to the newly manufactured ::MEASUREMENT_LATENCY_BUCKET. + * @retval NULL Failed to create the Latency Bucket. + *****************************************************************************/ +MEASUREMENT_LATENCY_BUCKET * evel_new_meas_latency_bucket(const int count); + +/**************************************************************************//** + * Set the High End property of the Measurement Latency Bucket. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param bucket Pointer to the Measurement Latency Bucket. + * @param high_end High end of the bucket's range. + *****************************************************************************/ +void evel_meas_latency_bucket_high_end_set( + MEASUREMENT_LATENCY_BUCKET * const bucket, + const double high_end); + +/**************************************************************************//** + * Set the Low End property of the Measurement Latency Bucket. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param bucket Pointer to the Measurement Latency Bucket. + * @param low_end Low end of the bucket's range. + *****************************************************************************/ +void evel_meas_latency_bucket_low_end_set( + MEASUREMENT_LATENCY_BUCKET * const bucket, + const double low_end); + +/**************************************************************************//** + * Add an additional Measurement Latency Bucket to the specified event. + * + * @param measurement Pointer to the Measurement event. + * @param bucket Pointer to the Measurement Latency Bucket to add. + *****************************************************************************/ +void evel_meas_latency_bucket_add(EVENT_MEASUREMENT * const measurement, + MEASUREMENT_LATENCY_BUCKET * const bucket); + +/**************************************************************************//** + * Add an additional Latency Distribution bucket to the Measurement. + * + * This function implements the previous API, purely for convenience. + * + * @param measurement Pointer to the measurement. + * @param low_end Low end of the bucket's range. + * @param high_end High end of the bucket's range. + * @param count Count of events in this bucket. + *****************************************************************************/ +void evel_measurement_latency_add(EVENT_MEASUREMENT * const measurement, + const double low_end, + const double high_end, + const int count); + +/**************************************************************************//** + * Create a new vNIC Use to be added to a Measurement event. + * + * @note The mandatory fields on the ::MEASUREMENT_VNIC_PERFORMANCE must be supplied + * to this factory function and are immutable once set. Optional + * fields have explicit setter functions, but again values may only be + * set once so that the ::MEASUREMENT_VNIC_PERFORMANCE has immutable + * properties. + * + * @param vnic_id ASCIIZ string with the vNIC's ID. + * @param val_suspect True or false confidence in data. + * + * @returns pointer to the newly manufactured ::MEASUREMENT_VNIC_PERFORMANCE. + * If the structure is not used it must be released using + * ::evel_measurement_free_vnic_performance. + * @retval NULL Failed to create the vNIC Use. + *****************************************************************************/ +MEASUREMENT_VNIC_PERFORMANCE * evel_measurement_new_vnic_performance(char * const vnic_id, char * const val_suspect); + +/**************************************************************************//** + * Free a vNIC Use. + * + * Free off the ::MEASUREMENT_VNIC_PERFORMANCE supplied. Will free all the contained + * allocated memory. + * + * @note It does not free the vNIC Use itself, since that may be part of a + * larger structure. + *****************************************************************************/ +void evel_measurement_free_vnic_performance(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance); + +/**************************************************************************//** + * Set the Accumulated Broadcast Packets Received in measurement interval + * property of the vNIC performance. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param vnic_performance Pointer to the vNIC Use. + * @param recvd_bcast_packets_acc + *****************************************************************************/ +void evel_vnic_performance_rx_bcast_pkt_acc_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance, + const double recvd_bcast_packets_acc); +/**************************************************************************//** + * Set the Delta Broadcast Packets Received in measurement interval + * property of the vNIC performance. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param vnic_performance Pointer to the vNIC Use. + * @param recvd_bcast_packets_delta + *****************************************************************************/ +void evel_vnic_performance_rx_bcast_pkt_delta_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance, + const double recvd_bcast_packets_delta); +/**************************************************************************//** + * Set the Discarded Packets Received in measurement interval + * property of the vNIC performance. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param vnic_performance Pointer to the vNIC Use. + * @param recvd_discard_packets_acc + *****************************************************************************/ +void evel_vnic_performance_rx_discard_pkt_acc_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance, + const double recvd_discard_packets_acc); +/**************************************************************************//** + * Set the Delta Discarded Packets Received in measurement interval + * property of the vNIC performance. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param vnic_performance Pointer to the vNIC Use. + * @param recvd_discard_packets_delta + *****************************************************************************/ +void evel_vnic_performance_rx_discard_pkt_delta_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance, + const double recvd_discard_packets_delta); +/**************************************************************************//** + * Set the Error Packets Received in measurement interval + * property of the vNIC performance. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param vnic_performance Pointer to the vNIC Use. + * @param recvd_error_packets_acc + *****************************************************************************/ +void evel_vnic_performance_rx_error_pkt_acc_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance, + const double recvd_error_packets_acc); +/**************************************************************************//** + * Set the Delta Error Packets Received in measurement interval + * property of the vNIC performance. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param vnic_performance Pointer to the vNIC Use. + * @param recvd_error_packets_delta + *****************************************************************************/ +void evel_vnic_performance_rx_error_pkt_delta_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance, + const double recvd_error_packets_delta); +/**************************************************************************//** + * Set the Accumulated Multicast Packets Received in measurement interval + * property of the vNIC performance. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param vnic_performance Pointer to the vNIC Use. + * @param recvd_mcast_packets_acc + *****************************************************************************/ +void evel_vnic_performance_rx_mcast_pkt_acc_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance, + const double recvd_mcast_packets_acc); +/**************************************************************************//** + * Set the Delta Multicast Packets Received in measurement interval + * property of the vNIC performance. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param vnic_performance Pointer to the vNIC Use. + * @param recvd_mcast_packets_delta + *****************************************************************************/ +void evel_vnic_performance_rx_mcast_pkt_delta_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance, + const double recvd_mcast_packets_delta); +/**************************************************************************//** + * Set the Accumulated Octets Received in measurement interval + * property of the vNIC performance. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param vnic_performance Pointer to the vNIC Use. + * @param recvd_octets_acc + *****************************************************************************/ +void evel_vnic_performance_rx_octets_acc_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance, + const double recvd_octets_acc); +/**************************************************************************//** + * Set the Delta Octets Received in measurement interval + * property of the vNIC performance. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param vnic_performance Pointer to the vNIC Use. + * @param recvd_octets_delta + *****************************************************************************/ +void evel_vnic_performance_rx_octets_delta_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance, + const double recvd_octets_delta); +/**************************************************************************//** + * Set the Accumulated Total Packets Received in measurement interval + * property of the vNIC performance. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param vnic_performance Pointer to the vNIC Use. + * @param recvd_total_packets_acc + *****************************************************************************/ +void evel_vnic_performance_rx_total_pkt_acc_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance, + const double recvd_total_packets_acc); +/**************************************************************************//** + * Set the Delta Total Packets Received in measurement interval + * property of the vNIC performance. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param vnic_performance Pointer to the vNIC Use. + * @param recvd_total_packets_delta + *****************************************************************************/ +void evel_vnic_performance_rx_total_pkt_delta_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance, + const double recvd_total_packets_delta); +/**************************************************************************//** + * Set the Accumulated Unicast Packets Received in measurement interval + * property of the vNIC performance. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param vnic_performance Pointer to the vNIC Use. + * @param recvd_ucast_packets_acc + *****************************************************************************/ +void evel_vnic_performance_rx_ucast_pkt_acc_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance, + const double recvd_ucast_packets_acc); +/**************************************************************************//** + * Set the Delta Unicast packets Received in measurement interval + * property of the vNIC performance. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param vnic_performance Pointer to the vNIC Use. + * @param recvd_ucast_packets_delta + *****************************************************************************/ +void evel_vnic_performance_rx_ucast_pkt_delta_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance, + const double recvd_ucast_packets_delta); +/**************************************************************************//** + * Set the Transmitted Broadcast Packets in measurement interval + * property of the vNIC performance. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param vnic_performance Pointer to the vNIC Use. + * @param tx_bcast_packets_acc + *****************************************************************************/ +void evel_vnic_performance_tx_bcast_pkt_acc_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance, + const double tx_bcast_packets_acc); +/**************************************************************************//** + * Set the Delta Broadcast packets Transmitted in measurement interval + * property of the vNIC performance. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param vnic_performance Pointer to the vNIC Use. + * @param tx_bcast_packets_delta + *****************************************************************************/ +void evel_vnic_performance_tx_bcast_pkt_delta_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance, + const double tx_bcast_packets_delta); +/**************************************************************************//** + * Set the Transmitted Discarded Packets in measurement interval + * property of the vNIC performance. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param vnic_performance Pointer to the vNIC Use. + * @param tx_discarded_packets_acc + *****************************************************************************/ +void evel_vnic_performance_tx_discarded_pkt_acc_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance, + const double tx_discarded_packets_acc); +/**************************************************************************//** + * Set the Delta Discarded packets Transmitted in measurement interval + * property of the vNIC performance. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param vnic_performance Pointer to the vNIC Use. + * @param tx_discarded_packets_delta + *****************************************************************************/ +void evel_vnic_performance_tx_discarded_pkt_delta_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance, + const double tx_discarded_packets_delta); +/**************************************************************************//** + * Set the Transmitted Errored Packets in measurement interval + * property of the vNIC performance. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param vnic_performance Pointer to the vNIC Use. + * @param tx_error_packets_acc + *****************************************************************************/ +void evel_vnic_performance_tx_error_pkt_acc_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance, + const double tx_error_packets_acc); +/**************************************************************************//** + * Set the Delta Errored packets Transmitted in measurement interval + * property of the vNIC performance. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param vnic_performance Pointer to the vNIC Use. + * @param tx_error_packets_delta + *****************************************************************************/ +void evel_vnic_performance_tx_error_pkt_delta_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance, + const double tx_error_packets_delta); +/**************************************************************************//** + * Set the Transmitted Multicast Packets in measurement interval + * property of the vNIC performance. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param vnic_performance Pointer to the vNIC Use. + * @param tx_mcast_packets_acc + *****************************************************************************/ +void evel_vnic_performance_tx_mcast_pkt_acc_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance, + const double tx_mcast_packets_acc); +/**************************************************************************//** + * Set the Delta Multicast packets Transmitted in measurement interval + * property of the vNIC performance. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param vnic_performance Pointer to the vNIC Use. + * @param tx_mcast_packets_delta + *****************************************************************************/ +void evel_vnic_performance_tx_mcast_pkt_delta_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance, + const double tx_mcast_packets_delta); +/**************************************************************************//** + * Set the Transmitted Octets in measurement interval + * property of the vNIC performance. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param vnic_performance Pointer to the vNIC Use. + * @param tx_octets_acc + *****************************************************************************/ +void evel_vnic_performance_tx_octets_acc_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance, + const double tx_octets_acc); +/**************************************************************************//** + * Set the Delta Octets Transmitted in measurement interval + * property of the vNIC performance. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param vnic_performance Pointer to the vNIC Use. + * @param tx_octets_delta + *****************************************************************************/ +void evel_vnic_performance_tx_octets_delta_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance, + const double tx_octets_delta); +/**************************************************************************//** + * Set the Transmitted Total Packets in measurement interval + * property of the vNIC performance. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param vnic_performance Pointer to the vNIC Use. + * @param tx_total_packets_acc + *****************************************************************************/ +void evel_vnic_performance_tx_total_pkt_acc_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance, + const double tx_total_packets_acc); +/**************************************************************************//** + * Set the Delta Total Packets Transmitted in measurement interval + * property of the vNIC performance. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param vnic_performance Pointer to the vNIC Use. + * @param tx_total_packets_delta + *****************************************************************************/ +void evel_vnic_performance_tx_total_pkt_delta_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance, + const double tx_total_packets_delta); +/**************************************************************************//** + * Set the Transmitted Unicast Packets in measurement interval + * property of the vNIC performance. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param vnic_performance Pointer to the vNIC Use. + * @param tx_ucast_packets_acc + *****************************************************************************/ +void evel_vnic_performance_tx_ucast_packets_acc_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance, + const double tx_ucast_packets_acc); +/**************************************************************************//** + * Set the Delta Octets Transmitted in measurement interval + * property of the vNIC performance. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param vnic_performance Pointer to the vNIC Use. + * @param tx_ucast_packets_delta + *****************************************************************************/ +void evel_vnic_performance_tx_ucast_pkt_delta_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance, + const double tx_ucast_packets_delta); + +/**************************************************************************//** + * Add an additional vNIC Use to the specified Measurement event. + * + * @param measurement Pointer to the measurement. + * @param vnic_performance Pointer to the vNIC Use to add. + *****************************************************************************/ +void evel_meas_vnic_performance_add(EVENT_MEASUREMENT * const measurement, + MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance); + +/**************************************************************************//** + * Add an additional vNIC usage record Measurement. + * + * This function implements the previous API, purely for convenience. + * + * The ID is null delimited ASCII string. The library takes a copy so the + * caller does not have to preserve values after the function returns. + * + * @param measurement Pointer to the measurement. + * @param vnic_id ASCIIZ string with the vNIC's ID. + * @param valset true or false confidence level + * @param recvd_bcast_packets_acc Recieved broadcast packets + * @param recvd_bcast_packets_delta Received delta broadcast packets + * @param recvd_discarded_packets_acc Recieved discarded packets + * @param recvd_discarded_packets_delta Received discarded delta packets + * @param recvd_error_packets_acc Received error packets + * @param recvd_error_packets_delta, Received delta error packets + * @param recvd_mcast_packets_acc Received multicast packets + * @param recvd_mcast_packets_delta Received delta multicast packets + * @param recvd_octets_acc Received octets + * @param recvd_octets_delta Received delta octets + * @param recvd_total_packets_acc Received total packets + * @param recvd_total_packets_delta Received delta total packets + * @param recvd_ucast_packets_acc Received Unicast packets + * @param recvd_ucast_packets_delta Received delta unicast packets + * @param tx_bcast_packets_acc Transmitted broadcast packets + * @param tx_bcast_packets_delta Transmitted delta broadcast packets + * @param tx_discarded_packets_acc Transmitted packets discarded + * @param tx_discarded_packets_delta Transmitted delta discarded packets + * @param tx_error_packets_acc Transmitted error packets + * @param tx_error_packets_delta Transmitted delta error packets + * @param tx_mcast_packets_acc Transmitted multicast packets accumulated + * @param tx_mcast_packets_delta Transmitted delta multicast packets + * @param tx_octets_acc Transmitted octets + * @param tx_octets_delta Transmitted delta octets + * @param tx_total_packets_acc Transmitted total packets + * @param tx_total_packets_delta Transmitted delta total packets + * @param tx_ucast_packets_acc Transmitted Unicast packets + * @param tx_ucast_packets_delta Transmitted delta Unicast packets + *****************************************************************************/ +void evel_measurement_vnic_performance_add(EVENT_MEASUREMENT * const measurement, + char * const vnic_id, + char * valset, + double recvd_bcast_packets_acc, + double recvd_bcast_packets_delta, + double recvd_discarded_packets_acc, + double recvd_discarded_packets_delta, + double recvd_error_packets_acc, + double recvd_error_packets_delta, + double recvd_mcast_packets_acc, + double recvd_mcast_packets_delta, + double recvd_octets_acc, + double recvd_octets_delta, + double recvd_total_packets_acc, + double recvd_total_packets_delta, + double recvd_ucast_packets_acc, + double recvd_ucast_packets_delta, + double tx_bcast_packets_acc, + double tx_bcast_packets_delta, + double tx_discarded_packets_acc, + double tx_discarded_packets_delta, + double tx_error_packets_acc, + double tx_error_packets_delta, + double tx_mcast_packets_acc, + double tx_mcast_packets_delta, + double tx_octets_acc, + double tx_octets_delta, + double tx_total_packets_acc, + double tx_total_packets_delta, + double tx_ucast_packets_acc, + double tx_ucast_packets_delta); + +/*****************************************************************************/ +/*****************************************************************************/ +/* */ +/* REPORT */ +/* */ +/*****************************************************************************/ +/*****************************************************************************/ + +/**************************************************************************//** + * Create a new Report event. + * + * @note The mandatory fields on the Report must be supplied to this + * factory function and are immutable once set. Optional fields have + * explicit setter functions, but again values may only be set once so + * that the Report has immutable properties. + * + * @param measurement_interval + * @param event_name Unique Event Name + * @param event_id A universal identifier of the event for analysis etc + * + * @returns pointer to the newly manufactured ::EVENT_REPORT. If the event is + * not used (i.e. posted) it must be released using + * ::evel_free_report. + * @retval NULL Failed to create the event. + *****************************************************************************/ +EVENT_REPORT * evel_new_report(double measurement_interval,const char* ev_name, const char *ev_id); + +/**************************************************************************//** + * Free a Report. + * + * Free off the Report supplied. Will free all the contained allocated memory. + * + * @note It does not free the Report itself, since that may be part of a + * larger structure. + *****************************************************************************/ +void evel_free_report(EVENT_REPORT * event); + +/**************************************************************************//** + * Set the Event Type property of the Report. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param report Pointer to the Report. + * @param type The Event Type to be set. ASCIIZ string. The caller + * does not need to preserve the value once the function + * returns. + *****************************************************************************/ +void evel_report_type_set(EVENT_REPORT * report, const char * const type); + +/**************************************************************************//** + * Add a Feature usage value name/value pair to the Report. + * + * The name is null delimited ASCII string. The library takes + * a copy so the caller does not have to preserve values after the function + * returns. + * + * @param report Pointer to the report. + * @param feature ASCIIZ string with the feature's name. + * @param utilization Utilization of the feature. + *****************************************************************************/ +void evel_report_feature_use_add(EVENT_REPORT * report, + char * feature, + int utilization); + +/**************************************************************************//** + * Add a Additional Measurement value name/value pair to the Report. + * + * The name is null delimited ASCII string. The library takes + * a copy so the caller does not have to preserve values after the function + * returns. + * + * @param report Pointer to the report. + * @param group ASCIIZ string with the measurement group's name. + * @param name ASCIIZ string containing the measurement's name. + * @param value ASCIIZ string containing the measurement's value. + *****************************************************************************/ +void evel_report_custom_measurement_add(EVENT_REPORT * report, + const char * const group, + const char * const name, + const char * const value); + +/*****************************************************************************/ +/*****************************************************************************/ +/* */ +/* MOBILE_FLOW */ +/* */ +/*****************************************************************************/ +/*****************************************************************************/ + +/**************************************************************************//** + * Create a new Mobile Flow event. + * + * @note The mandatory fields on the Mobile Flow must be supplied to this + * factory function and are immutable once set. Optional fields have + * explicit setter functions, but again values may only be set once so + * that the Mobile Flow has immutable properties. + * + * @param event_name Unique Event Name + * @param event_id A universal identifier of the event for analysis etc + * @param flow_direction + * @param gtp_per_flow_metrics + * @param ip_protocol_type + * @param ip_version + * @param other_endpoint_ip_address + * @param other_endpoint_port + * @param reporting_endpoint_ip_addr + * @param reporting_endpoint_port + * + * @returns pointer to the newly manufactured ::EVENT_MOBILE_FLOW. If the + * event is not used (i.e. posted) it must be released using + * ::evel_free_mobile_flow. + * @retval NULL Failed to create the event. + *****************************************************************************/ +EVENT_MOBILE_FLOW * evel_new_mobile_flow( + const char* ev_name, const char *ev_id, + const char * const flow_direction, + MOBILE_GTP_PER_FLOW_METRICS * gtp_per_flow_metrics, + const char * const ip_protocol_type, + const char * const ip_version, + const char * const other_endpoint_ip_address, + int other_endpoint_port, + const char * const reporting_endpoint_ip_addr, + int reporting_endpoint_port); + +/**************************************************************************//** + * Free a Mobile Flow. + * + * Free off the Mobile Flow supplied. Will free all the contained allocated + * memory. + * + * @note It does not free the Mobile Flow itself, since that may be part of a + * larger structure. + *****************************************************************************/ +void evel_free_mobile_flow(EVENT_MOBILE_FLOW * event); + +/**************************************************************************//** + * Set the Event Type property of the Mobile Flow. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param mobile_flow Pointer to the Mobile Flow. + * @param type The Event Type to be set. ASCIIZ string. The caller + * does not need to preserve the value once the function + * returns. + *****************************************************************************/ +void evel_mobile_flow_type_set(EVENT_MOBILE_FLOW * mobile_flow, + const char * const type); + +/**************************************************************************//** + * Set the Application Type property of the Mobile Flow. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param mobile_flow Pointer to the Mobile Flow. + * @param type The Application Type to be set. ASCIIZ string. The caller + * does not need to preserve the value once the function + * returns. + *****************************************************************************/ +void evel_mobile_flow_app_type_set(EVENT_MOBILE_FLOW * mobile_flow, + const char * const type); + +/**************************************************************************//** + * Set the Application Protocol Type property of the Mobile Flow. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param mobile_flow Pointer to the Mobile Flow. + * @param type The Application Protocol Type to be set. ASCIIZ string. + * The caller does not need to preserve the value once the + * function returns. + *****************************************************************************/ +void evel_mobile_flow_app_prot_type_set(EVENT_MOBILE_FLOW * mobile_flow, + const char * const type); + +/**************************************************************************//** + * Set the Application Protocol Version property of the Mobile Flow. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param mobile_flow Pointer to the Mobile Flow. + * @param version The Application Protocol Version to be set. ASCIIZ + * string. The caller does not need to preserve the value + * once the function returns. + *****************************************************************************/ +void evel_mobile_flow_app_prot_ver_set(EVENT_MOBILE_FLOW * mobile_flow, + const char * const version); + +/**************************************************************************//** + * Set the CID property of the Mobile Flow. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param mobile_flow Pointer to the Mobile Flow. + * @param cid The CID to be set. ASCIIZ string. The caller does not + * need to preserve the value once the function returns. + *****************************************************************************/ +void evel_mobile_flow_cid_set(EVENT_MOBILE_FLOW * mobile_flow, + const char * const cid); + +/**************************************************************************//** + * Set the Connection Type property of the Mobile Flow. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param mobile_flow Pointer to the Mobile Flow. + * @param type The Connection Type to be set. ASCIIZ string. The caller + * does not need to preserve the value once the function + * returns. + *****************************************************************************/ +void evel_mobile_flow_con_type_set(EVENT_MOBILE_FLOW * mobile_flow, + const char * const type); + +/**************************************************************************//** + * Set the ECGI property of the Mobile Flow. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param mobile_flow Pointer to the Mobile Flow. + * @param ecgi The ECGI to be set. ASCIIZ string. The caller does not + * need to preserve the value once the function returns. + *****************************************************************************/ +void evel_mobile_flow_ecgi_set(EVENT_MOBILE_FLOW * mobile_flow, + const char * const ecgi); + +/**************************************************************************//** + * Set the GTP Protocol Type property of the Mobile Flow. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param mobile_flow Pointer to the Mobile Flow. + * @param type The GTP Protocol Type to be set. ASCIIZ string. The + * caller does not need to preserve the value once the + * function returns. + *****************************************************************************/ +void evel_mobile_flow_gtp_prot_type_set(EVENT_MOBILE_FLOW * mobile_flow, + const char * const type); + +/**************************************************************************//** + * Set the GTP Protocol Version property of the Mobile Flow. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param mobile_flow Pointer to the Mobile Flow. + * @param version The GTP Protocol Version to be set. ASCIIZ string. The + * caller does not need to preserve the value once the + * function returns. + *****************************************************************************/ +void evel_mobile_flow_gtp_prot_ver_set(EVENT_MOBILE_FLOW * mobile_flow, + const char * const version); + +/**************************************************************************//** + * Set the HTTP Header property of the Mobile Flow. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param mobile_flow Pointer to the Mobile Flow. + * @param header The HTTP header to be set. ASCIIZ string. The caller does + * not need to preserve the value once the function returns. + *****************************************************************************/ +void evel_mobile_flow_http_header_set(EVENT_MOBILE_FLOW * mobile_flow, + const char * const header); + +/**************************************************************************//** + * Set the IMEI property of the Mobile Flow. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param mobile_flow Pointer to the Mobile Flow. + * @param imei The IMEI to be set. ASCIIZ string. The caller does not + * need to preserve the value once the function returns. + *****************************************************************************/ +void evel_mobile_flow_imei_set(EVENT_MOBILE_FLOW * mobile_flow, + const char * const imei); + +/**************************************************************************//** + * Set the IMSI property of the Mobile Flow. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param mobile_flow Pointer to the Mobile Flow. + * @param imsi The IMSI to be set. ASCIIZ string. The caller does not + * need to preserve the value once the function returns. + *****************************************************************************/ +void evel_mobile_flow_imsi_set(EVENT_MOBILE_FLOW * mobile_flow, + const char * const imsi); + +/**************************************************************************//** + * Set the LAC property of the Mobile Flow. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param mobile_flow Pointer to the Mobile Flow. + * @param lac The LAC to be set. ASCIIZ string. The caller does not + * need to preserve the value once the function returns. + *****************************************************************************/ +void evel_mobile_flow_lac_set(EVENT_MOBILE_FLOW * mobile_flow, + const char * const lac); + +/**************************************************************************//** + * Set the MCC property of the Mobile Flow. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param mobile_flow Pointer to the Mobile Flow. + * @param mcc The MCC to be set. ASCIIZ string. The caller does not + * need to preserve the value once the function returns. + *****************************************************************************/ +void evel_mobile_flow_mcc_set(EVENT_MOBILE_FLOW * mobile_flow, + const char * const mcc); + +/**************************************************************************//** + * Set the MNC property of the Mobile Flow. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param mobile_flow Pointer to the Mobile Flow. + * @param mnc The MNC to be set. ASCIIZ string. The caller does not + * need to preserve the value once the function returns. + *****************************************************************************/ +void evel_mobile_flow_mnc_set(EVENT_MOBILE_FLOW * mobile_flow, + const char * const mnc); + +/**************************************************************************//** + * Set the MSISDN property of the Mobile Flow. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param mobile_flow Pointer to the Mobile Flow. + * @param msisdn The MSISDN to be set. ASCIIZ string. The caller does not + * need to preserve the value once the function returns. + *****************************************************************************/ +void evel_mobile_flow_msisdn_set(EVENT_MOBILE_FLOW * mobile_flow, + const char * const msisdn); + +/**************************************************************************//** + * Set the Other Functional Role property of the Mobile Flow. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param mobile_flow Pointer to the Mobile Flow. + * @param role The Other Functional Role to be set. ASCIIZ string. The + * caller does not need to preserve the value once the + * function returns. + *****************************************************************************/ +void evel_mobile_flow_other_func_role_set(EVENT_MOBILE_FLOW * mobile_flow, + const char * const role); + +/**************************************************************************//** + * Set the RAC property of the Mobile Flow. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param mobile_flow Pointer to the Mobile Flow. + * @param rac The RAC to be set. ASCIIZ string. The caller does not + * need to preserve the value once the function returns. + *****************************************************************************/ +void evel_mobile_flow_rac_set(EVENT_MOBILE_FLOW * mobile_flow, + const char * const rac); + +/**************************************************************************//** + * Set the Radio Access Technology property of the Mobile Flow. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param mobile_flow Pointer to the Mobile Flow. + * @param tech The Radio Access Technology to be set. ASCIIZ string. The + * caller does not need to preserve the value once the + * function returns. + *****************************************************************************/ +void evel_mobile_flow_radio_acc_tech_set(EVENT_MOBILE_FLOW * mobile_flow, + const char * const tech); + +/**************************************************************************//** + * Set the SAC property of the Mobile Flow. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param mobile_flow Pointer to the Mobile Flow. + * @param sac The SAC to be set. ASCIIZ string. The caller does not + * need to preserve the value once the function returns. + *****************************************************************************/ +void evel_mobile_flow_sac_set(EVENT_MOBILE_FLOW * mobile_flow, + const char * const sac); + +/**************************************************************************//** + * Set the Sampling Algorithm property of the Mobile Flow. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param mobile_flow Pointer to the Mobile Flow. + * @param algorithm The Sampling Algorithm to be set. + *****************************************************************************/ +void evel_mobile_flow_samp_alg_set(EVENT_MOBILE_FLOW * mobile_flow, + int algorithm); + +/**************************************************************************//** + * Set the TAC property of the Mobile Flow. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param mobile_flow Pointer to the Mobile Flow. + * @param tac The TAC to be set. ASCIIZ string. The caller does not + * need to preserve the value once the function returns. + *****************************************************************************/ +void evel_mobile_flow_tac_set(EVENT_MOBILE_FLOW * mobile_flow, + const char * const tac); + +/**************************************************************************//** + * Set the Tunnel ID property of the Mobile Flow. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param mobile_flow Pointer to the Mobile Flow. + * @param tunnel_id The Tunnel ID to be set. ASCIIZ string. The caller does + * not need to preserve the value once the function returns. + *****************************************************************************/ +void evel_mobile_flow_tunnel_id_set(EVENT_MOBILE_FLOW * mobile_flow, + const char * const tunnel_id); + +/**************************************************************************//** + * Set the VLAN ID property of the Mobile Flow. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param mobile_flow Pointer to the Mobile Flow. + * @param vlan_id The VLAN ID to be set. ASCIIZ string. The caller does + * not need to preserve the value once the function returns. + *****************************************************************************/ +void evel_mobile_flow_vlan_id_set(EVENT_MOBILE_FLOW * mobile_flow, + const char * const vlan_id); + +/**************************************************************************//** + * Create a new Mobile GTP Per Flow Metrics. + * + * @note The mandatory fields on the Mobile GTP Per Flow Metrics must be + * supplied to this factory function and are immutable once set. + * Optional fields have explicit setter functions, but again values + * may only be set once so that the Mobile GTP Per Flow Metrics has + * immutable properties. + * + * @param avg_bit_error_rate + * @param avg_packet_delay_variation + * @param avg_packet_latency + * @param avg_receive_throughput + * @param avg_transmit_throughput + * @param flow_activation_epoch + * @param flow_activation_microsec + * @param flow_deactivation_epoch + * @param flow_deactivation_microsec + * @param flow_deactivation_time + * @param flow_status + * @param max_packet_delay_variation + * @param num_activation_failures + * @param num_bit_errors + * @param num_bytes_received + * @param num_bytes_transmitted + * @param num_dropped_packets + * @param num_l7_bytes_received + * @param num_l7_bytes_transmitted + * @param num_lost_packets + * @param num_out_of_order_packets + * @param num_packet_errors + * @param num_packets_received_excl_retrans + * @param num_packets_received_incl_retrans + * @param num_packets_transmitted_incl_retrans + * @param num_retries + * @param num_timeouts + * @param num_tunneled_l7_bytes_received + * @param round_trip_time + * @param time_to_first_byte + * + * @returns pointer to the newly manufactured ::MOBILE_GTP_PER_FLOW_METRICS. + * If the structure is not used it must be released using + * ::evel_free_mobile_gtp_flow_metrics. + * @retval NULL Failed to create the event. + *****************************************************************************/ +MOBILE_GTP_PER_FLOW_METRICS * evel_new_mobile_gtp_flow_metrics( + double avg_bit_error_rate, + double avg_packet_delay_variation, + int avg_packet_latency, + int avg_receive_throughput, + int avg_transmit_throughput, + int flow_activation_epoch, + int flow_activation_microsec, + int flow_deactivation_epoch, + int flow_deactivation_microsec, + time_t flow_deactivation_time, + const char * const flow_status, + int max_packet_delay_variation, + int num_activation_failures, + int num_bit_errors, + int num_bytes_received, + int num_bytes_transmitted, + int num_dropped_packets, + int num_l7_bytes_received, + int num_l7_bytes_transmitted, + int num_lost_packets, + int num_out_of_order_packets, + int num_packet_errors, + int num_packets_received_excl_retrans, + int num_packets_received_incl_retrans, + int num_packets_transmitted_incl_retrans, + int num_retries, + int num_timeouts, + int num_tunneled_l7_bytes_received, + int round_trip_time, + int time_to_first_byte); + +/**************************************************************************//** + * Free a Mobile GTP Per Flow Metrics. + * + * Free off the Mobile GTP Per Flow Metrics supplied. Will free all the + * contained allocated memory. + * + * @note It does not free the Mobile GTP Per Flow Metrics itself, since that + * may be part of a larger structure. + *****************************************************************************/ +void evel_free_mobile_gtp_flow_metrics(MOBILE_GTP_PER_FLOW_METRICS * metrics); + +/**************************************************************************//** + * Set the Duration of Connection Failed Status property of the Mobile GTP Per + * Flow Metrics. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param metrics Pointer to the Mobile GTP Per Flow Metrics. + * @param duration The Duration of Connection Failed Status to be set. + *****************************************************************************/ +void evel_mobile_gtp_metrics_dur_con_fail_set( + MOBILE_GTP_PER_FLOW_METRICS * metrics, + int duration); + +/**************************************************************************//** + * Set the Duration of Tunnel Failed Status property of the Mobile GTP Per Flow + * Metrics. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param metrics Pointer to the Mobile GTP Per Flow Metrics. + * @param duration The Duration of Tunnel Failed Status to be set. + *****************************************************************************/ +void evel_mobile_gtp_metrics_dur_tun_fail_set( + MOBILE_GTP_PER_FLOW_METRICS * metrics, + int duration); + +/**************************************************************************//** + * Set the Activated By property of the Mobile GTP Per Flow metrics. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param metrics Pointer to the Mobile GTP Per Flow Metrics. + * @param act_by The Activated By to be set. ASCIIZ string. The caller + * does not need to preserve the value once the function + * returns. + *****************************************************************************/ +void evel_mobile_gtp_metrics_act_by_set(MOBILE_GTP_PER_FLOW_METRICS * metrics, + const char * const act_by); + +/**************************************************************************//** + * Set the Activation Time property of the Mobile GTP Per Flow metrics. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param metrics Pointer to the Mobile GTP Per Flow Metrics. + * @param act_time The Activation Time to be set. ASCIIZ string. The caller + * does not need to preserve the value once the function + * returns. + *****************************************************************************/ +void evel_mobile_gtp_metrics_act_time_set( + MOBILE_GTP_PER_FLOW_METRICS * metrics, + time_t act_time); + +/**************************************************************************//** + * Set the Deactivated By property of the Mobile GTP Per Flow metrics. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param metrics Pointer to the Mobile GTP Per Flow Metrics. + * @param deact_by The Deactivated By to be set. ASCIIZ string. The caller + * does not need to preserve the value once the function + * returns. + *****************************************************************************/ +void evel_mobile_gtp_metrics_deact_by_set( + MOBILE_GTP_PER_FLOW_METRICS * metrics, + const char * const deact_by); + +/**************************************************************************//** + * Set the GTP Connection Status property of the Mobile GTP Per Flow metrics. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param metrics Pointer to the Mobile GTP Per Flow Metrics. + * @param status The GTP Connection Status to be set. ASCIIZ string. The + * caller does not need to preserve the value once the + * function returns. + *****************************************************************************/ +void evel_mobile_gtp_metrics_con_status_set( + MOBILE_GTP_PER_FLOW_METRICS * metrics, + const char * const status); + +/**************************************************************************//** + * Set the GTP Tunnel Status property of the Mobile GTP Per Flow metrics. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param metrics Pointer to the Mobile GTP Per Flow Metrics. + * @param status The GTP Tunnel Status to be set. ASCIIZ string. The + * caller does not need to preserve the value once the + * function returns. + *****************************************************************************/ +void evel_mobile_gtp_metrics_tun_status_set( + MOBILE_GTP_PER_FLOW_METRICS * metrics, + const char * const status); + +/**************************************************************************//** + * Set an IP Type-of-Service count property of the Mobile GTP Per Flow metrics. + * + * @param metrics Pointer to the Mobile GTP Per Flow Metrics. + * @param index The index of the IP Type-of-Service. + * @param count The count. + *****************************************************************************/ +void evel_mobile_gtp_metrics_iptos_set(MOBILE_GTP_PER_FLOW_METRICS * metrics, + int index, + int count); + +/**************************************************************************//** + * Set the Large Packet Round-Trip Time property of the Mobile GTP Per Flow + * Metrics. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param metrics Pointer to the Mobile GTP Per Flow Metrics. + * @param rtt The Large Packet Round-Trip Time to be set. + *****************************************************************************/ +void evel_mobile_gtp_metrics_large_pkt_rtt_set( + MOBILE_GTP_PER_FLOW_METRICS * metrics, + int rtt); + +/**************************************************************************//** + * Set the Large Packet Threshold property of the Mobile GTP Per Flow Metrics. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param metrics Pointer to the Mobile GTP Per Flow Metrics. + * @param threshold The Large Packet Threshold to be set. + *****************************************************************************/ +void evel_mobile_gtp_metrics_large_pkt_thresh_set( + MOBILE_GTP_PER_FLOW_METRICS * metrics, + double threshold); + +/**************************************************************************//** + * Set the Max Receive Bit Rate property of the Mobile GTP Per Flow Metrics. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param metrics Pointer to the Mobile GTP Per Flow Metrics. + * @param rate The Max Receive Bit Rate to be set. + *****************************************************************************/ +void evel_mobile_gtp_metrics_max_rcv_bit_rate_set( + MOBILE_GTP_PER_FLOW_METRICS * metrics, + int rate); + +/**************************************************************************//** + * Set the Max Transmit Bit Rate property of the Mobile GTP Per Flow Metrics. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param metrics Pointer to the Mobile GTP Per Flow Metrics. + * @param rate The Max Transmit Bit Rate to be set. + *****************************************************************************/ +void evel_mobile_gtp_metrics_max_trx_bit_rate_set( + MOBILE_GTP_PER_FLOW_METRICS * metrics, + int rate); + +/**************************************************************************//** + * Set the Number of GTP Echo Failures property of the Mobile GTP Per Flow + * Metrics. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param metrics Pointer to the Mobile GTP Per Flow Metrics. + * @param num The Number of GTP Echo Failures to be set. + *****************************************************************************/ +void evel_mobile_gtp_metrics_num_echo_fail_set( + MOBILE_GTP_PER_FLOW_METRICS * metrics, + int num); + +/**************************************************************************//** + * Set the Number of GTP Tunnel Errors property of the Mobile GTP Per Flow + * Metrics. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param metrics Pointer to the Mobile GTP Per Flow Metrics. + * @param num The Number of GTP Tunnel Errors to be set. + *****************************************************************************/ +void evel_mobile_gtp_metrics_num_tun_fail_set( + MOBILE_GTP_PER_FLOW_METRICS * metrics, + int num); + +/**************************************************************************//** + * Set the Number of HTTP Errors property of the Mobile GTP Per Flow Metrics. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param metrics Pointer to the Mobile GTP Per Flow Metrics. + * @param num The Number of HTTP Errors to be set. + *****************************************************************************/ +void evel_mobile_gtp_metrics_num_http_errors_set( + MOBILE_GTP_PER_FLOW_METRICS * metrics, + int num); + +/**************************************************************************//** + * Add a TCP flag count to the metrics. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param metrics Pointer to the Mobile GTP Per Flow Metrics. + * @param tcp_flag The TCP flag count to be updated. + * @param count The associated flag count. + *****************************************************************************/ +void evel_mobile_gtp_metrics_tcp_flag_count_add( + MOBILE_GTP_PER_FLOW_METRICS * metrics, + const EVEL_TCP_FLAGS tcp_flag, + const int count); + +/**************************************************************************//** + * Add a QCI COS count to the metrics. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param metrics Pointer to the Mobile GTP Per Flow Metrics. + * @param qci_cos The QCI COS count to be updated. + * @param count The associated QCI COS count. + *****************************************************************************/ +void evel_mobile_gtp_metrics_qci_cos_count_add( + MOBILE_GTP_PER_FLOW_METRICS * metrics, + const EVEL_QCI_COS_TYPES qci_cos, + const int count); + +/*****************************************************************************/ +/*****************************************************************************/ +/* */ +/* SIGNALING */ +/* */ +/*****************************************************************************/ +/*****************************************************************************/ + +/**************************************************************************//** + * Create a new Signaling event. + * + * @note The mandatory fields on the Signaling must be supplied to + * this factory function and are immutable once set. Optional fields + * have explicit setter functions, but again values may only be set + * once so that the event has immutable properties. + * @param event_name Unique Event Name + * @param event_id A universal identifier of the event for analysis etc + * @param vendor_name The vendor id to encode in the event vnf field. + * @param module The module to encode in the event. + * @param vnfname The Virtual network function to encode in the event. + * @returns pointer to the newly manufactured ::EVENT_SIGNALING. If the event + * is not used (i.e. posted) it must be released using + * ::evel_free_signaling. + * @retval NULL Failed to create the event. + *****************************************************************************/ +EVENT_SIGNALING * evel_new_signaling(const char* ev_name, const char *ev_id, + const char * const vendor_name, + const char * const correlator, + const char * const local_ip_address, + const char * const local_port, + const char * const remote_ip_address, + const char * const remote_port); + +/**************************************************************************//** + * Free a Signaling event. + * + * Free off the event supplied. Will free all the contained allocated memory. + * + * @note It does not free the event itself, since that may be part of a larger + * structure. + *****************************************************************************/ +void evel_free_signaling(EVENT_SIGNALING * const event); + +/**************************************************************************//** + * Set the Event Type property of the Signaling event. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param event Pointer to the Signaling event. + * @param type The Event Type to be set. ASCIIZ string. The caller + * does not need to preserve the value once the function + * returns. + *****************************************************************************/ +void evel_signaling_type_set(EVENT_SIGNALING * const event, + const char * const type); + +/**************************************************************************//** + * Add an additional value name/value pair to the SIP signaling. + * + * The name and value are null delimited ASCII strings. The library takes + * a copy so the caller does not have to preserve values after the function + * returns. + * + * @param event Pointer to the fault. + * @param name ASCIIZ string with the attribute's name. The caller + * does not need to preserve the value once the function + * returns. + * @param value ASCIIZ string with the attribute's value. The caller + * does not need to preserve the value once the function + * returns. + *****************************************************************************/ +void evel_signaling_addl_info_add(EVENT_SIGNALING * event, char * name, char * value); + +/**************************************************************************//** + * Set the Correlator property of the Signaling event. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param event Pointer to the Signaling event. + * @param correlator The correlator to be set. ASCIIZ string. The caller + * does not need to preserve the value once the function + * returns. + *****************************************************************************/ +void evel_signaling_correlator_set(EVENT_SIGNALING * const event, + const char * const correlator); + +/**************************************************************************//** + * Set the Local Ip Address property of the Signaling event. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param event Pointer to the Signaling event. + * @param local_ip_address + * The Local Ip Address to be set. ASCIIZ string. The + * caller does not need to preserve the value once the + * function returns. + *****************************************************************************/ +void evel_signaling_local_ip_address_set(EVENT_SIGNALING * const event, + const char * const local_ip_address); + +/**************************************************************************//** + * Set the Local Port property of the Signaling event. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param event Pointer to the Signaling event. + * @param local_port The Local Port to be set. ASCIIZ string. The caller + * does not need to preserve the value once the function + * returns. + *****************************************************************************/ +void evel_signaling_local_port_set(EVENT_SIGNALING * const event, + const char * const local_port); + +/**************************************************************************//** + * Set the Remote Ip Address property of the Signaling event. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param event Pointer to the Signaling event. + * @param remote_ip_address + * The Remote Ip Address to be set. ASCIIZ string. The + * caller does not need to preserve the value once the + * function returns. + *****************************************************************************/ +void evel_signaling_remote_ip_address_set(EVENT_SIGNALING * const event, + const char * const remote_ip_address); + +/**************************************************************************//** + * Set the Remote Port property of the Signaling event. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param event Pointer to the Signaling event. + * @param remote_port The Remote Port to be set. ASCIIZ string. The caller + * does not need to preserve the value once the function + * returns. + *****************************************************************************/ +void evel_signaling_remote_port_set(EVENT_SIGNALING * const event, + const char * const remote_port); +/**************************************************************************//** + * Set the Vendor module property of the Signaling event. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param event Pointer to the Signaling event. + * @param modulename The module name to be set. ASCIIZ string. The caller + * does not need to preserve the value once the function + * returns. + *****************************************************************************/ +void evel_signaling_vnfmodule_name_set(EVENT_SIGNALING * const event, + const char * const module_name); +/**************************************************************************//** + * Set the Vendor module property of the Signaling event. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param event Pointer to the Signaling event. + * @param vnfname The Virtual Network function to be set. ASCIIZ string. + * The caller does not need to preserve the value once + * the function returns. + *****************************************************************************/ +void evel_signaling_vnfname_set(EVENT_SIGNALING * const event, + const char * const vnfname); + +/**************************************************************************//** + * Set the Compressed SIP property of the Signaling event. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param event Pointer to the Signaling event. + * @param compressed_sip + * The Compressed SIP to be set. ASCIIZ string. The caller + * does not need to preserve the value once the function + * returns. + *****************************************************************************/ +void evel_signaling_compressed_sip_set(EVENT_SIGNALING * const event, + const char * const compressed_sip); + +/**************************************************************************//** + * Set the Summary SIP property of the Signaling event. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param event Pointer to the Signaling event. + * @param summary_sip The Summary SIP to be set. ASCIIZ string. The caller + * does not need to preserve the value once the function + * returns. + *****************************************************************************/ +void evel_signaling_summary_sip_set(EVENT_SIGNALING * const event, + const char * const summary_sip); + + +/*****************************************************************************/ +/*****************************************************************************/ +/* */ +/* STATE CHANGE */ +/* */ +/*****************************************************************************/ +/*****************************************************************************/ + +/**************************************************************************//** + * Create a new State Change event. + * + * @note The mandatory fields on the Syslog must be supplied to this factory + * function and are immutable once set. Optional fields have explicit + * setter functions, but again values may only be set once so that the + * Syslog has immutable properties. + * + * @param event_name Unique Event Name + * @param event_id A universal identifier of the event for analysis etc + * @param new_state The new state of the reporting entity. + * @param old_state The old state of the reporting entity. + * @param interface The card or port name of the reporting entity. + * + * @returns pointer to the newly manufactured ::EVENT_STATE_CHANGE. If the + * event is not used it must be released using + * ::evel_free_state_change + * @retval NULL Failed to create the event. + *****************************************************************************/ +EVENT_STATE_CHANGE * evel_new_state_change(const char* ev_name, const char *ev_id, + const EVEL_ENTITY_STATE new_state, + const EVEL_ENTITY_STATE old_state, + const char * const interface); + +/**************************************************************************//** + * Free a State Change. + * + * Free off the State Change supplied. Will free all the contained allocated + * memory. + * + * @note It does not free the State Change itself, since that may be part of a + * larger structure. + *****************************************************************************/ +void evel_free_state_change(EVENT_STATE_CHANGE * const state_change); + +/**************************************************************************//** + * Set the Event Type property of the State Change. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param state_change Pointer to the ::EVENT_STATE_CHANGE. + * @param type The Event Type to be set. ASCIIZ string. The caller + * does not need to preserve the value once the function + * returns. + *****************************************************************************/ +void evel_state_change_type_set(EVENT_STATE_CHANGE * const state_change, + const char * const type); + +/**************************************************************************//** + * Add an additional field name/value pair to the State Change. + * + * The name and value are null delimited ASCII strings. The library takes + * a copy so the caller does not have to preserve values after the function + * returns. + * + * @param state_change Pointer to the ::EVENT_STATE_CHANGE. + * @param name ASCIIZ string with the attribute's name. The caller + * does not need to preserve the value once the function + * returns. + * @param value ASCIIZ string with the attribute's value. The caller + * does not need to preserve the value once the function + * returns. + *****************************************************************************/ +void evel_state_change_addl_field_add(EVENT_STATE_CHANGE * const state_change, + const char * const name, + const char * const value); + +/*****************************************************************************/ +/*****************************************************************************/ +/* */ +/* SYSLOG */ +/* */ +/*****************************************************************************/ +/*****************************************************************************/ + +/**************************************************************************//** + * Create a new syslog event. + * + * @note The mandatory fields on the Syslog must be supplied to this factory + * function and are immutable once set. Optional fields have explicit + * setter functions, but again values may only be set once so that the + * Syslog has immutable properties. + * + * @param event_name Unique Event Name + * @param event_id A universal identifier of the event for analysis etc + * @param event_source_type + * @param syslog_msg + * @param syslog_tag + * @param version + * + * @returns pointer to the newly manufactured ::EVENT_SYSLOG. If the event is + * not used it must be released using ::evel_free_syslog + * @retval NULL Failed to create the event. + *****************************************************************************/ +EVENT_SYSLOG * evel_new_syslog(const char* ev_name, const char *ev_id, + EVEL_SOURCE_TYPES event_source_type, + const char * const syslog_msg, + const char * const syslog_tag); + +/**************************************************************************//** + * Set the Event Type property of the Syslog. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param syslog Pointer to the syslog. + * @param type The Event Type to be set. ASCIIZ string. The caller + * does not need to preserve the value once the function + * returns. + *****************************************************************************/ +void evel_syslog_type_set(EVENT_SYSLOG * syslog, + const char * const type); + +/**************************************************************************//** + * Free a Syslog. + * + * Free off the Syslog supplied. Will free all the contained allocated memory. + * + * @note It does not free the Syslog itself, since that may be part of a + * larger structure. + *****************************************************************************/ +void evel_free_syslog(EVENT_SYSLOG * event); + +/**************************************************************************//** + * Add an additional field name/value pair to the Syslog. + * + * The name and value are null delimited ASCII strings. The library takes + * a copy so the caller does not have to preserve values after the function + * returns. + * + * @param syslog Pointer to the syslog. + * @param name ASCIIZ string with the attribute's name. The caller + * does not need to preserve the value once the function + * returns. + * @param value ASCIIZ string with the attribute's value. The caller + * does not need to preserve the value once the function + * returns. + *****************************************************************************/ +void evel_syslog_addl_field_add(EVENT_SYSLOG * syslog, + char * name, + char * value); + +/**************************************************************************//** + * Set the Event Source Host property of the Syslog. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param syslog Pointer to the Syslog. + * @param host The Event Source Host to be set. ASCIIZ string. The + * caller does not need to preserve the value once the + * function returns. + *****************************************************************************/ +void evel_syslog_event_source_host_set(EVENT_SYSLOG * syslog, + const char * const host); + +/**************************************************************************//** + * Set the Syslog Facility property of the Syslog. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param syslog Pointer to the Syslog. + * @param facility The Syslog Facility to be set. ASCIIZ string. The caller + * does not need to preserve the value once the function + * returns. + *****************************************************************************/ +void evel_syslog_facility_set(EVENT_SYSLOG * syslog, + EVEL_SYSLOG_FACILITIES facility); + +/**************************************************************************//** + * Set the Process property of the Syslog. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param syslog Pointer to the Syslog. + * @param proc The Process to be set. ASCIIZ string. The caller does + * not need to preserve the value once the function returns. + *****************************************************************************/ +void evel_syslog_proc_set(EVENT_SYSLOG * syslog, const char * const proc); + +/**************************************************************************//** + * Set the Process ID property of the Syslog. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param syslog Pointer to the Syslog. + * @param proc_id The Process ID to be set. + *****************************************************************************/ +void evel_syslog_proc_id_set(EVENT_SYSLOG * syslog, int proc_id); + +/**************************************************************************//** + * Set the Version property of the Syslog. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param syslog Pointer to the Syslog. + * @param version The Version to be set. + *****************************************************************************/ +void evel_syslog_version_set(EVENT_SYSLOG * syslog, int version); + +/**************************************************************************//** + * Set the Structured Data property of the Syslog. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param syslog Pointer to the Syslog. + * @param s_data The Structured Data to be set. ASCIIZ string. The caller + * does not need to preserve the value once the function + * returns. + *****************************************************************************/ +void evel_syslog_s_data_set(EVENT_SYSLOG * syslog, const char * const s_data); + +/**************************************************************************//** + * Set the Structured SDID property of the Syslog. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param syslog Pointer to the Syslog. + * @param sdid The Structured Data to be set. ASCIIZ string. name@number + * Caller does not need to preserve the value once the function + * returns. + *****************************************************************************/ +void evel_syslog_sdid_set(EVENT_SYSLOG * syslog, const char * const sdid); + +/**************************************************************************//** + * Set the Structured Severity property of the Syslog. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param syslog Pointer to the Syslog. + * @param sdid The Structured Data to be set. ASCIIZ string. + * Caller does not need to preserve the value once the function + * returns. + *****************************************************************************/ +void evel_syslog_severity_set(EVENT_SYSLOG * syslog, const char * const severty); + + +/*****************************************************************************/ +/*****************************************************************************/ +/* */ +/* OTHER */ +/* */ +/*****************************************************************************/ +/*****************************************************************************/ + +/**************************************************************************//** + * Create a new other event. + * + * @param event_name Unique Event Name + * @param event_id A universal identifier of the event for analysis etc + * + * @returns pointer to the newly manufactured ::EVENT_OTHER. If the event is + * not used it must be released using ::evel_free_other. + * @retval NULL Failed to create the event. + *****************************************************************************/ +EVENT_OTHER * evel_new_other(const char* ev_name, const char *ev_id); + +/**************************************************************************//** + * Free an Other. + * + * Free off the Other supplied. Will free all the contained allocated memory. + * + * @note It does not free the Other itself, since that may be part of a + * larger structure. + *****************************************************************************/ +void evel_free_other(EVENT_OTHER * event); + +/**************************************************************************//** + * Set the Event Type property of the Other. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param other Pointer to the Other. + * @param type The Event Type to be set. ASCIIZ string. The caller + * does not need to preserve the value once the function + * returns. + *****************************************************************************/ +void evel_other_type_set(EVENT_OTHER * other, + const char * const type); + +/**************************************************************************//** + * Add a value name/value pair to the Other. + * + * The name and value are null delimited ASCII strings. The library takes + * a copy so the caller does not have to preserve values after the function + * returns. + * + * @param other Pointer to the Other. + * @param name ASCIIZ string with the attribute's name. + * @param value ASCIIZ string with the attribute's value. + *****************************************************************************/ +void evel_other_field_add(EVENT_OTHER * other, + char * name, + char * value); + +/*****************************************************************************/ +/*****************************************************************************/ +/* */ +/* THROTTLING */ +/* */ +/*****************************************************************************/ +/*****************************************************************************/ + +/**************************************************************************//** + * Return the current measurement interval provided by the Event Listener. + * + * @returns The current measurement interval + * @retval EVEL_MEASUREMENT_INTERVAL_UKNOWN (0) - interval has not been + * specified + *****************************************************************************/ +int evel_get_measurement_interval(); + +/*****************************************************************************/ +/* Supported Report version. */ +/*****************************************************************************/ +#define EVEL_VOICEQ_MAJOR_VERSION 1 +#define EVEL_VOICEQ_MINOR_VERSION 1 + +/**************************************************************************//** + * End of Call Voice Quality Metrices + * JSON equivalent field: endOfCallVqmSummaries + *****************************************************************************/ +typedef struct end_of_call_vqm_summaries { + /***************************************************************************/ + /* Mandatory fields */ + /***************************************************************************/ + char* adjacencyName; + char* endpointDescription; + + /***************************************************************************/ + /* Optional fields */ + /***************************************************************************/ + EVEL_OPTION_INT endpointJitter; + EVEL_OPTION_INT endpointRtpOctetsDiscarded; + EVEL_OPTION_INT endpointRtpOctetsReceived; + EVEL_OPTION_INT endpointRtpOctetsSent; + EVEL_OPTION_INT endpointRtpPacketsDiscarded; + EVEL_OPTION_INT endpointRtpPacketsReceived; + EVEL_OPTION_INT endpointRtpPacketsSent; + EVEL_OPTION_INT localJitter; + EVEL_OPTION_INT localRtpOctetsDiscarded; + EVEL_OPTION_INT localRtpOctetsReceived; + EVEL_OPTION_INT localRtpOctetsSent; + EVEL_OPTION_INT localRtpPacketsDiscarded; + EVEL_OPTION_INT localRtpPacketsReceived; + EVEL_OPTION_INT localRtpPacketsSent; + EVEL_OPTION_INT mosCqe; + EVEL_OPTION_INT packetsLost; + EVEL_OPTION_INT packetLossPercent; + EVEL_OPTION_INT rFactor; + EVEL_OPTION_INT roundTripDelay; + +} END_OF_CALL_VOICE_QUALITY_METRICS; + +/**************************************************************************//** +* Voice QUality. +* JSON equivalent field: voiceQualityFields +*****************************************************************************/ + +typedef struct event_voiceQuality { + /***************************************************************************/ + /* Header and version */ + /***************************************************************************/ + EVENT_HEADER header; + int major_version; + int minor_version; + + /***************************************************************************/ + /* Mandatory fields */ + /***************************************************************************/ + + char *calleeSideCodec; + char *callerSideCodec; + char *correlator; + char *midCallRtcp; + VENDOR_VNFNAME_FIELD vendorVnfNameFields; + END_OF_CALL_VOICE_QUALITY_METRICS *endOfCallVqmSummaries; + + /***************************************************************************/ + /* Optional fields */ + /***************************************************************************/ + EVEL_OPTION_STRING phoneNumber; + DLIST additionalInformation; + +} EVENT_VOICE_QUALITY; +/**************************************************************************//** + * Voice Quality Additional Info. + * JSON equivalent field: additionalInformation + *****************************************************************************/ +typedef struct voice_quality_additional_info { + char * name; + char * value; +} VOICE_QUALITY_ADDL_INFO; + +/**************************************************************************//** + * Create a new voice quality event. + * + * @note The mandatory fields on the Voice Quality must be supplied to this + * factory function and are immutable once set. Optional fields have + * explicit setter functions, but again values may only be set once + * so that the Voice Quality has immutable properties. + * @param event_name Unique Event Name + * @param event_id A universal identifier of the event for analysis etc + * @param calleeSideCodec Callee codec for the call. + * @param callerSideCodec Caller codec for the call. + * @param correlator Constant across all events on this call. + * @param midCallRtcp Base64 encoding of the binary RTCP data + * (excluding Eth/IP/UDP headers). + * @param vendorVnfNameFields Vendor, VNF and VfModule names. + * @returns pointer to the newly manufactured ::EVENT_VOICE_QUALITY. If the + * event is not used (i.e. posted) it must be released using + ::evel_free_voice_quality. + * @retval NULL Failed to create the event. + *****************************************************************************/ +EVENT_VOICE_QUALITY * evel_new_voice_quality(const char* ev_name, const char *ev_id, + const char * const calleeSideCodec, + const char * const callerSideCodec, const char * const correlator, + const char * const midCallRtcp, const char * const vendorVnfNameFields); + +/**************************************************************************//** + * Set the Callee side codec for Call for domain Voice Quality + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param voiceQuality Pointer to the Voice Quality Event. + * @param calleeCodecForCall The Callee Side Codec to be set. ASCIIZ + * string. The caller does not need to + * preserve the value once the function + * returns. + *****************************************************************************/ +void evel_voice_quality_callee_codec_set(EVENT_VOICE_QUALITY * voiceQuality, + const char * const calleeCodecForCall); + +/**************************************************************************//** + * Set the Caller side codec for Call for domain Voice Quality + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param voiceQuality Pointer to the Voice Quality Event. + * @param callerCodecForCall The Caller Side Codec to be set. ASCIIZ + * string. The caller does not need to + * preserve the value once the function + * returns. + *****************************************************************************/ +void evel_voice_quality_caller_codec_set(EVENT_VOICE_QUALITY * voiceQuality, + const char * const callerCodecForCall); + +/**************************************************************************//** + * Set the correlator for domain Voice Quality + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param voiceQuality Pointer to the Voice Quality Event. + * @param correlator The correlator value to be set. ASCIIZ + * string. The caller does not need to + * preserve the value once the function + * returns. + *****************************************************************************/ +void evel_voice_quality_correlator_set(EVENT_VOICE_QUALITY * voiceQuality, + const char * const vCorrelator); + +/**************************************************************************//** + * Set the RTCP Call Data for domain Voice Quality + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param voiceQuality Pointer to the Voice Quality Event. + * @param rtcpCallData The RTCP Call Data to be set. ASCIIZ + * string. The caller does not need to + * preserve the value once the function + * returns. + *****************************************************************************/ +void evel_voice_quality_rtcp_data_set(EVENT_VOICE_QUALITY * voiceQuality, + const char * const rtcpCallData); + +/**************************************************************************//** + * Set the Vendor VNF Name fields for domain Voice Quality + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param voiceQuality Pointer to the Voice Quality Event. + * @param nameFields The Vendor, VNF and VfModule names to be set. + * ASCIIZ string. The caller does not need to + * preserve the value once the function + * returns. + *****************************************************************************/ +void evel_voice_quality_name_fields_set(EVENT_VOICE_QUALITY * voiceQuality, + const char * const nameFields); + +/**************************************************************************//** + * Add an End of Call Voice Quality Metrices + + * The adjacencyName and endpointDescription is null delimited ASCII string. + * The library takes a copy so the caller does not have to preserve values + * after the function returns. + * + * @param voiceQuality Pointer to the measurement. + * @param adjacencyName Adjacency name + * @param endpointDescription Enumeration: ‘Caller’, ‘Callee’. + * @param endpointJitter Endpoint jitter + * @param endpointRtpOctetsDiscarded Endpoint RTP octets discarded. + * @param endpointRtpOctetsReceived Endpoint RTP octets received. + * @param endpointRtpOctetsSent Endpoint RTP octets sent + * @param endpointRtpPacketsDiscarded Endpoint RTP packets discarded. + * @param endpointRtpPacketsReceived Endpoint RTP packets received. + * @param endpointRtpPacketsSent Endpoint RTP packets sent. + * @param localJitter Local jitter. + * @param localRtpOctetsDiscarded Local RTP octets discarded. + * @param localRtpOctetsReceived Local RTP octets received. + * @param localRtpOctetsSent Local RTP octets sent. + * @param localRtpPacketsDiscarded Local RTP packets discarded. + * @param localRtpPacketsReceived Local RTP packets received. + * @param localRtpPacketsSent Local RTP packets sent. + * @param mosCqe Decimal range from 1 to 5 + * (1 decimal place) + * @param packetsLost No Packets lost + * @param packetLossPercent Calculated percentage packet loss + * @param rFactor rFactor from 0 to 100 + * @param roundTripDelay Round trip delay in milliseconds + *****************************************************************************/ +void evel_voice_quality_end_metrics_add(EVENT_VOICE_QUALITY * voiceQuality, + const char * adjacencyName, EVEL_SERVICE_ENDPOINT_DESC endpointDescription, + int endpointJitter, + int endpointRtpOctetsDiscarded, + int endpointRtpOctetsReceived, + int endpointRtpOctetsSent, + int endpointRtpPacketsDiscarded, + int endpointRtpPacketsReceived, + int endpointRtpPacketsSent, + int localJitter, + int localRtpOctetsDiscarded, + int localRtpOctetsReceived, + int localRtpOctetsSent, + int localRtpPacketsDiscarded, + int localRtpPacketsReceived, + int localRtpPacketsSent, + int mosCqe, + int packetsLost, + int packetLossPercent, + int rFactor, + int roundTripDelay); + +/**************************************************************************//** + * Free a Voice Quality. + * + * Free off the Voce Quality supplied. Will free all the contained allocated + * memory. + * + * @note It does not free the Voice Quality itself, since that may be part of a + * larger structure. + *****************************************************************************/ +void evel_free_voice_quality(EVENT_VOICE_QUALITY * voiceQuality); + +/**************************************************************************//** + * Add an additional value name/value pair to the Voice Quality. + * + * The name and value are null delimited ASCII strings. The library takes + * a copy so the caller does not have to preserve values after the function + * returns. + * + * @param fault Pointer to the fault. + * @param name ASCIIZ string with the attribute's name. The caller + * does not need to preserve the value once the function + * returns. + * @param value ASCIIZ string with the attribute's value. The caller + * does not need to preserve the value once the function + * returns. + *****************************************************************************/ +void evel_voice_quality_addl_info_add(EVENT_VOICE_QUALITY * voiceQuality, char * name, char * value); + + +/*****************************************************************************/ +/*****************************************************************************/ +/* */ +/* THRESHOLD CROSSING ALERT */ +/* */ +/*****************************************************************************/ +/*****************************************************************************/ + +typedef enum evel_event_action { + EVEL_EVENT_ACTION_CLEAR, + EVEL_EVENT_ACTION_CONTINUE, + EVEL_EVENT_ACTION_SET, + EVEL_MAX_EVENT_ACTION +}EVEL_EVENT_ACTION; + +typedef enum evel_alert_type { + EVEL_CARD_ANOMALY, + EVEL_ELEMENT_ANOMALY, + EVEL_INTERFACE_ANOMALY, + EVEL_SERVICE_ANOMALY, + EVEL_MAX_ANOMALY +}EVEL_ALERT_TYPE; + + +typedef struct perf_counter { + char * criticality; + char * name; + char * thresholdCrossed; + char * value; +}PERF_COUNTER; + + +/*****************************************************************************/ +/* Supported Threshold Crossing version. */ +/*****************************************************************************/ +#define EVEL_THRESHOLD_CROSS_MAJOR_VERSION 1 +#define EVEL_THRESHOLD_CROSS_MINOR_VERSION 1 + +/**************************************************************************//** + * Threshold Crossing. + * JSON equivalent field: Threshold Cross Fields + *****************************************************************************/ +typedef struct event_threshold_cross { + /***************************************************************************/ + /* Header and version */ + /***************************************************************************/ + EVENT_HEADER header; + int major_version; + int minor_version; + + /***************************************************************************/ + /* Mandatory fields */ + /***************************************************************************/ + PERF_COUNTER additionalParameters; + EVEL_EVENT_ACTION alertAction; + char * alertDescription; + EVEL_ALERT_TYPE alertType; + unsigned long long collectionTimestamp; + EVEL_SEVERITIES eventSeverity; + unsigned long long eventStartTimestamp; + + /***************************************************************************/ + /* Optional fields */ + /***************************************************************************/ + DLIST additional_info; + EVEL_OPTION_STRING alertValue; + DLIST alertidList; + EVEL_OPTION_STRING dataCollector; + EVEL_OPTION_STRING elementType; + EVEL_OPTION_STRING interfaceName; + EVEL_OPTION_STRING networkService; + EVEL_OPTION_STRING possibleRootCause; + +} EVENT_THRESHOLD_CROSS; + + +/**************************************************************************//** + * Create a new Threshold Crossing Alert event. + * + * @note The mandatory fields on the TCA must be supplied to this factory + * function and are immutable once set. Optional fields have explicit + * setter functions, but again values may only be set once so that the + * TCA has immutable properties. + * + * @param event_name Unique Event Name + * @param event_id A universal identifier of the event for analysis etc + * @param char* tcriticality Performance Counter Criticality MAJ MIN, + * @param char* tname Performance Counter Threshold name + * @param char* tthresholdCrossed Counter Threshold crossed value + * @param char* tvalue Counter actual value + * @param EVEL_EVENT_ACTION talertAction Alert set continue or clear + * @param char* talertDescription + * @param EVEL_ALERT_TYPE talertType Kind of anamoly + * @param unsigned long long tcollectionTimestamp time at which alert was collected + * @param EVEL_SEVERITIES teventSeverity Severity of Alert + * @param unsigned long long teventStartTimestamp Time when this alert started + * + * @returns pointer to the newly manufactured ::EVENT_THRESHOLD_CROSS. If the + * event is not used it must be released using + * ::evel_free_threshold_cross + * @retval NULL Failed to create the event. + *****************************************************************************/ +EVENT_THRESHOLD_CROSS * evel_new_threshold_cross( + const char* ev_name, const char *ev_id, + char * tcriticality, + char * tname, + char * tthresholdCrossed, + char * tvalue, + EVEL_EVENT_ACTION talertAction, + char * talertDescription, + EVEL_ALERT_TYPE talertType, + unsigned long long tcollectionTimestamp, + EVEL_SEVERITIES teventSeverity, + unsigned long long teventStartTimestamp); + +/**************************************************************************//** + * Free a Threshold cross event. + * + * Free off the Threshold crossing event supplied. Will free all the contained allocated + * memory. + * + * @note It does not free the Threshold Cross itself, since that may be part of a + * larger structure. + *****************************************************************************/ +void evel_free_threshold_cross(EVENT_THRESHOLD_CROSS * const tcp); + +/**************************************************************************//** + * Set the Event Type property of the Threshold Cross. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param tcp Pointer to the ::EVENT_THRESHOLD_CROSS. + * @param type The Event Type to be set. ASCIIZ string. The caller + * does not need to preserve the value once the function + * returns. + *****************************************************************************/ +void evel_threshold_cross_type_set(EVENT_THRESHOLD_CROSS * const tcp, char * type); + +/**************************************************************************//** + * Add an optional additional alertid value to Alert. + * + * @param alertid Adds Alert ID + *****************************************************************************/ +void evel_threshold_cross_alertid_add(EVENT_THRESHOLD_CROSS * const event,char * alertid); + + /**************************************************************************//** + * Set the TCA probable Root cause. + * + * @param sheader Possible root cause to Threshold + *****************************************************************************/ + void evel_threshold_cross_possible_rootcause_set(EVENT_THRESHOLD_CROSS * const event, char * sheader); + /**************************************************************************//** + * Set the TCA networking cause. + * + * @param sheader Possible networking service value to Threshold + *****************************************************************************/ + void evel_threshold_cross_networkservice_set(EVENT_THRESHOLD_CROSS * const event, char * sheader); + /**************************************************************************//** + * Set the TCA Interface name. + * + * @param sheader Interface name to threshold + *****************************************************************************/ + void evel_threshold_cross_interfacename_set(EVENT_THRESHOLD_CROSS * const event,char * sheader); + /**************************************************************************//** + * Set the TCA Data element type. + * + * @param sheader element type of Threshold + *****************************************************************************/ + void evel_threshold_cross_data_elementtype_set(EVENT_THRESHOLD_CROSS * const event,char * sheader); + /**************************************************************************//** + * Set the TCA Data collector value. + * + * @param sheader Data collector value + *****************************************************************************/ + void evel_threshold_cross_data_collector_set(EVENT_THRESHOLD_CROSS * const event,char * sheader); + /**************************************************************************//** + * Set the TCA alert value. + * + * @param sheader Possible alert value + *****************************************************************************/ + void evel_threshold_cross_alertvalue_set(EVENT_THRESHOLD_CROSS * const event,char * sheader); + +/**************************************************************************//** + * Add an additional field name/value pair to the THRESHOLD CROSS event. + * + * The name and value are null delimited ASCII strings. The library takes + * a copy so the caller does not have to preserve values after the function + * returns. + * + * @param state_change Pointer to the ::EVENT_THRESHOLD_CROSS. + * @param name ASCIIZ string with the attribute's name. The caller + * does not need to preserve the value once the function + * returns. + * @param value ASCIIZ string with the attribute's value. The caller + * does not need to preserve the value once the function + * returns. + *****************************************************************************/ +void evel_threshold_cross_addl_info_add(EVENT_THRESHOLD_CROSS * const tcp, + const char * const name, + const char * const value); + +/*****************************************************************************/ +/*****************************************************************************/ +/* */ +/* LOGGING */ +/* */ +/*****************************************************************************/ +/*****************************************************************************/ + +/*****************************************************************************/ +/* Debug macros. */ +/*****************************************************************************/ +#define EVEL_DEBUG(FMT, ...) log_debug(EVEL_LOG_DEBUG, (FMT), ##__VA_ARGS__) +#define EVEL_INFO(FMT, ...) log_debug(EVEL_LOG_INFO, (FMT), ##__VA_ARGS__) +#define EVEL_SPAMMY(FMT, ...) log_debug(EVEL_LOG_SPAMMY, (FMT), ##__VA_ARGS__) +#define EVEL_ERROR(FMT, ...) log_debug(EVEL_LOG_ERROR, "ERROR: " FMT, \ + ##__VA_ARGS__) +#define EVEL_ENTER() \ + { \ + log_debug(EVEL_LOG_DEBUG, "Enter %s {", __FUNCTION__); \ + debug_indent += 2; \ + } +#define EVEL_EXIT() \ + { \ + debug_indent -= 2; \ + log_debug(EVEL_LOG_DEBUG, "Exit %s }", __FUNCTION__); \ + } + +#define INDENT_SEPARATORS \ + "| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | " + +extern EVEL_LOG_LEVELS debug_level; +extern int debug_indent; +extern FILE * fout; + +#define EVEL_DEBUG_ON() ((debug_level) >= EVEL_LOG_DEBUG) + +/**************************************************************************//** + * Initialize logging + * + * @param[in] level The debugging level - one of ::EVEL_LOG_LEVELS. + * @param[in] ident The identifier for our logs. + *****************************************************************************/ +void log_initialize(EVEL_LOG_LEVELS level, const char * ident); + +/**************************************************************************//** + * Log debug information + * + * Logs debugging information in a platform independent manner. + * + * @param[in] level The debugging level - one of ::EVEL_LOG_LEVELS. + * @param[in] format Log formatting string in printf format. + * @param[in] ... Variable argument list. + *****************************************************************************/ +void log_debug(EVEL_LOG_LEVELS level, char * format, ...); + +/***************************************************************************//* + * Store the formatted string into the static error string and log the error. + * + * @param format Error string in standard printf format. + * @param ... Variable parameters to be substituted into the format string. + *****************************************************************************/ +void log_error_state(char * format, ...); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_event.c b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_event.c new file mode 100644 index 0000000..ced29b2 --- /dev/null +++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_event.c @@ -0,0 +1,755 @@ +/*************************************************************************//** + * + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************/ + +/**************************************************************************//** + * @file + * Implementation of EVEL functions relating to Event Headers - since + * Heartbeats only contain the Event Header, the Heartbeat factory function is + * here too. + *****************************************************************************/ + +#include +#include +#include +#include + +#include "evel.h" +#include "evel_internal.h" +#include "evel_throttle.h" +#include "metadata.h" + +/**************************************************************************//** + * Unique sequence number for events from this VNF. + *****************************************************************************/ +static int event_sequence = 1; + +/**************************************************************************//** + * Set the next event_sequence to use. + * + * @param sequence The next sequence number to use. + *****************************************************************************/ +void evel_set_next_event_sequence(const int sequence) +{ + EVEL_ENTER(); + + EVEL_INFO("Setting event sequence to %d, was %d ", sequence, event_sequence); + event_sequence = sequence; + + EVEL_EXIT(); +} + + +/**************************************************************************//** + * Create a new heartbeat event of given name and type. + * + * @note that the heartbeat is just a "naked" commonEventHeader! + * + * @param event_name Unique Event Name: in format + * {DomainAbbreviation}_{AsdcModel or ApplicationPlatform}_{DescriptionOfInfoBeingConveyed} + * @param event_id Uniquely identify event for correlation and analysis + * + * @returns pointer to the newly manufactured ::EVENT_HEADER. If the event is + * not used it must be released using ::evel_free_event + * @retval NULL Failed to create the event. + *****************************************************************************/ +EVENT_HEADER * evel_new_heartbeat_nameid(const char* ev_name, const char *ev_id) +{ + EVENT_HEADER * heartbeat = NULL; + EVEL_ENTER(); + + assert(ev_name != NULL); + assert(ev_id != NULL); + + /***************************************************************************/ + /* Allocate the header. */ + /***************************************************************************/ + heartbeat = malloc(sizeof(EVENT_HEADER)); + if (heartbeat == NULL) + { + log_error_state("Out of memory"); + goto exit_label; + } + memset(heartbeat, 0, sizeof(EVENT_HEADER)); + + /***************************************************************************/ + /* Initialize the header. Get a new event sequence number. Note that if */ + /* any memory allocation fails in here we will fail gracefully because */ + /* everything downstream can cope with NULLs. */ + /***************************************************************************/ + evel_init_header_nameid(heartbeat,ev_name,ev_id); + +exit_label: + EVEL_EXIT(); + return heartbeat; +} + +/**************************************************************************//** + * Create a new heartbeat event. + * + * @note that the heartbeat is just a "naked" commonEventHeader! + * + * @returns pointer to the newly manufactured ::EVENT_HEADER. If the event is + * not used it must be released using ::evel_free_event + * @retval NULL Failed to create the event. + *****************************************************************************/ +EVENT_HEADER * evel_new_heartbeat() +{ + EVENT_HEADER * heartbeat = NULL; + EVEL_ENTER(); + + /***************************************************************************/ + /* Allocate the header. */ + /***************************************************************************/ + heartbeat = malloc(sizeof(EVENT_HEADER)); + if (heartbeat == NULL) + { + log_error_state("Out of memory"); + goto exit_label; + } + memset(heartbeat, 0, sizeof(EVENT_HEADER)); + + /***************************************************************************/ + /* Initialize the header. Get a new event sequence number. Note that if */ + /* any memory allocation fails in here we will fail gracefully because */ + /* everything downstream can cope with NULLs. */ + /***************************************************************************/ + evel_init_header(heartbeat,"Heartbeat"); + evel_force_option_string(&heartbeat->event_type, "Autonomous heartbeat"); + +exit_label: + EVEL_EXIT(); + return heartbeat; +} + +/**************************************************************************//** + * Initialize a newly created event header. + * + * @param header Pointer to the header being initialized. + *****************************************************************************/ +void evel_init_header(EVENT_HEADER * const header,const char *const eventname) +{ + char scratchpad[EVEL_MAX_STRING_LEN + 1] = {0}; + struct timeval tv; + + EVEL_ENTER(); + + assert(header != NULL); + + gettimeofday(&tv, NULL); + + /***************************************************************************/ + /* Initialize the header. Get a new event sequence number. Note that if */ + /* any memory allocation fails in here we will fail gracefully because */ + /* everything downstream can cope with NULLs. */ + /***************************************************************************/ + header->event_domain = EVEL_DOMAIN_HEARTBEAT; + snprintf(scratchpad, EVEL_MAX_STRING_LEN, "%d", event_sequence); + header->event_id = strdup(scratchpad); + if( eventname == NULL ) + header->event_name = strdup(functional_role); + else + header->event_name = strdup(eventname); + header->last_epoch_microsec = tv.tv_usec + 1000000 * tv.tv_sec; + header->priority = EVEL_PRIORITY_NORMAL; + header->reporting_entity_name = strdup(openstack_vm_name()); + header->source_name = strdup(openstack_vm_name()); + header->sequence = event_sequence; + header->start_epoch_microsec = header->last_epoch_microsec; + header->major_version = EVEL_HEADER_MAJOR_VERSION; + header->minor_version = EVEL_HEADER_MINOR_VERSION; + event_sequence++; + + /***************************************************************************/ + /* Optional parameters. */ + /***************************************************************************/ + evel_init_option_string(&header->event_type); + evel_init_option_string(&header->nfcnaming_code); + evel_init_option_string(&header->nfnaming_code); + evel_force_option_string(&header->reporting_entity_id, openstack_vm_uuid()); + evel_force_option_string(&header->source_id, openstack_vm_uuid()); + evel_init_option_intheader(&header->internal_field); + + EVEL_EXIT(); +} + + +/**************************************************************************//** + * Initialize a newly created event header. + * + * @param header Pointer to the header being initialized. + *****************************************************************************/ +void evel_init_header_nameid(EVENT_HEADER * const header,const char *const eventname, const char *eventid) +{ + struct timeval tv; + + EVEL_ENTER(); + + assert(header != NULL); + assert(eventname != NULL); + assert(eventid != NULL); + + gettimeofday(&tv, NULL); + + /***************************************************************************/ + /* Initialize the header. Get a new event sequence number. Note that if */ + /* any memory allocation fails in here we will fail gracefully because */ + /* everything downstream can cope with NULLs. */ + /***************************************************************************/ + header->event_domain = EVEL_DOMAIN_HEARTBEAT; + header->event_id = strdup(eventid); + header->event_name = strdup(eventname); + header->last_epoch_microsec = tv.tv_usec + 1000000 * tv.tv_sec; + header->priority = EVEL_PRIORITY_NORMAL; + header->reporting_entity_name = strdup(openstack_vm_name()); + header->source_name = strdup(openstack_vm_name()); + header->sequence = event_sequence; + header->start_epoch_microsec = header->last_epoch_microsec; + header->major_version = EVEL_HEADER_MAJOR_VERSION; + header->minor_version = EVEL_HEADER_MINOR_VERSION; + event_sequence++; + + /***************************************************************************/ + /* Optional parameters. */ + /***************************************************************************/ + evel_init_option_string(&header->event_type); + evel_init_option_string(&header->nfcnaming_code); + evel_init_option_string(&header->nfnaming_code); + evel_force_option_string(&header->reporting_entity_id, openstack_vm_uuid()); + evel_force_option_string(&header->source_id, openstack_vm_uuid()); + evel_init_option_intheader(&header->internal_field); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Event Type property of the event header. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param header Pointer to the ::EVENT_HEADER. + * @param type The Event Type to be set. ASCIIZ string. The caller + * does not need to preserve the value once the function + * returns. + *****************************************************************************/ +void evel_header_type_set(EVENT_HEADER * const header, + const char * const type) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(header != NULL); + assert(type != NULL); + + evel_set_option_string(&header->event_type, type, "Event Type"); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Start Epoch property of the event header. + * + * @note The Start Epoch defaults to the time of event creation. + * + * @param header Pointer to the ::EVENT_HEADER. + * @param start_epoch_microsec + * The start epoch to set, in microseconds. + *****************************************************************************/ +void evel_start_epoch_set(EVENT_HEADER * const header, + const unsigned long long start_epoch_microsec) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions and assign the new value. */ + /***************************************************************************/ + assert(header != NULL); + header->start_epoch_microsec = start_epoch_microsec; + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Last Epoch property of the event header. + * + * @note The Last Epoch defaults to the time of event creation. + * + * @param header Pointer to the ::EVENT_HEADER. + * @param last_epoch_microsec + * The last epoch to set, in microseconds. + *****************************************************************************/ +void evel_last_epoch_set(EVENT_HEADER * const header, + const unsigned long long last_epoch_microsec) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions and assign the new value. */ + /***************************************************************************/ + assert(header != NULL); + header->last_epoch_microsec = last_epoch_microsec; + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the NFC Naming code property of the event header. + * + * @param header Pointer to the ::EVENT_HEADER. + * @param nfcnamingcode String + *****************************************************************************/ +void evel_nfcnamingcode_set(EVENT_HEADER * const header, + const char * const nfcnam) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions and assign the new value. */ + /***************************************************************************/ + assert(header != NULL); + assert(nfcnam != NULL); + evel_set_option_string(&header->nfcnaming_code, nfcnam, "NFC Naming Code"); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the NF Naming code property of the event header. + * + * @param header Pointer to the ::EVENT_HEADER. + * @param nfnamingcode String + *****************************************************************************/ +void evel_nfnamingcode_set(EVENT_HEADER * const header, + const char * const nfnam) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions and assign the new value. */ + /***************************************************************************/ + assert(header != NULL); + assert(nfnam != NULL); + evel_set_option_string(&header->nfnaming_code, nfnam, "NF Naming Code"); + + EVEL_EXIT(); +} + + +/**************************************************************************//** + * Set the Reporting Entity Name property of the event header. + * + * @note The Reporting Entity Name defaults to the OpenStack VM Name. + * + * @param header Pointer to the ::EVENT_HEADER. + * @param entity_name The entity name to set. + *****************************************************************************/ +void evel_reporting_entity_name_set(EVENT_HEADER * const header, + const char * const entity_name) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions and assign the new value. */ + /***************************************************************************/ + assert(header != NULL); + assert(entity_name != NULL); + assert(header->reporting_entity_name != NULL); + + /***************************************************************************/ + /* Free the previously allocated memory and replace it with a copy of the */ + /* provided one. */ + /***************************************************************************/ + free(header->reporting_entity_name); + header->reporting_entity_name = strdup(entity_name); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Reporting Entity Id property of the event header. + * + * @note The Reporting Entity Id defaults to the OpenStack VM UUID. + * + * @param header Pointer to the ::EVENT_HEADER. + * @param entity_id The entity id to set. + *****************************************************************************/ +void evel_reporting_entity_id_set(EVENT_HEADER * const header, + const char * const entity_id) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions and assign the new value. */ + /***************************************************************************/ + assert(header != NULL); + assert(entity_id != NULL); + + /***************************************************************************/ + /* Free the previously allocated memory and replace it with a copy of the */ + /* provided one. Note that evel_force_option_string strdups entity_id. */ + /***************************************************************************/ + evel_free_option_string(&header->reporting_entity_id); + evel_force_option_string(&header->reporting_entity_id, entity_id); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Encode the event as a JSON event object according to AT&T's schema. + * + * @param jbuf Pointer to the ::EVEL_JSON_BUFFER to encode into. + * @param event Pointer to the ::EVENT_HEADER to encode. + *****************************************************************************/ +void evel_json_encode_header(EVEL_JSON_BUFFER * jbuf, + EVENT_HEADER * event) +{ + char * domain; + char * priority; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(jbuf != NULL); + assert(jbuf->json != NULL); + assert(jbuf->max_size > 0); + assert(event != NULL); + + domain = evel_event_domain(event->event_domain); + priority = evel_event_priority(event->priority); + evel_json_open_named_object(jbuf, "commonEventHeader"); + + /***************************************************************************/ + /* Mandatory fields. */ + /***************************************************************************/ + evel_enc_kv_string(jbuf, "domain", domain); + evel_enc_kv_string(jbuf, "eventId", event->event_id); + evel_enc_kv_string(jbuf, "eventName", event->event_name); + evel_enc_kv_ull(jbuf, "lastEpochMicrosec", event->last_epoch_microsec); + evel_enc_kv_string(jbuf, "priority", priority); + evel_enc_kv_string( + jbuf, "reportingEntityName", event->reporting_entity_name); + evel_enc_kv_int(jbuf, "sequence", event->sequence); + evel_enc_kv_string(jbuf, "sourceName", event->source_name); + evel_enc_kv_ull(jbuf, "startEpochMicrosec", event->start_epoch_microsec); + evel_enc_version( + jbuf, "version", event->major_version, event->minor_version); + + /***************************************************************************/ + /* Optional fields. */ + /***************************************************************************/ + evel_enc_kv_opt_string(jbuf, "eventType", &event->event_type); + evel_enc_kv_opt_string( + jbuf, "reportingEntityId", &event->reporting_entity_id); + evel_enc_kv_opt_string(jbuf, "sourceId", &event->source_id); + evel_enc_kv_opt_string(jbuf, "nfcNamingCode", &event->nfcnaming_code); + evel_enc_kv_opt_string(jbuf, "nfNamingCode", &event->nfnaming_code); + + evel_json_close_object(jbuf); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Free an event header. + * + * Free off the event header supplied. Will free all the contained allocated + * memory. + * + * @note It does not free the header itself, since that may be part of a + * larger structure. + *****************************************************************************/ +void evel_free_header(EVENT_HEADER * const event) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. As an internal API we don't allow freeing NULL */ + /* events as we do on the public API. */ + /***************************************************************************/ + assert(event != NULL); + + /***************************************************************************/ + /* Free all internal strings. */ + /***************************************************************************/ + free(event->event_id); + evel_free_option_string(&event->event_type); + free(event->event_name); + evel_free_option_string(&event->reporting_entity_id); + free(event->reporting_entity_name); + evel_free_option_string(&event->source_id); + evel_free_option_string(&event->nfcnaming_code); + evel_free_option_string(&event->nfnaming_code); + evel_free_option_intheader(&event->internal_field); + free(event->source_name); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Encode the event as a JSON event object according to AT&T's schema. + * + * @param json Pointer to where to store the JSON encoded data. + * @param max_size Size of storage available in json_body. + * @param event Pointer to the ::EVENT_HEADER to encode. + * @returns Number of bytes actually written. + *****************************************************************************/ +int evel_json_encode_event(char * json, + int max_size, + EVENT_HEADER * event) +{ + EVEL_JSON_BUFFER json_buffer; + EVEL_JSON_BUFFER * jbuf = &json_buffer; + EVEL_THROTTLE_SPEC * throttle_spec; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Get the latest throttle specification for the domain. */ + /***************************************************************************/ + throttle_spec = evel_get_throttle_spec(event->event_domain); + + /***************************************************************************/ + /* Initialize the JSON_BUFFER and open the top-level objects. */ + /***************************************************************************/ + evel_json_buffer_init(jbuf, json, max_size, throttle_spec); + evel_json_open_object(jbuf); + evel_json_open_named_object(jbuf, "event"); + + switch (event->event_domain) + { + case EVEL_DOMAIN_HEARTBEAT: + evel_json_encode_header(jbuf, event); + break; + + case EVEL_DOMAIN_FAULT: + evel_json_encode_fault(jbuf, (EVENT_FAULT *)event); + break; + + case EVEL_DOMAIN_MEASUREMENT: + evel_json_encode_measurement(jbuf, (EVENT_MEASUREMENT *)event); + break; + + case EVEL_DOMAIN_MOBILE_FLOW: + evel_json_encode_mobile_flow(jbuf, (EVENT_MOBILE_FLOW *)event); + break; + + case EVEL_DOMAIN_REPORT: + evel_json_encode_report(jbuf, (EVENT_REPORT *)event); + break; + + case EVEL_DOMAIN_HEARTBEAT_FIELD: + evel_json_encode_hrtbt_field(jbuf, (EVENT_HEARTBEAT_FIELD *)event); + break; + + case EVEL_DOMAIN_SIPSIGNALING: + evel_json_encode_signaling(jbuf, (EVENT_SIGNALING *)event); + break; + + case EVEL_DOMAIN_STATE_CHANGE: + evel_json_encode_state_change(jbuf, (EVENT_STATE_CHANGE *)event); + break; + + case EVEL_DOMAIN_SYSLOG: + evel_json_encode_syslog(jbuf, (EVENT_SYSLOG *)event); + break; + + case EVEL_DOMAIN_OTHER: + evel_json_encode_other(jbuf, (EVENT_OTHER *)event); + break; + + case EVEL_DOMAIN_VOICE_QUALITY: + evel_json_encode_voice_quality(jbuf, (EVENT_VOICE_QUALITY *)event); + break; + + case EVEL_DOMAIN_THRESHOLD_CROSS: + evel_json_encode_threshold_cross(jbuf, (EVENT_THRESHOLD_CROSS *)event); + break; + + case EVEL_DOMAIN_INTERNAL: + default: + EVEL_ERROR("Unexpected domain %d", event->event_domain); + assert(0); + } + + evel_json_close_object(jbuf); + evel_json_close_object(jbuf); + + /***************************************************************************/ + /* Sanity check. */ + /***************************************************************************/ + assert(jbuf->depth == 0); + + EVEL_EXIT(); + + return jbuf->offset; +} + + +/**************************************************************************//** + * Initialize an event instance id. + * + * @param vfield Pointer to the event vnfname field being initialized. + * @param vendor_id The vendor id to encode in the event instance id. + * @param event_id The event id to encode in the event instance id. + *****************************************************************************/ +void evel_init_vendor_field(VENDOR_VNFNAME_FIELD * const vfield, + const char * const vendor_name) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(vfield != NULL); + assert(vendor_name != NULL); + + /***************************************************************************/ + /* Store the mandatory parts. */ + /***************************************************************************/ + vfield->vendorname = strdup(vendor_name); + evel_init_option_string(&vfield->vfmodule); + evel_init_option_string(&vfield->vnfname); + + /***************************************************************************/ + /* Initialize the optional parts. */ + /***************************************************************************/ + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Vendor module property of the Vendor. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param vfield Pointer to the Vendor field. + * @param module_name The module name to be set. ASCIIZ string. The caller + * does not need to preserve the value once the function + * returns. + *****************************************************************************/ +void evel_vendor_field_module_set(VENDOR_VNFNAME_FIELD * const vfield, + const char * const module_name) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(vfield != NULL); + assert(module_name != NULL); + + evel_set_option_string(&vfield->vfmodule, module_name, "Module name set"); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Vendor module property of the Vendor. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param vfield Pointer to the Vendor field. + * @param module_name The module name to be set. ASCIIZ string. The caller + * does not need to preserve the value once the function + * returns. + *****************************************************************************/ +void evel_vendor_field_vnfname_set(VENDOR_VNFNAME_FIELD * const vfield, + const char * const vnfname) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(vfield != NULL); + assert(vnfname != NULL); + + evel_set_option_string(&vfield->vnfname, vnfname, "Virtual Network Function name set"); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Free an event instance id. + * + * @param vfield Pointer to the event vnfname_field being freed. + *****************************************************************************/ +void evel_free_event_vendor_field(VENDOR_VNFNAME_FIELD * const vfield) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(vfield->vendorname != NULL); + + /***************************************************************************/ + /* Free everything. */ + /***************************************************************************/ + evel_free_option_string(&vfield->vfmodule); + evel_free_option_string(&vfield->vnfname); + free(vfield->vendorname); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Encode the instance id as a JSON object according to AT&T's schema. + * + * @param jbuf Pointer to the ::EVEL_JSON_BUFFER to encode into. + * @param vfield Pointer to the ::VENDOR_VNFNAME_FIELD to encode. + *****************************************************************************/ +void evel_json_encode_vendor_field(EVEL_JSON_BUFFER * jbuf, + VENDOR_VNFNAME_FIELD * vfield) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(jbuf != NULL); + assert(jbuf->json != NULL); + assert(jbuf->max_size > 0); + assert(vfield != NULL); + assert(vfield->vendorname != NULL); + + evel_json_open_named_object(jbuf, "vendorVnfNameFields"); + + /***************************************************************************/ + /* Mandatory fields. */ + /***************************************************************************/ + evel_enc_kv_string(jbuf, "vendorName", vfield->vendorname); + evel_enc_kv_opt_string(jbuf, "vfModuleName", &vfield->vfmodule); + evel_enc_kv_opt_string(jbuf, "vnfName", &vfield->vnfname); + + /***************************************************************************/ + /* Optional fields. */ + /***************************************************************************/ + + evel_json_close_object(jbuf); + + EVEL_EXIT(); +} diff --git a/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_event_mgr.c b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_event_mgr.c new file mode 100644 index 0000000..a96124a --- /dev/null +++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_event_mgr.c @@ -0,0 +1,1050 @@ +/*************************************************************************//** + * + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************/ + +/**************************************************************************//** + * @file + * Event Manager + * + * Simple event manager that is responsible for taking events (Heartbeats, + * Faults and Measurements) from the ring-buffer and posting them to the API. + * + ****************************************************************************/ + +#include +#include +#include +#include + +#include + +#include "evel.h" +#include "evel_internal.h" +#include "ring_buffer.h" +#include "evel_throttle.h" + +/**************************************************************************//** + * How long we're prepared to wait for the API service to respond in + * seconds. + *****************************************************************************/ +static const int EVEL_API_TIMEOUT = 5; + +/*****************************************************************************/ +/* Prototypes of locally scoped functions. */ +/*****************************************************************************/ +static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *userp); +static void * event_handler(void *arg); +static bool evel_handle_response_tokens(const MEMORY_CHUNK * const chunk, + const jsmntok_t * const json_tokens, + const int num_tokens, + MEMORY_CHUNK * const post); +static bool evel_tokens_match_command_list(const MEMORY_CHUNK * const chunk, + const jsmntok_t * const json_token, + const int num_tokens); +static bool evel_token_equals_string(const MEMORY_CHUNK * const chunk, + const jsmntok_t * const json_token, + const char * check_string); + +/**************************************************************************//** + * Buffers for error strings from libcurl. + *****************************************************************************/ +static char curl_err_string[CURL_ERROR_SIZE] = ""; + +/**************************************************************************//** + * Handle for the API into libcurl. + *****************************************************************************/ +static CURL * curl_handle = NULL; + +/**************************************************************************//** + * Special headers that we send. + *****************************************************************************/ +static struct curl_slist * hdr_chunk = NULL; + +/**************************************************************************//** + * Message queue for sending events to the API. + *****************************************************************************/ +static ring_buffer event_buffer; + +/**************************************************************************//** + * Single pending priority post, which can be generated as a result of a + * response to an event. Currently only used to respond to a commandList. + *****************************************************************************/ +static MEMORY_CHUNK priority_post; + +/**************************************************************************//** + * The thread which is responsible for handling events off of the ring-buffer + * and posting them to the Event Handler API. + *****************************************************************************/ +static pthread_t evt_handler_thread; + +/**************************************************************************//** + * Variable to convey to the event handler thread what the foreground wants it + * to do. + *****************************************************************************/ +static EVT_HANDLER_STATE evt_handler_state = EVT_HANDLER_UNINITIALIZED; + +/**************************************************************************//** + * The configured API URL for event and throttling. + *****************************************************************************/ +static char * evel_event_api_url; +static char * evel_throt_api_url; + +/**************************************************************************//** + * Initialize the event handler. + * + * Primarily responsible for getting CURL ready for use. + * + * @param[in] event_api_url + * The URL where the Vendor Event Listener API is expected + * to be. + * @param[in] throt_api_url + * The URL where the Throttling API is expected to be. + * @param[in] username The username for the Basic Authentication of requests. + * @param[in] password The password for the Basic Authentication of requests. + * @param verbosity 0 for normal operation, positive values for chattier + * logs. + *****************************************************************************/ +EVEL_ERR_CODES event_handler_initialize(const char * const event_api_url, + const char * const throt_api_url, + const char * const username, + const char * const password, + int verbosity) +{ + int rc = EVEL_SUCCESS; + CURLcode curl_rc = CURLE_OK; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Check assumptions. */ + /***************************************************************************/ + assert(event_api_url != NULL); + assert(throt_api_url != NULL); + assert(username != NULL); + assert(password != NULL); + + /***************************************************************************/ + /* Store the API URLs. */ + /***************************************************************************/ + evel_event_api_url = strdup(event_api_url); + assert(evel_event_api_url != NULL); + evel_throt_api_url = strdup(throt_api_url); + assert(evel_throt_api_url != NULL); + + + curl_version_info_data *d = curl_version_info(CURLVERSION_NOW); + /* compare with the 24 bit hex number in 8 bit fields */ + if(d->version_num >= 0x072100) { + /* this is libcurl 7.33.0 or later */ + EVEL_INFO("7.33 or later Curl version %x.",d->version_num); + } + else { + EVEL_INFO("Old Curl version."); + } + /***************************************************************************/ + /* Start the CURL library. Note that this initialization is not threadsafe */ + /* which imposes a constraint that the EVEL library is initialized before */ + /* any threads are started. */ + /***************************************************************************/ + curl_rc = curl_global_init(CURL_GLOBAL_SSL); + if (curl_rc != CURLE_OK) + { + rc = EVEL_CURL_LIBRARY_FAIL; + log_error_state("Failed to initialize libCURL. Error code=%d", curl_rc); + goto exit_label; + } + + /***************************************************************************/ + /* Get a curl handle which we'll use for all of our output. */ + /***************************************************************************/ + curl_handle = curl_easy_init(); + if (curl_handle == NULL) + { + rc = EVEL_CURL_LIBRARY_FAIL; + log_error_state("Failed to get libCURL handle"); + goto exit_label; + } + + /***************************************************************************/ + /* Prime the library to give friendly error codes. */ + /***************************************************************************/ + curl_rc = curl_easy_setopt(curl_handle, + CURLOPT_ERRORBUFFER, + curl_err_string); + if (curl_rc != CURLE_OK) + { + rc = EVEL_CURL_LIBRARY_FAIL; + log_error_state("Failed to initialize libCURL to provide friendly errors. " + "Error code=%d", curl_rc); + goto exit_label; + } + + /***************************************************************************/ + /* If running in verbose mode generate more output. */ + /***************************************************************************/ + if (verbosity > 0) + { + curl_rc = curl_easy_setopt(curl_handle, CURLOPT_VERBOSE, 1L); + if (curl_rc != CURLE_OK) + { + rc = EVEL_CURL_LIBRARY_FAIL; + log_error_state("Failed to initialize libCURL to be verbose. " + "Error code=%d", curl_rc); + goto exit_label; + } + } + + /***************************************************************************/ + /* Set the URL for the API. */ + /***************************************************************************/ + curl_rc = curl_easy_setopt(curl_handle, CURLOPT_URL, event_api_url); + if (curl_rc != CURLE_OK) + { + rc = EVEL_CURL_LIBRARY_FAIL; + log_error_state("Failed to initialize libCURL with the API URL. " + "Error code=%d (%s)", curl_rc, curl_err_string); + goto exit_label; + } + EVEL_INFO("Initializing CURL to send events to: %s", event_api_url); + + /***************************************************************************/ + /* send all data to this function. */ + /***************************************************************************/ + curl_rc = curl_easy_setopt(curl_handle, + CURLOPT_WRITEFUNCTION, + evel_write_callback); + if (curl_rc != CURLE_OK) + { + rc = EVEL_CURL_LIBRARY_FAIL; + log_error_state("Failed to initialize libCURL with the write callback. " + "Error code=%d (%s)", curl_rc, curl_err_string); + goto exit_label; + } + + /***************************************************************************/ + /* some servers don't like requests that are made without a user-agent */ + /* field, so we provide one. */ + /***************************************************************************/ + curl_rc = curl_easy_setopt(curl_handle, + CURLOPT_USERAGENT, + "libcurl-agent/1.0"); + if (curl_rc != CURLE_OK) + { + rc = EVEL_CURL_LIBRARY_FAIL; + log_error_state("Failed to initialize libCURL to upload. " + "Error code=%d (%s)", curl_rc, curl_err_string); + goto exit_label; + } + + /***************************************************************************/ + /* Specify that we are going to POST data. */ + /***************************************************************************/ + curl_rc = curl_easy_setopt(curl_handle, CURLOPT_POST, 1L); + if (curl_rc != CURLE_OK) + { + rc = EVEL_CURL_LIBRARY_FAIL; + log_error_state("Failed to initialize libCURL to upload. " + "Error code=%d (%s)", curl_rc, curl_err_string); + goto exit_label; + } + + /***************************************************************************/ + /* we want to use our own read function. */ + /***************************************************************************/ + curl_rc = curl_easy_setopt(curl_handle, CURLOPT_READFUNCTION, read_callback); + if (curl_rc != CURLE_OK) + { + rc = EVEL_CURL_LIBRARY_FAIL; + log_error_state("Failed to initialize libCURL to upload using read " + "function. Error code=%d (%s)", curl_rc, curl_err_string); + goto exit_label; + } + + /***************************************************************************/ + /* All of our events are JSON encoded. We also suppress the */ + /* Expect: 100-continue header that we would otherwise get since it */ + /* confuses some servers. */ + /* */ + /* @TODO: do AT&T want this behavior? */ + /***************************************************************************/ + hdr_chunk = curl_slist_append(hdr_chunk, "Content-type: application/json"); + hdr_chunk = curl_slist_append(hdr_chunk, "Expect:"); + + /***************************************************************************/ + /* set our custom set of headers. */ + /***************************************************************************/ + curl_rc = curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, hdr_chunk); + if (curl_rc != CURLE_OK) + { + rc = EVEL_CURL_LIBRARY_FAIL; + log_error_state("Failed to initialize libCURL to use custom headers. " + "Error code=%d (%s)", curl_rc, curl_err_string); + goto exit_label; + } + + /***************************************************************************/ + /* Set the timeout for the operation. */ + /***************************************************************************/ + curl_rc = curl_easy_setopt(curl_handle, + CURLOPT_TIMEOUT, + EVEL_API_TIMEOUT); + if (curl_rc != CURLE_OK) + { + rc = EVEL_CURL_LIBRARY_FAIL; + log_error_state("Failed to initialize libCURL for API timeout. " + "Error code=%d (%s)", curl_rc, curl_err_string); + goto exit_label; + } + + /***************************************************************************/ + /* Set that we want Basic authentication with username:password Base-64 */ + /* encoded for the operation. */ + /***************************************************************************/ + curl_rc = curl_easy_setopt(curl_handle, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); + if (curl_rc != CURLE_OK) + { + rc = EVEL_CURL_LIBRARY_FAIL; + log_error_state("Failed to initialize libCURL for Basic Authentication. " + "Error code=%d (%s)", curl_rc, curl_err_string); + goto exit_label; + } + curl_rc = curl_easy_setopt(curl_handle, CURLOPT_USERNAME, username); + if (curl_rc != CURLE_OK) + { + rc = EVEL_CURL_LIBRARY_FAIL; + log_error_state("Failed to initialize libCURL with username. " + "Error code=%d (%s)", curl_rc, curl_err_string); + goto exit_label; + } + curl_rc = curl_easy_setopt(curl_handle, CURLOPT_PASSWORD, password); + if (curl_rc != CURLE_OK) + { + rc = EVEL_CURL_LIBRARY_FAIL; + log_error_state("Failed to initialize libCURL with password. " + "Error code=%d (%s)", curl_rc, curl_err_string); + goto exit_label; + } + + /***************************************************************************/ + /* Initialize a message ring-buffer to be used between the foreground and */ + /* the thread which sends the messages. This can't fail. */ + /***************************************************************************/ + ring_buffer_initialize(&event_buffer, EVEL_EVENT_BUFFER_DEPTH); + + /***************************************************************************/ + /* Initialize the priority post buffer to empty. */ + /***************************************************************************/ + priority_post.memory = NULL; + +exit_label: + EVEL_EXIT(); + + return(rc); +} + +/**************************************************************************//** + * Run the event handler. + * + * Spawns the thread responsible for handling events and sending them to the + * API. + * + * @return Status code. + * @retval ::EVEL_SUCCESS if everything OK. + * @retval One of ::EVEL_ERR_CODES if there was a problem. + *****************************************************************************/ +EVEL_ERR_CODES event_handler_run() +{ + EVEL_ERR_CODES rc = EVEL_SUCCESS; + int pthread_rc = 0; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Start the event handler thread. */ + /***************************************************************************/ + evt_handler_state = EVT_HANDLER_INACTIVE; + pthread_rc = pthread_create(&evt_handler_thread, NULL, event_handler, NULL); + if (pthread_rc != 0) + { + rc = EVEL_PTHREAD_LIBRARY_FAIL; + log_error_state("Failed to start event handler thread. " + "Error code=%d", pthread_rc); + } + + EVEL_EXIT() + return rc; +} + +/**************************************************************************//** + * Terminate the event handler. + * + * Shuts down the event handler thread in as clean a way as possible. Sets the + * global exit flag and then signals the thread to interrupt it since it's + * most likely waiting on the ring-buffer. + * + * Having achieved an orderly shutdown of the event handler thread, clean up + * the cURL library's resources cleanly. + * + * @return Status code. + * @retval ::EVEL_SUCCESS if everything OK. + * @retval One of ::EVEL_ERR_CODES if there was a problem. + *****************************************************************************/ +EVEL_ERR_CODES event_handler_terminate() +{ + EVEL_ERR_CODES rc = EVEL_SUCCESS; + + EVEL_ENTER(); + EVENT_INTERNAL *event = NULL; + + /***************************************************************************/ + /* Make sure that we were initialized before trying to terminate the */ + /* event handler thread. */ + /***************************************************************************/ + if (evt_handler_state != EVT_HANDLER_UNINITIALIZED) + { + /*************************************************************************/ + /* Make sure that the event handler knows it's time to die. */ + /*************************************************************************/ + event = evel_new_internal_event(EVT_CMD_TERMINATE,"EVELinternal","EVELid"); + if (event == NULL) + { + /***********************************************************************/ + /* We failed to get an event, but we don't bail out - we will just */ + /* clean up what we can and continue on our way, since we're exiting */ + /* anyway. */ + /***********************************************************************/ + EVEL_ERROR("Failed to get internal event - perform dirty exit instead!"); + } + else + { + /***********************************************************************/ + /* Post the event then wait for the Event Handler to exit. Set the */ + /* global command, too, in case the ring-buffer is full. */ + /***********************************************************************/ + EVEL_DEBUG("Sending event to Event Hander to request it to exit."); + evt_handler_state = EVT_HANDLER_REQUEST_TERMINATE; + evel_post_event((EVENT_HEADER *) event); + pthread_join(evt_handler_thread, NULL); + EVEL_DEBUG("Event Handler thread has exited."); + } + } + else + { + EVEL_DEBUG("Event handler was not initialized, so no need to kill it"); + } + + /***************************************************************************/ + /* Clean-up the cURL library. */ + /***************************************************************************/ + if (curl_handle != NULL) + { + curl_easy_cleanup(curl_handle); + curl_handle = NULL; + } + if (hdr_chunk != NULL) + { + curl_slist_free_all(hdr_chunk); + hdr_chunk = NULL; + } + + /***************************************************************************/ + /* Free off the stored API URL strings. */ + /***************************************************************************/ + if (evel_event_api_url != NULL) + { + free(evel_event_api_url); + evel_event_api_url = NULL; + } + if (evel_throt_api_url != NULL) + { + free(evel_throt_api_url); + evel_throt_api_url = NULL; + } + + EVEL_EXIT(); + return rc; +} + +/**************************************************************************//** + * Post an event. + * + * @note So far as the caller is concerned, successfully posting the event + * relinquishes all responsibility for the event - the library will take care + * of freeing the event in due course. + + * @param event The event to be posted. + * + * @returns Status code + * @retval EVEL_SUCCESS On success + * @retval "One of ::EVEL_ERR_CODES" On failure. + *****************************************************************************/ +EVEL_ERR_CODES evel_post_event(EVENT_HEADER * event) +{ + int rc = EVEL_SUCCESS; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(event != NULL); + + /***************************************************************************/ + /* We need to make sure that we are either initializing or running */ + /* normally before writing the event into the buffer so that we can */ + /* guarantee that the ring-buffer empties properly on exit. */ + /***************************************************************************/ + if ((evt_handler_state == EVT_HANDLER_ACTIVE) || + (evt_handler_state == EVT_HANDLER_INACTIVE) || + (evt_handler_state == EVT_HANDLER_REQUEST_TERMINATE)) + { + if (ring_buffer_write(&event_buffer, event) == 0) + { + log_error_state("Failed to write event to buffer - event dropped!"); + rc = EVEL_EVENT_BUFFER_FULL; + evel_free_event(event); + } + } + else + { + /*************************************************************************/ + /* System is not in active operation, so reject the event. */ + /*************************************************************************/ + log_error_state("Event Handler system not active - event dropped!"); + rc = EVEL_EVENT_HANDLER_INACTIVE; + evel_free_event(event); + } + + EVEL_EXIT(); + return (rc); +} + +/**************************************************************************//** + * Post an event to the Vendor Event Listener API. + * + * @returns Status code + * @retval EVEL_SUCCESS On success + * @retval "One of ::EVEL_ERR_CODES" On failure. + *****************************************************************************/ +static EVEL_ERR_CODES evel_post_api(char * msg, size_t size) +{ + int rc = EVEL_SUCCESS; + CURLcode curl_rc = CURLE_OK; + MEMORY_CHUNK rx_chunk; + MEMORY_CHUNK tx_chunk; + int http_response_code = 0; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Create the memory chunk to be used for the response to the post. The */ + /* will be realloced. */ + /***************************************************************************/ + rx_chunk.memory = malloc(1); + assert(rx_chunk.memory != NULL); + rx_chunk.size = 0; + + /***************************************************************************/ + /* Create the memory chunk to be sent as the body of the post. */ + /***************************************************************************/ + tx_chunk.memory = msg; + tx_chunk.size = size; + EVEL_DEBUG("Sending chunk of size %d", tx_chunk.size); + + /***************************************************************************/ + /* Point to the data to be received. */ + /***************************************************************************/ + curl_rc = curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, &rx_chunk); + if (curl_rc != CURLE_OK) + { + rc = EVEL_CURL_LIBRARY_FAIL; + log_error_state("Failed to initialize libCURL to upload. " + "Error code=%d (%s)", curl_rc, curl_err_string); + goto exit_label; + } + EVEL_DEBUG("Initialized data to receive"); + + /***************************************************************************/ + /* Pointer to pass to our read function */ + /***************************************************************************/ + curl_rc = curl_easy_setopt(curl_handle, CURLOPT_READDATA, &tx_chunk); + if (curl_rc != CURLE_OK) + { + rc = EVEL_CURL_LIBRARY_FAIL; + log_error_state("Failed to set upload data for libCURL to upload. " + "Error code=%d (%s)", curl_rc, curl_err_string); + goto exit_label; + } + EVEL_DEBUG("Initialized data to send"); + + /***************************************************************************/ + /* Size of the data to transmit. */ + /***************************************************************************/ + curl_rc = curl_easy_setopt(curl_handle, + CURLOPT_POSTFIELDSIZE, + tx_chunk.size); + if (curl_rc != CURLE_OK) + { + rc = EVEL_CURL_LIBRARY_FAIL; + log_error_state("Failed to set length of upload data for libCURL to " + "upload. Error code=%d (%s)", curl_rc, curl_err_string); + goto exit_label; + } + EVEL_DEBUG("Initialized length of data to send"); + + /***************************************************************************/ + /* Now run off and do what you've been told! */ + /***************************************************************************/ + curl_rc = curl_easy_perform(curl_handle); + if (curl_rc != CURLE_OK) + { + rc = EVEL_CURL_LIBRARY_FAIL; + log_error_state("Failed to transfer an event to Vendor Event Listener! " + "Error code=%d (%s)", curl_rc, curl_err_string); + EVEL_ERROR("Dropped event: %s", msg); + goto exit_label; + } + + /***************************************************************************/ + /* See what response we got - any 2XX response is good. */ + /***************************************************************************/ + curl_easy_getinfo(curl_handle, CURLINFO_RESPONSE_CODE, &http_response_code); + EVEL_DEBUG("HTTP response code: %d", http_response_code); + if ((http_response_code / 100) == 2) + { + /*************************************************************************/ + /* If the server responded with data it may be interesting but not a */ + /* problem. */ + /*************************************************************************/ + if ((rx_chunk.size > 0) && (rx_chunk.memory != NULL)) + { + EVEL_DEBUG("Server returned data = %d (%s)", + rx_chunk.size, + rx_chunk.memory); + + /***********************************************************************/ + /* If this is a response to priority post, then we're not interested. */ + /***********************************************************************/ + if (priority_post.memory != NULL) + { + EVEL_ERROR("Ignoring priority post response"); + } + else + { + evel_handle_event_response(&rx_chunk, &priority_post); + } + } + } + else + { + EVEL_ERROR("Unexpected HTTP response code: %d with data size %d (%s)", + http_response_code, + rx_chunk.size, + rx_chunk.size > 0 ? rx_chunk.memory : "NONE"); + EVEL_ERROR("Potentially dropped event: %s", msg); + } + +exit_label: + free(rx_chunk.memory); + EVEL_EXIT(); + return(rc); +} + +/**************************************************************************//** + * Callback function to provide data to send. + * + * Copy data into the supplied buffer, read_callback::ptr, checking size + * limits. + * + * @returns Number of bytes placed into read_callback::ptr. 0 for EOF. + *****************************************************************************/ +static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *userp) +{ + size_t rtn = 0; + size_t bytes_to_write = 0; + MEMORY_CHUNK *tx_chunk = (MEMORY_CHUNK *)userp; + + EVEL_ENTER(); + + bytes_to_write = min(size*nmemb, tx_chunk->size); + + if (bytes_to_write > 0) + { + EVEL_DEBUG("Going to try to write %d bytes", bytes_to_write); + strncpy((char *)ptr, tx_chunk->memory, bytes_to_write); + tx_chunk->memory += bytes_to_write; + tx_chunk->size -= bytes_to_write; + rtn = bytes_to_write; + } + else + { + EVEL_DEBUG("Reached EOF"); + } + + EVEL_EXIT(); + return rtn; +} + +/**************************************************************************//** + * Callback function to provide returned data. + * + * Copy data into the supplied buffer, write_callback::ptr, checking size + * limits. + * + * @returns Number of bytes placed into write_callback::ptr. 0 for EOF. + *****************************************************************************/ +size_t evel_write_callback(void *contents, + size_t size, + size_t nmemb, + void *userp) +{ + size_t realsize = size * nmemb; + MEMORY_CHUNK * rx_chunk = (MEMORY_CHUNK *)userp; + + EVEL_ENTER(); + + EVEL_DEBUG("Called with %d chunks of %d size = %d", nmemb, size, realsize); + EVEL_DEBUG("rx chunk size is %d", rx_chunk->size); + + rx_chunk->memory = realloc(rx_chunk->memory, rx_chunk->size + realsize + 1); + if(rx_chunk->memory == NULL) { + /* out of memory! */ + printf("not enough memory (realloc returned NULL)\n"); + return 0; + } + + memcpy(&(rx_chunk->memory[rx_chunk->size]), contents, realsize); + rx_chunk->size += realsize; + rx_chunk->memory[rx_chunk->size] = 0; + + EVEL_DEBUG("Rx data: %s", rx_chunk->memory); + EVEL_DEBUG("Returning: %d", realsize); + + EVEL_EXIT(); + return realsize; +} + +/**************************************************************************//** + * Event Handler. + * + * Watch for messages coming on the internal queue and send them to the + * listener. + * + * param[in] arg Argument - unused. + *****************************************************************************/ +static void * event_handler(void * arg __attribute__ ((unused))) +{ + int old_type = 0; + EVENT_HEADER * msg = NULL; + EVENT_INTERNAL * internal_msg = NULL; + int json_size = 0; + char json_body[EVEL_MAX_JSON_BODY]; + int rc = EVEL_SUCCESS; + CURLcode curl_rc; + + EVEL_INFO("Event handler thread started"); + + /***************************************************************************/ + /* Set this thread to be cancellable immediately. */ + /***************************************************************************/ + pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &old_type); + + /***************************************************************************/ + /* Set the handler as active, defending against weird situations like */ + /* immediately shutting down after initializing the library so the */ + /* handler never gets started up properly. */ + /***************************************************************************/ + if (evt_handler_state == EVT_HANDLER_INACTIVE) + { + evt_handler_state = EVT_HANDLER_ACTIVE; + } + else + { + EVEL_ERROR("Event Handler State was not INACTIVE at start-up - " + "Handler will exit immediately!"); + } + + while (evt_handler_state == EVT_HANDLER_ACTIVE) + { + /*************************************************************************/ + /* Wait for a message to be received. */ + /*************************************************************************/ + EVEL_DEBUG("Event handler getting any messages"); + msg = ring_buffer_read(&event_buffer); + + /*************************************************************************/ + /* Internal events get special treatment while regular events get posted */ + /* to the far side. */ + /*************************************************************************/ + if (msg->event_domain != EVEL_DOMAIN_INTERNAL) + { + EVEL_DEBUG("External event received"); + + /***********************************************************************/ + /* Encode the event in JSON. */ + /***********************************************************************/ + json_size = evel_json_encode_event(json_body, EVEL_MAX_JSON_BODY, msg); + + /***********************************************************************/ + /* Send the JSON across the API. */ + /***********************************************************************/ + EVEL_DEBUG("Sending JSON of size %d is: %s", json_size, json_body); + rc = evel_post_api(json_body, json_size); + if (rc != EVEL_SUCCESS) + { + EVEL_ERROR("Failed to transfer the data. Error code=%d", rc); + } + } + else + { + EVEL_DEBUG("Internal event received"); + internal_msg = (EVENT_INTERNAL *) msg; + assert(internal_msg->command == EVT_CMD_TERMINATE); + evt_handler_state = EVT_HANDLER_TERMINATING; + } + + /*************************************************************************/ + /* We are responsible for freeing the memory. */ + /*************************************************************************/ + evel_free_event(msg); + msg = NULL; + + /*************************************************************************/ + /* There may be a single priority post to be sent. */ + /*************************************************************************/ + if (priority_post.memory != NULL) + { + EVEL_DEBUG("Priority Post"); + + /***********************************************************************/ + /* Set the URL for the throttling API. */ + /***********************************************************************/ + curl_rc = curl_easy_setopt(curl_handle, CURLOPT_URL, evel_throt_api_url); + if (curl_rc != CURLE_OK) + { + /*********************************************************************/ + /* This is only likely to happen with CURLE_OUT_OF_MEMORY, in which */ + /* case we carry on regardless. */ + /*********************************************************************/ + EVEL_ERROR("Failed to set throttling URL. Error code=%d", rc); + } + else + { + rc = evel_post_api(priority_post.memory, priority_post.size); + if (rc != EVEL_SUCCESS) + { + EVEL_ERROR("Failed to transfer priority post. Error code=%d", rc); + } + } + + /***********************************************************************/ + /* Reinstate the URL for the event API. */ + /***********************************************************************/ + curl_rc = curl_easy_setopt(curl_handle, CURLOPT_URL, evel_event_api_url); + if (curl_rc != CURLE_OK) + { + /*********************************************************************/ + /* This is only likely to happen with CURLE_OUT_OF_MEMORY, in which */ + /* case we carry on regardless. */ + /*********************************************************************/ + EVEL_ERROR("Failed to reinstate events URL. Error code=%d", rc); + } + + /***********************************************************************/ + /* We are responsible for freeing the memory. */ + /***********************************************************************/ + free(priority_post.memory); + priority_post.memory = NULL; + } + } + + /***************************************************************************/ + /* The event handler is now exiting. The ring-buffer could contain events */ + /* which have not been processed, so deplete those. Because we've been */ + /* asked to exit we can be confident that the foreground will have stopped */ + /* sending events in so we know that this process will conclude! */ + /***************************************************************************/ + evt_handler_state = EVT_HANDLER_TERMINATING; + while (!ring_buffer_is_empty(&event_buffer)) + { + EVEL_DEBUG("Reading event from buffer"); + msg = ring_buffer_read(&event_buffer); + evel_free_event(msg); + } + evt_handler_state = EVT_HANDLER_TERMINATED; + EVEL_INFO("Event handler thread stopped"); + + return (NULL); +} + +/**************************************************************************//** + * Handle a JSON response from the listener, contained in a ::MEMORY_CHUNK. + * + * Tokenize the response, and decode any tokens found. + * + * @param chunk The memory chunk containing the response. + * @param post The memory chunk in which to place any resulting POST. + *****************************************************************************/ +void evel_handle_event_response(const MEMORY_CHUNK * const chunk, + MEMORY_CHUNK * const post) +{ + jsmn_parser json_parser; + jsmntok_t json_tokens[EVEL_MAX_RESPONSE_TOKENS]; + int num_tokens = 0; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(chunk != NULL); + assert(priority_post.memory == NULL); + + EVEL_DEBUG("Response size = %d", chunk->size); + EVEL_DEBUG("Response = %s", chunk->memory); + + /***************************************************************************/ + /* Initialize the parser and tokenize the response. */ + /***************************************************************************/ + jsmn_init(&json_parser); + num_tokens = jsmn_parse(&json_parser, + chunk->memory, + chunk->size, + json_tokens, + EVEL_MAX_RESPONSE_TOKENS); + + if (num_tokens < 0) + { + EVEL_ERROR("Failed to parse JSON response. " + "Error code=%d", num_tokens); + } + else if (num_tokens == 0) + { + EVEL_DEBUG("No tokens found in JSON response"); + } + else + { + EVEL_DEBUG("Decode JSON response tokens"); + if (!evel_handle_response_tokens(chunk, json_tokens, num_tokens, post)) + { + EVEL_ERROR("Failed to handle JSON response."); + } + } + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Handle a JSON response from the listener, as a list of tokens from JSMN. + * + * @param chunk Memory chunk containing the JSON buffer. + * @param json_tokens Array of tokens to handle. + * @param num_tokens The number of tokens to handle. + * @param post The memory chunk in which to place any resulting POST. + * @return true if we handled the response, false otherwise. + *****************************************************************************/ +bool evel_handle_response_tokens(const MEMORY_CHUNK * const chunk, + const jsmntok_t * const json_tokens, + const int num_tokens, + MEMORY_CHUNK * const post) +{ + bool json_ok = false; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(chunk != NULL); + assert(json_tokens != NULL); + assert(num_tokens < EVEL_MAX_RESPONSE_TOKENS); + + /***************************************************************************/ + /* Peek at the tokens to decide what the response it, then call the */ + /* appropriate handler to handle it. There is only one handler at this */ + /* point. */ + /***************************************************************************/ + if (evel_tokens_match_command_list(chunk, json_tokens, num_tokens)) + { + json_ok = evel_handle_command_list(chunk, json_tokens, num_tokens, post); + } + + EVEL_EXIT(); + + return json_ok; +} + +/**************************************************************************//** + * Determine whether a list of tokens looks like a "commandList" response. + * + * @param chunk Memory chunk containing the JSON buffer. + * @param json_tokens Token to check. + * @param num_tokens The number of tokens to handle. + * @return true if the tokens look like a "commandList" match, or false. + *****************************************************************************/ +bool evel_tokens_match_command_list(const MEMORY_CHUNK * const chunk, + const jsmntok_t * const json_tokens, + const int num_tokens) +{ + bool result = false; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Make some checks on the basic layout of the commandList. */ + /***************************************************************************/ + if ((num_tokens > 3) && + (json_tokens[0].type == JSMN_OBJECT) && + (json_tokens[1].type == JSMN_STRING) && + (json_tokens[2].type == JSMN_ARRAY) && + (evel_token_equals_string(chunk, &json_tokens[1], "commandList"))) + { + result = true; + } + + EVEL_EXIT(); + + return result; +} + +/**************************************************************************//** + * Check that a string token matches a given input string. + * + * @param chunk Memory chunk containing the JSON buffer. + * @param json_token Token to check. + * @param check_string String to check it against. + * @return true if the strings match, or false. + *****************************************************************************/ +bool evel_token_equals_string(const MEMORY_CHUNK * const chunk, + const jsmntok_t * json_token, + const char * check_string) +{ + bool result = false; + + EVEL_ENTER(); + + const int token_length = json_token->end - json_token->start; + const char * const token_string = chunk->memory + json_token->start; + + if (token_length == (int)strlen(check_string)) + { + result = (strncmp(token_string, check_string, token_length) == 0); + } + + EVEL_EXIT(); + + return result; +} diff --git a/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_fault.c b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_fault.c new file mode 100644 index 0000000..c211f60 --- /dev/null +++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_fault.c @@ -0,0 +1,367 @@ +/*************************************************************************//** + * + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************/ + +/**************************************************************************//** + * @file + * Implementation of EVEL functions relating to the Fault. + * + ****************************************************************************/ + +#include +#include +#include + +#include "evel.h" +#include "evel_internal.h" +#include "evel_throttle.h" + +/**************************************************************************//** + * Create a new fault event. + * + * @note The mandatory fields on the Fault must be supplied to this factory + * function and are immutable once set. Optional fields have explicit + * setter functions, but again values may only be set once so that the + * Fault has immutable properties. + * @param event_name Unique Event Name confirming Domain AsdcModel Description + * @param event_id A universal identifier of the event for: troubleshooting correlation, analysis, etc + * @param condition The condition indicated by the Fault. + * @param specific_problem The specific problem triggering the fault. + * @param priority The priority of the event. + * @param severity The severity of the Fault. + * @param ev_source_type Source of Alarm event + * @param version fault version + * @param status status of Virtual Function + * @returns pointer to the newly manufactured ::EVENT_FAULT. If the event is + * not used (i.e. posted) it must be released using ::evel_free_fault. + * @retval NULL Failed to create the event. + *****************************************************************************/ +EVENT_FAULT * evel_new_fault(const char * ev_name, + const char * ev_id, + const char * const condition, + const char * const specific_problem, + EVEL_EVENT_PRIORITIES priority, + EVEL_SEVERITIES severity, + EVEL_SOURCE_TYPES ev_source_type, + EVEL_VF_STATUSES status) +{ + EVENT_FAULT * fault = NULL; + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(condition != NULL); + assert(specific_problem != NULL); + assert(priority < EVEL_MAX_PRIORITIES); + assert(severity < EVEL_MAX_SEVERITIES); + + /***************************************************************************/ + /* Allocate the fault. */ + /***************************************************************************/ + fault = malloc(sizeof(EVENT_FAULT)); + if (fault == NULL) + { + log_error_state("Out of memory"); + goto exit_label; + } + memset(fault, 0, sizeof(EVENT_FAULT)); + EVEL_DEBUG("New fault is at %lp", fault); + + /***************************************************************************/ + /* Initialize the header & the fault fields. Optional string values are */ + /* uninitialized (NULL). */ + /***************************************************************************/ + evel_init_header_nameid(&fault->header,ev_name,ev_id); + fault->header.event_domain = EVEL_DOMAIN_FAULT; + fault->header.priority = priority; + fault->major_version = EVEL_FAULT_MAJOR_VERSION; + fault->minor_version = EVEL_FAULT_MINOR_VERSION; + fault->event_severity = severity; + fault->event_source_type = ev_source_type; + fault->vf_status = status; + fault->alarm_condition = strdup(condition); + fault->specific_problem = strdup(specific_problem); + evel_init_option_string(&fault->category); + evel_init_option_string(&fault->alarm_interface_a); + dlist_initialize(&fault->additional_info); + +exit_label: + EVEL_EXIT(); + return fault; +} + +/**************************************************************************//** + * Add an additional value name/value pair to the Fault. + * + * The name and value are null delimited ASCII strings. The library takes + * a copy so the caller does not have to preserve values after the function + * returns. + * + * @param fault Pointer to the fault. + * @param name ASCIIZ string with the attribute's name. The caller + * does not need to preserve the value once the function + * returns. + * @param value ASCIIZ string with the attribute's value. The caller + * does not need to preserve the value once the function + * returns. + *****************************************************************************/ +void evel_fault_addl_info_add(EVENT_FAULT * fault, char * name, char * value) +{ + FAULT_ADDL_INFO * addl_info = NULL; + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(fault != NULL); + assert(fault->header.event_domain == EVEL_DOMAIN_FAULT); + assert(name != NULL); + assert(value != NULL); + + EVEL_DEBUG("Adding name=%s value=%s", name, value); + addl_info = malloc(sizeof(FAULT_ADDL_INFO)); + assert(addl_info != NULL); + memset(addl_info, 0, sizeof(FAULT_ADDL_INFO)); + addl_info->name = strdup(name); + addl_info->value = strdup(value); + assert(addl_info->name != NULL); + assert(addl_info->value != NULL); + + dlist_push_last(&fault->additional_info, addl_info); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Fault Category property of the Fault. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param fault Pointer to the fault. + * @param category Category : license, link, routing, security, signaling. + * ASCIIZ string. The caller + * does not need to preserve the value once the function + * returns. + *****************************************************************************/ +void evel_fault_category_set(EVENT_FAULT * fault, + const char * const category) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(fault != NULL); + assert(fault->header.event_domain == EVEL_DOMAIN_FAULT); + assert(category != NULL); + + evel_set_option_string(&fault->category, + category, + "Fault Category set"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Alarm Interface A property of the Fault. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param fault Pointer to the fault. + * @param interface The Alarm Interface A to be set. ASCIIZ string. The caller + * does not need to preserve the value once the function + * returns. + *****************************************************************************/ +void evel_fault_interface_set(EVENT_FAULT * fault, + const char * const interface) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(fault != NULL); + assert(fault->header.event_domain == EVEL_DOMAIN_FAULT); + assert(interface != NULL); + + evel_set_option_string(&fault->alarm_interface_a, + interface, + "Alarm Interface A"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Event Type property of the Fault. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param fault Pointer to the fault. + * @param type The Event Type to be set. ASCIIZ string. The caller + * does not need to preserve the value once the function + * returns. + *****************************************************************************/ +void evel_fault_type_set(EVENT_FAULT * fault, const char * const type) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions and call evel_header_type_set. */ + /***************************************************************************/ + assert(fault != NULL); + assert(fault->header.event_domain == EVEL_DOMAIN_FAULT); + evel_header_type_set(&fault->header, type); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Encode the fault in JSON according to AT&T's schema for the fault type. + * + * @param jbuf Pointer to the ::EVEL_JSON_BUFFER to encode into. + * @param event Pointer to the ::EVENT_HEADER to encode. + *****************************************************************************/ +void evel_json_encode_fault(EVEL_JSON_BUFFER * jbuf, + EVENT_FAULT * event) +{ + FAULT_ADDL_INFO * addl_info = NULL; + DLIST_ITEM * addl_info_item = NULL; + char * fault_severity; + char * fault_source_type; + char * fault_vf_status; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(event != NULL); + assert(event->header.event_domain == EVEL_DOMAIN_FAULT); + + fault_severity = evel_severity(event->event_severity); + fault_source_type = evel_source_type(event->event_source_type); + fault_vf_status = evel_vf_status(event->vf_status); + + evel_json_encode_header(jbuf, &event->header); + evel_json_open_named_object(jbuf, "faultFields"); + + /***************************************************************************/ + /* Mandatory fields. */ + /***************************************************************************/ + evel_enc_kv_string(jbuf, "alarmCondition", event->alarm_condition); + evel_enc_kv_opt_string(jbuf, "eventCategory", &event->category); + evel_enc_kv_string(jbuf, "eventSeverity", fault_severity); + evel_enc_kv_string(jbuf, "eventSourceType", fault_source_type); + evel_enc_kv_string(jbuf, "specificProblem", event->specific_problem); + evel_enc_kv_string(jbuf, "vfStatus", fault_vf_status); + evel_enc_version( + jbuf, "faultFieldsVersion", event->major_version, event->minor_version); + + /***************************************************************************/ + /* Optional fields. */ + /***************************************************************************/ + + /***************************************************************************/ + /* Checkpoint, so that we can wind back if all fields are suppressed. */ + /***************************************************************************/ + evel_json_checkpoint(jbuf); + if (evel_json_open_opt_named_list(jbuf, "alarmAdditionalInformation")) + { + bool item_added = false; + + addl_info_item = dlist_get_first(&event->additional_info); + while (addl_info_item != NULL) + { + addl_info = (FAULT_ADDL_INFO*) addl_info_item->item; + assert(addl_info != NULL); + + if (!evel_throttle_suppress_nv_pair(jbuf->throttle_spec, + "alarmAdditionalInformation", + addl_info->name)) + { + evel_json_open_object(jbuf); + evel_enc_kv_string(jbuf, "name", addl_info->name); + evel_enc_kv_string(jbuf, "value", addl_info->value); + evel_json_close_object(jbuf); + item_added = true; + } + addl_info_item = dlist_get_next(addl_info_item); + } + evel_json_close_list(jbuf); + + /*************************************************************************/ + /* If we've not written anything, rewind to before we opened the list. */ + /*************************************************************************/ + if (!item_added) + { + evel_json_rewind(jbuf); + } + } + evel_enc_kv_opt_string(jbuf, "alarmInterfaceA", &event->alarm_interface_a); + + evel_json_close_object(jbuf); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Free a Fault. + * + * Free off the Fault supplied. Will free all the contained allocated memory. + * + * @note It does not free the Fault itself, since that may be part of a + * larger structure. + *****************************************************************************/ +void evel_free_fault(EVENT_FAULT * event) +{ + FAULT_ADDL_INFO * addl_info = NULL; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. As an internal API we don't allow freeing NULL */ + /* events as we do on the public API. */ + /***************************************************************************/ + assert(event != NULL); + assert(event->header.event_domain == EVEL_DOMAIN_FAULT); + + /***************************************************************************/ + /* Free all internal strings then the header itself. */ + /***************************************************************************/ + addl_info = dlist_pop_last(&event->additional_info); + while (addl_info != NULL) + { + EVEL_DEBUG("Freeing Additional Info (%s, %s)", + addl_info->name, + addl_info->value); + free(addl_info->name); + free(addl_info->value); + free(addl_info); + addl_info = dlist_pop_last(&event->additional_info); + } + free(event->alarm_condition); + free(event->specific_problem); + evel_free_option_string(&event->category); + evel_free_option_string(&event->alarm_interface_a); + evel_free_header(&event->header); + + EVEL_EXIT(); +} diff --git a/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_heartbeat_fields.c b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_heartbeat_fields.c new file mode 100644 index 0000000..872af1f --- /dev/null +++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_heartbeat_fields.c @@ -0,0 +1,269 @@ +/*************************************************************************//** + * + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************/ + +/**************************************************************************//** + * @file + * Implementation of EVEL functions relating to Heartbeat fields. + * + ****************************************************************************/ + +#include +#include +#include + +#include "evel.h" +#include "evel_throttle.h" + +/**************************************************************************//** + * Create a new Heartbeat fields event. + * + * @note The mandatory fields on the Heartbeat fields must be supplied to + * this factory function and are immutable once set. Optional fields + * have explicit setter functions, but again values may only be set + * once so that the event has immutable properties. + * @param event_name Unique Event Name confirming Domain AsdcModel Description + * @param event_id A universal identifier of the event for: troubleshooting correlation, analysis, etc + * @param vendor_id The vendor id to encode in the event instance id. + * @param event_id The vendor event id to encode in the event instance id. + * @returns pointer to the newly manufactured ::EVENT_HEARTBEAT_FIELD. If the event + * is not used (i.e. posted) it must be released using + * ::evel_free_hrtbt_field. + * @retval NULL Failed to create the event. + *****************************************************************************/ +EVENT_HEARTBEAT_FIELD * evel_new_heartbeat_field(int interval,const char* ev_name, const char *ev_id) +{ + EVENT_HEARTBEAT_FIELD * event = NULL; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(interval > 0); + + /***************************************************************************/ + /* Allocate the Heartbeat fields event. */ + /***************************************************************************/ + event = malloc(sizeof(EVENT_HEARTBEAT_FIELD)); + if (event == NULL) + { + log_error_state("Out of memory"); + goto exit_label; + } + memset(event, 0, sizeof(EVENT_HEARTBEAT_FIELD)); + EVEL_DEBUG("New Heartbeat fields event is at %lp", event); + + /***************************************************************************/ + /* Initialize the header & the Heartbeat fields fields. */ + /***************************************************************************/ + evel_init_header_nameid(&event->header,ev_name,ev_id); + event->header.event_domain = EVEL_DOMAIN_HEARTBEAT_FIELD; + event->major_version = EVEL_HEARTBEAT_FIELD_MAJOR_VERSION; + event->minor_version = EVEL_HEARTBEAT_FIELD_MINOR_VERSION; + + event->heartbeat_interval = interval; + dlist_initialize(&event->additional_info); + +exit_label: + + EVEL_EXIT(); + return event; +} + +/**************************************************************************//** + * Add a name/value pair to the Heartbeat fields, under the additionalFields array. + * + * The name and value are null delimited ASCII strings. The library takes + * a copy so the caller does not have to preserve values after the function + * returns. + * + * @param event Pointer to the Heartbeat fields event. + * @param name ASCIIZ string with the field's name. The caller does not + * need to preserve the value once the function returns. + * @param value ASCIIZ string with the field's value. The caller does not + * need to preserve the value once the function returns. + *****************************************************************************/ +void evel_hrtbt_field_addl_field_add(EVENT_HEARTBEAT_FIELD * const event, + const char * const name, + const char * const value) +{ + OTHER_FIELD * nv_pair = NULL; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(event != NULL); + assert(event->header.event_domain == EVEL_DOMAIN_HEARTBEAT_FIELD); + assert(name != NULL); + assert(value != NULL); + + EVEL_DEBUG("Adding name=%s value=%s", name, value); + nv_pair = malloc(sizeof(OTHER_FIELD)); + assert(nv_pair != NULL); + nv_pair->name = strdup(name); + nv_pair->value = strdup(value); + assert(nv_pair->name != NULL); + assert(nv_pair->value != NULL); + + dlist_push_last(&event->additional_info, nv_pair); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Interval property of the Heartbeat fields event. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param event Pointer to the Heartbeat fields event. + * @param product_id The vendor product id to be set. ASCIIZ string. The + * caller does not need to preserve the value once the + * function returns. + *****************************************************************************/ +void evel_hrtbt_interval_set(EVENT_HEARTBEAT_FIELD * const event, + const int interval) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions and call evel_set_option_string. */ + /***************************************************************************/ + assert(event != NULL); + assert(event->header.event_domain == EVEL_DOMAIN_HEARTBEAT_FIELD); + assert(interval > 0); + + event->heartbeat_interval = interval; + EVEL_EXIT(); +} + + +/**************************************************************************//** + * Encode the Heartbeat fields in JSON according to AT&T's schema for the + * event type. + * + * @param jbuf Pointer to the ::EVEL_JSON_BUFFER to encode into. + * @param event Pointer to the ::EVENT_HEADER to encode. + *****************************************************************************/ +void evel_json_encode_hrtbt_field(EVEL_JSON_BUFFER * const jbuf, + EVENT_HEARTBEAT_FIELD * const event) +{ + OTHER_FIELD * nv_pair = NULL; + DLIST_ITEM * dlist_item = NULL; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(event != NULL); + assert(event->header.event_domain == EVEL_DOMAIN_HEARTBEAT_FIELD); + + evel_json_encode_header(jbuf, &event->header); + evel_json_open_named_object(jbuf, "heartbeatField"); + + /***************************************************************************/ + /* Mandatory fields */ + /***************************************************************************/ + evel_enc_version(jbuf, "heartbeatFieldsVersion", event->major_version,event->minor_version); + evel_enc_kv_int(jbuf, "heartbeatInterval", event->heartbeat_interval); + + /***************************************************************************/ + /* Optional fields */ + /***************************************************************************/ + + /***************************************************************************/ + /* Checkpoint, so that we can wind back if all fields are suppressed. */ + /***************************************************************************/ + evel_json_checkpoint(jbuf); + if (evel_json_open_opt_named_list(jbuf, "additionalFields")) + { + bool added = false; + + dlist_item = dlist_get_first(&event->additional_info); + while (dlist_item != NULL) + { + nv_pair = (OTHER_FIELD *) dlist_item->item; + assert(nv_pair != NULL); + + if (!evel_throttle_suppress_nv_pair(jbuf->throttle_spec, + "additionalFields", + nv_pair->name)) + { + evel_json_open_object(jbuf); + evel_enc_kv_string(jbuf, "name", nv_pair->name); + evel_enc_kv_string(jbuf, "value", nv_pair->value); + evel_json_close_object(jbuf); + added = true; + } + dlist_item = dlist_get_next(dlist_item); + } + evel_json_close_list(jbuf); + + /*************************************************************************/ + /* If we've not written anything, rewind to before we opened the list. */ + /*************************************************************************/ + if (!added) + { + evel_json_rewind(jbuf); + } + } + + evel_json_close_object(jbuf); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Free a Heartbeat fields event. + * + * Free off the event supplied. Will free all the contained allocated memory. + * + * @note It does not free the event itself, since that may be part of a larger + * structure. + *****************************************************************************/ +void evel_free_hrtbt_field(EVENT_HEARTBEAT_FIELD * const event) +{ + OTHER_FIELD * nv_pair = NULL; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(event != NULL); + assert(event->header.event_domain == EVEL_DOMAIN_HEARTBEAT_FIELD); + + /***************************************************************************/ + /* Free all internal strings then the header itself. */ + /***************************************************************************/ + nv_pair = dlist_pop_last(&event->additional_info); + while (nv_pair != NULL) + { + EVEL_DEBUG("Freeing Other Field (%s, %s)", nv_pair->name, nv_pair->value); + free(nv_pair->name); + free(nv_pair->value); + free(nv_pair); + nv_pair = dlist_pop_last(&event->additional_info); + } + evel_free_header(&event->header); + + EVEL_EXIT(); +} diff --git a/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_internal.h b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_internal.h new file mode 100644 index 0000000..46f71af --- /dev/null +++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_internal.h @@ -0,0 +1,858 @@ +/*************************************************************************//** + * + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************/ +/**************************************************************************//** + * @file + * EVEL internal definitions. + * + * These are internal definitions which need to be shared between modules + * within the library but are not intended for external consumption. + * + ****************************************************************************/ + +#ifndef EVEL_INTERNAL_INCLUDED +#define EVEL_INTERNAL_INCLUDED + +#include "evel.h" + +/*****************************************************************************/ +/* Define some type-safe min/max macros. */ +/*****************************************************************************/ +#define max(a,b) \ + ({ __typeof__ (a) _a = (a); \ + __typeof__ (b) _b = (b); \ + _a > _b ? _a : _b; }) + +#define min(a,b) \ + ({ __typeof__ (a) _a = (a); \ + __typeof__ (b) _b = (b); \ + _a < _b ? _a : _b; }) + + +/**************************************************************************//** + * Compile-time assertion. + *****************************************************************************/ +#define EVEL_CT_ASSERT(X) switch (0) {case 0: case (X):;} + +/**************************************************************************//** + * The Functional Role of the equipment represented by this VNF. + *****************************************************************************/ +extern char * functional_role; + +/**************************************************************************//** + * The type of equipment represented by this VNF. + *****************************************************************************/ +extern EVEL_SOURCE_TYPES event_source_type; + +/**************************************************************************//** + * A chunk of memory used in the cURL functions. + *****************************************************************************/ +typedef struct memory_chunk { + char * memory; + size_t size; +} MEMORY_CHUNK; + +/**************************************************************************//** + * Global commands that may be sent to the Event Handler thread. + *****************************************************************************/ +typedef enum { + EVT_CMD_TERMINATE, + EVT_CMD_MAX_COMMANDS +} EVT_HANDLER_COMMAND; + +/**************************************************************************//** + * State of the Event Handler thread. + *****************************************************************************/ +typedef enum { + EVT_HANDLER_UNINITIALIZED, /** The library cannot handle events. */ + EVT_HANDLER_INACTIVE, /** The event handler thread not started. */ + EVT_HANDLER_ACTIVE, /** The event handler thread is started. */ + EVT_HANDLER_REQUEST_TERMINATE, /** Initial stages of shutdown. */ + EVT_HANDLER_TERMINATING, /** The ring-buffer is being depleted. */ + EVT_HANDLER_TERMINATED, /** The library is exited. */ + EVT_HANDLER_MAX_STATES /** Maximum number of valid states. */ +} EVT_HANDLER_STATE; + +/**************************************************************************//** + * Internal event. + * Pseudo-event used for routing internal commands. + *****************************************************************************/ +typedef struct event_internal { + EVENT_HEADER header; + EVT_HANDLER_COMMAND command; +} EVENT_INTERNAL; + +/**************************************************************************//** + * Suppressed NV pairs list entry. + * JSON equivalent field: suppressedNvPairs + *****************************************************************************/ +typedef struct evel_suppressed_nv_pairs { + + /***************************************************************************/ + /* Mandatory fields */ + /* JSON equivalent field: nvPairFieldName */ + /***************************************************************************/ + char * nv_pair_field_name; + + /***************************************************************************/ + /* Optional fields */ + /* JSON equivalent field: suppressedNvPairNames */ + /* Type of each list entry: char * */ + /***************************************************************************/ + DLIST suppressed_nv_pair_names; + + /***************************************************************************/ + /* Hash table containing suppressed_nv_pair_names as keys. */ + /***************************************************************************/ + struct hsearch_data * hash_nv_pair_names; + +} EVEL_SUPPRESSED_NV_PAIRS; + +/**************************************************************************//** + * Event Throttling Specification for a domain which is in a throttled state. + * JSON equivalent object: eventThrottlingState + *****************************************************************************/ +typedef struct evel_throttle_spec { + + /***************************************************************************/ + /* List of field names to be suppressed. */ + /* JSON equivalent field: suppressedFieldNames */ + /* Type of each list entry: char * */ + /***************************************************************************/ + DLIST suppressed_field_names; + + /***************************************************************************/ + /* List of name-value pairs to be suppressed. */ + /* JSON equivalent field: suppressedNvPairsList */ + /* Type of each list entry: EVEL_SUPPRESSED_NV_PAIRS * */ + /***************************************************************************/ + DLIST suppressed_nv_pairs_list; + + /***************************************************************************/ + /* Hash table containing suppressed_nv_pair_names as keys. */ + /***************************************************************************/ + struct hsearch_data * hash_field_names; + + /***************************************************************************/ + /* Hash table containing nv_pair_field_name as keys, and */ + /* suppressed_nv_pairs_list as values. */ + /***************************************************************************/ + struct hsearch_data * hash_nv_pairs_list; + +} EVEL_THROTTLE_SPEC; + +/*****************************************************************************/ +/* RFC2822 format string for strftime. */ +/*****************************************************************************/ +#define EVEL_RFC2822_STRFTIME_FORMAT "%a, %d %b %Y %T %z" + +/*****************************************************************************/ +/* EVEL_JSON_BUFFER depth at which we throttle fields. */ +/*****************************************************************************/ +#define EVEL_THROTTLE_FIELD_DEPTH 3 + +/**************************************************************************//** + * Initialize the event handler. + * + * Primarily responsible for getting cURL ready for use. + * + * @param[in] event_api_url + * The URL where the Vendor Event Listener API is expected + * to be. + * @param[in] throt_api_url + * The URL where the Throttling API is expected to be. + * @param[in] username The username for the Basic Authentication of requests. + * @param[in] password The password for the Basic Authentication of requests. + * @param verbosity 0 for normal operation, positive values for chattier + * logs. + *****************************************************************************/ +EVEL_ERR_CODES event_handler_initialize(const char * const event_api_url, + const char * const throt_api_url, + const char * const username, + const char * const password, + int verbosity); + +/**************************************************************************//** + * Terminate the event handler. + * + * Shuts down the event handler thread in as clean a way as possible. Sets the + * global exit flag and then signals the thread to interrupt it since it's + * most likely waiting on the ring-buffer. + * + * Having achieved an orderly shutdown of the event handler thread, clean up + * the cURL library's resources cleanly. + * + * @return Status code. + * @retval ::EVEL_SUCCESS if everything OK. + * @retval One of ::EVEL_ERR_CODES if there was a problem. + *****************************************************************************/ +EVEL_ERR_CODES event_handler_terminate(); + +/**************************************************************************//** + * Run the event handler. + * + * Spawns the thread responsible for handling events and sending them to the + * API. + * + * @return Status code. + * @retval ::EVEL_SUCCESS if everything OK. + * @retval One of ::EVEL_ERR_CODES if there was a problem. + *****************************************************************************/ +EVEL_ERR_CODES event_handler_run(); + +/**************************************************************************//** + * Create a new internal event. + * + * @note The mandatory fields on the Fault must be supplied to this factory + * function and are immutable once set. Optional fields have explicit + * setter functions, but again values may only be set once so that the + * Fault has immutable properties. + * @param command The condition indicated by the event. + * @returns pointer to the newly manufactured ::EVENT_INTERNAL. If the event + * is not used (i.e. posted) it must be released using + * ::evel_free_event. + * @retval NULL Failed to create the event. + *****************************************************************************/ +EVENT_INTERNAL * evel_new_internal_event(EVT_HANDLER_COMMAND command,const char* ev_name, const char *ev_id); + +/**************************************************************************//** + * Free an internal event. + * + * Free off the event supplied. Will free all the contained* allocated memory. + * + * @note It does not free the internal event itself, since that may be part of + * a larger structure. + *****************************************************************************/ +void evel_free_internal_event(EVENT_INTERNAL * event); + +/*****************************************************************************/ +/* Structure to hold JSON buffer and associated tracking, as it is written. */ +/*****************************************************************************/ +typedef struct evel_json_buffer +{ + char * json; + int offset; + int max_size; + + /***************************************************************************/ + /* The working throttle specification, which can be NULL. */ + /***************************************************************************/ + EVEL_THROTTLE_SPEC * throttle_spec; + + /***************************************************************************/ + /* Current object/list nesting depth. */ + /***************************************************************************/ + int depth; + + /***************************************************************************/ + /* The checkpoint. */ + /***************************************************************************/ + int checkpoint; + +} EVEL_JSON_BUFFER; + +/**************************************************************************//** + * Encode the event as a JSON event object according to AT&T's schema. + * + * @param jbuf Pointer to the ::EVEL_JSON_BUFFER to encode into. + * @param event Pointer to the ::EVENT_HEADER to encode. + *****************************************************************************/ +void evel_json_encode_header(EVEL_JSON_BUFFER * jbuf, + EVENT_HEADER * event); + +/**************************************************************************//** + * Encode the fault in JSON according to AT&T's schema for the fault type. + * + * @param jbuf Pointer to the ::EVEL_JSON_BUFFER to encode into. + * @param event Pointer to the ::EVENT_HEADER to encode. + *****************************************************************************/ +void evel_json_encode_fault(EVEL_JSON_BUFFER * jbuf, + EVENT_FAULT * event); + +/**************************************************************************//** + * Encode the measurement as a JSON measurement. + * + * @param jbuf Pointer to the ::EVEL_JSON_BUFFER to encode into. + * @param event Pointer to the ::EVENT_HEADER to encode. + *****************************************************************************/ +void evel_json_encode_measurement(EVEL_JSON_BUFFER * jbuf, + EVENT_MEASUREMENT * event); + +/**************************************************************************//** + * Encode the Mobile Flow in JSON according to AT&T's schema for the event + * type. + * + * @param jbuf Pointer to the ::EVEL_JSON_BUFFER to encode into. + * @param event Pointer to the ::EVENT_HEADER to encode. + *****************************************************************************/ +void evel_json_encode_mobile_flow(EVEL_JSON_BUFFER * jbuf, + EVENT_MOBILE_FLOW * event); + +/**************************************************************************//** + * Encode the report as a JSON report. + * + * @param jbuf Pointer to the ::EVEL_JSON_BUFFER to encode into. + * @param event Pointer to the ::EVENT_HEADER to encode. + *****************************************************************************/ +void evel_json_encode_report(EVEL_JSON_BUFFER * jbuf, + EVENT_REPORT * event); + +/**************************************************************************//** + * Encode the Heartbeat fields in JSON according to AT&T's schema for the + * event type. + * + * @param jbuf Pointer to the ::EVEL_JSON_BUFFER to encode into. + * @param event Pointer to the ::EVENT_HEADER to encode. + *****************************************************************************/ +void evel_json_encode_hrtbt_field(EVEL_JSON_BUFFER * const jbuf, + EVENT_HEARTBEAT_FIELD * const event); + +/**************************************************************************//** + * Encode the Signaling in JSON according to AT&T's schema for the event type. + * + * @param jbuf Pointer to the ::EVEL_JSON_BUFFER to encode into. + * @param event Pointer to the ::EVENT_HEADER to encode. + *****************************************************************************/ +void evel_json_encode_signaling(EVEL_JSON_BUFFER * const jbuf, + EVENT_SIGNALING * const event); + +/**************************************************************************//** + * Encode the state change as a JSON state change. + * + * @param jbuf Pointer to the ::EVEL_JSON_BUFFER to encode into. + * @param state_change Pointer to the ::EVENT_STATE_CHANGE to encode. + *****************************************************************************/ +void evel_json_encode_state_change(EVEL_JSON_BUFFER * jbuf, + EVENT_STATE_CHANGE * state_change); + +/**************************************************************************//** + * Encode the Syslog in JSON according to AT&T's schema for the event type. + * + * @param jbuf Pointer to the ::EVEL_JSON_BUFFER to encode into. + * @param event Pointer to the ::EVENT_HEADER to encode. + *****************************************************************************/ +void evel_json_encode_syslog(EVEL_JSON_BUFFER * jbuf, + EVENT_SYSLOG * event); + +/**************************************************************************//** + * Encode the Other in JSON according to AT&T's schema for the event type. + * + * @param jbuf Pointer to the ::EVEL_JSON_BUFFER to encode into. + * @param event Pointer to the ::EVENT_HEADER to encode. + *****************************************************************************/ +void evel_json_encode_other(EVEL_JSON_BUFFER * jbuf, + EVENT_OTHER * event); + +/**************************************************************************//** + * Set the next event_sequence to use. + * + * @param sequence The next sequence number to use. + *****************************************************************************/ +void evel_set_next_event_sequence(const int sequence); + +/**************************************************************************//** + * Handle a JSON response from the listener, contained in a ::MEMORY_CHUNK. + * + * Tokenize the response, and decode any tokens found. + * + * @param chunk The memory chunk containing the response. + * @param post The memory chunk in which to place any resulting POST. + *****************************************************************************/ +void evel_handle_event_response(const MEMORY_CHUNK * const chunk, + MEMORY_CHUNK * const post); + +/**************************************************************************//** + * Initialize a ::EVEL_JSON_BUFFER. + * + * @param jbuf Pointer to the ::EVEL_JSON_BUFFER to initialise. + * @param json Pointer to the underlying working buffer to use. + * @param max_size Size of storage available in the JSON buffer. + * @param throttle_spec Pointer to throttle specification. Can be NULL. + *****************************************************************************/ +void evel_json_buffer_init(EVEL_JSON_BUFFER * jbuf, + char * const json, + const int max_size, + EVEL_THROTTLE_SPEC * throttle_spec); + +/**************************************************************************//** + * Encode a string key and string value to a ::EVEL_JSON_BUFFER. + * + * @param jbuf Pointer to working ::EVEL_JSON_BUFFER. + * @param key Pointer to the key to encode. + * @param option Pointer to holder of the corresponding value to encode. + * @return true if the key, value was added, false if it was suppressed. + *****************************************************************************/ +bool evel_enc_kv_opt_string(EVEL_JSON_BUFFER * jbuf, + const char * const key, + const EVEL_OPTION_STRING * const option); + +/**************************************************************************//** + * Encode a string key and string value to a ::EVEL_JSON_BUFFER. + * + * @param jbuf Pointer to working ::EVEL_JSON_BUFFER. + * @param key Pointer to the key to encode. + * @param value Pointer to the corresponding value to encode. + *****************************************************************************/ +void evel_enc_kv_string(EVEL_JSON_BUFFER * jbuf, + const char * const key, + const char * const value); + +/**************************************************************************//** + * Encode a string key and integer value to a ::EVEL_JSON_BUFFER. + * + * @param jbuf Pointer to working ::EVEL_JSON_BUFFER. + * @param key Pointer to the key to encode. + * @param option Pointer to holder of the corresponding value to encode. + * @return true if the key, value was added, false if it was suppressed. + *****************************************************************************/ +bool evel_enc_kv_opt_int(EVEL_JSON_BUFFER * jbuf, + const char * const key, + const EVEL_OPTION_INT * const option); + +/**************************************************************************//** + * Encode a string key and integer value to a ::EVEL_JSON_BUFFER. + * + * @param jbuf Pointer to working ::EVEL_JSON_BUFFER. + * @param key Pointer to the key to encode. + * @param value The corresponding value to encode. + *****************************************************************************/ +void evel_enc_kv_int(EVEL_JSON_BUFFER * jbuf, + const char * const key, + const int value); + +/**************************************************************************//** + * Encode a string key and double value to a ::EVEL_JSON_BUFFER. + * + * @param jbuf Pointer to working ::EVEL_JSON_BUFFER. + * @param key Pointer to the key to encode. + * @param option Pointer to holder of the corresponding value to encode. + * @return true if the key, value was added, false if it was suppressed. + *****************************************************************************/ +bool evel_enc_kv_opt_double(EVEL_JSON_BUFFER * jbuf, + const char * const key, + const EVEL_OPTION_DOUBLE * const option); + +/**************************************************************************//** + * Encode a string key and double value to a ::EVEL_JSON_BUFFER. + * + * @param jbuf Pointer to working ::EVEL_JSON_BUFFER. + * @param key Pointer to the key to encode. + * @param value The corresponding value to encode. + *****************************************************************************/ +void evel_enc_kv_double(EVEL_JSON_BUFFER * jbuf, + const char * const key, + const double value); + +/**************************************************************************//** + * Encode a string key and unsigned long long value to a ::EVEL_JSON_BUFFER. + * + * @param jbuf Pointer to working ::EVEL_JSON_BUFFER. + * @param key Pointer to the key to encode. + * @param option Pointer to holder of the corresponding value to encode. + * @return true if the key, value was added, false if it was suppressed. + *****************************************************************************/ +bool evel_enc_kv_opt_ull(EVEL_JSON_BUFFER * jbuf, + const char * const key, + const EVEL_OPTION_ULL * const option); + +/**************************************************************************//** + * Encode a string key and unsigned long long value to a ::EVEL_JSON_BUFFER. + * + * @param jbuf Pointer to working ::EVEL_JSON_BUFFER. + * @param key Pointer to the key to encode. + * @param value The corresponding value to encode. + *****************************************************************************/ +void evel_enc_kv_ull(EVEL_JSON_BUFFER * jbuf, + const char * const key, + const unsigned long long value); + +/**************************************************************************//** + * Encode a string key and time value to a ::EVEL_JSON_BUFFER. + * + * @param jbuf Pointer to working ::EVEL_JSON_BUFFER. + * @param key Pointer to the key to encode. + * @param option Pointer to holder of the corresponding value to encode. + * @return true if the key, value was added, false if it was suppressed. + *****************************************************************************/ +bool evel_enc_kv_opt_time(EVEL_JSON_BUFFER * jbuf, + const char * const key, + const EVEL_OPTION_TIME * const option); + +/**************************************************************************//** + * Encode a string key and time value to a ::EVEL_JSON_BUFFER. + * + * @param jbuf Pointer to working ::EVEL_JSON_BUFFER. + * @param key Pointer to the key to encode. + * @param time Pointer to the time to encode. + *****************************************************************************/ +void evel_enc_kv_time(EVEL_JSON_BUFFER * jbuf, + const char * const key, + const time_t * time); + +/**************************************************************************//** + * Encode a key and version. + * + * @param jbuf Pointer to working ::EVEL_JSON_BUFFER. + * @param key Pointer to the key to encode. + * @param major_version The major version to encode. + * @param minor_version The minor version to encode. + *****************************************************************************/ +void evel_enc_version(EVEL_JSON_BUFFER * jbuf, + const char * const key, + const int major_version, + const int minor_version); + +/**************************************************************************//** + * Add the key and opening bracket of an optional named list to a JSON buffer. + * + * @param jbuf Pointer to working ::EVEL_JSON_BUFFER. + * @param key Pointer to the key to encode. + * @return true if the list was opened, false if it was suppressed. + *****************************************************************************/ +bool evel_json_open_opt_named_list(EVEL_JSON_BUFFER * jbuf, + const char * const key); + +/**************************************************************************//** + * Add the key and opening bracket of a named list to a JSON buffer. + * + * @param jbuf Pointer to working ::EVEL_JSON_BUFFER. + * @param key Pointer to the key to encode. + *****************************************************************************/ +void evel_json_open_named_list(EVEL_JSON_BUFFER * jbuf, + const char * const key); + +/**************************************************************************//** + * Add the closing bracket of a list to a JSON buffer. + * + * @param jbuf Pointer to working ::EVEL_JSON_BUFFER. + *****************************************************************************/ +void evel_json_close_list(EVEL_JSON_BUFFER * jbuf); + +/**************************************************************************//** + * Encode a list item with format and param list to a ::EVEL_JSON_BUFFER. + * + * @param jbuf Pointer to working ::EVEL_JSON_BUFFER. + * @param format Format string in standard printf format. + * @param ... Variable parameters for format string. + *****************************************************************************/ +void evel_enc_list_item(EVEL_JSON_BUFFER * jbuf, + const char * const format, + ...); + +/**************************************************************************//** + * Add the opening bracket of an optional named object to a JSON buffer. + * + * @param jbuf Pointer to working ::EVEL_JSON_BUFFER. + * @param key Pointer to the key to encode. + *****************************************************************************/ +bool evel_json_open_opt_named_object(EVEL_JSON_BUFFER * jbuf, + const char * const key); + +/**************************************************************************//** + * Add the opening bracket of an object to a JSON buffer. + * + * @param jbuf Pointer to working ::EVEL_JSON_BUFFER. + * @param key Pointer to the key to encode. + * @return true if the object was opened, false if it was suppressed. + *****************************************************************************/ +void evel_json_open_named_object(EVEL_JSON_BUFFER * jbuf, + const char * const key); + +/**************************************************************************//** + * Add the opening bracket of an object to a JSON buffer. + * + * @param jbuf Pointer to working ::EVEL_JSON_BUFFER. + *****************************************************************************/ +void evel_json_open_object(EVEL_JSON_BUFFER * jbuf); + +/**************************************************************************//** + * Add the closing bracket of an object to a JSON buffer. + * + * @param jbuf Pointer to working ::EVEL_JSON_BUFFER. + *****************************************************************************/ +void evel_json_close_object(EVEL_JSON_BUFFER * jbuf); + +/**************************************************************************//** + * Add a checkpoint - a stake in the ground to which we can rewind. + * + * @param jbuf Pointer to working ::EVEL_JSON_BUFFER. + *****************************************************************************/ +void evel_json_checkpoint(EVEL_JSON_BUFFER * jbuf); + +/**************************************************************************//** + * Rewind to the latest checkoint. + * + * @param jbuf Pointer to working ::EVEL_JSON_BUFFER. + *****************************************************************************/ +void evel_json_rewind(EVEL_JSON_BUFFER * jbuf); + +/**************************************************************************//** + * Free the underlying resources of an ::EVEL_OPTION_STRING. + * + * @param option Pointer to the ::EVEL_OPTION_STRING. + *****************************************************************************/ +void evel_free_option_string(EVEL_OPTION_STRING * const option); + +/**************************************************************************//** + * Initialize an ::EVEL_OPTION_STRING to a not-set state. + * + * @param option Pointer to the ::EVEL_OPTION_STRING. + *****************************************************************************/ +void evel_init_option_string(EVEL_OPTION_STRING * const option); + +/**************************************************************************//** + * Set the value of an ::EVEL_OPTION_STRING. + * + * @param option Pointer to the ::EVEL_OPTION_STRING. + * @param value The value to set. + * @param description Description to be used in logging. + *****************************************************************************/ +void evel_set_option_string(EVEL_OPTION_STRING * const option, + const char * const value, + const char * const description); + +/**************************************************************************//** + * Force the value of an ::EVEL_OPTION_STRING. + * + * @param option Pointer to the ::EVEL_OPTION_STRING. + * @param value The value to set. + *****************************************************************************/ +void evel_force_option_string(EVEL_OPTION_STRING * const option, + const char * const value); + +/**************************************************************************//** + * Initialize an ::EVEL_OPTION_INT to a not-set state. + * + * @param option Pointer to the ::EVEL_OPTION_INT. + *****************************************************************************/ +void evel_init_option_int(EVEL_OPTION_INT * const option); + +/**************************************************************************//** + * Force the value of an ::EVEL_OPTION_INT. + * + * @param option Pointer to the ::EVEL_OPTION_INT. + * @param value The value to set. + *****************************************************************************/ +void evel_force_option_int(EVEL_OPTION_INT * const option, + const int value); + +/**************************************************************************//** + * Set the value of an ::EVEL_OPTION_INT. + * + * @param option Pointer to the ::EVEL_OPTION_INT. + * @param value The value to set. + * @param description Description to be used in logging. + *****************************************************************************/ +void evel_set_option_int(EVEL_OPTION_INT * const option, + const int value, + const char * const description); + +/**************************************************************************//** + * Initialize an ::EVEL_OPTION_DOUBLE to a not-set state. + * + * @param option Pointer to the ::EVEL_OPTION_DOUBLE. + *****************************************************************************/ +void evel_init_option_double(EVEL_OPTION_DOUBLE * const option); + +/**************************************************************************//** + * Force the value of an ::EVEL_OPTION_DOUBLE. + * + * @param option Pointer to the ::EVEL_OPTION_DOUBLE. + * @param value The value to set. + *****************************************************************************/ +void evel_force_option_double(EVEL_OPTION_DOUBLE * const option, + const double value); + +/**************************************************************************//** + * Set the value of an ::EVEL_OPTION_DOUBLE. + * + * @param option Pointer to the ::EVEL_OPTION_DOUBLE. + * @param value The value to set. + * @param description Description to be used in logging. + *****************************************************************************/ +void evel_set_option_double(EVEL_OPTION_DOUBLE * const option, + const double value, + const char * const description); + +/**************************************************************************//** + * Initialize an ::EVEL_OPTION_ULL to a not-set state. + * + * @param option Pointer to the ::EVEL_OPTION_ULL. + *****************************************************************************/ +void evel_init_option_ull(EVEL_OPTION_ULL * const option); + +/**************************************************************************//** + * Force the value of an ::EVEL_OPTION_ULL. + * + * @param option Pointer to the ::EVEL_OPTION_ULL. + * @param value The value to set. + *****************************************************************************/ +void evel_force_option_ull(EVEL_OPTION_ULL * const option, + const unsigned long long value); + +/**************************************************************************//** + * Set the value of an ::EVEL_OPTION_ULL. + * + * @param option Pointer to the ::EVEL_OPTION_ULL. + * @param value The value to set. + * @param description Description to be used in logging. + *****************************************************************************/ +void evel_set_option_ull(EVEL_OPTION_ULL * const option, + const unsigned long long value, + const char * const description); + +/**************************************************************************//** + * Initialize an ::EVEL_OPTION_TIME to a not-set state. + * + * @param option Pointer to the ::EVEL_OPTION_TIME. + *****************************************************************************/ +void evel_init_option_time(EVEL_OPTION_TIME * const option); + +/**************************************************************************//** + * Force the value of an ::EVEL_OPTION_TIME. + * + * @param option Pointer to the ::EVEL_OPTION_TIME. + * @param value The value to set. + *****************************************************************************/ +void evel_force_option_time(EVEL_OPTION_TIME * const option, + const time_t value); + +/**************************************************************************//** + * Set the value of an ::EVEL_OPTION_TIME. + * + * @param option Pointer to the ::EVEL_OPTION_TIME. + * @param value The value to set. + * @param description Description to be used in logging. + *****************************************************************************/ +void evel_set_option_time(EVEL_OPTION_TIME * const option, + const time_t value, + const char * const description); + +/**************************************************************************//** + * Map an ::EVEL_COUNTER_CRITICALITIES enum value to the equivalent string. + * + * @param criticality The criticality to convert. + * @returns The equivalent string. + *****************************************************************************/ +char * evel_criticality(const EVEL_COUNTER_CRITICALITIES criticality); + +/**************************************************************************//** + * Map an ::EVEL_SEVERITIES enum value to the equivalent string. + * + * @param severity The severity to convert. + * @returns The equivalent string. + *****************************************************************************/ +char * evel_severity(const EVEL_SEVERITIES severity); + +/**************************************************************************//** + * Map an ::EVEL_ALERT_ACTIONS enum value to the equivalent string. + * + * @param alert_action The alert_action to convert. + * @returns The equivalent string. + *****************************************************************************/ +char * evel_alert_action(const EVEL_ALERT_ACTIONS alert_action); + +/**************************************************************************//** + * Map an ::EVEL_ALERT_TYPES enum value to the equivalent string. + * + * @param alert_type The alert_type to convert. + * @returns The equivalent string. + *****************************************************************************/ +char * evel_alert_type(const EVEL_ALERT_TYPES alert_type); + +/**************************************************************************//** + * Map an ::EVEL_EVENT_DOMAINS enum value to the equivalent string. + * + * @param domain The domain to convert. + * @returns The equivalent string. + *****************************************************************************/ +char * evel_event_domain(const EVEL_EVENT_DOMAINS domain); + +/**************************************************************************//** + * Map an ::EVEL_EVENT_PRIORITIES enum value to the equivalent string. + * + * @param priority The priority to convert. + * @returns The equivalent string. + *****************************************************************************/ +char * evel_event_priority(const EVEL_EVENT_PRIORITIES priority); + +/**************************************************************************//** + * Map an ::EVEL_SOURCE_TYPES enum value to the equivalent string. + * + * @param source_type The source type to convert. + * @returns The equivalent string. + *****************************************************************************/ +char * evel_source_type(const EVEL_SOURCE_TYPES source_type); + +/**************************************************************************//** + * Map an ::EVEL_VF_STATUSES enum value to the equivalent string. + * + * @param vf_status The vf_status to convert. + * @returns The equivalent string. + *****************************************************************************/ +char * evel_vf_status(const EVEL_VF_STATUSES vf_status); + +/**************************************************************************//** + * Convert a ::EVEL_ENTITY_STATE to it's string form for JSON encoding. + * + * @param state The entity state to encode. + * + * @returns the corresponding string + *****************************************************************************/ +char * evel_entity_state(const EVEL_ENTITY_STATE state); + +/**************************************************************************//** + * Convert a ::EVEL_SERVICE_ENDPOINT_DESC to string form for JSON encoding. + * + * @param endpoint_desc endpoint description to encode. + * + * @returns the corresponding string + *****************************************************************************/ +char * evel_service_endpoint_desc(const EVEL_ENTITY_STATE endpoint_desc); + + +/**************************************************************************//** + * Initialize an ::EVEL_OPTION_INTHEADER_FIELDS to a not-set state. + * + * @param option Pointer to the ::EVEL_OPTION_INTHEADER_FIELDS. + *****************************************************************************/ +void evel_init_option_intheader(EVEL_OPTION_INTHEADER_FIELDS * const option); +/**************************************************************************//** + * Force the value of an ::EVEL_OPTION_INTHEADER_FIELDS. + * + * @param option Pointer to the ::EVEL_OPTION_INTHEADER_FIELDS. + * @param value The value to set. + *****************************************************************************/ +void evel_force_option_intheader(EVEL_OPTION_INTHEADER_FIELDS * const option, + const void* value); +/**************************************************************************//** + * Set the value of an ::EVEL_OPTION_INTHEADER_FIELDS. + * + * @param option Pointer to the ::EVEL_OPTION_INTHEADER_FIELDS. + * @param value The value to set. + * @param description Description to be used in logging. + *****************************************************************************/ +void evel_set_option_intheader(EVEL_OPTION_INTHEADER_FIELDS * const option, + const void * value, + const char * const description); +/**************************************************************************//** + * Free the underlying resources of an ::EVEL_OPTION_INTHEADER_FIELDS. + * + * @param option Pointer to the ::EVEL_OPTION_INTHEADER_FIELDS. + *****************************************************************************/ +void evel_free_option_intheader(EVEL_OPTION_INTHEADER_FIELDS * const option); + +#endif diff --git a/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_internal_event.c b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_internal_event.c new file mode 100644 index 0000000..cb56c88 --- /dev/null +++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_internal_event.c @@ -0,0 +1,113 @@ +/*************************************************************************//** + * + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************/ + +/**************************************************************************//** + * @file + * Implementation of EVEL functions relating to the internal events. + * + * Internal events are never expected to be sent to the JSON API but comply + * with interfaces for regular event types. The primary use-case is to enable + * the foreground processing to communicate with the background event handling + * processing in an orderly fashion. At present the only use is to initiate an + * orderly shutdown of the Event Handler thread. + * + ****************************************************************************/ + +#include +#include +#include + +#include "evel.h" +#include "evel_internal.h" + + +/**************************************************************************//** + * Create a new internal event. + * + * @note The mandatory fields on the Fault must be supplied to this factory + * function and are immutable once set. Optional fields have explicit + * setter functions, but again values may only be set once so that the + * Fault has immutable properties. + * @param command The condition indicated by the event. + * @param event_name Unique Event Name confirming Domain AsdcModel Description + * @param event_id A universal identifier of the event for: troubleshooting correlation, analysis, etc + * @returns pointer to the newly manufactured ::EVENT_INTERNAL. If the event + * is not used (i.e. posted) it must be released using + * ::evel_free_event. + * @retval NULL Failed to create the event. + *****************************************************************************/ +EVENT_INTERNAL * evel_new_internal_event(EVT_HANDLER_COMMAND command,const char* ev_name, const char *ev_id) +{ + EVENT_INTERNAL * event = NULL; + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(command < EVT_CMD_MAX_COMMANDS); + + /***************************************************************************/ + /* Allocate the fault. */ + /***************************************************************************/ + event = malloc(sizeof(EVENT_INTERNAL)); + if (event == NULL) + { + log_error_state("Out of memory"); + goto exit_label; + } + memset(event, 0, sizeof(EVENT_INTERNAL)); + EVEL_DEBUG("New internal event is at %lp", event); + + /***************************************************************************/ + /* Initialize the header & the event fields. */ + /***************************************************************************/ + evel_init_header_nameid(&event->header,ev_name,ev_id); + event->header.event_domain = EVEL_DOMAIN_INTERNAL; + event->command = command; + +exit_label: + EVEL_EXIT(); + return event; +} + +/**************************************************************************//** + * Free an internal event. + * + * Free off the event supplied. Will free all the contained allocated memory. + * + * @note It does not free the internal event itself, since that may be part of + * a larger structure. + *****************************************************************************/ +void evel_free_internal_event(EVENT_INTERNAL * event) +{ + + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. As an internal API we don't allow freeing NULL */ + /* events as we do on the public API. */ + /***************************************************************************/ + assert(event != NULL); + assert(event->header.event_domain == EVEL_DOMAIN_INTERNAL); + + /***************************************************************************/ + /* Free the header itself. */ + /***************************************************************************/ + evel_free_header(&event->header); + + EVEL_EXIT(); +} diff --git a/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_json_buffer.c b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_json_buffer.c new file mode 100644 index 0000000..b6026e2 --- /dev/null +++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_json_buffer.c @@ -0,0 +1,870 @@ +/*************************************************************************//** + * + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************/ + +/**************************************************************************//** + * @file + * Source module relating to internal EVEL_JSON_BUFFER manipulation functions. + * + ****************************************************************************/ + +#include +#include + +#include "evel_throttle.h" + +/*****************************************************************************/ +/* Local prototypes. */ +/*****************************************************************************/ +static char * evel_json_kv_comma(EVEL_JSON_BUFFER * jbuf); + +/**************************************************************************//** + * Initialize a ::EVEL_JSON_BUFFER. + * + * @param jbuf Pointer to the ::EVEL_JSON_BUFFER to initialise. + * @param json Pointer to the underlying working buffer to use. + * @param max_size Size of storage available in the JSON buffer. + * @param throttle_spec Pointer to throttle specification. Can be NULL. + *****************************************************************************/ +void evel_json_buffer_init(EVEL_JSON_BUFFER * jbuf, + char * const json, + const int max_size, + EVEL_THROTTLE_SPEC * throttle_spec) +{ + EVEL_ENTER(); + + assert(jbuf != NULL); + assert(json != NULL); + jbuf->json = json; + jbuf->max_size = max_size; + jbuf->offset = 0; + jbuf->throttle_spec = throttle_spec; + jbuf->depth = 0; + jbuf->checkpoint = -1; + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Encode an integer value to a JSON buffer. + * + * @param jbuf Pointer to working ::EVEL_JSON_BUFFER. + * @param value The integer to add to it. + *****************************************************************************/ +void evel_enc_int(EVEL_JSON_BUFFER * jbuf, + const int value) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(jbuf != NULL); + + jbuf->offset += snprintf(jbuf->json + jbuf->offset, + jbuf->max_size - jbuf->offset, + "%d", value); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Encode a string key and string value to a ::EVEL_JSON_BUFFER. + * + * @param jbuf Pointer to working ::EVEL_JSON_BUFFER. + * @param key Pointer to the key to encode. + * @param option Pointer to holder of the corresponding value to encode. + * @return true if the key, value was added, false if it was suppressed. + *****************************************************************************/ +bool evel_enc_kv_opt_string(EVEL_JSON_BUFFER * jbuf, + const char * const key, + const EVEL_OPTION_STRING * const option) +{ + bool added = false; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(option != NULL); + + if (option->is_set) + { + if ((jbuf->depth == EVEL_THROTTLE_FIELD_DEPTH) && + (jbuf->throttle_spec != NULL) && + evel_throttle_suppress_field(jbuf->throttle_spec, key)) + { + EVEL_INFO("Suppressed: %s, %s", key, option->value); + } + else + { + EVEL_DEBUG("Encoded: %s, %s", key, option->value); + evel_enc_kv_string(jbuf, key, option->value); + added = true; + } + } + + EVEL_EXIT(); + + return added; +} + +/**************************************************************************//** + * Encode a string key and string value to a ::EVEL_JSON_BUFFER. + * + * @param jbuf Pointer to working ::EVEL_JSON_BUFFER. + * @param key Pointer to the key to encode. + * @param value Pointer to the corresponding value to encode. + *****************************************************************************/ +void evel_enc_kv_string(EVEL_JSON_BUFFER * jbuf, + const char * const key, + const char * const value) +{ + int index; + int length; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(jbuf != NULL); + assert(key != NULL); + + jbuf->offset += snprintf(jbuf->json + jbuf->offset, + jbuf->max_size - jbuf->offset, + "%s\"%s\": \"", + evel_json_kv_comma(jbuf), + key); + + /***************************************************************************/ + /* We need to escape quotation marks and backslashes in the value. */ + /***************************************************************************/ + length = strlen(value); + + for (index = 0; index < length; index++) + { + /*************************************************************************/ + /* Drop out if no more space. */ + /*************************************************************************/ + if (jbuf->max_size - jbuf->offset < 2) + { + break; + } + + /*************************************************************************/ + /* Add an escape character if necessary, then write the character */ + /* itself. */ + /*************************************************************************/ + if ((value[index] == '\"') || (value[index] == '\\')) + { + jbuf->json[jbuf->offset] = '\\'; + jbuf->offset++; + } + + jbuf->json[jbuf->offset] = value[index]; + jbuf->offset++; + } + + jbuf->offset += snprintf(jbuf->json + jbuf->offset, + jbuf->max_size - jbuf->offset, + "\""); + + EVEL_EXIT(); +} + + +/**************************************************************************//** + * Encode a string key and integer value to a ::EVEL_JSON_BUFFER. + * + * @param jbuf Pointer to working ::EVEL_JSON_BUFFER. + * @param key Pointer to the key to encode. + * @param option Pointer to holder of the corresponding value to encode. + * @return true if the key, value was added, false if it was suppressed. + *****************************************************************************/ +bool evel_enc_kv_opt_int(EVEL_JSON_BUFFER * jbuf, + const char * const key, + const EVEL_OPTION_INT * const option) +{ + bool added = false; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(option != NULL); + + if (option->is_set) + { + if ((jbuf->depth == EVEL_THROTTLE_FIELD_DEPTH) && + (jbuf->throttle_spec != NULL) && + evel_throttle_suppress_field(jbuf->throttle_spec, key)) + { + EVEL_INFO("Suppressed: %s, %d", key, option->value); + } + else + { + EVEL_DEBUG("Encoded: %s, %d", key, option->value); + evel_enc_kv_int(jbuf, key, option->value); + added = true; + } + } + + EVEL_EXIT(); + + return added; +} + +/**************************************************************************//** + * Encode a string key and integer value to a ::EVEL_JSON_BUFFER. + * + * @param jbuf Pointer to working ::EVEL_JSON_BUFFER. + * @param key Pointer to the key to encode. + * @param value The corresponding value to encode. + *****************************************************************************/ +void evel_enc_kv_int(EVEL_JSON_BUFFER * jbuf, + const char * const key, + const int value) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(jbuf != NULL); + assert(key != NULL); + + jbuf->offset += snprintf(jbuf->json + jbuf->offset, + jbuf->max_size - jbuf->offset, + "%s\"%s\": %d", + evel_json_kv_comma(jbuf), + key, + value); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Encode a string key and json object value to a ::EVEL_JSON_BUFFER. + * + * @param jbuf Pointer to working ::EVEL_JSON_BUFFER. + * @param key Pointer to the key to encode. + * @param value The corresponding json string to encode. + *****************************************************************************/ +void evel_enc_kv_object(EVEL_JSON_BUFFER * jbuf, + const char * const key, + const char * value) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(jbuf != NULL); + assert(key != NULL); + + jbuf->offset += snprintf(jbuf->json + jbuf->offset, + jbuf->max_size - jbuf->offset, + "%s\"%s\": %s", + evel_json_kv_comma(jbuf), + key, + value); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Encode a string key and double value to a ::EVEL_JSON_BUFFER. + * + * @param jbuf Pointer to working ::EVEL_JSON_BUFFER. + * @param key Pointer to the key to encode. + * @param option Pointer to holder of the corresponding value to encode. + * @return true if the key, value was added, false if it was suppressed. + *****************************************************************************/ +bool evel_enc_kv_opt_double(EVEL_JSON_BUFFER * jbuf, + const char * const key, + const EVEL_OPTION_DOUBLE * const option) +{ + bool added = false; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(option != NULL); + + if (option->is_set) + { + if ((jbuf->depth == EVEL_THROTTLE_FIELD_DEPTH) && + (jbuf->throttle_spec != NULL) && + evel_throttle_suppress_field(jbuf->throttle_spec, key)) + { + EVEL_INFO("Suppressed: %s, %1f", key, option->value); + } + else + { + EVEL_DEBUG("Encoded: %s, %1f", key, option->value); + evel_enc_kv_double(jbuf, key, option->value); + added = true; + } + } + + EVEL_EXIT(); + + return added; +} + +/**************************************************************************//** + * Encode a string key and double value to a ::EVEL_JSON_BUFFER. + * + * @param jbuf Pointer to working ::EVEL_JSON_BUFFER. + * @param key Pointer to the key to encode. + * @param value The corresponding value to encode. + *****************************************************************************/ +void evel_enc_kv_double(EVEL_JSON_BUFFER * jbuf, + const char * const key, + const double value) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(jbuf != NULL); + assert(key != NULL); + + jbuf->offset += snprintf(jbuf->json + jbuf->offset, + jbuf->max_size - jbuf->offset, + "%s\"%s\": %1f", + evel_json_kv_comma(jbuf), + key, + value); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Encode a string key and unsigned long long value to a ::EVEL_JSON_BUFFER. + * + * @param jbuf Pointer to working ::EVEL_JSON_BUFFER. + * @param key Pointer to the key to encode. + * @param option Pointer to holder of the corresponding value to encode. + * @return true if the key, value was added, false if it was suppressed. + *****************************************************************************/ +bool evel_enc_kv_opt_ull(EVEL_JSON_BUFFER * jbuf, + const char * const key, + const EVEL_OPTION_ULL * const option) +{ + bool added = false; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(option != NULL); + + if (option->is_set) + { + if ((jbuf->depth == EVEL_THROTTLE_FIELD_DEPTH) && + (jbuf->throttle_spec != NULL) && + evel_throttle_suppress_field(jbuf->throttle_spec, key)) + { + EVEL_INFO("Suppressed: %s, %1lu", key, option->value); + } + else + { + EVEL_DEBUG("Encoded: %s, %1lu", key, option->value); + evel_enc_kv_ull(jbuf, key, option->value); + added = true; + } + } + + EVEL_EXIT(); + + return added; +} + +/**************************************************************************//** + * Encode a string key and unsigned long long value to a ::EVEL_JSON_BUFFER. + * + * @param jbuf Pointer to working ::EVEL_JSON_BUFFER. + * @param key Pointer to the key to encode. + * @param value The corresponding value to encode. + *****************************************************************************/ +void evel_enc_kv_ull(EVEL_JSON_BUFFER * jbuf, + const char * const key, + const unsigned long long value) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(jbuf != NULL); + assert(key != NULL); + + jbuf->offset += snprintf(jbuf->json + jbuf->offset, + jbuf->max_size - jbuf->offset, + "%s\"%s\": %llu", + evel_json_kv_comma(jbuf), + key, + value); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Encode a string key and time value to a ::EVEL_JSON_BUFFER. + * + * @param jbuf Pointer to working ::EVEL_JSON_BUFFER. + * @param key Pointer to the key to encode. + * @param option Pointer to holder of the corresponding value to encode. + * @return true if the key, value was added, false if it was suppressed. + *****************************************************************************/ +bool evel_enc_kv_opt_time(EVEL_JSON_BUFFER * jbuf, + const char * const key, + const EVEL_OPTION_TIME * const option) +{ + bool added = false; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(option != NULL); + + if (option->is_set) + { + if ((jbuf->depth == EVEL_THROTTLE_FIELD_DEPTH) && + (jbuf->throttle_spec != NULL) && + evel_throttle_suppress_field(jbuf->throttle_spec, key)) + { + EVEL_INFO("Suppressed time: %s", key); + } + else + { + EVEL_DEBUG("Encoded time: %s", key); + evel_enc_kv_time(jbuf, key, &option->value); + added = true; + } + } + + EVEL_EXIT(); + + return added; +} + +/**************************************************************************//** + * Encode a string key and time value to a ::EVEL_JSON_BUFFER. + * + * @param jbuf Pointer to working ::EVEL_JSON_BUFFER. + * @param key Pointer to the key to encode. + * @param time Pointer to the time to encode. + *****************************************************************************/ +void evel_enc_kv_time(EVEL_JSON_BUFFER * jbuf, + const char * const key, + const time_t * time) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(jbuf != NULL); + assert(key != NULL); + assert(time != NULL); + + jbuf->offset += snprintf(jbuf->json + jbuf->offset, + jbuf->max_size - jbuf->offset, + "%s\"%s\": \"", + evel_json_kv_comma(jbuf), + key); + jbuf->offset += strftime(jbuf->json + jbuf->offset, + jbuf->max_size - jbuf->offset, + EVEL_RFC2822_STRFTIME_FORMAT, + localtime(time)); + jbuf->offset += snprintf(jbuf->json + jbuf->offset, + jbuf->max_size - jbuf->offset, + "\""); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Encode a key and version. + * + * @param jbuf Pointer to working ::EVEL_JSON_BUFFER. + * @param key Pointer to the key to encode. + * @param major_version The major version to encode. + * @param minor_version The minor version to encode. + *****************************************************************************/ +void evel_enc_version(EVEL_JSON_BUFFER * jbuf, + const char * const key, + const int major_version, + const int minor_version) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(jbuf != NULL); + assert(key != NULL); + + evel_enc_kv_int(jbuf, key, major_version); + if (minor_version != 0) + { + jbuf->offset += snprintf(jbuf->json + jbuf->offset, + jbuf->max_size - jbuf->offset, + ".%d", + minor_version); + } + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Add the key and opening bracket of an optional named list to a JSON buffer. + * + * @param jbuf Pointer to working ::EVEL_JSON_BUFFER. + * @param key Pointer to the key to encode. + * @return true if the list was opened, false if it was suppressed. + *****************************************************************************/ +bool evel_json_open_opt_named_list(EVEL_JSON_BUFFER * jbuf, + const char * const key) +{ + bool opened = false; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(jbuf != NULL); + assert(key != NULL); + + if ((jbuf->depth == EVEL_THROTTLE_FIELD_DEPTH) && + (jbuf->throttle_spec != NULL) && + evel_throttle_suppress_field(jbuf->throttle_spec, key)) + { + EVEL_INFO("Suppressed: %s", key); + opened = false; + } + else + { + evel_json_open_named_list(jbuf, key); + opened = true; + } + + EVEL_EXIT(); + + return opened; +} + +/**************************************************************************//** + * Add the key and opening bracket of a named list to a JSON buffer. + * + * @param jbuf Pointer to working ::EVEL_JSON_BUFFER. + * @param key Pointer to the key to encode. + *****************************************************************************/ +void evel_json_open_named_list(EVEL_JSON_BUFFER * jbuf, + const char * const key) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(jbuf != NULL); + assert(key != NULL); + + jbuf->offset += snprintf(jbuf->json + jbuf->offset, + jbuf->max_size - jbuf->offset, + "%s\"%s\": [", + evel_json_kv_comma(jbuf), + key); + jbuf->depth++; + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Add the closing bracket of a list to a JSON buffer. + * + * @param jbuf Pointer to working ::EVEL_JSON_BUFFER. + *****************************************************************************/ +void evel_json_close_list(EVEL_JSON_BUFFER * jbuf) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(jbuf != NULL); + + jbuf->offset += snprintf(jbuf->json + jbuf->offset, + jbuf->max_size - jbuf->offset, + "]"); + jbuf->depth--; + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Encode a list item with format and param list to a ::EVEL_JSON_BUFFER. + * + * @param jbuf Pointer to working ::EVEL_JSON_BUFFER. + * @param format Format string in standard printf format. + * @param ... Variable parameters for format string. + *****************************************************************************/ +void evel_enc_list_item(EVEL_JSON_BUFFER * jbuf, + const char * const format, + ...) +{ + va_list largs; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(jbuf != NULL); + assert(format != NULL); + + /***************************************************************************/ + /* Add a comma unless we're at the start of the list. */ + /***************************************************************************/ + if (jbuf->json[jbuf->offset - 1] != '[') + { + jbuf->offset += snprintf(jbuf->json + jbuf->offset, + jbuf->max_size - jbuf->offset, + ", "); + } + + va_start(largs, format); + jbuf->offset += vsnprintf(jbuf->json + jbuf->offset, + jbuf->max_size - jbuf->offset, + format, + largs); + va_end(largs); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Add the opening bracket of an optional named object to a JSON buffer. + * + * @param jbuf Pointer to working ::EVEL_JSON_BUFFER. + * @param key Pointer to the key to encode. + *****************************************************************************/ +bool evel_json_open_opt_named_object(EVEL_JSON_BUFFER * jbuf, + const char * const key) +{ + bool opened = false; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(jbuf != NULL); + assert(key != NULL); + + if ((jbuf->depth == EVEL_THROTTLE_FIELD_DEPTH) && + (jbuf->throttle_spec != NULL) && + evel_throttle_suppress_field(jbuf->throttle_spec, key)) + { + EVEL_INFO("Suppressed: %s", key); + opened = false; + } + else + { + evel_json_open_named_object(jbuf, key); + opened = true; + } + + EVEL_EXIT(); + + return opened; +} + +/**************************************************************************//** + * Add the opening bracket of an object to a JSON buffer. + * + * @param jbuf Pointer to working ::EVEL_JSON_BUFFER. + * @param key Pointer to the key to encode. + * @return true if the object was opened, false if it was suppressed. + *****************************************************************************/ +void evel_json_open_named_object(EVEL_JSON_BUFFER * jbuf, + const char * const key) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(jbuf != NULL); + assert(key != NULL); + + jbuf->offset += snprintf(jbuf->json + jbuf->offset, + jbuf->max_size - jbuf->offset, + "%s\"%s\": {", + evel_json_kv_comma(jbuf), + key); + jbuf->depth++; + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Add the opening bracket of an object to a JSON buffer. + * + * @param jbuf Pointer to working ::EVEL_JSON_BUFFER. + *****************************************************************************/ +void evel_json_open_object(EVEL_JSON_BUFFER * jbuf) +{ + char * comma; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(jbuf != NULL); + + if ((jbuf->offset != 0) && (jbuf->json[jbuf->offset-1] == '}')) + { + comma = ", "; + } + else + { + comma = ""; + } + + jbuf->offset += snprintf(jbuf->json + jbuf->offset, + jbuf->max_size - jbuf->offset, + "%s{", + comma); + jbuf->depth++; + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Add the closing bracket of an object to a JSON buffer. + * + * @param jbuf Pointer to working ::EVEL_JSON_BUFFER. + *****************************************************************************/ +void evel_json_close_object(EVEL_JSON_BUFFER * jbuf) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(jbuf != NULL); + + jbuf->offset += snprintf(jbuf->json + jbuf->offset, + jbuf->max_size - jbuf->offset, + "}"); + jbuf->depth--; + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Determine whether to add a comma when adding a key-value pair. + * + * @param jbuf Pointer to working ::EVEL_JSON_BUFFER. + * @returns A string containing the comma if it is required. + *****************************************************************************/ +char * evel_json_kv_comma(EVEL_JSON_BUFFER * jbuf) +{ + char * result; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(jbuf != NULL); + + if ((jbuf->offset == 0) || + (jbuf->json[jbuf->offset-1] == '{') || + (jbuf->json[jbuf->offset-1] == '[')) + { + result = ""; + } + else + { + result = ", "; + } + + EVEL_EXIT(); + + return result; +} + +/**************************************************************************//** + * Add a checkpoint - a stake in the ground to which we can rewind. + * + * @param jbuf Pointer to working ::EVEL_JSON_BUFFER. + *****************************************************************************/ +void evel_json_checkpoint(EVEL_JSON_BUFFER * jbuf) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(jbuf != NULL); + + /***************************************************************************/ + /* Store the current offset. */ + /***************************************************************************/ + jbuf->checkpoint = jbuf->offset; + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Rewind to the latest checkoint. + * + * @param jbuf Pointer to working ::EVEL_JSON_BUFFER. + *****************************************************************************/ +void evel_json_rewind(EVEL_JSON_BUFFER * jbuf) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(jbuf != NULL); + assert(jbuf->checkpoint >= 0); + assert(jbuf->checkpoint <= jbuf->offset); + + /***************************************************************************/ + /* Reinstate the offset from the last checkpoint. */ + /***************************************************************************/ + jbuf->offset = jbuf->checkpoint; + jbuf->checkpoint = -1; + + EVEL_EXIT(); +} diff --git a/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_jsonobject.c b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_jsonobject.c new file mode 100644 index 0000000..caf1a1e --- /dev/null +++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_jsonobject.c @@ -0,0 +1,446 @@ +/*************************************************************************//** + * + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************/ + +/**************************************************************************//** + * @file + * Implementation of EVEL functions relating to json_object. + * + ****************************************************************************/ + +#include +#include +#include + +#include "jsmn.h" +#include "evel.h" +#include "evel_internal.h" + +/**************************************************************************//** + * Create a new json object. + * + * @note The mandatory fields on the Other must be supplied to this factory + * function and are immutable once set. Optional fields have explicit + * setter functions, but again values may only be set once so that the + * Other has immutable properties. + * @param name name of the object. + * @returns pointer to the newly manufactured ::EVEL_JSON_OBJECT. + * not used (i.e. posted) it must be released using ::evel_free_jsonobject. + * @retval NULL Failed to create the json object. + *****************************************************************************/ +EVEL_JSON_OBJECT * evel_new_jsonobject(const char *const name) +{ + EVEL_JSON_OBJECT *jobj = NULL; + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(name != NULL); + + /***************************************************************************/ + /* Allocate the json object. */ + /***************************************************************************/ + jobj = malloc(sizeof(EVEL_JSON_OBJECT)); + if (jobj == NULL) + { + log_error_state("Out of memory"); + goto exit_label; + } + memset(jobj, 0, sizeof(EVEL_JSON_OBJECT)); + EVEL_DEBUG("New json object is at %lp", jobj); + + /***************************************************************************/ + /* Initialize the fields. Optional string values are */ + /* uninitialized (NULL). */ + /***************************************************************************/ + jobj->object_name = strdup(name); + evel_init_option_string(&jobj->objectschema); + evel_init_option_string(&jobj->objectschemaurl); + evel_init_option_string(&jobj->nfsubscribedobjname); + evel_init_option_string(&jobj->nfsubscriptionid); + dlist_initialize(&jobj->jsonobjectinstances); + +exit_label: + EVEL_EXIT(); + return jobj; +} + + +/**************************************************************************//** + * Create a new json object instance. + * + * @note The mandatory fields on the Other must be supplied to this factory + * function and are immutable once set. Optional fields have explicit + * setter functions, but again values may only be set once so that the + * Other has immutable properties. + * @param yourjson json string. + * @returns pointer to the newly manufactured ::EVEL_JSON_OBJECT_INSTANCE. + * not used (i.e. posted) it must be released using ::evel_free_jsonobjectinstance. + * @retval NULL Failed to create the json object instance. + *****************************************************************************/ +EVEL_JSON_OBJECT_INSTANCE * evel_new_jsonobjinstance(const char *const yourjson) +{ + EVEL_JSON_OBJECT_INSTANCE *jobjinst = NULL; + jsmntok_t *key; + int resultCode; + jsmn_parser p; + jsmntok_t tokens[MAX_JSON_TOKENS]; // a number >= total number of tokens + int len=0; + + + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(yourjson != NULL); + len = strlen(yourjson)+1; + assert(len > 0); + + /***************************************************************************/ + /* Validate JSON for json object + /***************************************************************************/ + jsmn_init(&p); + resultCode = jsmn_parse(&p, yourjson, len, tokens, sizeof(tokens)/sizeof(tokens[0])); + if( resultCode < 0 ){ + log_error_state("Failed to parse json for object"); + goto exit_label; + } + + if (resultCode < 1 || tokens[0].type != JSMN_OBJECT) { + log_error_state("Error json object expected"); + goto exit_label; + } + + /***************************************************************************/ + /* Allocate the json object. */ + /***************************************************************************/ + jobjinst = malloc(sizeof(EVEL_JSON_OBJECT_INSTANCE)); + if (jobjinst == NULL) + { + log_error_state("Out of memory"); + goto exit_label; + } + memset(jobjinst, 0, sizeof(EVEL_JSON_OBJECT_INSTANCE)); + + /***************************************************************************/ + /* Initialize the fields. Optional key values are */ + /* uninitialized (NULL). */ + /***************************************************************************/ + jobjinst->jsonstring = strdup(yourjson); + dlist_initialize(&jobjinst->object_keys); + +exit_label: + EVEL_EXIT(); + return jobjinst; +} + + +/**************************************************************************//** + * Create a new internal key. + * + * @note The mandatory fields on the Other must be supplied to this factory + * function and are immutable once set. Optional fields have explicit + * setter functions, but again values may only be set once so that the + * Other has immutable properties. + * @param keyname name of the key. + * @returns pointer to the newly manufactured ::EVEL_INTERNAL_KEY. + * not used (i.e. posted) it must be released using ::evel_free_internal_key. + * @retval NULL Failed to create the internal key. + *****************************************************************************/ +EVEL_INTERNAL_KEY * evel_new_internal_key(char *keyname) +{ + EVEL_INTERNAL_KEY *keyinst = NULL; + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(keyname != NULL); + + /***************************************************************************/ + /* Allocate the key object. */ + /***************************************************************************/ + keyinst = malloc(sizeof(EVEL_INTERNAL_KEY)); + if (keyinst == NULL) + { + log_error_state("Out of memory"); + goto exit_label; + } + memset(keyinst, 0, sizeof(EVEL_INTERNAL_KEY)); + keyinst->keyname = strdup(keyname); + + /***************************************************************************/ + /* Optional string values are uninitialized (NULL). */ + /***************************************************************************/ + evel_init_option_int(&keyinst->keyorder); + evel_init_option_string(&keyinst->keyvalue); + +exit_label: + EVEL_EXIT(); + return keyinst; +} + +/**************************************************************************//** + * Set the keyorder of the internal key instance. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param int keyorder + *****************************************************************************/ +void evel_internal_key_keyorder_set(EVEL_INTERNAL_KEY * pinst, const int keyorder) +{ + assert (pinst != NULL); + evel_set_option_int(&pinst->keyorder,keyorder,"Key order"); +} + +/**************************************************************************//** + * Set the keyvalue of the internal key instance. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param string keyvalue + *****************************************************************************/ +void evel_internal_key_keyvalue_set(EVEL_INTERNAL_KEY * pinst, const char * const keyval) +{ + assert (pinst != NULL); + evel_set_option_string(&pinst->keyvalue,keyval,"Key Value"); +} + +/**************************************************************************//** + * Set the string values of json object + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param string object schema + *****************************************************************************/ +void evel_jsonobject_objectschema_set(EVEL_JSON_OBJECT * pinst, const char * const objectschema) +{ + assert (pinst != NULL); + evel_set_option_string(&pinst->objectschema,objectschema,"Object Schema"); +} + +/**************************************************************************//** + * Set the string values of json object + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param string object schema url + *****************************************************************************/ +void evel_jsonobject_objectschemaurl_set(EVEL_JSON_OBJECT * pinst, const char * const objectschemaurl) +{ + assert (pinst != NULL); + evel_set_option_string(&pinst->objectschemaurl,objectschemaurl,"Object Schema URL"); +} + +/**************************************************************************//** + * Set the string values of json object + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param string NF Subscribed object name + *****************************************************************************/ +void evel_jsonobject_nfsubscribedobjname_set(EVEL_JSON_OBJECT * pinst, const char * const nfsubscribedobjname) +{ + assert (pinst != NULL); + evel_set_option_string(&pinst->nfsubscribedobjname,nfsubscribedobjname,"NF Subscribed Object Name"); +} + +/**************************************************************************//** + * Set the string values of json object + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param string NF Subscription Id + *****************************************************************************/ +void evel_jsonobject_nfsubscriptionid_set(EVEL_JSON_OBJECT * pinst, const char * const nfsubscriptionid) +{ + assert (pinst != NULL); + evel_set_option_string(&pinst->nfsubscriptionid,nfsubscriptionid,"NF Subscription Id"); +} + +/**************************************************************************//** + * Set the Epoch time of the json object instance. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param unsigned long long epoch time + *****************************************************************************/ +void evel_epoch_microsec_set(EVEL_JSON_OBJECT_INSTANCE * pinst, const unsigned long long epmicrosec) +{ + assert(epmicrosec != 0 ); + pinst->objinst_epoch_microsec = epmicrosec; +} + +/**************************************************************************//** + * Add a json object instance to jsonObject list. + * + * The name and value are null delimited ASCII strings. The library takes + * a copy so the caller does not have to preserve values after the function + * returns. + * + * @param pobj Pointer to the Other. + * @param jinst Pointer to HashTable + *****************************************************************************/ +void evel_jsonobject_add_jsoninstance(EVEL_JSON_OBJECT * pobj, EVEL_JSON_OBJECT_INSTANCE *jinst) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(pobj != NULL); + assert(jinst != NULL); + + EVEL_DEBUG("Adding json object instance"); + + dlist_push_last(&pobj->jsonobjectinstances, jinst); + + EVEL_EXIT(); +} + + +/**************************************************************************//** + * Add a json object to jsonObject list. + * + * The name and value are null delimited ASCII strings. The library takes + * a copy so the caller does not have to preserve values after the function + * returns. + * + * @param other Pointer to the Other. + * @param jsonobj Pointer to json object + *****************************************************************************/ +void evel_jsonobjinst_add_objectkey(EVEL_JSON_OBJECT_INSTANCE * jsoninst, EVEL_INTERNAL_KEY *keyp) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(jsoninst != NULL); + assert(keyp != NULL); + + EVEL_DEBUG("Adding jsonObject instance"); + + dlist_push_last(&jsoninst->object_keys, keyp); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Free an internal key. + * + * Free off the internal key supplied. Will free all the contained allocated memory. + * + *****************************************************************************/ +void evel_free_internal_key(EVEL_INTERNAL_KEY * keyp) +{ + + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. As an internal API we don't allow freeing NULL */ + /* events as we do on the public API. */ + /***************************************************************************/ + assert(keyp != NULL); + + free(keyp->keyname); + evel_free_option_string(&keyp->keyvalue); + EVEL_EXIT(); +} + + +/**************************************************************************//** + * Free an json object instance. + * + * Free off the json object instance supplied. + * Will free all the contained allocated memory. + * + *****************************************************************************/ +void evel_free_jsonobjinst(EVEL_JSON_OBJECT_INSTANCE * objinst) +{ + EVEL_INTERNAL_KEY *other_field = NULL; + + EVEL_ENTER(); + assert(objinst != NULL); + assert(objinst->jsonstring != NULL); + + free(objinst->jsonstring); + + /***************************************************************************/ + /* Free all internal internal keys + /***************************************************************************/ + other_field = dlist_pop_last(&objinst->object_keys); + while (other_field != NULL) + { + EVEL_DEBUG("Freeing Object Instance Field (%s)", + other_field->keyname); + evel_free_internal_key(other_field); + other_field = dlist_pop_last(&objinst->object_keys); + } + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Free an json object. + * + * Free off the json object instance supplied. + * Will free all the contained allocated memory. + * + *****************************************************************************/ +void evel_free_jsonobject(EVEL_JSON_OBJECT * jsobj) +{ + EVEL_JSON_OBJECT_INSTANCE *other_field = NULL; + + EVEL_ENTER(); + assert(jsobj != NULL); + + free(jsobj->object_name); + evel_free_option_string(&jsobj->objectschema); + evel_free_option_string(&jsobj->objectschemaurl); + evel_free_option_string(&jsobj->nfsubscribedobjname); + evel_free_option_string(&jsobj->nfsubscriptionid); + + /***************************************************************************/ + /* Free all internal strings then the header itself. */ + /***************************************************************************/ + other_field = dlist_pop_last(&jsobj->jsonobjectinstances); + while (other_field != NULL) + { + EVEL_DEBUG("Freeing Object Instance Field (%s)", + other_field->jsonstring); + evel_free_jsonobjinst(other_field); + other_field = dlist_pop_last(&jsobj->jsonobjectinstances); + } + + EVEL_EXIT(); +} diff --git a/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_logging.c b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_logging.c new file mode 100644 index 0000000..5a44f07 --- /dev/null +++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_logging.c @@ -0,0 +1,167 @@ +/*************************************************************************//** + * + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************/ +/**************************************************************************//** + * @file + * Wrapper for event logging built on syslog. + * + ****************************************************************************/ + +#include +#include +#include +#include +#include + +#include + +#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] = ""; + + +/**************************************************************************//** + * 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 + * "" but will never be NULL. + * + * @returns Text error string. + * + * @note Must not be freed! + *****************************************************************************/ +const char * evel_error_string(void) +{ + return(evel_err_string); +} + +/***************************************************************************//* + * Store the formatted string into the static error string and log the error. + * + * @param format Error string in standard printf format. + * @param ... Variable parameters to be substituted into the format string. + *****************************************************************************/ +void log_error_state(char * format, ...) +{ + va_list largs; + + assert(format != NULL); + va_start(largs, format); + vsnprintf(evel_err_string, EVEL_MAX_ERROR_STRING_LEN, format, largs); + va_end(largs); + EVEL_ERROR("%s", evel_err_string); +} + + +/**************************************************************************//** + * Generate a debug log. + * + * Provides an interface to syslog with formatting of the nesting level + * so that it's easier to see function entry/exit. + * + * @param[in] level The debug level - see ::EVEL_LOG_LEVELS. + * @param[in] format The output formatting in printf style. + * @param[in] ... Variable arguments as specified in the format string. + *****************************************************************************/ +void log_debug(EVEL_LOG_LEVELS level, char * format, ...) +{ + va_list largs; + int priority; + char indent_fmt[1024]; + char *syslog_fmt = NULL; + + /***************************************************************************/ + /* Test assumptions. */ + /***************************************************************************/ + assert(format != NULL); + assert(level <= EVEL_LOG_MAX); + + if (level >= debug_level) + { + if ((debug_level == EVEL_LOG_INFO) || (debug_indent == 0)) + { + /***********************************************************************/ + /* Just use the format as is. */ + /***********************************************************************/ + syslog_fmt = format; + } + else + { + /***********************************************************************/ + /* Combine the format with a preceding number of indent markers. */ + /***********************************************************************/ + sprintf(indent_fmt, "%.*s%s", + debug_indent, + INDENT_SEPARATORS, + format); + syslog_fmt = indent_fmt; + } + + /*************************************************************************/ + /* Work out the syslog priority value. */ + /*************************************************************************/ + switch (level) + { + case EVEL_LOG_ERROR: + priority = LOG_ERR; + break; + + case EVEL_LOG_INFO: + priority = LOG_INFO; + break; + + case EVEL_LOG_DEBUG: + case EVEL_LOG_SPAMMY: + default: + priority = LOG_DEBUG; + break; + } + + /*************************************************************************/ + /* Write the log to the file next, which requires the var args list. */ + /*************************************************************************/ + va_start(largs, format); + vsyslog(priority, syslog_fmt, largs); + va_end(largs); + } +} diff --git a/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_mobile_flow.c b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_mobile_flow.c new file mode 100644 index 0000000..5085d6a --- /dev/null +++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_mobile_flow.c @@ -0,0 +1,2122 @@ +/*************************************************************************//** + * + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************/ +/**************************************************************************//** + * @file + * Implementation of EVEL functions relating to the Mobile Flow. + * + ****************************************************************************/ + +#include +#include +#include +#include + +#include "evel.h" +#include "evel_internal.h" + +/*****************************************************************************/ +/* Array of strings to use when encoding TCP flags. */ +/*****************************************************************************/ +static char * evel_tcp_flag_strings[EVEL_MAX_TCP_FLAGS] = { + "NS", + "CWR", + "ECE", + "URG", + "ACK", + "PSH", + "RST", + "SYN", + "FIN" +}; + +/*****************************************************************************/ +/* Array of strings to use when encoding QCI COS. */ +/*****************************************************************************/ +static char * evel_qci_cos_strings[EVEL_MAX_QCI_COS_TYPES] = { + "conversational", + "streaming", + "interactive", + "background", + "1", + "2", + "3", + "4", + "65", + "66", + "5", + "6", + "7", + "8", + "9", + "69", + "70" +}; + +/*****************************************************************************/ +/* Local prototypes */ +/*****************************************************************************/ +void evel_json_encode_mobile_flow_gtp_flow_metrics( + EVEL_JSON_BUFFER * jbuf, + MOBILE_GTP_PER_FLOW_METRICS * metrics); + +/**************************************************************************//** + * Create a new Mobile Flow event. + * + * @note The mandatory fields on the Mobile Flow must be supplied to this + * factory function and are immutable once set. Optional fields have + * explicit setter functions, but again values may only be set once so + * that the Mobile Flow has immutable properties. + * @param event_name Unique Event Name confirming Domain AsdcModel Description + * @param event_id A universal identifier of the event for: troubleshooting correlation, analysis, etc + * @param flow_direction Flow direction. + * @param gtp_per_flow_metrics GTP per-flow metrics. + * @param ip_protocol_type IP protocol type. + * @param ip_version IP protocol version. + * @param other_endpoint_ip_address IP address of the other endpoint. + * @param other_endpoint_port IP port of the other endpoint. + * @param reporting_endpoint_ip_addr IP address of the reporting endpoint. + * @param reporting_endpoint_port IP port of the reporting endpoint. + * @returns pointer to the newly manufactured ::EVENT_MOBILE_FLOW. If the + * event is not used (i.e. posted) it must be released using + * ::evel_free_mobile_flow. + * @retval NULL Failed to create the event. + *****************************************************************************/ +EVENT_MOBILE_FLOW * evel_new_mobile_flow(const char* ev_name, const char *ev_id, + const char * const flow_direction, + MOBILE_GTP_PER_FLOW_METRICS * gtp_per_flow_metrics, + const char * const ip_protocol_type, + const char * const ip_version, + const char * const other_endpoint_ip_address, + int other_endpoint_port, + const char * const reporting_endpoint_ip_addr, + int reporting_endpoint_port) +{ + EVENT_MOBILE_FLOW * mobile_flow = NULL; + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(flow_direction != NULL); + assert(gtp_per_flow_metrics != NULL); + assert(ip_protocol_type != NULL); + assert(ip_version != NULL); + assert(other_endpoint_ip_address != NULL); + assert(other_endpoint_port > 0); + assert(reporting_endpoint_ip_addr != NULL); + assert(reporting_endpoint_port > 0); + + /***************************************************************************/ + /* Allocate the Mobile Flow. */ + /***************************************************************************/ + mobile_flow = malloc(sizeof(EVENT_MOBILE_FLOW)); + if (mobile_flow == NULL) + { + log_error_state("Out of memory"); + goto exit_label; + } + memset(mobile_flow, 0, sizeof(EVENT_MOBILE_FLOW)); + EVEL_DEBUG("New Mobile Flow is at %lp", mobile_flow); + + /***************************************************************************/ + /* Initialize the header & the Mobile Flow fields. Optional string values */ + /* are uninitialized (NULL). */ + /***************************************************************************/ + evel_init_header_nameid(&mobile_flow->header,ev_name,ev_id); + mobile_flow->header.event_domain = EVEL_DOMAIN_MOBILE_FLOW; + mobile_flow->major_version = EVEL_MOBILE_FLOW_MAJOR_VERSION; + mobile_flow->minor_version = EVEL_MOBILE_FLOW_MINOR_VERSION; + mobile_flow->flow_direction = strdup(flow_direction); + mobile_flow->gtp_per_flow_metrics = gtp_per_flow_metrics; + mobile_flow->ip_protocol_type = strdup(ip_protocol_type); + mobile_flow->ip_version = strdup(ip_version); + mobile_flow->other_endpoint_ip_address = strdup(other_endpoint_ip_address); + mobile_flow->other_endpoint_port = other_endpoint_port; + mobile_flow->reporting_endpoint_ip_addr = strdup(reporting_endpoint_ip_addr); + mobile_flow->reporting_endpoint_port = reporting_endpoint_port; + evel_init_option_string(&mobile_flow->application_type); + evel_init_option_string(&mobile_flow->app_protocol_type); + evel_init_option_string(&mobile_flow->app_protocol_version); + evel_init_option_string(&mobile_flow->cid); + evel_init_option_string(&mobile_flow->connection_type); + evel_init_option_string(&mobile_flow->ecgi); + evel_init_option_string(&mobile_flow->gtp_protocol_type); + evel_init_option_string(&mobile_flow->gtp_version); + evel_init_option_string(&mobile_flow->http_header); + evel_init_option_string(&mobile_flow->imei); + evel_init_option_string(&mobile_flow->imsi); + evel_init_option_string(&mobile_flow->lac); + evel_init_option_string(&mobile_flow->mcc); + evel_init_option_string(&mobile_flow->mnc); + evel_init_option_string(&mobile_flow->msisdn); + evel_init_option_string(&mobile_flow->other_functional_role); + evel_init_option_string(&mobile_flow->rac); + evel_init_option_string(&mobile_flow->radio_access_technology); + evel_init_option_string(&mobile_flow->sac); + evel_init_option_int(&mobile_flow->sampling_algorithm); + evel_init_option_string(&mobile_flow->tac); + evel_init_option_string(&mobile_flow->tunnel_id); + evel_init_option_string(&mobile_flow->vlan_id); + dlist_initialize(&mobile_flow->additional_info); + +exit_label: + EVEL_EXIT(); + return mobile_flow; +} + +/**************************************************************************//** + * Add an additional value name/value pair to the Mobile flow. + * + * The name and value are null delimited ASCII strings. The library takes + * a copy so the caller does not have to preserve values after the function + * returns. + * + * @param fault Pointer to the Mobile flow. + * @param name ASCIIZ string with the attribute's name. The caller + * does not need to preserve the value once the function + * returns. + * @param value ASCIIZ string with the attribute's value. The caller + * does not need to preserve the value once the function + * returns. + *****************************************************************************/ +void evel_mobile_flow_addl_field_add(EVENT_MOBILE_FLOW * const event, char * name, char * value) +{ + OTHER_FIELD * nv_pair = NULL; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(event != NULL); + assert(event->header.event_domain == EVEL_DOMAIN_MOBILE_FLOW); + assert(name != NULL); + assert(value != NULL); + + EVEL_DEBUG("Adding name=%s value=%s", name, value); + nv_pair = malloc(sizeof(OTHER_FIELD)); + assert(nv_pair != NULL); + nv_pair->name = strdup(name); + nv_pair->value = strdup(value); + assert(nv_pair->name != NULL); + assert(nv_pair->value != NULL); + + dlist_push_last(&event->additional_info, nv_pair); + + EVEL_EXIT(); +} + + +/**************************************************************************//** + * Set the Event Type property of the Mobile Flow. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param mobile_flow Pointer to the Mobile Flow. + * @param type The Event Type to be set. ASCIIZ string. The caller + * does not need to preserve the value once the function + * returns. + *****************************************************************************/ +void evel_mobile_flow_type_set(EVENT_MOBILE_FLOW * mobile_flow, + const char * const type) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions and call evel_header_type_set. */ + /***************************************************************************/ + assert(mobile_flow != NULL); + assert(mobile_flow->header.event_domain == EVEL_DOMAIN_MOBILE_FLOW); + evel_header_type_set(&mobile_flow->header, type); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Application Type property of the Mobile Flow. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param mobile_flow Pointer to the Mobile Flow. + * @param type The Application Type to be set. ASCIIZ string. The caller + * does not need to preserve the value once the function + * returns. + *****************************************************************************/ +void evel_mobile_flow_app_type_set(EVENT_MOBILE_FLOW * mobile_flow, + const char * const type) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(mobile_flow != NULL); + assert(mobile_flow->header.event_domain == EVEL_DOMAIN_MOBILE_FLOW); + assert(type != NULL); + + evel_set_option_string(&mobile_flow->application_type, + type, + "Application Type"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Application Protocol Type property of the Mobile Flow. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param mobile_flow Pointer to the Mobile Flow. + * @param type The Application Protocol Type to be set. ASCIIZ string. + * The caller does not need to preserve the value once the + * function returns. + *****************************************************************************/ +void evel_mobile_flow_app_prot_type_set(EVENT_MOBILE_FLOW * mobile_flow, + const char * const type) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(mobile_flow != NULL); + assert(mobile_flow->header.event_domain == EVEL_DOMAIN_MOBILE_FLOW); + assert(type != NULL); + + evel_set_option_string(&mobile_flow->app_protocol_type, + type, + "Application Protocol Type"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Application Protocol Version property of the Mobile Flow. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param mobile_flow Pointer to the Mobile Flow. + * @param version The Application Protocol Version to be set. ASCIIZ + * string. The caller does not need to preserve the value + * once the function returns. + *****************************************************************************/ +void evel_mobile_flow_app_prot_ver_set(EVENT_MOBILE_FLOW * mobile_flow, + const char * const version) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(mobile_flow != NULL); + assert(mobile_flow->header.event_domain == EVEL_DOMAIN_MOBILE_FLOW); + assert(version != NULL); + + evel_set_option_string(&mobile_flow->app_protocol_version, + version, + "Application Protocol Version"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the CID property of the Mobile Flow. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param mobile_flow Pointer to the Mobile Flow. + * @param cid The CID to be set. ASCIIZ string. The caller does not + * need to preserve the value once the function returns. + *****************************************************************************/ +void evel_mobile_flow_cid_set(EVENT_MOBILE_FLOW * mobile_flow, + const char * const cid) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(mobile_flow != NULL); + assert(mobile_flow->header.event_domain == EVEL_DOMAIN_MOBILE_FLOW); + assert(cid != NULL); + + evel_set_option_string(&mobile_flow->cid, + cid, + "CID"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Connection Type property of the Mobile Flow. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param mobile_flow Pointer to the Mobile Flow. + * @param type The Connection Type to be set. ASCIIZ string. The caller + * does not need to preserve the value once the function + * returns. + *****************************************************************************/ +void evel_mobile_flow_con_type_set(EVENT_MOBILE_FLOW * mobile_flow, + const char * const type) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(mobile_flow != NULL); + assert(mobile_flow->header.event_domain == EVEL_DOMAIN_MOBILE_FLOW); + assert(type != NULL); + + evel_set_option_string(&mobile_flow->connection_type, + type, + "Connection Type"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the ECGI property of the Mobile Flow. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param mobile_flow Pointer to the Mobile Flow. + * @param ecgi The ECGI to be set. ASCIIZ string. The caller does not + * need to preserve the value once the function returns. + *****************************************************************************/ +void evel_mobile_flow_ecgi_set(EVENT_MOBILE_FLOW * mobile_flow, + const char * const ecgi) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(mobile_flow != NULL); + assert(mobile_flow->header.event_domain == EVEL_DOMAIN_MOBILE_FLOW); + assert(ecgi != NULL); + + evel_set_option_string(&mobile_flow->ecgi, + ecgi, + "ECGI"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the GTP Protocol Type property of the Mobile Flow. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param mobile_flow Pointer to the Mobile Flow. + * @param type The GTP Protocol Type to be set. ASCIIZ string. The + * caller does not need to preserve the value once the + * function returns. + *****************************************************************************/ +void evel_mobile_flow_gtp_prot_type_set(EVENT_MOBILE_FLOW * mobile_flow, + const char * const type) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(mobile_flow != NULL); + assert(mobile_flow->header.event_domain == EVEL_DOMAIN_MOBILE_FLOW); + assert(type != NULL); + + evel_set_option_string(&mobile_flow->gtp_protocol_type, + type, + "GTP Protocol Type"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the GTP Protocol Version property of the Mobile Flow. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param mobile_flow Pointer to the Mobile Flow. + * @param version The GTP Protocol Version to be set. ASCIIZ string. The + * caller does not need to preserve the value once the + * function returns. + *****************************************************************************/ +void evel_mobile_flow_gtp_prot_ver_set(EVENT_MOBILE_FLOW * mobile_flow, + const char * const version) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(mobile_flow != NULL); + assert(mobile_flow->header.event_domain == EVEL_DOMAIN_MOBILE_FLOW); + assert(version != NULL); + + evel_set_option_string(&mobile_flow->gtp_version, + version, + "GTP Protocol Version"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the HTTP Header property of the Mobile Flow. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param mobile_flow Pointer to the Mobile Flow. + * @param header The HTTP header to be set. ASCIIZ string. The caller does + * not need to preserve the value once the function returns. + *****************************************************************************/ +void evel_mobile_flow_http_header_set(EVENT_MOBILE_FLOW * mobile_flow, + const char * const header) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(mobile_flow != NULL); + assert(mobile_flow->header.event_domain == EVEL_DOMAIN_MOBILE_FLOW); + assert(header != NULL); + + evel_set_option_string(&mobile_flow->http_header, + header, + "HTTP Header"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the IMEI property of the Mobile Flow. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param mobile_flow Pointer to the Mobile Flow. + * @param imei The IMEI to be set. ASCIIZ string. The caller does not + * need to preserve the value once the function returns. + *****************************************************************************/ +void evel_mobile_flow_imei_set(EVENT_MOBILE_FLOW * mobile_flow, + const char * const imei) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(mobile_flow != NULL); + assert(mobile_flow->header.event_domain == EVEL_DOMAIN_MOBILE_FLOW); + assert(imei != NULL); + + evel_set_option_string(&mobile_flow->imei, + imei, + "IMEI"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the IMSI property of the Mobile Flow. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param mobile_flow Pointer to the Mobile Flow. + * @param imsi The IMSI to be set. ASCIIZ string. The caller does not + * need to preserve the value once the function returns. + *****************************************************************************/ +void evel_mobile_flow_imsi_set(EVENT_MOBILE_FLOW * mobile_flow, + const char * const imsi) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(mobile_flow != NULL); + assert(mobile_flow->header.event_domain == EVEL_DOMAIN_MOBILE_FLOW); + assert(imsi != NULL); + + evel_set_option_string(&mobile_flow->imsi, + imsi, + "IMSI"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the LAC property of the Mobile Flow. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param mobile_flow Pointer to the Mobile Flow. + * @param lac The LAC to be set. ASCIIZ string. The caller does not + * need to preserve the value once the function returns. + *****************************************************************************/ +void evel_mobile_flow_lac_set(EVENT_MOBILE_FLOW * mobile_flow, + const char * const lac) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(mobile_flow != NULL); + assert(mobile_flow->header.event_domain == EVEL_DOMAIN_MOBILE_FLOW); + assert(lac != NULL); + + evel_set_option_string(&mobile_flow->lac, + lac, + "LAC"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the MCC property of the Mobile Flow. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param mobile_flow Pointer to the Mobile Flow. + * @param mcc The MCC to be set. ASCIIZ string. The caller does not + * need to preserve the value once the function returns. + *****************************************************************************/ +void evel_mobile_flow_mcc_set(EVENT_MOBILE_FLOW * mobile_flow, + const char * const mcc) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(mobile_flow != NULL); + assert(mobile_flow->header.event_domain == EVEL_DOMAIN_MOBILE_FLOW); + assert(mcc != NULL); + + evel_set_option_string(&mobile_flow->mcc, + mcc, + "MCC"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the MNC property of the Mobile Flow. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param mobile_flow Pointer to the Mobile Flow. + * @param mnc The MNC to be set. ASCIIZ string. The caller does not + * need to preserve the value once the function returns. + *****************************************************************************/ +void evel_mobile_flow_mnc_set(EVENT_MOBILE_FLOW * mobile_flow, + const char * const mnc) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(mobile_flow != NULL); + assert(mobile_flow->header.event_domain == EVEL_DOMAIN_MOBILE_FLOW); + assert(mnc != NULL); + + evel_set_option_string(&mobile_flow->mnc, + mnc, + "MNC"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the MSISDN property of the Mobile Flow. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param mobile_flow Pointer to the Mobile Flow. + * @param msisdn The MSISDN to be set. ASCIIZ string. The caller does not + * need to preserve the value once the function returns. + *****************************************************************************/ +void evel_mobile_flow_msisdn_set(EVENT_MOBILE_FLOW * mobile_flow, + const char * const msisdn) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(mobile_flow != NULL); + assert(mobile_flow->header.event_domain == EVEL_DOMAIN_MOBILE_FLOW); + assert(msisdn != NULL); + + evel_set_option_string(&mobile_flow->msisdn, + msisdn, + "MSISDN"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Other Functional Role property of the Mobile Flow. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param mobile_flow Pointer to the Mobile Flow. + * @param role The Other Functional Role to be set. ASCIIZ string. The + * caller does not need to preserve the value once the + * function returns. + *****************************************************************************/ +void evel_mobile_flow_other_func_role_set(EVENT_MOBILE_FLOW * mobile_flow, + const char * const role) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(mobile_flow != NULL); + assert(mobile_flow->header.event_domain == EVEL_DOMAIN_MOBILE_FLOW); + assert(role != NULL); + + evel_set_option_string(&mobile_flow->other_functional_role, + role, + "Other Functional Role"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the RAC property of the Mobile Flow. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param mobile_flow Pointer to the Mobile Flow. + * @param rac The RAC to be set. ASCIIZ string. The caller does not + * need to preserve the value once the function returns. + *****************************************************************************/ +void evel_mobile_flow_rac_set(EVENT_MOBILE_FLOW * mobile_flow, + const char * const rac) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(mobile_flow != NULL); + assert(mobile_flow->header.event_domain == EVEL_DOMAIN_MOBILE_FLOW); + assert(rac != NULL); + + evel_set_option_string(&mobile_flow->rac, + rac, + "RAC"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Radio Access Technology property of the Mobile Flow. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param mobile_flow Pointer to the Mobile Flow. + * @param tech The Radio Access Technology to be set. ASCIIZ string. The + * caller does not need to preserve the value once the + * function returns. + *****************************************************************************/ +void evel_mobile_flow_radio_acc_tech_set(EVENT_MOBILE_FLOW * mobile_flow, + const char * const tech) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(mobile_flow != NULL); + assert(mobile_flow->header.event_domain == EVEL_DOMAIN_MOBILE_FLOW); + assert(tech != NULL); + + evel_set_option_string(&mobile_flow->radio_access_technology, + tech, + "Radio Access Technology"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the SAC property of the Mobile Flow. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param mobile_flow Pointer to the Mobile Flow. + * @param sac The SAC to be set. ASCIIZ string. The caller does not + * need to preserve the value once the function returns. + *****************************************************************************/ +void evel_mobile_flow_sac_set(EVENT_MOBILE_FLOW * mobile_flow, + const char * const sac) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(mobile_flow != NULL); + assert(mobile_flow->header.event_domain == EVEL_DOMAIN_MOBILE_FLOW); + assert(sac != NULL); + + evel_set_option_string(&mobile_flow->sac, + sac, + "SAC"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Sampling Algorithm property of the Mobile Flow. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param mobile_flow Pointer to the Mobile Flow. + * @param algorithm The Sampling Algorithm to be set. + *****************************************************************************/ +void evel_mobile_flow_samp_alg_set(EVENT_MOBILE_FLOW * mobile_flow, + int algorithm) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(mobile_flow != NULL); + assert(mobile_flow->header.event_domain == EVEL_DOMAIN_MOBILE_FLOW); + assert(algorithm >= 0); + + evel_set_option_int(&mobile_flow->sampling_algorithm, + algorithm, + "Sampling Algorithm"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the TAC property of the Mobile Flow. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param mobile_flow Pointer to the Mobile Flow. + * @param tac The TAC to be set. ASCIIZ string. The caller does not + * need to preserve the value once the function returns. + *****************************************************************************/ +void evel_mobile_flow_tac_set(EVENT_MOBILE_FLOW * mobile_flow, + const char * const tac) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(mobile_flow != NULL); + assert(mobile_flow->header.event_domain == EVEL_DOMAIN_MOBILE_FLOW); + assert(tac != NULL); + + evel_set_option_string(&mobile_flow->tac, + tac, + "TAC"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Tunnel ID property of the Mobile Flow. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param mobile_flow Pointer to the Mobile Flow. + * @param tunnel_id The Tunnel ID to be set. ASCIIZ string. The caller does + * not need to preserve the value once the function returns. + *****************************************************************************/ +void evel_mobile_flow_tunnel_id_set(EVENT_MOBILE_FLOW * mobile_flow, + const char * const tunnel_id) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(mobile_flow != NULL); + assert(mobile_flow->header.event_domain == EVEL_DOMAIN_MOBILE_FLOW); + assert(tunnel_id != NULL); + + evel_set_option_string(&mobile_flow->tunnel_id, + tunnel_id, + "Tunnel ID"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the VLAN ID property of the Mobile Flow. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param mobile_flow Pointer to the Mobile Flow. + * @param vlan_id The VLAN ID to be set. ASCIIZ string. The caller does + * not need to preserve the value once the function returns. + *****************************************************************************/ +void evel_mobile_flow_vlan_id_set(EVENT_MOBILE_FLOW * mobile_flow, + const char * const vlan_id) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(mobile_flow != NULL); + assert(mobile_flow->header.event_domain == EVEL_DOMAIN_MOBILE_FLOW); + assert(vlan_id != NULL); + + evel_set_option_string(&mobile_flow->vlan_id, + vlan_id, + "VLAN ID"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Encode the Mobile Flow in JSON according to AT&T's schema for the event + * type. + * + * @param jbuf Pointer to the ::EVEL_JSON_BUFFER to encode into. + * @param event Pointer to the ::EVENT_HEADER to encode. + *****************************************************************************/ +void evel_json_encode_mobile_flow(EVEL_JSON_BUFFER * jbuf, + EVENT_MOBILE_FLOW * event) +{ + OTHER_FIELD * nv_pair = NULL; + DLIST_ITEM * dlist_item = NULL; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(event != NULL); + assert(event->header.event_domain == EVEL_DOMAIN_MOBILE_FLOW); + + evel_json_encode_header(jbuf, &event->header); + evel_json_open_named_object(jbuf, "mobileFlowFields"); + + + /***************************************************************************/ + /* Checkpoint, so that we can wind back if all fields are suppressed. */ + /***************************************************************************/ + evel_json_checkpoint(jbuf); + if (evel_json_open_opt_named_list(jbuf, "additionalFields")) + { + bool added = false; + + dlist_item = dlist_get_first(&event->additional_info); + while (dlist_item != NULL) + { + nv_pair = (OTHER_FIELD *) dlist_item->item; + assert(nv_pair != NULL); + + if (!evel_throttle_suppress_nv_pair(jbuf->throttle_spec, + "additionalFields", + nv_pair->name)) + { + evel_json_open_object(jbuf); + evel_enc_kv_string(jbuf, "name", nv_pair->name); + evel_enc_kv_string(jbuf, "value", nv_pair->value); + evel_json_close_object(jbuf); + added = true; + } + dlist_item = dlist_get_next(dlist_item); + } + evel_json_close_list(jbuf); + + /*************************************************************************/ + /* If we've not written anything, rewind to before we opened the list. */ + /*************************************************************************/ + if (!added) + { + evel_json_rewind(jbuf); + } + } + + + /***************************************************************************/ + /* Mandatory parameters. */ + /***************************************************************************/ + evel_enc_kv_string(jbuf, "flowDirection", event->flow_direction); + evel_json_encode_mobile_flow_gtp_flow_metrics( + jbuf, event->gtp_per_flow_metrics); + evel_enc_kv_string(jbuf, "ipProtocolType", event->ip_protocol_type); + evel_enc_kv_string(jbuf, "ipVersion", event->ip_version); + evel_enc_kv_string( + jbuf, "otherEndpointIpAddress", event->other_endpoint_ip_address); + evel_enc_kv_int(jbuf, "otherEndpointPort", event->other_endpoint_port); + evel_enc_kv_string( + jbuf, "reportingEndpointIpAddr", event->reporting_endpoint_ip_addr); + evel_enc_kv_int( + jbuf, "reportingEndpointPort", event->reporting_endpoint_port); + + /***************************************************************************/ + /* Optional parameters. */ + /***************************************************************************/ + evel_enc_kv_opt_string(jbuf, "applicationType", &event->application_type); + evel_enc_kv_opt_string(jbuf, "appProtocolType", &event->app_protocol_type); + evel_enc_kv_opt_string( + jbuf, "appProtocolVersion", &event->app_protocol_version); + evel_enc_kv_opt_string(jbuf, "cid", &event->cid); + evel_enc_kv_opt_string(jbuf, "connectionType", &event->connection_type); + evel_enc_kv_opt_string(jbuf, "ecgi", &event->ecgi); + evel_enc_kv_opt_string(jbuf, "gtpProtocolType", &event->gtp_protocol_type); + evel_enc_kv_opt_string(jbuf, "gtpVersion", &event->gtp_version); + evel_enc_kv_opt_string(jbuf, "httpHeader", &event->http_header); + evel_enc_kv_opt_string(jbuf, "imei", &event->imei); + evel_enc_kv_opt_string(jbuf, "imsi", &event->imsi); + evel_enc_kv_opt_string(jbuf, "lac", &event->lac); + evel_enc_kv_opt_string(jbuf, "mcc", &event->mcc); + evel_enc_kv_opt_string(jbuf, "mnc", &event->mnc); + evel_enc_kv_opt_string(jbuf, "msisdn", &event->msisdn); + evel_enc_kv_opt_string( + jbuf, "otherFunctionalRole", &event->other_functional_role); + evel_enc_kv_opt_string(jbuf, "rac", &event->rac); + evel_enc_kv_opt_string( + jbuf, "radioAccessTechnology", &event->radio_access_technology); + evel_enc_kv_opt_string(jbuf, "sac", &event->sac); + evel_enc_kv_opt_int(jbuf, "samplingAlgorithm", &event->sampling_algorithm); + evel_enc_kv_opt_string(jbuf, "tac", &event->tac); + evel_enc_kv_opt_string(jbuf, "tunnelId", &event->tunnel_id); + evel_enc_kv_opt_string(jbuf, "vlanId", &event->vlan_id); + evel_enc_version(jbuf, + "mobileFlowFieldsVersion", + event->major_version, + event->minor_version); + evel_json_close_object(jbuf); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Free a Mobile Flow. + * + * Free off the Mobile Flow supplied. Will free all the contained allocated + * memory. + * + * @note It does not free the Mobile Flow itself, since that may be part of a + * larger structure. + *****************************************************************************/ +void evel_free_mobile_flow(EVENT_MOBILE_FLOW * event) +{ + OTHER_FIELD * nv_pair = NULL; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. As an internal API we don't allow freeing NULL */ + /* events as we do on the public API. */ + /***************************************************************************/ + assert(event != NULL); + assert(event->header.event_domain == EVEL_DOMAIN_MOBILE_FLOW); + + /***************************************************************************/ + /* Free all internal strings then the header itself. */ + /***************************************************************************/ + free(event->flow_direction); + + evel_free_mobile_gtp_flow_metrics(event->gtp_per_flow_metrics); + free(event->gtp_per_flow_metrics); + free(event->ip_protocol_type); + free(event->ip_version); + free(event->other_endpoint_ip_address); + free(event->reporting_endpoint_ip_addr); + evel_free_option_string(&event->application_type); + evel_free_option_string(&event->app_protocol_type); + evel_free_option_string(&event->app_protocol_version); + evel_free_option_string(&event->cid); + evel_free_option_string(&event->connection_type); + evel_free_option_string(&event->ecgi); + evel_free_option_string(&event->gtp_protocol_type); + evel_free_option_string(&event->gtp_version); + evel_free_option_string(&event->http_header); + evel_free_option_string(&event->imei); + evel_free_option_string(&event->imsi); + evel_free_option_string(&event->lac); + evel_free_option_string(&event->mcc); + evel_free_option_string(&event->mnc); + evel_free_option_string(&event->msisdn); + evel_free_option_string(&event->other_functional_role); + evel_free_option_string(&event->rac); + evel_free_option_string(&event->radio_access_technology); + evel_free_option_string(&event->sac); + evel_free_option_string(&event->tac); + evel_free_option_string(&event->tunnel_id); + evel_free_option_string(&event->vlan_id); + + /***************************************************************************/ + /* Free all internal strings then the header itself. */ + /***************************************************************************/ + nv_pair = dlist_pop_last(&event->additional_info); + while (nv_pair != NULL) + { + EVEL_DEBUG("Freeing Other Field (%s, %s)", nv_pair->name, nv_pair->value); + free(nv_pair->name); + free(nv_pair->value); + free(nv_pair); + nv_pair = dlist_pop_last(&event->additional_info); + } + + evel_free_header(&event->header); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Create a new Mobile GTP Per Flow Metrics. + * + * @note The mandatory fields on the Mobile GTP Per Flow Metrics must be + * supplied to this factory function and are immutable once set. + * Optional fields have explicit setter functions, but again values + * may only be set once so that the Mobile GTP Per Flow Metrics has + * immutable properties. + * + * @param avg_bit_error_rate Average bit error rate. + * @param avg_packet_delay_variation Average delay or jitter in ms. + * @param avg_packet_latency Average delivery latency. + * @param avg_receive_throughput Average receive throughput. + * @param avg_transmit_throughput Average transmit throughput. + * @param flow_activation_epoch Time the connection is activated. + * @param flow_activation_microsec Microseconds for the start of the flow + * connection. + * @param flow_deactivation_epoch Time for the end of the connection. + * @param flow_deactivation_microsec Microseconds for the end of the flow + * connection. + * @param flow_deactivation_time Transmission time of the first packet. + * @param flow_status Connection status. + * @param max_packet_delay_variation Maximum packet delay or jitter in ms. + * @param num_activation_failures Number of failed activation requests. + * @param num_bit_errors Number of errored bits. + * @param num_bytes_received Number of bytes received. + * @param num_bytes_transmitted Number of bytes transmitted. + * @param num_dropped_packets Number of received packets dropped. + * @param num_l7_bytes_received Number of tunneled Layer 7 bytes + * received. + * @param num_l7_bytes_transmitted Number of tunneled Layer 7 bytes + * transmitted. + * @param num_lost_packets Number of lost packets. + * @param num_out_of_order_packets Number of out-of-order packets. + * @param num_packet_errors Number of errored packets. + * @param num_packets_received_excl_retrans Number of packets received, + * excluding retransmits. + * @param num_packets_received_incl_retrans Number of packets received. + * @param num_packets_transmitted_incl_retrans Number of packets + * transmitted. + * @param num_retries Number of packet retries. + * @param num_timeouts Number of packet timeouts. + * @param num_tunneled_l7_bytes_received Number of tunneled Layer 7 bytes + * received, excluding retransmits. + * @param round_trip_time Round trip time. + * @param time_to_first_byte Time in ms between connection + * activation and first byte received. + * + * @returns pointer to the newly manufactured ::MOBILE_GTP_PER_FLOW_METRICS. + * If the structure is not used it must be released using + * ::evel_free_mobile_gtp_flow_metrics. + * @retval NULL Failed to create the event. + *****************************************************************************/ +MOBILE_GTP_PER_FLOW_METRICS * evel_new_mobile_gtp_flow_metrics( + double avg_bit_error_rate, + double avg_packet_delay_variation, + int avg_packet_latency, + int avg_receive_throughput, + int avg_transmit_throughput, + int flow_activation_epoch, + int flow_activation_microsec, + int flow_deactivation_epoch, + int flow_deactivation_microsec, + time_t flow_deactivation_time, + const char * const flow_status, + int max_packet_delay_variation, + int num_activation_failures, + int num_bit_errors, + int num_bytes_received, + int num_bytes_transmitted, + int num_dropped_packets, + int num_l7_bytes_received, + int num_l7_bytes_transmitted, + int num_lost_packets, + int num_out_of_order_packets, + int num_packet_errors, + int num_packets_received_excl_retrans, + int num_packets_received_incl_retrans, + int num_packets_transmitted_incl_retrans, + int num_retries, + int num_timeouts, + int num_tunneled_l7_bytes_received, + int round_trip_time, + int time_to_first_byte) +{ + MOBILE_GTP_PER_FLOW_METRICS * metrics = NULL; + int ii; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(avg_bit_error_rate >= 0.0); + assert(avg_packet_delay_variation >= 0.0); + assert(avg_packet_latency >= 0); + assert(avg_receive_throughput >= 0); + assert(avg_transmit_throughput >= 0); + assert(flow_activation_epoch > 0); + assert(flow_activation_microsec >= 0); + assert(flow_deactivation_epoch > 0); + assert(flow_deactivation_microsec >= 0); + assert(flow_status != NULL); + assert(max_packet_delay_variation >= 0); + assert(num_activation_failures >= 0); + assert(num_bit_errors >= 0); + assert(num_bytes_received >= 0); + assert(num_bytes_transmitted >= 0); + assert(num_dropped_packets >= 0); + assert(num_l7_bytes_received >= 0); + assert(num_l7_bytes_transmitted >= 0); + assert(num_lost_packets >= 0); + assert(num_out_of_order_packets >= 0); + assert(num_packet_errors >= 0); + assert(num_packets_received_excl_retrans >= 0); + assert(num_packets_received_incl_retrans >= 0); + assert(num_packets_transmitted_incl_retrans >= 0); + assert(num_retries >= 0); + assert(num_timeouts >= 0); + assert(num_tunneled_l7_bytes_received >= 0); + assert(round_trip_time >= 0); + assert(time_to_first_byte >= 0); + + /***************************************************************************/ + /* Allocate the Mobile Flow GTP Per Flow Metrics. */ + /***************************************************************************/ + metrics = malloc(sizeof(MOBILE_GTP_PER_FLOW_METRICS)); + if (metrics == NULL) + { + log_error_state("Out of memory"); + goto exit_label; + } + memset(metrics, 0, sizeof(MOBILE_GTP_PER_FLOW_METRICS)); + EVEL_DEBUG("New Mobile Flow GTP Per Flow Metrics is at %lp", metrics); + + /***************************************************************************/ + /* Initialize the Mobile Flow GTP Per Flow Metrics fields. Optional */ + /* string values are uninitialized (NULL). */ + /***************************************************************************/ + metrics->avg_bit_error_rate = avg_bit_error_rate; + metrics->avg_packet_delay_variation = avg_packet_delay_variation; + metrics->avg_packet_latency = avg_packet_latency; + metrics->avg_receive_throughput = avg_receive_throughput; + metrics->avg_transmit_throughput = avg_transmit_throughput; + metrics->flow_activation_epoch = flow_activation_epoch; + metrics->flow_activation_microsec = flow_activation_microsec; + metrics->flow_deactivation_epoch = flow_deactivation_epoch; + metrics->flow_deactivation_microsec = flow_deactivation_microsec; + metrics->flow_deactivation_time = flow_deactivation_time; + metrics->flow_status = strdup(flow_status); + metrics->max_packet_delay_variation = max_packet_delay_variation; + metrics->num_activation_failures = num_activation_failures; + metrics->num_bit_errors = num_bit_errors; + metrics->num_bytes_received = num_bytes_received; + metrics->num_bytes_transmitted = num_bytes_transmitted; + metrics->num_dropped_packets = num_dropped_packets; + metrics->num_l7_bytes_received = num_l7_bytes_received; + metrics->num_l7_bytes_transmitted = num_l7_bytes_transmitted; + metrics->num_lost_packets = num_lost_packets; + metrics->num_out_of_order_packets = num_out_of_order_packets; + metrics->num_packet_errors = num_packet_errors; + metrics->num_packets_received_excl_retrans = + num_packets_received_excl_retrans; + metrics->num_packets_received_incl_retrans = + num_packets_received_incl_retrans; + metrics->num_packets_transmitted_incl_retrans = + num_packets_transmitted_incl_retrans; + metrics->num_retries = num_retries; + metrics->num_timeouts = num_timeouts; + metrics->num_tunneled_l7_bytes_received = num_tunneled_l7_bytes_received; + metrics->round_trip_time = round_trip_time; + metrics->time_to_first_byte = time_to_first_byte; + for (ii = 0; ii < EVEL_TOS_SUPPORTED; ii++) + { + evel_init_option_int(&metrics->ip_tos_counts[ii]); + } + for (ii = 0; ii < EVEL_MAX_TCP_FLAGS; ii++) + { + evel_init_option_int(&metrics->tcp_flag_counts[ii]); + } + for (ii = 0; ii < EVEL_MAX_QCI_COS_TYPES; ii++) + { + evel_init_option_int(&metrics->qci_cos_counts[ii]); + } + evel_init_option_int(&metrics->dur_connection_failed_status); + evel_init_option_int(&metrics->dur_tunnel_failed_status); + evel_init_option_string(&metrics->flow_activated_by); + evel_init_option_time(&metrics->flow_activation_time); + evel_init_option_string(&metrics->flow_deactivated_by); + evel_init_option_string(&metrics->gtp_connection_status); + evel_init_option_string(&metrics->gtp_tunnel_status); + evel_init_option_int(&metrics->large_packet_rtt); + evel_init_option_double(&metrics->large_packet_threshold); + evel_init_option_int(&metrics->max_receive_bit_rate); + evel_init_option_int(&metrics->max_transmit_bit_rate); + evel_init_option_int(&metrics->num_gtp_echo_failures); + evel_init_option_int(&metrics->num_gtp_tunnel_errors); + evel_init_option_int(&metrics->num_http_errors); + +exit_label: + EVEL_EXIT(); + return metrics; +} + +/**************************************************************************//** + * Set the Duration of Connection Failed Status property of the Mobile GTP Per + * Flow Metrics. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param metrics Pointer to the Mobile GTP Per Flow Metrics. + * @param duration The Duration of Connection Failed Status to be set. + *****************************************************************************/ +void evel_mobile_gtp_metrics_dur_con_fail_set( + MOBILE_GTP_PER_FLOW_METRICS * metrics, + int duration) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(metrics != NULL); + assert(duration >= 0); + + evel_set_option_int(&metrics->dur_connection_failed_status, + duration, + "Duration of Connection Failed Status"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Duration of Tunnel Failed Status property of the Mobile GTP Per Flow + * Metrics. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param metrics Pointer to the Mobile GTP Per Flow Metrics. + * @param duration The Duration of Tunnel Failed Status to be set. + *****************************************************************************/ +void evel_mobile_gtp_metrics_dur_tun_fail_set( + MOBILE_GTP_PER_FLOW_METRICS * metrics, + int duration) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(metrics != NULL); + assert(duration >= 0); + + evel_set_option_int(&metrics->dur_tunnel_failed_status, + duration, + "Duration of Tunnel Failed Status"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Activated By property of the Mobile GTP Per Flow metrics. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param metrics Pointer to the Mobile GTP Per Flow Metrics. + * @param act_by The Activated By to be set. ASCIIZ string. The caller + * does not need to preserve the value once the function + * returns. + *****************************************************************************/ +void evel_mobile_gtp_metrics_act_by_set(MOBILE_GTP_PER_FLOW_METRICS * metrics, + const char * const act_by) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(metrics != NULL); + assert(act_by != NULL); + + evel_set_option_string(&metrics->flow_activated_by, + act_by, + "Activated By"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Activation Time property of the Mobile GTP Per Flow metrics. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param metrics Pointer to the Mobile GTP Per Flow Metrics. + * @param act_time The Activation Time to be set. ASCIIZ string. The caller + * does not need to preserve the value once the function + * returns. + *****************************************************************************/ +void evel_mobile_gtp_metrics_act_time_set( + MOBILE_GTP_PER_FLOW_METRICS * metrics, + time_t act_time) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(metrics != NULL); + assert(act_time > 0); + + evel_set_option_time(&metrics->flow_activation_time, + act_time, + "Activation Time"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Deactivated By property of the Mobile GTP Per Flow metrics. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param metrics Pointer to the Mobile GTP Per Flow Metrics. + * @param deact_by The Deactivated By to be set. ASCIIZ string. The caller + * does not need to preserve the value once the function + * returns. + *****************************************************************************/ +void evel_mobile_gtp_metrics_deact_by_set( + MOBILE_GTP_PER_FLOW_METRICS * metrics, + const char * const deact_by) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(metrics != NULL); + assert(deact_by != NULL); + + evel_set_option_string(&metrics->flow_deactivated_by, + deact_by, + "Deactivated By"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the GTP Connection Status property of the Mobile GTP Per Flow metrics. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param metrics Pointer to the Mobile GTP Per Flow Metrics. + * @param status The GTP Connection Status to be set. ASCIIZ string. The + * caller does not need to preserve the value once the + * function returns. + *****************************************************************************/ +void evel_mobile_gtp_metrics_con_status_set( + MOBILE_GTP_PER_FLOW_METRICS * metrics, + const char * const status) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(metrics != NULL); + assert(status != NULL); + + evel_set_option_string(&metrics->gtp_connection_status, + status, + "GTP Connection Status"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the GTP Tunnel Status property of the Mobile GTP Per Flow metrics. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param metrics Pointer to the Mobile GTP Per Flow Metrics. + * @param status The GTP Tunnel Status to be set. ASCIIZ string. The + * caller does not need to preserve the value once the + * function returns. + *****************************************************************************/ +void evel_mobile_gtp_metrics_tun_status_set( + MOBILE_GTP_PER_FLOW_METRICS * metrics, + const char * const status) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(metrics != NULL); + assert(status != NULL); + + evel_set_option_string(&metrics->gtp_tunnel_status, + status, + "GTP Tunnel Status"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set an IP Type-of-Service count property of the Mobile GTP Per Flow metrics. + * + * @param metrics Pointer to the Mobile GTP Per Flow Metrics. + * @param index The index of the IP Type-of-Service. + * @param count The count. + *****************************************************************************/ +void evel_mobile_gtp_metrics_iptos_set(MOBILE_GTP_PER_FLOW_METRICS * metrics, + int index, + int count) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(metrics != NULL); + assert(index >= 0); + assert(index < EVEL_TOS_SUPPORTED); + assert(count >= 0); + assert(count <= 255); + + EVEL_DEBUG("IP Type-of-Service %d", index); + evel_set_option_int(&metrics->ip_tos_counts[index], + count, + "IP Type-of-Service"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Large Packet Round-Trip Time property of the Mobile GTP Per Flow + * Metrics. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param metrics Pointer to the Mobile GTP Per Flow Metrics. + * @param rtt The Large Packet Round-Trip Time to be set. + *****************************************************************************/ +void evel_mobile_gtp_metrics_large_pkt_rtt_set( + MOBILE_GTP_PER_FLOW_METRICS * metrics, + int rtt) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(metrics != NULL); + assert(rtt >= 0); + + evel_set_option_int(&metrics->large_packet_rtt, + rtt, + "Large Packet Round-Trip Time"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Large Packet Threshold property of the Mobile GTP Per Flow Metrics. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param metrics Pointer to the Mobile GTP Per Flow Metrics. + * @param threshold The Large Packet Threshold to be set. + *****************************************************************************/ +void evel_mobile_gtp_metrics_large_pkt_thresh_set( + MOBILE_GTP_PER_FLOW_METRICS * metrics, + double threshold) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(metrics != NULL); + assert(threshold >= 0.0); + + evel_set_option_double(&metrics->large_packet_threshold, + threshold, + "Large Packet Threshold"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Max Receive Bit Rate property of the Mobile GTP Per Flow Metrics. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param metrics Pointer to the Mobile GTP Per Flow Metrics. + * @param rate The Max Receive Bit Rate to be set. + *****************************************************************************/ +void evel_mobile_gtp_metrics_max_rcv_bit_rate_set( + MOBILE_GTP_PER_FLOW_METRICS * metrics, + int rate) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(metrics != NULL); + assert(rate >= 0); + + evel_set_option_int(&metrics->max_receive_bit_rate, + rate, + "Max Receive Bit Rate"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Max Transmit Bit Rate property of the Mobile GTP Per Flow Metrics. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param metrics Pointer to the Mobile GTP Per Flow Metrics. + * @param rate The Max Transmit Bit Rate to be set. + *****************************************************************************/ +void evel_mobile_gtp_metrics_max_trx_bit_rate_set( + MOBILE_GTP_PER_FLOW_METRICS * metrics, + int rate) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(metrics != NULL); + assert(rate >= 0); + + evel_set_option_int(&metrics->max_transmit_bit_rate, + rate, + "Max Transmit Bit Rate"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Number of GTP Echo Failures property of the Mobile GTP Per Flow + * Metrics. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param metrics Pointer to the Mobile GTP Per Flow Metrics. + * @param num The Number of GTP Echo Failures to be set. + *****************************************************************************/ +void evel_mobile_gtp_metrics_num_echo_fail_set( + MOBILE_GTP_PER_FLOW_METRICS * metrics, + int num) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(metrics != NULL); + assert(num >= 0); + + evel_set_option_int(&metrics->num_gtp_echo_failures, + num, + "Number of GTP Echo Failures"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Number of GTP Tunnel Errors property of the Mobile GTP Per Flow + * Metrics. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param metrics Pointer to the Mobile GTP Per Flow Metrics. + * @param num The Number of GTP Tunnel Errors to be set. + *****************************************************************************/ +void evel_mobile_gtp_metrics_num_tun_fail_set( + MOBILE_GTP_PER_FLOW_METRICS * metrics, + int num) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(metrics != NULL); + assert(num >= 0); + + evel_set_option_int(&metrics->num_gtp_tunnel_errors, + num, + "Number of GTP Tunnel Errors"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Number of HTTP Errors property of the Mobile GTP Per Flow Metrics. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param metrics Pointer to the Mobile GTP Per Flow Metrics. + * @param num The Number of HTTP Errors to be set. + *****************************************************************************/ +void evel_mobile_gtp_metrics_num_http_errors_set( + MOBILE_GTP_PER_FLOW_METRICS * metrics, + int num) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(metrics != NULL); + assert(num >= 0); + + evel_set_option_int(&metrics->num_http_errors, + num, + "Number of HTTP Errors"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Add a TCP flag count to the metrics. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param metrics Pointer to the Mobile GTP Per Flow Metrics. + * @param tcp_flag The TCP flag to be updated. + * @param count The associated flag count, which must be nonzero. + *****************************************************************************/ +void evel_mobile_gtp_metrics_tcp_flag_count_add( + MOBILE_GTP_PER_FLOW_METRICS * metrics, + const EVEL_TCP_FLAGS tcp_flag, + const int count) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(metrics != NULL); + assert(tcp_flag >= 0); + assert(tcp_flag < EVEL_MAX_TCP_FLAGS); + assert(count >= 0); + + EVEL_DEBUG("TCP Flag: %d", tcp_flag); + evel_set_option_int(&metrics->tcp_flag_counts[tcp_flag], + count, + "TCP flag"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Add a QCI COS count to the metrics. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param metrics Pointer to the Mobile GTP Per Flow Metrics. + * @param qci_cos The QCI COS count to be updated. + * @param count The associated QCI COS count. + *****************************************************************************/ +void evel_mobile_gtp_metrics_qci_cos_count_add( + MOBILE_GTP_PER_FLOW_METRICS * metrics, + const EVEL_QCI_COS_TYPES qci_cos, + const int count) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(metrics != NULL); + assert(qci_cos >= 0); + assert(qci_cos < EVEL_MAX_QCI_COS_TYPES); + assert(count >= 0); + + EVEL_DEBUG("QCI COS: %d", qci_cos); + evel_set_option_int(&metrics->qci_cos_counts[qci_cos], + count, + "QCI COS"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Encode the Mobile Flow GTP Per Flow Metrics as a JSON object. + * + * @param jbuf Pointer to working ::EVEL_JSON_BUFFER. + * @param metrics Pointer to the ::EVENT_MOBILE_FLOW to encode. + * @returns Number of bytes actually written. + *****************************************************************************/ +void evel_json_encode_mobile_flow_gtp_flow_metrics( + EVEL_JSON_BUFFER * jbuf, + MOBILE_GTP_PER_FLOW_METRICS * metrics) +{ + int index; + bool found_ip_tos; + bool found_tcp_flag; + bool found_qci_cos; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(jbuf != NULL); + assert(metrics != NULL); + + evel_json_open_named_object(jbuf, "gtpPerFlowMetrics"); + + /***************************************************************************/ + /* Mandatory parameters. */ + /***************************************************************************/ + evel_enc_kv_double(jbuf, "avgBitErrorRate", metrics->avg_bit_error_rate); + evel_enc_kv_double( + jbuf, "avgPacketDelayVariation", metrics->avg_packet_delay_variation); + evel_enc_kv_int(jbuf, "avgPacketLatency", metrics->avg_packet_latency); + evel_enc_kv_int( + jbuf, "avgReceiveThroughput", metrics->avg_receive_throughput); + evel_enc_kv_int( + jbuf, "avgTransmitThroughput", metrics->avg_transmit_throughput); + evel_enc_kv_int(jbuf, "flowActivationEpoch", metrics->flow_activation_epoch); + evel_enc_kv_int( + jbuf, "flowActivationMicrosec", metrics->flow_activation_microsec); + evel_enc_kv_int( + jbuf, "flowDeactivationEpoch", metrics->flow_deactivation_epoch); + evel_enc_kv_int( + jbuf, "flowDeactivationMicrosec", metrics->flow_deactivation_microsec); + evel_enc_kv_time( + jbuf, "flowDeactivationTime", &metrics->flow_deactivation_time); + evel_enc_kv_string(jbuf, "flowStatus", metrics->flow_status); + evel_enc_kv_int( + jbuf, "maxPacketDelayVariation", metrics->max_packet_delay_variation); + evel_enc_kv_int( + jbuf, "numActivationFailures", metrics->num_activation_failures); + evel_enc_kv_int(jbuf, "numBitErrors", metrics->num_bit_errors); + evel_enc_kv_int(jbuf, "numBytesReceived", metrics->num_bytes_received); + evel_enc_kv_int(jbuf, "numBytesTransmitted", metrics->num_bytes_transmitted); + evel_enc_kv_int(jbuf, "numDroppedPackets", metrics->num_dropped_packets); + evel_enc_kv_int(jbuf, "numL7BytesReceived", metrics->num_l7_bytes_received); + evel_enc_kv_int( + jbuf, "numL7BytesTransmitted", metrics->num_l7_bytes_transmitted); + evel_enc_kv_int(jbuf, "numLostPackets", metrics->num_lost_packets); + evel_enc_kv_int( + jbuf, "numOutOfOrderPackets", metrics->num_out_of_order_packets); + evel_enc_kv_int(jbuf, "numPacketErrors", metrics->num_packet_errors); + evel_enc_kv_int(jbuf, + "numPacketsReceivedExclRetrans", + metrics->num_packets_received_excl_retrans); + evel_enc_kv_int(jbuf, + "numPacketsReceivedInclRetrans", + metrics->num_packets_received_incl_retrans); + evel_enc_kv_int(jbuf, + "numPacketsTransmittedInclRetrans", + metrics->num_packets_transmitted_incl_retrans); + evel_enc_kv_int(jbuf, "numRetries", metrics->num_retries); + evel_enc_kv_int(jbuf, "numTimeouts", metrics->num_timeouts); + evel_enc_kv_int(jbuf, + "numTunneledL7BytesReceived", + metrics->num_tunneled_l7_bytes_received); + evel_enc_kv_int(jbuf, "roundTripTime", metrics->round_trip_time); + evel_enc_kv_int(jbuf, "timeToFirstByte", metrics->time_to_first_byte); + + /***************************************************************************/ + /* Optional parameters. */ + /***************************************************************************/ + found_ip_tos = false; + for (index = 0; index < EVEL_TOS_SUPPORTED; index++) + { + if (metrics->ip_tos_counts[index].is_set) + { + found_ip_tos = true; + break; + } + } + + if (found_ip_tos) + { + evel_json_open_named_list(jbuf, "ipTosCountList"); + for (index = 0; index < EVEL_TOS_SUPPORTED; index++) + { + if (metrics->ip_tos_counts[index].is_set) + { + evel_enc_list_item(jbuf, + "[\"%d\", %d]", + index, + metrics->ip_tos_counts[index].value); + } + } + evel_json_close_list(jbuf); + } + + if (found_ip_tos) + { + evel_json_open_named_list(jbuf, "ipTosList"); + for (index = 0; index < EVEL_TOS_SUPPORTED; index++) + { + if (metrics->ip_tos_counts[index].is_set) + { + evel_enc_list_item(jbuf, "\"%d\"", index); + } + } + evel_json_close_list(jbuf); + } + + /***************************************************************************/ + /* Make some compile-time assertions about EVEL_TCP_FLAGS. If you update */ + /* these, make sure you update evel_tcp_flag_strings to match the enum. */ + /***************************************************************************/ + EVEL_CT_ASSERT(EVEL_TCP_NS == 0); + EVEL_CT_ASSERT(EVEL_TCP_CWR == 1); + EVEL_CT_ASSERT(EVEL_TCP_ECE == 2); + EVEL_CT_ASSERT(EVEL_TCP_URG == 3); + EVEL_CT_ASSERT(EVEL_TCP_ACK == 4); + EVEL_CT_ASSERT(EVEL_TCP_PSH == 5); + EVEL_CT_ASSERT(EVEL_TCP_RST == 6); + EVEL_CT_ASSERT(EVEL_TCP_SYN == 7); + EVEL_CT_ASSERT(EVEL_TCP_FIN == 8); + EVEL_CT_ASSERT(EVEL_MAX_TCP_FLAGS == 9); + + found_tcp_flag = false; + for (index = 0; index < EVEL_MAX_TCP_FLAGS; index++) + { + if (metrics->tcp_flag_counts[index].is_set) + { + found_tcp_flag = true; + break; + } + } + + if (found_tcp_flag) + { + evel_json_open_named_list(jbuf, "tcpFlagList"); + for (index = 0; index < EVEL_MAX_TCP_FLAGS; index++) + { + if (metrics->tcp_flag_counts[index].is_set) + { + evel_enc_list_item(jbuf, + "\"%s\"", + evel_tcp_flag_strings[index]); + } + } + evel_json_close_list(jbuf); + } + + if (found_tcp_flag) + { + evel_json_open_named_list(jbuf, "tcpFlagCountList"); + for (index = 0; index < EVEL_MAX_TCP_FLAGS; index++) + { + if (metrics->tcp_flag_counts[index].is_set) + { + evel_enc_list_item(jbuf, + "[\"%s\", %d]", + evel_tcp_flag_strings[index], + metrics->tcp_flag_counts[index].value); + } + } + evel_json_close_list(jbuf); + } + + /***************************************************************************/ + /* Make some compile-time assertions about EVEL_QCI_COS_TYPES. If you */ + /* update these, make sure you update evel_qci_cos_strings to match the */ + /* enum. */ + /***************************************************************************/ + EVEL_CT_ASSERT(EVEL_QCI_COS_UMTS_CONVERSATIONAL ==0); + EVEL_CT_ASSERT(EVEL_QCI_COS_UMTS_STREAMING == 1); + EVEL_CT_ASSERT(EVEL_QCI_COS_UMTS_INTERACTIVE == 2); + EVEL_CT_ASSERT(EVEL_QCI_COS_UMTS_BACKGROUND == 3); + EVEL_CT_ASSERT(EVEL_QCI_COS_LTE_1 == 4); + EVEL_CT_ASSERT(EVEL_QCI_COS_LTE_2 == 5); + EVEL_CT_ASSERT(EVEL_QCI_COS_LTE_3 == 6); + EVEL_CT_ASSERT(EVEL_QCI_COS_LTE_4 == 7); + EVEL_CT_ASSERT(EVEL_QCI_COS_LTE_65 == 8); + EVEL_CT_ASSERT(EVEL_QCI_COS_LTE_66 == 9); + EVEL_CT_ASSERT(EVEL_QCI_COS_LTE_5 == 10); + EVEL_CT_ASSERT(EVEL_QCI_COS_LTE_6 == 11); + EVEL_CT_ASSERT(EVEL_QCI_COS_LTE_7 == 12); + EVEL_CT_ASSERT(EVEL_QCI_COS_LTE_8 == 13); + EVEL_CT_ASSERT(EVEL_QCI_COS_LTE_9 == 14); + EVEL_CT_ASSERT(EVEL_QCI_COS_LTE_69 == 15); + EVEL_CT_ASSERT(EVEL_QCI_COS_LTE_70 == 16); + EVEL_CT_ASSERT(EVEL_MAX_QCI_COS_TYPES == 17); + + found_qci_cos = false; + for (index = 0; index < EVEL_MAX_QCI_COS_TYPES; index++) + { + if (metrics->qci_cos_counts[index].is_set) + { + found_qci_cos = true; + break; + } + } + + if (found_qci_cos) + { + evel_json_open_named_list(jbuf, "mobileQciCosList"); + for (index = 0; index < EVEL_MAX_QCI_COS_TYPES; index++) + { + if (metrics->qci_cos_counts[index].is_set) + { + evel_enc_list_item(jbuf, + "\"%s\"", + evel_qci_cos_strings[index]); + } + } + evel_json_close_list(jbuf); + } + + if (found_qci_cos) + { + evel_json_open_named_list(jbuf, "mobileQciCosCountList"); + for (index = 0; index < EVEL_MAX_QCI_COS_TYPES; index++) + { + if (metrics->qci_cos_counts[index].is_set) + { + evel_enc_list_item(jbuf, + "[\"%s\", %d]", + evel_qci_cos_strings[index], + metrics->qci_cos_counts[index].value); + } + } + evel_json_close_list(jbuf); + } + + evel_enc_kv_opt_int( + jbuf, "durConnectionFailedStatus", &metrics->dur_connection_failed_status); + evel_enc_kv_opt_int( + jbuf, "durTunnelFailedStatus", &metrics->dur_tunnel_failed_status); + evel_enc_kv_opt_string(jbuf, "flowActivatedBy", &metrics->flow_activated_by); + evel_enc_kv_opt_time( + jbuf, "flowActivationTime", &metrics->flow_activation_time); + evel_enc_kv_opt_string( + jbuf, "flowDeactivatedBy", &metrics->flow_deactivated_by); + evel_enc_kv_opt_string( + jbuf, "gtpConnectionStatus", &metrics->gtp_connection_status); + evel_enc_kv_opt_string(jbuf, "gtpTunnelStatus", &metrics->gtp_tunnel_status); + evel_enc_kv_opt_int(jbuf, "largePacketRtt", &metrics->large_packet_rtt); + evel_enc_kv_opt_double( + jbuf, "largePacketThreshold", &metrics->large_packet_threshold); + evel_enc_kv_opt_int( + jbuf, "maxReceiveBitRate", &metrics->max_receive_bit_rate); + evel_enc_kv_opt_int( + jbuf, "maxTransmitBitRate", &metrics->max_transmit_bit_rate); + evel_enc_kv_opt_int( + jbuf, "numGtpEchoFailures", &metrics->num_gtp_echo_failures); + evel_enc_kv_opt_int( + jbuf, "numGtpTunnelErrors", &metrics->num_gtp_tunnel_errors); + evel_enc_kv_opt_int(jbuf, "numHttpErrors", &metrics->num_http_errors); + + evel_json_close_object(jbuf); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Free a Mobile GTP Per Flow Metrics. + * + * Free off the Mobile GTP Per Flow Metrics supplied. Will free all the + * contained allocated memory. + * + * @note It does not free the Mobile GTP Per Flow Metrics itself, since that + * may be part of a larger structure. + *****************************************************************************/ +void evel_free_mobile_gtp_flow_metrics(MOBILE_GTP_PER_FLOW_METRICS * metrics) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(metrics != NULL); + + /***************************************************************************/ + /* Free all internal strings. */ + /***************************************************************************/ + free(metrics->flow_status); + + evel_free_option_string(&metrics->flow_activated_by); + evel_free_option_string(&metrics->flow_deactivated_by); + evel_free_option_string(&metrics->gtp_connection_status); + evel_free_option_string(&metrics->gtp_tunnel_status); + + EVEL_EXIT(); +} diff --git a/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_option.c b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_option.c new file mode 100644 index 0000000..7d53e8f --- /dev/null +++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_option.c @@ -0,0 +1,526 @@ +/*************************************************************************//** + * + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************/ +/**************************************************************************//** + * @file + * Source module relating to EVEL_OPTION_ types. + * + ****************************************************************************/ + +#include +#include +#include + +#include "evel_internal.h" + +/**************************************************************************//** + * Free the underlying resources of an ::EVEL_OPTION_STRING. + * + * @param option Pointer to the ::EVEL_OPTION_STRING. + *****************************************************************************/ +void evel_free_option_string(EVEL_OPTION_STRING * const option) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(option != NULL); + + if (option->is_set) + { + free(option->value); + option->value = NULL; + option->is_set = EVEL_FALSE; + } + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Initialize an ::EVEL_OPTION_STRING to a not-set state. + * + * @param option Pointer to the ::EVEL_OPTION_STRING. + *****************************************************************************/ +void evel_init_option_string(EVEL_OPTION_STRING * const option) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(option != NULL); + + option->value = NULL; + option->is_set = EVEL_FALSE; + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the value of an ::EVEL_OPTION_STRING. + * + * @param option Pointer to the ::EVEL_OPTION_STRING. + * @param value The value to set. + * @param description Description to be used in logging. + *****************************************************************************/ +void evel_set_option_string(EVEL_OPTION_STRING * const option, + const char * const value, + const char * const description) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(option != NULL); + assert(value != NULL); + assert(description != NULL); + + if (option->is_set) + { + EVEL_ERROR("Ignoring attempt to update %s to %s. %s already set to %s", + description, value, description, option->value); + } + else + { + EVEL_DEBUG("Setting %s to %s", description, value); + option->value = strdup(value); + option->is_set = EVEL_TRUE; + } + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Force the value of an ::EVEL_OPTION_STRING. + * + * @param option Pointer to the ::EVEL_OPTION_STRING. + * @param value The value to set. + *****************************************************************************/ +void evel_force_option_string(EVEL_OPTION_STRING * const option, + const char * const value) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(option != NULL); + assert(option->is_set == EVEL_FALSE); + assert(option->value == NULL); + + option->value = strdup(value); + option->is_set = EVEL_TRUE; + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Initialize an ::EVEL_OPTION_INT to a not-set state. + * + * @param option Pointer to the ::EVEL_OPTION_INT. + *****************************************************************************/ +void evel_init_option_int(EVEL_OPTION_INT * const option) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(option != NULL); + + option->value = 0; + option->is_set = EVEL_FALSE; + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Force the value of an ::EVEL_OPTION_INT. + * + * @param option Pointer to the ::EVEL_OPTION_INT. + * @param value The value to set. + *****************************************************************************/ +void evel_force_option_int(EVEL_OPTION_INT * const option, + const int value) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(option != NULL); + + option->value = value; + option->is_set = EVEL_TRUE; + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the value of an ::EVEL_OPTION_INT. + * + * @param option Pointer to the ::EVEL_OPTION_INT. + * @param value The value to set. + * @param description Description to be used in logging. + *****************************************************************************/ +void evel_set_option_int(EVEL_OPTION_INT * const option, + const int value, + const char * const description) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(option != NULL); + assert(description != NULL); + + if (option->is_set) + { + EVEL_ERROR("Ignoring attempt to update %s to %d. %s already set to %d", + description, value, description, option->value); + } + else + { + EVEL_DEBUG("Setting %s to %d", description, value); + option->value = value; + option->is_set = EVEL_TRUE; + } + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Initialize an ::EVEL_OPTION_DOUBLE to a not-set state. + * + * @param option Pointer to the ::EVEL_OPTION_DOUBLE. + *****************************************************************************/ +void evel_init_option_double(EVEL_OPTION_DOUBLE * const option) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(option != NULL); + + option->value = 0.0; + option->is_set = EVEL_FALSE; + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Force the value of an ::EVEL_OPTION_DOUBLE. + * + * @param option Pointer to the ::EVEL_OPTION_DOUBLE. + * @param value The value to set. + *****************************************************************************/ +void evel_force_option_double(EVEL_OPTION_DOUBLE * const option, + const double value) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(option != NULL); + + option->value = value; + option->is_set = EVEL_TRUE; + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the value of an ::EVEL_OPTION_DOUBLE. + * + * @param option Pointer to the ::EVEL_OPTION_DOUBLE. + * @param value The value to set. + * @param description Description to be used in logging. + *****************************************************************************/ +void evel_set_option_double(EVEL_OPTION_DOUBLE * const option, + const double value, + const char * const description) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(option != NULL); + assert(description != NULL); + + if (option->is_set) + { + EVEL_ERROR("Ignoring attempt to update %s to %lf. %s already set to %lf", + description, value, description, option->value); + } + else + { + EVEL_DEBUG("Setting %s to %lf", description, value); + option->value = value; + option->is_set = EVEL_TRUE; + } + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Initialize an ::EVEL_OPTION_ULL to a not-set state. + * + * @param option Pointer to the ::EVEL_OPTION_ULL. + *****************************************************************************/ +void evel_init_option_ull(EVEL_OPTION_ULL * const option) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(option != NULL); + option->value = 0; + option->is_set = EVEL_FALSE; + EVEL_EXIT(); +} + +/**************************************************************************//** + * Force the value of an ::EVEL_OPTION_ULL. + * + * @param option Pointer to the ::EVEL_OPTION_ULL. + * @param value The value to set. + *****************************************************************************/ +void evel_force_option_ull(EVEL_OPTION_ULL * const option, + const unsigned long long value) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(option != NULL); + + option->value = value; + option->is_set = EVEL_TRUE; + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the value of an ::EVEL_OPTION_ULL. + * + * @param option Pointer to the ::EVEL_OPTION_ULL. + * @param value The value to set. + * @param description Description to be used in logging. + *****************************************************************************/ +void evel_set_option_ull(EVEL_OPTION_ULL * const option, + const unsigned long long value, + const char * const description) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(option != NULL); + assert(description != NULL); + + if (option->is_set) + { + EVEL_ERROR("Ignoring attempt to update %s to %llu. %s already set to %llu", + description, value, description, option->value); + } + else + { + EVEL_DEBUG("Setting %s to %llu", description, value); + option->value = value; + option->is_set = EVEL_TRUE; + } + EVEL_EXIT(); +} + + +/**************************************************************************//** + * Initialize an ::EVEL_OPTION_INTHEADER_FIELDS to a not-set state. + * + * @param option Pointer to the ::EVEL_OPTION_INTHEADER_FIELDS. + *****************************************************************************/ +void evel_init_option_intheader(EVEL_OPTION_INTHEADER_FIELDS * const option) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(option != NULL); + option->object = NULL; + option->is_set = EVEL_FALSE; + EVEL_EXIT(); +} + +/**************************************************************************//** + * Force the value of an ::EVEL_OPTION_INTHEADER_FIELDS. + * + * @param option Pointer to the ::EVEL_OPTION_INTHEADER_FIELDS. + * @param value The value to set. + *****************************************************************************/ +void evel_force_option_intheader(EVEL_OPTION_INTHEADER_FIELDS * const option, + const void* value) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(option != NULL); + + option->object = value; + option->is_set = EVEL_TRUE; + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the value of an ::EVEL_OPTION_INTHEADER_FIELDS. + * + * @param option Pointer to the ::EVEL_OPTION_INTHEADER_FIELDS. + * @param value The value to set. + * @param description Description to be used in logging. + *****************************************************************************/ +void evel_set_option_intheader(EVEL_OPTION_INTHEADER_FIELDS * const option, + const void * value, + const char * const description) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(option != NULL); + assert(description != NULL); + + if (option->is_set) + { + EVEL_ERROR("Ignoring attempt to update %s to %llu. %s already set to %llu", + description, value, description, option->object); + } + else + { + EVEL_DEBUG("Setting %s to %llu", description, value); + option->object = value; + option->is_set = EVEL_TRUE; + } + EVEL_EXIT(); +} + +/**************************************************************************//** + * Free the underlying resources of an ::EVEL_OPTION_INTHEADER_FIELDS. + * + * @param option Pointer to the ::EVEL_OPTION_INTHEADER_FIELDS. + *****************************************************************************/ +void evel_free_option_intheader(EVEL_OPTION_INTHEADER_FIELDS * const option) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(option != NULL); + + if (option->is_set) + { + free(option->object); + option->object = NULL; + option->is_set = EVEL_FALSE; + } + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Initialize an ::EVEL_OPTION_TIME to a not-set state. + * + * @param option Pointer to the ::EVEL_OPTION_TIME. + *****************************************************************************/ +void evel_init_option_time(EVEL_OPTION_TIME * const option) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(option != NULL); + option->value = 0; + option->is_set = EVEL_FALSE; + EVEL_EXIT(); +} + +/**************************************************************************//** + * Force the value of an ::EVEL_OPTION_TIME. + * + * @param option Pointer to the ::EVEL_OPTION_TIME. + * @param value The value to set. + *****************************************************************************/ +void evel_force_option_time(EVEL_OPTION_TIME * const option, + const time_t value) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(option != NULL); + + option->value = value; + option->is_set = EVEL_TRUE; + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the value of an ::EVEL_OPTION_TIME. + * + * @param option Pointer to the ::EVEL_OPTION_TIME. + * @param value The value to set. + * @param description Description to be used in logging. + *****************************************************************************/ +void evel_set_option_time(EVEL_OPTION_TIME * const option, + const time_t value, + const char * const description) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(option != NULL); + assert(description != NULL); + + if (option->is_set) + { + EVEL_ERROR("Ignoring attempt to update %s to %d. %s already set to %d", + description, value, description, option->value); + } + else + { + EVEL_DEBUG("Setting %s to %d", description, value); + option->value = value; + option->is_set = EVEL_TRUE; + } + EVEL_EXIT(); +} diff --git a/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_other.c b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_other.c new file mode 100644 index 0000000..c7a227b --- /dev/null +++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_other.c @@ -0,0 +1,492 @@ +/*************************************************************************//** + * + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************/ + +/**************************************************************************//** + * @file + * Implementation of EVEL functions relating to Other. + * + ****************************************************************************/ + +#include +#include +#include + +#include "evel.h" +#include "evel_internal.h" + +/**************************************************************************//** + * Create a new Other event. + * + * @note The mandatory fields on the Other must be supplied to this factory + * function and are immutable once set. Optional fields have explicit + * setter functions, but again values may only be set once so that the + * Other has immutable properties. + * @returns pointer to the newly manufactured ::EVENT_OTHER. If the event is + * not used (i.e. posted) it must be released using ::evel_free_other. + * @retval NULL Failed to create the event. + *****************************************************************************/ +EVENT_OTHER * evel_new_other(const char *ev_name, const char *ev_id) +{ + EVENT_OTHER * other = NULL; + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + + /***************************************************************************/ + /* Allocate the Other. */ + /***************************************************************************/ + other = malloc(sizeof(EVENT_OTHER)); + if (other == NULL) + { + log_error_state("Out of memory"); + goto exit_label; + } + memset(other, 0, sizeof(EVENT_OTHER)); + EVEL_DEBUG("New Other is at %lp", other); + + /***************************************************************************/ + /* Initialize the header & the Other fields. Optional string values are */ + /* uninitialized (NULL). */ + /***************************************************************************/ + evel_init_header_nameid(&other->header,ev_name,ev_id); + other->header.event_domain = EVEL_DOMAIN_OTHER; + other->major_version = EVEL_OTHER_EVENT_MAJOR_VERSION; + other->minor_version = EVEL_OTHER_EVENT_MINOR_VERSION; + + other->namedarrays = NULL; + dlist_initialize(&other->jsonobjects); + dlist_initialize(&other->namedvalues); + +exit_label: + EVEL_EXIT(); + return other; +} + +/**************************************************************************//** + * Set the Event Type property of the Other. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param other Pointer to the Other. + * @param type The Event Type to be set. ASCIIZ string. The caller + * does not need to preserve the value once the function + * returns. + *****************************************************************************/ +void evel_other_type_set(EVENT_OTHER * other, + const char * const type) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions and call evel_header_type_set. */ + /***************************************************************************/ + assert(other != NULL); + assert(other->header.event_domain == EVEL_DOMAIN_OTHER); + evel_header_type_set(&other->header, type); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Add a json object to jsonObject list. + * + * The name and value are null delimited ASCII strings. The library takes + * a copy so the caller does not have to preserve values after the function + * returns. + * + * @param other Pointer to the Other. + * @param size size of hashtable + *****************************************************************************/ +void evel_other_field_set_namedarraysize(EVENT_OTHER * other, const int size) +{ + OTHER_FIELD * other_field = NULL; + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(other != NULL); + assert(other->header.event_domain == EVEL_DOMAIN_OTHER); + assert(other->namedarrays == NULL); + assert(size > 0); + + EVEL_DEBUG("Adding Named array"); + + other->namedarrays = ht_create(size); + + EVEL_EXIT(); +} + + +/**************************************************************************//** + * Add a json object to jsonObject list. + * + * The name and value are null delimited ASCII strings. The library takes + * a copy so the caller does not have to preserve values after the function + * returns. + * + * @param other Pointer to the Other. + * @param size size of hashtable + *****************************************************************************/ +void evel_other_field_add_namedarray(EVENT_OTHER * other, const char *hashname, char * name, char *value) +{ + OTHER_FIELD * other_field = NULL; + DLIST *list = NULL; + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(other != NULL); + assert(other->header.event_domain == EVEL_DOMAIN_OTHER); + assert(other->namedarrays != NULL); + + EVEL_DEBUG("Adding values to Named array"); + + EVEL_DEBUG("Adding name=%s value=%s", name, value); + other_field = malloc(sizeof(OTHER_FIELD)); + assert(other_field != NULL); + memset(other_field, 0, sizeof(OTHER_FIELD)); + other_field->name = strdup(name); + other_field->value = strdup(value); + assert(other_field->name != NULL); + assert(other_field->value != NULL); + + + list = ht_get(other->namedarrays, hashname); + if( list == NULL ) + { + DLIST * nlist = malloc(sizeof(DLIST)); + dlist_initialize(nlist); + dlist_push_last(nlist, other_field); + ht_set(other->namedarrays, hashname, nlist); + EVEL_DEBUG("Created to new table table"); + } + else + { + dlist_push_last(list, other_field); + EVEL_DEBUG("Adding to existing table"); + } + + EVEL_EXIT(); +} + + +/**************************************************************************//** + * Add a json object to jsonObject list. + * + * The name and value are null delimited ASCII strings. The library takes + * a copy so the caller does not have to preserve values after the function + * returns. + * + * @param other Pointer to the Other. + * @param jsonobj Pointer to json object + *****************************************************************************/ +void evel_other_field_add_jsonobj(EVENT_OTHER * other, EVEL_JSON_OBJECT *jsonobj) +{ + OTHER_FIELD * other_field = NULL; + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(other != NULL); + assert(other->header.event_domain == EVEL_DOMAIN_OTHER); + assert(jsonobj != NULL); + + EVEL_DEBUG("Adding jsonObject"); + + dlist_push_last(&other->jsonobjects, jsonobj); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Add a field name/value pair to the Other. + * + * The name and value are null delimited ASCII strings. The library takes + * a copy so the caller does not have to preserve values after the function + * returns. + * + * @param other Pointer to the Other. + * @param name ASCIIZ string with the field's name. The caller does not + * need to preserve the value once the function returns. + * @param value ASCIIZ string with the field's value. The caller does not + * need to preserve the value once the function returns. + *****************************************************************************/ +void evel_other_field_add(EVENT_OTHER * other, char * name, char * value) +{ + OTHER_FIELD * other_field = NULL; + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(other != NULL); + assert(other->header.event_domain == EVEL_DOMAIN_OTHER); + assert(name != NULL); + assert(value != NULL); + + EVEL_DEBUG("Adding name=%s value=%s", name, value); + other_field = malloc(sizeof(OTHER_FIELD)); + assert(other_field != NULL); + memset(other_field, 0, sizeof(OTHER_FIELD)); + other_field->name = strdup(name); + other_field->value = strdup(value); + assert(other_field->name != NULL); + assert(other_field->value != NULL); + + dlist_push_last(&other->namedvalues, other_field); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Encode the Other in JSON according to AT&T's schema for the event type. + * + * @param jbuf Pointer to the ::EVEL_JSON_BUFFER to encode into. + * @param event Pointer to the ::EVENT_HEADER to encode. + *****************************************************************************/ +void evel_json_encode_other(EVEL_JSON_BUFFER * jbuf, + EVENT_OTHER * event) +{ + OTHER_FIELD * other_field = NULL; + EVEL_JSON_OBJECT * jsonobjp = NULL; + DLIST_ITEM * other_field_item = NULL; + EVEL_JSON_OBJECT_INSTANCE * jsonobjinst = NULL; + DLIST_ITEM * jsobj_field_item = NULL; + EVEL_INTERNAL_KEY * keyinst = NULL; + DLIST_ITEM * keyinst_field_item = NULL; + HASHTABLE_T *ht = NULL; + int i; + bool itm_added = false; + DLIST *itm_list = NULL; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(event != NULL); + assert(event->header.event_domain == EVEL_DOMAIN_OTHER); + + evel_json_encode_header(jbuf, &event->header); + evel_json_open_named_object(jbuf, "otherFields"); + +// iterate through hashtable and print DLIST for each entry + + ht = event->namedarrays; + if( ht != NULL ) + { + if( ht->size > 0) + { + for( i = 0; i < ht->size; i++ ) { + if( ht->table[i] != NULL) + { + itm_added = true; + } + } + if( itm_added == true) + { + + if (evel_json_open_opt_named_list(jbuf, "hashOfNameValuePairArrays")) + { + for( i = 0; i < ht->size; i++ ) { + if( ht->table[i] != NULL) + { + itm_list = ht->table[i]; + + if(evel_json_open_opt_named_list(jbuf, ht->table[i]->key)) + { + other_field_item = dlist_get_first(&itm_list); + while (other_field_item != NULL) + { + other_field = (OTHER_FIELD *) other_field_item->item; + if(other_field != NULL){ + evel_json_open_object(jbuf); + evel_enc_kv_string(jbuf, "name", other_field->name); + evel_enc_kv_string(jbuf, "value", other_field->value); + evel_json_close_object(jbuf); + other_field_item = dlist_get_next(other_field_item); + } + } + evel_json_close_list(jbuf); + } + + } + } + + evel_json_close_list(jbuf); + } + + + } + } + } + + evel_json_checkpoint(jbuf); + if(evel_json_open_opt_named_list(jbuf, "jsonObjects")) + { + bool item_added = false; + other_field_item = dlist_get_first(&event->jsonobjects); + while (other_field_item != NULL) + { + jsonobjp = (EVEL_JSON_OBJECT *) other_field_item->item; + if(jsonobjp != NULL); + { + evel_json_open_object(jbuf); + + if( evel_json_open_opt_named_list(jbuf, "objectInstances")) + { + bool item_added2 = false; + jsobj_field_item = dlist_get_first(&jsonobjp->jsonobjectinstances); + while (jsobj_field_item != NULL) + { + jsonobjinst = (EVEL_JSON_OBJECT_INSTANCE *) jsobj_field_item->item; + if( jsonobjinst != NULL ) + { + evel_json_open_object(jbuf); + evel_enc_kv_object(jbuf, "objectInstance", jsonobjinst->jsonstring); + evel_enc_kv_ull(jbuf, "objectInstanceEpochMicrosec", jsonobjinst->objinst_epoch_microsec); + //evel_json_checkpoint(jbuf); + if (evel_json_open_opt_named_list(jbuf, "objectKeys")) + { + bool item_added3 = false; + + keyinst_field_item = dlist_get_first(&jsonobjinst->object_keys); + while (keyinst_field_item != NULL) + { + keyinst = (EVEL_INTERNAL_KEY *)keyinst_field_item->item; + if(keyinst != NULL) + { + evel_json_open_object(jbuf); + evel_enc_kv_string(jbuf, "keyName", keyinst->keyname); + evel_enc_kv_opt_int(jbuf, "keyOrder", &keyinst->keyorder); + evel_enc_kv_opt_string(jbuf, "keyValue", &keyinst->keyvalue); + evel_json_close_object(jbuf); + item_added3 = false; + } + keyinst_field_item = dlist_get_next(keyinst_field_item); + } + evel_json_close_list(jbuf); + + /*************************************************************************/ + /* If we've not written anything, rewind to before we opened the list. */ + /*************************************************************************/ + //if (!item_added3) + //{ + // evel_json_rewind(jbuf); + //} + } + evel_json_close_object(jbuf); + } + item_added2 = true; + jsobj_field_item = dlist_get_next(jsobj_field_item); + } + evel_json_close_list(jbuf); + if( !item_added2 ) + { + evel_json_rewind(jbuf); + } + } + + evel_enc_kv_string(jbuf, "objectName", jsonobjp->object_name); + evel_enc_kv_opt_string(jbuf, "objectSchema", &jsonobjp->objectschema); + evel_enc_kv_opt_string(jbuf, "objectSchemaUrl", &jsonobjp->objectschemaurl); + evel_enc_kv_opt_string(jbuf, "nfSubscribedObjectName", &jsonobjp->nfsubscribedobjname); + evel_enc_kv_opt_string(jbuf, "nfSubscriptionId", &jsonobjp->nfsubscriptionid); + evel_json_close_object(jbuf); + item_added = true; + } + other_field_item = dlist_get_next(other_field_item); + } + evel_json_close_list(jbuf); + + if (!item_added) + { + evel_json_rewind(jbuf); + } + + } + + if( evel_json_open_opt_named_list(jbuf, "nameValuePairs")) + { + other_field_item = dlist_get_first(&event->namedvalues); + while (other_field_item != NULL) + { + other_field = (OTHER_FIELD *) other_field_item->item; + assert(other_field != NULL); + + evel_json_open_object(jbuf); + evel_enc_kv_string(jbuf, "name", other_field->name); + evel_enc_kv_string(jbuf, "value", other_field->value); + evel_json_close_object(jbuf); + other_field_item = dlist_get_next(other_field_item); + } + } + evel_json_close_list(jbuf); + + evel_enc_version(jbuf, "otherFieldsVersion", event->major_version,event->minor_version); + + evel_json_close_object(jbuf); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Free an Other. + * + * Free off the Other supplied. Will free all the contained allocated memory. + * + * @note It does not free the Other itself, since that may be part of a + * larger structure. + *****************************************************************************/ +void evel_free_other(EVENT_OTHER * event) +{ + OTHER_FIELD * other_field = NULL; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. As an internal API we don't allow freeing NULL */ + /* events as we do on the public API. */ + /***************************************************************************/ + assert(event != NULL); + assert(event->header.event_domain == EVEL_DOMAIN_OTHER); + + /***************************************************************************/ + /* Free all internal strings then the header itself. */ + /***************************************************************************/ + other_field = dlist_pop_last(&event->namedvalues); + while (other_field != NULL) + { + EVEL_DEBUG("Freeing Other Field (%s, %s)", + other_field->name, + other_field->value); + free(other_field->name); + free(other_field->value); + free(other_field); + other_field = dlist_pop_last(&event->namedvalues); + } + evel_free_header(&event->header); + + EVEL_EXIT(); +} diff --git a/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_reporting_measurement.c b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_reporting_measurement.c new file mode 100644 index 0000000..36c34da --- /dev/null +++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_reporting_measurement.c @@ -0,0 +1,437 @@ +/*************************************************************************//** + * + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************/ + +/**************************************************************************//** + * @file + * Implementation of EVEL functions relating to the Measurement for VF + * Reporting event. + * + * @note This is an experimental event tytpe and does not form part of the + * currently approved AT&T event schema. It is intended to allow a + * less-onerous event reporting mechanism because it avoids having to + * return all the platform statistics which are mandatory in the + * **measurementsForVfScaling** event. + ****************************************************************************/ + +#include +#include +#include + +#include "evel.h" +#include "evel_internal.h" +#include "evel_throttle.h" + +/**************************************************************************//** + * Create a new Report event. + * + * @note The mandatory fields on the Report must be supplied to this + * factory function and are immutable once set. Optional fields have + * explicit setter functions, but again values may only be set once so + * that the Report has immutable properties. + * + * @param measurement_interval + * @param event_name Unique Event Name + * @param event_id A universal identifier of the event for analysis etc + * @returns pointer to the newly manufactured ::EVENT_REPORT. If the event is + * not used (i.e. posted) it must be released using ::evel_free_event. + * @retval NULL Failed to create the event. + *****************************************************************************/ +EVENT_REPORT * evel_new_report(double measurement_interval,const char *ev_name, const char *ev_id) +{ + EVENT_REPORT * report = NULL; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(measurement_interval >= 0.0); + + /***************************************************************************/ + /* Allocate the report. */ + /***************************************************************************/ + report = malloc(sizeof(EVENT_REPORT)); + if (report == NULL) + { + log_error_state("Out of memory for Report"); + goto exit_label; + } + memset(report, 0, sizeof(EVENT_REPORT)); + EVEL_DEBUG("New report is at %lp", report); + + /***************************************************************************/ + /* Initialize the header & the report fields. */ + /***************************************************************************/ + evel_init_header_nameid(&report->header,ev_name,ev_id); + report->header.event_domain = EVEL_DOMAIN_REPORT; + report->measurement_interval = measurement_interval; + + dlist_initialize(&report->feature_usage); + dlist_initialize(&report->measurement_groups); + report->major_version = EVEL_REPORT_MAJOR_VERSION; + report->minor_version = EVEL_REPORT_MINOR_VERSION; + +exit_label: + EVEL_EXIT(); + return report; +} + +/**************************************************************************//** + * Set the Event Type property of the Report. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param report Pointer to the Report. + * @param type The Event Type to be set. ASCIIZ string. The caller + * does not need to preserve the value once the function + * returns. + *****************************************************************************/ +void evel_report_type_set(EVENT_REPORT * report, + const char * const type) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions and call evel_header_type_set. */ + /***************************************************************************/ + assert(report != NULL); + assert(report->header.event_domain == EVEL_DOMAIN_REPORT); + evel_header_type_set(&report->header, type); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Add a Feature usage value name/value pair to the Report. + * + * The name is null delimited ASCII string. The library takes + * a copy so the caller does not have to preserve values after the function + * returns. + * + * @param report Pointer to the report. + * @param feature ASCIIZ string with the feature's name. + * @param utilization Utilization of the feature. + *****************************************************************************/ +void evel_report_feature_use_add(EVENT_REPORT * report, + char * feature, + int utilization) +{ + MEASUREMENT_FEATURE_USE * feature_use = NULL; + EVEL_ENTER(); + + /***************************************************************************/ + /* Check assumptions. */ + /***************************************************************************/ + assert(report != NULL); + assert(report->header.event_domain == EVEL_DOMAIN_REPORT); + assert(feature != NULL); + assert(utilization >= 0); + + /***************************************************************************/ + /* Allocate a container for the value and push onto the list. */ + /***************************************************************************/ + EVEL_DEBUG("Adding Feature=%s Use=%d", feature, utilization); + feature_use = malloc(sizeof(MEASUREMENT_FEATURE_USE)); + assert(feature_use != NULL); + memset(feature_use, 0, sizeof(MEASUREMENT_FEATURE_USE)); + feature_use->feature_id = strdup(feature); + assert(feature_use->feature_id != NULL); + feature_use->feature_utilization = utilization; + + dlist_push_last(&report->feature_usage, feature_use); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Add a Additional Measurement value name/value pair to the Report. + * + * The name is null delimited ASCII string. The library takes + * a copy so the caller does not have to preserve values after the function + * returns. + * + * @param report Pointer to the report. + * @param group ASCIIZ string with the measurement group's name. + * @param name ASCIIZ string containing the measurement's name. + * @param value ASCIIZ string containing the measurement's value. + *****************************************************************************/ +void evel_report_custom_measurement_add(EVENT_REPORT * report, + const char * const group, + const char * const name, + const char * const value) +{ + MEASUREMENT_GROUP * measurement_group = NULL; + CUSTOM_MEASUREMENT * measurement = NULL; + DLIST_ITEM * item = NULL; + EVEL_ENTER(); + + /***************************************************************************/ + /* Check assumptions. */ + /***************************************************************************/ + assert(report != NULL); + assert(report->header.event_domain == EVEL_DOMAIN_REPORT); + assert(group != NULL); + assert(name != NULL); + assert(value != NULL); + + /***************************************************************************/ + /* Allocate a container for the name/value pair. */ + /***************************************************************************/ + EVEL_DEBUG("Adding Measurement Group=%s Name=%s Value=%s", + group, name, value); + measurement = malloc(sizeof(CUSTOM_MEASUREMENT)); + assert(measurement != NULL); + memset(measurement, 0, sizeof(CUSTOM_MEASUREMENT)); + measurement->name = strdup(name); + assert(measurement->name != NULL); + measurement->value = strdup(value); + assert(measurement->value != NULL); + + /***************************************************************************/ + /* See if we have that group already. */ + /***************************************************************************/ + item = dlist_get_first(&report->measurement_groups); + while (item != NULL) + { + measurement_group = (MEASUREMENT_GROUP *) item->item; + assert(measurement_group != NULL); + + EVEL_DEBUG("Got measurement group %s", measurement_group->name); + if (strcmp(group, measurement_group->name) == 0) + { + EVEL_DEBUG("Found existing Measurement Group"); + break; + } + item = dlist_get_next(item); + } + + /***************************************************************************/ + /* If we didn't have the group already, create it. */ + /***************************************************************************/ + if (item == NULL) + { + EVEL_DEBUG("Creating new Measurement Group"); + measurement_group = malloc(sizeof(MEASUREMENT_GROUP)); + assert(measurement_group != NULL); + memset(measurement_group, 0, sizeof(MEASUREMENT_GROUP)); + measurement_group->name = strdup(group); + assert(measurement_group->name != NULL); + dlist_initialize(&measurement_group->measurements); + dlist_push_last(&report->measurement_groups, measurement_group); + } + + /***************************************************************************/ + /* If we didn't have the group already, create it. */ + /***************************************************************************/ + dlist_push_last(&measurement_group->measurements, measurement); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Encode the report as a JSON report. + * + * @param jbuf Pointer to the ::EVEL_JSON_BUFFER to encode into. + * @param event Pointer to the ::EVENT_HEADER to encode. + *****************************************************************************/ +void evel_json_encode_report(EVEL_JSON_BUFFER * jbuf, + EVENT_REPORT * event) +{ + MEASUREMENT_FEATURE_USE * feature_use = NULL; + MEASUREMENT_GROUP * measurement_group = NULL; + CUSTOM_MEASUREMENT * custom_measurement = NULL; + DLIST_ITEM * item = NULL; + DLIST_ITEM * nested_item = NULL; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(event != NULL); + assert(event->header.event_domain == EVEL_DOMAIN_REPORT); + + evel_json_encode_header(jbuf, &event->header); + evel_json_open_named_object(jbuf, "measurementsForVfReportingFields"); + evel_enc_kv_double(jbuf, "measurementInterval", event->measurement_interval); + + /***************************************************************************/ + /* Feature Utilization list. */ + /***************************************************************************/ + evel_json_checkpoint(jbuf); + if (evel_json_open_opt_named_list(jbuf, "featureUsageArray")) + { + bool item_added = false; + + item = dlist_get_first(&event->feature_usage); + while (item != NULL) + { + feature_use = (MEASUREMENT_FEATURE_USE*) item->item; + assert(feature_use != NULL); + + if (!evel_throttle_suppress_nv_pair(jbuf->throttle_spec, + "featureUsageArray", + feature_use->feature_id)) + { + evel_json_open_object(jbuf); + evel_enc_kv_string(jbuf, "featureIdentifier", feature_use->feature_id); + evel_enc_kv_int( + jbuf, "featureUtilization", feature_use->feature_utilization); + evel_json_close_object(jbuf); + item_added = true; + } + item = dlist_get_next(item); + } + evel_json_close_list(jbuf); + + /*************************************************************************/ + /* If we've not written anything, rewind to before we opened the list. */ + /*************************************************************************/ + if (!item_added) + { + evel_json_rewind(jbuf); + } + } + + /***************************************************************************/ + /* Additional Measurement Groups list. */ + /***************************************************************************/ + evel_json_checkpoint(jbuf); + if (evel_json_open_opt_named_list(jbuf, "additionalMeasurements")) + { + bool item_added = false; + + item = dlist_get_first(&event->measurement_groups); + while (item != NULL) + { + measurement_group = (MEASUREMENT_GROUP *) item->item; + assert(measurement_group != NULL); + + if (!evel_throttle_suppress_nv_pair(jbuf->throttle_spec, + "additionalMeasurements", + measurement_group->name)) + { + evel_json_open_object(jbuf); + evel_enc_kv_string(jbuf, "name", measurement_group->name); + evel_json_open_named_list(jbuf, "measurements"); + + /*********************************************************************/ + /* Measurements list. */ + /*********************************************************************/ + nested_item = dlist_get_first(&measurement_group->measurements); + while (nested_item != NULL) + { + custom_measurement = (CUSTOM_MEASUREMENT *) nested_item->item; + assert(custom_measurement != NULL); + + evel_json_open_object(jbuf); + evel_enc_kv_string(jbuf, "name", custom_measurement->name); + evel_enc_kv_string(jbuf, "value", custom_measurement->value); + evel_json_close_object(jbuf); + nested_item = dlist_get_next(nested_item); + } + evel_json_close_list(jbuf); + evel_json_close_object(jbuf); + item_added = true; + } + item = dlist_get_next(item); + } + evel_json_close_list(jbuf); + + /*************************************************************************/ + /* If we've not written anything, rewind to before we opened the list. */ + /*************************************************************************/ + if (!item_added) + { + evel_json_rewind(jbuf); + } + } + + /***************************************************************************/ + /* Although optional, we always generate the version. Note that this */ + /* closes the object, too. */ + /***************************************************************************/ + evel_enc_version(jbuf, + "measurementFieldsVersion", + event->major_version, + event->minor_version); + evel_json_close_object(jbuf); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Free a Report. + * + * Free off the Report supplied. Will free all the contained allocated memory. + * + * @note It does not free the Report itself, since that may be part of a + * larger structure. + *****************************************************************************/ +void evel_free_report(EVENT_REPORT * event) +{ + MEASUREMENT_FEATURE_USE * feature_use = NULL; + MEASUREMENT_GROUP * measurement_group = NULL; + CUSTOM_MEASUREMENT * custom_measurement = NULL; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. As an internal API we don't allow freeing NULL */ + /* events as we do on the public API. */ + /***************************************************************************/ + assert(event != NULL); + assert(event->header.event_domain == EVEL_DOMAIN_REPORT); + + /***************************************************************************/ + /* Free all internal strings then the header itself. */ + /***************************************************************************/ + feature_use = dlist_pop_last(&event->feature_usage); + while (feature_use != NULL) + { + EVEL_DEBUG("Freeing Feature use Info (%s)", feature_use->feature_id); + free(feature_use->feature_id); + free(feature_use); + feature_use = dlist_pop_last(&event->feature_usage); + } + measurement_group = dlist_pop_last(&event->measurement_groups); + while (measurement_group != NULL) + { + EVEL_DEBUG("Freeing Measurement Group (%s)", measurement_group->name); + + custom_measurement = dlist_pop_last(&measurement_group->measurements); + while (custom_measurement != NULL) + { + EVEL_DEBUG("Freeing mesaurement (%s)", custom_measurement->name); + + free(custom_measurement->name); + free(custom_measurement->value); + free(custom_measurement); + custom_measurement = dlist_pop_last(&measurement_group->measurements); + } + + free(measurement_group->name); + free(measurement_group); + measurement_group = dlist_pop_last(&event->measurement_groups); + } + + evel_free_header(&event->header); + + EVEL_EXIT(); +} diff --git a/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_scaling_measurement.c b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_scaling_measurement.c new file mode 100644 index 0000000..b3e73c9 --- /dev/null +++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_scaling_measurement.c @@ -0,0 +1,3716 @@ +/*************************************************************************//** + * + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************/ +/**************************************************************************//** + * @file + * Implementation of EVEL functions relating to the Measurement. + * + ****************************************************************************/ + +#include +#include +#include + +#include "evel.h" +#include "evel_internal.h" +#include "evel_throttle.h" + +/**************************************************************************//** + * Create a new Measurement event. + * + * @note The mandatory fields on the Measurement must be supplied to this + * factory function and are immutable once set. Optional fields have + * explicit setter functions, but again values may only be set once so + * that the Measurement has immutable properties. + * + * @param measurement_interval + * @param event_name Unique Event Name confirming Domain AsdcModel Description + * @param event_id A universal identifier of the event for: troubleshooting correlation, analysis, etc + * + * @returns pointer to the newly manufactured ::EVENT_MEASUREMENT. If the + * event is not used (i.e. posted) it must be released using + * ::evel_free_event. + * @retval NULL Failed to create the event. + *****************************************************************************/ +EVENT_MEASUREMENT * evel_new_measurement(double measurement_interval, const char* ev_name, const char *ev_id) +{ + EVENT_MEASUREMENT * measurement = NULL; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(measurement_interval >= 0.0); + + /***************************************************************************/ + /* Allocate the measurement. */ + /***************************************************************************/ + measurement = malloc(sizeof(EVENT_MEASUREMENT)); + if (measurement == NULL) + { + log_error_state("Out of memory for Measurement"); + goto exit_label; + } + memset(measurement, 0, sizeof(EVENT_MEASUREMENT)); + EVEL_DEBUG("New measurement is at %lp", measurement); + + /***************************************************************************/ + /* Initialize the header & the measurement fields. */ + /***************************************************************************/ + evel_init_header_nameid(&measurement->header,ev_name,ev_id); + measurement->header.event_domain = EVEL_DOMAIN_MEASUREMENT; + measurement->measurement_interval = measurement_interval; + dlist_initialize(&measurement->additional_info); + dlist_initialize(&measurement->additional_measurements); + dlist_initialize(&measurement->additional_objects); + dlist_initialize(&measurement->cpu_usage); + dlist_initialize(&measurement->disk_usage); + dlist_initialize(&measurement->mem_usage); + dlist_initialize(&measurement->filesystem_usage); + dlist_initialize(&measurement->latency_distribution); + dlist_initialize(&measurement->vnic_usage); + dlist_initialize(&measurement->codec_usage); + dlist_initialize(&measurement->feature_usage); + evel_init_option_double(&measurement->mean_request_latency); + evel_init_option_int(&measurement->vnfc_scaling_metric); + evel_init_option_int(&measurement->concurrent_sessions); + evel_init_option_int(&measurement->configured_entities); + evel_init_option_int(&measurement->media_ports_in_use); + evel_init_option_int(&measurement->request_rate); + measurement->major_version = EVEL_MEASUREMENT_MAJOR_VERSION; + measurement->minor_version = EVEL_MEASUREMENT_MINOR_VERSION; + +exit_label: + EVEL_EXIT(); + return measurement; +} + +/**************************************************************************//** + * Set the Event Type property of the Measurement. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param measurement Pointer to the Measurement. + * @param type The Event Type to be set. ASCIIZ string. The caller + * does not need to preserve the value once the function + * returns. + *****************************************************************************/ +void evel_measurement_type_set(EVENT_MEASUREMENT * measurement, + const char * const type) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions and call evel_header_type_set. */ + /***************************************************************************/ + assert(measurement != NULL); + assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT); + evel_header_type_set(&measurement->header, type); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Add an additional value name/value pair to the Measurement. + * + * The name and value are null delimited ASCII strings. The library takes + * a copy so the caller does not have to preserve values after the function + * returns. + * + * @param measurement Pointer to the measurement. + * @param name ASCIIZ string with the attribute's name. The caller + * does not need to preserve the value once the function + * returns. + * @param value ASCIIZ string with the attribute's value. The caller + * does not need to preserve the value once the function + * returns. + *****************************************************************************/ +void evel_measurement_addl_info_add(EVENT_MEASUREMENT * measurement, char * name, char * value) +{ + OTHER_FIELD * addl_info = NULL; + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(measurement != NULL); + assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT); + assert(name != NULL); + assert(value != NULL); + + EVEL_DEBUG("Adding name=%s value=%s", name, value); + addl_info = malloc(sizeof(OTHER_FIELD)); + assert(addl_info != NULL); + memset(addl_info, 0, sizeof(OTHER_FIELD)); + addl_info->name = strdup(name); + addl_info->value = strdup(value); + assert(addl_info->name != NULL); + assert(addl_info->value != NULL); + + dlist_push_last(&measurement->additional_info, addl_info); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Concurrent Sessions property of the Measurement. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param measurement Pointer to the Measurement. + * @param concurrent_sessions The Concurrent Sessions to be set. + *****************************************************************************/ +void evel_measurement_conc_sess_set(EVENT_MEASUREMENT * measurement, + int concurrent_sessions) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(measurement != NULL); + assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT); + assert(concurrent_sessions >= 0); + + evel_set_option_int(&measurement->concurrent_sessions, + concurrent_sessions, + "Concurrent Sessions"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Configured Entities property of the Measurement. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param measurement Pointer to the Measurement. + * @param configured_entities The Configured Entities to be set. + *****************************************************************************/ +void evel_measurement_cfg_ents_set(EVENT_MEASUREMENT * measurement, + int configured_entities) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(measurement != NULL); + assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT); + assert(configured_entities >= 0); + + evel_set_option_int(&measurement->configured_entities, + configured_entities, + "Configured Entities"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Add an additional set of Errors to the Measurement. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param measurement Pointer to the measurement. + * @param receive_discards The number of receive discards. + * @param receive_errors The number of receive errors. + * @param transmit_discards The number of transmit discards. + * @param transmit_errors The number of transmit errors. + *****************************************************************************/ +void evel_measurement_errors_set(EVENT_MEASUREMENT * measurement, + int receive_discards, + int receive_errors, + int transmit_discards, + int transmit_errors) +{ + MEASUREMENT_ERRORS * errors = NULL; + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(measurement != NULL); + assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT); + assert(receive_discards >= 0); + assert(receive_errors >= 0); + assert(transmit_discards >= 0); + assert(transmit_errors >= 0); + + if (measurement->errors == NULL) + { + EVEL_DEBUG("Adding Errors: %d, %d; %d, %d", + receive_discards, + receive_errors, + transmit_discards, + transmit_errors); + errors = malloc(sizeof(MEASUREMENT_ERRORS)); + assert(errors != NULL); + memset(errors, 0, sizeof(MEASUREMENT_ERRORS)); + errors->receive_discards = receive_discards; + errors->receive_errors = receive_errors; + errors->transmit_discards = transmit_discards; + errors->transmit_errors = transmit_errors; + measurement->errors = errors; + } + else + { + errors = measurement->errors; + EVEL_DEBUG("Ignoring attempt to add Errors: %d, %d; %d, %d\n" + "Errors already set: %d, %d; %d, %d", + receive_discards, + receive_errors, + transmit_discards, + transmit_errors, + errors->receive_discards, + errors->receive_errors, + errors->transmit_discards, + errors->transmit_errors); + } + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Mean Request Latency property of the Measurement. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param measurement Pointer to the Measurement. + * @param mean_request_latency The Mean Request Latency to be set. + *****************************************************************************/ +void evel_measurement_mean_req_lat_set(EVENT_MEASUREMENT * measurement, + double mean_request_latency) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(measurement != NULL); + assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT); + assert(mean_request_latency >= 0.0); + + evel_set_option_double(&measurement->mean_request_latency, + mean_request_latency, + "Mean Request Latency"); + EVEL_EXIT(); +} + + +/**************************************************************************//** + * Set the Request Rate property of the Measurement. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param measurement Pointer to the Measurement. + * @param request_rate The Request Rate to be set. + *****************************************************************************/ +void evel_measurement_request_rate_set(EVENT_MEASUREMENT * measurement, + int request_rate) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(measurement != NULL); + assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT); + assert(request_rate >= 0); + + evel_set_option_int(&measurement->request_rate, + request_rate, + "Request Rate"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Add an additional CPU usage value name/value pair to the Measurement. + * + * The name and value are null delimited ASCII strings. The library takes + * a copy so the caller does not have to preserve values after the function + * returns. + * + * @param measurement Pointer to the measurement. + * @param id ASCIIZ string with the CPU's identifier. + * @param usage CPU utilization. + *****************************************************************************/ +MEASUREMENT_CPU_USE *evel_measurement_new_cpu_use_add(EVENT_MEASUREMENT * measurement, + char * id, double usage) +{ + MEASUREMENT_CPU_USE * cpu_use = NULL; + EVEL_ENTER(); + + /***************************************************************************/ + /* Check assumptions. */ + /***************************************************************************/ + assert(measurement != NULL); + assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT); + assert(id != NULL); + assert(usage >= 0.0); + + /***************************************************************************/ + /* Allocate a container for the value and push onto the list. */ + /***************************************************************************/ + EVEL_DEBUG("Adding id=%s usage=%lf", id, usage); + cpu_use = malloc(sizeof(MEASUREMENT_CPU_USE)); + assert(cpu_use != NULL); + memset(cpu_use, 0, sizeof(MEASUREMENT_CPU_USE)); + cpu_use->id = strdup(id); + cpu_use->usage = usage; + evel_init_option_double(&cpu_use->idle); + evel_init_option_double(&cpu_use->intrpt); + evel_init_option_double(&cpu_use->nice); + evel_init_option_double(&cpu_use->softirq); + evel_init_option_double(&cpu_use->steal); + evel_init_option_double(&cpu_use->sys); + evel_init_option_double(&cpu_use->user); + evel_init_option_double(&cpu_use->wait); + + dlist_push_last(&measurement->cpu_usage, cpu_use); + + EVEL_EXIT(); + return cpu_use; +} + +/**************************************************************************//** + * Set the CPU Idle value in measurement interval + * percentage of CPU time spent in the idle task + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param cpu_use Pointer to the CPU Use. + * @param val double + *****************************************************************************/ +void evel_measurement_cpu_use_idle_set(MEASUREMENT_CPU_USE *const cpu_use, + const double val) +{ + EVEL_ENTER(); + evel_set_option_double(&cpu_use->idle, val, "CPU idle time"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the percentage of time spent servicing interrupts + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param cpu_use Pointer to the CPU Use. + * @param val double + *****************************************************************************/ +void evel_measurement_cpu_use_interrupt_set(MEASUREMENT_CPU_USE * const cpu_use, + const double val) +{ + EVEL_ENTER(); + evel_set_option_double(&cpu_use->intrpt, val, "CPU interrupt value"); + EVEL_EXIT(); +} + + +/**************************************************************************//** + * Set the percentage of time spent running user space processes that have been niced + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param cpu_use Pointer to the CPU Use. + * @param val double + *****************************************************************************/ +void evel_measurement_cpu_use_nice_set(MEASUREMENT_CPU_USE * const cpu_use, + const double val) +{ + EVEL_ENTER(); + evel_set_option_double(&cpu_use->nice, val, "CPU nice value"); + EVEL_EXIT(); +} + + +/**************************************************************************//** + * Set the percentage of time spent handling soft irq interrupts + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param cpu_use Pointer to the CPU Use. + * @param val double + *****************************************************************************/ +void evel_measurement_cpu_use_softirq_set(MEASUREMENT_CPU_USE * const cpu_use, + const double val) +{ + EVEL_ENTER(); + evel_set_option_double(&cpu_use->softirq, val, "CPU Soft IRQ value"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the percentage of time spent in involuntary wait + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param cpu_use Pointer to the CPU Use. + * @param val double + *****************************************************************************/ +void evel_measurement_cpu_use_steal_set(MEASUREMENT_CPU_USE * const cpu_use, + const double val) +{ + EVEL_ENTER(); + evel_set_option_double(&cpu_use->steal, val, "CPU involuntary wait"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the percentage of time spent on system tasks running the kernel + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param cpu_use Pointer to the CPU Use. + * @param val double + *****************************************************************************/ +void evel_measurement_cpu_use_system_set(MEASUREMENT_CPU_USE * const cpu_use, + const double val) +{ + EVEL_ENTER(); + evel_set_option_double(&cpu_use->sys, val, "CPU System load"); + EVEL_EXIT(); +} + + +/**************************************************************************//** + * Set the percentage of time spent running un-niced user space processes + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param cpu_use Pointer to the CPU Use. + * @param val double + *****************************************************************************/ +void evel_measurement_cpu_use_usageuser_set(MEASUREMENT_CPU_USE * const cpu_use, + const double val) +{ + EVEL_ENTER(); + evel_set_option_double(&cpu_use->user, val, "CPU User load value"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the percentage of CPU time spent waiting for I/O operations to complete + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param cpu_use Pointer to the CPU Use. + * @param val double + *****************************************************************************/ +void evel_measurement_cpu_use_wait_set(MEASUREMENT_CPU_USE * const cpu_use, + const double val) +{ + EVEL_ENTER(); + evel_set_option_double(&cpu_use->wait, val, "CPU Wait IO value"); + EVEL_EXIT(); +} + + +/**************************************************************************//** + * Add an additional Memory usage value name/value pair to the Measurement. + * + * The name and value are null delimited ASCII strings. The library takes + * a copy so the caller does not have to preserve values after the function + * returns. + * + * @param measurement Pointer to the measurement. + * @param id ASCIIZ string with the Memory identifier. + * @param vmidentifier ASCIIZ string with the VM's identifier. + * @param membuffsz Memory Size. + * + * @return Returns pointer to memory use structure in measurements + *****************************************************************************/ +MEASUREMENT_MEM_USE * evel_measurement_new_mem_use_add(EVENT_MEASUREMENT * measurement, + char * id, char *vmidentifier, double membuffsz) +{ + MEASUREMENT_MEM_USE * mem_use = NULL; + EVEL_ENTER(); + + /***************************************************************************/ + /* Check assumptions. */ + /***************************************************************************/ + assert(measurement != NULL); + assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT); + assert(id != NULL); + assert(membuffsz >= 0.0); + + /***************************************************************************/ + /* Allocate a container for the value and push onto the list. */ + /***************************************************************************/ + EVEL_DEBUG("Adding id=%s buffer size=%lf", id, membuffsz); + mem_use = malloc(sizeof(MEASUREMENT_MEM_USE)); + assert(mem_use != NULL); + memset(mem_use, 0, sizeof(MEASUREMENT_MEM_USE)); + mem_use->id = strdup(id); + mem_use->vmid = strdup(vmidentifier); + mem_use->membuffsz = membuffsz; + evel_init_option_double(&mem_use->memcache); + evel_init_option_double(&mem_use->memconfig); + evel_init_option_double(&mem_use->memfree); + evel_init_option_double(&mem_use->slabrecl); + evel_init_option_double(&mem_use->slabunrecl); + evel_init_option_double(&mem_use->memused); + + assert(mem_use->id != NULL); + + dlist_push_last(&measurement->mem_usage, mem_use); + + EVEL_EXIT(); + return mem_use; +} + +/**************************************************************************//** + * Set kilobytes of memory used for cache + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param mem_use Pointer to the Memory Use. + * @param val double + *****************************************************************************/ +void evel_measurement_mem_use_memcache_set(MEASUREMENT_MEM_USE * const mem_use, + const double val) +{ + EVEL_ENTER(); + evel_set_option_double(&mem_use->memcache, val, "Memory cache value"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set kilobytes of memory configured in the virtual machine on which the VNFC reporting + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param mem_use Pointer to the Memory Use. + * @param val double + *****************************************************************************/ +void evel_measurement_mem_use_memconfig_set(MEASUREMENT_MEM_USE * const mem_use, + const double val) +{ + EVEL_ENTER(); + evel_set_option_double(&mem_use->memconfig, val, "Memory configured value"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set kilobytes of physical RAM left unused by the system + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param mem_use Pointer to the Memory Use. + * @param val double + *****************************************************************************/ +void evel_measurement_mem_use_memfree_set(MEASUREMENT_MEM_USE * const mem_use, + const double val) +{ + EVEL_ENTER(); + evel_set_option_double(&mem_use->memfree, val, "Memory freely available value"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the part of the slab that can be reclaimed such as caches measured in kilobytes + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param mem_use Pointer to the Memory Use. + * @param val double + *****************************************************************************/ +void evel_measurement_mem_use_slab_reclaimed_set(MEASUREMENT_MEM_USE * const mem_use, + const double val) +{ + EVEL_ENTER(); + evel_set_option_double(&mem_use->slabrecl, val, "Memory reclaimable slab set"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the part of the slab that cannot be reclaimed such as caches measured in kilobytes + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param mem_use Pointer to the Memory Use. + * @param val double + *****************************************************************************/ +void evel_measurement_mem_use_slab_unreclaimable_set(MEASUREMENT_MEM_USE * const mem_use, + const double val) +{ + EVEL_ENTER(); + evel_set_option_double(&mem_use->slabunrecl, val, "Memory unreclaimable slab set"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the total memory minus the sum of free, buffered, cached and slab memory in kilobytes + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param mem_use Pointer to the Memory Use. + * @param val double + *****************************************************************************/ +void evel_measurement_mem_use_usedup_set(MEASUREMENT_MEM_USE * const mem_use, + const double val) +{ + EVEL_ENTER(); + evel_set_option_double(&mem_use->memused, val, "Memory usedup total set"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Add an additional Disk usage value name/value pair to the Measurement. + * + * The name and value are null delimited ASCII strings. The library takes + * a copy so the caller does not have to preserve values after the function + * returns. + * + * @param measurement Pointer to the measurement. + * @param id ASCIIZ string with the CPU's identifier. + * @param usage Disk utilization. + *****************************************************************************/ +MEASUREMENT_DISK_USE * evel_measurement_new_disk_use_add(EVENT_MEASUREMENT * measurement, char * id) +{ + MEASUREMENT_DISK_USE * disk_use = NULL; + EVEL_ENTER(); + + /***************************************************************************/ + /* Check assumptions. */ + /***************************************************************************/ + assert(measurement != NULL); + assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT); + assert(id != NULL); + + /***************************************************************************/ + /* Allocate a container for the value and push onto the list. */ + /***************************************************************************/ + EVEL_DEBUG("Adding id=%s disk usage", id); + disk_use = malloc(sizeof(MEASUREMENT_DISK_USE)); + assert(disk_use != NULL); + memset(disk_use, 0, sizeof(MEASUREMENT_DISK_USE)); + disk_use->id = strdup(id); + assert(disk_use->id != NULL); + dlist_push_last(&measurement->disk_usage, disk_use); + + evel_init_option_double(&disk_use->iotimeavg ); + evel_init_option_double(&disk_use->iotimelast ); + evel_init_option_double(&disk_use->iotimemax ); + evel_init_option_double(&disk_use->iotimemin ); + evel_init_option_double(&disk_use->mergereadavg ); + evel_init_option_double(&disk_use->mergereadlast ); + evel_init_option_double(&disk_use->mergereadmax ); + evel_init_option_double(&disk_use->mergereadmin ); + evel_init_option_double(&disk_use->mergewriteavg ); + evel_init_option_double(&disk_use->mergewritelast ); + evel_init_option_double(&disk_use->mergewritemax ); + evel_init_option_double(&disk_use->mergewritemin ); + evel_init_option_double(&disk_use->octetsreadavg ); + evel_init_option_double(&disk_use->octetsreadlast ); + evel_init_option_double(&disk_use->octetsreadmax ); + evel_init_option_double(&disk_use->octetsreadmin ); + evel_init_option_double(&disk_use->octetswriteavg ); + evel_init_option_double(&disk_use->octetswritelast ); + evel_init_option_double(&disk_use->octetswritemax ); + evel_init_option_double(&disk_use->octetswritemin ); + evel_init_option_double(&disk_use->opsreadavg ); + evel_init_option_double(&disk_use->opsreadlast ); + evel_init_option_double(&disk_use->opsreadmax ); + evel_init_option_double(&disk_use->opsreadmin ); + evel_init_option_double(&disk_use->opswriteavg ); + evel_init_option_double(&disk_use->opswritelast ); + evel_init_option_double(&disk_use->opswritemax ); + evel_init_option_double(&disk_use->opswritemin ); + evel_init_option_double(&disk_use->pendingopsavg ); + evel_init_option_double(&disk_use->pendingopslast ); + evel_init_option_double(&disk_use->pendingopsmax ); + evel_init_option_double(&disk_use->pendingopsmin ); + evel_init_option_double(&disk_use->timereadavg ); + evel_init_option_double(&disk_use->timereadlast ); + evel_init_option_double(&disk_use->timereadmax ); + evel_init_option_double(&disk_use->timereadmin ); + evel_init_option_double(&disk_use->timewriteavg ); + evel_init_option_double(&disk_use->timewritelast ); + evel_init_option_double(&disk_use->timewritemax ); + evel_init_option_double(&disk_use->timewritemin ); + + EVEL_EXIT(); + return disk_use; +} + +/**************************************************************************//** + * Set milliseconds spent doing input/output operations over 1 sec; treat + * this metric as a device load percentage where 1000ms matches 100% load; + * provide the average over the measurement interval + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param disk_use Pointer to the Disk Use. + * @param val double + *****************************************************************************/ +void evel_measurement_disk_use_iotimeavg_set(MEASUREMENT_DISK_USE * const disk_use, + const double val) +{ + EVEL_ENTER(); + evel_set_option_double(&disk_use->iotimeavg, val, "Disk ioload set"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set milliseconds spent doing input/output operations over 1 sec; treat + * this metric as a device load percentage where 1000ms matches 100% load; + * provide the last value within the measurement interval + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param disk_use Pointer to the Disk Use. + * @param val double + *****************************************************************************/ +void evel_measurement_disk_use_iotimelast_set(MEASUREMENT_DISK_USE * const disk_use, + const double val) +{ + EVEL_ENTER(); + evel_set_option_double(&disk_use->iotimelast, val, "Disk ioloadlast set"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set milliseconds spent doing input/output operations over 1 sec; treat + * this metric as a device load percentage where 1000ms matches 100% load; + * provide the maximum value within the measurement interval + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param disk_use Pointer to the Disk Use. + * @param val double + *****************************************************************************/ +void evel_measurement_disk_use_iotimemax_set(MEASUREMENT_DISK_USE * const disk_use, + const double val) +{ + EVEL_ENTER(); + evel_set_option_double(&disk_use->iotimemax, val, "Disk ioloadmax set"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set milliseconds spent doing input/output operations over 1 sec; treat + * this metric as a device load percentage where 1000ms matches 100% load; + * provide the minimum value within the measurement interval + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param disk_use Pointer to the Disk Use. + * @param val double + *****************************************************************************/ +void evel_measurement_disk_use_iotimemin_set(MEASUREMENT_DISK_USE * const disk_use, + const double val) +{ + EVEL_ENTER(); + evel_set_option_double(&disk_use->iotimemin, val, "Disk ioloadmin set"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set number of logical read operations that were merged into physical read + * operations, e.g., two logical reads were served by one physical disk access; + * provide the average measurement within the measurement interval + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param disk_use Pointer to the Disk Use. + * @param val double + *****************************************************************************/ +void evel_measurement_disk_use_mergereadavg_set(MEASUREMENT_DISK_USE * const disk_use, + const double val) +{ + EVEL_ENTER(); + evel_set_option_double(&disk_use->mergereadavg, val, "Disk Merged read average set"); + EVEL_EXIT(); +} +/**************************************************************************//** + * Set number of logical read operations that were merged into physical read + * operations, e.g., two logical reads were served by one physical disk access; + * provide the last measurement within the measurement interval + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param disk_use Pointer to the Disk Use. + * @param val double + *****************************************************************************/ +void evel_measurement_disk_use_mergereadlast_set(MEASUREMENT_DISK_USE * const disk_use, + const double val) +{ + EVEL_ENTER(); + evel_set_option_double(&disk_use->mergereadlast, val, "Disk mergedload last set"); + EVEL_EXIT(); +} +/**************************************************************************//** + * Set number of logical read operations that were merged into physical read + * operations, e.g., two logical reads were served by one physical disk access; + * provide the maximum measurement within the measurement interval + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param disk_use Pointer to the Disk Use. + * @param val double + *****************************************************************************/ +void evel_measurement_disk_use_mergereadmax_set(MEASUREMENT_DISK_USE * const disk_use, + const double val) +{ + EVEL_ENTER(); + evel_set_option_double(&disk_use->mergereadmax, val, "Disk merged loadmax set"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set number of logical read operations that were merged into physical read + * operations, e.g., two logical reads were served by one physical disk access; + * provide the minimum measurement within the measurement interval + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param disk_use Pointer to the Disk Use. + * @param val double + *****************************************************************************/ +void evel_measurement_disk_use_mergereadmin_set(MEASUREMENT_DISK_USE * const disk_use, + const double val) +{ + EVEL_ENTER(); + evel_set_option_double(&disk_use->mergereadmin, val, "Disk merged loadmin set"); + EVEL_EXIT(); +} +/**************************************************************************//** + * Set number of logical write operations that were merged into physical read + * operations, e.g., two logical writes were served by one physical disk access; + * provide the last measurement within the measurement interval + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param disk_use Pointer to the Disk Use. + * @param val double + *****************************************************************************/ +void evel_measurement_disk_use_mergewritelast_set(MEASUREMENT_DISK_USE * const disk_use, + const double val) +{ + EVEL_ENTER(); + evel_set_option_double(&disk_use->mergewritelast, val, "Disk merged writelast set"); + EVEL_EXIT(); +} +/**************************************************************************//** + * Set number of logical write operations that were merged into physical read + * operations, e.g., two logical writes were served by one physical disk access; + * provide the maximum measurement within the measurement interval + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param disk_use Pointer to the Disk Use. + * @param val double + *****************************************************************************/ +void evel_measurement_disk_use_mergewritemax_set(MEASUREMENT_DISK_USE * const disk_use, + const double val) +{ + EVEL_ENTER(); + evel_set_option_double(&disk_use->mergewritemax, val, "Disk writemax set"); + EVEL_EXIT(); +} +/**************************************************************************//** + * Set number of logical write operations that were merged into physical read + * operations, e.g., two logical writes were served by one physical disk access; + * provide the maximum measurement within the measurement interval + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param disk_use Pointer to the Disk Use. + * @param val double + *****************************************************************************/ +void evel_measurement_disk_use_mergewritemin_set(MEASUREMENT_DISK_USE * const disk_use, + const double val) +{ + EVEL_ENTER(); + evel_set_option_double(&disk_use->mergewritemin, val, "Disk writemin set"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set number of octets per second read from a disk or partition; + * provide the average measurement within the measurement interval + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param disk_use Pointer to the Disk Use. + * @param val double + *****************************************************************************/ +void evel_measurement_disk_use_octetsreadavg_set(MEASUREMENT_DISK_USE * const disk_use, + const double val) +{ + EVEL_ENTER(); + evel_set_option_double(&disk_use->octetsreadavg, val, "Octets readavg set"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set number of octets per second read from a disk or partition; + * provide the last measurement within the measurement interval + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param disk_use Pointer to the Disk Use. + * @param val double + *****************************************************************************/ +void evel_measurement_disk_use_octetsreadlast_set(MEASUREMENT_DISK_USE * const disk_use, + const double val) +{ + EVEL_ENTER(); + evel_set_option_double(&disk_use->octetsreadlast, val, "Octets readlast set"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set number of octets per second read from a disk or partition; + * provide the maximum measurement within the measurement interval + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param disk_use Pointer to the Disk Use. + * @param val double + *****************************************************************************/ +void evel_measurement_disk_use_octetsreadmax_set(MEASUREMENT_DISK_USE * const disk_use, + const double val) +{ + EVEL_ENTER(); + evel_set_option_double(&disk_use->octetsreadmax, val, "Octets readmax set"); + EVEL_EXIT(); +} +/**************************************************************************//** + * Set number of octets per second read from a disk or partition; + * provide the minimum measurement within the measurement interval + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param disk_use Pointer to the Disk Use. + * @param val double + *****************************************************************************/ +void evel_measurement_disk_use_octetsreadmin_set(MEASUREMENT_DISK_USE * const disk_use, + const double val) +{ + EVEL_ENTER(); + evel_set_option_double(&disk_use->octetsreadmin, val, "Octets readmin set"); + EVEL_EXIT(); +} +/**************************************************************************//** + * Set number of octets per second written to a disk or partition; + * provide the average measurement within the measurement interval + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param disk_use Pointer to the Disk Use. + * @param val double + *****************************************************************************/ +void evel_measurement_disk_use_octetswriteavg_set(MEASUREMENT_DISK_USE * const disk_use, + const double val) +{ + EVEL_ENTER(); + evel_set_option_double(&disk_use->octetswriteavg, val, "Octets writeavg set"); + EVEL_EXIT(); +} +/**************************************************************************//** + * Set number of octets per second written to a disk or partition; + * provide the last measurement within the measurement interval + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param disk_use Pointer to the Disk Use. + * @param val double + *****************************************************************************/ +void evel_measurement_disk_use_octetswritelast_set(MEASUREMENT_DISK_USE * const disk_use, + const double val) +{ + EVEL_ENTER(); + evel_set_option_double(&disk_use->octetswritelast, val, "Octets writelast set"); + EVEL_EXIT(); +} +/**************************************************************************//** + * Set number of octets per second written to a disk or partition; + * provide the maximum measurement within the measurement interval + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param disk_use Pointer to the Disk Use. + * @param val double + *****************************************************************************/ +void evel_measurement_disk_use_octetswritemax_set(MEASUREMENT_DISK_USE * const disk_use, + const double val) +{ + EVEL_ENTER(); + evel_set_option_double(&disk_use->octetswritemax, val, "Octets writemax set"); + EVEL_EXIT(); +} +/**************************************************************************//** + * Set number of octets per second written to a disk or partition; + * provide the minimum measurement within the measurement interval + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param disk_use Pointer to the Disk Use. + * @param val double + *****************************************************************************/ +void evel_measurement_disk_use_octetswritemin_set(MEASUREMENT_DISK_USE * const disk_use, + const double val) +{ + EVEL_ENTER(); + evel_set_option_double(&disk_use->octetswritemin, val, "Octets writemin set"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set number of read operations per second issued to the disk; + * provide the average measurement within the measurement interval + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param disk_use Pointer to the Disk Use. + * @param val double + *****************************************************************************/ +void evel_measurement_disk_use_opsreadavg_set(MEASUREMENT_DISK_USE * const disk_use, + const double val) +{ + EVEL_ENTER(); + evel_set_option_double(&disk_use->opsreadavg, val, "Disk read operation average set"); + EVEL_EXIT(); +} +/**************************************************************************//** + * Set number of read operations per second issued to the disk; + * provide the last measurement within the measurement interval + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param disk_use Pointer to the Disk Use. + * @param val double + *****************************************************************************/ +void evel_measurement_disk_use_opsreadlast_set(MEASUREMENT_DISK_USE * const disk_use, + const double val) +{ + EVEL_ENTER(); + evel_set_option_double(&disk_use->opsreadlast, val, "Disk read operation last set"); + EVEL_EXIT(); +} +/**************************************************************************//** + * Set number of read operations per second issued to the disk; + * provide the maximum measurement within the measurement interval + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param disk_use Pointer to the Disk Use. + * @param val double + *****************************************************************************/ +void evel_measurement_disk_use_opsreadmax_set(MEASUREMENT_DISK_USE * const disk_use, + const double val) +{ + EVEL_ENTER(); + evel_set_option_double(&disk_use->opsreadmax, val, "Disk read operation maximum set"); + EVEL_EXIT(); +} +/**************************************************************************//** + * Set number of read operations per second issued to the disk; + * provide the minimum measurement within the measurement interval + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param disk_use Pointer to the Disk Use. + * @param val double + *****************************************************************************/ +void evel_measurement_disk_use_opsreadmin_set(MEASUREMENT_DISK_USE * const disk_use, + const double val) +{ + EVEL_ENTER(); + evel_set_option_double(&disk_use->opsreadmin, val, "Disk read operation minimum set"); + EVEL_EXIT(); +} +/**************************************************************************//** + * Set number of write operations per second issued to the disk; + * provide the average measurement within the measurement interval + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param disk_use Pointer to the Disk Use. + * @param val double + *****************************************************************************/ +void evel_measurement_disk_use_opswriteavg_set(MEASUREMENT_DISK_USE * const disk_use, + const double val) +{ + EVEL_ENTER(); + evel_set_option_double(&disk_use->opswriteavg, val, "Disk write operation average set"); + EVEL_EXIT(); +} +/**************************************************************************//** + * Set number of write operations per second issued to the disk; + * provide the last measurement within the measurement interval + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param disk_use Pointer to the Disk Use. + * @param val double + *****************************************************************************/ +void evel_measurement_disk_use_opswritelast_set(MEASUREMENT_DISK_USE * const disk_use, + const double val) +{ + EVEL_ENTER(); + evel_set_option_double(&disk_use->opswritelast, val, "Disk write operation last set"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set number of write operations per second issued to the disk; + * provide the maximum measurement within the measurement interval + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param disk_use Pointer to the Disk Use. + * @param val double + *****************************************************************************/ +void evel_measurement_disk_use_opswritemax_set(MEASUREMENT_DISK_USE * const disk_use, + const double val) +{ + EVEL_ENTER(); + evel_set_option_double(&disk_use->opswritemax, val, "Disk write operation maximum set"); + EVEL_EXIT(); +} +/**************************************************************************//** + * Set number of write operations per second issued to the disk; + * provide the average measurement within the measurement interval + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param disk_use Pointer to the Disk Use. + * @param val double + *****************************************************************************/ +void evel_measurement_disk_use_opswritemin_set(MEASUREMENT_DISK_USE * const disk_use, + const double val) +{ + EVEL_ENTER(); + evel_set_option_double(&disk_use->opswritemin, val, "Disk write operation minimum set"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set queue size of pending I/O operations per second; + * provide the average measurement within the measurement interval + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param disk_use Pointer to the Disk Use. + * @param val double + *****************************************************************************/ +void evel_measurement_disk_use_pendingopsavg_set(MEASUREMENT_DISK_USE * const disk_use, + const double val) +{ + EVEL_ENTER(); + evel_set_option_double(&disk_use->pendingopsavg, val, "Disk pending operation average set"); + EVEL_EXIT(); +} +/**************************************************************************//** + * Set queue size of pending I/O operations per second; + * provide the last measurement within the measurement interval + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param disk_use Pointer to the Disk Use. + * @param val double + *****************************************************************************/ +void evel_measurement_disk_use_pendingopslast_set(MEASUREMENT_DISK_USE * const disk_use, + const double val) +{ + EVEL_ENTER(); + evel_set_option_double(&disk_use->pendingopslast, val, "Disk pending operation last set"); + EVEL_EXIT(); +} +/**************************************************************************//** + * Set queue size of pending I/O operations per second; + * provide the maximum measurement within the measurement interval + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param disk_use Pointer to the Disk Use. + * @param val double + *****************************************************************************/ +void evel_measurement_disk_use_pendingopsmax_set(MEASUREMENT_DISK_USE * const disk_use, + const double val) +{ + EVEL_ENTER(); + evel_set_option_double(&disk_use->pendingopsmax, val, "Disk pending operation maximum set"); + EVEL_EXIT(); +} +/**************************************************************************//** + * Set queue size of pending I/O operations per second; + * provide the minimum measurement within the measurement interval + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param disk_use Pointer to the Disk Use. + * @param val double + *****************************************************************************/ +void evel_measurement_disk_use_pendingopsmin_set(MEASUREMENT_DISK_USE * const disk_use, + const double val) +{ + EVEL_ENTER(); + evel_set_option_double(&disk_use->pendingopsmin, val, "Disk pending operation min set"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set milliseconds a read operation took to complete; + * provide the average measurement within the measurement interval + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param disk_use Pointer to the Disk Use. + * @param val double + *****************************************************************************/ +void evel_measurement_disk_use_timereadavg_set(MEASUREMENT_DISK_USE * const disk_use, + const double val) +{ + EVEL_ENTER(); + evel_set_option_double(&disk_use->timereadavg, val, "Disk read time average set"); + EVEL_EXIT(); +} +/**************************************************************************//** + * Set milliseconds a read operation took to complete; + * provide the last measurement within the measurement interval + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param disk_use Pointer to the Disk Use. + * @param val double + *****************************************************************************/ +void evel_measurement_disk_use_timereadlast_set(MEASUREMENT_DISK_USE * const disk_use, + const double val) +{ + EVEL_ENTER(); + evel_set_option_double(&disk_use->timereadlast, val, "Disk read time last set"); + EVEL_EXIT(); +} +/**************************************************************************//** + * Set milliseconds a read operation took to complete; + * provide the maximum measurement within the measurement interval + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param disk_use Pointer to the Disk Use. + * @param val double + *****************************************************************************/ +void evel_measurement_disk_use_timereadmax_set(MEASUREMENT_DISK_USE * const disk_use, + const double val) +{ + EVEL_ENTER(); + evel_set_option_double(&disk_use->timereadmax, val, "Disk read time maximum set"); + EVEL_EXIT(); +} +/**************************************************************************//** + * Set milliseconds a read operation took to complete; + * provide the minimum measurement within the measurement interval + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param disk_use Pointer to the Disk Use. + * @param val double + *****************************************************************************/ +void evel_measurement_disk_use_timereadmin_set(MEASUREMENT_DISK_USE * const disk_use, + const double val) +{ + EVEL_ENTER(); + evel_set_option_double(&disk_use->timereadmin, val, "Disk read time minimum set"); + EVEL_EXIT(); +} +/**************************************************************************//** + * Set milliseconds a write operation took to complete; + * provide the average measurement within the measurement interval + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param disk_use Pointer to the Disk Use. + * @param val double + *****************************************************************************/ +void evel_measurement_disk_use_timewriteavg_set(MEASUREMENT_DISK_USE * const disk_use, + const double val) +{ + EVEL_ENTER(); + evel_set_option_double(&disk_use->timewriteavg, val, "Disk write time average set"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set milliseconds a write operation took to complete; + * provide the last measurement within the measurement interval + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param disk_use Pointer to the Disk Use. + * @param val double + *****************************************************************************/ +void evel_measurement_disk_use_timewritelast_set(MEASUREMENT_DISK_USE * const disk_use, + const double val) +{ + EVEL_ENTER(); + evel_set_option_double(&disk_use->timewritelast, val, "Disk write time last set"); + EVEL_EXIT(); +} +/**************************************************************************//** + * Set milliseconds a write operation took to complete; + * provide the maximum measurement within the measurement interval + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param disk_use Pointer to the Disk Use. + * @param val double + *****************************************************************************/ +void evel_measurement_disk_use_timewritemax_set(MEASUREMENT_DISK_USE * const disk_use, + const double val) +{ + EVEL_ENTER(); + evel_set_option_double(&disk_use->timewritemax, val, "Disk write time max set"); + EVEL_EXIT(); +} +/**************************************************************************//** + * Set milliseconds a write operation took to complete; + * provide the average measurement within the measurement interval + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param disk_use Pointer to the Disk Use. + * @param val double + *****************************************************************************/ +void evel_measurement_disk_use_timewritemin_set(MEASUREMENT_DISK_USE * const disk_use, + const double val) +{ + EVEL_ENTER(); + evel_set_option_double(&disk_use->timewritemin, val, "Disk write time min set"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Add an additional File System usage value name/value pair to the + * Measurement. + * + * The filesystem_name is null delimited ASCII string. The library takes a + * copy so the caller does not have to preserve values after the function + * returns. + * + * @param measurement Pointer to the measurement. + * @param filesystem_name ASCIIZ string with the file-system's UUID. + * @param block_configured Block storage configured. + * @param block_used Block storage in use. + * @param block_iops Block storage IOPS. + * @param ephemeral_configured Ephemeral storage configured. + * @param ephemeral_used Ephemeral storage in use. + * @param ephemeral_iops Ephemeral storage IOPS. + *****************************************************************************/ +void evel_measurement_fsys_use_add(EVENT_MEASUREMENT * measurement, + char * filesystem_name, + double block_configured, + double block_used, + double block_iops, + double ephemeral_configured, + double ephemeral_used, + double ephemeral_iops) +{ + MEASUREMENT_FSYS_USE * fsys_use = NULL; + EVEL_ENTER(); + + /***************************************************************************/ + /* Check assumptions. */ + /***************************************************************************/ + assert(measurement != NULL); + assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT); + assert(filesystem_name != NULL); + assert(block_configured >= 0.0); + assert(block_used >= 0.0); + assert(block_iops >= 0.0); + assert(ephemeral_configured >= 0.0); + assert(ephemeral_used >= 0.0); + assert(ephemeral_iops >= 0.0); + + /***************************************************************************/ + /* Allocate a container for the value and push onto the list. */ + /***************************************************************************/ + EVEL_DEBUG("Adding filesystem_name=%s", filesystem_name); + fsys_use = malloc(sizeof(MEASUREMENT_FSYS_USE)); + assert(fsys_use != NULL); + memset(fsys_use, 0, sizeof(MEASUREMENT_FSYS_USE)); + fsys_use->filesystem_name = strdup(filesystem_name); + fsys_use->block_configured = block_configured; + fsys_use->block_used = block_used; + fsys_use->block_iops = block_iops; + fsys_use->ephemeral_configured = ephemeral_configured; + fsys_use->ephemeral_used = ephemeral_used; + fsys_use->ephemeral_iops = ephemeral_iops; + + dlist_push_last(&measurement->filesystem_usage, fsys_use); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Add a Feature usage value name/value pair to the Measurement. + * + * The name is null delimited ASCII string. The library takes + * a copy so the caller does not have to preserve values after the function + * returns. + * + * @param measurement Pointer to the measurement. + * @param feature ASCIIZ string with the feature's name. + * @param utilization Utilization of the feature. + *****************************************************************************/ +void evel_measurement_feature_use_add(EVENT_MEASUREMENT * measurement, + char * feature, + int utilization) +{ + MEASUREMENT_FEATURE_USE * feature_use = NULL; + EVEL_ENTER(); + + /***************************************************************************/ + /* Check assumptions. */ + /***************************************************************************/ + assert(measurement != NULL); + assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT); + assert(feature != NULL); + assert(utilization >= 0); + + /***************************************************************************/ + /* Allocate a container for the value and push onto the list. */ + /***************************************************************************/ + EVEL_DEBUG("Adding Feature=%s Use=%d", feature, utilization); + feature_use = malloc(sizeof(MEASUREMENT_FEATURE_USE)); + assert(feature_use != NULL); + memset(feature_use, 0, sizeof(MEASUREMENT_FEATURE_USE)); + feature_use->feature_id = strdup(feature); + assert(feature_use->feature_id != NULL); + feature_use->feature_utilization = utilization; + + dlist_push_last(&measurement->feature_usage, feature_use); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Add a Additional Measurement value name/value pair to the Report. + * + * The name is null delimited ASCII string. The library takes + * a copy so the caller does not have to preserve values after the function + * returns. + * + * @param measurement Pointer to the Measaurement. + * @param group ASCIIZ string with the measurement group's name. + * @param name ASCIIZ string containing the measurement's name. + * @param value ASCIIZ string containing the measurement's value. + *****************************************************************************/ +void evel_measurement_custom_measurement_add(EVENT_MEASUREMENT * measurement, + const char * const group, + const char * const name, + const char * const value) +{ + MEASUREMENT_GROUP * measurement_group = NULL; + CUSTOM_MEASUREMENT * custom_measurement = NULL; + DLIST_ITEM * item = NULL; + EVEL_ENTER(); + + /***************************************************************************/ + /* Check assumptions. */ + /***************************************************************************/ + assert(measurement != NULL); + assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT); + assert(group != NULL); + assert(name != NULL); + assert(value != NULL); + + /***************************************************************************/ + /* Allocate a container for the name/value pair. */ + /***************************************************************************/ + EVEL_DEBUG("Adding Measurement Group=%s Name=%s Value=%s", + group, name, value); + custom_measurement = malloc(sizeof(CUSTOM_MEASUREMENT)); + assert(custom_measurement != NULL); + memset(custom_measurement, 0, sizeof(CUSTOM_MEASUREMENT)); + custom_measurement->name = strdup(name); + assert(custom_measurement->name != NULL); + custom_measurement->value = strdup(value); + assert(custom_measurement->value != NULL); + + /***************************************************************************/ + /* See if we have that group already. */ + /***************************************************************************/ + item = dlist_get_first(&measurement->additional_measurements); + while (item != NULL) + { + measurement_group = (MEASUREMENT_GROUP *) item->item; + assert(measurement_group != NULL); + + EVEL_DEBUG("Got measurement group %s", measurement_group->name); + if (strcmp(group, measurement_group->name) == 0) + { + EVEL_DEBUG("Found existing Measurement Group"); + break; + } + item = dlist_get_next(item); + } + + /***************************************************************************/ + /* If we didn't have the group already, create it. */ + /***************************************************************************/ + if (item == NULL) + { + EVEL_DEBUG("Creating new Measurement Group"); + measurement_group = malloc(sizeof(MEASUREMENT_GROUP)); + assert(measurement_group != NULL); + memset(measurement_group, 0, sizeof(MEASUREMENT_GROUP)); + measurement_group->name = strdup(group); + assert(measurement_group->name != NULL); + dlist_initialize(&measurement_group->measurements); + dlist_push_last(&measurement->additional_measurements, measurement_group); + } + + /***************************************************************************/ + /* If we didn't have the group already, create it. */ + /***************************************************************************/ + dlist_push_last(&measurement_group->measurements, custom_measurement); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Add a Codec usage value name/value pair to the Measurement. + * + * The name is null delimited ASCII string. The library takes + * a copy so the caller does not have to preserve values after the function + * returns. + * + * @param measurement Pointer to the measurement. + * @param codec ASCIIZ string with the codec's name. + * @param utilization Number of codecs in use. + *****************************************************************************/ +void evel_measurement_codec_use_add(EVENT_MEASUREMENT * measurement, + char * codec, + int utilization) +{ + MEASUREMENT_CODEC_USE * codec_use = NULL; + EVEL_ENTER(); + + /***************************************************************************/ + /* Check assumptions. */ + /***************************************************************************/ + assert(measurement != NULL); + assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT); + assert(codec != NULL); + assert(utilization >= 0.0); + + /***************************************************************************/ + /* Allocate a container for the value and push onto the list. */ + /***************************************************************************/ + EVEL_DEBUG("Adding Codec=%s Use=%d", codec, utilization); + codec_use = malloc(sizeof(MEASUREMENT_CODEC_USE)); + assert(codec_use != NULL); + memset(codec_use, 0, sizeof(MEASUREMENT_CODEC_USE)); + codec_use->codec_id = strdup(codec); + assert(codec_use->codec_id != NULL); + codec_use->number_in_use = utilization; + + dlist_push_last(&measurement->codec_usage, codec_use); + + EVEL_EXIT(); +} + + +/**************************************************************************//** + * Set the Media Ports in Use property of the Measurement. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param measurement Pointer to the measurement. + * @param media_ports_in_use The media port usage to set. + *****************************************************************************/ +void evel_measurement_media_port_use_set(EVENT_MEASUREMENT * measurement, + int media_ports_in_use) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(measurement != NULL); + assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT); + assert(media_ports_in_use >= 0); + + evel_set_option_int(&measurement->media_ports_in_use, + media_ports_in_use, + "Media Ports In Use"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the VNFC Scaling Metric property of the Measurement. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param measurement Pointer to the measurement. + * @param scaling_metric The scaling metric to set. + *****************************************************************************/ +void evel_measurement_vnfc_scaling_metric_set(EVENT_MEASUREMENT * measurement, + int scaling_metric) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(measurement != NULL); + assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT); + assert(scaling_metric >= 0.0); + + evel_set_option_int(&measurement->vnfc_scaling_metric, + scaling_metric, + "VNFC Scaling Metric"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Create a new Latency Bucket to be added to a Measurement event. + * + * @note The mandatory fields on the ::MEASUREMENT_LATENCY_BUCKET must be + * supplied to this factory function and are immutable once set. + * Optional fields have explicit setter functions, but again values + * may only be set once so that the ::MEASUREMENT_LATENCY_BUCKET has + * immutable properties. + * + * @param count Count of events in this bucket. + * + * @returns pointer to the newly manufactured ::MEASUREMENT_LATENCY_BUCKET. + * If the structure is not used it must be released using free. + * @retval NULL Failed to create the Latency Bucket. + *****************************************************************************/ +MEASUREMENT_LATENCY_BUCKET * evel_new_meas_latency_bucket(const int count) +{ + MEASUREMENT_LATENCY_BUCKET * bucket; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(count >= 0); + + /***************************************************************************/ + /* Allocate, then set Mandatory Parameters. */ + /***************************************************************************/ + EVEL_DEBUG("Creating bucket, count = %d", count); + bucket = malloc(sizeof(MEASUREMENT_LATENCY_BUCKET)); + assert(bucket != NULL); + + /***************************************************************************/ + /* Set Mandatory Parameters. */ + /***************************************************************************/ + bucket->count = count; + + /***************************************************************************/ + /* Initialize Optional Parameters. */ + /***************************************************************************/ + evel_init_option_double(&bucket->high_end); + evel_init_option_double(&bucket->low_end); + + EVEL_EXIT(); + + return bucket; +} + +/**************************************************************************//** + * Set the High End property of the Measurement Latency Bucket. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param bucket Pointer to the Measurement Latency Bucket. + * @param high_end High end of the bucket's range. + *****************************************************************************/ +void evel_meas_latency_bucket_high_end_set( + MEASUREMENT_LATENCY_BUCKET * const bucket, + const double high_end) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(high_end >= 0.0); + evel_set_option_double(&bucket->high_end, high_end, "High End"); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Low End property of the Measurement Latency Bucket. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param bucket Pointer to the Measurement Latency Bucket. + * @param low_end Low end of the bucket's range. + *****************************************************************************/ +void evel_meas_latency_bucket_low_end_set( + MEASUREMENT_LATENCY_BUCKET * const bucket, + const double low_end) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(low_end >= 0.0); + evel_set_option_double(&bucket->low_end, low_end, "Low End"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Add an additional Measurement Latency Bucket to the specified event. + * + * @param measurement Pointer to the Measurement event. + * @param bucket Pointer to the Measurement Latency Bucket to add. + *****************************************************************************/ +void evel_meas_latency_bucket_add(EVENT_MEASUREMENT * const measurement, + MEASUREMENT_LATENCY_BUCKET * const bucket) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(measurement != NULL); + assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT); + assert(bucket != NULL); + dlist_push_last(&measurement->latency_distribution, bucket); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Add an additional Latency Distribution bucket to the Measurement. + * + * This function implements the previous API, purely for convenience. + * + * @param measurement Pointer to the measurement. + * @param low_end Low end of the bucket's range. + * @param high_end High end of the bucket's range. + * @param count Count of events in this bucket. + *****************************************************************************/ +void evel_measurement_latency_add(EVENT_MEASUREMENT * const measurement, + const double low_end, + const double high_end, + const int count) +{ + MEASUREMENT_LATENCY_BUCKET * bucket = NULL; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Trust the assertions in the underlying methods. */ + /***************************************************************************/ + bucket = evel_new_meas_latency_bucket(count); + evel_meas_latency_bucket_low_end_set(bucket, low_end); + evel_meas_latency_bucket_high_end_set(bucket, high_end); + evel_meas_latency_bucket_add(measurement, bucket); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Create a new vNIC Use to be added to a Measurement event. + * + * @note The mandatory fields on the ::MEASUREMENT_VNIC_PERFORMANCE must be supplied + * to this factory function and are immutable once set. Optional + * fields have explicit setter functions, but again values may only be + * set once so that the ::MEASUREMENT_VNIC_PERFORMANCE has immutable + * properties. + * + * @param vnic_id ASCIIZ string with the vNIC's ID. + * @param val_suspect True or false confidence in data. + * + * @returns pointer to the newly manufactured ::MEASUREMENT_VNIC_PERFORMANCE. + * If the structure is not used it must be released using + * ::evel_measurement_free_vnic_performance. + * @retval NULL Failed to create the vNIC Use. + *****************************************************************************/ +MEASUREMENT_VNIC_PERFORMANCE * evel_measurement_new_vnic_performance(char * const vnic_id, + char * const val_suspect) +{ + MEASUREMENT_VNIC_PERFORMANCE * vnic_performance; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(vnic_id != NULL); + assert(!strcmp(val_suspect,"true") || !strcmp(val_suspect,"false")); + + /***************************************************************************/ + /* Allocate, then set Mandatory Parameters. */ + /***************************************************************************/ + EVEL_DEBUG("Adding VNIC ID=%s", vnic_id); + vnic_performance = malloc(sizeof(MEASUREMENT_VNIC_PERFORMANCE)); + assert(vnic_performance != NULL); + vnic_performance->vnic_id = strdup(vnic_id); + vnic_performance->valuesaresuspect = strdup(val_suspect); + + /***************************************************************************/ + /* Initialize Optional Parameters. */ + /***************************************************************************/ + evel_init_option_double(&vnic_performance-> recvd_bcast_packets_acc); + evel_init_option_double(&vnic_performance-> recvd_bcast_packets_delta); + evel_init_option_double(&vnic_performance-> recvd_discarded_packets_acc); + evel_init_option_double(&vnic_performance-> recvd_discarded_packets_delta); + evel_init_option_double(&vnic_performance-> recvd_error_packets_acc); + evel_init_option_double(&vnic_performance-> recvd_error_packets_delta); + evel_init_option_double(&vnic_performance-> recvd_mcast_packets_acc); + evel_init_option_double(&vnic_performance-> recvd_mcast_packets_delta); + evel_init_option_double(&vnic_performance-> recvd_octets_acc); + evel_init_option_double(&vnic_performance-> recvd_octets_delta); + evel_init_option_double(&vnic_performance-> recvd_total_packets_acc); + evel_init_option_double(&vnic_performance-> recvd_total_packets_delta); + evel_init_option_double(&vnic_performance-> recvd_ucast_packets_acc); + evel_init_option_double(&vnic_performance-> recvd_ucast_packets_delta); + evel_init_option_double(&vnic_performance-> tx_bcast_packets_acc); + evel_init_option_double(&vnic_performance-> tx_bcast_packets_delta); + evel_init_option_double(&vnic_performance-> tx_discarded_packets_acc); + evel_init_option_double(&vnic_performance-> tx_discarded_packets_delta); + evel_init_option_double(&vnic_performance-> tx_error_packets_acc); + evel_init_option_double(&vnic_performance-> tx_error_packets_delta); + evel_init_option_double(&vnic_performance-> tx_mcast_packets_acc); + evel_init_option_double(&vnic_performance-> tx_mcast_packets_delta); + evel_init_option_double(&vnic_performance-> tx_octets_acc); + evel_init_option_double(&vnic_performance-> tx_octets_delta); + evel_init_option_double(&vnic_performance-> tx_total_packets_acc); + evel_init_option_double(&vnic_performance-> tx_total_packets_delta); + evel_init_option_double(&vnic_performance-> tx_ucast_packets_acc); + evel_init_option_double(&vnic_performance-> tx_ucast_packets_delta); + + EVEL_EXIT(); + + return vnic_performance; +} + +/**************************************************************************//** + * Free a vNIC Use. + * + * Free off the ::MEASUREMENT_VNIC_PERFORMANCE supplied. Will free all the contained + * allocated memory. + * + * @note It does not free the vNIC Use itself, since that may be part of a + * larger structure. + *****************************************************************************/ +void evel_measurement_free_vnic_performance(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(vnic_performance != NULL); + assert(vnic_performance->vnic_id != NULL); + assert(vnic_performance->valuesaresuspect != NULL); + + /***************************************************************************/ + /* Free the duplicated string. */ + /***************************************************************************/ + free(vnic_performance->vnic_id); + free(vnic_performance->valuesaresuspect); + vnic_performance->vnic_id = NULL; + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Accumulated Broadcast Packets Received in measurement interval + * property of the vNIC performance. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param vnic_performance Pointer to the vNIC Use. + * @param recvd_bcast_packets_acc + *****************************************************************************/ +void evel_vnic_performance_rx_bcast_pkt_acc_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance, + const double recvd_bcast_packets_acc) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(recvd_bcast_packets_acc >= 0.0); + + evel_set_option_double(&vnic_performance->recvd_bcast_packets_acc, + recvd_bcast_packets_acc, + "Broadcast Packets accumulated"); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Delta Broadcast Packets Received in measurement interval + * property of the vNIC performance. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param vnic_performance Pointer to the vNIC Use. + * @param recvd_bcast_packets_delta + *****************************************************************************/ +void evel_vnic_performance_rx_bcast_pkt_delta_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance, + const double recvd_bcast_packets_delta) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(recvd_bcast_packets_delta >= 0.0); + + evel_set_option_double(&vnic_performance->recvd_bcast_packets_delta, + recvd_bcast_packets_delta, + "Delta Broadcast Packets recieved"); + + EVEL_EXIT(); +} + + +/**************************************************************************//** + * Set the Discarded Packets Received in measurement interval + * property of the vNIC performance. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param vnic_performance Pointer to the vNIC Use. + * @param recvd_discard_packets_acc + *****************************************************************************/ +void evel_vnic_performance_rx_discard_pkt_acc_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance, + const double recvd_discard_packets_acc) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(recvd_discard_packets_acc >= 0.0); + + evel_set_option_double(&vnic_performance->recvd_discarded_packets_acc, + recvd_discard_packets_acc, + "Discarded Packets accumulated"); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Delta Discarded Packets Received in measurement interval + * property of the vNIC performance. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param vnic_performance Pointer to the vNIC Use. + * @param recvd_discard_packets_delta + *****************************************************************************/ +void evel_vnic_performance_rx_discard_pkt_delta_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance, + const double recvd_discard_packets_delta) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(recvd_discard_packets_delta >= 0.0); + + evel_set_option_double(&vnic_performance->recvd_discarded_packets_delta, + recvd_discard_packets_delta, + "Delta Discarded Packets recieved"); + + EVEL_EXIT(); +} + + +/**************************************************************************//** + * Set the Error Packets Received in measurement interval + * property of the vNIC performance. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param vnic_performance Pointer to the vNIC Use. + * @param recvd_error_packets_acc + *****************************************************************************/ +void evel_vnic_performance_rx_error_pkt_acc_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance, + const double recvd_error_packets_acc) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(recvd_error_packets_acc >= 0.0); + + evel_set_option_double(&vnic_performance->recvd_error_packets_acc, + recvd_error_packets_acc, + "Error Packets received accumulated"); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Delta Error Packets Received in measurement interval + * property of the vNIC performance. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param vnic_performance Pointer to the vNIC Use. + * @param recvd_error_packets_delta + *****************************************************************************/ +void evel_vnic_performance_rx_error_pkt_delta_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance, + const double recvd_error_packets_delta) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(recvd_error_packets_delta >= 0.0); + + evel_set_option_double(&vnic_performance->recvd_error_packets_delta, + recvd_error_packets_delta, + "Delta Error Packets recieved"); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Accumulated Multicast Packets Received in measurement interval + * property of the vNIC performance. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param vnic_performance Pointer to the vNIC Use. + * @param recvd_mcast_packets_acc + *****************************************************************************/ +void evel_vnic_performance_rx_mcast_pkt_acc_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance, + const double recvd_mcast_packets_acc) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(recvd_mcast_packets_acc >= 0.0); + + evel_set_option_double(&vnic_performance->recvd_mcast_packets_acc, + recvd_mcast_packets_acc, + "Multicast Packets accumulated"); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Delta Multicast Packets Received in measurement interval + * property of the vNIC performance. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param vnic_performance Pointer to the vNIC Use. + * @param recvd_mcast_packets_delta + *****************************************************************************/ +void evel_vnic_performance_rx_mcast_pkt_delta_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance, + const double recvd_mcast_packets_delta) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(recvd_mcast_packets_delta >= 0.0); + + evel_set_option_double(&vnic_performance->recvd_mcast_packets_delta, + recvd_mcast_packets_delta, + "Delta Multicast Packets recieved"); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Accumulated Octets Received in measurement interval + * property of the vNIC performance. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param vnic_performance Pointer to the vNIC Use. + * @param recvd_octets_acc + *****************************************************************************/ +void evel_vnic_performance_rx_octets_acc_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance, + const double recvd_octets_acc) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(recvd_octets_acc >= 0.0); + + evel_set_option_double(&vnic_performance->recvd_octets_acc, + recvd_octets_acc, + "Octets received accumulated"); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Delta Octets Received in measurement interval + * property of the vNIC performance. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param vnic_performance Pointer to the vNIC Use. + * @param recvd_octets_delta + *****************************************************************************/ +void evel_vnic_performance_rx_octets_delta_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance, + const double recvd_octets_delta) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(recvd_octets_delta >= 0.0); + + evel_set_option_double(&vnic_performance->recvd_octets_delta, + recvd_octets_delta, + "Delta Octets recieved"); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Accumulated Total Packets Received in measurement interval + * property of the vNIC performance. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param vnic_performance Pointer to the vNIC Use. + * @param recvd_total_packets_acc + *****************************************************************************/ +void evel_vnic_performance_rx_total_pkt_acc_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance, + const double recvd_total_packets_acc) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(recvd_total_packets_acc >= 0.0); + + evel_set_option_double(&vnic_performance->recvd_total_packets_acc, + recvd_total_packets_acc, + "Total Packets accumulated"); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Delta Total Packets Received in measurement interval + * property of the vNIC performance. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param vnic_performance Pointer to the vNIC Use. + * @param recvd_total_packets_delta + *****************************************************************************/ +void evel_vnic_performance_rx_total_pkt_delta_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance, + const double recvd_total_packets_delta) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(recvd_total_packets_delta >= 0.0); + + evel_set_option_double(&vnic_performance->recvd_total_packets_delta, + recvd_total_packets_delta, + "Delta Total Packets recieved"); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Accumulated Unicast Packets Received in measurement interval + * property of the vNIC performance. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param vnic_performance Pointer to the vNIC Use. + * @param recvd_ucast_packets_acc + *****************************************************************************/ +void evel_vnic_performance_rx_ucast_pkt_acc_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance, + const double recvd_ucast_packets_acc) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(recvd_ucast_packets_acc >= 0.0); + + evel_set_option_double(&vnic_performance->recvd_ucast_packets_acc, + recvd_ucast_packets_acc, + "Unicast Packets received accumulated"); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Delta Unicast packets Received in measurement interval + * property of the vNIC performance. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param vnic_performance Pointer to the vNIC Use. + * @param recvd_ucast_packets_delta + *****************************************************************************/ +void evel_vnic_performance_rx_ucast_pkt_delta_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance, + const double recvd_ucast_packets_delta) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(recvd_ucast_packets_delta >= 0.0); + + evel_set_option_double(&vnic_performance->recvd_ucast_packets_delta, + recvd_ucast_packets_delta, + "Delta Unicast packets recieved"); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Transmitted Broadcast Packets in measurement interval + * property of the vNIC performance. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param vnic_performance Pointer to the vNIC Use. + * @param tx_bcast_packets_acc + *****************************************************************************/ +void evel_vnic_performance_tx_bcast_pkt_acc_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance, + const double tx_bcast_packets_acc) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(tx_bcast_packets_acc >= 0.0); + + evel_set_option_double(&vnic_performance->tx_bcast_packets_acc, + tx_bcast_packets_acc, + "Transmitted Broadcast Packets accumulated"); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Delta Broadcast packets Transmitted in measurement interval + * property of the vNIC performance. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param vnic_performance Pointer to the vNIC Use. + * @param tx_bcast_packets_delta + *****************************************************************************/ +void evel_vnic_performance_tx_bcast_pkt_delta_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance, + const double tx_bcast_packets_delta) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(tx_bcast_packets_delta >= 0.0); + + evel_set_option_double(&vnic_performance->tx_bcast_packets_delta, + tx_bcast_packets_delta, + "Delta Transmitted Broadcast packets "); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Transmitted Discarded Packets in measurement interval + * property of the vNIC performance. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param vnic_performance Pointer to the vNIC Use. + * @param tx_discarded_packets_acc + *****************************************************************************/ +void evel_vnic_performance_tx_discarded_pkt_acc_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance, + const double tx_discarded_packets_acc) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(tx_discarded_packets_acc >= 0.0); + + evel_set_option_double(&vnic_performance->tx_discarded_packets_acc, + tx_discarded_packets_acc, + "Transmitted Discarded Packets accumulated"); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Delta Discarded packets Transmitted in measurement interval + * property of the vNIC performance. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param vnic_performance Pointer to the vNIC Use. + * @param tx_discarded_packets_delta + *****************************************************************************/ +void evel_vnic_performance_tx_discarded_pkt_delta_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance, + const double tx_discarded_packets_delta) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(tx_discarded_packets_delta >= 0.0); + + evel_set_option_double(&vnic_performance->tx_discarded_packets_delta, + tx_discarded_packets_delta, + "Delta Transmitted Discarded packets "); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Transmitted Errored Packets in measurement interval + * property of the vNIC performance. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param vnic_performance Pointer to the vNIC Use. + * @param tx_error_packets_acc + *****************************************************************************/ +void evel_vnic_performance_tx_error_pkt_acc_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance, + const double tx_error_packets_acc) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(tx_error_packets_acc >= 0.0); + + evel_set_option_double(&vnic_performance->tx_error_packets_acc, + tx_error_packets_acc, + "Transmitted Error Packets accumulated"); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Delta Errored packets Transmitted in measurement interval + * property of the vNIC performance. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param vnic_performance Pointer to the vNIC Use. + * @param tx_error_packets_delta + *****************************************************************************/ +void evel_vnic_performance_tx_error_pkt_delta_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance, + const double tx_error_packets_delta) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(tx_error_packets_delta >= 0.0); + + evel_set_option_double(&vnic_performance->tx_error_packets_delta, + tx_error_packets_delta, + "Delta Transmitted Error packets "); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Transmitted Multicast Packets in measurement interval + * property of the vNIC performance. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param vnic_performance Pointer to the vNIC Use. + * @param tx_mcast_packets_acc + *****************************************************************************/ +void evel_vnic_performance_tx_mcast_pkt_acc_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance, + const double tx_mcast_packets_acc) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(tx_mcast_packets_acc >= 0.0); + + evel_set_option_double(&vnic_performance->tx_mcast_packets_acc, + tx_mcast_packets_acc, + "Transmitted Multicast Packets accumulated"); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Delta Multicast packets Transmitted in measurement interval + * property of the vNIC performance. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param vnic_performance Pointer to the vNIC Use. + * @param tx_mcast_packets_delta + *****************************************************************************/ +void evel_vnic_performance_tx_mcast_pkt_delta_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance, + const double tx_mcast_packets_delta) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(tx_mcast_packets_delta >= 0.0); + + evel_set_option_double(&vnic_performance->tx_mcast_packets_delta, + tx_mcast_packets_delta, + "Delta Transmitted Multicast packets "); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Transmitted Octets in measurement interval + * property of the vNIC performance. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param vnic_performance Pointer to the vNIC Use. + * @param tx_octets_acc + *****************************************************************************/ +void evel_vnic_performance_tx_octets_acc_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance, + const double tx_octets_acc) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(tx_octets_acc >= 0.0); + + evel_set_option_double(&vnic_performance->tx_octets_acc, + tx_octets_acc, + "Transmitted Octets accumulated"); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Delta Octets Transmitted in measurement interval + * property of the vNIC performance. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param vnic_performance Pointer to the vNIC Use. + * @param tx_octets_delta + *****************************************************************************/ +void evel_vnic_performance_tx_octets_delta_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance, + const double tx_octets_delta) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(tx_octets_delta >= 0.0); + + evel_set_option_double(&vnic_performance->tx_octets_delta, + tx_octets_delta, + "Delta Transmitted Octets "); + + EVEL_EXIT(); +} + + +/**************************************************************************//** + * Set the Transmitted Total Packets in measurement interval + * property of the vNIC performance. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param vnic_performance Pointer to the vNIC Use. + * @param tx_total_packets_acc + *****************************************************************************/ +void evel_vnic_performance_tx_total_pkt_acc_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance, + const double tx_total_packets_acc) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(tx_total_packets_acc >= 0.0); + + evel_set_option_double(&vnic_performance->tx_total_packets_acc, + tx_total_packets_acc, + "Transmitted Total Packets accumulated"); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Delta Total Packets Transmitted in measurement interval + * property of the vNIC performance. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param vnic_performance Pointer to the vNIC Use. + * @param tx_total_packets_delta + *****************************************************************************/ +void evel_vnic_performance_tx_total_pkt_delta_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance, + const double tx_total_packets_delta) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(tx_total_packets_delta >= 0.0); + + evel_set_option_double(&vnic_performance->tx_total_packets_delta, + tx_total_packets_delta, + "Delta Transmitted Total Packets "); + + EVEL_EXIT(); +} + + +/**************************************************************************//** + * Set the Transmitted Unicast Packets in measurement interval + * property of the vNIC performance. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param vnic_performance Pointer to the vNIC Use. + * @param tx_ucast_packets_acc + *****************************************************************************/ +void evel_vnic_performance_tx_ucast_pkt_acc_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance, + const double tx_ucast_packets_acc) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(tx_ucast_packets_acc >= 0.0); + + evel_set_option_double(&vnic_performance->tx_ucast_packets_acc, + tx_ucast_packets_acc, + "Transmitted Unicast Packets accumulated"); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Delta Octets Transmitted in measurement interval + * property of the vNIC performance. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param vnic_performance Pointer to the vNIC Use. + * @param tx_ucast_packets_delta + *****************************************************************************/ +void evel_vnic_performance_tx_ucast_pkt_delta_set(MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance, + const double tx_ucast_packets_delta) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(tx_ucast_packets_delta >= 0.0); + + evel_set_option_double(&vnic_performance->tx_ucast_packets_delta, + tx_ucast_packets_delta, + "Delta Transmitted Unicast Packets "); + + EVEL_EXIT(); +} + + +/**************************************************************************//** + * Add an additional vNIC Use to the specified Measurement event. + * + * @param measurement Pointer to the measurement. + * @param vnic_performance Pointer to the vNIC Use to add. + *****************************************************************************/ +void evel_meas_vnic_performance_add(EVENT_MEASUREMENT * const measurement, + MEASUREMENT_VNIC_PERFORMANCE * const vnic_performance) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(measurement != NULL); + assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT); + assert(vnic_performance != NULL); + + dlist_push_last(&measurement->vnic_usage, vnic_performance); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Add an additional vNIC usage record Measurement. + * + * This function implements the previous API, purely for convenience. + * + * The ID is null delimited ASCII string. The library takes a copy so the + * caller does not have to preserve values after the function returns. + * + * @param measurement Pointer to the measurement. + * @param vnic_id ASCIIZ string with the vNIC's ID. + * @param valset true or false confidence level + * @param recvd_bcast_packets_acc Recieved broadcast packets + * @param recvd_bcast_packets_delta Received delta broadcast packets + * @param recvd_discarded_packets_acc Recieved discarded packets + * @param recvd_discarded_packets_delta Received discarded delta packets + * @param recvd_error_packets_acc Received error packets + * @param recvd_error_packets_delta, Received delta error packets + * @param recvd_mcast_packets_acc Received multicast packets + * @param recvd_mcast_packets_delta Received delta multicast packets + * @param recvd_octets_acc Received octets + * @param recvd_octets_delta Received delta octets + * @param recvd_total_packets_acc Received total packets + * @param recvd_total_packets_delta Received delta total packets + * @param recvd_ucast_packets_acc Received Unicast packets + * @param recvd_ucast_packets_delta Received delta unicast packets + * @param tx_bcast_packets_acc Transmitted broadcast packets + * @param tx_bcast_packets_delta Transmitted delta broadcast packets + * @param tx_discarded_packets_acc Transmitted packets discarded + * @param tx_discarded_packets_delta Transmitted delta discarded packets + * @param tx_error_packets_acc Transmitted error packets + * @param tx_error_packets_delta Transmitted delta error packets + * @param tx_mcast_packets_acc Transmitted multicast packets accumulated + * @param tx_mcast_packets_delta Transmitted delta multicast packets + * @param tx_octets_acc Transmitted octets + * @param tx_octets_delta Transmitted delta octets + * @param tx_total_packets_acc Transmitted total packets + * @param tx_total_packets_delta Transmitted delta total packets + * @param tx_ucast_packets_acc Transmitted Unicast packets + * @param tx_ucast_packets_delta Transmitted delta Unicast packets + *****************************************************************************/ +void evel_measurement_vnic_performance_add(EVENT_MEASUREMENT * const measurement, + char * const vnic_id, + char * valset, + double recvd_bcast_packets_acc, + double recvd_bcast_packets_delta, + double recvd_discarded_packets_acc, + double recvd_discarded_packets_delta, + double recvd_error_packets_acc, + double recvd_error_packets_delta, + double recvd_mcast_packets_acc, + double recvd_mcast_packets_delta, + double recvd_octets_acc, + double recvd_octets_delta, + double recvd_total_packets_acc, + double recvd_total_packets_delta, + double recvd_ucast_packets_acc, + double recvd_ucast_packets_delta, + double tx_bcast_packets_acc, + double tx_bcast_packets_delta, + double tx_discarded_packets_acc, + double tx_discarded_packets_delta, + double tx_error_packets_acc, + double tx_error_packets_delta, + double tx_mcast_packets_acc, + double tx_mcast_packets_delta, + double tx_octets_acc, + double tx_octets_delta, + double tx_total_packets_acc, + double tx_total_packets_delta, + double tx_ucast_packets_acc, + double tx_ucast_packets_delta) +{ + MEASUREMENT_VNIC_PERFORMANCE * vnic_performance = NULL; + EVEL_ENTER(); + + /***************************************************************************/ + /* Trust the assertions in the underlying methods. */ + /***************************************************************************/ + vnic_performance = evel_measurement_new_vnic_performance(vnic_id, valset); + + evel_vnic_performance_rx_bcast_pkt_acc_set(vnic_performance, recvd_bcast_packets_acc); + evel_vnic_performance_rx_bcast_pkt_delta_set(vnic_performance, recvd_bcast_packets_delta); + evel_vnic_performance_rx_discard_pkt_acc_set(vnic_performance, recvd_discarded_packets_acc); + evel_vnic_performance_rx_discard_pkt_delta_set(vnic_performance, recvd_discarded_packets_delta); + evel_vnic_performance_rx_error_pkt_acc_set(vnic_performance, recvd_error_packets_acc); + evel_vnic_performance_rx_error_pkt_delta_set(vnic_performance, recvd_error_packets_delta); + evel_vnic_performance_rx_mcast_pkt_acc_set(vnic_performance, recvd_mcast_packets_acc); + evel_vnic_performance_rx_mcast_pkt_delta_set(vnic_performance, recvd_mcast_packets_delta); + evel_vnic_performance_rx_octets_acc_set(vnic_performance, recvd_octets_acc); + evel_vnic_performance_rx_octets_delta_set(vnic_performance, recvd_octets_delta); + evel_vnic_performance_rx_total_pkt_acc_set(vnic_performance, recvd_total_packets_acc); + evel_vnic_performance_rx_total_pkt_delta_set(vnic_performance, recvd_total_packets_delta); + evel_vnic_performance_rx_ucast_pkt_acc_set(vnic_performance, recvd_ucast_packets_acc); + evel_vnic_performance_rx_ucast_pkt_delta_set(vnic_performance, recvd_ucast_packets_delta); + evel_vnic_performance_tx_bcast_pkt_acc_set(vnic_performance, tx_bcast_packets_acc); + evel_vnic_performance_tx_bcast_pkt_delta_set(vnic_performance, tx_bcast_packets_delta); + evel_vnic_performance_tx_discarded_pkt_acc_set(vnic_performance, tx_discarded_packets_acc); + evel_vnic_performance_tx_discarded_pkt_delta_set(vnic_performance, tx_discarded_packets_delta); + evel_vnic_performance_tx_error_pkt_acc_set(vnic_performance, tx_error_packets_acc); + evel_vnic_performance_tx_error_pkt_delta_set(vnic_performance, tx_error_packets_delta); + evel_vnic_performance_tx_mcast_pkt_acc_set(vnic_performance, tx_mcast_packets_acc); + evel_vnic_performance_tx_mcast_pkt_delta_set(vnic_performance, tx_mcast_packets_delta); + evel_vnic_performance_tx_octets_acc_set(vnic_performance, tx_octets_acc); + evel_vnic_performance_tx_octets_delta_set(vnic_performance, tx_octets_delta); + evel_vnic_performance_tx_total_pkt_acc_set(vnic_performance, tx_total_packets_acc); + evel_vnic_performance_tx_total_pkt_delta_set(vnic_performance, tx_total_packets_delta); + evel_vnic_performance_tx_ucast_pkt_acc_set(vnic_performance, tx_ucast_packets_acc); + evel_vnic_performance_tx_ucast_pkt_delta_set(vnic_performance, tx_ucast_packets_delta); + evel_meas_vnic_performance_add(measurement, vnic_performance); +} + +/**************************************************************************//** + * Encode the measurement as a JSON measurement. + * + * @param jbuf Pointer to the ::EVEL_JSON_BUFFER to encode into. + * @param event Pointer to the ::EVENT_HEADER to encode. + *****************************************************************************/ +void evel_json_encode_measurement(EVEL_JSON_BUFFER * jbuf, + EVENT_MEASUREMENT * event) +{ + MEASUREMENT_CPU_USE * cpu_use = NULL; + MEASUREMENT_MEM_USE * mem_use = NULL; + MEASUREMENT_DISK_USE * disk_use = NULL; + MEASUREMENT_FSYS_USE * fsys_use = NULL; + MEASUREMENT_LATENCY_BUCKET * bucket = NULL; + MEASUREMENT_VNIC_PERFORMANCE * vnic_performance = NULL; + MEASUREMENT_ERRORS * errors = NULL; + MEASUREMENT_FEATURE_USE * feature_use = NULL; + MEASUREMENT_CODEC_USE * codec_use = NULL; + MEASUREMENT_GROUP * measurement_group = NULL; + CUSTOM_MEASUREMENT * custom_measurement = NULL; + DLIST_ITEM * item = NULL; + DLIST_ITEM * nested_item = NULL; + DLIST_ITEM * addl_info_item = NULL; + OTHER_FIELD *addl_info = NULL; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(event != NULL); + assert(event->header.event_domain == EVEL_DOMAIN_MEASUREMENT); + + evel_json_encode_header(jbuf, &event->header); + evel_json_open_named_object(jbuf, "measurementsForVfScalingFields"); + + /***************************************************************************/ + /* Mandatory fields. */ + /***************************************************************************/ + evel_enc_kv_int(jbuf, "measurementInterval", event->measurement_interval); + + /***************************************************************************/ + /* Optional fields. */ + /***************************************************************************/ + // additional fields + evel_json_checkpoint(jbuf); + if (evel_json_open_opt_named_list(jbuf, "additionalFields")) + { + bool item_added = false; + + addl_info_item = dlist_get_first(&event->additional_info); + while (addl_info_item != NULL) + { + addl_info = (OTHER_FIELD*) addl_info_item->item; + assert(addl_info != NULL); + + if (!evel_throttle_suppress_nv_pair(jbuf->throttle_spec, + "additionalFields", + addl_info->name)) + { + evel_json_open_object(jbuf); + evel_enc_kv_string(jbuf, "name", addl_info->name); + evel_enc_kv_string(jbuf, "value", addl_info->value); + evel_json_close_object(jbuf); + item_added = true; + } + addl_info_item = dlist_get_next(addl_info_item); + } + evel_json_close_list(jbuf); + + /*************************************************************************/ + /* If we've not written anything, rewind to before we opened the list. */ + /*************************************************************************/ + if (!item_added) + { + evel_json_rewind(jbuf); + } + } + + // TBD additional json objects + evel_enc_kv_opt_int(jbuf, "concurrentSessions", &event->concurrent_sessions); + evel_enc_kv_opt_int(jbuf, "configuredEntities", &event->configured_entities); + + /***************************************************************************/ + /* CPU Use list. */ + /***************************************************************************/ + evel_json_checkpoint(jbuf); + if (evel_json_open_opt_named_list(jbuf, "cpuUsageArray")) + { + bool item_added = false; + + item = dlist_get_first(&event->cpu_usage); + while (item != NULL) + { + cpu_use = (MEASUREMENT_CPU_USE*) item->item; + assert(cpu_use != NULL); + + if (!evel_throttle_suppress_nv_pair(jbuf->throttle_spec, + "cpuUsageArray", + cpu_use->id)) + { + evel_json_open_object(jbuf); + evel_enc_kv_string(jbuf, "cpuIdentifier", cpu_use->id); + evel_enc_kv_opt_double(jbuf, "cpuIdle", &cpu_use->idle); + evel_enc_kv_opt_double(jbuf, "cpuUsageInterrupt", &cpu_use->intrpt); + evel_enc_kv_opt_double(jbuf, "cpuUsageNice", &cpu_use->nice); + evel_enc_kv_opt_double(jbuf, "cpuUsageSoftIrq", &cpu_use->softirq); + evel_enc_kv_opt_double(jbuf, "cpuUsageSteal", &cpu_use->steal); + evel_enc_kv_opt_double(jbuf, "cpuUsageSystem", &cpu_use->sys); + evel_enc_kv_opt_double(jbuf, "cpuUsageUser", &cpu_use->user); + evel_enc_kv_opt_double(jbuf, "cpuWait", &cpu_use->wait); + evel_enc_kv_double(jbuf, "percentUsage",cpu_use->usage); + evel_json_close_object(jbuf); + item_added = true; + } + item = dlist_get_next(item); + } + evel_json_close_list(jbuf); + + /*************************************************************************/ + /* If we've not written anything, rewind to before we opened the list. */ + /*************************************************************************/ + if (!item_added) + { + evel_json_rewind(jbuf); + } + } + + + /***************************************************************************/ + /* Disk Use list. */ + /***************************************************************************/ + evel_json_checkpoint(jbuf); + if (evel_json_open_opt_named_list(jbuf, "diskUsageArray")) + { + bool item_added = false; + + item = dlist_get_first(&event->disk_usage); + while (item != NULL) + { + disk_use = (MEASUREMENT_DISK_USE*) item->item; + assert(disk_use != NULL); + + if (!evel_throttle_suppress_nv_pair(jbuf->throttle_spec, + "diskUsageArray", + disk_use->id)) + { + evel_json_open_object(jbuf); + evel_enc_kv_string(jbuf, "diskIdentifier", disk_use->id); + evel_enc_kv_opt_double(jbuf, "diskIoTimeAvg", &disk_use->iotimeavg); + evel_enc_kv_opt_double(jbuf, "diskIoTimeLast", &disk_use->iotimelast); + evel_enc_kv_opt_double(jbuf, "diskIoTimeMax", &disk_use->iotimemax); + evel_enc_kv_opt_double(jbuf, "diskIoTimeMin", &disk_use->iotimemin); + evel_enc_kv_opt_double(jbuf, "diskMergedReadAvg", &disk_use->mergereadavg); + evel_enc_kv_opt_double(jbuf, "diskMergedReadLast", &disk_use->mergereadlast); + evel_enc_kv_opt_double(jbuf, "diskMergedReadMax", &disk_use->mergereadmax); + evel_enc_kv_opt_double(jbuf, "diskMergedReadMin", &disk_use->mergereadmin); + evel_enc_kv_opt_double(jbuf, "diskMergedWriteAvg", &disk_use->mergewriteavg); + evel_enc_kv_opt_double(jbuf, "diskMergedWriteLast", &disk_use->mergewritelast); + evel_enc_kv_opt_double(jbuf, "diskMergedWriteMax", &disk_use->mergewritemax); + evel_enc_kv_opt_double(jbuf, "diskMergedWriteMin", &disk_use->mergewritemin); + evel_enc_kv_opt_double(jbuf, "diskOctetsReadAvg", &disk_use->octetsreadavg); + evel_enc_kv_opt_double(jbuf, "diskOctetsReadLast", &disk_use->octetsreadlast); + evel_enc_kv_opt_double(jbuf, "diskOctetsReadMax", &disk_use->octetsreadmax); + evel_enc_kv_opt_double(jbuf, "diskOctetsReadMin", &disk_use->octetsreadmin); + evel_enc_kv_opt_double(jbuf, "diskOctetsWriteAvg", &disk_use->octetswriteavg); + evel_enc_kv_opt_double(jbuf, "diskOctetsWriteLast", &disk_use->octetswritelast); + evel_enc_kv_opt_double(jbuf, "diskOctetsWriteMax", &disk_use->octetswritemax); + evel_enc_kv_opt_double(jbuf, "diskOctetsWriteMin", &disk_use->octetswritemin); + evel_enc_kv_opt_double(jbuf, "diskOpsReadAvg", &disk_use->opsreadavg); + evel_enc_kv_opt_double(jbuf, "diskOpsReadLast", &disk_use->opsreadlast); + evel_enc_kv_opt_double(jbuf, "diskOpsReadMax", &disk_use->opsreadmax); + evel_enc_kv_opt_double(jbuf, "diskOpsReadMin", &disk_use->opsreadmin); + evel_enc_kv_opt_double(jbuf, "diskOpsWriteAvg", &disk_use->opswriteavg); + evel_enc_kv_opt_double(jbuf, "diskOpsWriteLast", &disk_use->opswritelast); + evel_enc_kv_opt_double(jbuf, "diskOpsWriteMax", &disk_use->opswritemax); + evel_enc_kv_opt_double(jbuf, "diskOpsWriteMin", &disk_use->opswritemin); + evel_enc_kv_opt_double(jbuf, "diskPendingOperationsAvg", &disk_use->pendingopsavg); + evel_enc_kv_opt_double(jbuf, "diskPendingOperationsLast", &disk_use->pendingopslast); + evel_enc_kv_opt_double(jbuf, "diskPendingOperationsMax", &disk_use->pendingopsmax); + evel_enc_kv_opt_double(jbuf, "diskPendingOperationsMin", &disk_use->pendingopsmin); + evel_enc_kv_opt_double(jbuf, "diskTimeReadAvg", &disk_use->timereadavg); + evel_enc_kv_opt_double(jbuf, "diskTimeReadLast", &disk_use->timereadlast); + evel_enc_kv_opt_double(jbuf, "diskTimeReadMax", &disk_use->timereadmax); + evel_enc_kv_opt_double(jbuf, "diskTimeReadMin", &disk_use->timereadmin); + evel_enc_kv_opt_double(jbuf, "diskTimeWriteAvg", &disk_use->timewriteavg); + evel_enc_kv_opt_double(jbuf, "diskTimeWriteLast", &disk_use->timewritelast); + evel_enc_kv_opt_double(jbuf, "diskTimeWriteMax", &disk_use->timewritemax); + evel_enc_kv_opt_double(jbuf, "diskTimeWriteMin", &disk_use->timewritemin); + evel_json_close_object(jbuf); + item_added = true; + } + item = dlist_get_next(item); + } + evel_json_close_list(jbuf); + + /*************************************************************************/ + /* If we've not written anything, rewind to before we opened the list. */ + /*************************************************************************/ + if (!item_added) + { + evel_json_rewind(jbuf); + } + } + + /***************************************************************************/ + /* Filesystem Usage list. */ + /***************************************************************************/ + evel_json_checkpoint(jbuf); + if (evel_json_open_opt_named_list(jbuf, "filesystemUsageArray")) + { + bool item_added = false; + + item = dlist_get_first(&event->filesystem_usage); + while (item != NULL) + { + fsys_use = (MEASUREMENT_FSYS_USE *) item->item; + assert(fsys_use != NULL); + + if (!evel_throttle_suppress_nv_pair(jbuf->throttle_spec, + "filesystemUsageArray", + fsys_use->filesystem_name)) + { + evel_json_open_object(jbuf); + evel_enc_kv_string(jbuf, "filesystemName", fsys_use->filesystem_name); + evel_enc_kv_double( + jbuf, "blockConfigured", fsys_use->block_configured); + evel_enc_kv_double(jbuf, "blockIops", fsys_use->block_iops); + evel_enc_kv_double(jbuf, "blockUsed", fsys_use->block_used); + evel_enc_kv_double( + jbuf, "ephemeralConfigured", fsys_use->ephemeral_configured); + evel_enc_kv_double(jbuf, "ephemeralIops", fsys_use->ephemeral_iops); + evel_enc_kv_double(jbuf, "ephemeralUsed", fsys_use->ephemeral_used); + evel_json_close_object(jbuf); + item_added = true; + } + item = dlist_get_next(item); + } + evel_json_close_list(jbuf); + + /*************************************************************************/ + /* If we've not written anything, rewind to before we opened the list. */ + /*************************************************************************/ + if (!item_added) + { + evel_json_rewind(jbuf); + } + } + + /***************************************************************************/ + /* Latency distribution. */ + /***************************************************************************/ + item = dlist_get_first(&event->latency_distribution); + if ((item != NULL) && + evel_json_open_opt_named_list(jbuf, "latencyDistribution")) + { + while (item != NULL) + { + bucket = (MEASUREMENT_LATENCY_BUCKET*) item->item; + assert(bucket != NULL); + + evel_json_open_object(jbuf); + evel_enc_kv_opt_double( + jbuf, "lowEndOfLatencyBucket", &bucket->low_end); + evel_enc_kv_opt_double( + jbuf, "highEndOfLatencyBucket", &bucket->high_end); + evel_enc_kv_int(jbuf, "countsInTheBucket", bucket->count); + evel_json_close_object(jbuf); + item = dlist_get_next(item); + } + evel_json_close_list(jbuf); + } + + evel_enc_kv_opt_double( + jbuf, "meanRequestLatency", &event->mean_request_latency); + evel_enc_kv_opt_int(jbuf, "requestRate", &event->request_rate); + + /***************************************************************************/ + /* vNIC Usage TBD Performance array */ + /***************************************************************************/ + evel_json_checkpoint(jbuf); + if (evel_json_open_opt_named_list(jbuf, "vNicUsageArray")) + { + bool item_added = false; + + item = dlist_get_first(&event->vnic_usage); + while (item != NULL) + { + vnic_performance = (MEASUREMENT_VNIC_PERFORMANCE *) item->item; + assert(vnic_performance != NULL); + + if (!evel_throttle_suppress_nv_pair(jbuf->throttle_spec, + "vNicPerformanceArray", + vnic_performance->vnic_id)) + { + evel_json_open_object(jbuf); + + /*********************************************************************/ + /* Optional fields. */ + /*********************************************************************/ + evel_enc_kv_opt_double( jbuf, + "receivedBroadcastPacketsAccumulated", &vnic_performance->recvd_bcast_packets_acc); + evel_enc_kv_opt_double( jbuf, + "receivedBroadcastPacketsDelta", &vnic_performance->recvd_bcast_packets_delta); + evel_enc_kv_opt_double( jbuf, + "receivedDiscardedPacketsAccumulated", &vnic_performance->recvd_discarded_packets_acc); + evel_enc_kv_opt_double( jbuf, + "receivedDiscardedPacketsDelta", &vnic_performance->recvd_discarded_packets_delta); + evel_enc_kv_opt_double( jbuf, + "receivedErrorPacketsAccumulated", &vnic_performance->recvd_error_packets_acc); + evel_enc_kv_opt_double( jbuf, + "receivedErrorPacketsDelta", &vnic_performance->recvd_error_packets_delta); + evel_enc_kv_opt_double( jbuf, + "receivedMulticastPacketsAccumulated", &vnic_performance->recvd_mcast_packets_acc); + evel_enc_kv_opt_double( jbuf, + "receivedMulticastPacketsDelta", &vnic_performance->recvd_mcast_packets_delta); + evel_enc_kv_opt_double( jbuf, + "receivedOctetsAccumulated", &vnic_performance->recvd_octets_acc); + evel_enc_kv_opt_double( jbuf, + "receivedOctetsDelta", &vnic_performance->recvd_octets_delta); + evel_enc_kv_opt_double( jbuf, + "receivedTotalPacketsAccumulated", &vnic_performance->recvd_total_packets_acc); + evel_enc_kv_opt_double( jbuf, + "receivedTotalPacketsDelta", &vnic_performance->recvd_total_packets_delta); + evel_enc_kv_opt_double( jbuf, + "receivedUnicastPacketsAccumulated", &vnic_performance->recvd_ucast_packets_acc); + evel_enc_kv_opt_double( jbuf, + "receivedUnicastPacketsDelta", &vnic_performance->recvd_ucast_packets_delta); + evel_enc_kv_opt_double( jbuf, + "transmittedBroadcastPacketsAccumulated", &vnic_performance->tx_bcast_packets_acc); + evel_enc_kv_opt_double( jbuf, + "transmittedBroadcastPacketsDelta", &vnic_performance->tx_bcast_packets_delta); + evel_enc_kv_opt_double( jbuf, + "transmittedDiscardedPacketsAccumulated", &vnic_performance->tx_discarded_packets_acc); + evel_enc_kv_opt_double( jbuf, + "transmittedDiscardedPacketsDelta", &vnic_performance->tx_discarded_packets_delta); + evel_enc_kv_opt_double( jbuf, + "transmittedErrorPacketsAccumulated", &vnic_performance->tx_error_packets_acc); + evel_enc_kv_opt_double( jbuf, + "transmittedErrorPacketsDelta", &vnic_performance->tx_error_packets_delta); + evel_enc_kv_opt_double( jbuf, + "transmittedMulticastPacketsAccumulated", &vnic_performance->tx_mcast_packets_acc); + evel_enc_kv_opt_double( jbuf, + "transmittedMulticastPacketsDelta", &vnic_performance->tx_mcast_packets_delta); + evel_enc_kv_opt_double( jbuf, + "transmittedOctetsAccumulated", &vnic_performance->tx_octets_acc); + evel_enc_kv_opt_double( jbuf, + "transmittedOctetsDelta", &vnic_performance->tx_octets_delta); + evel_enc_kv_opt_double( jbuf, + "transmittedTotalPacketsAccumulated", &vnic_performance->tx_total_packets_acc); + evel_enc_kv_opt_double( jbuf, + "transmittedTotalPacketsDelta", &vnic_performance->tx_total_packets_delta); + evel_enc_kv_opt_double( jbuf, + "transmittedUnicastPacketsAccumulated", &vnic_performance->tx_ucast_packets_acc); + evel_enc_kv_opt_double( jbuf, + "transmittedUnicastPacketsDelta", &vnic_performance->tx_ucast_packets_delta); + + /*********************************************************************/ + /* Mandatory fields. */ + /*********************************************************************/ + evel_enc_kv_string(jbuf, "valuesAreSuspect", vnic_performance->valuesaresuspect); + evel_enc_kv_string(jbuf, "vNicIdentifier", vnic_performance->vnic_id); + + evel_json_close_object(jbuf); + item_added = true; + } + item = dlist_get_next(item); + } + + evel_json_close_list(jbuf); + + /*************************************************************************/ + /* If we've not written anything, rewind to before we opened the list. */ + /*************************************************************************/ + if (!item_added) + { + evel_json_rewind(jbuf); + } + } + + + /***************************************************************************/ + /* Memory Use list. */ + /***************************************************************************/ + evel_json_checkpoint(jbuf); + if (evel_json_open_opt_named_list(jbuf, "memoryUsageArray")) + { + bool item_added = false; + + item = dlist_get_first(&event->mem_usage); + while (item != NULL) + { + mem_use = (MEASUREMENT_MEM_USE*) item->item; + assert(mem_use != NULL); + + if (!evel_throttle_suppress_nv_pair(jbuf->throttle_spec, + "memoryUsageArray", + mem_use->id)) + { + evel_json_open_object(jbuf); + evel_enc_kv_double(jbuf, "memoryBuffered", mem_use->membuffsz); + evel_enc_kv_opt_double(jbuf, "memoryCached", &mem_use->memcache); + evel_enc_kv_opt_double(jbuf, "memoryConfigured", &mem_use->memconfig); + evel_enc_kv_opt_double(jbuf, "memoryFree", &mem_use->memfree); + evel_enc_kv_opt_double(jbuf, "memorySlabRecl", &mem_use->slabrecl); + evel_enc_kv_opt_double(jbuf, "memorySlabUnrecl", &mem_use->slabunrecl); + evel_enc_kv_opt_double(jbuf, "memoryUsed", &mem_use->memused); + evel_enc_kv_string(jbuf, "vmIdentifier", mem_use->id); + evel_json_close_object(jbuf); + item_added = true; + } + item = dlist_get_next(item); + } + evel_json_close_list(jbuf); + + /*************************************************************************/ + /* If we've not written anything, rewind to before we opened the list. */ + /*************************************************************************/ + if (!item_added) + { + evel_json_rewind(jbuf); + } + } + + + evel_enc_kv_opt_int( + jbuf, "numberOfMediaPortsInUse", &event->media_ports_in_use); + evel_enc_kv_opt_int( + jbuf, "vnfcScalingMetric", &event->vnfc_scaling_metric); + + /***************************************************************************/ + /* Errors list. */ + /***************************************************************************/ + if ((event->errors != NULL) && + evel_json_open_opt_named_object(jbuf, "errors")) + { + errors = event->errors; + evel_enc_kv_int(jbuf, "receiveDiscards", errors->receive_discards); + evel_enc_kv_int(jbuf, "receiveErrors", errors->receive_errors); + evel_enc_kv_int(jbuf, "transmitDiscards", errors->transmit_discards); + evel_enc_kv_int(jbuf, "transmitErrors", errors->transmit_errors); + evel_json_close_object(jbuf); + } + + /***************************************************************************/ + /* Feature Utilization list. */ + /***************************************************************************/ + evel_json_checkpoint(jbuf); + if (evel_json_open_opt_named_list(jbuf, "featureUsageArray")) + { + bool item_added = false; + + item = dlist_get_first(&event->feature_usage); + while (item != NULL) + { + feature_use = (MEASUREMENT_FEATURE_USE*) item->item; + assert(feature_use != NULL); + + if (!evel_throttle_suppress_nv_pair(jbuf->throttle_spec, + "featureUsageArray", + feature_use->feature_id)) + { + evel_json_open_object(jbuf); + evel_enc_kv_string(jbuf, "featureIdentifier", feature_use->feature_id); + evel_enc_kv_int( + jbuf, "featureUtilization", feature_use->feature_utilization); + evel_json_close_object(jbuf); + item_added = true; + } + item = dlist_get_next(item); + } + evel_json_close_list(jbuf); + + /*************************************************************************/ + /* If we've not written anything, rewind to before we opened the list. */ + /*************************************************************************/ + if (!item_added) + { + evel_json_rewind(jbuf); + } + } + + /***************************************************************************/ + /* Codec Utilization list. */ + /***************************************************************************/ + evel_json_checkpoint(jbuf); + if (evel_json_open_opt_named_list(jbuf, "codecUsageArray")) + { + bool item_added = false; + + item = dlist_get_first(&event->codec_usage); + while (item != NULL) + { + codec_use = (MEASUREMENT_CODEC_USE*) item->item; + assert(codec_use != NULL); + + if (!evel_throttle_suppress_nv_pair(jbuf->throttle_spec, + "codecUsageArray", + codec_use->codec_id)) + { + evel_json_open_object(jbuf); + evel_enc_kv_string(jbuf, "codecIdentifier", codec_use->codec_id); + evel_enc_kv_int(jbuf, "numberInUse", codec_use->number_in_use); + evel_json_close_object(jbuf); + item_added = true; + } + item = dlist_get_next(item); + } + evel_json_close_list(jbuf); + + /*************************************************************************/ + /* If we've not written anything, rewind to before we opened the list. */ + /*************************************************************************/ + if (!item_added) + { + evel_json_rewind(jbuf); + } + } + + /***************************************************************************/ + /* Additional Measurement Groups list. */ + /***************************************************************************/ + evel_json_checkpoint(jbuf); + if (evel_json_open_opt_named_list(jbuf, "additionalMeasurements")) + { + bool item_added = false; + + item = dlist_get_first(&event->additional_measurements); + while (item != NULL) + { + measurement_group = (MEASUREMENT_GROUP *) item->item; + assert(measurement_group != NULL); + + if (!evel_throttle_suppress_nv_pair(jbuf->throttle_spec, + "additionalMeasurements", + measurement_group->name)) + { + evel_json_open_object(jbuf); + evel_enc_kv_string(jbuf, "name", measurement_group->name); + evel_json_open_opt_named_list(jbuf, "measurements"); + + /*********************************************************************/ + /* Measurements list. */ + /*********************************************************************/ + nested_item = dlist_get_first(&measurement_group->measurements); + while (nested_item != NULL) + { + custom_measurement = (CUSTOM_MEASUREMENT *) nested_item->item; + assert(custom_measurement != NULL); + + evel_json_open_object(jbuf); + evel_enc_kv_string(jbuf, "name", custom_measurement->name); + evel_enc_kv_string(jbuf, "value", custom_measurement->value); + evel_json_close_object(jbuf); + nested_item = dlist_get_next(nested_item); + } + evel_json_close_list(jbuf); + evel_json_close_object(jbuf); + item_added = true; + } + item = dlist_get_next(item); + } + evel_json_close_list(jbuf); + + /*************************************************************************/ + /* If we've not written anything, rewind to before we opened the list. */ + /*************************************************************************/ + if (!item_added) + { + evel_json_rewind(jbuf); + } + } + + /***************************************************************************/ + /* Although optional, we always generate the version. Note that this */ + /* closes the object, too. */ + /***************************************************************************/ + evel_enc_version(jbuf, + "measurementsForVfScalingVersion", + event->major_version, + event->minor_version); + evel_json_close_object(jbuf); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Free a Measurement. + * + * Free off the Measurement supplied. Will free all the contained allocated + * memory. + * + * @note It does not free the Measurement itself, since that may be part of a + * larger structure. + *****************************************************************************/ +void evel_free_measurement(EVENT_MEASUREMENT * event) +{ + MEASUREMENT_CPU_USE * cpu_use = NULL; + MEASUREMENT_DISK_USE * disk_use = NULL; + MEASUREMENT_FSYS_USE * fsys_use = NULL; + MEASUREMENT_LATENCY_BUCKET * bucket = NULL; + MEASUREMENT_MEM_USE * mem_use = NULL; + MEASUREMENT_VNIC_PERFORMANCE * vnic_performance = NULL; + MEASUREMENT_FEATURE_USE * feature_use = NULL; + MEASUREMENT_CODEC_USE * codec_use = NULL; + MEASUREMENT_GROUP * measurement_group = NULL; + CUSTOM_MEASUREMENT * measurement = NULL; + OTHER_FIELD *addl_info = NULL; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. As an internal API we don't allow freeing NULL */ + /* events as we do on the public API. */ + /***************************************************************************/ + assert(event != NULL); + assert(event->header.event_domain == EVEL_DOMAIN_MEASUREMENT); + + /***************************************************************************/ + /* Free all internal strings then the header itself. */ + /***************************************************************************/ + addl_info = dlist_pop_last(&event->additional_info); + while (addl_info != NULL) + { + EVEL_DEBUG("Freeing Additional Info (%s, %s)", + addl_info->name, + addl_info->value); + free(addl_info->name); + free(addl_info->value); + free(addl_info); + addl_info = dlist_pop_last(&event->additional_info); + } + + + + cpu_use = dlist_pop_last(&event->cpu_usage); + while (cpu_use != NULL) + { + EVEL_DEBUG("Freeing CPU use Info (%s)", cpu_use->id); + free(cpu_use->id); + free(cpu_use); + cpu_use = dlist_pop_last(&event->cpu_usage); + } + disk_use = dlist_pop_last(&event->disk_usage); + while (disk_use != NULL) + { + EVEL_DEBUG("Freeing Disk use Info (%s)", disk_use->id); + free(disk_use->id); + free(disk_use); + disk_use = dlist_pop_last(&event->disk_usage); + } + mem_use = dlist_pop_last(&event->mem_usage); + while (mem_use != NULL) + { + EVEL_DEBUG("Freeing Memory use Info (%s)", mem_use->id); + free(mem_use->id); + free(mem_use->vmid); + free(mem_use); + mem_use = dlist_pop_last(&event->mem_usage); + } + + fsys_use = dlist_pop_last(&event->filesystem_usage); + while (fsys_use != NULL) + { + EVEL_DEBUG("Freeing Filesystem Use info (%s)", fsys_use->filesystem_name); + free(fsys_use->filesystem_name); + free(fsys_use); + fsys_use = dlist_pop_last(&event->filesystem_usage); + } + + bucket = dlist_pop_last(&event->latency_distribution); + while (bucket != NULL) + { + EVEL_DEBUG("Freeing Latency Bucket"); + free(bucket); + bucket = dlist_pop_last(&event->latency_distribution); + } + + vnic_performance = dlist_pop_last(&event->vnic_usage); + while (vnic_performance != NULL) + { + EVEL_DEBUG("Freeing vNIC performance Info (%s)", vnic_performance->vnic_id); + evel_measurement_free_vnic_performance(vnic_performance); + free(vnic_performance); + vnic_performance = dlist_pop_last(&event->vnic_usage); + } + + codec_use = dlist_pop_last(&event->codec_usage); + while (codec_use != NULL) + { + EVEL_DEBUG("Freeing Codec use Info (%s)", codec_use->codec_id); + free(codec_use->codec_id); + free(codec_use); + codec_use = dlist_pop_last(&event->codec_usage); + } + + if (event->errors != NULL) + { + EVEL_DEBUG("Freeing Errors"); + free(event->errors); + } + + feature_use = dlist_pop_last(&event->feature_usage); + while (feature_use != NULL) + { + EVEL_DEBUG("Freeing Feature use Info (%s)", feature_use->feature_id); + free(feature_use->feature_id); + free(feature_use); + feature_use = dlist_pop_last(&event->feature_usage); + } + + measurement_group = dlist_pop_last(&event->additional_measurements); + while (measurement_group != NULL) + { + EVEL_DEBUG("Freeing Measurement Group (%s)", measurement_group->name); + + measurement = dlist_pop_last(&measurement_group->measurements); + while (measurement != NULL) + { + EVEL_DEBUG("Freeing Measurement (%s)", measurement->name); + free(measurement->name); + free(measurement->value); + free(measurement); + measurement = dlist_pop_last(&measurement_group->measurements); + } + free(measurement_group->name); + free(measurement_group); + measurement_group = dlist_pop_last(&event->additional_measurements); + } + + evel_free_header(&event->header); + + EVEL_EXIT(); +} + diff --git a/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_sipsignaling.c b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_sipsignaling.c new file mode 100644 index 0000000..45f5348 --- /dev/null +++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_sipsignaling.c @@ -0,0 +1,574 @@ +/*************************************************************************//** + * + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************/ +/**************************************************************************//** + * @file + * Implementation of EVEL functions relating to Signaling. + * + ****************************************************************************/ + +#include +#include +#include + +#include "evel_throttle.h" + +/**************************************************************************//** + * Create a new Signaling event. + * + * @note The mandatory fields on the Signaling must be supplied to + * this factory function and are immutable once set. Optional fields + * have explicit setter functions, but again values may only be set + * once so that the event has immutable properties. + * @param event_name Unique Event Name confirming Domain AsdcModel Description + * @param event_id A universal identifier of the event for: troubleshooting correlation, analysis, etc + * @param vendor_name The vendor id to encode in the event vnf field. + * @param module The module to encode in the event. + * @param vnfname The Virtual network function to encode in the event. + * @returns pointer to the newly manufactured ::EVENT_SIGNALING. If the event + * is not used (i.e. posted) it must be released using + * ::evel_free_signaling. + * @retval NULL Failed to create the event. + *****************************************************************************/ +EVENT_SIGNALING * evel_new_signaling(const char* ev_name, const char *ev_id, + const char * const vendor_name, + const char * const correlator, + const char * const local_ip_address, + const char * const local_port, + const char * const remote_ip_address, + const char * const remote_port) +{ + EVENT_SIGNALING * event = NULL; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(vendor_name != NULL); + + /***************************************************************************/ + /* Allocate the Signaling event. */ + /***************************************************************************/ + event = malloc(sizeof(EVENT_SIGNALING)); + if (event == NULL) + { + log_error_state("Out of memory"); + goto exit_label; + } + memset(event, 0, sizeof(EVENT_SIGNALING)); + EVEL_DEBUG("New Signaling event is at %lp", event); + + /***************************************************************************/ + /* Initialize the header & the Signaling fields. */ + /***************************************************************************/ + evel_init_header_nameid(&event->header,ev_name,ev_id); + event->header.event_domain = EVEL_DOMAIN_SIPSIGNALING; + event->major_version = EVEL_SIGNALING_MAJOR_VERSION; + event->minor_version = EVEL_SIGNALING_MINOR_VERSION; + evel_init_vendor_field(&event->vnfname_field, vendor_name); + evel_set_option_string(&event->correlator,correlator,"Init correlator"); + evel_set_option_string(&event->local_ip_address,local_ip_address,"Init correlator"); + evel_set_option_string(&event->local_port,local_port,"Init local port"); + evel_set_option_string(&event->remote_ip_address,remote_ip_address,"Init remote ip"); + evel_set_option_string(&event->remote_port,remote_port,"Init remote port"); + evel_init_option_string(&event->compressed_sip); + evel_init_option_string(&event->summary_sip); + dlist_initialize(&event->additional_info); + +exit_label: + + EVEL_EXIT(); + return event; +} + +/**************************************************************************//** + * Add an additional value name/value pair to the SIP signaling. + * + * The name and value are null delimited ASCII strings. The library takes + * a copy so the caller does not have to preserve values after the function + * returns. + * + * @param event Pointer to the fault. + * @param name ASCIIZ string with the attribute's name. The caller + * does not need to preserve the value once the function + * returns. + * @param value ASCIIZ string with the attribute's value. The caller + * does not need to preserve the value once the function + * returns. + *****************************************************************************/ +void evel_signaling_addl_info_add(EVENT_SIGNALING * event, char * name, char * value) +{ + FAULT_ADDL_INFO * addl_info = NULL; + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(event != NULL); + assert(event->header.event_domain == EVEL_DOMAIN_SIPSIGNALING); + assert(name != NULL); + assert(value != NULL); + + EVEL_DEBUG("Adding name=%s value=%s", name, value); + addl_info = malloc(sizeof(SIGNALING_ADDL_FIELD)); + assert(addl_info != NULL); + memset(addl_info, 0, sizeof(SIGNALING_ADDL_FIELD)); + addl_info->name = strdup(name); + addl_info->value = strdup(value); + assert(addl_info->name != NULL); + assert(addl_info->value != NULL); + + dlist_push_last(&event->additional_info, addl_info); + + EVEL_EXIT(); +} + + +/**************************************************************************//** + * Set the Event Type property of the Signaling event. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param event Pointer to the Signaling event. + * @param type The Event Type to be set. ASCIIZ string. The caller + * does not need to preserve the value once the function + * returns. + *****************************************************************************/ +void evel_signaling_type_set(EVENT_SIGNALING * const event, + const char * const type) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions and call evel_header_type_set. */ + /***************************************************************************/ + assert(event != NULL); + assert(event->header.event_domain == EVEL_DOMAIN_SIPSIGNALING); + evel_header_type_set(&event->header, type); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Local Ip Address property of the Signaling event. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param event Pointer to the Signaling event. + * @param local_ip_address + * The Local Ip Address to be set. ASCIIZ string. The + * caller does not need to preserve the value once the + * function returns. + *****************************************************************************/ +void evel_signaling_local_ip_address_set(EVENT_SIGNALING * const event, + const char * const local_ip_address) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(event != NULL); + assert(event->header.event_domain == EVEL_DOMAIN_SIPSIGNALING); + assert(local_ip_address != NULL); + + evel_set_option_string(&event->local_ip_address, + local_ip_address, + "Local Ip Address"); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Local Port property of the Signaling event. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param event Pointer to the Signaling event. + * @param local_port The Local Port to be set. ASCIIZ string. The caller + * does not need to preserve the value once the function + * returns. + *****************************************************************************/ +void evel_signaling_local_port_set(EVENT_SIGNALING * const event, + const char * const local_port) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(event != NULL); + assert(event->header.event_domain == EVEL_DOMAIN_SIPSIGNALING); + assert(local_port != NULL); + + evel_set_option_string(&event->local_port, + local_port, + "Local Port"); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Remote Ip Address property of the Signaling event. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param event Pointer to the Signaling event. + * @param remote_ip_address + * The Remote Ip Address to be set. ASCIIZ string. The + * caller does not need to preserve the value once the + * function returns. + *****************************************************************************/ +void evel_signaling_remote_ip_address_set(EVENT_SIGNALING * const event, + const char * const remote_ip_address) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(event != NULL); + assert(event->header.event_domain == EVEL_DOMAIN_SIPSIGNALING); + assert(remote_ip_address != NULL); + + evel_set_option_string(&event->remote_ip_address, + remote_ip_address, + "Remote Ip Address"); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Remote Port property of the Signaling event. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param event Pointer to the Signaling event. + * @param remote_port The Remote Port to be set. ASCIIZ string. The caller + * does not need to preserve the value once the function + * returns. + *****************************************************************************/ +void evel_signaling_remote_port_set(EVENT_SIGNALING * const event, + const char * const remote_port) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(event != NULL); + assert(event->header.event_domain == EVEL_DOMAIN_SIPSIGNALING); + assert(remote_port != NULL); + + evel_set_option_string(&event->remote_port, + remote_port, + "Remote Port"); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Vendor module property of the Signaling event. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param event Pointer to the Signaling event. + * @param modulename The module name to be set. ASCIIZ string. The caller + * does not need to preserve the value once the function + * returns. + *****************************************************************************/ +void evel_signaling_vnfmodule_name_set(EVENT_SIGNALING * const event, + const char * const module_name) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(event != NULL); + assert(event->header.event_domain == EVEL_DOMAIN_SIPSIGNALING); + assert(module_name != NULL); + + evel_vendor_field_module_set(&event->vnfname_field, module_name); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Vendor module property of the Signaling event. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param event Pointer to the Signaling event. + * @param vnfname The Virtual Network function to be set. ASCIIZ string. + * The caller does not need to preserve the value once + * the function returns. + *****************************************************************************/ +void evel_signaling_vnfname_set(EVENT_SIGNALING * const event, + const char * const vnfname) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(event != NULL); + assert(event->header.event_domain == EVEL_DOMAIN_SIPSIGNALING); + assert(vnfname != NULL); + + evel_vendor_field_vnfname_set(&event->vnfname_field, vnfname); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Compressed SIP property of the Signaling event. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param event Pointer to the Signaling event. + * @param compressed_sip + * The Compressed SIP to be set. ASCIIZ string. The caller + * does not need to preserve the value once the function + * returns. + *****************************************************************************/ +void evel_signaling_compressed_sip_set(EVENT_SIGNALING * const event, + const char * const compressed_sip) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(event != NULL); + assert(event->header.event_domain == EVEL_DOMAIN_SIPSIGNALING); + assert(compressed_sip != NULL); + + evel_set_option_string(&event->compressed_sip, + compressed_sip, + "Compressed SIP"); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Summary SIP property of the Signaling event. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param event Pointer to the Signaling event. + * @param summary_sip The Summary SIP to be set. ASCIIZ string. The caller + * does not need to preserve the value once the function + * returns. + *****************************************************************************/ +void evel_signaling_summary_sip_set(EVENT_SIGNALING * const event, + const char * const summary_sip) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(event != NULL); + assert(event->header.event_domain == EVEL_DOMAIN_SIPSIGNALING); + assert(summary_sip != NULL); + + evel_set_option_string(&event->summary_sip, + summary_sip, + "Summary SIP"); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Correlator property of the Signaling event. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param event Pointer to the Signaling event. + * @param correlator The correlator to be set. ASCIIZ string. The caller + * does not need to preserve the value once the function + * returns. + *****************************************************************************/ +void evel_signaling_correlator_set(EVENT_SIGNALING * const event, + const char * const correlator) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions and call evel_header_type_set. */ + /***************************************************************************/ + assert(event != NULL); + assert(event->header.event_domain == EVEL_DOMAIN_SIPSIGNALING); + evel_set_option_string(&event->correlator, + correlator, + "Correlator"); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Encode the Signaling in JSON according to AT&T's schema for the + * event type. + * + * @param jbuf Pointer to the ::EVEL_JSON_BUFFER to encode into. + * @param event Pointer to the ::EVENT_HEADER to encode. + *****************************************************************************/ +void evel_json_encode_signaling(EVEL_JSON_BUFFER * const jbuf, + EVENT_SIGNALING * const event) +{ + SIGNALING_ADDL_FIELD * addl_info = NULL; + DLIST_ITEM * addl_info_item = NULL; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(event != NULL); + assert(event->header.event_domain == EVEL_DOMAIN_SIPSIGNALING); + + evel_json_encode_header(jbuf, &event->header); + evel_json_open_named_object(jbuf, "signalingFields"); + + /***************************************************************************/ + /* Mandatory fields */ + /***************************************************************************/ + + /***************************************************************************/ + /* Optional fields */ + /***************************************************************************/ + evel_enc_kv_opt_string(jbuf, "compressedSip", &event->compressed_sip); + evel_enc_kv_opt_string(jbuf, "correlator", &event->correlator); + evel_enc_kv_opt_string(jbuf, "localIpAddress", &event->local_ip_address); + evel_enc_kv_opt_string(jbuf, "localPort", &event->local_port); + evel_enc_kv_opt_string(jbuf, "remoteIpAddress", &event->remote_ip_address); + evel_enc_kv_opt_string(jbuf, "remotePort", &event->remote_port); + evel_enc_version(jbuf, "signalingFieldsVersion", event->major_version,event->minor_version); + evel_enc_kv_opt_string(jbuf, "summarySip", &event->summary_sip); + evel_json_encode_vendor_field(jbuf, &event->vnfname_field); + + + /***************************************************************************/ + /* Checkpoint, so that we can wind back if all fields are suppressed. */ + /***************************************************************************/ + evel_json_checkpoint(jbuf); + if (evel_json_open_opt_named_list(jbuf, "additionalInformation")) + { + bool item_added = false; + + addl_info_item = dlist_get_first(&event->additional_info); + while (addl_info_item != NULL) + { + addl_info = (SIGNALING_ADDL_FIELD*) addl_info_item->item; + assert(addl_info != NULL); + + if (!evel_throttle_suppress_nv_pair(jbuf->throttle_spec, + "additionalInformation", + addl_info->name)) + { + evel_json_open_object(jbuf); + evel_enc_kv_string(jbuf, "name", addl_info->name); + evel_enc_kv_string(jbuf, "value", addl_info->value); + evel_json_close_object(jbuf); + item_added = true; + } + addl_info_item = dlist_get_next(addl_info_item); + } + evel_json_close_list(jbuf); + + /*************************************************************************/ + /* If we've not written anything, rewind to before we opened the list. */ + /*************************************************************************/ + if (!item_added) + { + evel_json_rewind(jbuf); + } + } + + evel_json_close_object(jbuf); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Free a Signaling event. + * + * Free off the event supplied. Will free all the contained allocated memory. + * + * @note It does not free the event itself, since that may be part of a larger + * structure. + *****************************************************************************/ +void evel_free_signaling(EVENT_SIGNALING * const event) +{ + SIGNALING_ADDL_FIELD * addl_info = NULL; + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. As an internal API we don't allow freeing NULL */ + /* events as we do on the public API. */ + /***************************************************************************/ + assert(event != NULL); + assert(event->header.event_domain == EVEL_DOMAIN_SIPSIGNALING); + + /***************************************************************************/ + /* Free all internal strings then the header itself. */ + /***************************************************************************/ + addl_info = dlist_pop_last(&event->additional_info); + while (addl_info != NULL) + { + EVEL_DEBUG("Freeing Additional Info (%s, %s)", + addl_info->name, + addl_info->value); + free(addl_info->name); + free(addl_info->value); + free(addl_info); + addl_info = dlist_pop_last(&event->additional_info); + } + + evel_free_event_vendor_field(&event->vnfname_field); + evel_free_option_string(&event->correlator); + evel_free_option_string(&event->local_ip_address); + evel_free_option_string(&event->local_port); + evel_free_option_string(&event->remote_ip_address); + evel_free_option_string(&event->remote_port); + evel_free_option_string(&event->compressed_sip); + evel_free_option_string(&event->summary_sip); + evel_free_header(&event->header); + + EVEL_EXIT(); +} diff --git a/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_state_change.c b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_state_change.c new file mode 100644 index 0000000..8915afa --- /dev/null +++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_state_change.c @@ -0,0 +1,286 @@ +/*************************************************************************//** + * + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************/ +/**************************************************************************//** + * @file + * Implementation of EVEL functions relating to the State Change. + * + ****************************************************************************/ + +#include +#include +#include + +#include "evel_throttle.h" + +/**************************************************************************//** + * Create a new State Change event. + * + * @note The mandatory fields on the State Change must be supplied to this + * factory function and are immutable once set. Optional fields have + * explicit setter functions, but again values may only be set once + * so that the State Change has immutable properties. + * + * @param event_name Unique Event Name confirming Domain AsdcModel Description + * @param event_id A universal identifier of the event for: troubleshooting correlation, analysis, etc + * @param new_state The new state of the reporting entity. + * @param old_state The old state of the reporting entity. + * @param interface The card or port name of the reporting entity. + * + * @returns pointer to the newly manufactured ::EVENT_STATE_CHANGE. If the + * event is not used it must be released using + * ::evel_free_state_change + * @retval NULL Failed to create the event. + *****************************************************************************/ +EVENT_STATE_CHANGE * evel_new_state_change(const char* ev_name, + const char *ev_id, + const EVEL_ENTITY_STATE new_state, + const EVEL_ENTITY_STATE old_state, + const char * const interface) +{ + EVENT_STATE_CHANGE * state_change = NULL; + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(new_state < EVEL_MAX_ENTITY_STATES); + assert(old_state < EVEL_MAX_ENTITY_STATES); + assert(interface != NULL); + + /***************************************************************************/ + /* Allocate the State Change. */ + /***************************************************************************/ + state_change = malloc(sizeof(EVENT_STATE_CHANGE)); + if (state_change == NULL) + { + log_error_state("Out of memory"); + goto exit_label; + } + memset(state_change, 0, sizeof(EVENT_STATE_CHANGE)); + EVEL_DEBUG("New State Change is at %lp", state_change); + + /***************************************************************************/ + /* Initialize the header & the State Change fields. Optional string */ + /* values are uninitialized (NULL). */ + /***************************************************************************/ + evel_init_header_nameid(&state_change->header,ev_name,ev_id); + state_change->header.event_domain = EVEL_DOMAIN_STATE_CHANGE; + state_change->major_version = EVEL_STATE_CHANGE_MAJOR_VERSION; + state_change->minor_version = EVEL_STATE_CHANGE_MINOR_VERSION; + state_change->new_state = new_state; + state_change->old_state = old_state; + state_change->state_interface = strdup(interface); + dlist_initialize(&state_change->additional_fields); + +exit_label: + EVEL_EXIT(); + return state_change; +} + +/**************************************************************************//** + * Free a State Change. + * + * Free off the State Change supplied. Will free all the contained allocated + * memory. + * + * @note It does not free the State Change itself, since that may be part of a + * larger structure. + *****************************************************************************/ +void evel_free_state_change(EVENT_STATE_CHANGE * const state_change) +{ + STATE_CHANGE_ADDL_FIELD * addl_field = NULL; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. As an internal API we don't allow freeing NULL */ + /* events as we do on the public API. */ + /***************************************************************************/ + assert(state_change != NULL); + assert(state_change->header.event_domain == EVEL_DOMAIN_STATE_CHANGE); + + /***************************************************************************/ + /* Free all internal strings then the header itself. */ + /***************************************************************************/ + addl_field = dlist_pop_last(&state_change->additional_fields); + while (addl_field != NULL) + { + EVEL_DEBUG("Freeing Additional Field (%s, %s)", + addl_field->name, + addl_field->value); + free(addl_field->name); + free(addl_field->value); + free(addl_field); + addl_field = dlist_pop_last(&state_change->additional_fields); + } + free(state_change->state_interface); + evel_free_header(&state_change->header); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Event Type property of the State Change. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param state_change Pointer to the ::EVENT_STATE_CHANGE. + * @param type The Event Type to be set. ASCIIZ string. The caller + * does not need to preserve the value once the function + * returns. + *****************************************************************************/ +void evel_state_change_type_set(EVENT_STATE_CHANGE * const state_change, + const char * const type) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions and call evel_header_type_set. */ + /***************************************************************************/ + assert(state_change != NULL); + assert(state_change->header.event_domain == EVEL_DOMAIN_STATE_CHANGE); + evel_header_type_set(&state_change->header, type); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Add an additional field name/value pair to the State Change. + * + * The name and value are null delimited ASCII strings. The library takes + * a copy so the caller does not have to preserve values after the function + * returns. + * + * @param state_change Pointer to the ::EVENT_STATE_CHANGE. + * @param name ASCIIZ string with the attribute's name. The caller + * does not need to preserve the value once the function + * returns. + * @param value ASCIIZ string with the attribute's value. The caller + * does not need to preserve the value once the function + * returns. + *****************************************************************************/ +void evel_state_change_addl_field_add(EVENT_STATE_CHANGE * const state_change, + const char * const name, + const char * const value) +{ + STATE_CHANGE_ADDL_FIELD * addl_field = NULL; + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(state_change != NULL); + assert(state_change->header.event_domain == EVEL_DOMAIN_STATE_CHANGE); + assert(name != NULL); + assert(value != NULL); + + EVEL_DEBUG("Adding name=%s value=%s", name, value); + addl_field = malloc(sizeof(STATE_CHANGE_ADDL_FIELD)); + assert(addl_field != NULL); + memset(addl_field, 0, sizeof(STATE_CHANGE_ADDL_FIELD)); + addl_field->name = strdup(name); + addl_field->value = strdup(value); + assert(addl_field->name != NULL); + assert(addl_field->value != NULL); + + dlist_push_last(&state_change->additional_fields, addl_field); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Encode the state change as a JSON state change. + * + * @param jbuf Pointer to the ::EVEL_JSON_BUFFER to encode into. + * @param state_change Pointer to the ::EVENT_STATE_CHANGE to encode. + *****************************************************************************/ +void evel_json_encode_state_change(EVEL_JSON_BUFFER * jbuf, + EVENT_STATE_CHANGE * state_change) +{ + STATE_CHANGE_ADDL_FIELD * addl_field = NULL; + DLIST_ITEM * addl_field_item = NULL; + char * new_state; + char * old_state; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(state_change != NULL); + assert(state_change->header.event_domain == EVEL_DOMAIN_STATE_CHANGE); + + new_state = evel_entity_state(state_change->new_state); + old_state = evel_entity_state(state_change->old_state); + + evel_json_encode_header(jbuf, &state_change->header); + evel_json_open_named_object(jbuf, "stateChangeFields"); + + /***************************************************************************/ + /* Mandatory fields. */ + /***************************************************************************/ + evel_enc_kv_string(jbuf, "newState", new_state); + evel_enc_kv_string(jbuf, "oldState", old_state); + evel_enc_kv_string(jbuf, "stateInterface", state_change->state_interface); + + /***************************************************************************/ + /* Optional fields. */ + /***************************************************************************/ + evel_json_checkpoint(jbuf); + if (evel_json_open_opt_named_list(jbuf, "additionalFields")) + { + bool item_added = false; + + addl_field_item = dlist_get_first(&state_change->additional_fields); + while (addl_field_item != NULL) + { + addl_field = (STATE_CHANGE_ADDL_FIELD *) addl_field_item->item; + assert(addl_field != NULL); + + if (!evel_throttle_suppress_nv_pair(jbuf->throttle_spec, + "additionalFields", + addl_field->name)) + { + evel_json_open_object(jbuf); + evel_enc_kv_string(jbuf, "name", addl_field->name); + evel_enc_kv_string(jbuf, "value", addl_field->value); + evel_json_close_object(jbuf); + item_added = true; + } + addl_field_item = dlist_get_next(addl_field_item); + } + evel_json_close_list(jbuf); + + /*************************************************************************/ + /* If we've not written anything, rewind to before we opened the list. */ + /*************************************************************************/ + if (!item_added) + { + evel_json_rewind(jbuf); + } + } + + evel_enc_version(jbuf, + "stateChangeFieldsVersion", + state_change->major_version,state_change->minor_version); + + evel_json_close_object(jbuf); + + EVEL_EXIT(); +} diff --git a/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_strings.c b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_strings.c new file mode 100644 index 0000000..96db59b --- /dev/null +++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_strings.c @@ -0,0 +1,473 @@ +/*************************************************************************//** + * + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************/ +/**************************************************************************//** + * @file + * Implementation of EVEL functions to convert common enum types to strings. + * + ****************************************************************************/ + +#include +#include +#include + +#include "evel_internal.h" + +/**************************************************************************//** + * Map an ::EVEL_COUNTER_CRITICALITIES enum value to the equivalent string. + * + * @param criticality The criticality to convert. + * @returns The equivalent string. + *****************************************************************************/ +char * evel_criticality(const EVEL_COUNTER_CRITICALITIES criticality) +{ + char * result; + + EVEL_ENTER(); + + switch (criticality) + { + case EVEL_COUNTER_CRITICALITY_CRIT: + result = "CRIT"; + break; + + case EVEL_COUNTER_CRITICALITY_MAJ: + result = "MAJ"; + break; + + default: + EVEL_ERROR("Unexpected counter criticality %d", criticality); + assert(0); + } + + EVEL_EXIT(); + + return result; +} + +/**************************************************************************//** + * Map an ::EVEL_SEVERITIES enum value to the equivalent string. + * + * @param severity The severity to convert. + * @returns The equivalent string. + *****************************************************************************/ +char * evel_severity(const EVEL_SEVERITIES severity) +{ + char * result; + + EVEL_ENTER(); + + switch (severity) + { + case EVEL_SEVERITY_CRITICAL: + result = "CRITICAL"; + break; + + case EVEL_SEVERITY_MAJOR: + result = "MAJOR"; + break; + + case EVEL_SEVERITY_MINOR: + result = "MINOR"; + break; + + case EVEL_SEVERITY_WARNING: + result = "WARNING"; + break; + + case EVEL_SEVERITY_NORMAL: + result = "NORMAL"; + break; + + default: + EVEL_ERROR("Unexpected event severity %d", severity); + assert(0); + } + + EVEL_EXIT(); + + return result; +} + +/**************************************************************************//** + * Map an ::EVEL_ALERT_ACTIONS enum value to the equivalent string. + * + * @param alert_action The alert_action to convert. + * @returns The equivalent string. + *****************************************************************************/ +char * evel_alert_action(const EVEL_ALERT_ACTIONS alert_action) +{ + char * result; + + EVEL_ENTER(); + + switch (alert_action) + { + case EVEL_ALERT_ACTION_CLEAR: + result = "CLEAR"; + break; + + case EVEL_ALERT_ACTION_CONT: + result = "CONT"; + break; + + case EVEL_ALERT_ACTION_SET: + result = "SET"; + break; + + default: + EVEL_ERROR("Unexpected alert action %d", alert_action); + assert(0); + } + + EVEL_EXIT(); + + return result; +} + +/**************************************************************************//** + * Map an ::EVEL_ALERT_TYPES enum value to the equivalent string. + * + * @param alert_type The alert_type to convert. + * @returns The equivalent string. + *****************************************************************************/ +char * evel_alert_type(const EVEL_ALERT_TYPES alert_type) +{ + char * result; + + EVEL_ENTER(); + + switch (alert_type) + { + case EVEL_ALERT_TYPE_CARD: + result = "CARD-ANOMALY"; + break; + + case EVEL_ALERT_TYPE_ELEMENT: + result = "ELEMENT-ANOMALY"; + break; + + case EVEL_ALERT_TYPE_INTERFACE: + result = "INTERFACE-ANOMALY"; + break; + + case EVEL_ALERT_TYPE_SERVICE: + result = "SERVICE-ANOMALY"; + break; + + default: + EVEL_ERROR("Unexpected alert type %d", alert_type); + assert(0); + } + + EVEL_EXIT(); + + return result; +} + +/**************************************************************************//** + * Map an ::EVEL_EVENT_DOMAINS enum value to the equivalent string. + * + * @param domain The domain to convert. + * @returns The equivalent string. + *****************************************************************************/ +char * evel_event_domain(const EVEL_EVENT_DOMAINS domain) +{ + char * result; + + EVEL_ENTER(); + + switch (domain) + { + case EVEL_DOMAIN_HEARTBEAT: + result = "heartbeat"; + break; + + case EVEL_DOMAIN_FAULT: + result = "fault"; + break; + + case EVEL_DOMAIN_MEASUREMENT: + result = "measurementsForVfScaling"; + break; + + case EVEL_DOMAIN_REPORT: + result = "measurementsForVfReporting"; + break; + + case EVEL_DOMAIN_MOBILE_FLOW: + result = "mobileFlow"; + break; + + case EVEL_DOMAIN_HEARTBEAT_FIELD: + result = "heartbeat"; + break; + + case EVEL_DOMAIN_SIPSIGNALING: + result = "sipSignaling"; + break; + + case EVEL_DOMAIN_STATE_CHANGE: + result = "stateChange"; + break; + + case EVEL_DOMAIN_SYSLOG: + result = "syslog"; + break; + + case EVEL_DOMAIN_OTHER: + result = "other"; + break; + + case EVEL_DOMAIN_VOICE_QUALITY: + result = "voiceQuality"; + break; + + case EVEL_DOMAIN_THRESHOLD_CROSS: + result = "thresholdCrossingAlert"; + break; + + default: + result = NULL; + EVEL_ERROR("Unexpected domain %d", domain); + assert(0); + } + + EVEL_EXIT(); + + return result; +} + +/**************************************************************************//** + * Map an ::EVEL_EVENT_PRIORITIES enum value to the equivalent string. + * + * @param priority The priority to convert. + * @returns The equivalent string. + *****************************************************************************/ +char * evel_event_priority(const EVEL_EVENT_PRIORITIES priority) +{ + char * result; + + EVEL_ENTER(); + + switch (priority) + { + case EVEL_PRIORITY_HIGH: + result = "High"; + break; + + case EVEL_PRIORITY_MEDIUM: + result = "Medium"; + break; + + case EVEL_PRIORITY_NORMAL: + result = "Normal"; + break; + + case EVEL_PRIORITY_LOW: + result = "Low"; + break; + + default: + result = NULL; + EVEL_ERROR("Unexpected priority %d", priority); + assert(0); + } + + EVEL_EXIT(); + + return result; +} + +/**************************************************************************//** + * Map an ::EVEL_SOURCE_TYPES enum value to the equivalent string. + * + * @param source_type The source type to convert. + * @returns The equivalent string. + *****************************************************************************/ +char * evel_source_type(const EVEL_SOURCE_TYPES source_type) +{ + char * result; + + EVEL_ENTER(); + + switch (source_type) + { + case EVEL_SOURCE_OTHER: + result = "other"; + break; + + case EVEL_SOURCE_ROUTER: + result = "router"; + break; + + case EVEL_SOURCE_SWITCH: + result = "switch"; + break; + + case EVEL_SOURCE_HOST: + result = "host"; + break; + + case EVEL_SOURCE_CARD: + result = "card"; + break; + + case EVEL_SOURCE_PORT: + result = "port"; + break; + + case EVEL_SOURCE_SLOT_THRESHOLD: + result = "slotThreshold"; + break; + + case EVEL_SOURCE_PORT_THRESHOLD: + result = "portThreshold"; + break; + + case EVEL_SOURCE_VIRTUAL_MACHINE: + result = "virtualMachine"; + break; + + case EVEL_SOURCE_VIRTUAL_NETWORK_FUNCTION: + result = "virtualNetworkFunction"; + break; + + default: + result = NULL; + EVEL_ERROR("Unexpected Event Source Type %d", (int) source_type); + assert(0); + } + + EVEL_EXIT(); + + return result; +} + +/**************************************************************************//** + * Map an ::EVEL_VF_STATUSES enum value to the equivalent string. + * + * @param vf_status The vf_status to convert. + * @returns The equivalent string. + *****************************************************************************/ +char * evel_vf_status(const EVEL_VF_STATUSES vf_status) +{ + char * result; + + EVEL_ENTER(); + + switch (vf_status) + { + case EVEL_VF_STATUS_ACTIVE: + result = "Active"; + break; + + case EVEL_VF_STATUS_IDLE: + result = "Idle"; + break; + + case EVEL_VF_STATUS_PREP_TERMINATE: + result = "Preparing to terminate"; + break; + + case EVEL_VF_STATUS_READY_TERMINATE: + result = "Ready to terminate"; + break; + + case EVEL_VF_STATUS_REQ_TERMINATE: + result = "Requesting termination"; + break; + + default: + result = NULL; + EVEL_ERROR("Unexpected VF Status %d", vf_status); + assert(0); + } + + EVEL_EXIT(); + + return result; +} + +/**************************************************************************//** + * Convert a ::EVEL_ENTITY_STATE to it's string form for JSON encoding. + * + * @param state The entity state to encode. + * + * @returns the corresponding string + *****************************************************************************/ +char * evel_entity_state(const EVEL_ENTITY_STATE state) +{ + char * result; + + EVEL_ENTER(); + + switch (state) + { + case EVEL_ENTITY_STATE_IN_SERVICE: + result = "inService"; + break; + + case EVEL_ENTITY_STATE_MAINTENANCE: + result = "maintenance"; + break; + + case EVEL_ENTITY_STATE_OUT_OF_SERVICE: + result = "outOfService"; + break; + + default: + EVEL_ERROR("Unexpected entity state %d", state); + assert(0); + } + + EVEL_EXIT(); + + return result; +} + +/**************************************************************************//** + * Convert a ::EVEL_SERVICE_ENDPOINT_DESC to string form for JSON encoding. + * + * @param endpoint_desc endpoint description to encode. + * + * @returns the corresponding string + *****************************************************************************/ +char * evel_service_endpoint_desc(const EVEL_ENTITY_STATE endpoint_desc) +{ + char * result; + + EVEL_ENTER(); + + switch (endpoint_desc) + { + case EVEL_SERVICE_ENDPOINT_CALLEE: + result = "Callee"; + break; + + case EVEL_SERVICE_ENDPOINT_CALLER: + result = "Caller"; + break; + + default: + EVEL_ERROR("Unexpected endpoint description %d", endpoint_desc); + assert(0); + } + + EVEL_EXIT(); + + return result; +} diff --git a/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_syslog.c b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_syslog.c new file mode 100644 index 0000000..85b0ec9 --- /dev/null +++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_syslog.c @@ -0,0 +1,505 @@ +/*************************************************************************//** + * + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************/ +/**************************************************************************//** + * @file + * Implementation of EVEL functions relating to the Syslog. + * + ****************************************************************************/ + +#include +#include +#include + +#include "evel_throttle.h" + +/**************************************************************************//** + * Create a new Syslog event. + * + * @note The mandatory fields on the Syslog must be supplied to this factory + * function and are immutable once set. Optional fields have explicit + * setter functions, but again values may only be set once so that the + * Syslog has immutable properties. + * @param event_name Unique Event Name confirming Domain AsdcModel Description + * @param event_id A universal identifier of the event for: troubleshooting correlation, analysis, etc + * @param event_source_type The type of Syslog event source. + * @param syslog_msg The Syslog event message. + * @param syslog_tag The messgaeId identifying the type of message. + * @returns pointer to the newly manufactured ::EVENT_SYSLOG. If the event is + * not used (i.e. posted) it must be released using + * ::evel_free_syslog. + * @retval NULL Failed to create the event. + *****************************************************************************/ +EVENT_SYSLOG * evel_new_syslog(const char* ev_name, const char *ev_id, + EVEL_SOURCE_TYPES event_source_type, + const char * const syslog_msg, + const char * const syslog_tag) +{ + EVENT_SYSLOG * syslog = NULL; + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(event_source_type < EVEL_MAX_SOURCE_TYPES); + assert(syslog_msg != NULL); + assert(syslog_tag != NULL); + + /***************************************************************************/ + /* Allocate the Syslog. */ + /***************************************************************************/ + syslog = malloc(sizeof(EVENT_SYSLOG)); + if (syslog == NULL) + { + log_error_state("Out of memory"); + goto exit_label; + } + memset(syslog, 0, sizeof(EVENT_SYSLOG)); + EVEL_DEBUG("New Syslog is at %lp", syslog); + + /***************************************************************************/ + /* Initialize the header & the Syslog fields. Optional string values are */ + /* uninitialized (NULL). */ + /***************************************************************************/ + evel_init_header_nameid(&syslog->header,ev_name,ev_id); + syslog->header.event_domain = EVEL_DOMAIN_SYSLOG; + syslog->major_version = EVEL_SYSLOG_MAJOR_VERSION; + syslog->minor_version = EVEL_SYSLOG_MINOR_VERSION; + syslog->event_source_type = event_source_type; + syslog->syslog_msg = strdup(syslog_msg); + syslog->syslog_tag = strdup(syslog_tag); + evel_init_option_int(&syslog->syslog_facility); + evel_init_option_int(&syslog->syslog_proc_id); + evel_init_option_int(&syslog->syslog_ver); + evel_init_option_string(&syslog->additional_filters); + evel_init_option_string(&syslog->event_source_host); + evel_init_option_string(&syslog->syslog_proc); + evel_init_option_string(&syslog->syslog_s_data); + evel_init_option_string(&syslog->syslog_sdid); + evel_init_option_string(&syslog->syslog_severity); + +exit_label: + EVEL_EXIT(); + return syslog; +} + +/**************************************************************************//** + * Set the Event Type property of the Syslog. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param syslog Pointer to the syslog. + * @param type The Event Type to be set. ASCIIZ string. The caller + * does not need to preserve the value once the function + * returns. + *****************************************************************************/ +void evel_syslog_type_set(EVENT_SYSLOG * syslog, + const char * const type) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions and call evel_header_type_set. */ + /***************************************************************************/ + assert(syslog != NULL); + assert(syslog->header.event_domain == EVEL_DOMAIN_SYSLOG); + evel_header_type_set(&syslog->header, type); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Add an additional value name/value pair to the Syslog. + * + * The name and value are null delimited ASCII strings. The library takes + * a copy so the caller does not have to preserve values after the function + * returns. + * + * @param syslog Pointer to the syslog. + * @param name ASCIIZ string with the attribute's name. The caller + * does not need to preserve the value once the function + * returns. + * @param value ASCIIZ string with the attribute's value. The caller + * does not need to preserve the value once the function + * returns. + *****************************************************************************/ +void evel_syslog_addl_filter_set(EVENT_SYSLOG * syslog, + char * filter) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(syslog != NULL); + assert(syslog->header.event_domain == EVEL_DOMAIN_SYSLOG); + assert(filter != NULL); + + evel_set_option_string(&syslog->additional_filters, + filter, + "Syslog filter string"); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Event Source Host property of the Syslog. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param syslog Pointer to the Syslog. + * @param host The Event Source Host to be set. ASCIIZ string. The caller + * does not need to preserve the value once the function + * returns. + *****************************************************************************/ +void evel_syslog_event_source_host_set(EVENT_SYSLOG * syslog, + const char * const host) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(syslog != NULL); + assert(syslog->header.event_domain == EVEL_DOMAIN_SYSLOG); + assert(host != NULL); + + evel_set_option_string(&syslog->event_source_host, + host, + "Event Source Host"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Facility property of the Syslog. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param syslog Pointer to the Syslog. + * @param facility The Syslog Facility to be set. ASCIIZ string. The caller + * does not need to preserve the value once the function + * returns. + *****************************************************************************/ +void evel_syslog_facility_set(EVENT_SYSLOG * syslog, + EVEL_SYSLOG_FACILITIES facility) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(syslog != NULL); + assert(syslog->header.event_domain == EVEL_DOMAIN_SYSLOG); + assert(facility < EVEL_MAX_SYSLOG_FACILITIES); + + evel_set_option_int(&syslog->syslog_facility, + facility, + "Facility"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Process property of the Syslog. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param syslog Pointer to the Syslog. + * @param proc The Process to be set. ASCIIZ string. The caller does not + * need to preserve the value once the function returns. + *****************************************************************************/ +void evel_syslog_proc_set(EVENT_SYSLOG * syslog, const char * const proc) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(syslog != NULL); + assert(syslog->header.event_domain == EVEL_DOMAIN_SYSLOG); + assert(proc != NULL); + + evel_set_option_string(&syslog->syslog_proc, proc, "Process"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Process ID property of the Syslog. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param syslog Pointer to the Syslog. + * @param proc_id The Process ID to be set. ASCIIZ string. The caller does + * not need to preserve the value once the function returns. + *****************************************************************************/ +void evel_syslog_proc_id_set(EVENT_SYSLOG * syslog, int proc_id) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(syslog != NULL); + assert(syslog->header.event_domain == EVEL_DOMAIN_SYSLOG); + assert(proc_id > 0); + + evel_set_option_int(&syslog->syslog_proc_id, + proc_id, + "Process ID"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Version property of the Syslog. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param syslog Pointer to the Syslog. + * @param version The Version to be set. ASCIIZ string. The caller does not + * need to preserve the value once the function returns. + *****************************************************************************/ +void evel_syslog_version_set(EVENT_SYSLOG * syslog, int version) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(syslog != NULL); + assert(syslog->header.event_domain == EVEL_DOMAIN_SYSLOG); + assert(version >= 0); + + evel_set_option_int(&syslog->syslog_ver, + version, + "Version"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Structured Data property of the Syslog. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param syslog Pointer to the Syslog. + * @param s_data The Structured Data to be set. ASCIIZ string. The caller + * does not need to preserve the value once the function + * returns. + *****************************************************************************/ +void evel_syslog_s_data_set(EVENT_SYSLOG * syslog, const char * const s_data) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(syslog != NULL); + assert(syslog->header.event_domain == EVEL_DOMAIN_SYSLOG); + assert(s_data != NULL); + + evel_set_option_string(&syslog->syslog_s_data, + s_data, + "Structured Data"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Structured SDID property of the Syslog. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param syslog Pointer to the Syslog. + * @param sdid The Structured Data to be set. ASCIIZ string. name@number + * Caller does not need to preserve the value once the function + * returns. + *****************************************************************************/ +void evel_syslog_sdid_set(EVENT_SYSLOG * syslog, const char * const sdid) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(syslog != NULL); + assert(syslog->header.event_domain == EVEL_DOMAIN_SYSLOG); + assert(sdid != NULL); + + evel_set_option_string(&syslog->syslog_sdid, + sdid, + "SdId set"); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Structured Severity property of the Syslog. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param syslog Pointer to the Syslog. + * @param sdid The Structured Data to be set. ASCIIZ string. + * Caller does not need to preserve the value once the function + * returns. + *****************************************************************************/ +void evel_syslog_severity_set(EVENT_SYSLOG * syslog, const char * const severty) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(syslog != NULL); + assert(syslog->header.event_domain == EVEL_DOMAIN_SYSLOG); + assert(severty != NULL); + + if( !strcmp(severty,"Alert") || !strcmp(severty,"Critical") || !strcmp(severty,"Debug") || + !strcmp(severty,"Emergency") || !strcmp(severty,"Error") || !strcmp(severty,"Info") || + !strcmp(severty,"Notice") || !strcmp(severty,"Warning") ) + { + evel_set_option_string(&syslog->syslog_severity, + severty, + "Severity set"); + } + EVEL_EXIT(); +} + +/**************************************************************************//** + * Encode the Syslog in JSON according to AT&T's schema for the event type. + * + * @param jbuf Pointer to the ::EVEL_JSON_BUFFER to encode into. + * @param event Pointer to the ::EVENT_HEADER to encode. + *****************************************************************************/ +void evel_json_encode_syslog(EVEL_JSON_BUFFER * jbuf, + EVENT_SYSLOG * event) +{ + char * event_source_type; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(event != NULL); + assert(event->header.event_domain == EVEL_DOMAIN_SYSLOG); + + event_source_type = evel_source_type(event->event_source_type); + + evel_json_encode_header(jbuf, &event->header); + evel_json_open_named_object(jbuf, "syslogFields"); + + evel_enc_kv_opt_string(jbuf, "additionalFields", &event->additional_filters); + /***************************************************************************/ + /* Mandatory fields */ + /***************************************************************************/ + evel_enc_kv_string(jbuf, "eventSourceType", event_source_type); + evel_enc_kv_string(jbuf, "syslogMsg", event->syslog_msg); + evel_enc_kv_string(jbuf, "syslogTag", event->syslog_tag); + evel_enc_version( + jbuf, "syslogFieldsVersion", event->major_version, event->minor_version); + + /***************************************************************************/ + /* Optional fields */ + /***************************************************************************/ + evel_enc_kv_opt_string(jbuf, "eventSourceHost", &event->event_source_host); + evel_enc_kv_opt_int(jbuf, "syslogFacility", &event->syslog_facility); + evel_enc_kv_opt_int(jbuf, "syslogPri", &event->syslog_priority); + evel_enc_kv_opt_string(jbuf, "syslogProc", &event->syslog_proc); + evel_enc_kv_opt_int(jbuf, "syslogProcId", &event->syslog_proc_id); + evel_enc_kv_opt_string(jbuf, "syslogSData", &event->syslog_s_data); + evel_enc_kv_opt_string(jbuf, "syslogSdId", &event->syslog_sdid); + evel_enc_kv_opt_string(jbuf, "syslogSev", &event->syslog_severity); + evel_enc_kv_opt_int(jbuf, "syslogVer", &event->syslog_ver); + evel_json_close_object(jbuf); + + EVEL_CT_ASSERT(EVEL_SYSLOG_FACILITY_KERNEL == 0); + EVEL_CT_ASSERT(EVEL_SYSLOG_FACILITY_USER == 1); + EVEL_CT_ASSERT(EVEL_SYSLOG_FACILITY_MAIL == 2); + EVEL_CT_ASSERT(EVEL_SYSLOG_FACILITY_SYSTEM_DAEMON == 3); + EVEL_CT_ASSERT(EVEL_SYSLOG_FACILITY_SECURITY_AUTH == 4); + EVEL_CT_ASSERT(EVEL_SYSLOG_FACILITY_INTERNAL == 5); + EVEL_CT_ASSERT(EVEL_SYSLOG_FACILITY_LINE_PRINTER == 6); + EVEL_CT_ASSERT(EVEL_SYSLOG_FACILITY_NETWORK_NEWS == 7); + EVEL_CT_ASSERT(EVEL_SYSLOG_FACILITY_UUCP == 8); + EVEL_CT_ASSERT(EVEL_SYSLOG_FACILITY_CLOCK_DAEMON == 9); + EVEL_CT_ASSERT(EVEL_SYSLOG_FACILITY_SECURITY_AUTH2 == 10); + EVEL_CT_ASSERT(EVEL_SYSLOG_FACILITY_FTP_DAEMON == 11); + EVEL_CT_ASSERT(EVEL_SYSLOG_FACILITY_NTP == 12); + EVEL_CT_ASSERT(EVEL_SYSLOG_FACILITY_LOG_AUDIT == 13); + EVEL_CT_ASSERT(EVEL_SYSLOG_FACILITY_LOG_ALERT == 14); + EVEL_CT_ASSERT(EVEL_SYSLOG_FACILITY_CLOCK_DAEMON2 == 15); + EVEL_CT_ASSERT(EVEL_SYSLOG_FACILITY_LOCAL0 == 16); + EVEL_CT_ASSERT(EVEL_SYSLOG_FACILITY_LOCAL1 == 17); + EVEL_CT_ASSERT(EVEL_SYSLOG_FACILITY_LOCAL2 == 18); + EVEL_CT_ASSERT(EVEL_SYSLOG_FACILITY_LOCAL3 == 19); + EVEL_CT_ASSERT(EVEL_SYSLOG_FACILITY_LOCAL4 == 20); + EVEL_CT_ASSERT(EVEL_SYSLOG_FACILITY_LOCAL5 == 21); + EVEL_CT_ASSERT(EVEL_SYSLOG_FACILITY_LOCAL6 == 22); + EVEL_CT_ASSERT(EVEL_SYSLOG_FACILITY_LOCAL7 == 23); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Free a Syslog. + * + * Free off the Syslog supplied. Will free all the contained allocated memory. + * + * @note It does not free the Syslog itself, since that may be part of a + * larger structure. + *****************************************************************************/ +void evel_free_syslog(EVENT_SYSLOG * event) +{ + + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. As an internal API we don't allow freeing NULL */ + /* events as we do on the public API. */ + /***************************************************************************/ + assert(event != NULL); + assert(event->header.event_domain == EVEL_DOMAIN_SYSLOG); + + /***************************************************************************/ + /* Free all internal strings then the header itself. */ + /***************************************************************************/ + + evel_free_option_string(&event->additional_filters); + evel_free_option_string(&event->event_source_host); + free(event->syslog_msg); + evel_free_option_string(&event->syslog_proc); + evel_free_option_string(&event->syslog_s_data); + evel_free_option_string(&event->syslog_sdid); + evel_free_option_string(&event->syslog_severity); + free(event->syslog_tag); + evel_free_header(&event->header); + + EVEL_EXIT(); +} diff --git a/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_threshold_cross.c b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_threshold_cross.c new file mode 100644 index 0000000..f4fa620 --- /dev/null +++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_threshold_cross.c @@ -0,0 +1,531 @@ +/*************************************************************************//** + * + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************/ +/**************************************************************************//** + * @file + * Implementation of EVEL functions relating to the Threshold Cross Alerts. + * + *****************************************************************************/ +#include +#include +#include +#include "evel.h" +#include "evel_internal.h" +#include "evel_throttle.h" + + +/**************************************************************************//** + * Create a new Threshold Crossing Alert event. + * + * @note The mandatory fields on the TCA must be supplied to this factory + * function and are immutable once set. Optional fields have explicit + * setter functions, but again values may only be set once so that the + * TCA has immutable properties. + * + * @param event_name Unique Event Name confirming Domain AsdcVnfModel Description + * @param event_id A universal identifier of the event for: troubleshooting correlation, analysis, etc + * @param char* tcriticality Performance Counter Criticality MAJ MIN, + * @param char* tname Performance Counter Threshold name + * @param char* tthresholdCrossed Counter Threshold crossed value + * @param char* tvalue Counter actual value + * @param EVEL_EVENT_ACTION talertAction Alert set continue or clear + * @param char* talertDescription + * @param EVEL_ALERT_TYPE talertType Kind of anamoly + * @param unsigned long long tcollectionTimestamp time at which alert was collected + * @param EVEL_SEVERITIES teventSeverity Severity of Alert + * @param unsigned long long teventStartTimestamp Time when this alert started + * + * @returns pointer to the newly manufactured ::EVENT_THRESHOLD_CROSS. If the + * event is not used it must be released using + * ::evel_free_threshold_cross + * @retval NULL Failed to create the event. + *****************************************************************************/ +EVENT_THRESHOLD_CROSS * evel_new_threshold_cross(const char * ev_name, const char * ev_id, + char * tcriticality, + char * tname, + char * tthresholdCrossed, + char * tvalue, + EVEL_EVENT_ACTION talertAction, + char * talertDescription, + EVEL_ALERT_TYPE talertType, + unsigned long long tcollectionTimestamp, + EVEL_SEVERITIES teventSeverity, + unsigned long long teventStartTimestamp ) +{ + EVENT_THRESHOLD_CROSS * event = NULL; + EVEL_ENTER(); + + assert( tcriticality!= NULL ); + assert( tname!= NULL ); + assert( tthresholdCrossed != NULL ); + assert( tvalue!= NULL ); + assert( talertDescription != NULL ); + + + /***************************************************************************/ + /* Allocate the Threshold crossing event. */ + /***************************************************************************/ + event = malloc(sizeof(EVENT_THRESHOLD_CROSS)); + if (event == NULL) + { + log_error_state("Out of memory"); + goto exit_label; + } + memset(event, 0, sizeof(EVENT_THRESHOLD_CROSS)); + EVEL_DEBUG("New Threshold Cross event is at %lp", event); + + /***************************************************************************/ + /* Initialize the header & the threshold crossing fields. */ + /***************************************************************************/ + evel_init_header_nameid(&event->header,ev_name,ev_id); + event->header.event_domain = EVEL_DOMAIN_THRESHOLD_CROSS; + event->major_version = EVEL_THRESHOLD_CROSS_MAJOR_VERSION; + event->minor_version = EVEL_THRESHOLD_CROSS_MINOR_VERSION; + + + event->additionalParameters.criticality = strdup(tcriticality); + event->additionalParameters.name = strdup(tname); + event->additionalParameters.thresholdCrossed = strdup(tthresholdCrossed); + event->additionalParameters.value = strdup(tvalue); + event->alertAction = talertAction; + event->alertDescription = strdup(talertDescription); + event->alertType = talertType; + event->collectionTimestamp = tcollectionTimestamp; + event->eventSeverity = teventSeverity; + event->eventStartTimestamp = teventStartTimestamp; + + evel_init_option_string(&event->alertValue); + evel_init_option_string(&event->dataCollector); + evel_init_option_string(&event->elementType); + evel_init_option_string(&event->interfaceName); + evel_init_option_string(&event->networkService); + evel_init_option_string(&event->possibleRootCause); + dlist_initialize(&event->additional_info); + dlist_initialize(&event->alertidList); + +exit_label: + + EVEL_EXIT(); + return event; + +} + + +/**************************************************************************//** + * Set the Event Type property of the TC Alert. + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param type The Event Type to be set. ASCIIZ string. The caller + * does not need to preserve the value once the function + * returns. + *****************************************************************************/ +void evel_threshold_cross_type_set(EVENT_THRESHOLD_CROSS * const event,char * type) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions and call evel_header_type_set. */ + /***************************************************************************/ + assert(type!=NULL); + assert(event->header.event_domain == EVEL_DOMAIN_THRESHOLD_CROSS); + evel_header_type_set(&event->header, type); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Add an optional additional alertid value to Alert. + * + *****************************************************************************/ +void evel_threshold_cross_alertid_add(EVENT_THRESHOLD_CROSS * const event,char * alertid) +{ + char *alid=NULL; + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(event != NULL); + assert(event->header.event_domain == EVEL_DOMAIN_THRESHOLD_CROSS); + assert(alertid != NULL); + + EVEL_DEBUG("Adding AlertId=%s", alertid); + alid = strdup(alertid); + assert(alid != NULL); + + dlist_push_last(&event->alertidList, alid); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Add an optional additional value name/value pair to the Alert. + * + * The name and value are NULL delimited ASCII strings. The library takes + * a copy so the caller does not have to preserve values after the function + * returns. + * @param name ASCIIZ string with the attribute's name. The caller + * does not need to preserve the value once the function + * returns. + * @param value ASCIIZ string with the attribute's value. The caller + * does not need to preserve the value once the function + * returns. + *****************************************************************************/ +void evel_threshold_cross_addl_info_add(EVENT_THRESHOLD_CROSS * const event, const char * name, const char * value) +{ + OTHER_FIELD * nv_pair = NULL; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(event != NULL); + assert(event->header.event_domain == EVEL_DOMAIN_THRESHOLD_CROSS); + assert(name != NULL); + assert(value != NULL); + + EVEL_DEBUG("Adding name=%s value=%s", name, value); + nv_pair = malloc(sizeof(OTHER_FIELD)); + assert(nv_pair != NULL); + nv_pair->name = strdup(name); + nv_pair->value = strdup(value); + assert(nv_pair->name != NULL); + assert(nv_pair->value != NULL); + + dlist_push_last(&event->additional_info, nv_pair); + + EVEL_EXIT(); +} + + +/**************************************************************************//** + * Free a Signaling event. + * + * Free off the event supplied. Will free all the contained allocated memory. + * + * @note It does not free the event itself, since that may be part of a larger + * structure. + *****************************************************************************/ +void evel_free_threshold_cross(EVENT_THRESHOLD_CROSS * const event) +{ + OTHER_FIELD * addl_info = NULL; + char *ptr; + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. As an internal API we don't allow freeing NULL */ + /* events as we do on the API. */ + /***************************************************************************/ + assert(event != NULL); + assert(event->header.event_domain == EVEL_DOMAIN_THRESHOLD_CROSS); + + /***************************************************************************/ + /* Free all internal strings then the header itself. */ + /***************************************************************************/ + addl_info = dlist_pop_last(&event->additional_info); + while (addl_info != NULL) + { + EVEL_DEBUG("Freeing Additional Info (%s, %s)", + addl_info->name, + addl_info->value); + free(addl_info->name); + free(addl_info->value); + free(addl_info); + addl_info = dlist_pop_last(&event->additional_info); + } + ptr = dlist_pop_last(&event->alertidList); + while (ptr != NULL) + { + free(ptr); + ptr = dlist_pop_last(&event->alertidList); + } + + free(event->additionalParameters.criticality); + free(event->additionalParameters.name); + free(event->additionalParameters.thresholdCrossed); + free(event->additionalParameters.value); + free(event->alertDescription); + + evel_free_option_string(&event->alertValue); + evel_free_option_string(&event->dataCollector); + evel_free_option_string(&event->elementType); + evel_free_option_string(&event->interfaceName); + evel_free_option_string(&event->networkService); + evel_free_option_string(&event->possibleRootCause); + evel_free_header(&event->header); + + EVEL_EXIT(); +} + + /**************************************************************************//** + * Set the TCA probable Root cause. + * + * @param sheader Possible root cause to Threshold + *****************************************************************************/ + void evel_threshold_cross_possible_rootcause_set(EVENT_THRESHOLD_CROSS * const event, char * sheader) + { + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(event->header.event_domain == EVEL_DOMAIN_THRESHOLD_CROSS); + assert(sheader != NULL); + + evel_set_option_string(&event->possibleRootCause, + sheader, + "Rootcause value"); + + EVEL_EXIT(); + } + + /**************************************************************************//** + * Set the TCA networking cause. + * + * @param sheader Possible networking service value to Threshold + *****************************************************************************/ + void evel_threshold_cross_networkservice_set(EVENT_THRESHOLD_CROSS * const event, char * sheader) + { + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(event->header.event_domain == EVEL_DOMAIN_THRESHOLD_CROSS); + assert(sheader != NULL); + + evel_set_option_string(&event->networkService, + sheader, + "Networking service value"); + + EVEL_EXIT(); + } + + /**************************************************************************//** + * Set the TCA Interface name. + * + * @param sheader Interface name to threshold + *****************************************************************************/ + void evel_threshold_cross_interfacename_set(EVENT_THRESHOLD_CROSS * const event,char * sheader) + { + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(event->header.event_domain == EVEL_DOMAIN_THRESHOLD_CROSS); + assert(sheader != NULL); + + evel_set_option_string(&event->interfaceName, + sheader, + "TCA Interface name"); + EVEL_EXIT(); + } + + /**************************************************************************//** + * Set the TCA Data element type. + * + * @param sheader element type of Threshold + *****************************************************************************/ + void evel_threshold_cross_data_elementtype_set(EVENT_THRESHOLD_CROSS * const event,char * sheader) + { + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(event->header.event_domain == EVEL_DOMAIN_THRESHOLD_CROSS); + assert(sheader != NULL); + + evel_set_option_string(&event->elementType, + sheader, + "TCA Element type value"); + EVEL_EXIT(); + } + + /**************************************************************************//** + * Set the TCA Data collector value. + * + * @param sheader Data collector value + *****************************************************************************/ + void evel_threshold_cross_data_collector_set(EVENT_THRESHOLD_CROSS * const event,char * sheader) + { + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(event->header.event_domain == EVEL_DOMAIN_THRESHOLD_CROSS); + assert(sheader != NULL); + + evel_set_option_string(&event->dataCollector, + sheader, + "Datacollector value"); + EVEL_EXIT(); + } + + + + /**************************************************************************//** + * Set the TCA alert value. + * + * @param sheader Possible alert value + *****************************************************************************/ + void evel_threshold_cross_alertvalue_set(EVENT_THRESHOLD_CROSS * const event,char * sheader) + { + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(event->header.event_domain == EVEL_DOMAIN_THRESHOLD_CROSS); + assert(sheader != NULL); + + evel_set_option_string(&event->alertValue, + sheader, + "Alert value"); + EVEL_EXIT(); + } + +/**************************************************************************//** + * Encode the Mobile Flow GTP Per Flow Metrics as a JSON object. + * + * @param jbuf Pointer to working ::EVEL_JSON_BUFFER. + * @param metrics Pointer to the ::EVENT_MOBILE_FLOW to encode. + * @returns Number of bytes actually written. + *****************************************************************************/ +void evel_json_encode_perf_counter( EVEL_JSON_BUFFER * jbuf, PERF_COUNTER *pcounter) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(jbuf != NULL); + assert(pcounter != NULL); + + evel_json_open_named_object(jbuf, "additionalParameters"); + + /***************************************************************************/ + /* Mandatory parameters. */ + /***************************************************************************/ + evel_enc_kv_string(jbuf, "criticality", pcounter->criticality); + evel_enc_kv_string(jbuf, "name", pcounter->name); + evel_enc_kv_string(jbuf, "thresholdCrossed", pcounter->name); + evel_enc_kv_string(jbuf, "value", pcounter->value); + + evel_json_close_object(jbuf); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Encode the Signaling in JSON according to AT&T's schema for the + * event type. + * + * @param jbuf Pointer to the ::EVEL_JSON_BUFFER to encode into. + * @param event Pointer to the ::EVENT_HEADER to encode. + *****************************************************************************/ +void evel_json_encode_threshold_cross(EVEL_JSON_BUFFER * const jbuf, + EVENT_THRESHOLD_CROSS * const event) +{ + OTHER_FIELD * nv_pair = NULL; + DLIST_ITEM * dlist_item = NULL; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(event != NULL); + assert(event->header.event_domain == EVEL_DOMAIN_THRESHOLD_CROSS); + + evel_json_encode_header(jbuf, &event->header); + evel_json_open_named_object(jbuf, "thresholdCrossingAlert"); + + /***************************************************************************/ + /* Mandatory fields */ + /***************************************************************************/ + evel_json_encode_perf_counter(jbuf, &event->additionalParameters); + evel_enc_kv_int(jbuf, "alertAction", event->alertAction); + evel_enc_kv_string(jbuf, "alertDescription", event->alertDescription); + evel_enc_kv_int(jbuf, "alertType", event->alertType); + evel_enc_kv_ull( + jbuf, "collectionTimestamp", event->collectionTimestamp); + evel_enc_kv_int(jbuf, "eventSeverity", event->eventSeverity); + evel_enc_kv_ull( + jbuf, "eventStartTimestamp", event->eventStartTimestamp); + + /***************************************************************************/ + /* Optional fields */ + /***************************************************************************/ + evel_enc_kv_opt_string(jbuf, "alertValue", &event->alertValue); + evel_enc_kv_opt_string(jbuf, "dataCollector", &event->dataCollector); + evel_enc_kv_opt_string(jbuf, "elementType", &event->elementType); + evel_enc_kv_opt_string(jbuf, "interfaceName", &event->interfaceName); + evel_enc_kv_opt_string(jbuf, "networkService", &event->networkService); + evel_enc_kv_opt_string(jbuf, "possibleRootCause", &event->possibleRootCause); + + /***************************************************************************/ + /* Checkpoint, so that we can wind back if all fields are suppressed. */ + /***************************************************************************/ + evel_json_checkpoint(jbuf); + if (evel_json_open_opt_named_list(jbuf, "additionalFields")) + { + bool added = false; + + dlist_item = dlist_get_first(&event->additional_info); + while (dlist_item != NULL) + { + nv_pair = (OTHER_FIELD *) dlist_item->item; + assert(nv_pair != NULL); + + if (!evel_throttle_suppress_nv_pair(jbuf->throttle_spec, + "additionalFields", + nv_pair->name)) + { + evel_json_open_object(jbuf); + evel_enc_kv_string(jbuf, "name", nv_pair->name); + evel_enc_kv_string(jbuf, "value", nv_pair->value); + evel_json_close_object(jbuf); + added = true; + } + dlist_item = dlist_get_next(dlist_item); + } + evel_json_close_list(jbuf); + + /*************************************************************************/ + /* If we've not written anything, rewind to before we opened the list. */ + /*************************************************************************/ + if (!added) + { + evel_json_rewind(jbuf); + } + } + evel_enc_version(jbuf, + "thresholdCrossingFieldsVersion", + event->major_version, + event->minor_version); + + evel_json_close_object(jbuf); + + EVEL_EXIT(); +} + diff --git a/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_throttle.c b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_throttle.c new file mode 100644 index 0000000..6327741 --- /dev/null +++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_throttle.c @@ -0,0 +1,2103 @@ +/*************************************************************************//** + * + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************/ + +/**************************************************************************//** + * @file + * Event Manager + * + * Simple event manager that is responsible for taking events (Heartbeats, + * Faults and Measurements) from the ring-buffer and posting them to the API. + * + ****************************************************************************/ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include + +#include "evel_throttle.h" + +/*****************************************************************************/ +/* The Event Throttling State for all domains, indexed by */ +/* ::EVEL_EVENT_DOMAINS, corresponding to JSON eventDomain. */ +/* */ +/* A given domain is in a throttled state if ::evel_throttle_spec is */ +/* non-NULL. */ +/*****************************************************************************/ +static EVEL_THROTTLE_SPEC * evel_throttle_spec[EVEL_MAX_DOMAINS]; + +/*****************************************************************************/ +/* The current measurement interval. Default: MEASUREMENT_INTERVAL_UKNOWN. */ +/* Must be protected by evel_measurement_interval_mutex. */ +/*****************************************************************************/ +static int evel_measurement_interval; + +/*****************************************************************************/ +/* Mutex protecting evel_measurement_interval from contention between an */ +/* EVEL client reading it, and the EVEL event handler updating it. */ +/*****************************************************************************/ +static pthread_mutex_t evel_measurement_interval_mutex; + +/*****************************************************************************/ +/* Flag stating that we have received a "provideThrottlingState" command. */ +/* Set during JSON processing and cleared on sending the throttling state. */ +/*****************************************************************************/ +static bool evel_provide_throttling_state; + +/*****************************************************************************/ +/* Holder for the "commandType" value during JSON processing. */ +/*****************************************************************************/ +static char * evel_command_type_value; + +/*****************************************************************************/ +/* Holder for the "measurementInterval" value during JSON processing. */ +/*****************************************************************************/ +static char * evel_measurement_interval_value; + +/*****************************************************************************/ +/* Holder for the "eventDomain" value during JSON processing. */ +/*****************************************************************************/ +static char * evel_throttle_spec_domain_value; + +/*****************************************************************************/ +/* Decoded version of ::evel_throttle_spec_domain_value. */ +/*****************************************************************************/ +static EVEL_EVENT_DOMAINS evel_throttle_spec_domain; + +/*****************************************************************************/ +/* During JSON processing of a single throttling specification, we collect */ +/* parameters in this working ::EVEL_THROTTLE_SPEC */ +/*****************************************************************************/ +static EVEL_THROTTLE_SPEC * evel_temp_throttle; + +/*****************************************************************************/ +/* State tracking our progress through the command list */ +/*****************************************************************************/ +EVEL_JSON_COMMAND_STATE evel_json_command_state; + +/*****************************************************************************/ +/* Debug strings for ::EVEL_JSON_COMMAND_STATE. */ +/*****************************************************************************/ +static const char * const evel_jcs_strings[EVEL_JCS_MAX] = { + "EVEL_JCS_START", + "EVEL_JCS_COMMAND_LIST", + "EVEL_JCS_COMMAND_LIST_ENTRY", + "EVEL_JCS_COMMAND", + "EVEL_JCS_SPEC", + "EVEL_JCS_FIELD_NAMES", + "EVEL_JCS_PAIRS_LIST", + "EVEL_JCS_PAIRS_LIST_ENTRY", + "EVEL_JCS_NV_PAIR_NAMES" +}; + +/*****************************************************************************/ +/* Debug strings for JSON token type. */ +/*****************************************************************************/ +#define JSON_TOKEN_TYPES (JSMN_PRIMITIVE + 1) +static const char * const evel_json_token_strings[JSON_TOKEN_TYPES] = { + "JSMN_UNDEFINED", + "JSMN_OBJECT", + "JSMN_ARRAY", + "JSMN_STRING", + "JSMN_PRIMITIVE" +}; + +/*****************************************************************************/ +/* Debug strings for JSON domains. */ +/*****************************************************************************/ +static const char * evel_domain_strings[EVEL_MAX_DOMAINS] = { + "internal", + "heartbeat", + "fault", + "measurementsForVfScaling", + "mobileFlow", + "report", + "serviceEvents", + "signaling", + "stateChange", + "syslog", + "other" + "voiceQuality", + "maxDomain" +}; + +/*****************************************************************************/ +/* Local prototypes. */ +/*****************************************************************************/ +static void evel_throttle_finalize(EVEL_THROTTLE_SPEC * throttle_spec); +static struct hsearch_data * evel_throttle_hash_create(DLIST * hash_keys); +static void evel_throttle_free(EVEL_THROTTLE_SPEC * throttle_spec); +static void evel_throttle_free_nv_pair(EVEL_SUPPRESSED_NV_PAIRS * nv_pairs); +static void evel_init_json_stack(EVEL_JSON_STACK * json_stack, + const MEMORY_CHUNK * const chunk); +static bool evel_stack_push(EVEL_JSON_STACK * const json_stack, + const int num_required, + const EVEL_JSON_STATE new_state); +static void evel_stack_pop(EVEL_JSON_STACK * const json_stack); +static void evel_stack_cleanup(EVEL_JSON_STACK * const json_stack); +static char * evel_stack_strdup(const MEMORY_CHUNK * const chunk, + const jsmntok_t * const token); +static void evel_stack_store_key(EVEL_JSON_STACK * const json_stack, + const jsmntok_t * const token); +static void evel_stack_store_value(EVEL_JSON_STACK * const json_stack, + const jsmntok_t * const token); +static void evel_stack_store_item(EVEL_JSON_STACK * const json_stack, + const jsmntok_t * const token); +static void evel_set_command_state(const EVEL_JSON_COMMAND_STATE new_state); +static void evel_debug_token(const MEMORY_CHUNK * const chunk, + const jsmntok_t * const token); +static void evel_command_list_response(MEMORY_CHUNK * const post); +static int evel_json_encode_throttle(char * const json, const int max_size); +static int evel_json_encode_throttle_spec(char * const json, + const int max_size, + const EVEL_EVENT_DOMAINS domain); +static int evel_json_encode_nv_pairs(char * const json, + const int max_size, + EVEL_SUPPRESSED_NV_PAIRS * nv_pairs); +static void evel_close_command(); +static void evel_open_command(); +static void evel_set_throttling_spec(); +static void evel_set_measurement_interval(); +static void evel_open_throttle_spec(); +static void evel_close_throttle_spec(); +static EVEL_EVENT_DOMAINS evel_decode_domain(char * domain_value); +static void evel_open_nv_pairs_list_entry(); +static void evel_close_nv_pairs_list_entry(); +static void evel_store_nv_pair_field_name(char * const value); +static void evel_store_nv_pair_name(char * const item); +static void evel_store_suppressed_field_name(char * const item); +static EVEL_SUPPRESSED_NV_PAIRS * evel_get_last_nv_pairs(); + +/**************************************************************************//** + * Return the current measurement interval provided by the Event Listener. + * + * @returns The current measurement interval + * @retval EVEL_MEASUREMENT_INTERVAL_UKNOWN (0) - interval has not been + * specified + *****************************************************************************/ +int evel_get_measurement_interval() +{ + int result; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Lock, read, unlock. */ + /***************************************************************************/ + pthread_mutex_lock(&evel_measurement_interval_mutex); + result = evel_measurement_interval; + pthread_mutex_unlock(&evel_measurement_interval_mutex); + + EVEL_EXIT(); + + return result; +} + +/**************************************************************************//** + * Return the ::EVEL_THROTTLE_SPEC for a given domain. + * + * @param domain The domain for which to return state. + *****************************************************************************/ +EVEL_THROTTLE_SPEC * evel_get_throttle_spec(EVEL_EVENT_DOMAINS domain) +{ + EVEL_THROTTLE_SPEC * result; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(domain < EVEL_MAX_DOMAINS); + + result = evel_throttle_spec[domain]; + + EVEL_EXIT(); + + return result; +} + +/**************************************************************************//** + * Determine whether a field_name should be suppressed. + * + * @param throttle_spec Throttle specification for the domain being encoded. + * @param field_name The field name to encoded or suppress. + * @return true if the field_name should be suppressed, false otherwise. + *****************************************************************************/ +bool evel_throttle_suppress_field(EVEL_THROTTLE_SPEC * throttle_spec, + const char * const field_name) +{ + bool suppress = false; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(field_name != NULL); + + /***************************************************************************/ + /* If the throttle spec and hash table exist, query the field_names table. */ + /***************************************************************************/ + if ((throttle_spec != NULL) && (throttle_spec->hash_field_names != NULL)) + { + ENTRY hash_query; + ENTRY * hash_result; + hash_query.key = (char * const) field_name; + suppress = (hsearch_r(hash_query, + FIND, + &hash_result, + throttle_spec->hash_field_names) != 0); + } + + EVEL_EXIT(); + + return suppress; +} + +/**************************************************************************//** + * Determine whether a name-value pair should be allowed (not suppressed). + * + * @param throttle_spec Throttle specification for the domain being encoded. + * @param field_name The field name holding the name-value pairs. + * @param name The name of the name-value pair to encoded or suppress. + * @return true if the name-value pair should be suppressed, false otherwise. + *****************************************************************************/ +bool evel_throttle_suppress_nv_pair(EVEL_THROTTLE_SPEC * throttle_spec, + const char * const field_name, + const char * const name) +{ + EVEL_SUPPRESSED_NV_PAIRS * nv_pairs; + bool hit = false; + bool suppress = false; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(field_name != NULL); + assert(name != NULL); + + /***************************************************************************/ + /* If the throttle spec and hash table exist, query the nv_pairs table. */ + /***************************************************************************/ + if ((throttle_spec != NULL) && (throttle_spec->hash_nv_pairs_list != NULL)) + { + ENTRY hash_query; + ENTRY * hash_result; + hash_query.key = (char * const) field_name; + hit = (hsearch_r(hash_query, + FIND, + &hash_result, + throttle_spec->hash_nv_pairs_list) != 0); + if (hit) + { + nv_pairs = hash_result->data; + } + } + + /***************************************************************************/ + /* If we got a hit, and the nv_pairs and hash table exist, query the */ + /* nv_pairs table. */ + /***************************************************************************/ + if (hit && (nv_pairs != NULL) && (nv_pairs->hash_nv_pair_names != NULL)) + { + ENTRY hash_query; + ENTRY * hash_result; + hash_query.key = (char * const) name; + suppress = (hsearch_r(hash_query, + FIND, + &hash_result, + nv_pairs->hash_nv_pair_names) != 0); + } + + EVEL_EXIT(); + + return suppress; +} + +/**************************************************************************//** + * Initialize event throttling to the default state. + * + * Called from ::evel_initialize. + *****************************************************************************/ +void evel_throttle_initialize() +{ + int pthread_rc; + int ii; + + EVEL_ENTER(); + + for (ii = 0; ii < EVEL_MAX_DOMAINS; ii++) + { + evel_throttle_spec[ii] = NULL; + } + + pthread_rc = pthread_mutex_init(&evel_measurement_interval_mutex, NULL); + assert(pthread_rc == 0); + + evel_measurement_interval = EVEL_MEASUREMENT_INTERVAL_UKNOWN; + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Clean up event throttling. + * + * Called from ::evel_terminate. + *****************************************************************************/ +void evel_throttle_terminate() +{ + int pthread_rc; + int ii; + + EVEL_ENTER(); + + for (ii = 0; ii < EVEL_MAX_DOMAINS; ii++) + { + if (evel_throttle_spec[ii] != NULL) + { + evel_throttle_free(evel_throttle_spec[ii]); + evel_throttle_spec[ii] = NULL; + } + } + + pthread_rc = pthread_mutex_destroy(&evel_measurement_interval_mutex); + assert(pthread_rc == 0); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Finalize a single ::EVEL_THROTTLE_SPEC. + * + * Now that the specification is collected, build hash tables to simplify the + * throttling itself. + * + * @param throttle_spec The ::EVEL_THROTTLE_SPEC to finalize. + *****************************************************************************/ +void evel_throttle_finalize(EVEL_THROTTLE_SPEC * throttle_spec) +{ + int nv_pairs_count; + DLIST_ITEM * dlist_item; + ENTRY * add_result; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(throttle_spec != NULL); + + /***************************************************************************/ + /* Populate the hash table for suppressed field names. */ + /***************************************************************************/ + throttle_spec->hash_field_names = + evel_throttle_hash_create(&throttle_spec->suppressed_field_names); + + /***************************************************************************/ + /* Create the hash table for suppressed nv pairs. */ + /***************************************************************************/ + nv_pairs_count = dlist_count(&throttle_spec->suppressed_nv_pairs_list); + if (nv_pairs_count > 0) + { + throttle_spec->hash_nv_pairs_list = calloc(1, sizeof(struct hsearch_data)); + assert(throttle_spec->hash_nv_pairs_list != NULL); + + /*************************************************************************/ + /* Provide plenty of space in the table - see hcreate_r notes. */ + /*************************************************************************/ + if (hcreate_r(nv_pairs_count * 2, throttle_spec->hash_nv_pairs_list) == 0) + { + EVEL_ERROR("Failed to create hash table"); + free(throttle_spec->hash_nv_pairs_list); + throttle_spec->hash_nv_pairs_list = NULL; + } + } + + /***************************************************************************/ + /* Populate the hash tables under suppressed field names. */ + /***************************************************************************/ + dlist_item = dlist_get_first(&throttle_spec->suppressed_nv_pairs_list); + while (dlist_item != NULL) + { + EVEL_SUPPRESSED_NV_PAIRS * nv_pairs = dlist_item->item; + ENTRY hash_add; + + /*************************************************************************/ + /* Set the key to the string, and the item to the nv_pairs. */ + /*************************************************************************/ + assert(nv_pairs != NULL); + hash_add.key = nv_pairs->nv_pair_field_name; + hash_add.data = nv_pairs; + hsearch_r(hash_add, ENTER, &add_result, throttle_spec->hash_nv_pairs_list); + + /*************************************************************************/ + /* Create the nv_pair_names hash since we're in here. */ + /*************************************************************************/ + nv_pairs->hash_nv_pair_names = + evel_throttle_hash_create(&nv_pairs->suppressed_nv_pair_names); + + dlist_item = dlist_get_next(dlist_item); + } + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Create and populate a hash table from a DLIST of keys. + * + * @param hash_keys Pointer to a DLIST of hash table keys. + * @return Pointer to the created hash-table, or NULL on failure. + *****************************************************************************/ +struct hsearch_data * evel_throttle_hash_create(DLIST * hash_keys) +{ + int key_count; + struct hsearch_data * hash_table; + ENTRY * add_result; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(hash_keys != NULL); + + /***************************************************************************/ + /* Count the keys and if there are any, populate the hash table with them. */ + /***************************************************************************/ + key_count = dlist_count(hash_keys); + if (key_count > 0) + { + EVEL_DEBUG("Populating table for %d keys", key_count); + + hash_table = calloc(1, sizeof(struct hsearch_data)); + assert(hash_table != NULL); + + /*************************************************************************/ + /* We need to leave plenty of space in the table - see hcreate_r notes. */ + /*************************************************************************/ + if (hcreate_r(key_count * 2, hash_table) != 0) + { + DLIST_ITEM * dlist_item; + dlist_item = dlist_get_first(hash_keys); + while (dlist_item != NULL) + { + assert(dlist_item->item != NULL); + + /*********************************************************************/ + /* Set the key and data to the item, which is a string in this case. */ + /*********************************************************************/ + ENTRY hash_add; + hash_add.key = dlist_item->item; + hash_add.data = dlist_item->item; + hsearch_r(hash_add, ENTER, &add_result, hash_table); + dlist_item = dlist_get_next(dlist_item); + } + } + else + { + EVEL_ERROR("Failed to create hash table"); + free(hash_table); + hash_table = NULL; + } + } + else + { + hash_table = NULL; + } + + EVEL_EXIT(); + + return hash_table; +} + +/**************************************************************************//** + * Free resources associated with a single ::EVEL_THROTTLE_SPEC. + * + * @param throttle_spec The ::EVEL_THROTTLE_SPEC to free. + *****************************************************************************/ +void evel_throttle_free(EVEL_THROTTLE_SPEC * throttle_spec) +{ + char * field_name; + EVEL_SUPPRESSED_NV_PAIRS * nv_pairs; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(throttle_spec != NULL); + + /***************************************************************************/ + /* Free any hash tables. */ + /***************************************************************************/ + if (throttle_spec->hash_field_names != NULL) + { + hdestroy_r(throttle_spec->hash_field_names); + free(throttle_spec->hash_field_names); + } + if (throttle_spec->hash_nv_pairs_list != NULL) + { + hdestroy_r(throttle_spec->hash_nv_pairs_list); + free(throttle_spec->hash_nv_pairs_list); + } + + /***************************************************************************/ + /* Iterate through the linked lists, freeing memory. */ + /***************************************************************************/ + field_name = dlist_pop_last(&throttle_spec->suppressed_field_names); + while (field_name != NULL) + { + free(field_name); + field_name = dlist_pop_last(&throttle_spec->suppressed_field_names); + } + + nv_pairs = dlist_pop_last(&throttle_spec->suppressed_nv_pairs_list); + while (nv_pairs != NULL) + { + evel_throttle_free_nv_pair(nv_pairs); + nv_pairs = dlist_pop_last(&throttle_spec->suppressed_nv_pairs_list); + } + + free(throttle_spec); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Free resources associated with a single ::EVEL_SUPPRESSED_NV_PAIR. + * + * @param nv_pair The ::EVEL_SUPPRESSED_NV_PAIR to free. + *****************************************************************************/ +void evel_throttle_free_nv_pair(EVEL_SUPPRESSED_NV_PAIRS * nv_pairs) +{ + char * suppressed_name; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(nv_pairs != NULL); + + /***************************************************************************/ + /* Free any hash tables. */ + /***************************************************************************/ + if (nv_pairs->hash_nv_pair_names != NULL) + { + hdestroy_r(nv_pairs->hash_nv_pair_names); + free(nv_pairs->hash_nv_pair_names); + } + + /***************************************************************************/ + /* Iterate through the linked lists, freeing memory. */ + /***************************************************************************/ + suppressed_name = dlist_pop_last(&nv_pairs->suppressed_nv_pair_names); + while (suppressed_name != NULL) + { + free(suppressed_name); + suppressed_name = dlist_pop_last(&nv_pairs->suppressed_nv_pair_names); + } + if (nv_pairs->nv_pair_field_name != NULL) + { + free(nv_pairs->nv_pair_field_name); + } + free(nv_pairs); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Handle a JSON response from the listener, as a list of tokens from JSMN. + * + * @param chunk Memory chunk containing the JSON buffer. + * @param json_tokens Array of tokens to handle. + * @param num_tokens The number of tokens to handle. + * @param post The memory chunk in which to place any resulting POST. + * @return true if the command was handled, false otherwise. + *****************************************************************************/ +bool evel_handle_command_list(const MEMORY_CHUNK * const chunk, + const jsmntok_t * const json_tokens, + const int num_tokens, + MEMORY_CHUNK * const post) +{ + EVEL_JSON_STACK stack; + EVEL_JSON_STACK * json_stack = &stack; + EVEL_JSON_STACK_ENTRY * entry; + + bool json_ok = true; + int token_index = 0; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(chunk != NULL); + assert(json_tokens != NULL); + assert(num_tokens < EVEL_MAX_RESPONSE_TOKENS); + + /***************************************************************************/ + /* Collect one top-level item. */ + /***************************************************************************/ + evel_init_json_stack(json_stack, chunk); + + /***************************************************************************/ + /* Initialize JSON processing variables. */ + /***************************************************************************/ + evel_provide_throttling_state = false; + evel_command_type_value = NULL; + evel_measurement_interval_value = NULL; + evel_throttle_spec_domain_value = NULL; + evel_throttle_spec_domain = EVEL_MAX_DOMAINS; + evel_temp_throttle = NULL; + evel_json_command_state = EVEL_JCS_START; + + /***************************************************************************/ + /* Loop through the tokens, keeping a stack of state representing the */ + /* nested JSON structure (see json_state). We also track our way through */ + /* the ::EVEL_JSON_COMMAND_STATE as we go. */ + /***************************************************************************/ + while (json_ok && (token_index < num_tokens)) + { + const jsmntok_t * const token = &json_tokens[token_index]; + + if (EVEL_DEBUG_ON()) + { + evel_debug_token(chunk, token); + } + + /*************************************************************************/ + /* We may have popped or pushed, so always re-evaluate the stack entry. */ + /*************************************************************************/ + entry = &json_stack->entry[json_stack->level]; + + switch(token->type) + { + case JSMN_OBJECT: + if ((entry->json_state == EVEL_JSON_ITEM) || + (entry->json_state == EVEL_JSON_VALUE)) + { + json_ok = evel_stack_push(json_stack, token->size, EVEL_JSON_KEY); + } + else + { + EVEL_ERROR("Unexpected JSON state %d at token %d (%d)", + entry->json_state, token_index, token->type); + json_ok = false; + } + break; + + case JSMN_ARRAY: + if ((entry->json_state == EVEL_JSON_ITEM) || + (entry->json_state == EVEL_JSON_VALUE)) + { + json_ok = evel_stack_push(json_stack, token->size, EVEL_JSON_ITEM); + } + else + { + EVEL_ERROR("Unexpected JSON state %d at token %d (%d)", + entry->json_state, token_index, token->type); + json_ok = false; + } + break; + + case JSMN_STRING: + if (entry->json_state == EVEL_JSON_KEY) + { + evel_stack_store_key(json_stack, token); + } + else if (entry->json_state == EVEL_JSON_VALUE) + { + evel_stack_store_value(json_stack, token); + } + else if (entry->json_state == EVEL_JSON_ITEM) + { + evel_stack_store_item(json_stack, token); + } + else + { + EVEL_ERROR("Unexpected JSON state %d at token %d (%d)", + entry->json_state, token_index, token->type); + json_ok = false; + } + break; + + case JSMN_PRIMITIVE: + if (entry->json_state == EVEL_JSON_VALUE) + { + evel_stack_store_value(json_stack, token); + } + else if (entry->json_state == EVEL_JSON_ITEM) + { + evel_stack_store_item(json_stack, token); + } + else + { + EVEL_ERROR("Unexpected JSON state %d at token %d (%d)", + entry->json_state, token_index, token->type); + json_ok = false; + } + break; + + case JSMN_UNDEFINED: + default: + EVEL_ERROR("Unexpected JSON format at token %d (%d)", + token_index, token->type); + json_ok = false; + break; + } + + /*************************************************************************/ + /* Pop the stack if we're counted enough nested items. */ + /*************************************************************************/ + evel_stack_pop(json_stack); + + token_index++; + } + + /***************************************************************************/ + /* Cleanup the stack - we may have exited without winding it back, if the */ + /* input was not well formed. */ + /***************************************************************************/ + evel_stack_cleanup(json_stack); + + /***************************************************************************/ + /* We may want to generate and POST a response to the command list. */ + /***************************************************************************/ + if (json_ok) + { + evel_command_list_response(post); + } + + /***************************************************************************/ + /* Make sure we're clean on exit. */ + /***************************************************************************/ + assert(evel_command_type_value == NULL); + assert(evel_measurement_interval_value == NULL); + assert(evel_throttle_spec_domain_value == NULL); + assert(evel_throttle_spec_domain == EVEL_MAX_DOMAINS); + assert(evel_temp_throttle == NULL); + + EVEL_EXIT(); + + return json_ok; +} + +/**************************************************************************//** + * Copy a copy of an element, in string form. + * + * The caller must manage memory allocated for the copied string. + * + * @param chunk Memory chunk containing the JSON buffer. + * @param token The token to copy from. + * @return the copy of the element. + *****************************************************************************/ +char * evel_stack_strdup(const MEMORY_CHUNK * const chunk, + const jsmntok_t * const token) +{ + char temp_char; + char * result; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Call strdup to copy the string, inserting a temporary \0 for the call. */ + /***************************************************************************/ + temp_char = chunk->memory[token->end]; + chunk->memory[token->end] = '\0'; + result = strdup(chunk->memory + token->start); + assert(result != NULL); + chunk->memory[token->end] = temp_char; + + EVEL_EXIT(); + + return result; +} + +/**************************************************************************//** + * Copy a copy of an element, in string form. + * + * @param json_stack The JSON stack to initialize. + * @param chunk The underlying memory chunk used for parsing. + *****************************************************************************/ +void evel_init_json_stack(EVEL_JSON_STACK * json_stack, + const MEMORY_CHUNK * const chunk) +{ + EVEL_JSON_STACK_ENTRY * entry; + + EVEL_ENTER(); + + json_stack->level = 0; + entry = json_stack->entry; + entry->json_state = EVEL_JSON_ITEM; + entry->json_count = 0; + entry->num_required = 1; + entry->json_key = NULL; + json_stack->chunk = chunk; + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Push a new entry on the stack + * + * @param json_stack The stack. + * @param num_required The number of elements required. + * @param new_state The state for the new entry. + * @return false if we cannot push onto the stack. + *****************************************************************************/ +bool evel_stack_push(EVEL_JSON_STACK * const json_stack, + const int num_required, + const EVEL_JSON_STATE new_state) +{ + EVEL_JSON_STACK_ENTRY * entry; + char * key; + bool result; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(json_stack != NULL); + assert(json_stack->level >= 0); + assert(json_stack->level < EVEL_JSON_STACK_DEPTH); + assert((new_state == EVEL_JSON_ITEM) || (new_state == EVEL_JSON_KEY)); + + /***************************************************************************/ + /* Check nesting depth, and stop processing if we hit the limit. */ + /***************************************************************************/ + if ((json_stack->level + 1) >= EVEL_JSON_STACK_DEPTH) + { + EVEL_ERROR("JSON Nesting is too deep - stop processing"); + result = false; + goto exit_label; + } + + /***************************************************************************/ + /* Evaluate cases where we recurse and are interested in the contents. */ + /***************************************************************************/ + entry = &json_stack->entry[json_stack->level]; + key = entry->json_key; + + /***************************************************************************/ + /* Note that this is the key before we drop a level. */ + /***************************************************************************/ + if (key != NULL) + { + EVEL_DEBUG("Push with key: %s", key); + + switch (evel_json_command_state) + { + case EVEL_JCS_START: + if (strcmp(key, "commandList") == 0) + { + evel_set_command_state(EVEL_JCS_COMMAND_LIST); + } + break; + + case EVEL_JCS_COMMAND_LIST_ENTRY: + if (strcmp(key, "command") == 0) + { + evel_open_command(); + evel_set_command_state(EVEL_JCS_COMMAND); + } + break; + + case EVEL_JCS_COMMAND: + if (strcmp(key, "eventDomainThrottleSpecification") == 0) + { + evel_open_throttle_spec(); + evel_set_command_state(EVEL_JCS_SPEC); + } + break; + + case EVEL_JCS_SPEC: + if (strcmp(key, "suppressedFieldNames") == 0) + { + evel_set_command_state(EVEL_JCS_FIELD_NAMES); + } + else if (strcmp(key, "suppressedNvPairsList") == 0) + { + evel_set_command_state(EVEL_JCS_PAIRS_LIST); + } + break; + + case EVEL_JCS_PAIRS_LIST_ENTRY: + if (strcmp(key, "suppressedNvPairNames") == 0) + { + evel_set_command_state(EVEL_JCS_NV_PAIR_NAMES); + } + break; + + case EVEL_JCS_FIELD_NAMES: + case EVEL_JCS_PAIRS_LIST: + case EVEL_JCS_NV_PAIR_NAMES: + default: + EVEL_ERROR("Unexpected JSON key %s in state %d", + key, + evel_json_command_state); + break; + } + } + else + { + EVEL_DEBUG("Push with no key"); + + /*************************************************************************/ + /* If we're pushing without a key, then we're in an array. We switch */ + /* state based on the existing state and stack level. */ + /*************************************************************************/ + const int COMMAND_LIST_LEVEL = 2; + const int NV_PAIRS_LIST_LEVEL = 6; + + if ((evel_json_command_state == EVEL_JCS_PAIRS_LIST) && + (json_stack->level == NV_PAIRS_LIST_LEVEL)) + { + /***********************************************************************/ + /* We are entering an object within the "suppressedNvPairsList" array. */ + /***********************************************************************/ + evel_open_nv_pairs_list_entry(); + evel_set_command_state(EVEL_JCS_PAIRS_LIST_ENTRY); + } + + if ((evel_json_command_state == EVEL_JCS_COMMAND_LIST) && + (json_stack->level == COMMAND_LIST_LEVEL)) + { + /***********************************************************************/ + /* We are entering an object within the "commandList" array. */ + /***********************************************************************/ + evel_set_command_state(EVEL_JCS_COMMAND_LIST_ENTRY); + } + } + + /***************************************************************************/ + /* Push the stack and initialize the entry. */ + /***************************************************************************/ + json_stack->level++; + entry++; + EVEL_DEBUG("Stack Push -> %d", json_stack->level); + entry = &json_stack->entry[json_stack->level]; + entry->json_count = 0; + entry->num_required = num_required; + entry->json_state = new_state; + entry->json_key = NULL; + result = true; + +exit_label: + + EVEL_EXIT(); + + return result; +} + +/**************************************************************************//** + * Pop any stack entries which have collected the required number of items. + * + * @param json_stack The stack. + *****************************************************************************/ +void evel_stack_pop(EVEL_JSON_STACK * const json_stack) +{ + EVEL_JSON_STACK_ENTRY * entry; + char * key; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(json_stack != NULL); + assert(json_stack->level >= 0); + assert(json_stack->level < EVEL_JSON_STACK_DEPTH); + + entry = &json_stack->entry[json_stack->level]; + while ((json_stack->level > 0) && (entry->json_count == entry->num_required)) + { + key = entry->json_key; + + switch (evel_json_command_state) + { + case EVEL_JCS_COMMAND_LIST: + evel_set_command_state(EVEL_JCS_START); + break; + + case EVEL_JCS_COMMAND_LIST_ENTRY: + evel_set_command_state(EVEL_JCS_COMMAND_LIST); + break; + + case EVEL_JCS_COMMAND: + evel_close_command(); + evel_set_command_state(EVEL_JCS_COMMAND_LIST_ENTRY); + break; + + case EVEL_JCS_SPEC: + evel_close_throttle_spec(); + evel_set_command_state(EVEL_JCS_COMMAND); + break; + + case EVEL_JCS_FIELD_NAMES: + evel_set_command_state(EVEL_JCS_SPEC); + break; + + case EVEL_JCS_PAIRS_LIST: + evel_set_command_state(EVEL_JCS_SPEC); + break; + + case EVEL_JCS_PAIRS_LIST_ENTRY: + evel_close_nv_pairs_list_entry(); + evel_set_command_state(EVEL_JCS_PAIRS_LIST); + break; + + case EVEL_JCS_NV_PAIR_NAMES: + evel_set_command_state(EVEL_JCS_PAIRS_LIST_ENTRY); + break; + + default: + break; + } + + /*************************************************************************/ + /* Free off any key that was duplicated and stored. */ + /*************************************************************************/ + if (key != NULL) + { + free(key); + entry->json_key = NULL; + } + + /*************************************************************************/ + /* We just reached the required number of key-value pairs or items, so */ + /* pop the stack. */ + /*************************************************************************/ + json_stack->level--; + entry--; + + EVEL_DEBUG("Stack Pop -> %d", json_stack->level); + + /*************************************************************************/ + /* We just completed collection of an ITEM (within an ARRAY) or a VALUE */ + /* (within an OBJECT). Either way, we need to count it. */ + /*************************************************************************/ + entry->json_count++; + + /*************************************************************************/ + /* If we just completed a VALUE, then we expect the next element to be a */ + /* key, if there is a next element. */ + /*************************************************************************/ + if (entry->json_state == EVEL_JSON_VALUE) + { + entry->json_state = EVEL_JSON_KEY; + } + } + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Pop all stack entries, freeing any memory as we go. + * + * @param json_stack The stack. + *****************************************************************************/ +void evel_stack_cleanup(EVEL_JSON_STACK * const json_stack) +{ + EVEL_JSON_STACK_ENTRY * entry; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(json_stack != NULL); + assert(json_stack->level >= 0); + assert(json_stack->level < EVEL_JSON_STACK_DEPTH); + + entry = &json_stack->entry[json_stack->level]; + while ((json_stack->level > 0)) + { + /*************************************************************************/ + /* Free off any key that was duplicated and stored. */ + /*************************************************************************/ + if (entry->json_key != NULL) + { + free(entry->json_key); + entry->json_key = NULL; + } + + /*************************************************************************/ + /* We just reached the required number of key-value pairs or items, so */ + /* pop the stack. */ + /*************************************************************************/ + json_stack->level--; + entry--; + } + + /***************************************************************************/ + /* If we hit EVEL_JSON_STACK_DEPTH, we exit the loop and can leave these */ + /* values hanging - so clean them up. */ + /***************************************************************************/ + if (evel_command_type_value != NULL) + { + free(evel_command_type_value); + evel_command_type_value = NULL; + } + if (evel_measurement_interval_value != NULL) + { + free(evel_measurement_interval_value); + evel_measurement_interval_value = NULL; + } + if (evel_throttle_spec_domain_value != NULL) + { + free(evel_throttle_spec_domain_value); + evel_throttle_spec_domain_value = NULL; + } + evel_throttle_spec_domain = EVEL_MAX_DOMAINS; + if (evel_temp_throttle != NULL) + { + evel_throttle_free(evel_temp_throttle); + evel_temp_throttle = NULL; + } + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Store a key in the JSON stack. + * + * We always store the most recent key at each level in the stack. + * + * @param json_stack The stack. + * @param token The token holding the key. + *****************************************************************************/ +void evel_stack_store_key(EVEL_JSON_STACK * const json_stack, + const jsmntok_t * const token) +{ + EVEL_JSON_STACK_ENTRY * entry; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(json_stack != NULL); + assert(json_stack->level >= 0); + assert(json_stack->level < EVEL_JSON_STACK_DEPTH); + + /***************************************************************************/ + /* Free any previously stored key, replacing it with the new one. */ + /***************************************************************************/ + entry = &json_stack->entry[json_stack->level]; + if (entry->json_key != NULL) + { + free(entry->json_key); + } + entry->json_key = evel_stack_strdup(json_stack->chunk, token); + + /***************************************************************************/ + /* Switch state to collecting the corresponding value. */ + /***************************************************************************/ + entry->json_state = EVEL_JSON_VALUE; + + EVEL_DEBUG("Stored key: %s", entry->json_key); + EVEL_EXIT(); +} + +/**************************************************************************//** + * Store a value in the JSON stack. + * + * @param json_stack The stack. + * @param token The token holding the value. + *****************************************************************************/ +void evel_stack_store_value(EVEL_JSON_STACK * const json_stack, + const jsmntok_t * const token) +{ + EVEL_JSON_STACK_ENTRY * entry; + char * value; + bool stored; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(json_stack != NULL); + assert(json_stack->level >= 0); + assert(json_stack->level < EVEL_JSON_STACK_DEPTH); + + /***************************************************************************/ + /* Based on the (key, state), work out whether we're expecting a value, */ + /* then store or ignore it as required. */ + /***************************************************************************/ + entry = &json_stack->entry[json_stack->level]; + value = evel_stack_strdup(json_stack->chunk, token); + stored = false; + EVEL_DEBUG("Store value: %s", value); + + switch (evel_json_command_state) + { + case EVEL_JCS_COMMAND: + if (strcmp(entry->json_key, "commandType") == 0) + { + evel_command_type_value = value; + stored = true; + } + else if (strcmp(entry->json_key, "measurementInterval") == 0) + { + evel_measurement_interval_value = value; + stored = true; + } + break; + + case EVEL_JCS_SPEC: + if (strcmp(entry->json_key, "eventDomain") == 0) + { + evel_throttle_spec_domain_value = value; + stored = true; + } + break; + + case EVEL_JCS_PAIRS_LIST_ENTRY: + if (strcmp(entry->json_key, "nvPairFieldName") == 0) + { + evel_store_nv_pair_field_name(value); + stored = true; + } + break; + + default: + EVEL_DEBUG("Ignoring value in state: %s", + evel_jcs_strings[evel_json_command_state]); + break; + } + + if (!stored) + { + EVEL_DEBUG("Ignored value: %s", value); + free(value); + } + + /***************************************************************************/ + /* Switch state to another key. */ + /***************************************************************************/ + entry->json_state = EVEL_JSON_KEY; + + /***************************************************************************/ + /* Count the key-value pair. */ + /***************************************************************************/ + entry->json_count++; + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Store an item in the JSON stack - a string or primitive in an array. + * + * @param json_stack The stack. + * @param token The token holding the item. + *****************************************************************************/ +void evel_stack_store_item(EVEL_JSON_STACK * const json_stack, + const jsmntok_t * const token) +{ + EVEL_JSON_STACK_ENTRY * entry; + char * item; + bool stored; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(json_stack != NULL); + assert(json_stack->level >= 0); + assert(json_stack->level < EVEL_JSON_STACK_DEPTH); + + /***************************************************************************/ + /* Based on the state, work out whether we're expecting an item, then */ + /* store or ignore it as required. */ + /***************************************************************************/ + entry = &json_stack->entry[json_stack->level]; + item = evel_stack_strdup(json_stack->chunk, token); + stored = false; + EVEL_DEBUG("Store item: %s", item); + + switch (evel_json_command_state) + { + case EVEL_JCS_NV_PAIR_NAMES: + evel_store_nv_pair_name(item); + stored = true; + break; + + case EVEL_JCS_FIELD_NAMES: + evel_store_suppressed_field_name(item); + stored = true; + break; + + default: + EVEL_DEBUG("Ignoring item in state: %s", + evel_jcs_strings[evel_json_command_state]); + break; + } + + if (!stored) + { + EVEL_DEBUG("Ignored item: %s", item); + free(item); + } + + /***************************************************************************/ + /* We need another item. This is purely defensive. */ + /***************************************************************************/ + entry->json_state = EVEL_JSON_ITEM; + + /***************************************************************************/ + /* Count the item. */ + /***************************************************************************/ + entry->json_count++; +} + +/**************************************************************************//** + * Set the JSON command state to a new value. + * + * @param new_state The new state to set. + *****************************************************************************/ +void evel_set_command_state(const EVEL_JSON_COMMAND_STATE new_state) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(evel_json_command_state < EVEL_JCS_MAX); + assert(new_state < EVEL_JCS_MAX); + + /***************************************************************************/ + /* Provide common debug, and set the new state. */ + /***************************************************************************/ + EVEL_DEBUG("Command State: %s -> %s", + evel_jcs_strings[evel_json_command_state], + evel_jcs_strings[new_state]); + evel_json_command_state = new_state; + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Produce debug output from a JSON token. + * + * @param chunk Memory chunk containing the JSON buffer. + * @param token Token to dump. + *****************************************************************************/ +void evel_debug_token(const MEMORY_CHUNK * const chunk, + const jsmntok_t * const token) +{ + char temp_char; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(token->type > 0); + assert(token->type < JSON_TOKEN_TYPES); + + /***************************************************************************/ + /* Log the token, leaving it in the state in which it started. */ + /***************************************************************************/ + temp_char = chunk->memory[token->end]; + chunk->memory[token->end] = '\0'; + EVEL_DEBUG("JSON token type: %s", evel_json_token_strings[token->type]); + EVEL_DEBUG("JSON token: %s", chunk->memory + token->start); + chunk->memory[token->end] = temp_char; + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Post a response to the commandList. + * + * @param post Memory chunk in which to post a response. + *****************************************************************************/ +void evel_command_list_response(MEMORY_CHUNK * const post) +{ + char * json_post; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(post != NULL); + assert(post->memory == NULL); + + if (evel_provide_throttling_state) + { + EVEL_DEBUG("Provide throttling state"); + + /*************************************************************************/ + /* Encode the response, making it printf-able for debug. */ + /*************************************************************************/ + json_post = malloc(EVEL_MAX_JSON_BODY); + assert(json_post != NULL); + post->size = evel_json_encode_throttle(json_post, EVEL_MAX_JSON_BODY - 1); + post->memory = json_post; + post->memory[post->size] = '\0'; + evel_provide_throttling_state = false; + } + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Encode the full throttling specification according to AT&T's schema. + * + * @param json Pointer to where to store the JSON encoded data. + * @param max_size Size of storage available in json_body. + * @returns Number of bytes actually written. + *****************************************************************************/ +int evel_json_encode_throttle(char * const json, const int max_size) +{ + bool throttled; + int domain; + int offset; + bool domain_added; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(json != NULL); + assert(max_size > 0); + + /***************************************************************************/ + /* Work out if we're throttled. */ + /***************************************************************************/ + throttled = false; + for (domain = EVEL_DOMAIN_FAULT; domain < EVEL_MAX_DOMAINS; domain++) + { + if (evel_throttle_spec[domain] != NULL) + { + throttled = true; + } + } + + /***************************************************************************/ + /* Encode the response. */ + /***************************************************************************/ + offset = 0; + offset += snprintf(json + offset, max_size - offset, + "{\"eventThrottlingState\": {"); + offset += snprintf(json + offset, max_size - offset, + "\"eventThrottlingMode\": \"%s\"", + throttled ? "throttled" : "normal"); + if (throttled) + { + offset += snprintf(json + offset, max_size - offset, + ", \"eventDomainThrottleSpecificationList\": ["); + + domain_added = false; + for (domain = EVEL_DOMAIN_FAULT; domain < EVEL_MAX_DOMAINS; domain++) + { + if (evel_throttle_spec[domain] != NULL) + { + if (domain_added) + { + offset += snprintf(json + offset, max_size - offset, ", "); + } + + offset += evel_json_encode_throttle_spec(json + offset, + max_size - offset, + domain); + domain_added = true; + } + } + + offset += snprintf(json + offset, max_size - offset, "]"); + } + + offset += snprintf(json + offset, max_size - offset, "}}"); + + EVEL_EXIT(); + + return offset; +} + +/**************************************************************************//** + * Encode a throttling specification for a domain. + * + * @param json Pointer to where to store the JSON encoded data. + * @param max_size Size of storage available in json_body. + * @returns Number of bytes actually written. + *****************************************************************************/ +int evel_json_encode_throttle_spec(char * const json, + const int max_size, + const EVEL_EVENT_DOMAINS domain) +{ + int offset; + EVEL_THROTTLE_SPEC * throttle_spec; + DLIST_ITEM * dlist_item; + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(domain >= EVEL_DOMAIN_FAULT); + assert(domain < EVEL_MAX_DOMAINS); + assert(evel_throttle_spec[domain] != NULL); + + throttle_spec = evel_throttle_spec[domain]; + + /***************************************************************************/ + /* Encode the domain. */ + /***************************************************************************/ + offset = 0; + offset += snprintf(json + offset, max_size - offset, + "{"); + offset += snprintf(json + offset, max_size - offset, + "\"eventDomain\": \"%s\"", + evel_domain_strings[domain]); + + /***************************************************************************/ + /* Encode "suppressedFieldNames". */ + /***************************************************************************/ + dlist_item = dlist_get_first(&throttle_spec->suppressed_field_names); + if (dlist_item != NULL) + { + offset += snprintf(json + offset, max_size - offset, + ", \"suppressedFieldNames\": ["); + while (dlist_item != NULL) + { + char * suppressed_field = dlist_item->item; + assert(suppressed_field != NULL); + + offset += snprintf(json + offset, max_size - offset, + "\"%s\"", suppressed_field); + dlist_item = dlist_get_next(dlist_item); + if (dlist_item != NULL) + { + offset += snprintf(json + offset, max_size - offset, ", "); + } + } + + offset += snprintf(json + offset, max_size - offset, "]"); + } + + /***************************************************************************/ + /* Encode "suppressedNvPairsList". */ + /***************************************************************************/ + dlist_item = dlist_get_first(&throttle_spec->suppressed_nv_pairs_list); + if (dlist_item != NULL) + { + offset += snprintf(json + offset, max_size - offset, + ", \"suppressedNvPairsList\": ["); + while (dlist_item != NULL) + { + offset += evel_json_encode_nv_pairs(json + offset, + max_size - offset, + dlist_item->item); + dlist_item = dlist_get_next(dlist_item); + if (dlist_item != NULL) + { + offset += snprintf(json + offset, max_size - offset, ", "); + } + } + + offset += snprintf(json + offset, max_size - offset, "]"); + } + + offset += snprintf(json + offset, max_size - offset, "}"); + + EVEL_EXIT(); + + return offset; +} + +/**************************************************************************//** + * Encode a single "suppressedNvPairsListEntry". + * + * @param json Pointer to where to store the JSON encoded data. + * @param max_size Size of storage available in json_body. + * @returns Number of bytes actually written. + *****************************************************************************/ +int evel_json_encode_nv_pairs(char * const json, + const int max_size, + EVEL_SUPPRESSED_NV_PAIRS * nv_pairs) +{ + DLIST_ITEM * dlist_item; + char * name; + int offset; + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(nv_pairs != NULL); + assert(nv_pairs->nv_pair_field_name != NULL); + assert(!dlist_is_empty(&nv_pairs->suppressed_nv_pair_names)); + + /***************************************************************************/ + /* Encode it. */ + /***************************************************************************/ + offset = 0; + offset += snprintf(json + offset, max_size - offset, "{"); + offset += snprintf(json + offset, max_size - offset, + "\"nvPairFieldName\": \"%s\"", + nv_pairs->nv_pair_field_name); + dlist_item = dlist_get_first(&nv_pairs->suppressed_nv_pair_names); + offset += snprintf(json + offset, max_size - offset, + ", \"suppressedNvPairNames\": ["); + while (dlist_item != NULL) + { + name = dlist_item->item; + assert(name != NULL); + offset += snprintf(json + offset, max_size - offset, "\"%s\"", name); + dlist_item = dlist_get_next(dlist_item); + if (dlist_item != NULL) + { + offset += snprintf(json + offset, max_size - offset, ", "); + } + } + offset += snprintf(json + offset, max_size - offset, "]"); + offset += snprintf(json + offset, max_size - offset, "}"); + + EVEL_EXIT(); + + return offset; +} + +/**************************************************************************//** + * Method called when we open a "command" object. + *****************************************************************************/ +void evel_open_command() +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Make some assertions. */ + /***************************************************************************/ + assert(evel_command_type_value == NULL); + assert(evel_measurement_interval_value == NULL); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Method called when we close a "command" object. + *****************************************************************************/ +void evel_close_command() +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* If a commandType was provided, fan out and handle it now what we have */ + /* fathered all related information. */ + /* */ + /* Note that we handle throttling specification and measurement interval */ + /* updates immediately on closing the command (not the list). We could */ + /* reject *all* commands in a list if any of them are invalid, but we are */ + /* take a best-effort strategy here - any valid-looking command gets */ + /* implemented regardless of what follows. */ + /***************************************************************************/ + if (evel_command_type_value != NULL) + { + EVEL_DEBUG("Closing command %s", evel_command_type_value); + + if (strcmp(evel_command_type_value, "provideThrottlingState") == 0) + { + evel_provide_throttling_state = true; + } + else if (strcmp(evel_command_type_value, "throttlingSpecification") == 0) + { + evel_set_throttling_spec(); + } + else if (strcmp(evel_command_type_value, "measurementIntervalChange") == 0) + { + evel_set_measurement_interval(); + } + else + { + EVEL_ERROR("Ignoring unknown commandType: %s\n", + evel_command_type_value); + } + + /*************************************************************************/ + /* Free the captured "commandType" value. */ + /*************************************************************************/ + free(evel_command_type_value); + evel_command_type_value = NULL; + } + + /***************************************************************************/ + /* There could be an unused working throttle spec at this point - if the */ + /* "throttlingSpecification" commandType was not provided, or an invalid */ + /* domain was provided, or was not provided at all. */ + /***************************************************************************/ + if (evel_temp_throttle != NULL) + { + evel_throttle_free(evel_temp_throttle); + evel_temp_throttle = NULL; + } + + /***************************************************************************/ + /* Similarly, the domain could be set. */ + /***************************************************************************/ + evel_throttle_spec_domain = EVEL_MAX_DOMAINS; + + /***************************************************************************/ + /* There could be an unused measurement interval value at this point - if */ + /* the "measurementIntervalChange" command was not provided. */ + /***************************************************************************/ + if (evel_measurement_interval_value != NULL) + { + free(evel_measurement_interval_value); + evel_measurement_interval_value = NULL; + } + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the provided throttling specification, when the command closes. + *****************************************************************************/ +void evel_set_throttling_spec() +{ + EVEL_ENTER(); + + if ((evel_throttle_spec_domain >= 0) && + (evel_throttle_spec_domain < EVEL_MAX_DOMAINS)) + { + EVEL_DEBUG("Updating throttle spec for domain: %s", + evel_domain_strings[evel_throttle_spec_domain]); + + /*************************************************************************/ + /* Free off the previous throttle specification for the domain, if there */ + /* is one. */ + /*************************************************************************/ + if (evel_throttle_spec[evel_throttle_spec_domain] != NULL) + { + evel_throttle_free(evel_throttle_spec[evel_throttle_spec_domain]); + } + + /*************************************************************************/ + /* Finalize the working throttling spec, if there is one. */ + /*************************************************************************/ + if (evel_temp_throttle != NULL) + { + evel_throttle_finalize(evel_temp_throttle); + } + + /*************************************************************************/ + /* Replace the throttle specification for the domain with the working */ + /* throttle specification. This could be NULL, if an empty throttle */ + /* specification has been received for a domain. */ + /*************************************************************************/ + evel_throttle_spec[evel_throttle_spec_domain] = evel_temp_throttle; + evel_temp_throttle = NULL; + } + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the provided measurement interval, when the command closes. + *****************************************************************************/ +void evel_set_measurement_interval() +{ + EVEL_ENTER(); + + if (evel_measurement_interval_value != NULL) + { + const long int value = strtol(evel_measurement_interval_value, NULL, 10); + + if ((value >= 0) && (value <= INT_MAX)) + { + /***********************************************************************/ + /* Lock, update, unlock. */ + /***********************************************************************/ + EVEL_DEBUG("Updating measurement interval to %d\n", value); + + pthread_mutex_lock(&evel_measurement_interval_mutex); + evel_measurement_interval = value; + pthread_mutex_unlock(&evel_measurement_interval_mutex); + } + else + { + EVEL_ERROR("Ignoring invalid measurement interval: %s", + evel_measurement_interval_value); + } + } + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Method called when we open an "eventDomainThrottleSpecification" object. + *****************************************************************************/ +void evel_open_throttle_spec() +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(evel_throttle_spec_domain_value == NULL); + assert(evel_throttle_spec_domain == EVEL_MAX_DOMAINS); + assert(evel_temp_throttle == NULL); + + /***************************************************************************/ + /* Allocate and initialize an ::EVEL_THROTTLE_SPEC in which to hold */ + /* captured JSON elements. */ + /***************************************************************************/ + evel_temp_throttle = malloc(sizeof(EVEL_THROTTLE_SPEC)); + assert(evel_temp_throttle != NULL); + dlist_initialize(&evel_temp_throttle->suppressed_field_names); + dlist_initialize(&evel_temp_throttle->suppressed_nv_pairs_list); + evel_temp_throttle->hash_field_names = NULL; + evel_temp_throttle->hash_nv_pairs_list = NULL; + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Method called when we close an "eventDomainThrottleSpecification" object. + *****************************************************************************/ +void evel_close_throttle_spec() +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Decode, free and blank a captured event domain value. */ + /***************************************************************************/ + if (evel_throttle_spec_domain_value != NULL) + { + evel_throttle_spec_domain = + evel_decode_domain(evel_throttle_spec_domain_value); + free(evel_throttle_spec_domain_value); + evel_throttle_spec_domain_value = NULL; + } + + /***************************************************************************/ + /* Free off an empty working throttle spec, to stop it being used. This */ + /* state should be represented by a NULL pointer for the domain. */ + /***************************************************************************/ + if (evel_temp_throttle != NULL) + { + if (dlist_is_empty(&evel_temp_throttle->suppressed_field_names) && + dlist_is_empty(&evel_temp_throttle->suppressed_nv_pairs_list)) + { + free(evel_temp_throttle); + evel_temp_throttle = NULL; + } + } + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Convert a value for an "eventDomain" into an ::EVEL_EVENT_DOMAINS. + * + * @param domain_value The domain string value to decode. + * @returns The matching ::EVEL_EVENT_DOMAINS, or ::EVEL_MAX_DOMAINS on error. + *****************************************************************************/ +EVEL_EVENT_DOMAINS evel_decode_domain(char * domain_value) +{ + EVEL_EVENT_DOMAINS result; + int ii; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(domain_value != NULL); + + result = EVEL_MAX_DOMAINS; + for (ii = EVEL_DOMAIN_FAULT; ii < EVEL_MAX_DOMAINS; ii++) + { + assert(evel_domain_strings[ii] != NULL); + if (strcmp(evel_domain_strings[ii], domain_value) == 0) + { + result = ii; + } + } + + EVEL_EXIT(); + + return result; +} + +/**************************************************************************//** + * Method called when we open a "suppressedNvPairsListEntry" object. + *****************************************************************************/ +void evel_open_nv_pairs_list_entry() +{ + EVEL_SUPPRESSED_NV_PAIRS * nv_pairs; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(evel_temp_throttle != NULL); + + /***************************************************************************/ + /* Allocate and initialize an ::EVEL_SUPPRESSED_NV_PAIRS, and add it to */ + /* the list. */ + /***************************************************************************/ + nv_pairs = malloc(sizeof(EVEL_SUPPRESSED_NV_PAIRS)); + assert(nv_pairs != NULL); + nv_pairs->nv_pair_field_name = NULL; + dlist_initialize(&nv_pairs->suppressed_nv_pair_names); + nv_pairs->hash_nv_pair_names = NULL; + dlist_push_last(&evel_temp_throttle->suppressed_nv_pairs_list, nv_pairs); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Method called when we close a "suppressedNvPairsListEntry" object. + *****************************************************************************/ +void evel_close_nv_pairs_list_entry() +{ + EVEL_SUPPRESSED_NV_PAIRS * nv_pairs; + EVEL_SUPPRESSED_NV_PAIRS * popped; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Get the latest nv pairs. This also performs the required checks. */ + /***************************************************************************/ + nv_pairs = evel_get_last_nv_pairs(); + + /***************************************************************************/ + /* For a "suppressedNvPairsListEntry" to have any meaning, we need both */ + /* "nvPairFieldName" and "suppressedNvPairNames". If we don't, then pop */ + /* and free whatever we just collected. */ + /***************************************************************************/ + if ((nv_pairs->nv_pair_field_name == NULL) || + dlist_is_empty(&nv_pairs->suppressed_nv_pair_names)) + { + popped = dlist_pop_last(&evel_temp_throttle->suppressed_nv_pairs_list); + assert(popped == nv_pairs); + evel_throttle_free_nv_pair(popped); + } + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Store an "nvPairFieldName" value in the working throttle spec. + * + * @param value The value to store. + *****************************************************************************/ +void evel_store_nv_pair_field_name(char * const value) +{ + EVEL_SUPPRESSED_NV_PAIRS * nv_pairs; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Get the latest nv pairs. This also performs the required checks. */ + /***************************************************************************/ + nv_pairs = evel_get_last_nv_pairs(); + + /***************************************************************************/ + /* Store the value. */ + /***************************************************************************/ + nv_pairs->nv_pair_field_name = value; + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Store a "suppressedNvPairNames" item in the working throttle spec. + * + * @param item The item to store. + *****************************************************************************/ +void evel_store_nv_pair_name(char * const item) +{ + EVEL_SUPPRESSED_NV_PAIRS * nv_pairs; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Get the latest nv pairs. This also performs the required checks. */ + /***************************************************************************/ + nv_pairs = evel_get_last_nv_pairs(); + + /***************************************************************************/ + /* Store the item. */ + /***************************************************************************/ + dlist_push_last(&nv_pairs->suppressed_nv_pair_names, item); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Store a "suppressedFieldNames" item in the working throttle spec. + * + * @param item The item to store. + *****************************************************************************/ +void evel_store_suppressed_field_name(char * const item) +{ + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(evel_temp_throttle != NULL); + + /***************************************************************************/ + /* Store the item. */ + /***************************************************************************/ + dlist_push_last(&evel_temp_throttle->suppressed_field_names, item); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Get the last added suppressed nv pairs list entry in the working spec. + * + * @returns The last entry. + *****************************************************************************/ +EVEL_SUPPRESSED_NV_PAIRS * evel_get_last_nv_pairs() +{ + DLIST_ITEM * dlist_item; + EVEL_SUPPRESSED_NV_PAIRS * nv_pairs; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(evel_temp_throttle != NULL); + + /***************************************************************************/ + /* Get the pair that was added when we opened the list entry. */ + /***************************************************************************/ + dlist_item = dlist_get_last(&evel_temp_throttle->suppressed_nv_pairs_list); + assert(dlist_item != NULL); + nv_pairs = dlist_item->item; + assert(nv_pairs != NULL); + + EVEL_EXIT(); + + return nv_pairs; +} diff --git a/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_throttle.h b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_throttle.h new file mode 100644 index 0000000..c97b3c3 --- /dev/null +++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_throttle.h @@ -0,0 +1,214 @@ +/*************************************************************************//** + * + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************/ +/**************************************************************************//** + * @file + * EVEL throttle definitions. + * + * These are internal definitions related to throttling specicications, which + * are required within the library but are not intended for external + * consumption. + * + ****************************************************************************/ + +#ifndef EVEL_THROTTLE_INCLUDED +#define EVEL_THROTTLE_INCLUDED + +#include "evel_internal.h" +#include "jsmn.h" + +/*****************************************************************************/ +/* Maximum depth of JSON response that we can handle. */ +/*****************************************************************************/ +#define EVEL_JSON_STACK_DEPTH 10 + +/**************************************************************************//** + * Maximum number of tokens that we allow for in a JSON response. + *****************************************************************************/ +#define EVEL_MAX_RESPONSE_TOKENS 1024 + +/**************************************************************************//** + * The nature of the next token that we are iterating through. Within an + * object, we alternate between collecting keys and values. Within an array, + * we only collect items. + *****************************************************************************/ +typedef enum { + EVEL_JSON_KEY, + EVEL_JSON_VALUE, + EVEL_JSON_ITEM +} EVEL_JSON_STATE; + +/**************************************************************************//** + * States which we move through during JSON processing, tracking our way + * through the supported JSON structure. + *****************************************************************************/ +typedef enum +{ + /***************************************************************************/ + /* Initial state. */ + /***************************************************************************/ + EVEL_JCS_START, + + /***************************************************************************/ + /* {"commandList": [ */ + /***************************************************************************/ + EVEL_JCS_COMMAND_LIST, + + /***************************************************************************/ + /* {"commandList": [{ */ + /***************************************************************************/ + EVEL_JCS_COMMAND_LIST_ENTRY, + + /***************************************************************************/ + /* {"commandList": [{"command": { */ + /***************************************************************************/ + EVEL_JCS_COMMAND, + + /***************************************************************************/ + /* ... "eventDomainThrottleSpecification": { */ + /***************************************************************************/ + EVEL_JCS_SPEC, + + /***************************************************************************/ + /* ... "suppressedFieldNames": [ */ + /***************************************************************************/ + EVEL_JCS_FIELD_NAMES, + + /***************************************************************************/ + /* ... "suppressedNvPairsList": [ */ + /***************************************************************************/ + EVEL_JCS_PAIRS_LIST, + + /***************************************************************************/ + /* ... "suppressedNvPairsList": [{ */ + /***************************************************************************/ + EVEL_JCS_PAIRS_LIST_ENTRY, + + /***************************************************************************/ + /* ... "suppressedNvPairNames": [ */ + /***************************************************************************/ + EVEL_JCS_NV_PAIR_NAMES, + + EVEL_JCS_MAX +} EVEL_JSON_COMMAND_STATE; + +/**************************************************************************//** + * An entry in the JSON stack. + *****************************************************************************/ +typedef struct evel_json_stack_entry { + + /***************************************************************************/ + /* The number of elements required at this level. */ + /***************************************************************************/ + int num_required; + + /***************************************************************************/ + /* The number of elements collected at this level. */ + /***************************************************************************/ + int json_count; + + /***************************************************************************/ + /* The collection state at this level in the JSON stack. */ + /***************************************************************************/ + EVEL_JSON_STATE json_state; + + /***************************************************************************/ + /* The key being collected (if json_state is EVEL_JSON_VALUE), or NULL. */ + /***************************************************************************/ + char * json_key; + +} EVEL_JSON_STACK_ENTRY; + +/**************************************************************************//** + * The JSON stack. + *****************************************************************************/ +typedef struct evel_json_stack { + + /***************************************************************************/ + /* The current position of the stack - starting at zero. */ + /***************************************************************************/ + int level; + + /***************************************************************************/ + /* The stack itself. */ + /***************************************************************************/ + EVEL_JSON_STACK_ENTRY entry[EVEL_JSON_STACK_DEPTH]; + + /***************************************************************************/ + /* The underlying memory chunk. */ + /***************************************************************************/ + const MEMORY_CHUNK * chunk; + +} EVEL_JSON_STACK; + +/**************************************************************************//** + * Initialize event throttling to the default state. + * + * Called from ::evel_initialize. + *****************************************************************************/ +void evel_throttle_initialize(); + +/**************************************************************************//** + * Clean up event throttling. + * + * Called from ::evel_terminate. + *****************************************************************************/ +void evel_throttle_terminate(); + +/**************************************************************************//** + * Handle a JSON response from the listener, as a list of tokens from JSMN. + * + * @param chunk Memory chunk containing the JSON buffer. + * @param json_tokens Array of tokens to handle. + * @param num_tokens The number of tokens to handle. + * @param post The memory chunk in which to place any resulting POST. + * @return true if the command was handled, false otherwise. + *****************************************************************************/ +bool evel_handle_command_list(const MEMORY_CHUNK * const chunk, + const jsmntok_t * const json_tokens, + const int num_tokens, + MEMORY_CHUNK * const post); + +/**************************************************************************//** + * Return the ::EVEL_THROTTLE_SPEC for a given domain. + * + * @param domain The domain for which to return state. + *****************************************************************************/ +EVEL_THROTTLE_SPEC * evel_get_throttle_spec(EVEL_EVENT_DOMAINS domain); + +/**************************************************************************//** + * Determine whether a field_name should be suppressed. + * + * @param throttle_spec Throttle specification for the domain being encoded. + * @param field_name The field name to encoded or suppress. + * @return true if the field_name should be suppressed, false otherwise. + *****************************************************************************/ +bool evel_throttle_suppress_field(EVEL_THROTTLE_SPEC * throttle_spec, + const char * const field_name); + +/**************************************************************************//** + * Determine whether a name-value pair should be allowed (not suppressed). + * + * @param throttle_spec Throttle specification for the domain being encoded. + * @param field_name The field name holding the name-value pairs. + * @param name The name of the name-value pair to encoded or suppress. + * @return true if the name-value pair should be suppressed, false otherwise. + *****************************************************************************/ +bool evel_throttle_suppress_nv_pair(EVEL_THROTTLE_SPEC * throttle_spec, + const char * const field_name, + const char * const name); + +#endif diff --git a/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_voicequality.c b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_voicequality.c new file mode 100644 index 0000000..cf2ec87 --- /dev/null +++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/evel_voicequality.c @@ -0,0 +1,640 @@ +/*************************************************************************//** + * + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************/ +/**************************************************************************//** + * @file + * Implementation of EVEL functions relating to the Voice Quality. + *****************************************************************************/ + +#include +#include +#include + +#include "evel.h" +#include "evel_internal.h" +#include "evel_throttle.h" + +/**************************************************************************//** + * Create a new voice quality event. + * + * @note The mandatory fields on the Voice Quality must be supplied to this + * factory function and are immutable once set. Optional fields have + * explicit setter functions, but again values may only be set once + * so that the Voice Quality has immutable properties. + * @param event_name Unique Event Name + * @param event_id A universal identifier of the event for analysis etc. + * @param calleeSideCodec Callee codec for the call. + * @param callerSideCodec Caller codec for the call. + * @param correlator Constant across all events on this call. + * @param midCallRtcp Base64 encoding of the binary RTCP data + * (excluding Eth/IP/UDP headers). + * @param vendorVnfNameFields Vendor, VNF and VfModule names. + * @returns pointer to the newly manufactured ::EVENT_VOICE_QUALITY. If the + * event is not used (i.e. posted) it must be released using + ::evel_free_voice_quality. + * @retval NULL Failed to create the event. + *****************************************************************************/ +EVENT_VOICE_QUALITY * evel_new_voice_quality(const char* ev_name, const char *ev_id, + const char * const calleeSideCodec, + const char * const callerSideCodec, const char * const correlator, + const char * const midCallRtcp, const char * const vendorName) { + + bool inError = false; + EVENT_VOICE_QUALITY *voiceQuality = NULL; + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(calleeSideCodec != NULL); + assert(callerSideCodec != NULL); + assert(correlator != NULL); + assert(midCallRtcp != NULL); + assert(vendorName != NULL); + + /***************************************************************************/ + /* Allocate the Voice Quality. */ + /***************************************************************************/ + voiceQuality = malloc(sizeof(EVENT_VOICE_QUALITY)); + + if (voiceQuality == NULL) + { + log_error_state("Out of memory"); + inError = true; + } + + //Only in case of successful allocation initialize data. + if (inError == false) { + memset(voiceQuality, 0, sizeof(EVENT_VOICE_QUALITY)); + EVEL_DEBUG("New Voice Quality is at %lp", voiceQuality); + + /***************************************************************************/ + /* Initialize the header & the fault fields. Optional integer values are */ + /* initialized as 0. */ + /***************************************************************************/ + evel_init_header_nameid(&voiceQuality->header,ev_name,ev_id); + voiceQuality->header.event_domain = EVEL_DOMAIN_VOICE_QUALITY; + voiceQuality->major_version = EVEL_VOICEQ_MAJOR_VERSION; + voiceQuality->minor_version = EVEL_VOICEQ_MINOR_VERSION; + + voiceQuality->calleeSideCodec = strdup(calleeSideCodec); + voiceQuality->callerSideCodec = strdup(callerSideCodec); + voiceQuality->correlator = strdup(correlator); + voiceQuality->midCallRtcp = strdup(midCallRtcp); + evel_init_vendor_field(&voiceQuality->vendorVnfNameFields, vendorName); + dlist_initialize(&voiceQuality->additionalInformation); + voiceQuality->endOfCallVqmSummaries = NULL; + evel_init_option_string(&voiceQuality->phoneNumber); + } + + EVEL_EXIT(); + return voiceQuality; + +} + +/**************************************************************************//** + * Add an additional value name/value pair to the Voice Quality. + * + * The name and value are null delimited ASCII strings. The library takes + * a copy so the caller does not have to preserve values after the function + * returns. + * + * @param fault Pointer to the fault. + * @param name ASCIIZ string with the attribute's name. The caller + * does not need to preserve the value once the function + * returns. + * @param value ASCIIZ string with the attribute's value. The caller + * does not need to preserve the value once the function + * returns. + *****************************************************************************/ +void evel_voice_quality_addl_info_add(EVENT_VOICE_QUALITY * voiceQ, char * name, char * value) { + VOICE_QUALITY_ADDL_INFO * addlInfo = NULL; + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(voiceQ != NULL); + assert(voiceQ->header.event_domain == EVEL_DOMAIN_VOICE_QUALITY); + assert(name != NULL); + assert(value != NULL); + + EVEL_DEBUG("Adding name=%s value=%s", name, value); + addlInfo = malloc(sizeof(VOICE_QUALITY_ADDL_INFO)); + assert(addlInfo != NULL); + memset(addlInfo, 0, sizeof(VOICE_QUALITY_ADDL_INFO)); + addlInfo->name = strdup(name); + addlInfo->value = strdup(value); + assert(addlInfo->name != NULL); + assert(addlInfo->value != NULL); + + dlist_push_last(&voiceQ->additionalInformation, addlInfo); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Callee side codec for Call for domain Voice Quality + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param voiceQuality Pointer to the Voice Quality Event. + * @param calleeCodecForCall The Callee Side Codec to be set. ASCIIZ + * string. The caller does not need to + * preserve the value once the function + * returns. + *****************************************************************************/ +void evel_voice_quality_callee_codec_set(EVENT_VOICE_QUALITY * voiceQuality, + const char * const calleeCodecForCall) { + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(voiceQuality != NULL); + assert(voiceQuality->header.event_domain == EVEL_DOMAIN_VOICE_QUALITY); + assert(calleeCodecForCall != NULL); + + voiceQuality->calleeSideCodec = strdup(calleeCodecForCall); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Caller side codec for Call for domain Voice Quality + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param voiceQuality Pointer to the Voice Quality Event. + * @param callerCodecForCall The Caller Side Codec to be set. ASCIIZ + * string. The caller does not need to + * preserve the value once the function + * returns. + *****************************************************************************/ +void evel_voice_quality_caller_codec_set(EVENT_VOICE_QUALITY * voiceQuality, + const char * const callerCodecForCall) { + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(voiceQuality != NULL); + assert(voiceQuality->header.event_domain == EVEL_DOMAIN_VOICE_QUALITY); + assert(callerCodecForCall != NULL); + + voiceQuality->calleeSideCodec = strdup(callerCodecForCall); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the correlator for domain Voice Quality + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param voiceQuality Pointer to the Voice Quality Event. + * @param correlator The correlator value to be set. ASCIIZ + * string. The caller does not need to + * preserve the value once the function + * returns. + *****************************************************************************/ +void evel_voice_quality_correlator_set(EVENT_VOICE_QUALITY * voiceQuality, + const char * const vCorrelator) { + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(voiceQuality != NULL); + assert(voiceQuality->header.event_domain == EVEL_DOMAIN_VOICE_QUALITY); + assert(vCorrelator != NULL); + + voiceQuality->correlator = strdup(vCorrelator); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the RTCP Call Data for domain Voice Quality + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param voiceQuality Pointer to the Voice Quality Event. + * @param rtcpCallData The RTCP Call Data to be set. ASCIIZ + * string. The caller does not need to + * preserve the value once the function + * returns. + *****************************************************************************/ +void evel_voice_quality_rtcp_data_set(EVENT_VOICE_QUALITY * voiceQuality, + const char * const rtcpCallData) { + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(voiceQuality != NULL); + assert(voiceQuality->header.event_domain == EVEL_DOMAIN_VOICE_QUALITY); + assert(rtcpCallData != NULL); + + voiceQuality->midCallRtcp = strdup(rtcpCallData); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Vendor VNF Name fields for domain Voice Quality + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param voiceQuality Pointer to the Voice Quality Event. + * @param modulename The Vendor, VNF and VfModule names to be set. + * ASCIIZ string. The caller does not need to + * preserve the value once the function + * returns. + *****************************************************************************/ +void evel_voice_quality_vnfmodule_name_set(EVENT_VOICE_QUALITY * voiceQuality, + const char * const module_name) { + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(voiceQuality != NULL); + assert(voiceQuality->header.event_domain == EVEL_DOMAIN_VOICE_QUALITY); + assert(module_name != NULL); + + evel_vendor_field_module_set(&voiceQuality->vendorVnfNameFields, module_name); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Vendor VNF Name fields for domain Voice Quality + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param voiceQuality Pointer to the Voice Quality Event. + * @param modulename The Vendor, VNF and VfModule names to be set. + * ASCIIZ string. The caller does not need to + * preserve the value once the function + * returns. + *****************************************************************************/ +void evel_voice_quality_vnfname_set(EVENT_VOICE_QUALITY * voiceQuality, + const char * const vnfname) { + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(voiceQuality != NULL); + assert(voiceQuality->header.event_domain == EVEL_DOMAIN_VOICE_QUALITY); + assert(vnfname != NULL); + + evel_vendor_field_vnfname_set(&voiceQuality->vendorVnfNameFields, vnfname); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Set the Phone Number associated with the Correlator for domain Voice Quality + * + * @note The property is treated as immutable: it is only valid to call + * the setter once. However, we don't assert if the caller tries to + * overwrite, just ignoring the update instead. + * + * @param voiceQuality Pointer to the Voice Quality Event. + * @param calleeCodecForCall The Phone Number to be set. ASCIIZ + * string. The caller does not need to + * preserve the value once the function + * returns. + *****************************************************************************/ +void evel_voice_quality_phone_number_set(EVENT_VOICE_QUALITY * voiceQuality, + const char * const phoneNumber) { + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(voiceQuality != NULL); + assert(voiceQuality->header.event_domain == EVEL_DOMAIN_VOICE_QUALITY); + assert(phoneNumber != NULL); + + evel_set_option_string(&voiceQuality->phoneNumber, phoneNumber, "Phone_Number"); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Add an End of Call Voice Quality Metrices + + * The adjacencyName and endpointDescription is null delimited ASCII string. + * The library takes a copy so the caller does not have to preserve values + * after the function returns. + * + * @param voiceQuality Pointer to the measurement. + * @param adjacencyName Adjacency name + * @param endpointDescription Enumeration: ‘Caller’, ‘Callee’. + * @param endpointJitter Endpoint jitter + * @param endpointRtpOctetsDiscarded Endpoint RTP octets discarded. + * @param endpointRtpOctetsReceived Endpoint RTP octets received. + * @param endpointRtpOctetsSent Endpoint RTP octets sent + * @param endpointRtpPacketsDiscarded Endpoint RTP packets discarded. + * @param endpointRtpPacketsReceived Endpoint RTP packets received. + * @param endpointRtpPacketsSent Endpoint RTP packets sent. + * @param localJitter Local jitter. + * @param localRtpOctetsDiscarded Local RTP octets discarded. + * @param localRtpOctetsReceived Local RTP octets received. + * @param localRtpOctetsSent Local RTP octets sent. + * @param localRtpPacketsDiscarded Local RTP packets discarded. + * @param localRtpPacketsReceived Local RTP packets received. + * @param localRtpPacketsSent Local RTP packets sent. + * @param mosCqe Decimal range from 1 to 5 + * (1 decimal place) + * @param packetsLost No Packets lost + * @param packetLossPercent Calculated percentage packet loss + * @param rFactor rFactor from 0 to 100 + * @param roundTripDelay Round trip delay in milliseconds + *****************************************************************************/ +void evel_voice_quality_end_metrics_add(EVENT_VOICE_QUALITY * voiceQuality, + const char * adjacencyName, EVEL_SERVICE_ENDPOINT_DESC endpointDescription, + int endpointJitter, + int endpointRtpOctetsDiscarded, + int endpointRtpOctetsReceived, + int endpointRtpOctetsSent, + int endpointRtpPacketsDiscarded, + int endpointRtpPacketsReceived, + int endpointRtpPacketsSent, + int localJitter, + int localRtpOctetsDiscarded, + int localRtpOctetsReceived, + int localRtpOctetsSent, + int localRtpPacketsDiscarded, + int localRtpPacketsReceived, + int localRtpPacketsSent, + int mosCqe, + int packetsLost, + int packetLossPercent, + int rFactor, + int roundTripDelay) { + + END_OF_CALL_VOICE_QUALITY_METRICS * vQMetrices = NULL; + EVEL_ENTER(); + + /***************************************************************************/ + /* Check assumptions. */ + /***************************************************************************/ + assert(voiceQuality != NULL); + assert(voiceQuality->header.event_domain == EVEL_DOMAIN_VOICE_QUALITY); + assert(adjacencyName != NULL); + assert(endpointDescription >= 0); + assert(mosCqe >= 1 && mosCqe <= 5); + assert(rFactor >= 0 && rFactor <= 100); + assert(voiceQuality->endOfCallVqmSummaries == NULL); + + /***************************************************************************/ + /* Allocate a container for the value and push onto the list. */ + /***************************************************************************/ + EVEL_DEBUG("Adding adjacencyName=%s endpointDescription=%d", adjacencyName, endpointDescription); + vQMetrices = malloc(sizeof(END_OF_CALL_VOICE_QUALITY_METRICS)); + assert(vQMetrices != NULL); + memset(vQMetrices, 0, sizeof(END_OF_CALL_VOICE_QUALITY_METRICS)); + + vQMetrices->adjacencyName = strdup(adjacencyName); + vQMetrices->endpointDescription = evel_service_endpoint_desc(endpointDescription); + + evel_set_option_int(&vQMetrices->endpointJitter, endpointJitter, "Endpoint jitter"); + evel_set_option_int(&vQMetrices->endpointRtpOctetsDiscarded, endpointRtpOctetsDiscarded, "Endpoint RTP octets discarded"); + evel_set_option_int(&vQMetrices->endpointRtpOctetsReceived, endpointRtpOctetsReceived, "Endpoint RTP octets received"); + evel_set_option_int(&vQMetrices->endpointRtpOctetsSent, endpointRtpOctetsSent, "Endpoint RTP octets sent"); + evel_set_option_int(&vQMetrices->endpointRtpPacketsDiscarded, endpointRtpPacketsDiscarded, "Endpoint RTP packets discarded"); + evel_set_option_int(&vQMetrices->endpointRtpPacketsReceived, endpointRtpPacketsReceived, "Endpoint RTP packets received"); + evel_set_option_int(&vQMetrices->endpointRtpPacketsSent, endpointRtpPacketsSent, "Endpoint RTP packets sent"); + evel_set_option_int(&vQMetrices->localJitter, localJitter, "Local jitter"); + evel_set_option_int(&vQMetrices->localRtpOctetsDiscarded, localRtpOctetsDiscarded, "Local RTP octets discarded"); + evel_set_option_int(&vQMetrices->localRtpOctetsReceived, localRtpOctetsReceived, "Local RTP octets received"); + evel_set_option_int(&vQMetrices->localRtpOctetsSent, localRtpOctetsSent, "Local RTP octets sent"); + evel_set_option_int(&vQMetrices->localRtpPacketsDiscarded, localRtpPacketsDiscarded, "Local RTP packets discarded"); + evel_set_option_int(&vQMetrices->localRtpPacketsReceived, localRtpPacketsReceived, "Local RTP packets received"); + evel_set_option_int(&vQMetrices->localRtpPacketsSent, localRtpPacketsSent, "Local RTP packets sent"); + evel_set_option_int(&vQMetrices->mosCqe, mosCqe, "Decimal range from 1 to 5 (1 decimal place)"); + evel_set_option_int(&vQMetrices->packetsLost, packetsLost, "Packets lost"); + evel_set_option_int(&vQMetrices->packetLossPercent, packetLossPercent, "Calculated percentage packet loss"); + evel_set_option_int(&vQMetrices->rFactor, rFactor, "rFactor "); + evel_set_option_int(&vQMetrices->roundTripDelay, roundTripDelay, "Round trip delay in milliseconds "); + + voiceQuality->endOfCallVqmSummaries = vQMetrices; + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Encode the Voce Quality in JSON according to AT&T's schema for the voice + * quality type. + * + * @param jbuf Pointer to the ::EVEL_JSON_BUFFER to encode into. + * @param event Pointer to the ::EVENT_HEADER to encode. + *****************************************************************************/ +void evel_json_encode_voice_quality(EVEL_JSON_BUFFER * jbuf, + EVENT_VOICE_QUALITY * event) +{ + VOICE_QUALITY_ADDL_INFO * addlInfo = NULL; + DLIST_ITEM * addlInfoItem = NULL; + + END_OF_CALL_VOICE_QUALITY_METRICS * vQMetrics = NULL; + DLIST_ITEM * vQMetricsItem = NULL; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(event != NULL); + assert(event->header.event_domain == EVEL_DOMAIN_VOICE_QUALITY); + + evel_json_encode_header(jbuf, &event->header); + evel_json_open_named_object(jbuf, "voiceQualityFields"); + + /***************************************************************************/ + /* Mandatory fields. */ + /***************************************************************************/ + evel_enc_kv_string(jbuf, "calleeSideCodec", event->calleeSideCodec); + evel_enc_kv_string(jbuf, "callerSideCodec", event->callerSideCodec); + evel_enc_kv_string(jbuf, "correlator", event->correlator); + evel_enc_kv_string(jbuf, "midCallRtcp", event->midCallRtcp); + evel_json_encode_vendor_field(jbuf, &event->vendorVnfNameFields); + evel_enc_version( + jbuf, "voiceQualityFieldsVersion", event->major_version, event->minor_version); + + /***************************************************************************/ + /* Optional fields. */ + /***************************************************************************/ + evel_enc_kv_opt_string(jbuf, "phoneNumber", &event->phoneNumber); + /***************************************************************************/ + /* Checkpoint, so that we can wind back if all fields are suppressed. */ + /***************************************************************************/ + //additionalInformation for Voice Quality + bool item_added = false; + + evel_json_checkpoint(jbuf); + if (evel_json_open_opt_named_list(jbuf, "additionalInformation")) + { + + addlInfoItem = dlist_get_first(&event->additionalInformation); + while (addlInfoItem != NULL) + { + addlInfo = (VOICE_QUALITY_ADDL_INFO*)addlInfoItem->item; + assert(addlInfo != NULL); + + if (!evel_throttle_suppress_nv_pair(jbuf->throttle_spec, + "additionalInformation", + addlInfo->name)) + { + evel_json_open_object(jbuf); + evel_enc_kv_string(jbuf, "name", addlInfo->name); + evel_enc_kv_string(jbuf, "value", addlInfo->value); + evel_json_close_object(jbuf); + item_added = true; + } + addlInfoItem = dlist_get_next(addlInfoItem); + } + evel_json_close_list(jbuf); + /*************************************************************************/ + /* If we've not written anything, rewind to before we opened the list. */ + /*************************************************************************/ + if (!item_added) + { + evel_json_rewind(jbuf); + } + } + + //endOfCallVqmSummaries + if( event->endOfCallVqmSummaries != NULL ) + { + evel_json_open_named_object(jbuf, "endOfCallVqmSummaries"); + vQMetrics = event->endOfCallVqmSummaries; + assert(vQMetrics != NULL); + + if (!evel_throttle_suppress_nv_pair(jbuf->throttle_spec, + "endOfCallVqmSummaries", vQMetrics->adjacencyName)) + { + evel_enc_kv_string(jbuf, "adjacencyName", vQMetrics->adjacencyName); + evel_enc_kv_string(jbuf, "endpointDescription", vQMetrics->endpointDescription); + evel_enc_kv_opt_int(jbuf, "endpointJitter", &vQMetrics->endpointJitter); + evel_enc_kv_opt_int(jbuf, "endpointRtpOctetsDiscarded", &vQMetrics->endpointRtpOctetsDiscarded); + evel_enc_kv_opt_int(jbuf, "endpointRtpOctetsReceived", &vQMetrics->endpointRtpOctetsReceived); + evel_enc_kv_opt_int(jbuf, "endpointRtpOctetsSent", &vQMetrics->endpointRtpOctetsSent); + evel_enc_kv_opt_int(jbuf, "endpointRtpPacketsDiscarded", &vQMetrics->endpointRtpPacketsDiscarded); + evel_enc_kv_opt_int(jbuf, "endpointRtpPacketsReceived", &vQMetrics->endpointRtpPacketsReceived); + evel_enc_kv_opt_int(jbuf, "endpointRtpPacketsSent", &vQMetrics->endpointRtpPacketsSent); + evel_enc_kv_opt_int(jbuf, "localJitter", &vQMetrics->localJitter); + evel_enc_kv_opt_int(jbuf, "localRtpOctetsDiscarded", &vQMetrics->localRtpOctetsDiscarded); + evel_enc_kv_opt_int(jbuf, "localRtpOctetsReceived", &vQMetrics->localRtpOctetsReceived); + evel_enc_kv_opt_int(jbuf, "localRtpOctetsSent", &vQMetrics->localRtpOctetsSent); + evel_enc_kv_opt_int(jbuf, "localRtpPacketsDiscarded", &vQMetrics->localRtpPacketsDiscarded); + evel_enc_kv_opt_int(jbuf, "localRtpPacketsReceived", &vQMetrics->localRtpPacketsReceived); + evel_enc_kv_opt_int(jbuf, "localRtpPacketsSent", &vQMetrics->localRtpPacketsSent); + evel_enc_kv_opt_int(jbuf, "mosCqe", &vQMetrics->mosCqe); + evel_enc_kv_opt_int(jbuf, "packetsLost", &vQMetrics->packetsLost); + evel_enc_kv_opt_int(jbuf, "packetLossPercent", &vQMetrics->packetLossPercent); + evel_enc_kv_opt_int(jbuf, "rFactor", &vQMetrics->rFactor); + evel_enc_kv_opt_int(jbuf, "roundTripDelay", &vQMetrics->roundTripDelay); + + } + + evel_json_close_object(jbuf); + } + + evel_json_close_object(jbuf); + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Free a Voice Quality. + * + * Free off the Voce Quality supplied. Will free all the contained allocated + * memory. + * + * @note It does not free the Voice Quality itself, since that may be part of a + * larger structure. + *****************************************************************************/ +void evel_free_voice_quality(EVENT_VOICE_QUALITY * voiceQuality) { + END_OF_CALL_VOICE_QUALITY_METRICS * vQMetrices = NULL; + VOICE_QUALITY_ADDL_INFO * addlInfo = NULL; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Check preconditions. As an internal API we don't allow freeing NULL */ + /* events as we do on the public API. */ + /***************************************************************************/ + assert(voiceQuality != NULL); + assert(voiceQuality->header.event_domain == EVEL_DOMAIN_VOICE_QUALITY); + + /***************************************************************************/ + /* Free all internal strings then the header itself. */ + /***************************************************************************/ + + //Additional Information + addlInfo = dlist_pop_last(&voiceQuality->additionalInformation); + while (addlInfo != NULL) + { + EVEL_DEBUG("Freeing Additional Info (%s, %s)", + addlInfo->name, + addlInfo->value); + free(addlInfo->name); + free(addlInfo->value); + free(addlInfo); + addlInfo = dlist_pop_last(&voiceQuality->additionalInformation); + } + + //Summary Information + if(voiceQuality->endOfCallVqmSummaries != NULL) + { + vQMetrices = voiceQuality->endOfCallVqmSummaries; + EVEL_DEBUG("Freeing End of Call Voice Measurements Info (%s, %s)", + vQMetrices->adjacencyName, + vQMetrices->endpointDescription); + free(vQMetrices->adjacencyName); + free(vQMetrices); + } + + //Members + free(voiceQuality->calleeSideCodec); + free(voiceQuality->callerSideCodec); + free(voiceQuality->correlator); + free(voiceQuality->midCallRtcp); + evel_free_option_string(&voiceQuality->phoneNumber); + evel_free_event_vendor_field(&voiceQuality->vendorVnfNameFields); + + //header + evel_free_header(&voiceQuality->header); + + EVEL_EXIT(); +} + diff --git a/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/hashtable.c b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/hashtable.c new file mode 100644 index 0000000..0e2f764 --- /dev/null +++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/hashtable.c @@ -0,0 +1,222 @@ +/*************************************************************************//** + * + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************/ +/**************************************************************************//** + * @file + * A simple Hashtable. + * + * @note No thread protection so you will need to use appropriate + * synchronization if use spans multiple threads. + * + ****************************************************************************/ + +#include +#include +#include +#include + +#include "hashtable.h" + +/**************************************************************************//** + * Hashtable initialization. + * + * Initialize the list supplied to be empty. + * + * @param size Size of hashtable + + * @returns Hashtable pointer +******************************************************************************/ +/* Create a new hashtable. */ +HASHTABLE_T *ht_create( size_t size ) { + + HASHTABLE_T *hashtable = NULL; + size_t i; + + if( size < 1 ) return NULL; + + /* Allocate the table itself. */ + if( ( hashtable = malloc( sizeof( HASHTABLE_T ) ) ) == NULL ) { + return NULL; + } + + /* Allocate pointers to the head nodes. */ + if( ( hashtable->table = malloc( sizeof( ENTRY_T * ) * size ) ) == NULL ) { + return NULL; + } + for( i = 0; i < size; i++ ) { + hashtable->table[i] = NULL; + } + + hashtable->size = size; + + return hashtable; +} + +/**************************************************************************//** + * Hash a string for a particular hash table. + * + * Initialize the list supplied to be empty. + * + * @param hashtable Pointer to the hashtable + * @param key String + + * @returns hashvalue +******************************************************************************/ +size_t ht_hash( HASHTABLE_T *hashtable, char *key ) +{ + + size_t hash, i; + +#ifdef HASHTABLE_USE_SIMPLE_HASH + for ( hash = i = 0; i < strlen(key); hash = hash << 8, hash += key[ i++ ] ); +#else /* Use: Jenkins' "One At a Time Hash" === Perl "Like" Hashing */ + // http://en.wikipedia.org/wiki/Jenkins_hash_function + for ( hash = i = 0; i < strlen(key); ++i ) { + hash += key[i], hash += ( hash << 10 ), hash ^= ( hash >> 6 ); + } + hash += ( hash << 3 ), hash ^= ( hash >> 11 ), hash += ( hash << 15 ); +#endif + + return hash % hashtable->size; + +} + +/**************************************************************************//** + * Create a key-value pair. + * + * @param key key string + * @param value value string + * + * @returns hashtable entry +******************************************************************************/ +ENTRY_T *ht_newpair( char *key, void *value ) +{ + ENTRY_T *newpair; + + if( ( newpair = malloc( sizeof( ENTRY_T ) ) ) == NULL ) { + return NULL; + } + + if( ( newpair->key = strdup( key ) ) == NULL ) { + return NULL; + } + + if( ( newpair->value = value ) == NULL ) { + return NULL; + } + + newpair->next = NULL; + + return newpair; +} + +/**************************************************************************//** + * Insert a key-value pair into a hash table. + * + * @param key key string + * @param value value string + * + * @returns Nothing +******************************************************************************/ +void ht_set( HASHTABLE_T *hashtable, char *key, void *value ) { + size_t bin = 0; + ENTRY_T *newpair = NULL; + ENTRY_T *next = NULL; + ENTRY_T *last = NULL; + + bin = ht_hash( hashtable, key ); + + next = hashtable->table[ bin ]; + + while( next != NULL && next->key != NULL && strcmp( key, next->key ) > 0 ) { + last = next; + next = next->next; + } + + /* There's already a pair. Let's replace that string. */ + if( next != NULL && next->key != NULL && strcmp( key, next->key ) == 0 ) { + + free( next->value ); + next->value = value ; + + /* Nope, could't find it. Time to grow a pair. */ + } else { + newpair = ht_newpair( key, value ); + + /* We're at the start of the linked list in this bin. */ + if( next == hashtable->table[ bin ] ) { + newpair->next = next; + hashtable->table[ bin ] = newpair; + + /* We're at the end of the linked list in this bin. */ + } else if ( next == NULL ) { + last->next = newpair; + + /* We're in the middle of the list. */ + } else { + newpair->next = next; + last->next = newpair; + } + } +} + +/**************************************************************************//** + * Retrieve a key-value pair from a hash table. + * + * @param key key string + * + * @returns value string +******************************************************************************/ +void *ht_get( HASHTABLE_T *hashtable, char *key ) { + size_t bin = 0; + ENTRY_T *pair; + + bin = ht_hash( hashtable, key ); + + /* Step through the bin, looking for our value. */ + pair = hashtable->table[ bin ]; + while( pair != NULL && pair->key != NULL && strcmp( key, pair->key ) > 0 ) { + pair = pair->next; + } + + /* Did we actually find anything? */ + if( pair == NULL || pair->key == NULL || strcmp( key, pair->key ) != 0 ) { + return NULL; + + } else { + return pair->value; + } + +} + +/* +int main( int argc, char **argv ) { + + HASHTABLE_T *hashtable = ht_create( 65536 ); + + ht_set( hashtable, "key1", "inky" ); + ht_set( hashtable, "key2", "pinky" ); + ht_set( hashtable, "key3", "blinky" ); + ht_set( hashtable, "key4", "floyd" ); + + printf( "%s\n", ht_get( hashtable, "key1" ) ); + printf( "%s\n", ht_get( hashtable, "key2" ) ); + printf( "%s\n", ht_get( hashtable, "key3" ) ); + printf( "%s\n", ht_get( hashtable, "key4" ) ); + + return 0; +} +*/ diff --git a/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/hashtable.h b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/hashtable.h new file mode 100644 index 0000000..8be17dc --- /dev/null +++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/hashtable.h @@ -0,0 +1,97 @@ +#ifndef HASHTABLE_INCLUDED +#define HASHTABLE_INCLUDED + +/*************************************************************************//** + * + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************/ + +/**************************************************************************//** + * @file + * A simple hashtable. + * + * @note No thread protection so you will need to use appropriate + * synchronization if use spans multiple threads. +*****************************************************************************/ + +typedef struct entry_s { + char *key; + void *value; + struct entry_s *next; +} ENTRY_T; + +/**************************************************************************//** + * Hashtable structure + *****************************************************************************/ + +typedef struct hashtable_s { + size_t size; + struct entry_s **table; +} HASHTABLE_T; + +/**************************************************************************//** + * Hashtable initialization. + * + * Initialize the list supplied to be empty. + * + * @param size Size of hashtable + + * @returns Hashtable pointer +******************************************************************************/ +/* Create a new hashtable. */ +HASHTABLE_T *ht_create( size_t size ); + +/**************************************************************************//** + * Hash a string for a particular hash table. + * + * Initialize the list supplied to be empty. + * + * @param hashtable Pointer to the hashtable + * @param key String + + * @returns hashvalue +******************************************************************************/ +size_t ht_hash( HASHTABLE_T *hashtable, char *key ); + +/**************************************************************************//** + * Create a key-value pair. + * + * @param key key string + * @param value value string + * + * @returns hashtable entry +******************************************************************************/ +ENTRY_T *ht_newpair( char *key, void *value ); + +/**************************************************************************//** + * Insert a key-value pair into a hash table. + * + * @param key key string + * @param value value string + * + * @returns Nothing +******************************************************************************/ +void ht_set( HASHTABLE_T *hashtable, char *key, void *value ); + +/**************************************************************************//** + * Retrieve a key-value pair from a hash table. + * + * @param key key string + * + * @returns value string +******************************************************************************/ +void *ht_get( HASHTABLE_T *hashtable, char *key ); + +#endif diff --git a/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/jsmn.c b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/jsmn.c new file mode 100644 index 0000000..f374a57 --- /dev/null +++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/jsmn.c @@ -0,0 +1,328 @@ +/*************************************************************************//** + * + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************/ + +#include "jsmn.h" + +/** + * Allocates a fresh unused token from the token pull. + */ +static jsmntok_t *jsmn_alloc_token(jsmn_parser *parser, + jsmntok_t *tokens, size_t num_tokens) { + jsmntok_t *tok; + if (parser->toknext >= num_tokens) { + return NULL; + } + tok = &tokens[parser->toknext++]; + tok->start = tok->end = -1; + tok->size = 0; +#ifdef JSMN_PARENT_LINKS + tok->parent = -1; +#endif + return tok; +} + +/** + * Fills token type and boundaries. + */ +static void jsmn_fill_token(jsmntok_t *token, jsmntype_t type, + int start, int end) { + token->type = type; + token->start = start; + token->end = end; + token->size = 0; +} + +/** + * Fills next available token with JSON primitive. + */ +static int jsmn_parse_primitive(jsmn_parser *parser, const char *js, + size_t len, jsmntok_t *tokens, size_t num_tokens) { + jsmntok_t *token; + int start; + + start = parser->pos; + + for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { + switch (js[parser->pos]) { +#ifndef JSMN_STRICT + /* In strict mode primitive must be followed by "," or "}" or "]" */ + case ':': +#endif + case '\t' : case '\r' : case '\n' : case ' ' : + case ',' : case ']' : case '}' : + goto found; + } + if (js[parser->pos] < 32 || js[parser->pos] >= 127) { + parser->pos = start; + return JSMN_ERROR_INVAL; + } + } +#ifdef JSMN_STRICT + /* In strict mode primitive must be followed by a comma/object/array */ + parser->pos = start; + return JSMN_ERROR_PART; +#endif + +found: + if (tokens == NULL) { + parser->pos--; + return 0; + } + token = jsmn_alloc_token(parser, tokens, num_tokens); + if (token == NULL) { + parser->pos = start; + return JSMN_ERROR_NOMEM; + } + jsmn_fill_token(token, JSMN_PRIMITIVE, start, parser->pos); +#ifdef JSMN_PARENT_LINKS + token->parent = parser->toksuper; +#endif + parser->pos--; + return 0; +} + +/** + * Fills next token with JSON string. + */ +static int jsmn_parse_string(jsmn_parser *parser, const char *js, + size_t len, jsmntok_t *tokens, size_t num_tokens) { + jsmntok_t *token; + + int start = parser->pos; + + parser->pos++; + + /* Skip starting quote */ + for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { + char c = js[parser->pos]; + + /* Quote: end of string */ + if (c == '\"') { + if (tokens == NULL) { + return 0; + } + token = jsmn_alloc_token(parser, tokens, num_tokens); + if (token == NULL) { + parser->pos = start; + return JSMN_ERROR_NOMEM; + } + jsmn_fill_token(token, JSMN_STRING, start+1, parser->pos); +#ifdef JSMN_PARENT_LINKS + token->parent = parser->toksuper; +#endif + return 0; + } + + /* Backslash: Quoted symbol expected */ + if (c == '\\' && parser->pos + 1 < len) { + int i; + parser->pos++; + switch (js[parser->pos]) { + /* Allowed escaped symbols */ + case '\"': case '/' : case '\\' : case 'b' : + case 'f' : case 'r' : case 'n' : case 't' : + break; + /* Allows escaped symbol \uXXXX */ + case 'u': + parser->pos++; + for(i = 0; i < 4 && parser->pos < len && js[parser->pos] != '\0'; i++) { + /* If it isn't a hex character we have an error */ + if(!((js[parser->pos] >= 48 && js[parser->pos] <= 57) || /* 0-9 */ + (js[parser->pos] >= 65 && js[parser->pos] <= 70) || /* A-F */ + (js[parser->pos] >= 97 && js[parser->pos] <= 102))) { /* a-f */ + parser->pos = start; + return JSMN_ERROR_INVAL; + } + parser->pos++; + } + parser->pos--; + break; + /* Unexpected symbol */ + default: + parser->pos = start; + return JSMN_ERROR_INVAL; + } + } + } + parser->pos = start; + return JSMN_ERROR_PART; +} + +/** + * Parse JSON string and fill tokens. + */ +int jsmn_parse(jsmn_parser *parser, const char *js, size_t len, + jsmntok_t *tokens, unsigned int num_tokens) { + int r; + int i; + jsmntok_t *token; + int count = parser->toknext; + + for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { + char c; + jsmntype_t type; + + c = js[parser->pos]; + switch (c) { + case '{': case '[': + count++; + if (tokens == NULL) { + break; + } + token = jsmn_alloc_token(parser, tokens, num_tokens); + if (token == NULL) + return JSMN_ERROR_NOMEM; + if (parser->toksuper != -1) { + tokens[parser->toksuper].size++; +#ifdef JSMN_PARENT_LINKS + token->parent = parser->toksuper; +#endif + } + token->type = (c == '{' ? JSMN_OBJECT : JSMN_ARRAY); + token->start = parser->pos; + parser->toksuper = parser->toknext - 1; + break; + case '}': case ']': + if (tokens == NULL) + break; + type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY); +#ifdef JSMN_PARENT_LINKS + if (parser->toknext < 1) { + return JSMN_ERROR_INVAL; + } + token = &tokens[parser->toknext - 1]; + for (;;) { + if (token->start != -1 && token->end == -1) { + if (token->type != type) { + return JSMN_ERROR_INVAL; + } + token->end = parser->pos + 1; + parser->toksuper = token->parent; + break; + } + if (token->parent == -1) { + break; + } + token = &tokens[token->parent]; + } +#else + for (i = parser->toknext - 1; i >= 0; i--) { + token = &tokens[i]; + if (token->start != -1 && token->end == -1) { + if (token->type != type) { + return JSMN_ERROR_INVAL; + } + parser->toksuper = -1; + token->end = parser->pos + 1; + break; + } + } + /* Error if unmatched closing bracket */ + if (i == -1) return JSMN_ERROR_INVAL; + for (; i >= 0; i--) { + token = &tokens[i]; + if (token->start != -1 && token->end == -1) { + parser->toksuper = i; + break; + } + } +#endif + break; + case '\"': + r = jsmn_parse_string(parser, js, len, tokens, num_tokens); + if (r < 0) return r; + count++; + if (parser->toksuper != -1 && tokens != NULL) + tokens[parser->toksuper].size++; + break; + case '\t' : case '\r' : case '\n' : case ' ': + break; + case ':': + parser->toksuper = parser->toknext - 1; + break; + case ',': + if (tokens != NULL && parser->toksuper != -1 && + tokens[parser->toksuper].type != JSMN_ARRAY && + tokens[parser->toksuper].type != JSMN_OBJECT) { +#ifdef JSMN_PARENT_LINKS + parser->toksuper = tokens[parser->toksuper].parent; +#else + for (i = parser->toknext - 1; i >= 0; i--) { + if (tokens[i].type == JSMN_ARRAY || tokens[i].type == JSMN_OBJECT) { + if (tokens[i].start != -1 && tokens[i].end == -1) { + parser->toksuper = i; + break; + } + } + } +#endif + } + break; +#ifdef JSMN_STRICT + /* In strict mode primitives are: numbers and booleans */ + case '-': case '0': case '1' : case '2': case '3' : case '4': + case '5': case '6': case '7' : case '8': case '9': + case 't': case 'f': case 'n' : + /* And they must not be keys of the object */ + if (tokens != NULL && parser->toksuper != -1) { + jsmntok_t *t = &tokens[parser->toksuper]; + if (t->type == JSMN_OBJECT || + (t->type == JSMN_STRING && t->size != 0)) { + return JSMN_ERROR_INVAL; + } + } +#else + /* In non-strict mode every unquoted value is a primitive */ + default: +#endif + r = jsmn_parse_primitive(parser, js, len, tokens, num_tokens); + if (r < 0) return r; + count++; + if (parser->toksuper != -1 && tokens != NULL) + tokens[parser->toksuper].size++; + break; + +#ifdef JSMN_STRICT + /* Unexpected char in strict mode */ + default: + return JSMN_ERROR_INVAL; +#endif + } + } + + if (tokens != NULL) { + for (i = parser->toknext - 1; i >= 0; i--) { + /* Unmatched opened object or array */ + if (tokens[i].start != -1 && tokens[i].end == -1) { + return JSMN_ERROR_PART; + } + } + } + + return count; +} + +/** + * Creates a new parser based over a given buffer with an array of tokens + * available. + */ +void jsmn_init(jsmn_parser *parser) { + parser->pos = 0; + parser->toknext = 0; + parser->toksuper = -1; +} + diff --git a/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/jsmn.h b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/jsmn.h new file mode 100644 index 0000000..4ae6d9b --- /dev/null +++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/jsmn.h @@ -0,0 +1,93 @@ +/*************************************************************************//** + * + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************/ + +#ifndef __JSMN_H_ +#define __JSMN_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * JSON type identifier. Basic types are: + * o Object + * o Array + * o String + * o Other primitive: number, boolean (true/false) or null + */ +typedef enum { + JSMN_UNDEFINED = 0, + JSMN_OBJECT = 1, + JSMN_ARRAY = 2, + JSMN_STRING = 3, + JSMN_PRIMITIVE = 4 +} jsmntype_t; + +enum jsmnerr { + /* Not enough tokens were provided */ + JSMN_ERROR_NOMEM = -1, + /* Invalid character inside JSON string */ + JSMN_ERROR_INVAL = -2, + /* The string is not a full JSON packet, more bytes expected */ + JSMN_ERROR_PART = -3 +}; + +/** + * JSON token description. + * @param type type (object, array, string etc.) + * @param start start position in JSON data string + * @param end end position in JSON data string + */ +typedef struct { + jsmntype_t type; + int start; + int end; + int size; +#ifdef JSMN_PARENT_LINKS + int parent; +#endif +} jsmntok_t; + +/** + * JSON parser. Contains an array of token blocks available. Also stores + * the string being parsed now and current position in that string + */ +typedef struct { + unsigned int pos; /* offset in the JSON string */ + unsigned int toknext; /* next token to allocate */ + int toksuper; /* superior token node, e.g parent object or array */ +} jsmn_parser; + +/** + * Create JSON parser over an array of tokens + */ +void jsmn_init(jsmn_parser *parser); + +/** + * Run JSON parser. It parses a JSON data string into and array of tokens, each describing + * a single JSON object. + */ +int jsmn_parse(jsmn_parser *parser, const char *js, size_t len, + jsmntok_t *tokens, unsigned int num_tokens); + +#ifdef __cplusplus +} +#endif + +#endif /* __JSMN_H_ */ diff --git a/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/license.md b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/license.md new file mode 100644 index 0000000..95e459a --- /dev/null +++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/license.md @@ -0,0 +1,81 @@ +# Licensing {#licensing} + +# Introduction {#lic_intro} + +This Licensing section describes licensing of IPR in the EVEL Library. + +# Licensed Software {#lic_software} + +## EVEL Library {#lic_evel} + + +Copyright © 2017 AT&T Intellectual Property. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +## libcurl {#lic_libcurl} + +The EVEL Library makes use of the the [cURL Library] +(https://curl.haxx.se/libcurl/) in order to send and receive HTTP data. + +### License + +COPYRIGHT AND PERMISSION NOTICE + +Copyright (c) 1996 - 2016, Daniel Stenberg, daniel@haxx.se, and many +contributors, see the THANKS file. + +All rights reserved. + +Permission to use, copy, modify, and distribute this software for any purpose +with or without fee is hereby granted, provided that the above copyright notice +and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN +NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of a copyright holder shall not be +used in advertising or otherwise to promote the sale, use or other dealings in +this Software without prior written authorization of the copyright holder. + +## JSMN {#lic_jsmn} + +The EVEL Library makes use of the [JSMN library](http://zserge.com/jsmn.html) +in order to decode JSON data. + +### License {#lic_jsmn_license} + +Copyright (c) 2010 Serge A. Zaitsev + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + diff --git a/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/metadata.c b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/metadata.c new file mode 100644 index 0000000..11fef1b --- /dev/null +++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/metadata.c @@ -0,0 +1,592 @@ +/*************************************************************************//** + * + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************/ +/**************************************************************************//** + * @file + * Wrap the OpenStack metadata service. + ****************************************************************************/ + +#include +#include +#include + +#include + +#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] = ""; + jsmn_parser json_parser; + jsmntok_t tokens[MAX_METADATA_TOKENS]; + int json_token_count = 0; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Initialize dummy values for the metadata - needed for test */ + /* environments. */ + /***************************************************************************/ + openstack_metadata_initialize(); + + /***************************************************************************/ + /* Get a curl handle which we'll use for accessing the metadata service. */ + /***************************************************************************/ + curl_handle = curl_easy_init(); + if (curl_handle == NULL) + { + rc = EVEL_CURL_LIBRARY_FAIL; + EVEL_ERROR("Failed to get libcurl handle"); + goto exit_label; + } + + /***************************************************************************/ + /* Prime the library to give friendly error codes. */ + /***************************************************************************/ + curl_rc = curl_easy_setopt(curl_handle, + CURLOPT_ERRORBUFFER, + curl_err_string); + if (curl_rc != CURLE_OK) + { + rc = EVEL_CURL_LIBRARY_FAIL; + EVEL_ERROR("Failed to initialize libcurl to provide friendly errors. " + "Error code=%d", curl_rc); + goto exit_label; + } + + /***************************************************************************/ + /* Set the URL for the metadata API. */ + /***************************************************************************/ + curl_rc = curl_easy_setopt(curl_handle, CURLOPT_URL, OPENSTACK_METADATA_URL); + if (curl_rc != CURLE_OK) + { + rc = EVEL_CURL_LIBRARY_FAIL; + EVEL_ERROR("Failed to initialize libcurl with the API URL. " + "Error code=%d (%s)", curl_rc, curl_err_string); + goto exit_label; + } + + /***************************************************************************/ + /* send all data to this function. */ + /***************************************************************************/ + curl_rc = curl_easy_setopt(curl_handle, + CURLOPT_WRITEFUNCTION, + evel_write_callback); + if (curl_rc != CURLE_OK) + { + rc = EVEL_CURL_LIBRARY_FAIL; + EVEL_ERROR("Failed to initialize libcurl with the write callback. " + "Error code=%d (%s)", curl_rc, curl_err_string); + goto exit_label; + } + + /***************************************************************************/ + /* some servers don't like requests that are made without a user-agent */ + /* field, so we provide one. */ + /***************************************************************************/ + curl_rc = curl_easy_setopt(curl_handle, + CURLOPT_USERAGENT, + "libcurl-agent/1.0"); + if (curl_rc != CURLE_OK) + { + rc = EVEL_CURL_LIBRARY_FAIL; + EVEL_ERROR("Failed to initialize libcurl to upload. Error code=%d (%s)", + curl_rc, curl_err_string); + goto exit_label; + } + + /***************************************************************************/ + /* Set the timeout for the operation. */ + /***************************************************************************/ + curl_rc = curl_easy_setopt(curl_handle, + CURLOPT_TIMEOUT, + OPENSTACK_METADATA_TIMEOUT); + if (curl_rc != CURLE_OK) + { + rc = EVEL_NO_METADATA; + EVEL_ERROR("Failed to initialize libcurl to set timeout. " + "Error code=%d (%s)", curl_rc, curl_err_string); + goto exit_label; + } + + /***************************************************************************/ + /* Create the memory chunk to be used for the response to the post. The */ + /* will be realloced. */ + /***************************************************************************/ + rx_chunk.memory = malloc(1); + assert(rx_chunk.memory != NULL); + rx_chunk.size = 0; + + /***************************************************************************/ + /* Point to the data to be received. */ + /***************************************************************************/ + curl_rc = curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)&rx_chunk); + if (curl_rc != CURLE_OK) + { + rc = EVEL_CURL_LIBRARY_FAIL; + EVEL_ERROR("Failed to initialize libcurl to receive metadata. " + "Error code=%d (%s)", curl_rc, curl_err_string); + goto exit_label; + } + EVEL_DEBUG("Initialized data to receive"); + + /***************************************************************************/ + /* If running in verbose mode generate more output. */ + /***************************************************************************/ + if (verbosity > 0) + { + curl_rc = curl_easy_setopt(curl_handle, CURLOPT_VERBOSE, 1L); + if (curl_rc != CURLE_OK) + { + rc = EVEL_CURL_LIBRARY_FAIL; + log_error_state("Failed to initialize libcurl to be verbose. " + "Error code=%d", curl_rc); + goto exit_label; + } + } + + /***************************************************************************/ + /* Now run off and do what you've been told! */ + /***************************************************************************/ + curl_rc = curl_easy_perform(curl_handle); + if (curl_rc != CURLE_OK) + { + rc = EVEL_CURL_LIBRARY_FAIL; + EVEL_ERROR("Failed to transfer the data from metadata service. " + "Error code=%d (%s)", curl_rc, curl_err_string); + } + else + { + /*************************************************************************/ + /* We have some metadata available, so break it out into tokens. */ + /*************************************************************************/ + EVEL_DEBUG("Received metadata size = %d", rx_chunk.size); + EVEL_INFO("Received metadata = %s", rx_chunk.memory); + jsmn_init(&json_parser); + json_token_count = jsmn_parse(&json_parser, + rx_chunk.memory, rx_chunk.size, + tokens, MAX_METADATA_TOKENS); + + /*************************************************************************/ + /* Check that we parsed some data and that the top level is as expected. */ + /*************************************************************************/ + if (json_token_count < 0 || tokens[0].type != JSMN_OBJECT) + { + rc = EVEL_BAD_METADATA; + EVEL_ERROR("Failed to parse received JSON OpenStack metadata. " + "Error code=%d", json_token_count); + goto exit_label; + } + else + { + EVEL_DEBUG("Extracted %d tokens from the JSON OpenStack metadata. ", + json_token_count); + } + + /*************************************************************************/ + /* Find the keys we want from the metadata. */ + /*************************************************************************/ + if (json_get_string(rx_chunk.memory, + tokens, + json_token_count, + "uuid", + vm_uuid) != EVEL_SUCCESS) + { + rc = EVEL_BAD_METADATA; + EVEL_ERROR("Failed to extract UUID from OpenStack metadata"); + } + else + { + EVEL_DEBUG("UUID: %s", vm_uuid); + } + if (json_get_top_level_string(rx_chunk.memory, + tokens, + json_token_count, + "name", + vm_name) != EVEL_SUCCESS) + { + rc = EVEL_BAD_METADATA; + EVEL_ERROR("Failed to extract VM Name from OpenStack metadata"); + } + else + { + EVEL_DEBUG("VM Name: %s", vm_name); + } + } + +exit_label: + + /***************************************************************************/ + /* Shut down the cURL library in a tidy manner. */ + /***************************************************************************/ + if (curl_handle != NULL) + { + curl_easy_cleanup(curl_handle); + curl_handle = NULL; + } + free(rx_chunk.memory); + + EVEL_EXIT(); + return rc; +} + +/**************************************************************************//** + * Initialize default values for vm_name and vm_uuid - for testing purposes. + *****************************************************************************/ +void openstack_metadata_initialize() +{ + strncpy(vm_uuid, + "Dummy VM UUID - No Metadata available", + MAX_METADATA_STRING); + strncpy(vm_name, + "Dummy VM name - No Metadata available", + MAX_METADATA_STRING); +} + +/**************************************************************************//** + * Get a string value from supplied JSON by matching the key. + * + * As the structure of the metadata we're looking at is pretty straightforward + * we don't do anything complex (a la XPath) to extract nested keys with the + * same leaf name, for example. Simply walk the structure until we find a + * string with the correct value. + * + * @param[in] json_string The string which contains the JSON and has already + * been parsed. + * @param[in] tokens The tokens which the JSON parser found in the JSON. + * @param[in] json_token_count How many tokens were found. + * @param[in] key The key we're looking for. + * @param[out] value The string we found at @p key. + * + * @returns Status code + * @retval EVEL_SUCCESS On success - contents of @p value updated. + * @retval EVEL_JSON_KEY_NOT_FOUND Key not found - @p value not updated. + * @retval EVEL_BAD_JSON Parser hit unexpected data - @p value not + * updated. + *****************************************************************************/ +static EVEL_ERR_CODES json_get_string(const char * json_string, + const jsmntok_t * tokens, + int json_token_count, + const char * key, + char * value) +{ + EVEL_ERR_CODES rc = EVEL_JSON_KEY_NOT_FOUND; + int token_num = 0; + int token_len = 0; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Check assumptions. */ + /***************************************************************************/ + assert(json_string != NULL); + assert(tokens != NULL); + assert(json_token_count >= 0); + assert(key != NULL); + assert(value != NULL); + + for (token_num = 0; token_num < json_token_count; token_num++) + { + switch(tokens[token_num].type) + { + case JSMN_OBJECT: + EVEL_DEBUG("Skipping object"); + break; + + case JSMN_ARRAY: + EVEL_DEBUG("Skipping array"); + break; + + case JSMN_STRING: + /***********************************************************************/ + /* This is a string, so may be what we want. Compare keys. */ + /***********************************************************************/ + if (jsoneq(json_string, &tokens[token_num], key) == 0) + { + token_len = tokens[token_num + 1].end - tokens[token_num + 1].start; + EVEL_DEBUG("Token %d len %d matches at %d to %d", token_num, + tokens[token_num + 1].start, + tokens[token_num + 1].end); + strncpy(value, json_string + tokens[token_num + 1].start, token_len); + value[token_len] = '\0'; + EVEL_DEBUG("Extracted key: \"%s\" Value: \"%s\"", key, value); + rc = EVEL_SUCCESS; + goto exit_label; + } + else + { + EVEL_DEBUG("String key did not match"); + } + + /***********************************************************************/ + /* Step over the value, whether we used it or not. */ + /***********************************************************************/ + token_num++; + break; + + case JSMN_PRIMITIVE: + EVEL_INFO("Skipping primitive"); + break; + + case JSMN_UNDEFINED: + default: + rc = EVEL_BAD_JSON_FORMAT; + EVEL_ERROR("Unexpected JSON format at token %d (%d)", + token_num, + tokens[token_num].type); + goto exit_label; + } + } + +exit_label: + EVEL_EXIT(); + return rc; +} + +/**************************************************************************//** + * Get a top-level string value from supplied JSON by matching the key. + * + * Unlike json_get_string, this only returns a value that is in the top-level + * JSON object. + * + * @param[in] json_string The string which contains the JSON and has already + * been parsed. + * @param[in] tokens The tokens which the JSON parser found in the JSON. + * @param[in] json_token_count How many tokens were found. + * @param[in] key The key we're looking for. + * @param[out] value The string we found at @p key. + * + * @returns Status code + * @retval EVEL_SUCCESS On success - contents of @p value updated. + * @retval EVEL_JSON_KEY_NOT_FOUND Key not found - @p value not updated. + * @retval EVEL_BAD_JSON Parser hit unexpected data - @p value not + * updated. + *****************************************************************************/ +static EVEL_ERR_CODES json_get_top_level_string(const char * json_string, + const jsmntok_t * tokens, + int json_token_count, + const char * key, + char * value) +{ + EVEL_ERR_CODES rc = EVEL_JSON_KEY_NOT_FOUND; + int token_num = 0; + int token_len = 0; + int bracket_count = 0; + int string_index = 0; + int increment = 0; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Check assumptions. */ + /***************************************************************************/ + assert(json_string != NULL); + assert(tokens != NULL); + assert(json_token_count >= 0); + assert(key != NULL); + assert(value != NULL); + + for (token_num = 0; token_num < json_token_count; token_num++) + { + switch(tokens[token_num].type) + { + case JSMN_OBJECT: + EVEL_DEBUG("Skipping object"); + break; + + case JSMN_ARRAY: + EVEL_DEBUG("Skipping array"); + break; + + case JSMN_STRING: + /***********************************************************************/ + /* This is a string, so may be what we want. Compare keys. */ + /***********************************************************************/ + if (jsoneq(json_string, &tokens[token_num], key) == 0) + { + /*********************************************************************/ + /* Count the difference in the number of opening and closing */ + /* brackets up to this token. This needs to be 1 for a top-level */ + /* string. Let's just hope we don't have any strings containing */ + /* brackets. */ + /*********************************************************************/ + increment = ((string_index < tokens[token_num].start) ? 1 : -1); + + while (string_index != tokens[token_num].start) + { + if (json_string[string_index] == '{') + { + bracket_count += increment; + } + else if (json_string[string_index] == '}') + { + bracket_count -= increment; + } + + string_index += increment; + } + + if (bracket_count == 1) + { + token_len = tokens[token_num + 1].end - tokens[token_num + 1].start; + EVEL_DEBUG("Token %d len %d matches at top level at %d to %d", + token_num, + tokens[token_num + 1].start, + tokens[token_num + 1].end); + strncpy(value, json_string + tokens[token_num + 1].start, token_len); + value[token_len] = '\0'; + EVEL_DEBUG("Extracted key: \"%s\" Value: \"%s\"", key, value); + rc = EVEL_SUCCESS; + goto exit_label; + } + else + { + EVEL_DEBUG("String key did match, but not at top level"); + } + } + else + { + EVEL_DEBUG("String key did not match"); + } + + /***********************************************************************/ + /* Step over the value, whether we used it or not. */ + /***********************************************************************/ + token_num++; + break; + + case JSMN_PRIMITIVE: + EVEL_INFO("Skipping primitive"); + break; + + case JSMN_UNDEFINED: + default: + rc = EVEL_BAD_JSON_FORMAT; + EVEL_ERROR("Unexpected JSON format at token %d (%d)", + token_num, + tokens[token_num].type); + goto exit_label; + } + } + +exit_label: + EVEL_EXIT(); + return rc; +} + +/**************************************************************************//** + * Compare a JSON string token with a value. + * + * @param[in] json The string which contains the JSON and has already been + * parsed. + * @param[in] tok The token which the JSON parser found in the JSON. + * @param[in] s The string we're looking for. + * + * @returns Whether the token matches the string or not. + * @retval 0 Value matches + * @retval -1 Value does not match. + *****************************************************************************/ +static int jsoneq(const char *json, const jsmntok_t *tok, const char *s) { + if (tok->type == JSMN_STRING && (int) strlen(s) == tok->end - tok->start && + strncmp(json + tok->start, s, tok->end - tok->start) == 0) { + return 0; + } + return -1; +} + +/**************************************************************************//** + * Get the VM name provided by the metadata service. + * + * @returns VM name + *****************************************************************************/ +const char *openstack_vm_name() +{ + return vm_name; +} + +/**************************************************************************//** + * Get the VM UUID provided by the metadata service. + * + * @returns VM UUID + *****************************************************************************/ +const char *openstack_vm_uuid() +{ + return vm_uuid; +} diff --git a/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/metadata.h b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/metadata.h new file mode 100644 index 0000000..1ee4409 --- /dev/null +++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/metadata.h @@ -0,0 +1,58 @@ +#ifndef METADATA_INCLUDED +#define METADATA_INCLUDED +/*************************************************************************//** + * + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************/ + +/**************************************************************************//** + * @file + * Wrap the OpenStack metadata service. + * + ****************************************************************************/ + +#include "evel.h" + +/**************************************************************************//** + * Download metadata from the OpenStack metadata service. + * + * @param verbosity Controls whether to generate debug to stdout. Zero: + * none. Non-zero: generate debug. + * @returns Status code + * @retval EVEL_SUCCESS On success + * @retval ::EVEL_ERR_CODES On failure. + *****************************************************************************/ +EVEL_ERR_CODES openstack_metadata(int verbosity); + +/**************************************************************************//** + * Initialize default values for vm_name and vm_uuid - for testing purposes. + *****************************************************************************/ +void openstack_metadata_initialize(); + +/**************************************************************************//** + * Get the VM name provided by the metadata service. + * + * @returns VM name + *****************************************************************************/ +const char *openstack_vm_name(); + +/**************************************************************************//** + * Get the VM UUID provided by the metadata service. + * + * @returns VM UUID + *****************************************************************************/ +const char *openstack_vm_uuid(); + +#endif diff --git a/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/quickstart.md b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/quickstart.md new file mode 100644 index 0000000..1c735cc --- /dev/null +++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/quickstart.md @@ -0,0 +1,445 @@ +# Quick Start Guide {#quickstart} + +# Introduction {#qs_intro} + +This Quick-Start section describes how to: + + * Install and compile the supplied library code + * Integrate an existing project to use the EVEL library + +# Installation {#qs_install} + +The library is supplied as a source-code compressed-tar file. It is +straightforward to install and build to integrate with an existing or new +development project. + +## Unpack the Source Code {#qs_unpack} + +The file should unpacked into your development environment: +``` +$ mkdir evel +$ cd evel +$ tar zxvf evel-library-package.tgz +``` +### Satisfy Dependencies {#qs_depend} + +Note that all commands in this section are based on CentOS package management +tools and you may need to substitute the appropriate tools/packages for your +distribution, for example `apt-get` for Ubuntu. + +Ensure that GCC development tools are available. + +``` +$ sudo yum install gcc +``` +Additionally, the library has a dependency on the cURL library, so you'll need +the development tools for libCurl installed. (At runtime, only the runtime +library is required, of course.) + +``` +$ sudo yum install libcurl-devel +``` +If you wish to make the project documentation, then Doxygen and Graphviz are +required. (Again, this is only in the development environment, not the runtime +environment!) + +``` +$ sudo yum install doxygen graphviz +``` + +Note that some distributions have quite old versions of Doxygen by default and +it may be necessary to install a later version to use all the features. + +If you want to build PDFs from the LaTeX you will need a texlive install. + +``` +$ sudo yum install texlive +``` + +### Test Build {#qs_build} +Make sure that the library makes cleanly: + +``` +$ cd bldjobs +$ make +Making dependency file evel_unit.d for evel_unit.c +Making dependency file evel_test_control.d for evel_test_control.c +Making dependency file evel_demo.d for evel_demo.c +Making dependency file jsmn.d for jsmn.c +Making dependency file evel_logging.d for evel_logging.c +Making dependency file evel_event_mgr.d for evel_event_mgr.c +Making dependency file evel_internal_event.d for evel_internal_event.c +Making dependency file evel_throttle.d for evel_throttle.c +Making dependency file evel_syslog.d for evel_syslog.c +Making dependency file evel_strings.d for evel_strings.c +Making dependency file evel_state_change.d for evel_state_change.c +Making dependency file evel_scaling_measurement.d for evel_scaling_measurement.c +Making dependency file evel_signaling.d for evel_signaling.c +Making dependency file evel_service.d for evel_service.c +Making dependency file evel_reporting_measurement.d for evel_reporting_measurement.c +Making dependency file evel_json_buffer.d for evel_json_buffer.c +Making dependency file evel_other.d for evel_other.c +Making dependency file evel_option.d for evel_option.c +Making dependency file evel_mobile_flow.d for evel_mobile_flow.c +Making dependency file evel_fault.d for evel_fault.c +Making dependency file evel_event.d for evel_event.c +Making dependency file double_list.d for double_list.c +Making dependency file ring_buffer.d for ring_buffer.c +Making dependency file metadata.d for metadata.c +Making dependency file evel.d for evel.c +Making evel.o from evel.c +Making metadata.o from metadata.c +Making ring_buffer.o from ring_buffer.c +Making double_list.o from double_list.c +Making evel_event.o from evel_event.c +Making evel_fault.o from evel_fault.c +Making evel_mobile_flow.o from evel_mobile_flow.c +Making evel_option.o from evel_option.c +Making evel_other.o from evel_other.c +Making evel_json_buffer.o from evel_json_buffer.c +Making evel_reporting_measurement.o from evel_reporting_measurement.c +Making evel_service.o from evel_service.c +Making evel_signaling.o from evel_signaling.c +Making evel_scaling_measurement.o from evel_scaling_measurement.c +Making evel_state_change.o from evel_state_change.c +Making evel_strings.o from evel_strings.c +Making evel_syslog.o from evel_syslog.c +Making evel_throttle.o from evel_throttle.c +Making evel_internal_event.o from evel_internal_event.c +Making evel_event_mgr.o from evel_event_mgr.c +Making evel_logging.o from evel_logging.c +Making jsmn.o from jsmn.c +Linking API Shared Library +Linking API Static Library +Making evel_demo.o from evel_demo.c +Making evel_test_control.o from evel_test_control.c +Linking EVEL demo +Making EVEL training +$ +``` +You should now be able to run the demo CLI application. Since it will want to +dynamically link to the library that you've just made, you will need to set +your `LD_LIBRARY_PATH` appropriately first. Make sure that you specify +your actual directory paths correctly in the following: + +``` +$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/centos/evel/libs/x86_64 +$ ../output/x86_64/evel_demo +evel_demo [--help] + --fqdn + --port + [--path ] + [--topic ] + [--username ] + [--password ] + [--https] + [--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 times round the main loop. Default = 1. + --cycles + + -v Generate much chattier logs. + --verbose + + -x Exclude throttling commands from demonstration. + --nothrott + +$ +``` +Assuming that all worked as expected, you are ready to start integrating with +your application. It probably makes sense to make the LD_LIBRARY_PATH change +above permanent by incorporating it into your `.bash_profile` file. + +### Project Documentation {#qs_build_docs} + +The source comes with its own documentation included. The documentation can be +built using the `docs` target in the Makefile. By default this builds HTML +and LaTeX documentation, the latter being used to prepare PDFs. + +To make the documentation: +``` +$ cd bldjobs +$ make docs +Cleaning docs... +Making Doxygen documentation +$ +``` + +There is a make target that is intended to install the documentation on a +"team server" - it will need adaptation for your team's environment - see the +`docs_install` target in the Makefile: + +``` +$ make docs_install +Cleaning docs... +Making Doxygen documentation +Copying docs to team web-server... +Enter passphrase for key '/data/home/.ssh/id_rsa': +annotated.html 100% 8088 7.9KB/s 00:00 +arrowdown.png 100% 246 0.2KB/s 00:00 +arrowright.png 100% 229 0.2KB/s 00:00 + ... +$ +``` + +# Project Integration {#qs_integrate} + +There are two key steps to the integration which have to be undertaken: + + * Initialization/Termination of the library. + * Creation & posting of individual events. + +Additionally, it may be necessary to consider changes to the EVEL library's +source code if assumptions made by the library are either not satisfied or +inconvenient. In particular: + + * If the project already uses libcurl then the global initialization of the + library should be removed from the _EVEL Library_. + * The _EVEL Library_ uses `syslog` for event logging. If the project uses a + different event logging process, then EVEL's event logging macros should be + rewritten appropriately. + +These steps are considered in the [Normal Use](@ref qs_normal_use) and +[EVEL Adaptation](@ref qs_adaptation) sections below. + +## Normal Use {#qs_normal_use} + +The _EVEL Library_ should be integrated with your project at a per-process +level: each process is an independent client of the ECOMP Vendor Event Listener +API. + +### Initialization {#qs_initialize} + +The _EVEL Library_ should be initialized before the process becomes +multi-threaded. This constraint arises from the use of libcurl which imposes +the constraint that initialization occurs before the system is multi-threaded. +This is described in more detail in the libcurl documentation for the +[curl_global_init](https://curl.haxx.se/libcurl/c/curl_global_init.html) +function. + +Initialization stores configuration of the Vendor Event Listener API's details, +such as the FQDN or IP address of the service, so the initializing process must +have either extracted this information from its configuration or have this +information "hard-wired" into the application, so that it is available at the +point the `evel_initialize()` function is called: + +```C + #include "evel.h" + ... + if (evel_initialize(api_fqdn, + api_port, + api_path, + api_topic, + api_secure, + "Alice", + "This isn't very secure!", + EVEL_SOURCE_VIRTUAL_MACHINE, + "EVEL demo client", + verbose_mode)) + { + fprintf(stderr, "Failed to initialize the EVEL library!!!"); + exit(-1); + } + ... +``` +Once initialization has occurred successfully, the application may raise events +and may also use the logging functions such as EVEL_INFO(). + +Initialization is entirely local (there is no interaction with the service) so +it is very unlikely to fail, unless the application environment is seriously +degraded. + +### Event Generation {#qs_generate} + +Generating events is a two stage process: + + 1. Firstly, the _EVEL Library_ is called to allocate an event of the correct + type. + * If this is successful, the caller is given a pointer to the event. + * All mandatory fields on the event are provided to this factory function + and are thereafter immutable. + * The application may add any necessary optional fields to the event, using + the pointer previously returned. + 2. The event is sent to the JSON API using the evel_post_event() function. + * At this point, the application relinquishes all responsibility for the + event: + * It will be posted to the JSON API, if possible. + * Whether or not the posting is successful, the memory used will be + freed. + +In practice this looks like: + +```C + #include "evel.h" + ... + + /***************************************************************************/ + /* Create a new Fault object, setting mandatory fields as we do so... */ + /***************************************************************************/ + fault = evel_new_fault("My alarm condition", + "It broke very badly", + EVEL_PRIORITY_NORMAL, + EVEL_SEVERITY_MAJOR); + if (fault != NULL) + { + /*************************************************************************/ + /* We have a Fault object - add some optional fields to it... */ + /*************************************************************************/ + evel_fault_type_set(fault, "Bad things happen..."); + evel_fault_interface_set(fault, "My Interface Card"); + evel_fault_addl_info_add(fault, "name1", "value1"); + evel_fault_addl_info_add(fault, "name2", "value2"); + + /*************************************************************************/ + /* Finally, post the Fault. In practice this will only ever fail if */ + /* local ring-buffer is full because of event overload. */ + /*************************************************************************/ + evel_rc = evel_post_event((EVENT_HEADER *)fault); + if (evel_rc != EVEL_SUCCESS) + { + EVEL_ERROR("Post failed %d (%s)", evel_rc, evel_error_string()); + } + } + ... +``` +### Event Types {#qs_event_types} + +The _EVEL Library_ supports the following types of events: + + 1. Faults + + These represent the **fault** domain in the event schema. + + 2. Measurements + + These represent the **measurementsForVfScaling** domain in the event + schema. + + 3. Reports + + This is an experimental type, designed to allow VNFs to report + application-level statistics unencumbered with platform measurements. + The formal AT&T schema has been updated to include this experimental + type as **measurementsForVfReporting**. + + 4. Mobile Flow + + These represent the **mobileFlow** domain in the event schema. + + 5. Other + + These represent the **other** domain in the event schema. + + 6. Service Events + + These represent the **serviceEvents** domain in the event schema. + + 7. Signaling + + These represent the **signaling** domain in the event schema. + + 8. State Change + + These represent the **stateChange** domain in the event schema. + + 9. Syslog + + These represent the **syslog** domain in the event schema. + +### Throttling {#qs_throttling} + +The _EVEL library_ supports the following command types as defined in the JSON API: + + 1. commandType: throttlingSpecification + + This is handled internally by the EVEL library, which stores the provided + throttling specification internally and applies it to all subsequent events. + + 2. commandType: provideThrottlingState + + This is handled internally by the EVEL library, which returns the current + throttling specification for each domain. + + 3. commandType: measurementIntervalChange + + This is handled by the EVEL library, which makes the latest measurement + interval available via the ::evel_get_measurement_interval function. + The application is responsible for checking and adhering to the latest + provided interval. + +### Termination {#qs_termination} + +Termination of the _EVEL Library_ is swift and brutal! Events in the buffer +at the time are "dropped on the floor" rather than waiting for the buffer to +deplete first. + +```C + #include "evel.h" + ... + + /***************************************************************************/ + /* Shutdown the library. */ + /***************************************************************************/ + evel_terminate(); + + ... +``` + +## EVEL Adaptation {#qs_adaptation} + +The _EVEL Library_ is relatively simple and should be easy to adapt into other +project environments. + +### LibcURL Lifecycle + +There are two circumstances where initialization of libcurl may be required: + + 1. If libcurl is used by the project already, and therefore already takes + responsibility of its initialization, then the libcurl initialization and + termination functions should be removed from evel_initialize() and + evel_terminate() respectively. + 2. If the project is unable to satisfy the constraint that libcurl + initialization takes place in a single-threaded environment at the point + that the _EVEL Library_ can be initialized (for example, if MT code is + necessary to read the configuration parameters required for + _EVEL Library_ initialization) then it may be necessary to extract the + libcurl functions and call them separately, earlier in the program's + operation. + +### Event Logging + +The _EVEL Library_ uses `syslog` for logging. If this is inappropriate then +the log_debug() and log_initialize() functions should be rewritten accordingly. + +**Note**: it would be a really bad idea to use the _EVEL Library_ itself for this +logging function. +[Turtles all the way down...](https://en.wikipedia.org/wiki/Turtles_all_the_way_down) + + \ No newline at end of file diff --git a/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/readme.md b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/readme.md new file mode 100644 index 0000000..3cf5708 --- /dev/null +++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/readme.md @@ -0,0 +1,236 @@ +# EVEL Library Overview {#mainpage} + +# Introduction + +The ECOMP Vendor Event Listener ("EVEL") library encapsulates the use of +AT&T's JSON API to the collector function within the ECOMP infrastructure. + +As such, it provides a reference implementation of the EVEL JSON API which +can either be directly as part of a project or can be used to inform the +independent implementation of an equivalent binding to the API in another +development environment. + +This section provides an overview of the library and how it is integrated +into the target application. If all you want is a set of instructions to +get you started, the @ref quickstart "Quick Start" section is for you. If +you want a more in-depth understanding of the _EVEL Library_ then this section +provides an overview and then you can read the detailed API documentation for +each function. The documentation for evel.h is a good starting point, since +that defines the public API of the _EVEL Library_. + +# Library Structure + +The API is designed to be used on multi-process platforms where each process +may be multi-threaded. Each process using this library will create an +independent HTTP client (using libcURL). Each process will have a single +thread running the HTTP client but that thread receives work on a +ring-buffer from however may threads are required to implement the function. + +**Note**: libcurl imposes a constraint that it is initialized before +the process starts multi-threaded operation. + +# Typical Usage + +The library is designed to be very straightforward to use and lightweight to +integrate into projects. The only serious external dependency is on libcURL. + +The supplied Makefile produces a single library **libevel.so** or +**libevel.a** which your application needs to be linked against. + +Each process within the application which wants to generate events needs to +call ::evel_initialize at the start of day (observing the above warning +about not being MT safe at this stage.) The initialization specifies the +details of where the API is located. Management of configuration is the +responsibility of the client. + +Once initialized, and now MT-safe, there are factory functions to produce +new events: +- Faults - ::evel_new_fault +- Measurements - ::evel_new_measurement +- Report - ::evel_new_report +- State Change - ::evel_new_state_change +- Syslog - ::evel_new_syslog +- Other - ::evel_new_other +- Mobile Flow - ::evel_new_mobile_flow + +There is also a factory function ::evel_new_mobile_gtp_flow_metrics to create +the parameter gtp_per_flow_metrics, which is then configured and passed to the +::evel_new_mobile_flow factory function. + +The event structures are initialized with mandatory fields at the point of +creation and optional fields may be added thereafter. Once set, values in +the structures are immutable. + +Once the event is prepared, it may be posted, using ::evel_post_event, at +which point the calling thread relinquishes all responsibility for the +event. It will be freed once successfully or unsuccessfully posted to the +API. If, for any reason, you change your mind and don't want to post a +created event, it must be destroyed with ::evel_free_event. + +Finally, at the end of day, the library can be terminated cleanly by calling +::evel_terminate. + +## Example Code + +The following fragment illustrates the above usage: + +```C + + if (evel_initialize(api_fqdn, + api_port, + api_path, + api_topic, + api_secure, + "Alice", + "This isn't very secure!", + EVEL_SOURCE_VIRTUAL_MACHINE, + "EVEL demo client", + verbose_mode)) + { + fprintf(stderr, "Failed to initialize the EVEL library!!!"); + exit(-1); + } + + ... + + fault = evel_new_fault("My alarm condition", + "It broke very badly", + EVEL_PRIORITY_NORMAL, + EVEL_SEVERITY_MAJOR); + if (fault != NULL) + { + evel_fault_type_set(fault, "Bad things happen..."); + evel_fault_interface_set(fault, "My Interface Card"); + evel_fault_addl_info_add(fault, "name1", "value1"); + evel_fault_addl_info_add(fault, "name2", "value2"); + evel_rc = evel_post_event((EVENT_HEADER *)fault); + if (evel_rc != EVEL_SUCCESS) + { + EVEL_ERROR("Post failed %d (%s)", evel_rc, evel_error_string()); + } + } + +``` + +The public API to the library is defined in evel.h. The internal APIs +within library are defined in separate headers (e.g. +evel_internal.h), but these should not need to be included by the code +using the library. + +# Example Application + +A simple command-line application to generate events is provided as part of +the source package (the above code fragment is taken from that application). + +The following illustrates its operation to a co-located "test-collector": +``` +$ ./evel_demo --fqdn 127.0.0.1 --port 30000 --path vendor_event_listener --topic example_vnf --verbose +./evel_demo built Feb 26 2016 18:14:48 +* About to connect() to 169.254.169.254 port 80 (#0) +* Trying 169.254.169.254... * Timeout +* connect() timed out! +* Closing connection #0 +* About to connect() to 127.0.0.1 port 30000 (#0) +* Trying 127.0.0.1... * connected +* Connected to 127.0.0.1 (127.0.0.1) port 30000 (#0) +* Server auth using Basic with user 'Alice' +> POST /vendor_event_listener/eventListener/v1/example_vnf HTTP/1.1 +Authorization: Basic QWxpY2U6VGhpcyBpc24ndCB2ZXJ5IHNlY3VyZSE= +User-Agent: libcurl-agent/1.0 +Host: 127.0.0.1:30000 +Accept: */* +Content-type: application/json +Content-Length: 510 + +* HTTP 1.0, assume close after body +< HTTP/1.0 204 No Content +< Date: Fri, 04 Mar 2016 15:37:22 GMT +< Server: WSGIServer/0.1 Python/2.6.6 +< +* Closing connection #0 +* About to connect() to 127.0.0.1 port 30000 (#0) +* Trying 127.0.0.1... * connected +* Connected to 127.0.0.1 (127.0.0.1) port 30000 (#0) +* Server auth using Basic with user 'Alice' +> POST /vendor_event_listener/eventListener/v1/example_vnf HTTP/1.1 +Authorization: Basic QWxpY2U6VGhpcyBpc24ndCB2ZXJ5IHNlY3VyZSE= +User-Agent: libcurl-agent/1.0 +Host: 127.0.0.1:30000 +Accept: */* +Content-type: application/json +Content-Length: 865 + +* HTTP 1.0, assume close after body +< HTTP/1.0 204 No Content +< Date: Fri, 04 Mar 2016 15:37:22 GMT +< Server: WSGIServer/0.1 Python/2.6.6 +< +* Closing connection #0 +* About to connect() to 127.0.0.1 port 30000 (#0) +* Trying 127.0.0.1... * connected +* Connected to 127.0.0.1 (127.0.0.1) port 30000 (#0) +* Server auth using Basic with user 'Alice' +> POST /vendor_event_listener/eventListener/v1/example_vnf HTTP/1.1 +Authorization: Basic QWxpY2U6VGhpcyBpc24ndCB2ZXJ5IHNlY3VyZSE= +User-Agent: libcurl-agent/1.0 +Host: 127.0.0.1:30000 +Accept: */* +Content-type: application/json +Content-Length: 2325 + +* HTTP 1.0, assume close after body +< HTTP/1.0 204 No Content +< Date: Fri, 04 Mar 2016 15:37:22 GMT +< Server: WSGIServer/0.1 Python/2.6.6 +< +* Closing connection #0 +^C + +Interrupted - quitting! +$ +``` + +# Restrictions and Limitations + +## Constraint Validation + +The _EVEL Library_ has been designed to be production-safe code with the +emphasis at this stage being in correctness of operation rather than +raw performance. + +The API tries to check as much information as possible to avoid misuse and +will **assert()** if constraints are not satisfied. This is likely to lead +to the rapid discovery of coding errors by programmers, but does mean that +the application can fail abruptly if the library is misused in any way. + +## Performance + +The default Makefile avoids aggressive optimizations so that any core-files +are easy to interpret. Production code should use greater optimization +levels. + +As described above, the HTTP client is single threaded and will run all +transactions synchronously. As transactions are serialized, a client that +generates a lot of events will be paced by the round-trip time. + +It would be a straightforward enhancement to use the multi-thread API into +libcurl and use a pool of client threads to run transactions in parallel if +this ever became a bottleneck. + +## Logging + +The initialization of the library includes the log verbosity. The verbose +operation makes the library very chatty so syslog may get rather clogged +with detailed diagnostics. It is possible to configure syslog to put these +events into a separate file. A trivial syslog.conf file would be: + +``` + +# Log all user messages so debug information is captured. + +user.* /var/log/debug +``` + +If verbose logging is enabled, the cURL library will generate information +about the HTTP operations on **stdout**. + diff --git a/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/ring_buffer.c b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/ring_buffer.c new file mode 100644 index 0000000..8080e02 --- /dev/null +++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/ring_buffer.c @@ -0,0 +1,192 @@ +/*************************************************************************//** + * + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************/ +/**************************************************************************//** + * @file + * A ring buffer with multi-threaded synchronization. + * + ****************************************************************************/ + +#include +#include + +#include "ring_buffer.h" +#include "evel.h" + +/**************************************************************************//** + * Ring buffer initialization. + * + * Initialize the buffer supplied to the specified size. + * + * @param buffer Pointer to the ring-buffer to be initialized. + * @param size How many elements to be stored in the ring-buffer. + * + * @returns Nothing +******************************************************************************/ +void ring_buffer_initialize(ring_buffer * buffer, int size) +{ + int pthread_rc = 0; + + EVEL_ENTER(); + + /***************************************************************************/ + /* Check assumptions. */ + /***************************************************************************/ + assert(buffer != NULL); + assert(size > 0); + + /***************************************************************************/ + /* Initialize the synchronization objects. */ + /***************************************************************************/ + pthread_rc = pthread_mutex_init(&buffer->ring_mutex, NULL); + assert(pthread_rc == 0); + pthread_rc = pthread_cond_init(&buffer->ring_cv, NULL); + assert(pthread_rc == 0); + + /***************************************************************************/ + /* Allocate the ring buffer itself. */ + /***************************************************************************/ + buffer->ring = malloc(size * sizeof(void *)); + assert(buffer->ring != NULL); + + /***************************************************************************/ + /* Initialize the ring as empty. */ + /***************************************************************************/ + buffer->next_write = 0; + buffer->next_read = 0; + buffer->size = size; + + EVEL_EXIT(); +} + +/**************************************************************************//** + * Read an element from a ring_buffer. + * + * Reads an element from the ring_buffer, advancing the next-read position. + * Operation is synchronized and therefore MT-safe. Blocks if no data is + * available. + * + * @param buffer Pointer to the ring-buffer to be read. + * + * @returns Pointer to the element read from the buffer. +******************************************************************************/ +void * ring_buffer_read(ring_buffer * buffer) +{ + void *msg = NULL; + EVEL_DEBUG("RBR: Ring buffer read"); + + pthread_mutex_lock(&buffer->ring_mutex); + while (1) + { + EVEL_DEBUG("RBR: got lock. NR=%d NW=%d", + buffer->next_read, + buffer->next_write); + if(buffer->next_read != buffer->next_write) + { + EVEL_DEBUG("RBR: buffer has item available"); + msg = (buffer->ring)[buffer->next_read]; + buffer->ring[buffer->next_read] = NULL; + buffer->next_read = (buffer->next_read + 1) % buffer->size; + EVEL_DEBUG("RBR: next read location is %d", buffer->next_read); + pthread_mutex_unlock(&buffer->ring_mutex); + break; + } + else + { + EVEL_DEBUG("RBR: Waiting for condition variable"); + pthread_cond_wait(&buffer->ring_cv, &buffer->ring_mutex); + EVEL_DEBUG("RBR: Condition variable wait completed"); + } + } + EVEL_DEBUG("RBR: Ring buffer read returning data at %lp", msg); + return msg; +} + +/**************************************************************************//** + * Write an element into a ring_buffer. + * + * Writes an element into the ring_buffer, advancing the next-write position. + * Operation is synchronized and therefore MT-safe. Fails if the buffer is + * full without blocking. + * + * @param buffer Pointer to the ring-buffer to be written. + * @param msg Pointer to data to be stored in the ring_buffer. + * + * @returns Number of items written. + * @retval 1 The data was written successfully. + * @retval 0 The ring_buffer was full so no data written. +******************************************************************************/ +int ring_buffer_write(ring_buffer * buffer, void * msg) +{ + int item_count = 0; + int items_written = 0; + EVEL_DEBUG("RBW: Ring Buffer Write message at %lp", msg); + + pthread_mutex_lock(&buffer->ring_mutex); + EVEL_DEBUG("RBW: got lock. NR=%d NW=%d SZ=%d", + buffer->next_read, + buffer->next_write, + buffer->size); + + item_count = (buffer->next_write - buffer->next_read) % buffer->size; + if (item_count < 0) + { + item_count += buffer->size; + } + if (item_count < buffer->size - 1) + { + EVEL_DEBUG("RBW: %d items in buffer", item_count); + buffer->ring[buffer->next_write] = msg; + buffer->next_write = (buffer->next_write + 1) % buffer->size; + EVEL_DEBUG("RBW: next write location is %d", buffer->next_write); + items_written = 1; + } + else + { + EVEL_ERROR("RBW: ring buffer full - unable to write event"); + } + + pthread_mutex_unlock(&buffer->ring_mutex); + EVEL_DEBUG("RBW: released lock"); + pthread_cond_signal(&buffer->ring_cv); + + return items_written; +} + +/**************************************************************************//** + * Tests whether there is data in the ring_buffer. + * + * Tests whether there is currently data in the ring_buffer without blocking. + * + * @param buffer Pointer to the ring-buffer to be tested. + * + * @returns Whether there is data in the ring_buffer. + * @retval 0 There isn't any data in the ring_buffer. + * @retval 1 There is data in the ring_buffer. +******************************************************************************/ +int ring_buffer_is_empty(ring_buffer * buffer) +{ + int is_empty = 0; + EVEL_DEBUG("RBE: Ring empty check"); + + pthread_mutex_lock(&buffer->ring_mutex); + is_empty = (buffer->next_read == buffer->next_write); + pthread_mutex_unlock(&buffer->ring_mutex); + + EVEL_DEBUG("RBE: Ring state= %d", is_empty); + return is_empty; +} + diff --git a/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/ring_buffer.h b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/ring_buffer.h new file mode 100644 index 0000000..1236b78 --- /dev/null +++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_library/ring_buffer.h @@ -0,0 +1,96 @@ +/*************************************************************************//** + * + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************/ + +#ifndef RING_BUFFER_INCLUDED +#define RING_BUFFER_INCLUDED + +/**************************************************************************//** + * @file + * Ring buffer to handle message requests. + * + ****************************************************************************/ + +#include + +/**************************************************************************//** + * Ring buffer structure. + *****************************************************************************/ +typedef struct ring_buffer +{ + int size; + int next_write; + int next_read; + void ** ring; + pthread_cond_t ring_cv; + pthread_mutex_t ring_mutex; +} ring_buffer; + +/**************************************************************************//** + * Ring buffer initialization. + * + * Initialize the buffer supplied to the specified size. + * + * @param buffer Pointer to the ring-buffer to be initialized. + * @param size How many elements to be stored in the ring-buffer. + * + * @returns Nothing +******************************************************************************/ +void ring_buffer_initialize(ring_buffer * buffer, int size); + +/**************************************************************************//** + * Read an element from a ring_buffer. + * + * Reads an element from the ring_buffer, advancing the next-read position. + * Operation is synchronized and therefore MT-safe. Blocks if no data is + * available. + * + * @param buffer Pointer to the ring-buffer to be read. + * + * @returns Pointer to the element read from the buffer. +******************************************************************************/ +void * ring_buffer_read(ring_buffer * buffer); + +/**************************************************************************//** + * Write an element into a ring_buffer. + * + * Writes an element into the ring_buffer, advancing the next-write position. + * Operation is synchronized and therefore MT-safe. Fails if the buffer is + * full without blocking. + * + * @param buffer Pointer to the ring-buffer to be written. + * @param msg Pointer to data to be stored in the ring_buffer. + * + * @returns Number of items written. + * @retval 1 The data was written successfully. + * @retval 0 The ring_buffer was full so no data written. +******************************************************************************/ +int ring_buffer_write(ring_buffer * buffer, void * msg); + +/**************************************************************************//** + * Tests whether there is data in the ring_buffer. + * + * Tests whether there is currently data in the ring_buffer without blocking. + * + * @param buffer Pointer to the ring-buffer to be tested. + * + * @returns Whether there is data in the ring_buffer. + * @retval 0 There isn't any data in the ring_buffer. + * @retval 1 There is data in the ring_buffer. +******************************************************************************/ +int ring_buffer_is_empty(ring_buffer * buffer); + +#endif diff --git a/veslibrary/ves_clibrary/evel/evel-library/code/evel_unit/evel_unit.c b/veslibrary/ves_clibrary/evel/evel-library/code/evel_unit/evel_unit.c new file mode 100644 index 0000000..f52dc27 --- /dev/null +++ b/veslibrary/ves_clibrary/evel/evel-library/code/evel_unit/evel_unit.c @@ -0,0 +1,3484 @@ +/*************************************************************************//** + * + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************/ +/**************************************************************************//** + * @file + * Unit tests for JSON encoding and throttling. + * + * This software is intended to show the essential elements of the library's + * use. + * + ****************************************************************************/ + +#include +#include +#include +#include +#include + +#include "evel.h" +#include "evel_internal.h" +#include "evel_throttle.h" +#include "metadata.h" + +typedef enum { + SERVICE_NONE, + SERVICE_CODEC, + SERVICE_TRANSCODING, + SERVICE_RTCP, + SERVICE_EOC_VQM, + SERVICE_MARKER +} SERVICE_TEST; + +/*****************************************************************************/ +/* Local prototypes. */ +/*****************************************************************************/ +static void test_encode_heartbeat(); +static void test_encode_header_overrides(); +static void test_encode_fault(); +static void test_encode_fault_with_escaping(); +static void test_encode_measurement(); +static void test_encode_mobile_mand(); +static void test_encode_mobile_opts(); +static void test_encode_other(); +static void test_encode_report(); +static void test_encode_service(); +static void test_encode_service_subset(const SERVICE_TEST service_test); +static void test_encode_signaling(); +static void test_encode_state_change(); +static void test_encode_syslog(); +static void test_json_response_junk(); +static void test_json_provide_throttle_state(); +static void test_json_measurement_interval(); +static void test_json_throttle_spec_field(); +static void test_json_throttle_spec_nv_pair(); +static void test_json_throttle_spec_two_domains(); +static void test_json_throttle_spec_bad_command_type(); +static void test_encode_fault_throttled(); +static void test_encode_measurement_throttled(); +static void test_encode_mobile_throttled(); +static void test_encode_other_throttled(); +static void test_encode_report_throttled(); +static void test_encode_service_throttled(); +static void test_encode_signaling_throttled(); +static void test_encode_state_change_throttled(); +static void test_encode_syslog_throttled(); +static void compare_strings(char * expected, + char * actual, + int max_size, + char * description); + +/**************************************************************************//** + * Main function. + * + * Runs all unit test cases, and fails hard on the first failure. + * + * @param[in] argc Argument count. + * @param[in] argv Argument vector - for usage see usage_text. + *****************************************************************************/ +int main(int argc, char ** argv) +{ + assert(argc >= 0); + assert(argv != NULL); + + /***************************************************************************/ + /* Fix our timezone to UTC. */ + /***************************************************************************/ + putenv("TZ=UTC"); + + /***************************************************************************/ + /* Initialize metadata. */ + /***************************************************************************/ + openstack_metadata_initialize(); + + /***************************************************************************/ + /* Minimal initialisation to exercise the encoders. */ + /***************************************************************************/ + functional_role = "UNIT TEST"; + log_initialize(EVEL_LOG_DEBUG, "EVEL"); + + /***************************************************************************/ + /* Test each encoder. */ + /***************************************************************************/ + test_encode_heartbeat(); + test_encode_header_overrides(); + test_encode_fault(); + test_encode_measurement(); + test_encode_mobile_mand(); + test_encode_mobile_opts(); + test_encode_other(); + test_encode_report(); + test_encode_service(); + test_encode_signaling(); + test_encode_state_change(); + test_encode_syslog(); + + /***************************************************************************/ + /* Test JSON Throttle. */ + /***************************************************************************/ + test_json_response_junk(); + test_json_provide_throttle_state(); + test_json_measurement_interval(); + test_json_throttle_spec_field(); + test_json_throttle_spec_nv_pair(); + test_json_throttle_spec_two_domains(); + test_json_throttle_spec_bad_command_type(); + + /***************************************************************************/ + /* Test each encoder with throttling applied. */ + /***************************************************************************/ + test_encode_fault_throttled(); + test_encode_measurement_throttled(); + test_encode_mobile_throttled(); + test_encode_other_throttled(); + test_encode_report_throttled(); + test_encode_service_throttled(); + test_encode_signaling_throttled(); + test_encode_state_change_throttled(); + test_encode_syslog_throttled(); + + /***************************************************************************/ + /* Test character escaping. */ + /***************************************************************************/ + test_encode_fault_with_escaping(); + + printf ("\nAll Tests Passed\n"); + + return 0; +} + +/*****************************************************************************/ +/* We link with this gettimeofday so that we get a fixed result */ +/*****************************************************************************/ +int gettimeofday(struct timeval *tv, + struct timezone *tz __attribute__((unused))) +{ + tv->tv_sec = 1; + tv->tv_usec = 2; + return 0; +} + +void test_encode_heartbeat() +{ + char * expected = + "{\"event\": {" + "\"commonEventHeader\": {" + "\"domain\": \"heartbeat\", " + "\"eventId\": \"121\", " + "\"functionalRole\": \"UNIT TEST\", " + "\"lastEpochMicrosec\": 1000002, " + "\"priority\": \"Normal\", " + "\"reportingEntityName\": \"Dummy VM name - No Metadata available\", " + "\"sequence\": 121, " + "\"sourceName\": \"Dummy VM name - No Metadata available\", " + "\"startEpochMicrosec\": 1000002, " + "\"version\": 1.2, " + "\"eventType\": \"Autonomous heartbeat\", " + "\"reportingEntityId\": \"Dummy VM UUID - No Metadata available\", " + "\"sourceId\": \"Dummy VM UUID - No Metadata available\"" + "}}}"; + + size_t json_size = 0; + char json_body[EVEL_MAX_JSON_BODY]; + + /***************************************************************************/ + /* Test the VM name/uuid once. */ + /***************************************************************************/ + evel_set_next_event_sequence(121); + + EVENT_HEADER * heartbeat = evel_new_heartbeat(); + assert(heartbeat != NULL); + + json_size = evel_json_encode_event( + json_body, EVEL_MAX_JSON_BODY, (EVENT_HEADER *) heartbeat); + compare_strings(expected, json_body, EVEL_MAX_JSON_BODY, "Heartbeat"); + assert((json_size == strlen(json_body)) && "Bad size returned"); + + evel_free_event(heartbeat); +} + +void test_encode_header_overrides() +{ + char * expected = + "{\"event\": {" + "\"commonEventHeader\": {" + "\"domain\": \"heartbeat\", " + "\"eventId\": \"121\", " + "\"functionalRole\": \"UNIT TEST\", " + "\"lastEpochMicrosec\": 1000, " + "\"priority\": \"Normal\", " + "\"reportingEntityName\": \"entity_name_override\", " + "\"sequence\": 121, " + "\"sourceName\": \"Dummy VM name - No Metadata available\", " + "\"startEpochMicrosec\": 1001, " + "\"version\": 1.2, " + "\"eventType\": \"Autonomous heartbeat\", " + "\"reportingEntityId\": \"entity_id_override\", " + "\"sourceId\": \"Dummy VM UUID - No Metadata available\"" + "}}}"; + + size_t json_size = 0; + char json_body[EVEL_MAX_JSON_BODY]; + + /***************************************************************************/ + /* Test the VM name/uuid once. */ + /***************************************************************************/ + evel_set_next_event_sequence(121); + + EVENT_HEADER * heartbeat = evel_new_heartbeat(); + assert(heartbeat != NULL); + + evel_start_epoch_set(heartbeat, 1001); + evel_last_epoch_set(heartbeat, 1000); + evel_reporting_entity_name_set(heartbeat, "entity_name_override"); + evel_reporting_entity_id_set(heartbeat, "entity_id_override"); + + json_size = evel_json_encode_event( + json_body, EVEL_MAX_JSON_BODY, (EVENT_HEADER *) heartbeat); + compare_strings(expected, json_body, EVEL_MAX_JSON_BODY, "Heartbeat"); + assert((json_size == strlen(json_body)) && "Bad size returned"); + + evel_free_event(heartbeat); +} + +void test_encode_fault() +{ + char * expected = + "{\"event\": {" + "\"commonEventHeader\": {" + "\"domain\": \"fault\", " + "\"eventId\": \"122\", " + "\"functionalRole\": \"UNIT TEST\", " + "\"lastEpochMicrosec\": 1000002, " + "\"priority\": \"Normal\", " + "\"reportingEntityName\": \"Dummy VM name - No Metadata available\", " + "\"sequence\": 122, " + "\"sourceName\": \"Dummy VM name - No Metadata available\", " + "\"startEpochMicrosec\": 1000002, " + "\"version\": 1.2, " + "\"eventType\": \"Bad things happen...\", " + "\"reportingEntityId\": \"Dummy VM UUID - No Metadata available\", " + "\"sourceId\": \"Dummy VM UUID - No Metadata available\"" + "}, " + "\"faultFields\": {" + "\"alarmCondition\": \"My alarm condition\", " + "\"eventSeverity\": \"MAJOR\", " + "\"eventSourceType\": \"other\", " + "\"specificProblem\": \"It broke very badly\", " + "\"eventCategory\": \"link\", " + "\"vfStatus\": \"Active\", " + "\"faultFieldsVersion\": 1.1, " + "\"alarmAdditionalInformation\": [" + "{\"name\": \"name1\", " + "\"value\": \"value1\"}, " + "{\"name\": \"name2\", " + "\"value\": \"value2\"}], " + "\"alarmInterfaceA\": \"My Interface Card\"" + "}}}"; + + size_t json_size = 0; + char json_body[EVEL_MAX_JSON_BODY]; + evel_set_next_event_sequence(122); + EVENT_FAULT * fault = evel_new_fault("My alarm condition", + "It broke very badly", + EVEL_PRIORITY_NORMAL, + EVEL_SEVERITY_MAJOR, + EVEL_SOURCE_HOST, + EVEL_VF_STATUS_PREP_TERMINATE); + assert(fault != NULL); + evel_fault_type_set(fault, "Bad things happen..."); + evel_fault_interface_set(fault, "My Interface Card"); + evel_fault_addl_info_add(fault, "name1", "value1"); + evel_fault_addl_info_add(fault, "name2", "value2"); + + json_size = evel_json_encode_event( + json_body, EVEL_MAX_JSON_BODY, (EVENT_HEADER *) fault); + compare_strings(expected, json_body, EVEL_MAX_JSON_BODY, "Fault"); + assert((json_size == strlen(json_body)) && "Bad size returned"); + + evel_free_event(fault); +} + +void test_encode_measurement() +{ + char * expected = + "{\"event\": " + "{\"commonEventHeader\": {" + "\"domain\": \"measurementsForVfScaling\", " + "\"eventId\": \"123\", " + "\"functionalRole\": \"UNIT TEST\", " + "\"lastEpochMicrosec\": 3000, " + "\"priority\": \"Normal\", " + "\"reportingEntityName\": \"entity_name\", " + "\"sequence\": 123, " + "\"sourceName\": \"Dummy VM name - No Metadata available\", " + "\"startEpochMicrosec\": 2000, " + "\"version\": 1.2, " + "\"eventType\": \"Perf management...\", " + "\"reportingEntityId\": \"entity_id\", " + "\"sourceId\": \"Dummy VM UUID - No Metadata available\"" + "}, " + "\"measurementsForVfScalingFields\": " + "{" + "\"measurementInterval\": 5.500000, " + "\"concurrentSessions\": 1, " + "\"configuredEntities\": 2, " + "\"cpuUsageArray\": [" + "{\"cpuIdentifier\": \"cpu1\", " + "\"percentUsage\": 11.110000}, " + "{\"cpuIdentifier\": \"cpu2\", " + "\"percentUsage\": 22.220000}], " + "\"filesystemUsageArray\": [" + "{\"blockConfigured\": 100.110000, " + "\"blockIops\": 33, " + "\"blockUsed\": 100.220000, " + "\"ephemeralConfigured\": 100.110000, " + "\"ephemeralIops\": 44, " + "\"ephemeralUsed\": 200.220000, " + "\"filesystemName\": \"00-11-22\"}, " + "{\"blockConfigured\": 300.110000, " + "\"blockIops\": 55, " + "\"blockUsed\": 300.220000, " + "\"ephemeralConfigured\": 300.110000, " + "\"ephemeralIops\": 66, " + "\"ephemeralUsed\": 400.220000, " + "\"filesystemName\": \"33-44-55\"}], " + "\"latencyDistribution\": [" + "{\"countsInTheBucket\": 20}, " + "{\"lowEndOfLatencyBucket\": 10.000000, " + "\"highEndOfLatencyBucket\": 20.000000, " + "\"countsInTheBucket\": 30}], " + "\"meanRequestLatency\": 4.400000, " + "\"memoryConfigured\": 6.600000, " + "\"memoryUsed\": 3.300000, " + "\"requestRate\": 7, " + "\"vNicUsageArray\": [" + "{" + "\"bytesIn\": 3, " + "\"bytesOut\": 4, " + "\"packetsIn\": 100, " + "\"packetsOut\": 200, " + "\"vNicIdentifier\": \"eth0\"" + "}, " + "{" + "\"bytesIn\": 13, " + "\"bytesOut\": 14, " + "\"packetsIn\": 110, " + "\"packetsOut\": 240, " + "\"vNicIdentifier\": \"eth1\", " + "\"broadcastPacketsIn\": 11, " + "\"broadcastPacketsOut\": 12, " + "\"multicastPacketsIn\": 15, " + "\"multicastPacketsOut\": 16, " + "\"unicastPacketsIn\": 17, " + "\"unicastPacketsOut\": 18" + "}" + "], " + "\"aggregateCpuUsage\": 8.800000, " + "\"numberOfMediaPortsInUse\": 1234, " + "\"vnfcScalingMetric\": 1234.567800, " + "\"errors\": {" + "\"receiveDiscards\": 1, " + "\"receiveErrors\": 0, " + "\"transmitDiscards\": 2, " + "\"transmitErrors\": 1}, " + "\"featureUsageArray\": [" + "{\"featureIdentifier\": \"FeatureA\", " + "\"featureUtilization\": 123}, " + "{\"featureIdentifier\": \"FeatureB\", " + "\"featureUtilization\": 567}], " + "\"codecUsageArray\": [" + "{\"codecIdentifier\": \"G711a\", " + "\"numberInUse\": 91}, " + "{\"codecIdentifier\": \"G729ab\", " + "\"numberInUse\": 92}], " + "\"additionalMeasurements\": [" + "{\"name\": \"Group1\", " + "\"measurements\": [" + "{\"name\": \"Name1\", " + "\"value\": \"Value1\"}]}, " + "{\"name\": \"Group2\", " + "\"measurements\": [" + "{\"name\": \"Name1\", " + "\"value\": \"Value1\"}, " + "{\"name\": \"Name2\", " + "\"value\": \"Value2\"}]}], " + "\"measurementsForVfScalingVersion\": 1.1}}}"; + + size_t json_size = 0; + char json_body[EVEL_MAX_JSON_BODY]; + EVENT_MEASUREMENT * measurement = NULL; + MEASUREMENT_LATENCY_BUCKET * bucket = NULL; + MEASUREMENT_VNIC_PERFORMANCE * vnic_use = NULL; + MEASUREMENT_CPU_USE *cpu_use; + + /***************************************************************************/ + /* Measurement. */ + /***************************************************************************/ + evel_set_next_event_sequence(123); + measurement = evel_new_measurement(5.5); + assert(measurement != NULL); + evel_measurement_type_set(measurement, "Perf management..."); + evel_measurement_conc_sess_set(measurement, 1); + evel_measurement_cfg_ents_set(measurement, 2); + evel_measurement_mean_req_lat_set(measurement, 4.4); + evel_measurement_request_rate_set(measurement, 7); + + cpu_use = evel_measurement_new_cpu_use_add(measurement, "cpu1", 11.11); + evel_measurement_cpu_use_idle_set(cpu_use,22.22); + evel_measurement_cpu_use_interrupt_set(cpu_use,33.33); + evel_measurement_cpu_use_nice_set(cpu_use,44.44); + evel_measurement_cpu_use_softirq_set(cpu_use,55.55); + evel_measurement_cpu_use_steal_set(cpu_use,66.66); + evel_measurement_cpu_use_system_set(cpu_use,77.77); + evel_measurement_cpu_use_usageuser_set(cpu_use,88.88); + evel_measurement_cpu_use_wait_set(cpu_use,99.99); + + cpu_use = evel_measurement_new_cpu_use_add(measurement, "cpu2", 22.22); + evel_measurement_cpu_use_idle_set(cpu_use,12.22); + evel_measurement_cpu_use_interrupt_set(cpu_use,33.33); + evel_measurement_cpu_use_nice_set(cpu_use,44.44); + evel_measurement_cpu_use_softirq_set(cpu_use,55.55); + evel_measurement_cpu_use_steal_set(cpu_use,66.66); + evel_measurement_cpu_use_system_set(cpu_use,77.77); + evel_measurement_cpu_use_usageuser_set(cpu_use,88.88); + evel_measurement_cpu_use_wait_set(cpu_use,19.99); + + + evel_measurement_fsys_use_add(measurement,"00-11-22",100.11, 100.22, 33, + 200.11, 200.22, 44); + evel_measurement_fsys_use_add(measurement,"33-44-55",300.11, 300.22, 55, + 400.11, 400.22, 66); + evel_start_epoch_set(&measurement->header, 2000); + evel_last_epoch_set(&measurement->header, 3000); + evel_reporting_entity_name_set(&measurement->header, "entity_name"); + evel_reporting_entity_id_set(&measurement->header, "entity_id"); + + /***************************************************************************/ + /* Latency Bucket with no optional parameters. */ + /***************************************************************************/ + bucket = evel_new_meas_latency_bucket(20); + evel_meas_latency_bucket_add(measurement, bucket); + + /***************************************************************************/ + /* Latency Bucket with all optional parameters. */ + /***************************************************************************/ + bucket = evel_new_meas_latency_bucket(30); + evel_meas_latency_bucket_low_end_set(bucket, 10.0); + evel_meas_latency_bucket_high_end_set(bucket, 20.0); + evel_meas_latency_bucket_add(measurement, bucket); + + /***************************************************************************/ + /* vNIC Use with no optional parameters. */ + /***************************************************************************/ + vnic_use = evel_new_measurement_vnic_use("eth0", 100, 200, 3, 4); + evel_meas_vnic_use_add(measurement, vnic_use); + + /***************************************************************************/ + /* vNIC Use with all optional parameters. */ + /***************************************************************************/ + vnic_use = evel_new_measurement_vnic_use("eth1", 110, 240, 13, 14); + evel_vnic_use_bcast_pkt_in_set(vnic_use, 11); + evel_vnic_use_bcast_pkt_out_set(vnic_use, 12); + evel_vnic_use_mcast_pkt_in_set(vnic_use, 15); + evel_vnic_use_mcast_pkt_out_set(vnic_use, 16); + evel_vnic_use_ucast_pkt_in_set(vnic_use, 17); + evel_vnic_use_ucast_pkt_out_set(vnic_use, 18); + evel_meas_vnic_use_add(measurement, vnic_use); + + evel_measurement_errors_set(measurement, 1, 0, 2, 1); + + evel_measurement_feature_use_add(measurement, "FeatureA", 123); + evel_measurement_feature_use_add(measurement, "FeatureB", 567); + + evel_measurement_codec_use_add(measurement, "G711a", 91); + evel_measurement_codec_use_add(measurement, "G729ab", 92); + + evel_measurement_media_port_use_set(measurement, 1234); + + evel_measurement_vnfc_scaling_metric_set(measurement, 1234.5678); + + evel_measurement_custom_measurement_add(measurement, + "Group1", "Name1", "Value1"); + evel_measurement_custom_measurement_add(measurement, + "Group2", "Name1", "Value1"); + evel_measurement_custom_measurement_add(measurement, + "Group2", "Name2", "Value2"); + + json_size = evel_json_encode_event( + json_body, EVEL_MAX_JSON_BODY, (EVENT_HEADER *) measurement); + compare_strings(expected, json_body, EVEL_MAX_JSON_BODY, "Measurement"); + assert((json_size == strlen(json_body)) && "Bad size returned"); + + evel_free_event(measurement); +} + +void test_encode_mobile_mand() +{ + char * expected = + "{\"event\": " + "{\"commonEventHeader\": {" + "\"domain\": \"mobileFlow\", " + "\"eventId\": \"1241\", " + "\"functionalRole\": \"UNIT TEST\", " + "\"lastEpochMicrosec\": 1000002, " + "\"priority\": \"Normal\", " + "\"reportingEntityName\": \"Dummy VM name - No Metadata available\", " + "\"sequence\": 1241, " + "\"sourceName\": \"Dummy VM name - No Metadata available\", " + "\"startEpochMicrosec\": 1000002, " + "\"version\": 1.2, " + "\"reportingEntityId\": \"Dummy VM UUID - No Metadata available\", " + "\"sourceId\": \"Dummy VM UUID - No Metadata available\"" + "}, " + "\"mobileFlowFields\": {" + "\"flowDirection\": \"Outbound\", " + "\"gtpPerFlowMetrics\": {" + "\"avgBitErrorRate\": 12.300000, " + "\"avgPacketDelayVariation\": 3.120000, " + "\"avgPacketLatency\": 100, " + "\"avgReceiveThroughput\": 2100, " + "\"avgTransmitThroughput\": 500, " + "\"flowActivationEpoch\": 1470409421, " + "\"flowActivationMicrosec\": 987, " + "\"flowDeactivationEpoch\": 1470409431, " + "\"flowDeactivationMicrosec\": 11, " + "\"flowDeactivationTime\": \"Fri, 05 Aug 2016 15:03:51 +0000\", " + "\"flowStatus\": \"Working\", " + "\"maxPacketDelayVariation\": 87, " + "\"numActivationFailures\": 3, " + "\"numBitErrors\": 17, " + "\"numBytesReceived\": 123654, " + "\"numBytesTransmitted\": 4561, " + "\"numDroppedPackets\": 0, " + "\"numL7BytesReceived\": 12, " + "\"numL7BytesTransmitted\": 10, " + "\"numLostPackets\": 1, " + "\"numOutOfOrderPackets\": 3, " + "\"numPacketErrors\": 7, " + "\"numPacketsReceivedExclRetrans\": 899, " + "\"numPacketsReceivedInclRetrans\": 901, " + "\"numPacketsTransmittedInclRetrans\": 302, " + "\"numRetries\": 6, " + "\"numTimeouts\": 2, " + "\"numTunneledL7BytesReceived\": 0, " + "\"roundTripTime\": 110, " + "\"timeToFirstByte\": 225" + "}, " + "\"ipProtocolType\": \"TCP\", " + "\"ipVersion\": \"IPv4\", " + "\"otherEndpointIpAddress\": \"2.3.4.1\", " + "\"otherEndpointPort\": 2341, " + "\"reportingEndpointIpAddr\": \"4.2.3.1\", " + "\"reportingEndpointPort\": 4321" + "}}}"; + + size_t json_size = 0; + char json_body[EVEL_MAX_JSON_BODY]; + MOBILE_GTP_PER_FLOW_METRICS * metrics = NULL; + EVENT_MOBILE_FLOW * mobile_flow = NULL; + + /***************************************************************************/ + /* Mobile. */ + /***************************************************************************/ + evel_set_next_event_sequence(1241); + + metrics = evel_new_mobile_gtp_flow_metrics(12.3, + 3.12, + 100, + 2100, + 500, + 1470409421, + 987, + 1470409431, + 11, + (time_t)1470409431, + "Working", + 87, + 3, + 17, + 123654, + 4561, + 0, + 12, + 10, + 1, + 3, + 7, + 899, + 901, + 302, + 6, + 2, + 0, + 110, + 225); + assert(metrics != NULL); + mobile_flow = evel_new_mobile_flow("Outbound", + metrics, + "TCP", + "IPv4", + "2.3.4.1", + 2341, + "4.2.3.1", + 4321); + assert(mobile_flow != NULL); + + json_size = evel_json_encode_event( + json_body, EVEL_MAX_JSON_BODY, (EVENT_HEADER *) mobile_flow); + compare_strings(expected, json_body, EVEL_MAX_JSON_BODY, "Mobile"); + assert((json_size == strlen(json_body)) && "Bad size returned"); + + evel_free_event(mobile_flow); +} + +void test_encode_mobile_opts() +{ + char * expected = + "{\"event\": " + "{\"commonEventHeader\": {" + "\"domain\": \"mobileFlow\", " + "\"eventId\": \"1242\", " + "\"functionalRole\": \"UNIT TEST\", " + "\"lastEpochMicrosec\": 1000002, " + "\"priority\": \"Normal\", " + "\"reportingEntityName\": \"Dummy VM name - No Metadata available\", " + "\"sequence\": 1242, " + "\"sourceName\": \"Dummy VM name - No Metadata available\", " + "\"startEpochMicrosec\": 1000002, " + "\"version\": 1.2, " + "\"eventType\": \"Mobile flow...\", " + "\"reportingEntityId\": \"Dummy VM UUID - No Metadata available\", " + "\"sourceId\": \"Dummy VM UUID - No Metadata available\"" + "}, " + "\"mobileFlowFields\": {" + "\"flowDirection\": \"Inbound\", " + "\"gtpPerFlowMetrics\": {" + "\"avgBitErrorRate\": 132.000100, " + "\"avgPacketDelayVariation\": 31.200000, " + "\"avgPacketLatency\": 101, " + "\"avgReceiveThroughput\": 2101, " + "\"avgTransmitThroughput\": 501, " + "\"flowActivationEpoch\": 1470409422, " + "\"flowActivationMicrosec\": 988, " + "\"flowDeactivationEpoch\": 1470409432, " + "\"flowDeactivationMicrosec\": 12, " + "\"flowDeactivationTime\": \"Fri, 05 Aug 2016 15:03:52 +0000\", " + "\"flowStatus\": \"Inactive\", " + "\"maxPacketDelayVariation\": 88, " + "\"numActivationFailures\": 4, " + "\"numBitErrors\": 18, " + "\"numBytesReceived\": 123655, " + "\"numBytesTransmitted\": 4562, " + "\"numDroppedPackets\": 1, " + "\"numL7BytesReceived\": 13, " + "\"numL7BytesTransmitted\": 11, " + "\"numLostPackets\": 2, " + "\"numOutOfOrderPackets\": 4, " + "\"numPacketErrors\": 8, " + "\"numPacketsReceivedExclRetrans\": 900, " + "\"numPacketsReceivedInclRetrans\": 902, " + "\"numPacketsTransmittedInclRetrans\": 303, " + "\"numRetries\": 7, " + "\"numTimeouts\": 3, " + "\"numTunneledL7BytesReceived\": 1, " + "\"roundTripTime\": 111, " + "\"timeToFirstByte\": 226, " + "\"ipTosCountList\": [" + "[\"1\", 13], " + "[\"4\", 99], " + "[\"17\", 1]], " + "\"ipTosList\": [\"1\", \"4\", \"17\"], " + "\"tcpFlagList\": [\"CWR\", \"URG\"], " + "\"tcpFlagCountList\": [[\"CWR\", 10], [\"URG\", 121]], " + "\"mobileQciCosList\": [\"conversational\", \"65\"], " + "\"mobileQciCosCountList\": [[\"conversational\", 11], [\"65\", 122]], " + "\"durConnectionFailedStatus\": 12, " + "\"durTunnelFailedStatus\": 13, " + "\"flowActivatedBy\": \"Remote\", " + "\"flowActivationTime\": \"Fri, 05 Aug 2016 15:03:43 +0000\", " + "\"flowDeactivatedBy\": \"Remote\", " + "\"gtpConnectionStatus\": \"Connected\", " + "\"gtpTunnelStatus\": \"Not tunneling\", " + "\"largePacketRtt\": 80, " + "\"largePacketThreshold\": 600.000000, " + "\"maxReceiveBitRate\": 1357924680, " + "\"maxTransmitBitRate\": 235711, " + "\"numGtpEchoFailures\": 1, " + "\"numGtpTunnelErrors\": 4, " + "\"numHttpErrors\": 2" + "}, " + "\"ipProtocolType\": \"UDP\", " + "\"ipVersion\": \"IPv6\", " + "\"otherEndpointIpAddress\": \"2.3.4.2\", " + "\"otherEndpointPort\": 2342, " + "\"reportingEndpointIpAddr\": \"4.2.3.2\", " + "\"reportingEndpointPort\": 4322, " + "\"applicationType\": \"Demo application\", " + "\"appProtocolType\": \"GSM\", " + "\"appProtocolVersion\": \"1\", " + "\"cid\": \"65535\", " + "\"connectionType\": \"S1-U\", " + "\"ecgi\": \"e65535\", " + "\"gtpProtocolType\": \"GTP-U\", " + "\"gtpVersion\": \"1\", " + "\"httpHeader\": \"http://www.something.com\", " + "\"imei\": \"209917614823\", " + "\"imsi\": \"355251/05/850925/8\", " + "\"lac\": \"1\", " + "\"mcc\": \"410\", " + "\"mnc\": \"04\", " + "\"msisdn\": \"6017123456789\", " + "\"otherFunctionalRole\": \"MME\", " + "\"rac\": \"514\", " + "\"radioAccessTechnology\": \"LTE\", " + "\"sac\": \"1\", " + "\"samplingAlgorithm\": 1, " + "\"tac\": \"2099\", " + "\"tunnelId\": \"Tunnel 1\", " + "\"vlanId\": \"15\"" + "}}}"; + + size_t json_size = 0; + char json_body[EVEL_MAX_JSON_BODY]; + MOBILE_GTP_PER_FLOW_METRICS * metrics = NULL; + EVENT_MOBILE_FLOW * mobile_flow = NULL; + + /***************************************************************************/ + /* Mobile. */ + /***************************************************************************/ + evel_set_next_event_sequence(1242); + + metrics = evel_new_mobile_gtp_flow_metrics(132.0001, + 31.2, + 101, + 2101, + 501, + 1470409422, + 988, + 1470409432, + 12, + (time_t)1470409432, + "Inactive", + 88, + 4, + 18, + 123655, + 4562, + 1, + 13, + 11, + 2, + 4, + 8, + 900, + 902, + 303, + 7, + 3, + 1, + 111, + 226); + assert(metrics != NULL); + + evel_mobile_gtp_metrics_dur_con_fail_set(metrics, 12); + evel_mobile_gtp_metrics_dur_tun_fail_set(metrics, 13); + evel_mobile_gtp_metrics_act_by_set(metrics, "Remote"); + evel_mobile_gtp_metrics_act_time_set(metrics, (time_t)1470409423); + evel_mobile_gtp_metrics_deact_by_set(metrics, "Remote"); + evel_mobile_gtp_metrics_con_status_set(metrics, "Connected"); + evel_mobile_gtp_metrics_tun_status_set(metrics, "Not tunneling"); + evel_mobile_gtp_metrics_iptos_set(metrics, 1, 13); + evel_mobile_gtp_metrics_iptos_set(metrics, 17, 1); + evel_mobile_gtp_metrics_iptos_set(metrics, 4, 99); + evel_mobile_gtp_metrics_large_pkt_rtt_set(metrics, 80); + evel_mobile_gtp_metrics_large_pkt_thresh_set(metrics, 600.0); + evel_mobile_gtp_metrics_max_rcv_bit_rate_set(metrics, 1357924680); + evel_mobile_gtp_metrics_max_trx_bit_rate_set(metrics, 235711); + evel_mobile_gtp_metrics_num_echo_fail_set(metrics, 1); + evel_mobile_gtp_metrics_num_tun_fail_set(metrics, 4); + evel_mobile_gtp_metrics_num_http_errors_set(metrics, 2); + evel_mobile_gtp_metrics_tcp_flag_count_add(metrics, EVEL_TCP_CWR, 10); + evel_mobile_gtp_metrics_tcp_flag_count_add(metrics, EVEL_TCP_URG, 121); + evel_mobile_gtp_metrics_qci_cos_count_add( + metrics, EVEL_QCI_COS_UMTS_CONVERSATIONAL, 11); + evel_mobile_gtp_metrics_qci_cos_count_add( + metrics, EVEL_QCI_COS_LTE_65, 122); + + mobile_flow = evel_new_mobile_flow("Inbound", + metrics, + "UDP", + "IPv6", + "2.3.4.2", + 2342, + "4.2.3.2", + 4322); + assert(mobile_flow != NULL); + + evel_mobile_flow_type_set(mobile_flow, "Mobile flow..."); + evel_mobile_flow_app_type_set(mobile_flow, "Demo application"); + evel_mobile_flow_app_prot_type_set(mobile_flow, "GSM"); + evel_mobile_flow_app_prot_ver_set(mobile_flow, "1"); + evel_mobile_flow_cid_set(mobile_flow, "65535"); + evel_mobile_flow_con_type_set(mobile_flow, "S1-U"); + evel_mobile_flow_ecgi_set(mobile_flow, "e65535"); + evel_mobile_flow_gtp_prot_type_set(mobile_flow, "GTP-U"); + evel_mobile_flow_gtp_prot_ver_set(mobile_flow, "1"); + evel_mobile_flow_http_header_set(mobile_flow, + "http://www.something.com"); + evel_mobile_flow_imei_set(mobile_flow, "209917614823"); + evel_mobile_flow_imsi_set(mobile_flow, "355251/05/850925/8"); + evel_mobile_flow_lac_set(mobile_flow, "1"); + evel_mobile_flow_mcc_set(mobile_flow, "410"); + evel_mobile_flow_mnc_set(mobile_flow, "04"); + evel_mobile_flow_msisdn_set(mobile_flow, "6017123456789"); + evel_mobile_flow_other_func_role_set(mobile_flow, "MME"); + evel_mobile_flow_rac_set(mobile_flow, "514"); + evel_mobile_flow_radio_acc_tech_set(mobile_flow, "LTE"); + evel_mobile_flow_sac_set(mobile_flow, "1"); + evel_mobile_flow_samp_alg_set(mobile_flow, 1); + evel_mobile_flow_tac_set(mobile_flow, "2099"); + evel_mobile_flow_tunnel_id_set(mobile_flow, "Tunnel 1"); + evel_mobile_flow_vlan_id_set(mobile_flow, "15"); + + json_size = evel_json_encode_event( + json_body, EVEL_MAX_JSON_BODY, (EVENT_HEADER *) mobile_flow); + compare_strings(expected, json_body, EVEL_MAX_JSON_BODY, "Mobile"); + assert((json_size == strlen(json_body)) && "Bad size returned"); + + evel_free_event(mobile_flow); +} + +void test_encode_report() +{ + char * expected = + "{\"event\": " + "{\"commonEventHeader\": {" + "\"domain\": \"measurementsForVfReporting\", " + "\"eventId\": \"125\", " + "\"functionalRole\": \"UNIT TEST\", " + "\"lastEpochMicrosec\": 1000002, " + "\"priority\": \"Normal\", " + "\"reportingEntityName\": \"Dummy VM name - No Metadata available\", " + "\"sequence\": 125, " + "\"sourceName\": \"Dummy VM name - No Metadata available\", " + "\"startEpochMicrosec\": 1000002, " + "\"version\": 1.2, " + "\"eventType\": \"Perf reporting...\", " + "\"reportingEntityId\": \"Dummy VM UUID - No Metadata available\", " + "\"sourceId\": \"Dummy VM UUID - No Metadata available\"" + "}, " + "\"measurementsForVfReportingFields\": " + "{\"measurementInterval\": 1.100000, " + "\"featureUsageArray\": [" + "{\"featureIdentifier\": \"FeatureA\", " + "\"featureUtilization\": 123}, " + "{\"featureIdentifier\": \"FeatureB\", " + "\"featureUtilization\": 567}], " + "\"additionalMeasurements\": [" + "{\"name\": \"Group1\", " + "\"measurements\": [" + "{\"name\": \"Name1\", " + "\"value\": \"Value1\"}]}, " + "{\"name\": \"Group2\", " + "\"measurements\": [" + "{\"name\": \"Name1\", " + "\"value\": \"Value1\"}, " + "{\"name\": \"Name2\", " + "\"value\": \"Value2\"}]}], " + "\"measurementFieldsVersion\": 1.1}}}"; + + size_t json_size = 0; + char json_body[EVEL_MAX_JSON_BODY]; + EVENT_REPORT * report = NULL; + + /***************************************************************************/ + /* Report. */ + /***************************************************************************/ + evel_set_next_event_sequence(125); + report = evel_new_report(1.1); + assert(report != NULL); + evel_report_type_set(report, "Perf reporting..."); + evel_report_feature_use_add(report, "FeatureA", 123); + evel_report_feature_use_add(report, "FeatureB", 567); + evel_report_custom_measurement_add(report, "Group1", "Name1", "Value1"); + evel_report_custom_measurement_add(report, "Group2", "Name1", "Value1"); + evel_report_custom_measurement_add(report, "Group2", "Name2", "Value2"); + + json_size = evel_json_encode_event( + json_body, EVEL_MAX_JSON_BODY, (EVENT_HEADER *) report); + compare_strings(expected, json_body, EVEL_MAX_JSON_BODY, "Report"); + assert((json_size == strlen(json_body)) && "Bad size returned"); + + evel_free_event(report); +} + +void test_encode_service() +{ + test_encode_service_subset(SERVICE_NONE); + test_encode_service_subset(SERVICE_CODEC); + test_encode_service_subset(SERVICE_TRANSCODING); + test_encode_service_subset(SERVICE_RTCP); + test_encode_service_subset(SERVICE_EOC_VQM); + test_encode_service_subset(SERVICE_MARKER); +} + +void test_encode_service_subset(const SERVICE_TEST service_test) +{ + char * expected_start = + "{\"event\": " + "{\"commonEventHeader\": {" + "\"domain\": \"serviceEvents\", " + "\"eventId\": \"2000\", " + "\"functionalRole\": \"UNIT TEST\", " + "\"lastEpochMicrosec\": 1000002, " + "\"priority\": \"Normal\", " + "\"reportingEntityName\": \"Dummy VM name - No Metadata available\", " + "\"sequence\": 2000, " + "\"sourceName\": \"Dummy VM name - No Metadata available\", " + "\"startEpochMicrosec\": 1000002, " + "\"version\": 1.2, " + "\"eventType\": \"Service Event\", " + "\"reportingEntityId\": \"Dummy VM UUID - No Metadata available\", " + "\"sourceId\": \"Dummy VM UUID - No Metadata available\"" + "}, " + "\"serviceEventsFields\": {" + "\"eventInstanceIdentifier\": " + "{" + "\"vendorId\": \"vendor_x_id\", " + "\"eventId\": \"vendor_x_event_id\", " + "\"productId\": \"vendor_x_product_id\", " + "\"subsystemId\": \"vendor_x_subsystem_id\", " + "\"eventFriendlyName\": \"vendor_x_frieldly_name\"" + "}, " + "\"serviceEventsFieldsVersion\": 1.1, " + "\"correlator\": \"vendor_x_correlator\", " + "\"additionalFields\": [" + "{\"name\": \"Name1\", \"value\": \"Value1\"}, " + "{\"name\": \"Name2\", \"value\": \"Value2\"}, " + "{\"name\": \"Name3\", \"value\": \"Value3\"}, " + "{\"name\": \"Name4\", \"value\": \"Value4\"}]"; + char * expected_codec = + ", " + "\"codecSelected\": {" + "\"codec\": \"PCMA\"" + "}"; + char * expected_transcoding = + ", " + "\"codecSelectedTranscoding\": {" + "\"calleeSideCodec\": \"PCMA\", " + "\"callerSideCodec\": \"G729A\"" + "}"; + char * expected_rtcp = + ", " + "\"midCallRtcp\": {" + "\"rtcpData\": \"some_rtcp_data\"" + "}"; + char * expected_eoc_vqm = + ", " + "\"endOfCallVqmSummaries\": {" + "\"adjacencyName\": \"vendor_x_adjacency\", " + "\"endpointDescription\": \"Caller\", " + "\"endpointJitter\": 66, " + "\"endpointRtpOctetsDiscarded\": 100, " + "\"endpointRtpOctetsReceived\": 200, " + "\"endpointRtpOctetsSent\": 300, " + "\"endpointRtpPacketsDiscarded\": 400, " + "\"endpointRtpPacketsReceived\": 500, " + "\"endpointRtpPacketsSent\": 600, " + "\"localJitter\": 99, " + "\"localRtpOctetsDiscarded\": 150, " + "\"localRtpOctetsReceived\": 250, " + "\"localRtpOctetsSent\": 350, " + "\"localRtpPacketsDiscarded\": 450, " + "\"localRtpPacketsReceived\": 550, " + "\"localRtpPacketsSent\": 650, " + "\"mosCqe\": 12.255000, " + "\"packetsLost\": 157, " + "\"packetLossPercent\": 0.232000, " + "\"rFactor\": 11, " + "\"roundTripDelay\": 15" + "}"; + char * expected_marker = + ", " + "\"marker\": {" + "\"phoneNumber\": \"0888888888\"" + "}"; + char * expected_end = + "}}}"; + + char * expected_middle = NULL; + switch (service_test) + { + case SERVICE_NONE: + expected_middle = ""; + break; + case SERVICE_CODEC: + expected_middle = expected_codec; + break; + case SERVICE_TRANSCODING: + expected_middle = expected_transcoding; + break; + case SERVICE_RTCP: + expected_middle = expected_rtcp; + break; + case SERVICE_EOC_VQM: + expected_middle = expected_eoc_vqm; + break; + case SERVICE_MARKER: + expected_middle = expected_marker; + break; + } + assert(expected_middle != NULL); + + int offset = 0; + char expected[EVEL_MAX_JSON_BODY]; + offset = snprintf(expected + offset, + EVEL_MAX_JSON_BODY - offset, + "%s%s%s", + expected_start, + expected_middle, + expected_end); + + size_t json_size = 0; + char json_body[EVEL_MAX_JSON_BODY]; + EVENT_SGNALING * event = NULL; + evel_set_next_event_sequence(2000); + event = evel_new_signaling("vendor_x_id", + "correlator", "1.0.3.1", "1234", "192.168.1.3","3456"); + assert(event != NULL); + evel_signaling_type_set(event, "Signaling"); + evel_signaling_correlator_set(event, "vendor_x_correlator"); + evel_signaling_vnfmodule_name_set(event, "vendor_x_module"); + evel_signaling_vnfname_set(event, "vendor_x_vnf"); + + switch (service_test) + { + case SERVICE_NONE: + break; + case SERVICE_CODEC: + evel_signaling_addl_info_add(event, "codec", "PCMA"); + break; + case SERVICE_TRANSCODING: + evel_signaling_addl_info_add(event, "calleecodec", "PCMA"); + evel_signaling_addl_info_add(event, "callercodec", "G729A"); + break; + case SERVICE_RTCP: + evel_signaling_addl_info_add(event, "rtcpdata", "abcdefgh"); + break; + case SERVICE_EOC_VQM: + evel_signaling_addl_info_add(event, "adjacency", "vendor_x"); + /*evel_service_adjacency_name_set(event, "vendor_x_adjacency"); + evel_service_endpoint_desc_set(event, EVEL_SERVICE_ENDPOINT_CALLER); + evel_service_endpoint_jitter_set(event, 66); + evel_service_endpoint_rtp_oct_disc_set(event, 100); + evel_service_endpoint_rtp_oct_recv_set(event, 200); + evel_service_endpoint_rtp_oct_sent_set(event, 300); + evel_service_endpoint_rtp_pkt_disc_set(event, 400); + evel_service_endpoint_rtp_pkt_recv_set(event, 500); + evel_service_endpoint_rtp_pkt_sent_set(event, 600); + evel_service_local_jitter_set(event, 99); + evel_service_local_rtp_oct_disc_set(event, 150); + evel_service_local_rtp_oct_recv_set(event, 250); + evel_service_local_rtp_oct_sent_set(event, 350); + evel_service_local_rtp_pkt_disc_set(event, 450); + evel_service_local_rtp_pkt_recv_set(event, 550); + evel_service_local_rtp_pkt_sent_set(event, 650); + evel_service_mos_cqe_set(event, 12.255); + evel_service_packets_lost_set(event, 157); + evel_service_packet_loss_percent_set(event, 0.232); + evel_service_r_factor_set(event, 11); + evel_service_round_trip_delay_set(event, 15);*/ + break; + case SERVICE_MARKER: + evel_signaling_addl_info_add(event, "service_phone", "0888888888"); + break; + } + + json_size = evel_json_encode_event( + json_body, EVEL_MAX_JSON_BODY, (EVENT_HEADER *) event); + compare_strings(expected, json_body, EVEL_MAX_JSON_BODY, "Service"); + assert((json_size == strlen(json_body)) && "Bad size returned"); + + evel_free_event(event); +} + +void test_encode_signaling() +{ + char * expected = + "{\"event\": " + "{\"commonEventHeader\": {" + "\"domain\": \"signaling\", " + "\"eventId\": \"2001\", " + "\"functionalRole\": \"UNIT TEST\", " + "\"lastEpochMicrosec\": 1000002, " + "\"priority\": \"Normal\", " + "\"reportingEntityName\": \"Dummy VM name - No Metadata available\", " + "\"sequence\": 2001, " + "\"sourceName\": \"Dummy VM name - No Metadata available\", " + "\"startEpochMicrosec\": 1000002, " + "\"version\": 1.2, " + "\"eventType\": \"Signaling\", " + "\"reportingEntityId\": \"Dummy VM UUID - No Metadata available\", " + "\"sourceId\": \"Dummy VM UUID - No Metadata available\"" + "}, " + "\"signalingFields\": {" + "\"eventInstanceIdentifier\": " + "{" + "\"vendorId\": \"vendor_x_id\", " + "\"eventId\": \"vendor_x_event_id\", " + "\"productId\": \"vendor_x_product_id\", " + "\"subsystemId\": \"vendor_x_subsystem_id\", " + "\"eventFriendlyName\": \"vendor_x_frieldly_name\"" + "}, " + "\"signalingFieldsVersion\": 1.1, " + "\"correlator\": \"vendor_x_correlator\", " + "\"localIpAddress\": \"1.0.3.1\", " + "\"localPort\": \"1031\", " + "\"remoteIpAddress\": \"5.3.3.0\", " + "\"remotePort\": \"5330\", " + "\"compressedSip\": \"compressed_sip\", " + "\"summarySip\": \"summary_sip\"" + "}}}"; + + size_t json_size = 0; + char json_body[EVEL_MAX_JSON_BODY]; + EVENT_SIGNALING * event = NULL; + evel_set_next_event_sequence(2001); + event = evel_new_signaling("vendor_x_id", + "correlator", "1.0.3.1", "1234", "192.168.1.3","3456"); + assert(event != NULL); + evel_signaling_vnfmodule_name_set(event, "vendor_x_module"); + evel_signaling_vnfname_set(event, "vendor_x_vnf"); + evel_signaling_type_set(event, "Signaling"); + evel_signaling_product_id_set(event, "vendor_x_product_id"); + evel_signaling_subsystem_id_set(event, "vendor_x_subsystem_id"); + evel_signaling_friendly_name_set(event, "vendor_x_frieldly_name"); + evel_signaling_correlator_set(event, "vendor_x_correlator"); + evel_signaling_local_ip_address_set(event, "1.0.3.1"); + evel_signaling_local_port_set(event, "1031"); + evel_signaling_remote_ip_address_set(event, "5.3.3.0"); + evel_signaling_remote_port_set(event, "5330"); + evel_signaling_compressed_sip_set(event, "compressed_sip"); + evel_signaling_summary_sip_set(event, "summary_sip"); + json_size = evel_json_encode_event( + json_body, EVEL_MAX_JSON_BODY, (EVENT_HEADER *) event); + compare_strings(expected, json_body, EVEL_MAX_JSON_BODY, "Signaling"); + assert((json_size == strlen(json_body)) && "Bad size returned"); + + evel_free_event(event); +} + +void test_encode_state_change() +{ + char * expected = + "{\"event\": " + "{\"commonEventHeader\": {" + "\"domain\": \"stateChange\", " + "\"eventId\": \"128\", " + "\"functionalRole\": \"UNIT TEST\", " + "\"lastEpochMicrosec\": 1000002, " + "\"priority\": \"Normal\", " + "\"reportingEntityName\": \"Dummy VM name - No Metadata available\", " + "\"sequence\": 128, " + "\"sourceName\": \"Dummy VM name - No Metadata available\", " + "\"startEpochMicrosec\": 1000002, " + "\"version\": 1.2, " + "\"eventType\": \"SC Type\", " + "\"reportingEntityId\": \"Dummy VM UUID - No Metadata available\", " + "\"sourceId\": \"Dummy VM UUID - No Metadata available\"" + "}, " + "\"stateChangeFields\": {" + "\"newState\": \"inService\", " + "\"oldState\": \"outOfService\", " + "\"stateInterface\": \"An Interface\", " + "\"additionalFields\": [" + "{\"name\": \"Name1\", " + "\"value\": \"Value1\"}, " + "{\"name\": \"Name2\", " + "\"value\": \"Value2\"}" + "], " + "\"stateChangeFieldsVersion\": 1.1" + "}}}"; + + size_t json_size = 0; + char json_body[EVEL_MAX_JSON_BODY]; + EVENT_STATE_CHANGE * state_change = NULL; + evel_set_next_event_sequence(128); + state_change = evel_new_state_change(EVEL_ENTITY_STATE_IN_SERVICE, + EVEL_ENTITY_STATE_OUT_OF_SERVICE, + "An Interface"); + assert(state_change != NULL); + evel_state_change_type_set(state_change, "SC Type"); + evel_state_change_addl_field_add(state_change, "Name1", "Value1"); + evel_state_change_addl_field_add(state_change, "Name2", "Value2"); + + json_size = evel_json_encode_event( + json_body, EVEL_MAX_JSON_BODY, (EVENT_HEADER *) state_change); + compare_strings(expected, json_body, EVEL_MAX_JSON_BODY, "StateChange"); + assert((json_size == strlen(json_body)) && "Bad size returned"); + + evel_free_event(state_change); +} + +void test_encode_syslog() +{ + char * expected = + "{\"event\": " + "{\"commonEventHeader\": {" + "\"domain\": \"syslog\", " + "\"eventId\": \"126\", " + "\"functionalRole\": \"UNIT TEST\", " + "\"lastEpochMicrosec\": 1000002, " + "\"priority\": \"Normal\", " + "\"reportingEntityName\": \"Dummy VM name - No Metadata available\", " + "\"sequence\": 126, " + "\"sourceName\": \"Dummy VM name - No Metadata available\", " + "\"startEpochMicrosec\": 1000002, " + "\"version\": 1.2, " + "\"eventType\": \"SL Type\", " + "\"reportingEntityId\": \"Dummy VM UUID - No Metadata available\", " + "\"sourceId\": \"Dummy VM UUID - No Metadata available\"" + "}, " + "\"syslogFields\": {" + "\"eventSourceType\": \"virtualNetworkFunction\", " + "\"syslogMsg\": \"SL Message\", " + "\"syslogTag\": \"SL Tag\", " + "\"syslogFieldsVersion\": 1.1, " + "\"eventSourceHost\": \"SL Host\", " + "\"syslogFacility\": 6, " + "\"syslogProc\": \"SL Proc\", " + "\"syslogProcId\": 2, " + "\"syslogSData\": \"SL SDATA\", " + "\"syslogVer\": 1" + "}}}"; + size_t json_size = 0; + char json_body[EVEL_MAX_JSON_BODY]; + EVENT_SYSLOG * syslog = NULL; + evel_set_next_event_sequence(126); + syslog = evel_new_syslog(EVEL_SOURCE_VIRTUAL_NETWORK_FUNCTION, + "SL Message", + "SL Tag"); + assert(syslog != NULL); + evel_syslog_type_set(syslog, "SL Type"); + evel_syslog_event_source_host_set(syslog, "SL Host"); + evel_syslog_facility_set(syslog, EVEL_SYSLOG_FACILITY_LINE_PRINTER); + evel_syslog_proc_set(syslog, "SL Proc"); + evel_syslog_proc_id_set(syslog, 2); + evel_syslog_version_set(syslog, 1); + evel_syslog_s_data_set(syslog, "SL SDATA"); + + json_size = evel_json_encode_event( + json_body, EVEL_MAX_JSON_BODY, (EVENT_HEADER *) syslog); + compare_strings(expected, json_body, EVEL_MAX_JSON_BODY, "Syslog"); + assert((json_size == strlen(json_body)) && "Bad size returned"); + + evel_free_event(syslog); +} + +void test_encode_other() +{ + char * expected = + "{\"event\": " + "{\"commonEventHeader\": {" + "\"domain\": \"other\", " + "\"eventId\": \"129\", " + "\"functionalRole\": \"UNIT TEST\", " + "\"lastEpochMicrosec\": 1000002, " + "\"priority\": \"Normal\", " + "\"reportingEntityName\": \"Dummy VM name - No Metadata available\", " + "\"sequence\": 129, " + "\"sourceName\": \"Dummy VM name - No Metadata available\", " + "\"startEpochMicrosec\": 1000002, " + "\"version\": 1.2, " + "\"eventType\": \"Other Type\", " + "\"reportingEntityId\": \"Dummy VM UUID - No Metadata available\", " + "\"sourceId\": \"Dummy VM UUID - No Metadata available\"" + "}, " + "\"otherFields\": [" + "{\"name\": \"Other field 1\", " + "\"value\": \"Other value 1\"}, " + "{\"name\": \"Other field 2\", " + "\"value\": \"Other value 2\"}" + "]" + "}}"; + + size_t json_size = 0; + char json_body[EVEL_MAX_JSON_BODY]; + EVENT_OTHER * other = NULL; + evel_set_next_event_sequence(129); + other = evel_new_other(); + assert(other != NULL); + evel_other_type_set(other, "Other Type"); + evel_other_field_add(other, + "Other field 1", + "Other value 1"); + evel_other_field_add(other, + "Other field 2", + "Other value 2"); + + json_size = evel_json_encode_event( + json_body, EVEL_MAX_JSON_BODY, (EVENT_HEADER *) other); + compare_strings(expected, json_body, EVEL_MAX_JSON_BODY, "Other"); + assert((json_size == strlen(json_body)) && "Bad size returned"); + + evel_free_event(other); +} + +void compare_strings(char * expected, + char * actual, + int max_size, + char * description) +{ + if (strncmp(expected, actual, max_size) != 0) + { + int diff = 0; + while (diff < max_size) + { + if (expected[diff] != actual[diff]) + { + break; + } + diff++; + } + + printf("Comparison Failure at Offset %d\n\n", diff); + printf("Expected:\n%s\n", expected); + printf("Actual:\n%s\n", actual); + printf("Description: %s\n", description); + assert(0); + } +} + +/**************************************************************************//** + * Copy a json string to a ::MEMORY_CHUNK for testing. + * + * @param chunk The memory chunk. + * @param string The json string. + *****************************************************************************/ +void copy_string_to_chunk(MEMORY_CHUNK * chunk, char * string) +{ + int mem_size; + + /***************************************************************************/ + /* Check preconditions. */ + /***************************************************************************/ + assert(chunk != NULL); + assert(string != NULL); + + mem_size = strlen(string) + 1; + chunk->memory = malloc(mem_size); + memcpy(chunk->memory, string, mem_size); + chunk->size = mem_size; +} + +/**************************************************************************//** + * Copy a json string to a ::MEMORY_CHUNK for testing. + * + * @param json The JSON string. + * @param post Memory chunk to post a response. + *****************************************************************************/ +void handle_json_response(char * json, MEMORY_CHUNK * post) +{ + MEMORY_CHUNK chunk; + post->memory = NULL; + post->size = 0; + copy_string_to_chunk(&chunk, json); + evel_handle_event_response(&chunk, post); + free(chunk.memory); +} + +/**************************************************************************//** + * Test that a non-"commandList" JSON buffer leaves the throttle state off. + *****************************************************************************/ +void test_json_response_junk() +{ + MEMORY_CHUNK post; + int domain; + char * json_junk = + "{" + "\"junk1\": [" + "\"1\", \"2\", \"3\"], " + "\"junk2\": [" + "\"1\", \"2\", \"3\"]" + "}"; + + evel_throttle_initialize(); + handle_json_response(json_junk, &post); + + /***************************************************************************/ + /* Check that all domains are not throttled. */ + /***************************************************************************/ + for (domain = EVEL_DOMAIN_FAULT; domain < EVEL_MAX_DOMAINS; domain++) + { + assert(evel_get_throttle_spec(domain) == NULL); + } + + /***************************************************************************/ + /* Check that we generated no post. */ + /***************************************************************************/ + assert(post.memory == NULL); + + evel_throttle_terminate(); +} + +char * json_command_list_provide = + "{" + "\"commandList\": [" + "{" + "\"command\": {" + "\"commandType\": \"provideThrottlingState\"" + "}" + "}" + "]" + "}"; + +char * json_command_list_fault_clear = + "{" + "\"commandList\": [" + "{" + "\"command\": {" + "\"commandType\": \"throttlingSpecification\", " + "\"eventDomainThrottleSpecification\": {" + "\"eventDomain\": \"fault\"" + "}" + "}" + "}" + "]" + "}"; + +char * json_command_list_syslog_clear = + "{" + "\"commandList\": [" + "{" + "\"command\": {" + "\"commandType\": \"throttlingSpecification\", " + "\"eventDomainThrottleSpecification\": {" + "\"eventDomain\": \"syslog\"" + "}" + "}" + "}" + "]" + "}"; + +char * expected_throttle_state_normal = + "{" + "\"eventThrottlingState\": {" + "\"eventThrottlingMode\": \"normal\"}" + "}"; + +/**************************************************************************//** + * Test that we can return the default throttling state. + *****************************************************************************/ +void test_json_provide_throttle_state() +{ + MEMORY_CHUNK post; + int domain; + + char * expected_post = expected_throttle_state_normal; + + evel_throttle_initialize(); + handle_json_response(json_command_list_provide, &post); + + /***************************************************************************/ + /* Check that all domains are not throttled. */ + /***************************************************************************/ + for (domain = EVEL_DOMAIN_FAULT; domain < EVEL_MAX_DOMAINS; domain++) + { + assert(evel_get_throttle_spec(domain) == NULL); + } + + /***************************************************************************/ + /* Check that we generated a throttling specification post. */ + /***************************************************************************/ + assert(post.memory != NULL); + compare_strings(expected_post, post.memory, strlen(expected_post), + "Throttle State Normal"); + free(post.memory); + + evel_throttle_terminate(); +} + +/**************************************************************************//** + * Test the measurement interval handling and API. + *****************************************************************************/ +void test_json_measurement_interval() +{ + MEMORY_CHUNK post; + char * json_command_list_interval_only = + "{" + "\"commandList\": [" + "{" + "\"command\": {" + "\"measurementInterval\": 60" + "}" + "}" + "]" + "}"; + + char * json_command_list_interval_first = + "{" + "\"commandList\": [" + "{" + "\"command\": {" + "\"measurementInterval\": 30, " + "\"commandType\": \"measurementIntervalChange\"" + "}" + "}" + "]" + "}"; + + char * json_command_list_command_first = + "{" + "\"commandList\": [" + "{" + "\"command\": {" + "\"commandType\": \"measurementIntervalChange\", " + "\"measurementInterval\": 60" + "}" + "}" + "]" + "}"; + + evel_throttle_initialize(); + assert(evel_get_measurement_interval() == EVEL_MEASUREMENT_INTERVAL_UKNOWN); + + /***************************************************************************/ + /* Check that we're not handling stuff when we shouldn't. */ + /***************************************************************************/ + handle_json_response(json_command_list_interval_only, &post); + assert(post.memory == NULL); + assert(evel_get_measurement_interval() == EVEL_MEASUREMENT_INTERVAL_UKNOWN); + + /***************************************************************************/ + /* Check that we're OK with the interval coming first. */ + /***************************************************************************/ + handle_json_response(json_command_list_interval_first, &post); + assert(post.memory == NULL); + assert(evel_get_measurement_interval() == 30); + + /***************************************************************************/ + /* Check that we're OK with the command type coming first. */ + /***************************************************************************/ + handle_json_response(json_command_list_command_first, &post); + assert(post.memory == NULL); + assert(evel_get_measurement_interval() == 60); + + evel_throttle_terminate(); +} + +/**************************************************************************//** + * Test a single domain, single field suppression. + *****************************************************************************/ +void test_json_throttle_spec_field() +{ + MEMORY_CHUNK post; + int domain; + + char * json_command_list_fault_single = + "{" + "\"commandList\": [" + "{" + "\"command\": {" + "\"commandType\": \"throttlingSpecification\", " + "\"eventDomainThrottleSpecification\": {" + "\"eventDomain\": \"fault\", " + "\"suppressedFieldNames\": [\"alarmInterfaceA\"]" + "}" + "}" + "}" + "]" + "}"; + + char * json_command_list_fault_double = + "{" + "\"commandList\": [" + "{" + "\"command\": {" + "\"commandType\": \"throttlingSpecification\", " + "\"eventDomainThrottleSpecification\": {" + "\"eventDomain\": \"fault\", " + "\"suppressedFieldNames\": [" + "\"alarmInterfaceA\", \"alarmAdditionalInformation\"]" + "}" + "}" + "}" + "]" + "}"; + + char * expected_post_fault_single = + "{" + "\"eventThrottlingState\": {" + "\"eventThrottlingMode\": \"throttled\", " + "\"eventDomainThrottleSpecificationList\": [" + "{" + "\"eventDomain\": \"fault\", " + "\"suppressedFieldNames\": [\"alarmInterfaceA\"]" + "}" + "]" + "}" + "}"; + + char * expected_post_fault_double = + "{" + "\"eventThrottlingState\": {" + "\"eventThrottlingMode\": \"throttled\", " + "\"eventDomainThrottleSpecificationList\": [" + "{" + "\"eventDomain\": \"fault\", " + "\"suppressedFieldNames\": [" + "\"alarmInterfaceA\", \"alarmAdditionalInformation\"]" + "}" + "]" + "}" + "}"; + + /***************************************************************************/ + /* Initialize and provide a specification with a single fault suppressed. */ + /***************************************************************************/ + evel_throttle_initialize(); + handle_json_response(json_command_list_fault_single, &post); + + /***************************************************************************/ + /* Check that the FAULT domain is throttled. */ + /***************************************************************************/ + assert(evel_get_throttle_spec(EVEL_DOMAIN_FAULT) != NULL); + for (domain = EVEL_DOMAIN_MEASUREMENT; domain < EVEL_MAX_DOMAINS; domain++) + { + if (domain != EVEL_DOMAIN_FAULT) + { + assert(evel_get_throttle_spec(domain) == NULL); + } + } + assert(post.memory == NULL); + + /***************************************************************************/ + /* Request and verify the throttling state. */ + /***************************************************************************/ + handle_json_response(json_command_list_provide, &post); + assert(post.memory != NULL); + compare_strings(expected_post_fault_single, + post.memory, + strlen(expected_post_fault_single), + "Fault - Single Field"); + free(post.memory); + post.memory = NULL; + + /***************************************************************************/ + /* Update a specification with two faults suppressed. */ + /***************************************************************************/ + handle_json_response(json_command_list_fault_double, &post); + + /***************************************************************************/ + /* Check that the FAULT domain is throttled. */ + /***************************************************************************/ + assert(evel_get_throttle_spec(EVEL_DOMAIN_FAULT) != NULL); + for (domain = EVEL_DOMAIN_MEASUREMENT; domain < EVEL_MAX_DOMAINS; domain++) + { + if (domain != EVEL_DOMAIN_FAULT) + { + assert(evel_get_throttle_spec(domain) == NULL); + } + } + assert(post.memory == NULL); + + /***************************************************************************/ + /* Request and verify the throttling state. */ + /***************************************************************************/ + handle_json_response(json_command_list_provide, &post); + assert(post.memory != NULL); + compare_strings(expected_post_fault_double, + post.memory, + strlen(expected_post_fault_double), + "Fault - Double Field"); + free(post.memory); + post.memory = NULL; + + /***************************************************************************/ + /* Now clear the FAULT domain. */ + /***************************************************************************/ + handle_json_response(json_command_list_fault_clear, &post); + for (domain = EVEL_DOMAIN_FAULT; domain < EVEL_MAX_DOMAINS; domain++) + { + assert(evel_get_throttle_spec(domain) == NULL); + } + + evel_throttle_terminate(); +} + +/**************************************************************************//** + * Test a single domain, nv_pair suppression. + *****************************************************************************/ +void test_json_throttle_spec_nv_pair() +{ + MEMORY_CHUNK post; + int domain; + + char * json_command_list_fault_pair_single = + "{" + "\"commandList\": [" + "{" + "\"command\": {" + "\"commandType\": \"throttlingSpecification\", " + "\"eventDomainThrottleSpecification\": {" + "\"eventDomain\": \"fault\", " + "\"suppressedNvPairsList\": [" + "{" + "\"nvPairFieldName\": \"alarmAdditionalInformation\", " + "\"suppressedNvPairNames\": [\"name1\"]" + "}" + "]" + "}" + "}" + "}" + "]" + "}"; + + char * json_command_list_fault_pair_double = + "{" + "\"commandList\": [" + "{" + "\"command\": {" + "\"commandType\": \"throttlingSpecification\", " + "\"eventDomainThrottleSpecification\": {" + "\"eventDomain\": \"fault\", " + "\"suppressedNvPairsList\": [" + "{" + "\"nvPairFieldName\": \"alarmAdditionalInformation\", " + "\"suppressedNvPairNames\": [\"name1\", \"name2\"]" + "}" + "]" + "}" + "}" + "}" + "]" + "}"; + + char * expected_post_fault_pair_single = + "{" + "\"eventThrottlingState\": {" + "\"eventThrottlingMode\": \"throttled\", " + "\"eventDomainThrottleSpecificationList\": [" + "{" + "\"eventDomain\": \"fault\", " + "\"suppressedNvPairsList\": [" + "{" + "\"nvPairFieldName\": \"alarmAdditionalInformation\", " + "\"suppressedNvPairNames\": [\"name1\"]" + "}" + "]" + "}" + "]" + "}" + "}"; + + char * expected_post_fault_pair_double = + "{" + "\"eventThrottlingState\": {" + "\"eventThrottlingMode\": \"throttled\", " + "\"eventDomainThrottleSpecificationList\": [" + "{" + "\"eventDomain\": \"fault\", " + "\"suppressedNvPairsList\": [" + "{" + "\"nvPairFieldName\": \"alarmAdditionalInformation\", " + "\"suppressedNvPairNames\": [\"name1\", \"name2\"]" + "}" + "]" + "}" + "]" + "}" + "}"; + + /***************************************************************************/ + /* Initialize and provide a specification with a single nvpair with a */ + /* single sub-field suppressed. */ + /***************************************************************************/ + evel_throttle_initialize(); + handle_json_response(json_command_list_fault_pair_single, &post); + + /***************************************************************************/ + /* Check that the FAULT domain is throttled. */ + /***************************************************************************/ + assert(evel_get_throttle_spec(EVEL_DOMAIN_FAULT) != NULL); + for (domain = EVEL_DOMAIN_MEASUREMENT; domain < EVEL_MAX_DOMAINS; domain++) + { + if (domain != EVEL_DOMAIN_FAULT) + { + assert(evel_get_throttle_spec(domain) == NULL); + } + } + assert(post.memory == NULL); + + /***************************************************************************/ + /* Request and verify the throttling state. */ + /***************************************************************************/ + handle_json_response(json_command_list_provide, &post); + assert(post.memory != NULL); + compare_strings(expected_post_fault_pair_single, + post.memory, + strlen(expected_post_fault_pair_single), + "Fault - Single Pair, Single Field"); + free(post.memory); + post.memory = NULL; + + /***************************************************************************/ + /* Update a specification with a single nvpair with two sub-fields */ + /* suppressed. */ + /***************************************************************************/ + handle_json_response(json_command_list_fault_pair_double, &post); + + /***************************************************************************/ + /* Check that the FAULT domain is throttled. */ + /***************************************************************************/ + assert(evel_get_throttle_spec(EVEL_DOMAIN_FAULT) != NULL); + for (domain = EVEL_DOMAIN_MEASUREMENT; domain < EVEL_MAX_DOMAINS; domain++) + { + if (domain != EVEL_DOMAIN_FAULT) + { + assert(evel_get_throttle_spec(domain) == NULL); + } + } + assert(post.memory == NULL); + + /***************************************************************************/ + /* Request and verify the throttling state. */ + /***************************************************************************/ + handle_json_response(json_command_list_provide, &post); + assert(post.memory != NULL); + compare_strings(expected_post_fault_pair_double, + post.memory, + strlen(expected_post_fault_pair_double), + "Fault - Double Field"); + free(post.memory); + post.memory = NULL; + + /***************************************************************************/ + /* Now clear the FAULT domain. */ + /***************************************************************************/ + handle_json_response(json_command_list_fault_clear, &post); + for (domain = EVEL_DOMAIN_FAULT; domain < EVEL_MAX_DOMAINS; domain++) + { + assert(evel_get_throttle_spec(domain) == NULL); + } + + evel_throttle_terminate(); +} + +/**************************************************************************//** + * Test two domains, nv_pair suppression. + *****************************************************************************/ +void test_json_throttle_spec_two_domains() +{ + MEMORY_CHUNK post; + int domain; + + char * json_command_list_two_domains = + "{" + "\"commandList\": [" + "{" + "\"command\": {" + "\"commandType\": \"throttlingSpecification\", " + "\"eventDomainThrottleSpecification\": {" + "\"eventDomain\": \"fault\", " + "\"suppressedFieldNames\": [\"alarmInterfaceA\"], " + "\"suppressedNvPairsList\": [" + "{" + "\"nvPairFieldName\": \"alarmAdditionalInformation\", " + "\"suppressedNvPairNames\": [\"name1\"]" + "}]}}}, " + "{" + "\"command\": {" + "\"commandType\": \"throttlingSpecification\", " + "\"eventDomainThrottleSpecification\": {" + "\"eventDomain\": \"syslog\", " + "\"suppressedFieldNames\": [\"syslogProcId\"], " + "\"suppressedNvPairsList\": [" + "{" + "\"nvPairFieldName\": \"additionalFields\", " + "\"suppressedNvPairNames\": [\"name1\"]" + "}]}}}" + "]" + "}"; + + char * expected_post_two_domains = + "{" + "\"eventThrottlingState\": {" + "\"eventThrottlingMode\": \"throttled\", " + "\"eventDomainThrottleSpecificationList\": [" + "{" + "\"eventDomain\": \"fault\", " + "\"suppressedFieldNames\": [\"alarmInterfaceA\"], " + "\"suppressedNvPairsList\": [" + "{" + "\"nvPairFieldName\": \"alarmAdditionalInformation\", " + "\"suppressedNvPairNames\": [\"name1\"]" + "}]}, " + "{" + "\"eventDomain\": \"syslog\", " + "\"suppressedFieldNames\": [\"syslogProcId\"], " + "\"suppressedNvPairsList\": [" + "{" + "\"nvPairFieldName\": \"additionalFields\", " + "\"suppressedNvPairNames\": [\"name1\"]" + "}]}" + "]" + "}" + "}"; + + /***************************************************************************/ + /* Initialize and provide a specification with a single nvpair with a */ + /* single sub-field suppressed. */ + /***************************************************************************/ + evel_throttle_initialize(); + handle_json_response(json_command_list_two_domains, &post); + + /***************************************************************************/ + /* Check that the FAULT and SYSLOG domains are throttled. */ + /***************************************************************************/ + assert(evel_get_throttle_spec(EVEL_DOMAIN_FAULT) != NULL); + assert(evel_get_throttle_spec(EVEL_DOMAIN_SYSLOG) != NULL); + for (domain = EVEL_DOMAIN_MEASUREMENT; domain < EVEL_MAX_DOMAINS; domain++) + { + if ((domain != EVEL_DOMAIN_FAULT) && (domain != EVEL_DOMAIN_SYSLOG)) + { + assert(evel_get_throttle_spec(domain) == NULL); + } + } + assert(post.memory == NULL); + + /***************************************************************************/ + /* Request and verify the throttling state. */ + /***************************************************************************/ + handle_json_response(json_command_list_provide, &post); + assert(post.memory != NULL); + compare_strings(expected_post_two_domains, + post.memory, + strlen(expected_post_two_domains), + "Fault - Two Domains"); + free(post.memory); + post.memory = NULL; + + /***************************************************************************/ + /* Now clear the FAULT and SYSLOG domains. */ + /***************************************************************************/ + handle_json_response(json_command_list_fault_clear, &post); + assert(evel_get_throttle_spec(EVEL_DOMAIN_FAULT) == NULL); + assert(evel_get_throttle_spec(EVEL_DOMAIN_SYSLOG) != NULL); + handle_json_response(json_command_list_syslog_clear, &post); + for (domain = EVEL_DOMAIN_FAULT; domain < EVEL_MAX_DOMAINS; domain++) + { + assert(evel_get_throttle_spec(domain) == NULL); + } + + evel_throttle_terminate(); +} + +/**************************************************************************//** + * Test bad command type. + *****************************************************************************/ +void test_json_throttle_spec_bad_command_type() +{ + MEMORY_CHUNK post; + int domain; + + /***************************************************************************/ + /* Search for "dodgy" in the JSON, and you will see the dodgy bits we're */ + /* handling in these tests. */ + /***************************************************************************/ + #define NUM_BAD_COMMANDS 8 + char * json_command_list_dodgy_command = + "{" + "\"commandList\": [" + "{" + "\"command\": {" + "\"commandType\": \"dodgyCommand\", " + "\"eventDomainThrottleSpecification\": {" + "\"eventDomain\": \"fault\", " + "\"suppressedFieldNames\": [\"alarmInterfaceA\"], " + "\"suppressedNvPairsList\": [" + "{" + "\"nvPairFieldName\": \"alarmAdditionalInformation\", " + "\"suppressedNvPairNames\": [\"name1\"]" + "}]}}}" + "]" + "}"; + + char * json_command_list_dodgy_spec = + "{" + "\"commandList\": [" + "{" + "\"command\": {" + "\"commandType\": \"throttlingSpecification\", " + "\"dodgyEventDomainThrottleSpecification\": {" + "\"eventDomain\": \"fault\", " + "\"suppressedFieldNames\": [\"alarmInterfaceA\"], " + "\"suppressedNvPairsList\": [" + "{" + "\"nvPairFieldName\": \"alarmAdditionalInformation\", " + "\"suppressedNvPairNames\": [\"name1\"]" + "}]}}}" + "]" + "}"; + + char * json_command_list_dodgy_event_domain_key = + "{" + "\"commandList\": [" + "{" + "\"command\": {" + "\"commandType\": \"throttlingSpecification\", " + "\"eventDomainThrottleSpecification\": {" + "\"dodgyEventDomainKey\": \"fault\", " + "\"suppressedFieldNames\": [\"alarmInterfaceA\"], " + "\"suppressedNvPairsList\": [" + "{" + "\"nvPairFieldName\": \"alarmAdditionalInformation\", " + "\"suppressedNvPairNames\": [\"name1\"]" + "}]}}}" + "]" + "}"; + + char * json_command_list_dodgy_event_domain = + "{" + "\"commandList\": [" + "{" + "\"command\": {" + "\"commandType\": \"throttlingSpecification\", " + "\"eventDomainThrottleSpecification\": {" + "\"eventDomain\": \"dodgyEventDomain\", " + "\"suppressedFieldNames\": [\"alarmInterfaceA\"], " + "\"suppressedNvPairsList\": [" + "{" + "\"nvPairFieldName\": \"alarmAdditionalInformation\", " + "\"suppressedNvPairNames\": [\"name1\"]" + "}]}}}" + "]" + "}"; + + char * json_command_list_dodgy_field_names_key = + "{" + "\"commandList\": [" + "{" + "\"command\": {" + "\"commandType\": \"throttlingSpecification\", " + "\"eventDomainThrottleSpecification\": {" + "\"eventDomain\": \"fault\", " + "\"suppressedNvPairsList\": [" + "{" + "\"nvPairFieldName\": \"alarmAdditionalInformation\", " + "\"suppressedNvPairNames\": [\"name1\"]" + "}]}}}" + "]" + "}"; + + char * json_command_list_dodgy_pair_names_list_key = + "{" + "\"commandList\": [" + "{" + "\"command\": {" + "\"commandType\": \"throttlingSpecification\", " + "\"eventDomainThrottleSpecification\": {" + "\"eventDomain\": \"fault\", " + "\"suppressedFieldNames\": [\"alarmInterfaceA\"], " + "\"dodgySuppressedNvPairsListKey\": [" + "{" + "\"nvPairFieldName\": \"alarmAdditionalInformation\", " + "\"suppressedNvPairNames\": [\"name1\"]" + "}]}}}" + "]" + "}"; + + char * json_command_list_dodgy_pair_field_name_key = + "{" + "\"commandList\": [" + "{" + "\"command\": {" + "\"commandType\": \"throttlingSpecification\", " + "\"eventDomainThrottleSpecification\": {" + "\"eventDomain\": \"fault\", " + "\"suppressedFieldNames\": [\"alarmInterfaceA\"], " + "\"suppressedNvPairsList\": [" + "{" + "\"dodgyNvPairFieldNameKey\": \"alarmAdditionalInformation\", " + "\"suppressedNvPairNames\": [\"name1\"]" + "}]}}}" + "]" + "}"; + + char * json_command_list_dodgy_pair_names_key = + "{" + "\"commandList\": [" + "{" + "\"command\": {" + "\"commandType\": \"throttlingSpecification\", " + "\"eventDomainThrottleSpecification\": {" + "\"eventDomain\": \"fault\", " + "\"suppressedFieldNames\": [\"alarmInterfaceA\"], " + "\"suppressedNvPairsList\": [" + "{" + "\"nvPairFieldName\": \"alarmAdditionalInformation\", " + "\"dodgySuppressedNvPairNamesKey\": [\"name1\"]" + "}]}}}" + "]" + "}"; + + char * json_command_list_dodgy_depth = + "{" + "\"commandList\": [" + "{" + "\"command\": {" + "\"commandType\": \"throttlingSpecification\", " + "\"eventDomainThrottleSpecification\": {" + "\"eventDomain\": \"fault\", " + "\"suppressedFieldNames\": [\"alarmInterfaceA\"], " + "\"suppressedNvPairsList\": [" + "{" + "\"nvPairFieldName\": \"alarmAdditionalInformation\", " + "\"dodgySuppressedNvPairNamesKey\": " + "[\"name1\", [[[[[[[[]]]]]]]]]" + "}]}}}" + "]" + "}"; + + char * expected_throttle_state_dodgy_field_names_key = + "{" + "\"eventThrottlingState\": {" + "\"eventThrottlingMode\": \"throttled\", " + "\"eventDomainThrottleSpecificationList\": [" + "{" + "\"eventDomain\": \"fault\", " + "\"suppressedNvPairsList\": [" + "{" + "\"nvPairFieldName\": \"alarmAdditionalInformation\", " + "\"suppressedNvPairNames\": [\"name1\"]" + "}]}" + "]" + "}" + "}"; + + char * expected_throttle_state_dodgy_pair_names_list_key = + "{" + "\"eventThrottlingState\": {" + "\"eventThrottlingMode\": \"throttled\", " + "\"eventDomainThrottleSpecificationList\": [" + "{" + "\"eventDomain\": \"fault\", " + "\"suppressedFieldNames\": [\"alarmInterfaceA\"]" + "}" + "]" + "}" + "}"; + + char * expected_throttle_state_dodgy_pair_field_name_key = + "{" + "\"eventThrottlingState\": {" + "\"eventThrottlingMode\": \"throttled\", " + "\"eventDomainThrottleSpecificationList\": [" + "{" + "\"eventDomain\": \"fault\", " + "\"suppressedFieldNames\": [\"alarmInterfaceA\"]" + "}" + "]" + "}" + "}"; + + char * expected_throttle_state_dodgy_pair_names_key = + "{" + "\"eventThrottlingState\": {" + "\"eventThrottlingMode\": \"throttled\", " + "\"eventDomainThrottleSpecificationList\": [" + "{" + "\"eventDomain\": \"fault\", " + "\"suppressedFieldNames\": [\"alarmInterfaceA\"]" + "}" + "]" + "}" + "}"; + + char * json_command_lists[] = { + json_command_list_dodgy_command, + json_command_list_dodgy_spec, + json_command_list_dodgy_event_domain_key, + json_command_list_dodgy_event_domain, + json_command_list_dodgy_depth, + json_command_list_dodgy_field_names_key, + json_command_list_dodgy_pair_names_list_key, + json_command_list_dodgy_pair_field_name_key, + json_command_list_dodgy_pair_names_key + }; + + char * expected_posts[] = { + expected_throttle_state_normal, + expected_throttle_state_normal, + expected_throttle_state_normal, + expected_throttle_state_normal, + expected_throttle_state_normal, + expected_throttle_state_dodgy_field_names_key, + expected_throttle_state_dodgy_pair_names_list_key, + expected_throttle_state_dodgy_pair_field_name_key, + expected_throttle_state_dodgy_pair_names_key + }; + + const int num_commands = + sizeof(json_command_lists) / sizeof(json_command_lists[0]); + const int num_posts = + sizeof(expected_posts) / sizeof(expected_posts[0]); + assert(num_commands == num_posts); + + /***************************************************************************/ + /* Initialize and provide a specification with a single nvpair with a */ + /* single sub-field suppressed. */ + /***************************************************************************/ + evel_throttle_initialize(); + + int ii; + for (ii = 0; ii < num_commands; ii++) + { + EVEL_DEBUG("Testing commandList[%d] = %s\n", ii, json_command_lists[ii]); + handle_json_response(json_command_lists[ii], &post); + + /*************************************************************************/ + /* Check that throttling is in a normal state - because we ignored the */ + /* command / ..... */ + /*************************************************************************/ + for (domain = EVEL_DOMAIN_MEASUREMENT; domain < EVEL_MAX_DOMAINS; domain++) + { + assert(evel_get_throttle_spec(domain) == NULL); + } + if (expected_posts[ii] == expected_throttle_state_normal) + { + assert(evel_get_throttle_spec(EVEL_DOMAIN_FAULT) == NULL); + } + else + { + assert(evel_get_throttle_spec(EVEL_DOMAIN_FAULT) != NULL); + } + assert(post.memory == NULL); + + /*************************************************************************/ + /* Request and verify the throttling state. */ + /*************************************************************************/ + handle_json_response(json_command_list_provide, &post); + assert(post.memory != NULL); + compare_strings(expected_posts[ii], + post.memory, + strlen(expected_posts[ii]), + "Throttle State Normal"); + free(post.memory); + post.memory = NULL; + } + + evel_throttle_terminate(); +} + +void test_encode_fault_throttled() +{ + MEMORY_CHUNK post; + + /***************************************************************************/ + /* We also test suppression of the event header parameters here. */ + /***************************************************************************/ + char * json_command_list = + "{" + "\"commandList\": [" + "{" + "\"command\": {" + "\"commandType\": \"throttlingSpecification\", " + "\"eventDomainThrottleSpecification\": {" + "\"eventDomain\": \"fault\", " + "\"suppressedFieldNames\": [" + "\"alarmInterfaceA\", " + "\"eventType\", " + "\"reportingEntityId\", " + "\"sourceId\"], " + "\"suppressedNvPairsList\": [" + "{" + "\"nvPairFieldName\": \"alarmAdditionalInformation\", " + "\"suppressedNvPairNames\": [\"name3\", \"name4\"]" + "}]}}}" + "]" + "}"; + + char * expected = + "{\"event\": {" + "\"commonEventHeader\": {" + "\"domain\": \"fault\", " + "\"eventId\": \"122\", " + "\"functionalRole\": \"UNIT TEST\", " + "\"lastEpochMicrosec\": 1000002, " + "\"priority\": \"Normal\", " + "\"reportingEntityName\": \"Dummy VM name - No Metadata available\", " + "\"sequence\": 122, " + "\"sourceName\": \"Dummy VM name - No Metadata available\", " + "\"startEpochMicrosec\": 1000002, " + "\"version\": 1.2" + "}, " + "\"faultFields\": {" + "\"alarmCondition\": \"My alarm condition\", " + "\"eventSeverity\": \"MAJOR\", " + "\"eventSourceType\": \"other\", " + "\"specificProblem\": \"It broke very badly\", " + "\"vfStatus\": \"Active\", " + "\"faultFieldsVersion\": 1.1, " + "\"alarmAdditionalInformation\": [" + "{\"name\": \"name1\", " + "\"value\": \"value1\"}, " + "{\"name\": \"name2\", " + "\"value\": \"value2\"}]" + "}}}"; + + /***************************************************************************/ + /* Initialize and provide a specification with a single fault suppressed. */ + /***************************************************************************/ + evel_throttle_initialize(); + handle_json_response(json_command_list, &post); + + /***************************************************************************/ + /* Check that the domain is throttled. */ + /***************************************************************************/ + assert(evel_get_throttle_spec(EVEL_DOMAIN_FAULT) != NULL); + assert(post.memory == NULL); + + size_t json_size = 0; + char json_body[EVEL_MAX_JSON_BODY]; + evel_set_next_event_sequence(122); + EVENT_FAULT * fault = evel_new_fault("My alarm condition", + "It broke very badly", + EVEL_PRIORITY_NORMAL, + EVEL_SEVERITY_MAJOR, + EVEL_SOURCE_HOST, + EVEL_VF_STATUS_PREP_TERMINATE); + assert(fault != NULL); + evel_fault_type_set(fault, "Bad things happen..."); + evel_fault_addl_info_add(fault, "name1", "value1"); + evel_fault_addl_info_add(fault, "name2", "value2"); + + /***************************************************************************/ + /* Suppressed fields. */ + /***************************************************************************/ + evel_fault_interface_set(fault, "My Interface Card"); + evel_fault_addl_info_add(fault, "name3", "value3"); + evel_fault_addl_info_add(fault, "name4", "value4"); + + json_size = evel_json_encode_event( + json_body, EVEL_MAX_JSON_BODY, (EVENT_HEADER *) fault); + compare_strings(expected, json_body, EVEL_MAX_JSON_BODY, "Fault"); + assert((json_size == strlen(json_body)) && "Bad size returned"); + + evel_free_event(fault); + evel_throttle_terminate(); +} + +void test_encode_measurement_throttled() +{ + MEMORY_CHUNK post; + + /***************************************************************************/ + /* We also test suppression of the event header parameters here. */ + /***************************************************************************/ + char * json_command_list = + "{" + "\"commandList\": [" + "{" + "\"command\": {" + "\"commandType\": \"throttlingSpecification\", " + "\"eventDomainThrottleSpecification\": {" + "\"eventDomain\": \"measurementsForVfScaling\", " + "\"suppressedFieldNames\": [" + "\"errors\", " + "\"vnfcScalingMetric\", " + "\"numberOfMediaPortsInUse\", " + "\"aggregateCpuUsage\", " + "\"requestRate\", " + "\"memoryUsed\", " + "\"memoryConfigured\", " + "\"meanRequestLatency\", " + "\"latencyDistribution\", " + "\"concurrentSessions\", " + "\"configuredEntities\", " + "\"eventType\", " + "\"reportingEntityId\", " + "\"sourceId\"], " + "\"suppressedNvPairsList\": [" + "{" + "\"nvPairFieldName\": \"cpuUsageArray\", " + "\"suppressedNvPairNames\": [\"cpu3\", \"cpu4\"]" + "}, " + "{" + "\"nvPairFieldName\": \"filesystemUsageArray\", " + "\"suppressedNvPairNames\": [\"00-11-22\", \"33-44-55\"]" + "}, " + "{" + "\"nvPairFieldName\": \"vNicUsageArray\", " + "\"suppressedNvPairNames\": [\"eth1\", \"eth0\"]" + "}, " + "{" + "\"nvPairFieldName\": \"featureUsageArray\", " + "\"suppressedNvPairNames\": [\"FeatureB\", \"FeatureC\"]" + "}," + "{" + "\"nvPairFieldName\": \"codecUsageArray\", " + "\"suppressedNvPairNames\": [\"G729ab\"]" + "}," + "{" + "\"nvPairFieldName\": \"additionalMeasurements\", " + "\"suppressedNvPairNames\": [\"Group2\"]" + "}" + "]}}}" + "]" + "}"; + + char * expected = + "{\"event\": " + "{\"commonEventHeader\": {" + "\"domain\": \"measurementsForVfScaling\", " + "\"eventId\": \"123\", " + "\"functionalRole\": \"UNIT TEST\", " + "\"lastEpochMicrosec\": 1000002, " + "\"priority\": \"Normal\", " + "\"reportingEntityName\": \"Dummy VM name - No Metadata available\", " + "\"sequence\": 123, " + "\"sourceName\": \"Dummy VM name - No Metadata available\", " + "\"startEpochMicrosec\": 1000002, " + "\"version\": 1.2" + "}, " + "\"measurementsForVfScalingFields\": " + "{" + "\"measurementInterval\": 5.500000, " + "\"cpuUsageArray\": [" + "{\"cpuIdentifier\": \"cpu1\", " + "\"percentUsage\": 11.110000}, " + "{\"cpuIdentifier\": \"cpu2\", " + "\"percentUsage\": 22.220000}], " + "\"filesystemUsageArray\": [" + "{\"blockConfigured\": 500.110000, " + "\"blockIops\": 77, " + "\"blockUsed\": 500.220000, " + "\"ephemeralConfigured\": 500.110000, " + "\"ephemeralIops\": 88, " + "\"ephemeralUsed\": 600.220000, " + "\"filesystemName\": \"66-77-88\"}], " + "\"featureUsageArray\": [" + "{\"featureIdentifier\": \"FeatureA\", " + "\"featureUtilization\": 123}], " + "\"codecUsageArray\": [" + "{\"codecIdentifier\": \"G711a\", " + "\"numberInUse\": 91}], " + "\"additionalMeasurements\": [" + "{\"name\": \"Group1\", " + "\"measurements\": [" + "{\"name\": \"Name1\", " + "\"value\": \"Value1\"}]}], " + "\"measurementsForVfScalingVersion\": 1.1}}}"; + MEASUREMENT_CPU_USE *cpu_use; + + /***************************************************************************/ + /* Initialize and provide a specification with a single fault suppressed. */ + /***************************************************************************/ + evel_throttle_initialize(); + handle_json_response(json_command_list, &post); + + /***************************************************************************/ + /* Check that the domain is throttled. */ + /***************************************************************************/ + assert(evel_get_throttle_spec(EVEL_DOMAIN_MEASUREMENT) != NULL); + assert(post.memory == NULL); + + size_t json_size = 0; + char json_body[EVEL_MAX_JSON_BODY]; + evel_set_next_event_sequence(123); + EVENT_MEASUREMENT * measurement = evel_new_measurement(5.5); + MEASUREMENT_LATENCY_BUCKET * bucket = NULL; + MEASUREMENT_VNIC_PERFORMANCE * vnic_use = NULL; + assert(measurement != NULL); + + evel_measurement_type_set(measurement, "Perf management..."); + evel_measurement_conc_sess_set(measurement, 1); + evel_measurement_cfg_ents_set(measurement, 2); + evel_measurement_mean_req_lat_set(measurement, 4.4); + evel_measurement_mem_cfg_set(measurement, 6.6); + evel_measurement_mem_used_set(measurement, 3.3); + evel_measurement_request_rate_set(measurement, 7); + + cpu_use = evel_measurement_new_cpu_use_add(measurement, "cpu1", 11.11); + evel_measurement_cpu_use_idle_set(cpu_use,22.22); + evel_measurement_cpu_use_interrupt_set(cpu_use,33.33); + evel_measurement_cpu_use_nice_set(cpu_use,44.44); + evel_measurement_cpu_use_softirq_set(cpu_use,55.55); + evel_measurement_cpu_use_steal_set(cpu_use,66.66); + evel_measurement_cpu_use_system_set(cpu_use,77.77); + evel_measurement_cpu_use_usageuser_set(cpu_use,88.88); + evel_measurement_cpu_use_wait_set(cpu_use,99.99); + + cpu_use = evel_measurement_new_cpu_use_add(measurement, "cpu2", 22.22); + evel_measurement_cpu_use_idle_set(cpu_use,12.22); + evel_measurement_cpu_use_interrupt_set(cpu_use,33.33); + evel_measurement_cpu_use_nice_set(cpu_use,44.44); + evel_measurement_cpu_use_softirq_set(cpu_use,55.55); + evel_measurement_cpu_use_steal_set(cpu_use,66.66); + evel_measurement_cpu_use_system_set(cpu_use,77.77); + evel_measurement_cpu_use_usageuser_set(cpu_use,88.88); + evel_measurement_cpu_use_wait_set(cpu_use,19.99); + + evel_measurement_fsys_use_add(measurement, "00-11-22", + 100.11, 100.22, 33, + 200.11, 200.22, 44); + evel_measurement_fsys_use_add(measurement, "33-44-55", + 300.11, 300.22, 55, + 400.11, 400.22, 66); + evel_measurement_fsys_use_add(measurement, "66-77-88", + 500.11, 500.22, 77, + 600.11, 600.22, 88); + + bucket = evel_new_meas_latency_bucket(20); + evel_meas_latency_bucket_add(measurement, bucket); + + bucket = evel_new_meas_latency_bucket(30); + evel_meas_latency_bucket_low_end_set(bucket, 10.0); + evel_meas_latency_bucket_high_end_set(bucket, 20.0); + evel_meas_latency_bucket_add(measurement, bucket); + + vnic_use = evel_new_measurement_vnic_use("eth0", 100, 200, 3, 4); + evel_vnic_use_bcast_pkt_in_set(vnic_use, 1); + evel_vnic_use_bcast_pkt_out_set(vnic_use, 2); + evel_vnic_use_mcast_pkt_in_set(vnic_use, 5); + evel_vnic_use_mcast_pkt_out_set(vnic_use, 6); + evel_vnic_use_ucast_pkt_in_set(vnic_use, 7); + evel_vnic_use_ucast_pkt_out_set(vnic_use, 8); + evel_meas_vnic_use_add(measurement, vnic_use); + + vnic_use = evel_new_measurement_vnic_use("eth1", 110, 240, 13, 14); + evel_vnic_use_bcast_pkt_in_set(vnic_use, 11); + evel_vnic_use_bcast_pkt_out_set(vnic_use, 12); + evel_vnic_use_mcast_pkt_in_set(vnic_use, 15); + evel_vnic_use_mcast_pkt_out_set(vnic_use, 16); + evel_vnic_use_ucast_pkt_in_set(vnic_use, 17); + evel_vnic_use_ucast_pkt_out_set(vnic_use, 18); + evel_meas_vnic_use_add(measurement, vnic_use); + + evel_measurement_errors_set(measurement, 1, 0, 2, 1); + evel_measurement_feature_use_add(measurement, "FeatureA", 123); + evel_measurement_feature_use_add(measurement, "FeatureB", 567); + evel_measurement_codec_use_add(measurement, "G711a", 91); + evel_measurement_codec_use_add(measurement, "G729ab", 92); + evel_measurement_media_port_use_set(measurement, 1234); + evel_measurement_vnfc_scaling_metric_set(measurement, 1234.5678); + evel_measurement_custom_measurement_add(measurement, + "Group1", "Name1", "Value1"); + evel_measurement_custom_measurement_add(measurement, + "Group2", "Name1", "Value1"); + evel_measurement_custom_measurement_add(measurement, + "Group2", "Name2", "Value2"); + + json_size = evel_json_encode_event( + json_body, EVEL_MAX_JSON_BODY, (EVENT_HEADER *) measurement); + compare_strings(expected, json_body, EVEL_MAX_JSON_BODY, "Measurement"); + assert((json_size == strlen(json_body)) && "Bad size returned"); + + evel_free_event(measurement); + evel_throttle_terminate(); +} + +void test_encode_mobile_throttled() +{ + MEMORY_CHUNK post; + + /***************************************************************************/ + /* We also test suppression of the event header parameters here. */ + /***************************************************************************/ + char * json_command_list = + "{" + "\"commandList\": [" + "{" + "\"command\": {" + "\"commandType\": \"throttlingSpecification\", " + "\"eventDomainThrottleSpecification\": {" + "\"eventDomain\": \"mobileFlow\", " + "\"suppressedFieldNames\": [" + "\"applicationType\", " + "\"appProtocolType\", " + "\"appProtocolVersion\", " + "\"cid\", " + "\"connectionType\", " + "\"ecgi\", " + "\"gtpProtocolType\", " + "\"gtpVersion\", " + "\"httpHeader\", " + "\"imei\", " + "\"imsi\", " + "\"lac\", " + "\"mcc\", " + "\"mnc\", " + "\"msisdn\", " + "\"otherFunctionalRole\", " + "\"rac\", " + "\"radioAccessTechnology\", " + "\"sac\", " + "\"samplingAlgorithm\", " + "\"tac\", " + "\"tunnelId\", " + "\"vlanId\", " + "\"eventType\", " + "\"reportingEntityId\", " + "\"sourceId\"], " + "\"suppressedNvPairsList\": [" + "]}}}" + "]" + "}"; + + char * expected = + "{\"event\": " + "{\"commonEventHeader\": {" + "\"domain\": \"mobileFlow\", " + "\"eventId\": \"1242\", " + "\"functionalRole\": \"UNIT TEST\", " + "\"lastEpochMicrosec\": 1000002, " + "\"priority\": \"Normal\", " + "\"reportingEntityName\": \"Dummy VM name - No Metadata available\", " + "\"sequence\": 1242, " + "\"sourceName\": \"Dummy VM name - No Metadata available\", " + "\"startEpochMicrosec\": 1000002, " + "\"version\": 1.2" + "}, " + "\"mobileFlowFields\": {" + "\"flowDirection\": \"Inbound\", " + "\"gtpPerFlowMetrics\": {" + "\"avgBitErrorRate\": 132.000100, " + "\"avgPacketDelayVariation\": 31.200000, " + "\"avgPacketLatency\": 101, " + "\"avgReceiveThroughput\": 2101, " + "\"avgTransmitThroughput\": 501, " + "\"flowActivationEpoch\": 1470409422, " + "\"flowActivationMicrosec\": 988, " + "\"flowDeactivationEpoch\": 1470409432, " + "\"flowDeactivationMicrosec\": 12, " + "\"flowDeactivationTime\": \"Fri, 05 Aug 2016 15:03:52 +0000\", " + "\"flowStatus\": \"Inactive\", " + "\"maxPacketDelayVariation\": 88, " + "\"numActivationFailures\": 4, " + "\"numBitErrors\": 18, " + "\"numBytesReceived\": 123655, " + "\"numBytesTransmitted\": 4562, " + "\"numDroppedPackets\": 1, " + "\"numL7BytesReceived\": 13, " + "\"numL7BytesTransmitted\": 11, " + "\"numLostPackets\": 2, " + "\"numOutOfOrderPackets\": 4, " + "\"numPacketErrors\": 8, " + "\"numPacketsReceivedExclRetrans\": 900, " + "\"numPacketsReceivedInclRetrans\": 902, " + "\"numPacketsTransmittedInclRetrans\": 303, " + "\"numRetries\": 7, " + "\"numTimeouts\": 3, " + "\"numTunneledL7BytesReceived\": 1, " + "\"roundTripTime\": 111, " + "\"timeToFirstByte\": 226, " + "\"ipTosCountList\": [" + "[\"1\", 13], " + "[\"4\", 99], " + "[\"17\", 1]], " + "\"ipTosList\": [\"1\", \"4\", \"17\"], " + "\"tcpFlagList\": [\"CWR\", \"URG\"], " + "\"tcpFlagCountList\": [[\"CWR\", 10], [\"URG\", 121]], " + "\"mobileQciCosList\": [\"conversational\", \"65\"], " + "\"mobileQciCosCountList\": [[\"conversational\", 11], [\"65\", 122]], " + "\"durConnectionFailedStatus\": 12, " + "\"durTunnelFailedStatus\": 13, " + "\"flowActivatedBy\": \"Remote\", " + "\"flowActivationTime\": \"Fri, 05 Aug 2016 15:03:43 +0000\", " + "\"flowDeactivatedBy\": \"Remote\", " + "\"gtpConnectionStatus\": \"Connected\", " + "\"gtpTunnelStatus\": \"Not tunneling\", " + "\"largePacketRtt\": 80, " + "\"largePacketThreshold\": 600.000000, " + "\"maxReceiveBitRate\": 1357924680, " + "\"maxTransmitBitRate\": 235711, " + "\"numGtpEchoFailures\": 1, " + "\"numGtpTunnelErrors\": 4, " + "\"numHttpErrors\": 2" + "}, " + "\"ipProtocolType\": \"UDP\", " + "\"ipVersion\": \"IPv6\", " + "\"otherEndpointIpAddress\": \"2.3.4.2\", " + "\"otherEndpointPort\": 2342, " + "\"reportingEndpointIpAddr\": \"4.2.3.2\", " + "\"reportingEndpointPort\": 4322" + "}}}"; + + /***************************************************************************/ + /* Initialize and provide a specification with a single fault suppressed. */ + /***************************************************************************/ + evel_throttle_initialize(); + handle_json_response(json_command_list, &post); + + /***************************************************************************/ + /* Check that the domain is throttled. */ + /***************************************************************************/ + assert(evel_get_throttle_spec(EVEL_DOMAIN_MOBILE_FLOW) != NULL); + assert(post.memory == NULL); + + size_t json_size = 0; + char json_body[EVEL_MAX_JSON_BODY]; + MOBILE_GTP_PER_FLOW_METRICS * metrics = NULL; + EVENT_MOBILE_FLOW * mobile_flow = NULL; + + /***************************************************************************/ + /* Mobile. */ + /***************************************************************************/ + evel_set_next_event_sequence(1242); + + metrics = evel_new_mobile_gtp_flow_metrics(132.0001, + 31.2, + 101, + 2101, + 501, + 1470409422, + 988, + 1470409432, + 12, + (time_t)1470409432, + "Inactive", + 88, + 4, + 18, + 123655, + 4562, + 1, + 13, + 11, + 2, + 4, + 8, + 900, + 902, + 303, + 7, + 3, + 1, + 111, + 226); + assert(metrics != NULL); + + evel_mobile_gtp_metrics_dur_con_fail_set(metrics, 12); + evel_mobile_gtp_metrics_dur_tun_fail_set(metrics, 13); + evel_mobile_gtp_metrics_act_by_set(metrics, "Remote"); + evel_mobile_gtp_metrics_act_time_set(metrics, (time_t)1470409423); + evel_mobile_gtp_metrics_deact_by_set(metrics, "Remote"); + evel_mobile_gtp_metrics_con_status_set(metrics, "Connected"); + evel_mobile_gtp_metrics_tun_status_set(metrics, "Not tunneling"); + evel_mobile_gtp_metrics_iptos_set(metrics, 1, 13); + evel_mobile_gtp_metrics_iptos_set(metrics, 17, 1); + evel_mobile_gtp_metrics_iptos_set(metrics, 4, 99); + evel_mobile_gtp_metrics_large_pkt_rtt_set(metrics, 80); + evel_mobile_gtp_metrics_large_pkt_thresh_set(metrics, 600.0); + evel_mobile_gtp_metrics_max_rcv_bit_rate_set(metrics, 1357924680); + evel_mobile_gtp_metrics_max_trx_bit_rate_set(metrics, 235711); + evel_mobile_gtp_metrics_num_echo_fail_set(metrics, 1); + evel_mobile_gtp_metrics_num_tun_fail_set(metrics, 4); + evel_mobile_gtp_metrics_num_http_errors_set(metrics, 2); + evel_mobile_gtp_metrics_tcp_flag_count_add(metrics, EVEL_TCP_CWR, 10); + evel_mobile_gtp_metrics_tcp_flag_count_add(metrics, EVEL_TCP_URG, 121); + evel_mobile_gtp_metrics_qci_cos_count_add( + metrics, EVEL_QCI_COS_UMTS_CONVERSATIONAL, 11); + evel_mobile_gtp_metrics_qci_cos_count_add( + metrics, EVEL_QCI_COS_LTE_65, 122); + + mobile_flow = evel_new_mobile_flow("Inbound", + metrics, + "UDP", + "IPv6", + "2.3.4.2", + 2342, + "4.2.3.2", + 4322); + assert(mobile_flow != NULL); + + evel_mobile_flow_type_set(mobile_flow, "Mobile flow..."); + evel_mobile_flow_app_type_set(mobile_flow, "Demo application"); + evel_mobile_flow_app_prot_type_set(mobile_flow, "GSM"); + evel_mobile_flow_app_prot_ver_set(mobile_flow, "1"); + evel_mobile_flow_cid_set(mobile_flow, "65535"); + evel_mobile_flow_con_type_set(mobile_flow, "S1-U"); + evel_mobile_flow_ecgi_set(mobile_flow, "e65535"); + evel_mobile_flow_gtp_prot_type_set(mobile_flow, "GTP-U"); + evel_mobile_flow_gtp_prot_ver_set(mobile_flow, "1"); + evel_mobile_flow_http_header_set(mobile_flow, + "http://www.something.com"); + evel_mobile_flow_imei_set(mobile_flow, "209917614823"); + evel_mobile_flow_imsi_set(mobile_flow, "355251/05/850925/8"); + evel_mobile_flow_lac_set(mobile_flow, "1"); + evel_mobile_flow_mcc_set(mobile_flow, "410"); + evel_mobile_flow_mnc_set(mobile_flow, "04"); + evel_mobile_flow_msisdn_set(mobile_flow, "6017123456789"); + evel_mobile_flow_other_func_role_set(mobile_flow, "MME"); + evel_mobile_flow_rac_set(mobile_flow, "514"); + evel_mobile_flow_radio_acc_tech_set(mobile_flow, "LTE"); + evel_mobile_flow_sac_set(mobile_flow, "1"); + evel_mobile_flow_samp_alg_set(mobile_flow, 1); + evel_mobile_flow_tac_set(mobile_flow, "2099"); + evel_mobile_flow_tunnel_id_set(mobile_flow, "Tunnel 1"); + evel_mobile_flow_vlan_id_set(mobile_flow, "15"); + + json_size = evel_json_encode_event( + json_body, EVEL_MAX_JSON_BODY, (EVENT_HEADER *) mobile_flow); + compare_strings(expected, json_body, EVEL_MAX_JSON_BODY, "Mobile"); + assert((json_size == strlen(json_body)) && "Bad size returned"); + + evel_free_event(mobile_flow); + evel_throttle_terminate(); +} + +void test_encode_other_throttled() +{ + MEMORY_CHUNK post; + + /***************************************************************************/ + /* We also test suppression of the event header parameters here. */ + /***************************************************************************/ + char * json_command_list = + "{" + "\"commandList\": [" + "{" + "\"command\": {" + "\"commandType\": \"throttlingSpecification\", " + "\"eventDomainThrottleSpecification\": {" + "\"eventDomain\": \"other\", " + "\"suppressedFieldNames\": [" + "\"eventType\", " + "\"reportingEntityId\", " + "\"sourceId\"], " + "\"suppressedNvPairsList\": [" + "]}}}" + "]" + "}"; + + char * expected = + "{\"event\": " + "{\"commonEventHeader\": {" + "\"domain\": \"other\", " + "\"eventId\": \"129\", " + "\"functionalRole\": \"UNIT TEST\", " + "\"lastEpochMicrosec\": 1000002, " + "\"priority\": \"Normal\", " + "\"reportingEntityName\": \"Dummy VM name - No Metadata available\", " + "\"sequence\": 129, " + "\"sourceName\": \"Dummy VM name - No Metadata available\", " + "\"startEpochMicrosec\": 1000002, " + "\"version\": 1.2" + "}, " + "\"otherFields\": [" + "{\"name\": \"Other field 1\", " + "\"value\": \"Other value 1\"}, " + "{\"name\": \"Other field 2\", " + "\"value\": \"Other value 2\"}" + "]" + "}}"; + + /***************************************************************************/ + /* Initialize and provide a specification with a single fault suppressed. */ + /***************************************************************************/ + evel_throttle_initialize(); + handle_json_response(json_command_list, &post); + + /***************************************************************************/ + /* Check that the domain is throttled. */ + /***************************************************************************/ + assert(evel_get_throttle_spec(EVEL_DOMAIN_OTHER) != NULL); + assert(post.memory == NULL); + + size_t json_size = 0; + char json_body[EVEL_MAX_JSON_BODY]; + EVENT_OTHER * other = NULL; + evel_set_next_event_sequence(129); + other = evel_new_other(); + assert(other != NULL); + evel_other_type_set(other, "Other Type"); + evel_other_field_add(other, + "Other field 1", + "Other value 1"); + evel_other_field_add(other, + "Other field 2", + "Other value 2"); + + json_size = evel_json_encode_event( + json_body, EVEL_MAX_JSON_BODY, (EVENT_HEADER *) other); + compare_strings(expected, json_body, EVEL_MAX_JSON_BODY, "Other"); + assert((json_size == strlen(json_body)) && "Bad size returned"); + + evel_free_event(other); + evel_throttle_terminate(); +} + +void test_encode_report_throttled() +{ + MEMORY_CHUNK post; + + /***************************************************************************/ + /* We also test suppression of the event header parameters here. */ + /***************************************************************************/ + char * json_command_list = + "{" + "\"commandList\": [" + "{" + "\"command\": {" + "\"commandType\": \"throttlingSpecification\", " + "\"eventDomainThrottleSpecification\": {" + "\"eventDomain\": \"report\", " + "\"suppressedFieldNames\": [" + "\"eventType\", " + "\"reportingEntityId\", " + "\"sourceId\"], " + "\"suppressedNvPairsList\": [" + "{" + "\"nvPairFieldName\": \"featureUsageArray\", " + "\"suppressedNvPairNames\": [\"FeatureB\", \"FeatureC\"]" + "}," + "{" + "\"nvPairFieldName\": \"additionalMeasurements\", " + "\"suppressedNvPairNames\": [\"Group2\"]" + "}" + "]}}}" + "]" + "}"; + + char * expected = + "{\"event\": " + "{\"commonEventHeader\": {" + "\"domain\": \"measurementsForVfReporting\", " + "\"eventId\": \"125\", " + "\"functionalRole\": \"UNIT TEST\", " + "\"lastEpochMicrosec\": 1000002, " + "\"priority\": \"Normal\", " + "\"reportingEntityName\": \"Dummy VM name - No Metadata available\", " + "\"sequence\": 125, " + "\"sourceName\": \"Dummy VM name - No Metadata available\", " + "\"startEpochMicrosec\": 1000002, " + "\"version\": 1.2" + "}, " + "\"measurementsForVfReportingFields\": " + "{\"measurementInterval\": 1.100000, " + "\"featureUsageArray\": [" + "{\"featureIdentifier\": \"FeatureA\", " + "\"featureUtilization\": 123}], " + "\"additionalMeasurements\": [" + "{\"name\": \"Group1\", " + "\"measurements\": [" + "{\"name\": \"Name1\", " + "\"value\": \"Value1\"}]}], " + "\"measurementFieldsVersion\": 1.1}}}"; + + /***************************************************************************/ + /* Initialize and provide a specification with a single fault suppressed. */ + /***************************************************************************/ + evel_throttle_initialize(); + handle_json_response(json_command_list, &post); + + /***************************************************************************/ + /* Check that the domain is throttled. */ + /***************************************************************************/ + assert(evel_get_throttle_spec(EVEL_DOMAIN_REPORT) != NULL); + assert(post.memory == NULL); + + size_t json_size = 0; + char json_body[EVEL_MAX_JSON_BODY]; + EVENT_REPORT * report = NULL; + + /***************************************************************************/ + /* Report. */ + /***************************************************************************/ + evel_set_next_event_sequence(125); + report = evel_new_report(1.1); + assert(report != NULL); + evel_report_type_set(report, "Perf reporting..."); + evel_report_feature_use_add(report, "FeatureA", 123); + evel_report_feature_use_add(report, "FeatureB", 567); + evel_report_custom_measurement_add(report, "Group1", "Name1", "Value1"); + evel_report_custom_measurement_add(report, "Group2", "Name1", "Value1"); + evel_report_custom_measurement_add(report, "Group2", "Name2", "Value2"); + + json_size = evel_json_encode_event( + json_body, EVEL_MAX_JSON_BODY, (EVENT_HEADER *) report); + compare_strings(expected, json_body, EVEL_MAX_JSON_BODY, "Report"); + assert((json_size == strlen(json_body)) && "Bad size returned"); + + evel_free_event(report); + evel_throttle_terminate(); +} + +void test_encode_service_throttled() +{ + MEMORY_CHUNK post; + + /***************************************************************************/ + /* We also test suppression of the event header parameters here. */ + /***************************************************************************/ + char * json_command_list = + "{" + "\"commandList\": [" + "{" + "\"command\": {" + "\"commandType\": \"throttlingSpecification\", " + "\"eventDomainThrottleSpecification\": {" + "\"eventDomain\": \"serviceEvents\", " + "\"suppressedFieldNames\": [" + "\"eventType\", " + "\"correlator\", " + "\"codecSelected\", " + "\"codecSelectedTranscoding\", " + "\"endOfCallVqmSummaries\", " + "\"midCallRtcp\", " + "\"marker\", " + "\"reportingEntityId\", " + "\"sourceId\"], " + "\"suppressedNvPairsList\": [" + "{" + "\"nvPairFieldName\": \"additionalFields\", " + "\"suppressedNvPairNames\": [\"Name1\", \"Name3\"]" + "}" + "]}}}" + "]" + "}"; + + char * expected = + "{\"event\": " + "{\"commonEventHeader\": {" + "\"domain\": \"serviceEvents\", " + "\"eventId\": \"2000\", " + "\"functionalRole\": \"UNIT TEST\", " + "\"lastEpochMicrosec\": 1000002, " + "\"priority\": \"Normal\", " + "\"reportingEntityName\": \"Dummy VM name - No Metadata available\", " + "\"sequence\": 2000, " + "\"sourceName\": \"Dummy VM name - No Metadata available\", " + "\"startEpochMicrosec\": 1000002, " + "\"version\": 1.2" + "}, " + "\"serviceEventsFields\": {" + "\"eventInstanceIdentifier\": " + "{" + "\"vendorId\": \"vendor_x_id\", " + "\"eventId\": \"vendor_x_event_id\", " + "\"productId\": \"vendor_x_product_id\", " + "\"subsystemId\": \"vendor_x_subsystem_id\", " + "\"eventFriendlyName\": \"vendor_x_frieldly_name\"" + "}, " + "\"serviceEventsFieldsVersion\": 1.1, " + "\"additionalFields\": [" + "{\"name\": \"Name2\", \"value\": \"Value2\"}, " + "{\"name\": \"Name4\", \"value\": \"Value4\"}]" + "}}}"; + + /***************************************************************************/ + /* Initialize and provide a specification with a single fault suppressed. */ + /***************************************************************************/ + evel_throttle_initialize(); + handle_json_response(json_command_list, &post); + + /***************************************************************************/ + /* Check that the domain is throttled. */ + /***************************************************************************/ + assert(evel_get_throttle_spec(EVEL_DOMAIN_SERVICE) != NULL); + assert(post.memory == NULL); + + size_t json_size = 0; + char json_body[EVEL_MAX_JSON_BODY]; + EVENT_SERVICE * event = NULL; + evel_set_next_event_sequence(2000); + event = evel_new_service("vendor_x_id", "vendor_x_event_id"); + assert(event != NULL); + evel_service_type_set(event, "Service Event"); + evel_service_product_id_set(event, "vendor_x_product_id"); + evel_service_subsystem_id_set(event, "vendor_x_subsystem_id"); + evel_service_friendly_name_set(event, "vendor_x_frieldly_name"); + evel_service_correlator_set(event, "vendor_x_correlator"); + evel_service_codec_set(event, "PCMA"); + evel_service_codec_set(event, "PCMA"); + evel_service_callee_codec_set(event, "PCMA"); + evel_service_caller_codec_set(event, "G729A"); + evel_service_rtcp_data_set(event, "some_rtcp_data"); + evel_service_adjacency_name_set(event, "vendor_x_adjacency"); + evel_service_endpoint_desc_set(event, EVEL_SERVICE_ENDPOINT_CALLER); + evel_service_endpoint_jitter_set(event, 66); + evel_service_endpoint_rtp_oct_disc_set(event, 100); + evel_service_endpoint_rtp_oct_recv_set(event, 200); + evel_service_endpoint_rtp_oct_sent_set(event, 300); + evel_service_endpoint_rtp_pkt_disc_set(event, 400); + evel_service_endpoint_rtp_pkt_recv_set(event, 500); + evel_service_endpoint_rtp_pkt_sent_set(event, 600); + evel_service_local_jitter_set(event, 99); + evel_service_local_rtp_oct_disc_set(event, 150); + evel_service_local_rtp_oct_recv_set(event, 250); + evel_service_local_rtp_oct_sent_set(event, 350); + evel_service_local_rtp_pkt_disc_set(event, 450); + evel_service_local_rtp_pkt_recv_set(event, 550); + evel_service_local_rtp_pkt_sent_set(event, 650); + evel_service_mos_cqe_set(event, 12.255); + evel_service_packets_lost_set(event, 157); + evel_service_packet_loss_percent_set(event, 0.232); + evel_service_r_factor_set(event, 11); + evel_service_round_trip_delay_set(event, 15); + evel_service_phone_number_set(event, "0888888888"); + evel_service_addl_field_add(event, "Name1", "Value1"); + evel_service_addl_field_add(event, "Name2", "Value2"); + evel_service_addl_field_add(event, "Name3", "Value3"); + evel_service_addl_field_add(event, "Name4", "Value4"); + json_size = evel_json_encode_event( + json_body, EVEL_MAX_JSON_BODY, (EVENT_HEADER *) event); + compare_strings(expected, json_body, EVEL_MAX_JSON_BODY, "Service"); + assert((json_size == strlen(json_body)) && "Bad size returned"); + + evel_free_event(event); + evel_throttle_terminate(); +} + +void test_encode_signaling_throttled() +{ + MEMORY_CHUNK post; + + /***************************************************************************/ + /* We also test suppression of the event header parameters here. */ + /***************************************************************************/ + char * json_command_list = + "{" + "\"commandList\": [" + "{" + "\"command\": {" + "\"commandType\": \"throttlingSpecification\", " + "\"eventDomainThrottleSpecification\": {" + "\"eventDomain\": \"signaling\", " + "\"suppressedFieldNames\": [" + "\"correlator\", " + "\"eventType\", " + "\"reportingEntityId\", " + "\"sourceId\", " + "\"localIpAddress\", " + "\"localPort\", " + "\"remoteIpAddress\", " + "\"remotePort\", " + "\"compressedSip\", " + "\"summarySip\"], " + "\"suppressedNvPairsList\": [" + "]}}}" + "]" + "}"; + + char * expected = + "{\"event\": " + "{\"commonEventHeader\": {" + "\"domain\": \"signaling\", " + "\"eventId\": \"2001\", " + "\"functionalRole\": \"UNIT TEST\", " + "\"lastEpochMicrosec\": 1000002, " + "\"priority\": \"Normal\", " + "\"reportingEntityName\": \"Dummy VM name - No Metadata available\", " + "\"sequence\": 2001, " + "\"sourceName\": \"Dummy VM name - No Metadata available\", " + "\"startEpochMicrosec\": 1000002, " + "\"version\": 1.2" + "}, " + "\"signalingFields\": {" + "\"eventInstanceIdentifier\": " + "{" + "\"vendorId\": \"vendor_x_id\", " + "\"eventId\": \"vendor_x_event_id\", " + "\"productId\": \"vendor_x_product_id\", " + "\"subsystemId\": \"vendor_x_subsystem_id\", " + "\"eventFriendlyName\": \"vendor_x_frieldly_name\"" + "}, " + "\"signalingFieldsVersion\": 1.1" + "}}}"; + + /***************************************************************************/ + /* Initialize and provide a specification with a single fault suppressed. */ + /***************************************************************************/ + evel_throttle_initialize(); + handle_json_response(json_command_list, &post); + + /***************************************************************************/ + /* Check that the domain is throttled. */ + /***************************************************************************/ + assert(evel_get_throttle_spec(EVEL_DOMAIN_SIGNALING) != NULL); + assert(post.memory == NULL); + + size_t json_size = 0; + char json_body[EVEL_MAX_JSON_BODY]; + EVENT_SIGNALING * event = NULL; + evel_set_next_event_sequence(2001); + event = evel_new_signaling("vendor_x_id", + "correlator", "1.0.3.1", "1234", "192.168.1.3","3456"); + assert(event != NULL); + evel_signaling_vnfmodule_name_set(event, "vendor_x_module"); + evel_signaling_vnfname_set(event, "vendor_x_vnf"); + evel_signaling_type_set(event, "Signaling"); + evel_signaling_product_id_set(event, "vendor_x_product_id"); + evel_signaling_subsystem_id_set(event, "vendor_x_subsystem_id"); + evel_signaling_friendly_name_set(event, "vendor_x_frieldly_name"); + evel_signaling_correlator_set(event, "vendor_x_correlator"); + evel_signaling_local_ip_address_set(event, "1.0.3.1"); + evel_signaling_local_port_set(event, "1031"); + evel_signaling_remote_ip_address_set(event, "5.3.3.0"); + evel_signaling_remote_port_set(event, "5330"); + evel_signaling_compressed_sip_set(event, "compressed_sip"); + evel_signaling_summary_sip_set(event, "summary_sip"); + json_size = evel_json_encode_event( + json_body, EVEL_MAX_JSON_BODY, (EVENT_HEADER *) event); + compare_strings(expected, json_body, EVEL_MAX_JSON_BODY, "Signaling"); + assert((json_size == strlen(json_body)) && "Bad size returned"); + + evel_free_event(event); + evel_throttle_terminate(); +} + +void test_encode_state_change_throttled() +{ + MEMORY_CHUNK post; + + /***************************************************************************/ + /* We also test suppression of the event header parameters here. */ + /***************************************************************************/ + char * json_command_list = + "{" + "\"commandList\": [" + "{" + "\"command\": {" + "\"commandType\": \"throttlingSpecification\", " + "\"eventDomainThrottleSpecification\": {" + "\"eventDomain\": \"stateChange\", " + "\"suppressedFieldNames\": [" + "\"eventType\", " + "\"reportingEntityId\", " + "\"sourceId\"], " + "\"suppressedNvPairsList\": [" + "{" + "\"nvPairFieldName\": \"additionalFields\", " + "\"suppressedNvPairNames\": [\"Name1\"]" + "}," + "]}}}" + "]" + "}"; + + char * expected = + "{\"event\": " + "{\"commonEventHeader\": {" + "\"domain\": \"stateChange\", " + "\"eventId\": \"128\", " + "\"functionalRole\": \"UNIT TEST\", " + "\"lastEpochMicrosec\": 1000002, " + "\"priority\": \"Normal\", " + "\"reportingEntityName\": \"Dummy VM name - No Metadata available\", " + "\"sequence\": 128, " + "\"sourceName\": \"Dummy VM name - No Metadata available\", " + "\"startEpochMicrosec\": 1000002, " + "\"version\": 1.2" + "}, " + "\"stateChangeFields\": {" + "\"newState\": \"inService\", " + "\"oldState\": \"outOfService\", " + "\"stateInterface\": \"An Interface\", " + "\"additionalFields\": [" + "{\"name\": \"Name2\", " + "\"value\": \"Value2\"}" + "], " + "\"stateChangeFieldsVersion\": 1.1" + "}}}"; + + /***************************************************************************/ + /* Initialize and provide a specification with a single fault suppressed. */ + /***************************************************************************/ + evel_throttle_initialize(); + handle_json_response(json_command_list, &post); + + /***************************************************************************/ + /* Check that the domain is throttled. */ + /***************************************************************************/ + assert(evel_get_throttle_spec(EVEL_DOMAIN_STATE_CHANGE) != NULL); + assert(post.memory == NULL); + + size_t json_size = 0; + char json_body[EVEL_MAX_JSON_BODY]; + EVENT_STATE_CHANGE * state_change = NULL; + evel_set_next_event_sequence(128); + state_change = evel_new_state_change(EVEL_ENTITY_STATE_IN_SERVICE, + EVEL_ENTITY_STATE_OUT_OF_SERVICE, + "An Interface"); + assert(state_change != NULL); + evel_state_change_type_set(state_change, "SC Type"); + evel_state_change_addl_field_add(state_change, "Name1", "Value1"); + evel_state_change_addl_field_add(state_change, "Name2", "Value2"); + + json_size = evel_json_encode_event( + json_body, EVEL_MAX_JSON_BODY, (EVENT_HEADER *) state_change); + compare_strings(expected, json_body, EVEL_MAX_JSON_BODY, "StateChange"); + assert((json_size == strlen(json_body)) && "Bad size returned"); + + evel_free_event(state_change); + evel_throttle_terminate(); +} + +void test_encode_syslog_throttled() +{ + MEMORY_CHUNK post; + + /***************************************************************************/ + /* We also test suppression of the event header parameters here. */ + /***************************************************************************/ + char * json_command_list = + "{" + "\"commandList\": [" + "{" + "\"command\": {" + "\"commandType\": \"throttlingSpecification\", " + "\"eventDomainThrottleSpecification\": {" + "\"eventDomain\": \"syslog\", " + "\"suppressedFieldNames\": [" + "\"eventSourceHost\", " + "\"syslogFacility\", " + "\"syslogProc\", " + "\"syslogProcId\", " + "\"syslogSData\", " + "\"syslogVer\", " + "\"eventType\", " + "\"reportingEntityId\", " + "\"sourceId\"], " + "\"suppressedNvPairsList\": [" + "{" + "\"nvPairFieldName\": \"additionalFields\", " + "\"suppressedNvPairNames\": [\"Name2\"]" + "}," + "]}}}" + "]" + "}"; + + char * expected = + "{\"event\": " + "{\"commonEventHeader\": {" + "\"domain\": \"syslog\", " + "\"eventId\": \"126\", " + "\"functionalRole\": \"UNIT TEST\", " + "\"lastEpochMicrosec\": 1000002, " + "\"priority\": \"Normal\", " + "\"reportingEntityName\": \"Dummy VM name - No Metadata available\", " + "\"sequence\": 126, " + "\"sourceName\": \"Dummy VM name - No Metadata available\", " + "\"startEpochMicrosec\": 1000002, " + "\"version\": 1.2" + "}, " + "\"syslogFields\": {" + "\"eventSourceType\": \"virtualNetworkFunction\", " + "\"syslogMsg\": \"SL Message\", " + "\"syslogTag\": \"SL Tag\", " + "\"syslogFieldsVersion\": 1.1, " + "\"additionalFields\": [" + "{\"name\": \"Name1\", " + "\"value\": \"Value1\"}" + "]" + "}}}"; + + /***************************************************************************/ + /* Initialize and provide a specification with a single fault suppressed. */ + /***************************************************************************/ + evel_throttle_initialize(); + handle_json_response(json_command_list, &post); + + /***************************************************************************/ + /* Check that the domain is throttled. */ + /***************************************************************************/ + assert(evel_get_throttle_spec(EVEL_DOMAIN_SYSLOG) != NULL); + assert(post.memory == NULL); + + size_t json_size = 0; + char json_body[EVEL_MAX_JSON_BODY]; + EVENT_SYSLOG * syslog = NULL; + evel_set_next_event_sequence(126); + syslog = evel_new_syslog(EVEL_SOURCE_VIRTUAL_NETWORK_FUNCTION, + "SL Message", + "SL Tag"); + assert(syslog != NULL); + evel_syslog_type_set(syslog, "SL Type"); + evel_syslog_event_source_host_set(syslog, "SL Host"); + evel_syslog_facility_set(syslog, EVEL_SYSLOG_FACILITY_LINE_PRINTER); + evel_syslog_proc_set(syslog, "SL Proc"); + evel_syslog_proc_id_set(syslog, 2); + evel_syslog_version_set(syslog, 1); + evel_syslog_s_data_set(syslog, "SL SDATA"); + evel_syslog_addl_field_add(syslog, "Name1", "Value1"); + evel_syslog_addl_field_add(syslog, "Name2", "Value2"); + + json_size = evel_json_encode_event( + json_body, EVEL_MAX_JSON_BODY, (EVENT_HEADER *) syslog); + compare_strings(expected, json_body, EVEL_MAX_JSON_BODY, "Syslog"); + assert((json_size == strlen(json_body)) && "Bad size returned"); + + evel_free_event(syslog); + evel_throttle_terminate(); +} + +void test_encode_fault_with_escaping() +{ + char * expected = + "{\"event\": {" + "\"commonEventHeader\": {" + "\"domain\": \"fault\", " + "\"eventId\": \"122\", " + "\"functionalRole\": \"UNIT TEST\", " + "\"lastEpochMicrosec\": 1000002, " + "\"priority\": \"Normal\", " + "\"reportingEntityName\": \"Dummy VM name - No Metadata available\", " + "\"sequence\": 122, " + "\"sourceName\": \"Dummy VM name - No Metadata available\", " + "\"startEpochMicrosec\": 1000002, " + "\"version\": 1.2, " + "\"eventType\": \"Bad things happen...\\\\\", " + "\"reportingEntityId\": \"Dummy VM UUID - No Metadata available\", " + "\"sourceId\": \"Dummy VM UUID - No Metadata available\"" + "}, " + "\"faultFields\": {" + "\"alarmCondition\": \"My alarm condition\", " + "\"eventSeverity\": \"MAJOR\", " + "\"eventSourceType\": \"other\", " + "\"specificProblem\": \"It broke \\\"very\\\" badly\", " + "\"vfStatus\": \"Active\", " + "\"faultFieldsVersion\": 1.1, " + "\"alarmAdditionalInformation\": [" + "{\"name\": \"name1\", " + "\"value\": \"value1\"}, " + "{\"name\": \"name2\", " + "\"value\": \"value2\"}], " + "\"alarmInterfaceA\": \"My Interface Card\"" + "}}}"; + + size_t json_size = 0; + char json_body[EVEL_MAX_JSON_BODY]; + evel_set_next_event_sequence(122); + EVENT_FAULT * fault = evel_new_fault("My alarm condition", + "It broke \"very\" badly", + EVEL_PRIORITY_NORMAL, + EVEL_SEVERITY_MAJOR, + EVEL_SOURCE_HOST, + EVEL_VF_STATUS_PREP_TERMINATE); + assert(fault != NULL); + evel_fault_type_set(fault, "Bad things happen...\\"); + evel_fault_interface_set(fault, "My Interface Card"); + evel_fault_addl_info_add(fault, "name1", "value1"); + evel_fault_addl_info_add(fault, "name2", "value2"); + + json_size = evel_json_encode_event( + json_body, EVEL_MAX_JSON_BODY, (EVENT_HEADER *) fault); + compare_strings(expected, json_body, EVEL_MAX_JSON_BODY, "Fault"); + assert((json_size == strlen(json_body)) && "Bad size returned"); + + evel_free_event(fault); +} diff --git a/veslibrary/ves_clibrary/evel/evel-library/docs/source/evel/README b/veslibrary/ves_clibrary/evel/evel-library/docs/source/evel/README new file mode 100644 index 0000000..89e7a3a --- /dev/null +++ b/veslibrary/ves_clibrary/evel/evel-library/docs/source/evel/README @@ -0,0 +1 @@ +Generated source code documentation. \ No newline at end of file diff --git a/veslibrary/ves_clibrary/evel/evel-library/libs/x86_64/README b/veslibrary/ves_clibrary/evel/evel-library/libs/x86_64/README new file mode 100644 index 0000000..760fdc1 --- /dev/null +++ b/veslibrary/ves_clibrary/evel/evel-library/libs/x86_64/README @@ -0,0 +1 @@ +Generated libraries. \ No newline at end of file diff --git a/veslibrary/ves_clibrary/evel/evel-library/output/x86_64/README b/veslibrary/ves_clibrary/evel/evel-library/output/x86_64/README new file mode 100644 index 0000000..d1c9f1f --- /dev/null +++ b/veslibrary/ves_clibrary/evel/evel-library/output/x86_64/README @@ -0,0 +1 @@ +Generated executables. \ No newline at end of file diff --git a/veslibrary/ves_clibrary/evel/evel-library/readme.md b/veslibrary/ves_clibrary/evel/evel-library/readme.md new file mode 100644 index 0000000..65ce4ef --- /dev/null +++ b/veslibrary/ves_clibrary/evel/evel-library/readme.md @@ -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/veslibrary/ves_clibrary/evel/evel-test-collector/LICENSE.md b/veslibrary/ves_clibrary/evel/evel-test-collector/LICENSE.md new file mode 100644 index 0000000..afb56c9 --- /dev/null +++ b/veslibrary/ves_clibrary/evel/evel-test-collector/LICENSE.md @@ -0,0 +1,18 @@ +/*************************************************************************//** + * + * 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. + * + ****************************************************************************/ + + diff --git a/veslibrary/ves_clibrary/evel/evel-test-collector/README.md b/veslibrary/ves_clibrary/evel/evel-test-collector/README.md new file mode 100644 index 0000000..b81ada3 --- /dev/null +++ b/veslibrary/ves_clibrary/evel/evel-test-collector/README.md @@ -0,0 +1,30 @@ +# ECOMP Vendor Event Listener API Test Collector + +This project contains a Python application that represents a test version of +the ECOMP Vendor Event Listener API. For an overview of ECOMP, see the +[ECOMP White Paper](http://att.com/ECOMP). For an overview of the +ECOMP Vendor Event Listener, see the +[ECOMP Vendor Event Listener Library project](http://github.com/blsaws/evel-library). + +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 + +Clone this project, and follow the instructions in the [Test Collector User +Guide](./docs/test_collector_user_guide/test_collector_user_guide.md). + +# Use + +The code is documented using docstrings - start from the +[Test Collector](./code/collector/collector.py). + +For further information see the [Vendor Event Listener +specification](./docs/att_interface_definition/att_service_specification.docx). \ No newline at end of file diff --git a/veslibrary/ves_clibrary/evel/evel-test-collector/code/collector/LICENSE.TXT b/veslibrary/ves_clibrary/evel/evel-test-collector/code/collector/LICENSE.TXT new file mode 100644 index 0000000..ae12da2 --- /dev/null +++ b/veslibrary/ves_clibrary/evel/evel-test-collector/code/collector/LICENSE.TXT @@ -0,0 +1,22 @@ +/* + * ============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. + * + */ diff --git a/veslibrary/ves_clibrary/evel/evel-test-collector/code/collector/__init__.py b/veslibrary/ves_clibrary/evel/evel-test-collector/code/collector/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/veslibrary/ves_clibrary/evel/evel-test-collector/code/collector/collector.py b/veslibrary/ves_clibrary/evel/evel-test-collector/code/collector/collector.py new file mode 100644 index 0000000..8e702aa --- /dev/null +++ b/veslibrary/ves_clibrary/evel/evel-test-collector/code/collector/collector.py @@ -0,0 +1,643 @@ +#!/usr/bin/env python +''' +Program which acts as the collector for the Vendor Event Listener REST API. + +Only intended for test purposes. + +License +------- + + * =================================================================== + * 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. +''' + +from rest_dispatcher import PathDispatcher, set_404_content +from wsgiref.simple_server import make_server +import sys +import os +import platform +import traceback +import time +from argparse import ArgumentParser, ArgumentDefaultsHelpFormatter +import ConfigParser +import logging.handlers +from base64 import b64decode +import string +import json +import jsonschema +from functools import partial + +_hello_resp = '''\ + + + Hello {name} + + +

Hello {name}!

+ +''' + +_localtime_resp = '''\ + +''' + +__all__ = [] +__version__ = 0.1 +__date__ = '2015-12-04' +__updated__ = '2015-12-04' + +TESTRUN = False +DEBUG = False +PROFILE = False + +#------------------------------------------------------------------------------ +# Credentials we expect clients to authenticate themselves with. +#------------------------------------------------------------------------------ +vel_username = '' +vel_password = '' + +#------------------------------------------------------------------------------ +# The JSON schema which we will use to validate events. +#------------------------------------------------------------------------------ +vel_schema = None + +#------------------------------------------------------------------------------ +# The JSON schema which we will use to validate client throttle state. +#------------------------------------------------------------------------------ +throttle_schema = None + +#------------------------------------------------------------------------------ +# The JSON schema which we will use to provoke throttling commands for testing. +#------------------------------------------------------------------------------ +test_control_schema = None + +#------------------------------------------------------------------------------ +# Pending command list from the testControl API +# This is sent as a response commandList to the next received event. +#------------------------------------------------------------------------------ +pending_command_list = None + +#------------------------------------------------------------------------------ +# Logger for this module. +#------------------------------------------------------------------------------ +logger = None + +def listener(environ, start_response, schema): + ''' + Handler for the Vendor Event Listener REST API. + + Extract headers and the body and check that: + + 1) The client authenticated themselves correctly. + 2) The body validates against the provided schema for the API. + + ''' + logger.info('Got a Vendor Event request') + print('==== ' + time.asctime() + ' ' + '=' * 49) + + #-------------------------------------------------------------------------- + # Extract the content from the request. + #-------------------------------------------------------------------------- + length = int(environ.get('CONTENT_LENGTH', '0')) + logger.debug('Content Length: {0}'.format(length)) + body = environ['wsgi.input'].read(length) + logger.debug('Content Body: {0}'.format(body)) + + mode, b64_credentials = string.split(environ.get('HTTP_AUTHORIZATION', + 'None None')) + # logger.debug('Auth. Mode: {0} Credentials: {1}'.format(mode, + # b64_credentials)) + logger.debug('Auth. Mode: {0} Credentials: ****'.format(mode)) + if (b64_credentials != 'None'): + credentials = b64decode(b64_credentials) + else: + credentials = None + + logger.debug('Credentials: {0}'.format(credentials)) + #logger.debug('Credentials: ****') + + #-------------------------------------------------------------------------- + # If we have a schema file then check that the event matches that expected. + #-------------------------------------------------------------------------- + if (schema is not None): + logger.debug('Attempting to validate data: {0}\n' + 'Against schema: {1}'.format(body, schema)) + try: + decoded_body = json.loads(body) + jsonschema.validate(decoded_body, schema) + logger.info('Event is valid!') + print('Valid body decoded & checked against schema OK:\n' + '{0}'.format(json.dumps(decoded_body, + sort_keys=True, + indent=4, + separators=(',', ': ')))) + + except jsonschema.SchemaError as e: + logger.error('Schema is not valid! {0}'.format(e)) + print('Schema is not valid! {0}'.format(e)) + + except jsonschema.ValidationError as e: + logger.warn('Event is not valid against schema! {0}'.format(e)) + print('Event is not valid against schema! {0}'.format(e)) + print('Bad JSON body decoded:\n' + '{0}'.format(json.dumps(decoded_body, + sort_keys=True, + indent=4, + separators=(',', ': ')))) + + except Exception as e: + logger.error('Event invalid for unexpected reason! {0}'.format(e)) + print('Schema is not valid for unexpected reason! {0}'.format(e)) + else: + logger.debug('No schema so just decode JSON: {0}'.format(body)) + try: + decoded_body = json.loads(body) + print('Valid JSON body (no schema checking) decoded:\n' + '{0}'.format(json.dumps(decoded_body, + sort_keys=True, + indent=4, + separators=(',', ': ')))) + logger.info('Event is valid JSON but not checked against schema!') + + except Exception as e: + logger.error('Event invalid for unexpected reason! {0}'.format(e)) + print('JSON body not valid for unexpected reason! {0}'.format(e)) + + #-------------------------------------------------------------------------- + # See whether the user authenticated themselves correctly. + #-------------------------------------------------------------------------- + if (credentials == (vel_username + ':' + vel_password)): + logger.debug('Authenticated OK') + print('Authenticated OK') + + #---------------------------------------------------------------------- + # Respond to the caller. If we have a pending commandList from the + # testControl API, send it in response. + #---------------------------------------------------------------------- + global pending_command_list + if pending_command_list is not None: + start_response('202 Accepted', + [('Content-type', 'application/json')]) + response = pending_command_list + pending_command_list = None + + print('\n'+ '='*80) + print('Sending pending commandList in the response:\n' + '{0}'.format(json.dumps(response, + sort_keys=True, + indent=4, + separators=(',', ': ')))) + print('='*80 + '\n') + yield json.dumps(response) + else: + start_response('202 Accepted', []) + yield '' + else: + logger.warn('Failed to authenticate OK'+vel_username + ':' + vel_password) + print('Failed to authenticate OK'+vel_username + ':' + vel_password) + + #---------------------------------------------------------------------- + # Respond to the caller. + #---------------------------------------------------------------------- + start_response('401 Unauthorized', [ ('Content-type', + 'application/json')]) + req_error = { 'requestError': { + 'policyException': { + 'messageId': 'POL0001', + 'text': 'Failed to authenticate' + } + } + } + yield json.dumps(req_error) + +def test_listener(environ, start_response, schema): + ''' + Handler for the Test Collector Test Control API. + + There is no authentication on this interface. + + This simply stores a commandList which will be sent in response to the next + incoming event on the EVEL interface. + ''' + global pending_command_list + logger.info('Got a Test Control input') + print('============================') + print('==== TEST CONTROL INPUT ====') + + #-------------------------------------------------------------------------- + # GET allows us to get the current pending request. + #-------------------------------------------------------------------------- + if environ.get('REQUEST_METHOD') == 'GET': + start_response('200 OK', [('Content-type', 'application/json')]) + yield json.dumps(pending_command_list) + return + + #-------------------------------------------------------------------------- + # Extract the content from the request. + #-------------------------------------------------------------------------- + length = int(environ.get('CONTENT_LENGTH', '0')) + logger.debug('TestControl Content Length: {0}'.format(length)) + body = environ['wsgi.input'].read(length) + logger.debug('TestControl Content Body: {0}'.format(body)) + + #-------------------------------------------------------------------------- + # If we have a schema file then check that the event matches that expected. + #-------------------------------------------------------------------------- + if (schema is not None): + logger.debug('Attempting to validate data: {0}\n' + 'Against schema: {1}'.format(body, schema)) + try: + decoded_body = json.loads(body) + jsonschema.validate(decoded_body, schema) + logger.info('TestControl is valid!') + print('TestControl:\n' + '{0}'.format(json.dumps(decoded_body, + sort_keys=True, + indent=4, + separators=(',', ': ')))) + + except jsonschema.SchemaError as e: + logger.error('TestControl Schema is not valid: {0}'.format(e)) + print('TestControl Schema is not valid: {0}'.format(e)) + + except jsonschema.ValidationError as e: + logger.warn('TestControl input not valid: {0}'.format(e)) + print('TestControl input not valid: {0}'.format(e)) + print('Bad JSON body decoded:\n' + '{0}'.format(json.dumps(decoded_body, + sort_keys=True, + indent=4, + separators=(',', ': ')))) + + except Exception as e: + logger.error('TestControl input not valid: {0}'.format(e)) + print('TestControl Schema not valid: {0}'.format(e)) + else: + logger.debug('Missing schema just decode JSON: {0}'.format(body)) + try: + decoded_body = json.loads(body) + print('Valid JSON body (no schema checking) decoded:\n' + '{0}'.format(json.dumps(decoded_body, + sort_keys=True, + indent=4, + separators=(',', ': ')))) + logger.info('TestControl input not checked against schema!') + + except Exception as e: + logger.error('TestControl input not valid: {0}'.format(e)) + print('TestControl input not valid: {0}'.format(e)) + + #-------------------------------------------------------------------------- + # Respond to the caller. If we received otherField 'ThrottleRequest', + # generate the appropriate canned response. + #-------------------------------------------------------------------------- + pending_command_list = decoded_body + print('===== TEST CONTROL END =====') + print('============================') + start_response('202 Accepted', []) + yield '' + +def main(argv=None): + ''' + Main function for the collector start-up. + + Called with command-line arguments: + * --config ** + * --section *
* + * --verbose + + Where: + + ** specifies the path to the configuration file. + + *
* specifies the section within that config file. + + *verbose* generates more information in the log files. + + The process listens for REST API invocations and checks them. Errors are + displayed to stdout and logged. + ''' + + if argv is None: + argv = sys.argv + else: + sys.argv.extend(argv) + + program_name = os.path.basename(sys.argv[0]) + program_version = 'v{0}'.format(__version__) + program_build_date = str(__updated__) + program_version_message = '%%(prog)s {0} ({1})'.format(program_version, + program_build_date) + if (__import__('__main__').__doc__ is not None): + program_shortdesc = __import__('__main__').__doc__.split('\n')[1] + else: + program_shortdesc = 'Running in test harness' + program_license = '''{0} + + Created on {1}. + Copyright 2015 Metaswitch Networks Ltd. All rights reserved. + + Distributed on an "AS IS" basis without warranties + or conditions of any kind, either express or implied. + +USAGE +'''.format(program_shortdesc, str(__date__)) + + try: + #---------------------------------------------------------------------- + # Setup argument parser so we can parse the command-line. + #---------------------------------------------------------------------- + parser = ArgumentParser(description=program_license, + formatter_class=ArgumentDefaultsHelpFormatter) + parser.add_argument('-v', '--verbose', + dest='verbose', + action='count', + help='set verbosity level') + parser.add_argument('-V', '--version', + action='version', + version=program_version_message, + help='Display version information') + parser.add_argument('-a', '--api-version', + dest='api_version', + default='5', + help='set API version') + parser.add_argument('-c', '--config', + dest='config', + default='/etc/opt/att/collector.conf', + help='Use this config file.', + metavar='') + parser.add_argument('-s', '--section', + dest='section', + default='default', + metavar='
', + help='section to use in the config file') + + #---------------------------------------------------------------------- + # Process arguments received. + #---------------------------------------------------------------------- + args = parser.parse_args() + verbose = args.verbose + api_version = args.api_version + config_file = args.config + config_section = args.section + + #---------------------------------------------------------------------- + # Now read the config file, using command-line supplied values as + # overrides. + #---------------------------------------------------------------------- + defaults = {'log_file': 'collector.log', + 'vel_port': '12233', + 'vel_path': '', + 'vel_topic_name': '' + } + overrides = {} + config = ConfigParser.SafeConfigParser(defaults) + config.read(config_file) + + #---------------------------------------------------------------------- + # extract the values we want. + #---------------------------------------------------------------------- + log_file = config.get(config_section, 'log_file', vars=overrides) + vel_port = config.get(config_section, 'vel_port', vars=overrides) + vel_path = config.get(config_section, 'vel_path', vars=overrides) + vel_topic_name = config.get(config_section, + 'vel_topic_name', + vars=overrides) + global vel_username + global vel_password + vel_username = config.get(config_section, + 'vel_username', + vars=overrides) + vel_password = config.get(config_section, + 'vel_password', + vars=overrides) + vel_schema_file = config.get(config_section, + 'schema_file', + vars=overrides) + base_schema_file = config.get(config_section, + 'base_schema_file', + vars=overrides) + throttle_schema_file = config.get(config_section, + 'throttle_schema_file', + vars=overrides) + test_control_schema_file = config.get(config_section, + 'test_control_schema_file', + vars=overrides) + + #---------------------------------------------------------------------- + # Finally we have enough info to start a proper flow trace. + #---------------------------------------------------------------------- + global logger + print('Logfile: {0}'.format(log_file)) + logger = logging.getLogger('collector') + if verbose > 0: + print('Verbose mode on') + logger.setLevel(logging.DEBUG) + else: + logger.setLevel(logging.INFO) + handler = logging.handlers.RotatingFileHandler(log_file, + maxBytes=1000000, + backupCount=10) + if (platform.system() == 'Windows'): + date_format = '%Y-%m-%d %H:%M:%S' + else: + date_format = '%Y-%m-%d %H:%M:%S.%f %z' + formatter = logging.Formatter('%(asctime)s %(name)s - ' + '%(levelname)s - %(message)s', + date_format) + handler.setFormatter(formatter) + logger.addHandler(handler) + logger.info('Started') + + #---------------------------------------------------------------------- + # Log the details of the configuration. + #---------------------------------------------------------------------- + logger.debug('Log file = {0}'.format(log_file)) + logger.debug('Event Listener Port = {0}'.format(vel_port)) + logger.debug('Event Listener Path = {0}'.format(vel_path)) + logger.debug('Event Listener Topic = {0}'.format(vel_topic_name)) + logger.debug('Event Listener Username = {0}'.format(vel_username)) + # logger.debug('Event Listener Password = {0}'.format(vel_password)) + logger.debug('Event Listener JSON Schema File = {0}'.format( + vel_schema_file)) + logger.debug('Base JSON Schema File = {0}'.format(base_schema_file)) + logger.debug('Throttle JSON Schema File = {0}'.format( + throttle_schema_file)) + logger.debug('Test Control JSON Schema File = {0}'.format( + test_control_schema_file)) + + #---------------------------------------------------------------------- + # Perform some basic error checking on the config. + #---------------------------------------------------------------------- + if (int(vel_port) < 1024 or int(vel_port) > 65535): + logger.error('Invalid Vendor Event Listener port ({0}) ' + 'specified'.format(vel_port)) + raise RuntimeError('Invalid Vendor Event Listener port ({0}) ' + 'specified'.format(vel_port)) + + if (len(vel_path) > 0 and vel_path[-1] != '/'): + logger.warning('Event Listener Path ({0}) should have terminating ' + '"/"! Adding one on to configured string.'.format( + vel_path)) + vel_path += '/' + + #---------------------------------------------------------------------- + # Load up the vel_schema, if it exists. + #---------------------------------------------------------------------- + if not os.path.exists(vel_schema_file): + logger.warning('Event Listener Schema File ({0}) not found. ' + 'No validation will be undertaken.'.format( + vel_schema_file)) + else: + global vel_schema + global throttle_schema + global test_control_schema + vel_schema = json.load(open(vel_schema_file, 'r')) + logger.debug('Loaded the JSON schema file') + + #------------------------------------------------------------------ + # Load up the throttle_schema, if it exists. + #------------------------------------------------------------------ + if (os.path.exists(throttle_schema_file)): + logger.debug('Loading throttle schema') + throttle_fragment = json.load(open(throttle_schema_file, 'r')) + throttle_schema = {} + throttle_schema.update(vel_schema) + throttle_schema.update(throttle_fragment) + logger.debug('Loaded the throttle schema') + + #------------------------------------------------------------------ + # Load up the test control _schema, if it exists. + #------------------------------------------------------------------ + if (os.path.exists(test_control_schema_file)): + logger.debug('Loading test control schema') + test_control_fragment = json.load( + open(test_control_schema_file, 'r')) + test_control_schema = {} + test_control_schema.update(vel_schema) + test_control_schema.update(test_control_fragment) + logger.debug('Loaded the test control schema') + + #------------------------------------------------------------------ + # Load up the base_schema, if it exists. + #------------------------------------------------------------------ + if (os.path.exists(base_schema_file)): + logger.debug('Updating the schema with base definition') + base_schema = json.load(open(base_schema_file, 'r')) + vel_schema.update(base_schema) + logger.debug('Updated the JSON schema file') + + #---------------------------------------------------------------------- + # We are now ready to get started with processing. Start-up the various + # components of the system in order: + # + # 1) Create the dispatcher. + # 2) Register the functions for the URLs of interest. + # 3) Run the webserver. + #---------------------------------------------------------------------- + root_url = '/{0}eventListener/v{1}{2}'.\ + format(vel_path, + api_version, + '/' + vel_topic_name + if len(vel_topic_name) > 0 + else '') + throttle_url = '/{0}eventListener/v{1}/clientThrottlingState'.\ + format(vel_path, api_version) + set_404_content(root_url) + dispatcher = PathDispatcher() + vendor_event_listener = partial(listener, schema = vel_schema) + dispatcher.register('GET', root_url, vendor_event_listener) + dispatcher.register('POST', root_url, vendor_event_listener) + vendor_throttle_listener = partial(listener, schema = throttle_schema) + dispatcher.register('GET', throttle_url, vendor_throttle_listener) + dispatcher.register('POST', throttle_url, vendor_throttle_listener) + + #---------------------------------------------------------------------- + # We also add a POST-only mechanism for test control, so that we can + # send commands to a single attached client. + #---------------------------------------------------------------------- + test_control_url = '/testControl/v{0}/commandList'.format(api_version) + test_control_listener = partial(test_listener, + schema = test_control_schema) + dispatcher.register('POST', test_control_url, test_control_listener) + dispatcher.register('GET', test_control_url, test_control_listener) + + httpd = make_server('', int(vel_port), dispatcher) + print('Serving on port {0}...'.format(vel_port)) + httpd.serve_forever() + + logger.error('Main loop exited unexpectedly!') + return 0 + + except KeyboardInterrupt: + #---------------------------------------------------------------------- + # handle keyboard interrupt + #---------------------------------------------------------------------- + logger.info('Exiting on keyboard interrupt!') + return 0 + + except Exception as e: + #---------------------------------------------------------------------- + # Handle unexpected exceptions. + #---------------------------------------------------------------------- + if DEBUG or TESTRUN: + raise(e) + indent = len(program_name) * ' ' + sys.stderr.write(program_name + ': ' + repr(e) + '\n') + sys.stderr.write(indent + ' for help use --help\n') + sys.stderr.write(traceback.format_exc()) + logger.critical('Exiting because of exception: {0}'.format(e)) + logger.critical(traceback.format_exc()) + return 2 + +#------------------------------------------------------------------------------ +# MAIN SCRIPT ENTRY POINT. +#------------------------------------------------------------------------------ +if __name__ == '__main__': + if TESTRUN: + #---------------------------------------------------------------------- + # Running tests - note that doctest comments haven't been included so + # this is a hook for future improvements. + #---------------------------------------------------------------------- + import doctest + doctest.testmod() + + if PROFILE: + #---------------------------------------------------------------------- + # Profiling performance. Performance isn't expected to be a major + # issue, but this should all work as expected. + #---------------------------------------------------------------------- + import cProfile + import pstats + profile_filename = 'collector_profile.txt' + cProfile.run('main()', profile_filename) + statsfile = open('collector_profile_stats.txt', 'wb') + p = pstats.Stats(profile_filename, stream=statsfile) + stats = p.strip_dirs().sort_stats('cumulative') + stats.print_stats() + statsfile.close() + sys.exit(0) + + #-------------------------------------------------------------------------- + # Normal operation - call through to the main function. + #-------------------------------------------------------------------------- + sys.exit(main()) diff --git a/veslibrary/ves_clibrary/evel/evel-test-collector/code/collector/rest_dispatcher.py b/veslibrary/ves_clibrary/evel/evel-test-collector/code/collector/rest_dispatcher.py new file mode 100644 index 0000000..e3b51aa --- /dev/null +++ b/veslibrary/ves_clibrary/evel/evel-test-collector/code/collector/rest_dispatcher.py @@ -0,0 +1,92 @@ +#!/usr/bin/env python +''' +Simple dispatcher for the REST API. + +Only intended for test purposes. + +License +------- + + * =================================================================== + * 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. + +''' + +import logging +logger = logging.getLogger('collector.disp') + +base_url = '' + +template_404 = b'''POST {0}''' + +def set_404_content(url): + ''' + Called at initialization to set the base URL so that we can serve helpful + diagnostics as part of the 404 response. + ''' + global base_url + base_url = url + return + +def notfound_404(environ, start_response): + ''' + Serve the 404 Not Found response. + + Provides diagnostics in the 404 response showing the hierarchy of valid + REST resources. + ''' + logger.warning('Unexpected URL/Method: {0} {1}'.format( + environ['REQUEST_METHOD'].upper(), + environ['PATH_INFO'])) + start_response('404 Not Found', [ ('Content-type', 'text/plain') ]) + return [template_404.format(base_url)] + +class PathDispatcher: + ''' + A dispatcher which can take HTTP requests in a WSGI environment and invoke + appropriate methods for each request. + ''' + def __init__(self): + '''Constructor: initialize the pathmap to be empty.''' + self.pathmap = { } + + def __call__(self, environ, start_response): + ''' + The main callable that the WSGI app will invoke with each request. + ''' + #---------------------------------------------------------------------- + # Extract the method and path from the environment. + #---------------------------------------------------------------------- + method = environ['REQUEST_METHOD'].lower() + path = environ['PATH_INFO'] + logger.info('Dispatcher called for: {0} {1}'.format(method, path)) + logger.debug('Dispatcher environment is: {0}'.format(environ)) + + #---------------------------------------------------------------------- + # See if we have a handler for this path, and if so invoke it. + # Otherwise, return a 404. + #---------------------------------------------------------------------- + handler = self.pathmap.get((method, path), notfound_404) + logger.debug('Dispatcher will use handler: {0}'.format(handler)) + return handler(environ, start_response) + + def register(self, method, path, function): + ''' + Register a handler for a method/path, adding it to the pathmap. + ''' + logger.debug('Registering for {0} at {1}'.format(method, path)) + print('Registering for {0} at {1}'.format(method, path)) + self.pathmap[method.lower(), path] = function + return function diff --git a/veslibrary/ves_clibrary/evel/evel-test-collector/code/collector/test_control.py b/veslibrary/ves_clibrary/evel/evel-test-collector/code/collector/test_control.py new file mode 100644 index 0000000..8783d30 --- /dev/null +++ b/veslibrary/ves_clibrary/evel/evel-test-collector/code/collector/test_control.py @@ -0,0 +1,180 @@ +#!/usr/bin/env python +''' +Example script to inject a throttling command list to the test_collector. + +Only intended for test purposes. + +License +------- + + * =================================================================== + * 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. + +''' +import optparse +import requests +import json + +############################################################################### +# Functions to build up commandList contents +############################################################################### +def command_state(): + "return a provideThrottlingState command" + return {'command': + {'commandType': 'provideThrottlingState'}} + +def command_interval(interval): + "return a measurementIntervalChange command" + return {'command': + {'commandType': 'measurementIntervalChange', + 'measurementInterval': interval}} + +def command_throttle(domain, fields, pairs): + "return a throttlingSpecification" + throttle_spec = {'eventDomain' : domain} + if len(fields): + throttle_spec['suppressedFieldNames'] = fields + if len(pairs): + throttle_spec['suppressedNvPairsList'] = pairs + return {'command': + {'commandType': 'throttlingSpecification', + 'eventDomainThrottleSpecification': throttle_spec}} + +def command_nvpairs(field_name, pair_names): + "return a suppressedNvPairs" + return {'nvPairFieldName' : field_name, + 'suppressedNvPairNames' : pair_names} + +############################################################################### +# Example functions to build up commandLists for various domains. +############################################################################### +def command_list_empty(): + return {'commandList' : []} + +def command_list_provide(): + return {'commandList' : [command_state()]} + +def command_list_interval(interval): + return {'commandList' : [command_interval(interval)]} + +def command_list_fault_suppress_fields(): + "Throttling Specification - two suppressedFieldNames" + fields = ['alarmInterfaceA', 'alarmAdditionalInformation'] + pairs = [] + command_list = [command_throttle('fault', fields, pairs)] + return {'commandList' : command_list} + +def command_list_fault_suppress_nothing(): + "Throttling Specification - no suppression" + fields = [] + pairs = [] + command_list = [command_throttle('fault', fields, pairs)] + return {'commandList' : command_list} + +def command_list_fault_suppress_pairs(): + "Throttling Specification - two suppressedNvPairNames" + fields = [] + pairs = [command_nvpairs('alarmAdditionalInformation', + ['name1', 'name2'])] + command_list = [command_throttle('fault', fields, pairs)] + return {'commandList' : command_list} + +def command_list_fault_suppress_fields_and_pairs(): + "Throttling Specification - a mixture of fields and pairs" + fields = ['alarmInterfaceA'] + pairs = [command_nvpairs('alarmAdditionalInformation', + ['name1', 'name2'])] + command_list = [command_throttle('fault', fields, pairs)] + return {'commandList' : command_list} + +def command_list_measurements_suppress_example(): + "Throttling Specification - measurements" + fields = ['numberOfMediaPortsInUse', 'aggregateCpuUsage'] + pairs = [command_nvpairs('cpuUsageArray', + ['cpu1', 'cpu3'])] + command_list = [command_throttle('measurementsForVfScaling', + fields, pairs)] + return {'commandList' : command_list} + +def command_list_mobile_flow_suppress_example(): + "Throttling Specification - mobile flow" + fields = ['radioAccessTechnology', 'samplingAlgorithm'] + pairs = [] + command_list = [command_throttle('mobileFlow', fields, pairs)] + return {'commandList' : command_list} + +def command_list_state_change_suppress_example(): + "Throttling Specification - state change" + fields = ['reportingEntityId', 'eventType', 'sourceId'] + pairs = [command_nvpairs('additionalFields', ['Name1'])] + command_list = [command_throttle('stateChange', fields, pairs)] + return {'commandList' : command_list} + +def command_list_syslog_suppress_example(): + "Throttling Specification - syslog" + fields = ['syslogFacility', 'syslogProc', 'syslogProcId'] + pairs = [command_nvpairs('additionalFields', ['Name1', 'Name4'])] + command_list = [command_throttle('syslog', fields, pairs)] + return {'commandList' : command_list} + +def command_list_reset_all_domains(): + "Throttling Specification - reset all domains" + command_list = [command_throttle('fault', [], []), + command_throttle('measurementsForVfScaling', [], []), + command_throttle('mobileFlow', [], []), + command_throttle('stateChange', [], []), + command_throttle('syslog', [], [])] + return {'commandList' : command_list} + +def mixed_example(): + fields = ['alarmInterfaceA'] + pairs = [command_nvpairs('alarmAdditionalInformation', + ['name1', 'name2'])] + command_list = [command_throttle('fault', fields, pairs), + command_interval(10), + command_state()] + return {'commandList' : command_list} + +############################################################################### +# Default command line values +############################################################################### +DEFAULT_FQDN = "127.0.0.1" +DEFAULT_PORT = 30000 + +############################################################################### +# Command Line Parsing +############################################################################### +parser = optparse.OptionParser() +parser.add_option('--fqdn', + action="store", + dest="fqdn", + default=DEFAULT_FQDN) +parser.add_option('--port', + action="store", + dest="port", + default=DEFAULT_PORT, + type="int") +options, remainder = parser.parse_args() + +############################################################################### +# Derive the Test Control URL +############################################################################### +url = 'http://%s:%d/testControl/v1.1/commandList'%(options.fqdn, options.port) + +############################################################################### +# Create JSON and POST it to the Test Control URL. +############################################################################### +command_list = command_list_fault_suppress_fields_and_pairs() +requests.post(url, json = command_list) diff --git a/veslibrary/ves_clibrary/evel/evel-test-collector/config/collector.conf b/veslibrary/ves_clibrary/evel/evel-test-collector/config/collector.conf new file mode 100644 index 0000000..3e23c59 --- /dev/null +++ b/veslibrary/ves_clibrary/evel/evel-test-collector/config/collector.conf @@ -0,0 +1,99 @@ +# * =================================================================== +# * 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. +# * ECOMP and OpenECOMP are trademarks +# * and service marks of AT&T Intellectual Property. +#------------------------------------------------------------------------------ +# This is a config file for the collector test harness. +# +# On the target platform is is expected to be located in: +# +# /etc/opt/att/collector.conf +# +# However, the location can be overridden by setting the --config +# argument to the collector code. +#------------------------------------------------------------------------------ + +#------------------------------------------------------------------------------ +# The default section to be used. Alternative configuration sections can be +# provided by using the --section command-line parameter. +#------------------------------------------------------------------------------ +[default] +log_file = /var/log/att/collector.log +schema_file = ../../docs/att_interface_definition/event_format_updated.json +base_schema_file = ../../docs/att_interface_definition/base_schema.json +throttle_schema_file = ../../docs/att_interface_definition/throttle_schema.json +test_control_schema_file = ../../docs/att_interface_definition/test_control_schema.json + +#------------------------------------------------------------------------------ +# Details of the Vendor Event Listener REST service. +# +# REST resources are defined with respect to a ServerRoot: +# ServerRoot = https://{Domain}:{Port}/{optionalRoutingPath} +# +# REST resources are of the form: +# * {ServerRoot}/eventListener/v{apiVersion} +# * {ServerRoot}/eventListener/v{apiVersion}/{topicName} +# * {ServerRoot}/eventListener/v{apiVersion}/eventBatch +# * {ServerRoot}/eventListener/v{apiVersion}/clientThrottlingState +# +# The "vel_topic_name" parameter is used as the "topicName" element in the path +# and may be empty. +# +# Note that the path, if present, should have no leading "/" but should have a +# training "/". +#------------------------------------------------------------------------------ +vel_domain = 127.0.0.1 +vel_port = 30000 +vel_path = vendor_event_listener/ +vel_username = +vel_password = +vel_topic_name = example_vnf + +#------------------------------------------------------------------------------ +# Settings to be used when running in a windows test environment rather than +# the target environment. +#------------------------------------------------------------------------------ +[windows] +log_file = ../../logs/collector.log +schema_file = ../../docs/att_interface_definition/event_format_updated.json +base_schema_file = +throttle_schema_file = ../../docs/att_interface_definition/throttle_schema.json +test_control_schema_file = ../../docs/att_interface_definition/test_control_schema.json + +#------------------------------------------------------------------------------ +# Details of the Vendor Event Listener REST service. +# +# REST resources are defined with respect to a ServerRoot: +# ServerRoot = https://{Domain}:{Port}/{optionalRoutingPath} +# +# REST resources are of the form: +# * {ServerRoot}/eventListener/v{apiVersion} +# * {ServerRoot}/eventListener/v{apiVersion}/{topicName} +# * {ServerRoot}/eventListener/v{apiVersion}/eventBatch +# * {ServerRoot}/eventListener/v{apiVersion}/clientThrottlingState +# +# The "vel_topic_name" parameter is used as the "topicName" element in the path +# and may be empty. +# +# Note that the path, if present, should have no leading "/" but should have a +# training "/". +#------------------------------------------------------------------------------ +vel_domain = 127.0.0.1 +vel_port = 30000 +vel_path = +vel_username = will +vel_password = pill +vel_topic_name = + diff --git a/veslibrary/ves_clibrary/evel/evel-test-collector/docs/att_interface_definition/LICENSE.TXT b/veslibrary/ves_clibrary/evel/evel-test-collector/docs/att_interface_definition/LICENSE.TXT new file mode 100644 index 0000000..ae12da2 --- /dev/null +++ b/veslibrary/ves_clibrary/evel/evel-test-collector/docs/att_interface_definition/LICENSE.TXT @@ -0,0 +1,22 @@ +/* + * ============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. + * + */ diff --git a/veslibrary/ves_clibrary/evel/evel-test-collector/docs/att_interface_definition/base_schema.json b/veslibrary/ves_clibrary/evel/evel-test-collector/docs/att_interface_definition/base_schema.json new file mode 100644 index 0000000..8efd08a --- /dev/null +++ b/veslibrary/ves_clibrary/evel/evel-test-collector/docs/att_interface_definition/base_schema.json @@ -0,0 +1,10 @@ + { + "$schema": "http://json-schema.org/draft-04/schema#", + + "title": "Vendor Event Listener API updated", + "type": "object", + "properties": { + "event": {"$ref": "#/definitions/event"} + }, + "required": ["event"] +} \ No newline at end of file diff --git a/veslibrary/ves_clibrary/evel/evel-test-collector/docs/att_interface_definition/event_format_updated.json b/veslibrary/ves_clibrary/evel/evel-test-collector/docs/att_interface_definition/event_format_updated.json new file mode 100644 index 0000000..82339b0 --- /dev/null +++ b/veslibrary/ves_clibrary/evel/evel-test-collector/docs/att_interface_definition/event_format_updated.json @@ -0,0 +1,1885 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + + "definitions": { + "attCopyrightNotice": { + "description": "Copyright (c) <2017>, AT&T Intellectual Property. All rights reserved. Licensed under the Apache License, Version 2.0 (the License)", + "type": "object", + "properties": { + "useAndRedistribution": { + "description": "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", + "type": "string" + }, + "licenseLink": "http://www.apache.org/licenses/LICENSE-2.0", + "condition1": { + "description": "Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an AS IS BASIS,", + "type": "string" + }, + "condition2": { + "description": "Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.", + "type": "string" + }, + "condition3": { + "description": "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", + "type": "string" + }, + "condition4": { + "description": "See the License for the specific language governing permissions and limitations under the License.", + "type": "string" + }, + "Trademarks": { + "description": "ECOMP and OpenECOMP are trademarks and service marks of AT&T Intellectual Property.", + "type": "string" + } + } + }, + "codecsInUse": { + "description": "number of times an identified codec was used over the measurementInterval", + "type": "object", + "properties": { + "codecIdentifier": { "type": "string" }, + "numberInUse": { "type": "integer" } + }, + "required": [ "codecIdentifier", "numberInUse" ] + }, + "command": { + "description": "command from an event collector toward an event source", + "type": "object", + "properties": { + "commandType": { + "type": "string", + "enum": [ + "heartbeatIntervalChange", + "measurementIntervalChange", + "provideThrottlingState", + "throttlingSpecification" + ] + }, + "eventDomainThrottleSpecification": { "$ref": "#/definitions/eventDomainThrottleSpecification" }, + "heartbeatInterval": { "type": "integer" }, + "measurementInterval": { "type": "integer" } + }, + "required": [ "commandType" ] + }, + "commandList": { + "description": "array of commands from an event collector toward an event source", + "type": "array", + "items": { + "$ref": "#/definitions/commandListEntry" + }, + "minItems": 0 + }, + "commandListEntry": { + "description": "reference to a command object", + "type": "object", + "properties": { + "command": {"$ref": "#/definitions/command"} + }, + "required": [ "command" ] + }, + "commonEventHeader": { + "description": "fields common to all events", + "type": "object", + "properties": { + "domain": { + "description": "the eventing domain associated with the event", + "type": "string", + "enum": [ + "fault", + "heartbeat", + "measurementsForVfScaling", + "mobileFlow", + "other", + "sipSignaling", + "stateChange", + "syslog", + "thresholdCrossingAlert", + "voiceQuality" + ] + }, + "eventId": { + "description": "event key that is unique to the event source", + "type": "string" + }, + "eventName": { + "description": "unique event name", + "type": "string" + }, + "eventType": { + "description": "for example - applicationVnf, guestOS, hostOS, platform", + "type": "string" + }, + "internalHeaderFields": { "$ref": "#/definitions/internalHeaderFields" }, + "lastEpochMicrosec": { + "description": "the latest unix time aka epoch time associated with the event from any component--as microseconds elapsed since 1 Jan 1970 not including leap seconds", + "type": "number" + }, + "nfcNamingCode": { + "description": "3 character network function component type, aligned with vfc naming standards", + "type": "string" + }, + "nfNamingCode": { + "description": "4 character network function type, aligned with vnf naming standards", + "type": "string" + }, + "priority": { + "description": "processing priority", + "type": "string", + "enum": [ + "High", + "Medium", + "Normal", + "Low" + ] + }, + "reportingEntityId": { + "description": "UUID identifying the entity reporting the event, for example an OAM VM; must be populated by the ATT enrichment process", + "type": "string" + }, + "reportingEntityName": { + "description": "name of the entity reporting the event, for example, an EMS name; may be the same as sourceName", + "type": "string" + }, + "sequence": { + "description": "ordering of events communicated by an event source instance or 0 if not needed", + "type": "integer" + }, + "sourceId": { + "description": "UUID identifying the entity experiencing the event issue; must be populated by the ATT enrichment process", + "type": "string" + }, + "sourceName": { + "description": "name of the entity experiencing the event issue", + "type": "string" + }, + "startEpochMicrosec": { + "description": "the earliest unix time aka epoch time associated with the event from any component--as microseconds elapsed since 1 Jan 1970 not including leap seconds", + "type": "number" + }, + "version": { + "description": "version of the event header", + "type": "number" + } + }, + "required": [ "domain", "eventId", "eventName", "lastEpochMicrosec", + "priority", "reportingEntityName", "sequence", "sourceName", + "startEpochMicrosec", "version" ] + }, + "counter": { + "description": "performance counter", + "type": "object", + "properties": { + "criticality": { "type": "string", "enum": [ "CRIT", "MAJ" ] }, + "name": { "type": "string" }, + "thresholdCrossed": { "type": "string" }, + "value": { "type": "string"} + }, + "required": [ "criticality", "name", "thresholdCrossed", "value" ] + }, + "cpuUsage": { + "description": "usage of an identified CPU", + "type": "object", + "properties": { + "cpuIdentifier": { + "description": "cpu identifer", + "type": "string" + }, + "cpuIdle": { + "description": "percentage of CPU time spent in the idle task", + "type": "number" + }, + "cpuUsageInterrupt": { + "description": "percentage of time spent servicing interrupts", + "type": "number" + }, + "cpuUsageNice": { + "description": "percentage of time spent running user space processes that have been niced", + "type": "number" + }, + "cpuUsageSoftIrq": { + "description": "percentage of time spent handling soft irq interrupts", + "type": "number" + }, + "cpuUsageSteal": { + "description": "percentage of time spent in involuntary wait which is neither user, system or idle time and is effectively time that went missing", + "type": "number" + }, + "cpuUsageSystem": { + "description": "percentage of time spent on system tasks running the kernel", + "type": "number" + }, + "cpuUsageUser": { + "description": "percentage of time spent running un-niced user space processes", + "type": "number" + }, + "cpuWait": { + "description": "percentage of CPU time spent waiting for I/O operations to complete", + "type": "number" + }, + "percentUsage": { + "description": "aggregate cpu usage of the virtual machine on which the VNFC reporting the event is running", + "type": "number" + } + }, + "required": [ "cpuIdentifier", "percentUsage" ] + }, + "diskUsage": { + "description": "usage of an identified disk", + "type": "object", + "properties": { + "diskIdentifier": { + "description": "disk identifier", + "type": "string" + }, + "diskIoTimeAvg": { + "description": "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", + "type": "number" + }, + "diskIoTimeLast": { + "description": "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 measurement within the measurement interval", + "type": "number" + }, + "diskIoTimeMax": { + "description": "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 measurement within the measurement interval", + "type": "number" + }, + "diskIoTimeMin": { + "description": "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 measurement within the measurement interval", + "type": "number" + }, + "diskMergedReadAvg": { + "description": "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", + "type": "number" + }, + "diskMergedReadLast": { + "description": "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 value measurement within the measurement interval", + "type": "number" + }, + "diskMergedReadMax": { + "description": "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 value measurement within the measurement interval", + "type": "number" + }, + "diskMergedReadMin": { + "description": "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 value measurement within the measurement interval", + "type": "number" + }, + "diskMergedWriteAvg": { + "description": "number of logical write operations that were merged into physical write operations, e.g., two logical writes were served by one physical disk access; provide the average measurement within the measurement interval", + "type": "number" + }, + "diskMergedWriteLast": { + "description": "number of logical write operations that were merged into physical write operations, e.g., two logical writes were served by one physical disk access; provide the last value measurement within the measurement interval", + "type": "number" + }, + "diskMergedWriteMax": { + "description": "number of logical write operations that were merged into physical write operations, e.g., two logical writes were served by one physical disk access; provide the maximum value measurement within the measurement interval", + "type": "number" + }, + "diskMergedWriteMin": { + "description": "number of logical write operations that were merged into physical write operations, e.g., two logical writes were served by one physical disk access; provide the minimum value measurement within the measurement interval", + "type": "number" + }, + "diskOctetsReadAvg": { + "description": "number of octets per second read from a disk or partition; provide the average measurement within the measurement interval", + "type": "number" + }, + "diskOctetsReadLast": { + "description": "number of octets per second read from a disk or partition; provide the last measurement within the measurement interval", + "type": "number" + }, + "diskOctetsReadMax": { + "description": "number of octets per second read from a disk or partition; provide the maximum measurement within the measurement interval", + "type": "number" + }, + "diskOctetsReadMin": { + "description": "number of octets per second read from a disk or partition; provide the minimum measurement within the measurement interval", + "type": "number" + }, + "diskOctetsWriteAvg": { + "description": "number of octets per second written to a disk or partition; provide the average measurement within the measurement interval", + "type": "number" + }, + "diskOctetsWriteLast": { + "description": "number of octets per second written to a disk or partition; provide the last measurement within the measurement interval", + "type": "number" + }, + "diskOctetsWriteMax": { + "description": "number of octets per second written to a disk or partition; provide the maximum measurement within the measurement interval", + "type": "number" + }, + "diskOctetsWriteMin": { + "description": "number of octets per second written to a disk or partition; provide the minimum measurement within the measurement interval", + "type": "number" + }, + "diskOpsReadAvg": { + "description": "number of read operations per second issued to the disk; provide the average measurement within the measurement interval", + "type": "number" + }, + "diskOpsReadLast": { + "description": "number of read operations per second issued to the disk; provide the last measurement within the measurement interval", + "type": "number" + }, + "diskOpsReadMax": { + "description": "number of read operations per second issued to the disk; provide the maximum measurement within the measurement interval", + "type": "number" + }, + "diskOpsReadMin": { + "description": "number of read operations per second issued to the disk; provide the minimum measurement within the measurement interval", + "type": "number" + }, + "diskOpsWriteAvg": { + "description": "number of write operations per second issued to the disk; provide the average measurement within the measurement interval", + "type": "number" + }, + "diskOpsWriteLast": { + "description": "number of write operations per second issued to the disk; provide the last measurement within the measurement interval", + "type": "number" + }, + "diskOpsWriteMax": { + "description": "number of write operations per second issued to the disk; provide the maximum measurement within the measurement interval", + "type": "number" + }, + "diskOpsWriteMin": { + "description": "number of write operations per second issued to the disk; provide the minimum measurement within the measurement interval", + "type": "number" + }, + "diskPendingOperationsAvg": { + "description": "queue size of pending I/O operations per second; provide the average measurement within the measurement interval", + "type": "number" + }, + "diskPendingOperationsLast": { + "description": "queue size of pending I/O operations per second; provide the last measurement within the measurement interval", + "type": "number" + }, + "diskPendingOperationsMax": { + "description": "queue size of pending I/O operations per second; provide the maximum measurement within the measurement interval", + "type": "number" + }, + "diskPendingOperationsMin": { + "description": "queue size of pending I/O operations per second; provide the minimum measurement within the measurement interval", + "type": "number" + }, + "diskTimeReadAvg": { + "description": "milliseconds a read operation took to complete; provide the average measurement within the measurement interval", + "type": "number" + }, + "diskTimeReadLast": { + "description": "milliseconds a read operation took to complete; provide the last measurement within the measurement interval", + "type": "number" + }, + "diskTimeReadMax": { + "description": "milliseconds a read operation took to complete; provide the maximum measurement within the measurement interval", + "type": "number" + }, + "diskTimeReadMin": { + "description": "milliseconds a read operation took to complete; provide the minimum measurement within the measurement interval", + "type": "number" + }, + "diskTimeWriteAvg": { + "description": "milliseconds a write operation took to complete; provide the average measurement within the measurement interval", + "type": "number" + }, + "diskTimeWriteLast": { + "description": "milliseconds a write operation took to complete; provide the last measurement within the measurement interval", + "type": "number" + }, + "diskTimeWriteMax": { + "description": "milliseconds a write operation took to complete; provide the maximum measurement within the measurement interval", + "type": "number" + }, + "diskTimeWriteMin": { + "description": "milliseconds a write operation took to complete; provide the minimum measurement within the measurement interval", + "type": "number" + } + }, + "required": [ "diskIdentifier" ] + }, + "endOfCallVqmSummaries": { + "description": "provides end of call voice quality metrics", + "type": "object", + "properties": { + "adjacencyName": { + "description": " adjacency name", + "type": "string" + }, + "endpointDescription": { + "description": "Either Caller or Callee", + "type": "string", + "enum": ["Caller", "Callee"] + }, + "endpointJitter": { + "description": "", + "type": "number" + }, + "endpointRtpOctetsDiscarded": { + "description": "", + "type": "number" + }, + "endpointRtpOctetsReceived": { + "description": "", + "type": "number" + }, + "endpointRtpOctetsSent": { + "description": "", + "type": "number" + }, + "endpointRtpPacketsDiscarded": { + "description": "", + "type": "number" + }, + "endpointRtpPacketsReceived": { + "description": "", + "type": "number" + }, + "endpointRtpPacketsSent": { + "description": "", + "type": "number" + }, + "localJitter": { + "description": "", + "type": "number" + }, + "localRtpOctetsDiscarded": { + "description": "", + "type": "number" + }, + "localRtpOctetsReceived": { + "description": "", + "type": "number" + }, + "localRtpOctetsSent": { + "description": "", + "type": "number" + }, + "localRtpPacketsDiscarded": { + "description": "", + "type": "number" + }, + "localRtpPacketsReceived": { + "description": "", + "type": "number" + }, + "localRtpPacketsSent": { + "description": "", + "type": "number" + }, + "mosCqe": { + "description": "1-5 1dp", + "type": "number" + }, + "packetsLost": { + "description": "", + "type": "number" + }, + "packetLossPercent": { + "description" : "Calculated percentage packet loss based on Endpoint RTP packets lost (as reported in RTCP) and Local RTP packets sent. Direction is based on Endpoint description (Caller, Callee). Decimal (2 dp)", + "type": "number" + }, + "rFactor": { + "description": "0-100", + "type": "number" + }, + "roundTripDelay": { + "description": "millisecs", + "type": "number" + } + }, + "required": [ "adjacencyName", "endpointDescription" ] + }, + "event": { + "description": "the root level of the common event format", + "type": "object", + "properties": { + "commonEventHeader": { "$ref": "#/definitions/commonEventHeader" }, + "faultFields": { "$ref": "#/definitions/faultFields" }, + "heartbeatFields": { "$ref": "#/definitions/heartbeatFields" }, + "measurementsForVfScalingFields": { "$ref": "#/definitions/measurementsForVfScalingFields" }, + "mobileFlowFields": { "$ref": "#/definitions/mobileFlowFields" }, + "otherFields": { "$ref": "#/definitions/otherFields" }, + "sipSignalingFields": { "$ref": "#/definitions/sipSignalingFields" }, + "stateChangeFields": { "$ref": "#/definitions/stateChangeFields" }, + "syslogFields": { "$ref": "#/definitions/syslogFields" }, + "thresholdCrossingAlertFields": { "$ref": "#/definitions/thresholdCrossingAlertFields" }, + "voiceQualityFields": { "$ref": "#/definitions/voiceQualityFields" } + }, + "required": [ "commonEventHeader" ] + }, + "eventDomainThrottleSpecification": { + "description": "specification of what information to suppress within an event domain", + "type": "object", + "properties": { + "eventDomain": { + "description": "Event domain enum from the commonEventHeader domain field", + "type": "string" + }, + "suppressedFieldNames": { + "description": "List of optional field names in the event block that should not be sent to the Event Listener", + "type": "array", + "items": { + "type": "string" + } + }, + "suppressedNvPairsList": { + "description": "Optional list of specific NvPairsNames to suppress within a given Name-Value Field", + "type": "array", + "items": { + "$ref": "#/definitions/suppressedNvPairs" + } + } + }, + "required": [ "eventDomain" ] + }, + "eventDomainThrottleSpecificationList": { + "description": "array of eventDomainThrottleSpecifications", + "type": "array", + "items": { + "$ref": "#/definitions/eventDomainThrottleSpecification" + }, + "minItems": 0 + }, + "eventList": { + "description": "array of events", + "type": "array", + "items": { + "$ref": "#/definitions/event" + } + }, + "eventThrottlingState": { + "description": "reports the throttling in force at the event source", + "type": "object", + "properties": { + "eventThrottlingMode": { + "description": "Mode the event manager is in", + "type": "string", + "enum": [ + "normal", + "throttled" + ] + }, + "eventDomainThrottleSpecificationList": { "$ref": "#/definitions/eventDomainThrottleSpecificationList" } + }, + "required": [ "eventThrottlingMode" ] + }, + "faultFields": { + "description": "fields specific to fault events", + "type": "object", + "properties": { + "alarmAdditionalInformation": { + "description": "additional alarm information", + "type": "array", + "items": { + "$ref": "#/definitions/field" + } + }, + "alarmCondition": { + "description": "alarm condition reported by the device", + "type": "string" + }, + "alarmInterfaceA": { + "description": "card, port, channel or interface name of the device generating the alarm", + "type": "string" + }, + "eventCategory": { + "description": "Event category, for example: license, link, routing, security, signaling", + "type": "string" + }, + "eventSeverity": { + "description": "event severity", + "type": "string", + "enum": [ + "CRITICAL", + "MAJOR", + "MINOR", + "WARNING", + "NORMAL" + ] + }, + "eventSourceType": { + "description": "type of event source; examples: card, host, other, port, portThreshold, router, slotThreshold, switch, virtualMachine, virtualNetworkFunction", + "type": "string" + }, + "faultFieldsVersion": { + "description": "version of the faultFields block", + "type": "number" + }, + "specificProblem": { + "description": "short description of the alarm or problem", + "type": "string" + }, + "vfStatus": { + "description": "virtual function status enumeration", + "type": "string", + "enum": [ + "Active", + "Idle", + "Preparing to terminate", + "Ready to terminate", + "Requesting termination" + ] + } + }, + "required": [ "alarmCondition", "eventSeverity", "eventSourceType", + "faultFieldsVersion", "specificProblem", "vfStatus" ] + }, + "featuresInUse": { + "description": "number of times an identified feature was used over the measurementInterval", + "type": "object", + "properties": { + "featureIdentifier": { "type": "string" }, + "featureUtilization": { "type": "integer" } + }, + "required": [ "featureIdentifier", "featureUtilization" ] + }, + "field": { + "description": "name value pair", + "type": "object", + "properties": { + "name": { "type": "string" }, + "value": { "type": "string" } + }, + "required": [ "name", "value" ] + }, + "filesystemUsage": { + "description": "disk usage of an identified virtual machine in gigabytes and/or gigabytes per second", + "type": "object", + "properties": { + "blockConfigured": { "type": "number" }, + "blockIops": { "type": "number" }, + "blockUsed": { "type": "number" }, + "ephemeralConfigured": { "type": "number" }, + "ephemeralIops": { "type": "number" }, + "ephemeralUsed": { "type": "number" }, + "filesystemName": { "type": "string" } + }, + "required": [ "blockConfigured", "blockIops", "blockUsed", "ephemeralConfigured", + "ephemeralIops", "ephemeralUsed", "filesystemName" ] + }, + "gtpPerFlowMetrics": { + "description": "Mobility GTP Protocol per flow metrics", + "type": "object", + "properties": { + "avgBitErrorRate": { + "description": "average bit error rate", + "type": "number" + }, + "avgPacketDelayVariation": { + "description": "Average packet delay variation or jitter in milliseconds for received packets: Average difference between the packet timestamp and time received for all pairs of consecutive packets", + "type": "number" + }, + "avgPacketLatency": { + "description": "average delivery latency", + "type": "number" + }, + "avgReceiveThroughput": { + "description": "average receive throughput", + "type": "number" + }, + "avgTransmitThroughput": { + "description": "average transmit throughput", + "type": "number" + }, + "durConnectionFailedStatus": { + "description": "duration of failed state in milliseconds, computed as the cumulative time between a failed echo request and the next following successful error request, over this reporting interval", + "type": "number" + }, + "durTunnelFailedStatus": { + "description": "Duration of errored state, computed as the cumulative time between a tunnel error indicator and the next following non-errored indicator, over this reporting interval", + "type": "number" + }, + "flowActivatedBy": { + "description": "Endpoint activating the flow", + "type": "string" + }, + "flowActivationEpoch": { + "description": "Time the connection is activated in the flow (connection) being reported on, or transmission time of the first packet if activation time is not available", + "type": "number" + }, + "flowActivationMicrosec": { + "description": "Integer microseconds for the start of the flow connection", + "type": "number" + }, + "flowActivationTime": { + "description": "time the connection is activated in the flow being reported on, or transmission time of the first packet if activation time is not available; with RFC 2822 compliant format: Sat, 13 Mar 2010 11:29:05 -0800", + "type": "string" + }, + "flowDeactivatedBy": { + "description": "Endpoint deactivating the flow", + "type": "string" + }, + "flowDeactivationEpoch": { + "description": "Time for the start of the flow connection, in integer UTC epoch time aka UNIX time", + "type": "number" + }, + "flowDeactivationMicrosec": { + "description": "Integer microseconds for the start of the flow connection", + "type": "number" + }, + "flowDeactivationTime": { + "description": "Transmission time of the first packet in the flow connection being reported on; with RFC 2822 compliant format: Sat, 13 Mar 2010 11:29:05 -0800", + "type": "string" + }, + "flowStatus": { + "description": "connection status at reporting time as a working / inactive / failed indicator value", + "type": "string" + }, + "gtpConnectionStatus": { + "description": "Current connection state at reporting time", + "type": "string" + }, + "gtpTunnelStatus": { + "description": "Current tunnel state at reporting time", + "type": "string" + }, + "ipTosCountList": { + "description": "array of key: value pairs where the keys are drawn from the IP Type-of-Service identifiers which range from '0' to '255', and the values are the count of packets that had those ToS identifiers in the flow", + "type": "array", + "items": { + "type": "array", + "items": [ + { "type": "string" }, + { "type": "number" } + ] + } + }, + "ipTosList": { + "description": "Array of unique IP Type-of-Service values observed in the flow where values range from '0' to '255'", + "type": "array", + "items": { + "type": "string" + } + }, + "largePacketRtt": { + "description": "large packet round trip time", + "type": "number" + }, + "largePacketThreshold": { + "description": "large packet threshold being applied", + "type": "number" + }, + "maxPacketDelayVariation": { + "description": "Maximum packet delay variation or jitter in milliseconds for received packets: Maximum of the difference between the packet timestamp and time received for all pairs of consecutive packets", + "type": "number" + }, + "maxReceiveBitRate": { + "description": "maximum receive bit rate", + "type": "number" + }, + "maxTransmitBitRate": { + "description": "maximum transmit bit rate", + "type": "number" + }, + "mobileQciCosCountList": { + "description": "array of key: value pairs where the keys are drawn from LTE QCI or UMTS class of service strings, and the values are the count of packets that had those strings in the flow", + "type": "array", + "items": { + "type": "array", + "items": [ + { "type": "string" }, + { "type": "number" } + ] + } + }, + "mobileQciCosList": { + "description": "Array of unique LTE QCI or UMTS class-of-service values observed in the flow", + "type": "array", + "items": { + "type": "string" + } + }, + "numActivationFailures": { + "description": "Number of failed activation requests, as observed by the reporting node", + "type": "number" + }, + "numBitErrors": { + "description": "number of errored bits", + "type": "number" + }, + "numBytesReceived": { + "description": "number of bytes received, including retransmissions", + "type": "number" + }, + "numBytesTransmitted": { + "description": "number of bytes transmitted, including retransmissions", + "type": "number" + }, + "numDroppedPackets": { + "description": "number of received packets dropped due to errors per virtual interface", + "type": "number" + }, + "numGtpEchoFailures": { + "description": "Number of Echo request path failures where failed paths are defined in 3GPP TS 29.281 sec 7.2.1 and 3GPP TS 29.060 sec. 11.2", + "type": "number" + }, + "numGtpTunnelErrors": { + "description": "Number of tunnel error indications where errors are defined in 3GPP TS 29.281 sec 7.3.1 and 3GPP TS 29.060 sec. 11.1", + "type": "number" + }, + "numHttpErrors": { + "description": "Http error count", + "type": "number" + }, + "numL7BytesReceived": { + "description": "number of tunneled layer 7 bytes received, including retransmissions", + "type": "number" + }, + "numL7BytesTransmitted": { + "description": "number of tunneled layer 7 bytes transmitted, excluding retransmissions", + "type": "number" + }, + "numLostPackets": { + "description": "number of lost packets", + "type": "number" + }, + "numOutOfOrderPackets": { + "description": "number of out-of-order packets", + "type": "number" + }, + "numPacketErrors": { + "description": "number of errored packets", + "type": "number" + }, + "numPacketsReceivedExclRetrans": { + "description": "number of packets received, excluding retransmission", + "type": "number" + }, + "numPacketsReceivedInclRetrans": { + "description": "number of packets received, including retransmission", + "type": "number" + }, + "numPacketsTransmittedInclRetrans": { + "description": "number of packets transmitted, including retransmissions", + "type": "number" + }, + "numRetries": { + "description": "number of packet retries", + "type": "number" + }, + "numTimeouts": { + "description": "number of packet timeouts", + "type": "number" + }, + "numTunneledL7BytesReceived": { + "description": "number of tunneled layer 7 bytes received, excluding retransmissions", + "type": "number" + }, + "roundTripTime": { + "description": "round trip time", + "type": "number" + }, + "tcpFlagCountList": { + "description": "array of key: value pairs where the keys are drawn from TCP Flags and the values are the count of packets that had that TCP Flag in the flow", + "type": "array", + "items": { + "type": "array", + "items": [ + { "type": "string" }, + { "type": "number" } + ] + } + }, + "tcpFlagList": { + "description": "Array of unique TCP Flags observed in the flow", + "type": "array", + "items": { + "type": "string" + } + }, + "timeToFirstByte": { + "description": "Time in milliseconds between the connection activation and first byte received", + "type": "number" + } + }, + "required": [ "avgBitErrorRate", "avgPacketDelayVariation", "avgPacketLatency", + "avgReceiveThroughput", "avgTransmitThroughput", + "flowActivationEpoch", "flowActivationMicrosec", + "flowDeactivationEpoch", "flowDeactivationMicrosec", + "flowDeactivationTime", "flowStatus", + "maxPacketDelayVariation", "numActivationFailures", + "numBitErrors", "numBytesReceived", "numBytesTransmitted", + "numDroppedPackets", "numL7BytesReceived", + "numL7BytesTransmitted", "numLostPackets", + "numOutOfOrderPackets", "numPacketErrors", + "numPacketsReceivedExclRetrans", + "numPacketsReceivedInclRetrans", + "numPacketsTransmittedInclRetrans", + "numRetries", "numTimeouts", "numTunneledL7BytesReceived", + "roundTripTime", "timeToFirstByte" + ] + }, + "heartbeatFields": { + "description": "optional field block for fields specific to heartbeat events", + "type": "object", + "properties": { + "additionalFields": { + "description": "additional heartbeat fields if needed", + "type": "array", + "items": { + "$ref": "#/definitions/field" + } + }, + "heartbeatFieldsVersion": { + "description": "version of the heartbeatFields block", + "type": "number" + }, + "heartbeatInterval": { + "description": "current heartbeat interval in seconds", + "type": "integer" + } + }, + "required": [ "heartbeatFieldsVersion", "heartbeatInterval" ] + }, + "internalHeaderFields": { + "description": "enrichment fields for internal VES Event Listener service use only, not supplied by event sources", + "type": "object" + }, + "jsonObject": { + "description": "json object schema, name and other meta-information along with one or more object instances", + "type": "object", + "properties": { + "objectInstances": { + "description": "one or more instances of the jsonObject", + "type": "array", + "items": { + "$ref": "#/definitions/jsonObjectInstance" + } + }, + "objectName": { + "description": "name of the JSON Object", + "type": "string" + }, + "objectSchema": { + "description": "json schema for the object", + "type": "string" + }, + "objectSchemaUrl": { + "description": "Url to the json schema for the object", + "type": "string" + }, + "nfSubscribedObjectName": { + "description": "name of the object associated with the nfSubscriptonId", + "type": "string" + }, + "nfSubscriptionId": { + "description": "identifies an openConfig telemetry subscription on a network function, which configures the network function to send complex object data associated with the jsonObject", + "type": "string" + } + }, + "required": [ "objectInstances", "objectName" ] + }, + "jsonObjectInstance": { + "description": "meta-information about an instance of a jsonObject along with the actual object instance", + "type": "object", + "properties": { + "objectInstance": { + "description": "an instance conforming to the jsonObject schema", + "type": "object" + }, + "objectInstanceEpochMicrosec": { + "description": "the unix time aka epoch time associated with this objectInstance--as microseconds elapsed since 1 Jan 1970 not including leap seconds", + "type": "number" + }, + "objectKeys": { + "description": "an ordered set of keys that identifies this particular instance of jsonObject", + "type": "array", + "items": { + "$ref": "#/definitions/key" + } + } + }, + "required": [ "objectInstance" ] + }, + "key": { + "description": "tuple which provides the name of a key along with its value and relative order", + "type": "object", + "properties": { + "keyName": { + "description": "name of the key", + "type": "string" + }, + "keyOrder": { + "description": "relative sequence or order of the key with respect to other keys", + "type": "integer" + }, + "keyValue": { + "description": "value of the key", + "type": "string" + } + }, + "required": [ "keyName" ] + }, + "latencyBucketMeasure": { + "description": "number of counts falling within a defined latency bucket", + "type": "object", + "properties": { + "countsInTheBucket": { "type": "number" }, + "highEndOfLatencyBucket": { "type": "number" }, + "lowEndOfLatencyBucket": { "type": "number" } + }, + "required": [ "countsInTheBucket" ] + }, + "measurementGroup": { + "description": "measurement group", + "type": "object", + "properties": { + "name": { "type": "string" }, + "measurements": { + "description": "array of name value pair measurements", + "type": "array", + "items": { + "$ref": "#/definitions/field" + } + } + }, + "required": [ "name", "measurements" ] + }, + "measurementsForVfScalingFields": { + "description": "measurementsForVfScaling fields", + "type": "object", + "properties": { + "additionalFields": { + "description": "additional name-value-pair fields", + "type": "array", + "items": { + "$ref": "#/definitions/field" + } + }, + "additionalMeasurements": { + "description": "array of named name-value-pair arrays", + "type": "array", + "items": { + "$ref": "#/definitions/namedArrayOfFields" + } + }, + "additionalObjects": { + "description": "array of JSON objects described by name, schema and other meta-information", + "type": "array", + "items": { + "$ref": "#/definitions/jsonObject" + } + }, + "codecUsageArray": { + "description": "array of codecs in use", + "type": "array", + "items": { + "$ref": "#/definitions/codecsInUse" + } + }, + "concurrentSessions": { + "description": "peak concurrent sessions for the VM or VNF over the measurementInterval", + "type": "integer" + }, + "configuredEntities": { + "description": "over the measurementInterval, peak total number of: users, subscribers, devices, adjacencies, etc., for the VM, or subscribers, devices, etc., for the VNF", + "type": "integer" + }, + "cpuUsageArray": { + "description": "usage of an array of CPUs", + "type": "array", + "items": { + "$ref": "#/definitions/cpuUsage" + } + }, + "diskUsageArray": { + "description": "usage of an array of disks", + "type": "array", + "items": { + "$ref": "#/definitions/diskUsage" + } + }, + "featureUsageArray": { + "description": "array of features in use", + "type": "array", + "items": { + "$ref": "#/definitions/featuresInUse" + } + }, + "filesystemUsageArray": { + "description": "filesystem usage of the VM on which the VNFC reporting the event is running", + "type": "array", + "items": { + "$ref": "#/definitions/filesystemUsage" + } + }, + "latencyDistribution": { + "description": "array of integers representing counts of requests whose latency in milliseconds falls within per-VNF configured ranges", + "type": "array", + "items": { + "$ref": "#/definitions/latencyBucketMeasure" + } + }, + "meanRequestLatency": { + "description": "mean seconds required to respond to each request for the VM on which the VNFC reporting the event is running", + "type": "number" + }, + "measurementInterval": { + "description": "interval over which measurements are being reported in seconds", + "type": "number" + }, + "measurementsForVfScalingVersion": { + "description": "version of the measurementsForVfScaling block", + "type": "number" + }, + "memoryUsageArray": { + "description": "memory usage of an array of VMs", + "type": "array", + "items": { + "$ref": "#/definitions/memoryUsage" + } + }, + "numberOfMediaPortsInUse": { + "description": "number of media ports in use", + "type": "integer" + }, + "requestRate": { + "description": "peak rate of service requests per second to the VNF over the measurementInterval", + "type": "number" + }, + "vnfcScalingMetric": { + "description": "represents busy-ness of the VNF from 0 to 100 as reported by the VNFC", + "type": "integer" + }, + "vNicPerformanceArray": { + "description": "usage of an array of virtual network interface cards", + "type": "array", + "items": { + "$ref": "#/definitions/vNicPerformance" + } + } + }, + "required": [ "measurementInterval", "measurementsForVfScalingVersion" ] + }, + "memoryUsage": { + "description": "memory usage of an identified virtual machine", + "type": "object", + "properties": { + "memoryBuffered": { + "description": "kilobytes of temporary storage for raw disk blocks", + "type": "number" + }, + "memoryCached": { + "description": "kilobytes of memory used for cache", + "type": "number" + }, + "memoryConfigured": { + "description": "kilobytes of memory configured in the virtual machine on which the VNFC reporting the event is running", + "type": "number" + }, + "memoryFree": { + "description": "kilobytes of physical RAM left unused by the system", + "type": "number" + }, + "memorySlabRecl": { + "description": "the part of the slab that can be reclaimed such as caches measured in kilobytes", + "type": "number" + }, + "memorySlabUnrecl": { + "description": "the part of the slab that cannot be reclaimed even when lacking memory measured in kilobytes", + "type": "number" + }, + "memoryUsed": { + "description": "total memory minus the sum of free, buffered, cached and slab memory measured in kilobytes", + "type": "number" + }, + "vmIdentifier": { + "description": "virtual machine identifier associated with the memory metrics", + "type": "string" + } + }, + "required": [ "memoryFree", "memoryUsed", "vmIdentifier" ] + }, + "mobileFlowFields": { + "description": "mobileFlow fields", + "type": "object", + "properties": { + "additionalFields": { + "description": "additional mobileFlow fields if needed", + "type": "array", + "items": { + "$ref": "#/definitions/field" + } + }, + "applicationType": { + "description": "Application type inferred", + "type": "string" + }, + "appProtocolType": { + "description": "application protocol", + "type": "string" + }, + "appProtocolVersion": { + "description": "application protocol version", + "type": "string" + }, + "cid": { + "description": "cell id", + "type": "string" + }, + "connectionType": { + "description": "Abbreviation referencing a 3GPP reference point e.g., S1-U, S11, etc", + "type": "string" + }, + "ecgi": { + "description": "Evolved Cell Global Id", + "type": "string" + }, + "flowDirection": { + "description": "Flow direction, indicating if the reporting node is the source of the flow or destination for the flow", + "type": "string" + }, + "gtpPerFlowMetrics": { "$ref": "#/definitions/gtpPerFlowMetrics" }, + "gtpProtocolType": { + "description": "GTP protocol", + "type": "string" + }, + "gtpVersion": { + "description": "GTP protocol version", + "type": "string" + }, + "httpHeader": { + "description": "HTTP request header, if the flow connects to a node referenced by HTTP", + "type": "string" + }, + "imei": { + "description": "IMEI for the subscriber UE used in this flow, if the flow connects to a mobile device", + "type": "string" + }, + "imsi": { + "description": "IMSI for the subscriber UE used in this flow, if the flow connects to a mobile device", + "type": "string" + }, + "ipProtocolType": { + "description": "IP protocol type e.g., TCP, UDP, RTP...", + "type": "string" + }, + "ipVersion": { + "description": "IP protocol version e.g., IPv4, IPv6", + "type": "string" + }, + "lac": { + "description": "location area code", + "type": "string" + }, + "mcc": { + "description": "mobile country code", + "type": "string" + }, + "mnc": { + "description": "mobile network code", + "type": "string" + }, + "mobileFlowFieldsVersion": { + "description": "version of the mobileFlowFields block", + "type": "number" + }, + "msisdn": { + "description": "MSISDN for the subscriber UE used in this flow, as an integer, if the flow connects to a mobile device", + "type": "string" + }, + "otherEndpointIpAddress": { + "description": "IP address for the other endpoint, as used for the flow being reported on", + "type": "string" + }, + "otherEndpointPort": { + "description": "IP Port for the reporting entity, as used for the flow being reported on", + "type": "integer" + }, + "otherFunctionalRole": { + "description": "Functional role of the other endpoint for the flow being reported on e.g., MME, S-GW, P-GW, PCRF...", + "type": "string" + }, + "rac": { + "description": "routing area code", + "type": "string" + }, + "radioAccessTechnology": { + "description": "Radio Access Technology e.g., 2G, 3G, LTE", + "type": "string" + }, + "reportingEndpointIpAddr": { + "description": "IP address for the reporting entity, as used for the flow being reported on", + "type": "string" + }, + "reportingEndpointPort": { + "description": "IP port for the reporting entity, as used for the flow being reported on", + "type": "integer" + }, + "sac": { + "description": "service area code", + "type": "string" + }, + "samplingAlgorithm": { + "description": "Integer identifier for the sampling algorithm or rule being applied in calculating the flow metrics if metrics are calculated based on a sample of packets, or 0 if no sampling is applied", + "type": "integer" + }, + "tac": { + "description": "transport area code", + "type": "string" + }, + "tunnelId": { + "description": "tunnel identifier", + "type": "string" + }, + "vlanId": { + "description": "VLAN identifier used by this flow", + "type": "string" + } + }, + "required": [ "flowDirection", "gtpPerFlowMetrics", "ipProtocolType", "ipVersion", + "mobileFlowFieldsVersion", "otherEndpointIpAddress", "otherEndpointPort", + "reportingEndpointIpAddr", "reportingEndpointPort" ] + }, + "namedArrayOfFields": { + "description": "an array of name value pairs along with a name for the array", + "type": "object", + "properties": { + "name": { "type": "string" }, + "arrayOfFields": { + "description": "array of name value pairs", + "type": "array", + "items": { + "$ref": "#/definitions/field" + } + } + }, + "required": [ "name", "measurements" ] + }, + "otherFields": { + "description": "fields for events belonging to the 'other' domain of the commonEventHeader domain enumeration", + "type": "object", + "properties": { + "hashOfNameValuePairArrays": { + "description": "array of named name-value-pair arrays", + "type": "array", + "items": { + "$ref": "#/definitions/namedArrayOfFields" + } + }, + "jsonObjects": { + "description": "array of JSON objects described by name, schema and other meta-information", + "type": "array", + "items": { + "$ref": "#/definitions/jsonObject" + } + }, + "nameValuePairs": { + "description": "array of name-value pairs", + "type": "array", + "items": { + "$ref": "#/definitions/field" + } + }, + "otherFieldsVersion": { + "description": "version of the otherFields block", + "type": "number" + } + }, + "required": [ "otherFieldsVersion" ] + }, + "requestError": { + "description": "standard request error data structure", + "type": "object", + "properties": { + "messageId": { + "description": "Unique message identifier of the format ABCnnnn where ABC is either SVC for Service Exceptions or POL for Policy Exception", + "type": "string" + }, + "text": { + "description": "Message text, with replacement variables marked with %n, where n is an index into the list of elements, starting at 1", + "type": "string" + }, + "url": { + "description": "Hyperlink to a detailed error resource e.g., an HTML page for browser user agents", + "type": "string" + }, + "variables": { + "description": "List of zero or more strings that represent the contents of the variables used by the message text", + "type": "string" + } + }, + "required": [ "messageId", "text" ] + }, + "sipSignalingFields": { + "description": "sip signaling fields", + "type": "object", + "properties": { + "additionalInformation": { + "description": "additional sip signaling fields if needed", + "type": "array", + "items": { + "$ref": "#/definitions/field" + } + }, + "compressedSip": { + "description": "the full SIP request/response including headers and bodies", + "type": "string" + }, + "correlator": { + "description": "this is the same for all events on this call", + "type": "string" + }, + "localIpAddress": { + "description": "IP address on VNF", + "type": "string" + }, + "localPort": { + "description": "port on VNF", + "type": "string" + }, + "remoteIpAddress": { + "description": "IP address of peer endpoint", + "type": "string" + }, + "remotePort": { + "description": "port of peer endpoint", + "type": "string" + }, + "sipSignalingFieldsVersion": { + "description": "version of the sipSignalingFields block", + "type": "number" + }, + "summarySip": { + "description": "the SIP Method or Response (‘INVITE’, ‘200 OK’, ‘BYE’, etc)", + "type": "string" + }, + "vnfVendorNameFields": { + "$ref": "#/definitions/vendorVnfNameFields" + } + }, + "required": [ "correlator", "localIpAddress", "localPort", "remoteIpAddress", + "remotePort", "sipSignalingFieldsVersion", "vnfVendorNameFields" ] + }, + "stateChangeFields": { + "description": "stateChange fields", + "type": "object", + "properties": { + "additionalFields": { + "description": "additional stateChange fields if needed", + "type": "array", + "items": { + "$ref": "#/definitions/field" + } + }, + "newState": { + "description": "new state of the entity", + "type": "string", + "enum": [ + "inService", + "maintenance", + "outOfService" + ] + }, + "oldState": { + "description": "previous state of the entity", + "type": "string", + "enum": [ + "inService", + "maintenance", + "outOfService" + ] + }, + "stateChangeFieldsVersion": { + "description": "version of the stateChangeFields block", + "type": "number" + }, + "stateInterface": { + "description": "card or port name of the entity that changed state", + "type": "string" + } + }, + "required": [ "newState", "oldState", "stateChangeFieldsVersion", "stateInterface" ] + }, + "suppressedNvPairs": { + "description": "List of specific NvPairsNames to suppress within a given Name-Value Field for event Throttling", + "type": "object", + "properties": { + "nvPairFieldName": { + "description": "Name of the field within which are the nvpair names to suppress", + "type": "string" + }, + "suppressedNvPairNames": { + "description": "Array of nvpair names to suppress within the nvpairFieldName", + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ "nvPairFieldName", "suppressedNvPairNames" ] + }, + "syslogFields": { + "description": "sysLog fields", + "type": "object", + "properties": { + "additionalFields": { + "description": "additional syslog fields if needed provided as name=value delimited by a pipe ‘|’ symbol, for example: 'name1=value1|name2=value2|…'", + "type": "string" + }, + "eventSourceHost": { + "description": "hostname of the device", + "type": "string" + }, + "eventSourceType": { + "description": "type of event source; examples: other, router, switch, host, card, port, slotThreshold, portThreshold, virtualMachine, virtualNetworkFunction", + "type": "string" + }, + "syslogFacility": { + "description": "numeric code from 0 to 23 for facility--see table in documentation", + "type": "integer" + }, + "syslogFieldsVersion": { + "description": "version of the syslogFields block", + "type": "number" + }, + "syslogMsg": { + "description": "syslog message", + "type": "string" + }, + "syslogPri": { + "description": "0-192 combined severity and facility", + "type": "integer" + }, + "syslogProc": { + "description": "identifies the application that originated the message", + "type": "string" + }, + "syslogProcId": { + "description": "a change in the value of this field indicates a discontinuity in syslog reporting", + "type": "number" + }, + "syslogSData": { + "description": "syslog structured data consisting of a structured data Id followed by a set of key value pairs", + "type": "string" + }, + "syslogSdId": { + "description": "0-32 char in format name@number for example ourSDID@32473", + "type": "string" + }, + "syslogSev": { + "description": "numerical Code for severity derived from syslogPri as remaider of syslogPri / 8", + "type": "string", + "enum": [ + "Alert", + "Critical", + "Debug", + "Emergency", + "Error", + "Info", + "Notice", + "Warning" + ] + }, + "syslogTag": { + "description": "msgId indicating the type of message such as TCPOUT or TCPIN; NILVALUE should be used when no other value can be provided", + "type": "string" + }, + "syslogVer": { + "description": "IANA assigned version of the syslog protocol specification - typically 1", + "type": "number" + } + }, + "required": [ "eventSourceType", "syslogFieldsVersion", "syslogMsg", "syslogTag" ] + }, + "thresholdCrossingAlertFields": { + "description": "fields specific to threshold crossing alert events", + "type": "object", + "properties": { + "additionalFields": { + "description": "additional threshold crossing alert fields if needed", + "type": "array", + "items": { + "$ref": "#/definitions/field" + } + }, + "additionalParameters": { + "description": "performance counters", + "type": "array", + "items": { + "$ref": "#/definitions/counter" + } + }, + "alertAction": { + "description": "Event action", + "type": "string", + "enum": [ + "CLEAR", + "CONT", + "SET" + ] + }, + "alertDescription": { + "description": "Unique short alert description such as IF-SHUB-ERRDROP", + "type": "string" + }, + "alertType": { + "description": "Event type", + "type": "string", + "enum": [ + "CARD-ANOMALY", + "ELEMENT-ANOMALY", + "INTERFACE-ANOMALY", + "SERVICE-ANOMALY" + ] + }, + "alertValue": { + "description": "Calculated API value (if applicable)", + "type": "string" + }, + "associatedAlertIdList": { + "description": "List of eventIds associated with the event being reported", + "type": "array", + "items": { "type": "string" } + }, + "collectionTimestamp": { + "description": "Time when the performance collector picked up the data; with RFC 2822 compliant format: Sat, 13 Mar 2010 11:29:05 -0800", + "type": "string" + }, + "dataCollector": { + "description": "Specific performance collector instance used", + "type": "string" + }, + "elementType": { + "description": "type of network element - internal ATT field", + "type": "string" + }, + "eventSeverity": { + "description": "event severity or priority", + "type": "string", + "enum": [ + "CRITICAL", + "MAJOR", + "MINOR", + "WARNING", + "NORMAL" + ] + }, + "eventStartTimestamp": { + "description": "Time closest to when the measurement was made; with RFC 2822 compliant format: Sat, 13 Mar 2010 11:29:05 -0800", + "type": "string" + }, + "interfaceName": { + "description": "Physical or logical port or card (if applicable)", + "type": "string" + }, + "networkService": { + "description": "network name - internal ATT field", + "type": "string" + }, + "possibleRootCause": { + "description": "Reserved for future use", + "type": "string" + }, + "thresholdCrossingFieldsVersion": { + "description": "version of the thresholdCrossingAlertFields block", + "type": "number" + } + }, + "required": [ + "additionalParameters", + "alertAction", + "alertDescription", + "alertType", + "collectionTimestamp", + "eventSeverity", + "eventStartTimestamp", + "thresholdCrossingFieldsVersion" + ] + }, + "vendorVnfNameFields": { + "description": "provides vendor, vnf and vfModule identifying information", + "type": "object", + "properties": { + "vendorName": { + "description": "VNF vendor name", + "type": "string" + }, + "vfModuleName": { + "description": "ASDC vfModuleName for the vfModule generating the event", + "type": "string" + }, + "vnfName": { + "description": "ASDC modelName for the VNF generating the event", + "type": "string" + } + }, + "required": [ "vendorName" ] + }, + "vNicPerformance": { + "description": "describes the performance and errors of an identified virtual network interface card", + "type": "object", + "properties": { + "receivedBroadcastPacketsAccumulated": { + "description": "Cumulative count of broadcast packets received as read at the end of the measurement interval", + "type": "number" + }, + "receivedBroadcastPacketsDelta": { + "description": "Count of broadcast packets received within the measurement interval", + "type": "number" + }, + "receivedDiscardedPacketsAccumulated": { + "description": "Cumulative count of discarded packets received as read at the end of the measurement interval", + "type": "number" + }, + "receivedDiscardedPacketsDelta": { + "description": "Count of discarded packets received within the measurement interval", + "type": "number" + }, + "receivedErrorPacketsAccumulated": { + "description": "Cumulative count of error packets received as read at the end of the measurement interval", + "type": "number" + }, + "receivedErrorPacketsDelta": { + "description": "Count of error packets received within the measurement interval", + "type": "number" + }, + "receivedMulticastPacketsAccumulated": { + "description": "Cumulative count of multicast packets received as read at the end of the measurement interval", + "type": "number" + }, + "receivedMulticastPacketsDelta": { + "description": "Count of multicast packets received within the measurement interval", + "type": "number" + }, + "receivedOctetsAccumulated": { + "description": "Cumulative count of octets received as read at the end of the measurement interval", + "type": "number" + }, + "receivedOctetsDelta": { + "description": "Count of octets received within the measurement interval", + "type": "number" + }, + "receivedTotalPacketsAccumulated": { + "description": "Cumulative count of all packets received as read at the end of the measurement interval", + "type": "number" + }, + "receivedTotalPacketsDelta": { + "description": "Count of all packets received within the measurement interval", + "type": "number" + }, + "receivedUnicastPacketsAccumulated": { + "description": "Cumulative count of unicast packets received as read at the end of the measurement interval", + "type": "number" + }, + "receivedUnicastPacketsDelta": { + "description": "Count of unicast packets received within the measurement interval", + "type": "number" + }, + "transmittedBroadcastPacketsAccumulated": { + "description": "Cumulative count of broadcast packets transmitted as read at the end of the measurement interval", + "type": "number" + }, + "transmittedBroadcastPacketsDelta": { + "description": "Count of broadcast packets transmitted within the measurement interval", + "type": "number" + }, + "transmittedDiscardedPacketsAccumulated": { + "description": "Cumulative count of discarded packets transmitted as read at the end of the measurement interval", + "type": "number" + }, + "transmittedDiscardedPacketsDelta": { + "description": "Count of discarded packets transmitted within the measurement interval", + "type": "number" + }, + "transmittedErrorPacketsAccumulated": { + "description": "Cumulative count of error packets transmitted as read at the end of the measurement interval", + "type": "number" + }, + "transmittedErrorPacketsDelta": { + "description": "Count of error packets transmitted within the measurement interval", + "type": "number" + }, + "transmittedMulticastPacketsAccumulated": { + "description": "Cumulative count of multicast packets transmitted as read at the end of the measurement interval", + "type": "number" + }, + "transmittedMulticastPacketsDelta": { + "description": "Count of multicast packets transmitted within the measurement interval", + "type": "number" + }, + "transmittedOctetsAccumulated": { + "description": "Cumulative count of octets transmitted as read at the end of the measurement interval", + "type": "number" + }, + "transmittedOctetsDelta": { + "description": "Count of octets transmitted within the measurement interval", + "type": "number" + }, + "transmittedTotalPacketsAccumulated": { + "description": "Cumulative count of all packets transmitted as read at the end of the measurement interval", + "type": "number" + }, + "transmittedTotalPacketsDelta": { + "description": "Count of all packets transmitted within the measurement interval", + "type": "number" + }, + "transmittedUnicastPacketsAccumulated": { + "description": "Cumulative count of unicast packets transmitted as read at the end of the measurement interval", + "type": "number" + }, + "transmittedUnicastPacketsDelta": { + "description": "Count of unicast packets transmitted within the measurement interval", + "type": "number" + }, + "valuesAreSuspect": { + "description": "Indicates whether vNicPerformance values are likely inaccurate due to counter overflow or other condtions", + "type": "string", + "enum": [ "true", "false" ] + }, + "vNicIdentifier": { + "description": "vNic identification", + "type": "string" + } + }, + "required": [ "valuesAreSuspect", "vNicIdentifier" ] + }, + "voiceQualityFields": { + "description": "provides statistics related to customer facing voice products", + "type": "object", + "properties": { + "additionalInformation": { + "description": "additional voice quality fields if needed", + "type": "array", + "items": { + "$ref": "#/definitions/field" + } + }, + "calleeSideCodec": { + "description": "callee codec for the call", + "type": "string" + }, + "callerSideCodec": { + "description": "caller codec for the call", + "type": "string" + }, + "correlator": { + "description": "this is the same for all events on this call", + "type": "string" + }, + "endOfCallVqmSummaries": { + "$ref": "#/definitions/endOfCallVqmSummaries" + }, + "phoneNumber": { + "description": "phone number associated with the correlator", + "type": "string" + }, + "midCallRtcp": { + "description": "Base64 encoding of the binary RTCP data excluding Eth/IP/UDP headers", + "type": "string" + }, + "vendorVnfNameFields": { + "$ref": "#/definitions/vendorVnfNameFields" + }, + "voiceQualityFieldsVersion": { + "description": "version of the voiceQualityFields block", + "type": "number" + } + }, + "required": [ "calleeSideCodec", "callerSideCodec", "correlator", "midCallRtcp", + "vendorVnfNameFields", "voiceQualityFieldsVersion" ] + } + }, + "title": "Event Listener", + "type": "object", + "properties": { + "event": {"$ref": "#/definitions/event"} + } +} diff --git a/veslibrary/ves_clibrary/evel/evel-test-collector/docs/att_interface_definition/test_control_schema.json b/veslibrary/ves_clibrary/evel/evel-test-collector/docs/att_interface_definition/test_control_schema.json new file mode 100644 index 0000000..ced0153 --- /dev/null +++ b/veslibrary/ves_clibrary/evel/evel-test-collector/docs/att_interface_definition/test_control_schema.json @@ -0,0 +1,15 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "Test Collector Test Control API - commands", + "type": "object", + "properties": { + "commandList": { + "description": "array of commands from an event collector toward an event source", + "type": "array", + "items": { + "$ref": "#/definitions/commandListEntry" + }, + "minItems": 0} + }, + "required": ["commandList"] +} diff --git a/veslibrary/ves_clibrary/evel/evel-test-collector/docs/att_interface_definition/throttle_schema.json b/veslibrary/ves_clibrary/evel/evel-test-collector/docs/att_interface_definition/throttle_schema.json new file mode 100644 index 0000000..7763a34 --- /dev/null +++ b/veslibrary/ves_clibrary/evel/evel-test-collector/docs/att_interface_definition/throttle_schema.json @@ -0,0 +1,9 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "Vendor Event Listener API - eventThrottlingState", + "type": "object", + "properties": { + "eventThrottlingState": {"$ref": "#/definitions/eventThrottlingState"} + }, + "required": ["eventThrottlingState"] +} diff --git a/veslibrary/ves_clibrary/evel/evel-test-collector/docs/test_collector_user_guide/LICENSE.TXT b/veslibrary/ves_clibrary/evel/evel-test-collector/docs/test_collector_user_guide/LICENSE.TXT new file mode 100644 index 0000000..ae12da2 --- /dev/null +++ b/veslibrary/ves_clibrary/evel/evel-test-collector/docs/test_collector_user_guide/LICENSE.TXT @@ -0,0 +1,22 @@ +/* + * ============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. + * + */ diff --git a/veslibrary/ves_clibrary/evel/evel-test-collector/docs/test_collector_user_guide/images/architecture.png b/veslibrary/ves_clibrary/evel/evel-test-collector/docs/test_collector_user_guide/images/architecture.png new file mode 100644 index 0000000..98adb31 Binary files /dev/null and b/veslibrary/ves_clibrary/evel/evel-test-collector/docs/test_collector_user_guide/images/architecture.png differ diff --git a/veslibrary/ves_clibrary/evel/evel-test-collector/docs/test_collector_user_guide/test_collector_user_guide.md b/veslibrary/ves_clibrary/evel/evel-test-collector/docs/test_collector_user_guide/test_collector_user_guide.md new file mode 100644 index 0000000..f7a0818 --- /dev/null +++ b/veslibrary/ves_clibrary/evel/evel-test-collector/docs/test_collector_user_guide/test_collector_user_guide.md @@ -0,0 +1,294 @@ +# AT&T Vendor Event Listener Service - Test Collector - User Guide +# =================================================================== +# 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. + + +Introduction +============ + +Background +---------- + +This document describes how to use the Test Collector application to simulate +the service API described in "AT&T Service Specification, Service: +Vendor Event Listener Revision 2.11, 16-Sep-2016". + +Purpose +------- + +This User Guide is intended to enable the reader to understand how + the Test Collector can be used to verify the operation of applications + supporting the Vendor Event Listener API. + + +Realization +=========== + +The realization of the Test Collector is a Python script which acts as a +server for the Vendor Event Listener API. It uses [jsonschema](https://pypi.python.org/pypi/jsonschema) +in order to validate the received JSON events against AT&T's published +schema for the API. + +The overall system architecture is shown in Figure 1 and comprises + three key deliverables: + +* The web-application itself. + +* A Backend service. + +* A validating test collector application. + +The Test Collector is described in more detail in the + following sections. The other two components are described in a separate + documents: + +* Reference VNF User Guide + +* Reference VNF Application Note + +Figure 1: Realization Architecture + +![Realization Architecture](images/architecture.png) + +Note that items shown in green in the diagram are existing AT&T + systems and do not form part of the delivery. + +Validating Collector +-------------------- + +The validating collector provides a basic test capability for + the Reference VNF. The application implements the Vendor Event + Listener API providing: + +- Logging of new requests. + +- Validating requests against the published schema. + +- Validating the credentials provided in the request. + +- Responding with a 202 Accepted for valid requests. + +- Test Control endpoint allowing a test harness or user to set a pending + commandList, to be sent in response to the next event received. + +- Responding with a 202 Accepted plus a pending commandList. + +- Responding with a 401 Unauthorized error response-code and a JSON + exception response for failed authentication. + +It is intended to be used in environments where the "real" AT&T + Vendor Event Listener service is not available in order to test the + Reference VNF or, indeed, any other software which needs to send + events to a server. + +Using the Validating Collector +============================== + +The test collector can be run manually, either on a Linux platform + or a Windows PC. It is invoked with a number of command-line + arguments: + +``` + C:> python collector.py --config + --section
+ --verbose +``` + +Where: + + - **config** defines the path to the config file to be used. + + - **section** defines the section in the config file to be used. + + - **verbose** controls the level of logging to be generated. + +Wherever you chose to run the Test Collector, note that the + configuration of the backend service running on the VM generating + the events has to match so that the events generated by the backend + service are sent to the correct location and the Test Collector is + listening on the correct ports and URLs. The relevant section of the + Test Collector config file is: + +``` + #------------------------------------------------------------------------------ + # Details of the Vendor Event Listener REST service. + # + # REST resources are defined with respect to a ServerRoot: + # ServerRoot = https://{Domain}:{Port}/{optionalRoutingPath} + # + # REST resources are of the form: + # * {ServerRoot}/eventListener/v{apiVersion} + # * {ServerRoot}/eventListener/v{apiVersion}/{topicName} + # * {ServerRoot}/eventListener/v{apiVersion}/eventBatch + # * {ServerRoot}/eventListener/v{apiVersion}/clientThrottlingState + # + # The "vel\_topic\_name" parameter is used as the "topicName" element in the path + # and may be empty. + # + # Note that the path, if present, should have no leading "/" but should have a + # training "/". + #------------------------------------------------------------------------------ + vel_domain = 127.0.0.1 + vel_port = 30000 + vel_path = vendor_event_listener/ + vel_username = Alice + vel_password = This isn't very secure! + vel_topic_name = example_vnf +``` +The equivalent section of the backend service's configuration has to + match, or the equivalent parameters injected in the VM by the + OpenStack metadata service have to match. + +When events are sent from the web application, the results of the + validation will be displayed on stdout and be written to the log + file specified in the configuration file. + +For example: A Fault event failing to validate: + +``` + ; - - [29/Feb/2016 10:58:28] "POST + /vendor_event_listener/eventListener/v1/example_vnf HTTP/1.1" 204 0 + Event is not valid against schema! 'eventSeverity' is a required + property + Failed validating 'required' in + schema['properties']['event']['properties']['faultFields']: + {'description': 'fields specific to fault events', + 'properties': {'alarmAdditionalInformation': {'description':'additional alarm information', + 'items': {'$ref': '#/definitions/field'}, + 'type': 'array'}, + 'alarmCondition': {'description': 'alarm condition reportedby the device', + 'type': 'string'}, + 'alarmInterfaceA': {'description': 'card, port, channel or interface name of the device generating the alarm', + 'type': 'string'}, + 'eventSeverity': {'description': 'event severity or priority', + 'enum': ['CRITICAL', + 'MAJOR', + 'MINOR', + 'WARNING', + 'NORMAL'], + 'type': 'string'}, + 'eventSourceType': {'description': 'type of event source', + 'enum': ['other(0)', + 'router(1)', + 'switch(2)', + 'host(3)', + 'card(4)', + 'port(5)', + 'slotThreshold(6)', + 'portThreshold(7)', + 'virtualMachine(8)'], + 'type': 'string'}, + 'faultFieldsVersion': {'description': 'version of the faultFields block', + 'type': 'number'}, + 'specificProblem': {'description': 'short description of the alarm or problem', + 'type': 'string'}, + 'vfStatus': {'description': 'virtual function status enumeration', + 'enum': ['Active', + 'Idle', + 'Preparing to terminate', + 'Ready to terminate', + 'Requesting termination'], + 'type': 'string'}}, + 'required': ['alarmCondition', + 'eventSeverity', + 'eventSourceType', + 'specificProblem', + 'vfStatus'], + 'type': 'object'} + On instance['event']['faultFields']: + {'alarmAdditionalInformation': [{'name': 'extra information', + 'value': '2'}, + {'name': 'more information', + 'value': '1'}], + 'alarmCondition': 'alarm condition 1', + 'eventSourceType': 'virtualMachine(8)', + 'faultFieldsVersion': 1, + 'specificProblem': 'problem 1', + 'vfStatus': 'Active'} + Bad JSON body decoded: + { + "event": { + "commonEventHeader": { + "domain": "fault", + "eventId": "6", + "eventType": "event type 1", + "functionalRole": "unknown", + "lastEpochMicrosec": 1456743510381000.0, + "priority": "Normal", + "reportingEntityId": "Not in OpenStack", + "reportingEntityName": "Not in OpenStack Environment", + "sequence": 0, + "sourceId": "Not in OpenStack", + "sourceName": "Not in OpenStack Environment", + "startEpochMicrosec": 1456743510381000.0, + "version": 1 + }, + "faultFields": { + "alarmAdditionalInformation": [ + { + "name": "extra information", + "value": "2" + }, + { + "name": "more information", + "value": "1" + } + ], + "alarmCondition": "alarm condition 1", + "eventSourceType": "virtualMachine(8)", + "faultFieldsVersion": 1, + "specificProblem": "problem 1", + "vfStatus": "Active" + } + } + } +``` + +Test Control Interface +---------------------- + +The test collector will accept any valid commandList on the Test Control interface, +and will store it until the next event is received at the collector. +At this point, it will send it to the event sender, and discard the pending commandList. + +For example, a POST of the following JSON will result in a measurement interval change +command being sent to the sender of the next event. + +``` +{ + "commandList": [ + { + "command": { + "commandType": "measurementIntervalChange", + "measurementInterval": 60 + } + } + ] +} +``` + +A python script "test_control.py" provides an example of commandList injection, +and contains various functions to generate example command lists. + +The test control script can be run manually, either on a Linux platform or a Windows PC. +It is invoked with optional command-line arguments for the fqdn and port number of the +test collector to be controlled: +``` + C:> python test_control.py --fqdn 127.0.0.1 --port 30000 +``` diff --git a/veslibrary/ves_clibrary/evel/evel-test-collector/scripts/linux/go-collector.sh b/veslibrary/ves_clibrary/evel/evel-test-collector/scripts/linux/go-collector.sh new file mode 100644 index 0000000..31fd8af --- /dev/null +++ b/veslibrary/ves_clibrary/evel/evel-test-collector/scripts/linux/go-collector.sh @@ -0,0 +1,21 @@ +# Run the validating test collector. +# =================================================================== +# 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. + + +python ../../code/collector/collector.py \ + --config ../../config/collector.conf \ + --section windows \ + --verbose diff --git a/veslibrary/ves_clibrary/evel/evel-test-collector/scripts/windows/go-collector.bat b/veslibrary/ves_clibrary/evel/evel-test-collector/scripts/windows/go-collector.bat new file mode 100644 index 0000000..7241442 --- /dev/null +++ b/veslibrary/ves_clibrary/evel/evel-test-collector/scripts/windows/go-collector.bat @@ -0,0 +1,22 @@ +REM =================================================================== +REM Copyright © 2017 AT&T Intellectual Property. All rights reserved. +REM =================================================================== +REM Licensed under the Apache License, Version 2.0 (the "License"); +REM you may not use this file except in compliance with the License. +REM You may obtain a copy of the License at +REM +REM http://www.apache.org/licenses/LICENSE-2.0 +REM +REM Unless required by applicable law or agreed to in writing, software +REM distributed under the License is distributed on an "AS IS" BASIS, +REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +REM See the License for the specific language governing permissions and +REM limitations under the License. +@echo off + +REM Run the validating test collector. + +python ..\..\code\collector\collector.py ^ + --config ..\..\config\collector.conf ^ + --section windows ^ + --verbose -- cgit 1.2.3-korg