summaryrefslogtreecommitdiffstats
path: root/VES5.0/evel/evel-library
diff options
context:
space:
mode:
authorMarco Platania <platania@research.att.com>2017-05-18 15:02:10 +0000
committerGerrit Code Review <gerrit@onap.org>2017-05-18 15:02:10 +0000
commit0078971a8b764a79ec0a516c022576f7ffe2ed2a (patch)
tree55a140f432d9e8d8834da24ccd956dd792172c5a /VES5.0/evel/evel-library
parent2fa991c3273897940ef0d92e020daa298c68c73b (diff)
parent6c98a31b980d1d6cbbc9aeb2064d3f1c2252c3da (diff)
Merge "VES5.0 development changes not for test"
Diffstat (limited to 'VES5.0/evel/evel-library')
-rw-r--r--VES5.0/evel/evel-library/bldjobs/Doxyfile1475
-rw-r--r--VES5.0/evel/evel-library/bldjobs/Makefile384
-rw-r--r--VES5.0/evel/evel-library/code/evel_demo/evel_demo.c1611
-rw-r--r--VES5.0/evel/evel-library/code/evel_demo/evel_demo.h44
-rw-r--r--VES5.0/evel/evel-library/code/evel_demo/evel_test_control.c632
-rw-r--r--VES5.0/evel/evel-library/code/evel_demo/evel_test_control.cbak599
-rw-r--r--VES5.0/evel/evel-library/code/evel_demo/evel_test_control.h104
-rwxr-xr-xVES5.0/evel/evel-library/code/evel_library/a.outbin0 -> 13128 bytes
-rw-r--r--VES5.0/evel/evel-library/code/evel_library/double_list.c194
-rw-r--r--VES5.0/evel/evel-library/code/evel_library/double_list.h70
-rw-r--r--VES5.0/evel/evel-library/code/evel_library/evel.c402
-rw-r--r--VES5.0/evel/evel-library/code/evel_library/evel.h4204
-rw-r--r--VES5.0/evel/evel-library/code/evel_library/evel_event.c671
-rw-r--r--VES5.0/evel/evel-library/code/evel_library/evel_event_mgr.c1053
-rw-r--r--VES5.0/evel/evel-library/code/evel_library/evel_fault.c376
-rw-r--r--VES5.0/evel/evel-library/code/evel_library/evel_heartbeat_fields.c278
-rw-r--r--VES5.0/evel/evel-library/code/evel_library/evel_internal.h872
-rw-r--r--VES5.0/evel/evel-library/code/evel_library/evel_internal_event.c124
-rw-r--r--VES5.0/evel/evel-library/code/evel_library/evel_json_buffer.c883
-rw-r--r--VES5.0/evel/evel-library/code/evel_library/evel_jsonobject.c459
-rw-r--r--VES5.0/evel/evel-library/code/evel_library/evel_logging.c181
-rw-r--r--VES5.0/evel/evel-library/code/evel_library/evel_mobile_flow.c2132
-rw-r--r--VES5.0/evel/evel-library/code/evel_library/evel_option.c540
-rw-r--r--VES5.0/evel/evel-library/code/evel_library/evel_other.c503
-rw-r--r--VES5.0/evel/evel-library/code/evel_library/evel_reporting_measurement.c450
-rw-r--r--VES5.0/evel/evel-library/code/evel_library/evel_scaling_measurement.c3727
-rw-r--r--VES5.0/evel/evel-library/code/evel_library/evel_sipsignaling.c583
-rw-r--r--VES5.0/evel/evel-library/code/evel_library/evel_state_change.c294
-rw-r--r--VES5.0/evel/evel-library/code/evel_library/evel_strings.c481
-rw-r--r--VES5.0/evel/evel-library/code/evel_library/evel_syslog.c514
-rw-r--r--VES5.0/evel/evel-library/code/evel_library/evel_throttle.c2116
-rw-r--r--VES5.0/evel/evel-library/code/evel_library/evel_throttle.h228
-rw-r--r--VES5.0/evel/evel-library/code/evel_library/evel_voicequality.c661
-rw-r--r--VES5.0/evel/evel-library/code/evel_library/hashtable.c236
-rw-r--r--VES5.0/evel/evel-library/code/evel_library/hashtable.h58
-rw-r--r--VES5.0/evel/evel-library/code/evel_library/jsmn.c311
-rw-r--r--VES5.0/evel/evel-library/code/evel_library/jsmn.h76
-rw-r--r--VES5.0/evel/evel-library/code/evel_library/license.md95
-rw-r--r--VES5.0/evel/evel-library/code/evel_library/metadata.c607
-rw-r--r--VES5.0/evel/evel-library/code/evel_library/metadata.h72
-rw-r--r--VES5.0/evel/evel-library/code/evel_library/quickstart.md445
-rw-r--r--VES5.0/evel/evel-library/code/evel_library/readme.md236
-rw-r--r--VES5.0/evel/evel-library/code/evel_library/ring_buffer.c206
-rw-r--r--VES5.0/evel/evel-library/code/evel_library/ring_buffer.h109
-rw-r--r--VES5.0/evel/evel-library/code/evel_training/01-hello-world/Makefile13
-rw-r--r--VES5.0/evel/evel-library/code/evel_training/01-hello-world/hello_evel_world.c7
-rw-r--r--VES5.0/evel/evel-library/code/evel_training/02-library-link/Makefile22
-rw-r--r--VES5.0/evel/evel-library/code/evel_training/02-library-link/hello_evel_world.c7
-rw-r--r--VES5.0/evel/evel-library/code/evel_training/03-include-header/Makefile24
-rw-r--r--VES5.0/evel/evel-library/code/evel_training/03-include-header/hello_evel_world.c9
-rw-r--r--VES5.0/evel/evel-library/code/evel_training/04-basic-lifecycle/Makefile24
-rw-r--r--VES5.0/evel/evel-library/code/evel_training/04-basic-lifecycle/hello_evel_world.c69
-rw-r--r--VES5.0/evel/evel-library/code/evel_training/05-raise-event/Makefile24
-rw-r--r--VES5.0/evel/evel-library/code/evel_training/05-raise-event/hello_evel_world.c96
-rw-r--r--VES5.0/evel/evel-library/code/evel_training/06-username-password/Makefile31
-rw-r--r--VES5.0/evel/evel-library/code/evel_training/06-username-password/hello_evel_world.c98
-rw-r--r--VES5.0/evel/evel-library/code/evel_training/07-raise-measurement/Makefile31
-rw-r--r--VES5.0/evel/evel-library/code/evel_training/07-raise-measurement/hello_evel_world.c196
-rw-r--r--VES5.0/evel/evel-library/code/evel_training/08-raise-mobile-flow/Makefile31
-rw-r--r--VES5.0/evel/evel-library/code/evel_training/08-raise-mobile-flow/hello_evel_world.c201
-rw-r--r--VES5.0/evel/evel-library/code/evel_training/09-raise-state-change/Makefile31
-rw-r--r--VES5.0/evel/evel-library/code/evel_training/09-raise-state-change/hello_evel_world.c117
-rw-r--r--VES5.0/evel/evel-library/code/evel_training/10-raise-syslog/Makefile31
-rw-r--r--VES5.0/evel/evel-library/code/evel_training/10-raise-syslog/hello_evel_world.c117
-rw-r--r--VES5.0/evel/evel-library/code/evel_training/11-raise-other/Makefile31
-rw-r--r--VES5.0/evel/evel-library/code/evel_training/11-raise-other/hello_evel_world.c118
-rw-r--r--VES5.0/evel/evel-library/code/evel_training/12-suppress-fault-fields/Makefile35
-rw-r--r--VES5.0/evel/evel-library/code/evel_training/12-suppress-fault-fields/hello_evel_world.c180
-rw-r--r--VES5.0/evel/evel-library/code/evel_training/13-suppress-fault-pairs/Makefile35
-rw-r--r--VES5.0/evel/evel-library/code/evel_training/13-suppress-fault-pairs/hello_evel_world.c181
-rw-r--r--VES5.0/evel/evel-library/code/evel_training/14-measurement-interval/Makefile35
-rw-r--r--VES5.0/evel/evel-library/code/evel_training/14-measurement-interval/hello_evel_world.c293
-rw-r--r--VES5.0/evel/evel-library/code/evel_training/15-raise-signaling/Makefile31
-rw-r--r--VES5.0/evel/evel-library/code/evel_training/15-raise-signaling/hello_evel_world.c115
-rw-r--r--VES5.0/evel/evel-library/code/evel_training/16-raise-service/Makefile31
-rw-r--r--VES5.0/evel/evel-library/code/evel_training/16-raise-service/hello_evel_world.c119
-rw-r--r--VES5.0/evel/evel-library/code/evel_training/_gitignore1
-rw-r--r--VES5.0/evel/evel-library/code/evel_unit/evel_unit.c3498
-rw-r--r--VES5.0/evel/evel-library/docs/source/evel/README1
-rw-r--r--VES5.0/evel/evel-library/libs/x86_64/README1
-rwxr-xr-xVES5.0/evel/evel-library/libs/x86_64/libevel.abin0 -> 509752 bytes
-rw-r--r--VES5.0/evel/evel-library/output/x86_64/README1
-rw-r--r--VES5.0/evel/evel-library/readme.md28
83 files changed, 35209 insertions, 0 deletions
diff --git a/VES5.0/evel/evel-library/bldjobs/Doxyfile b/VES5.0/evel/evel-library/bldjobs/Doxyfile
new file mode 100644
index 00000000..f96ead25
--- /dev/null
+++ b/VES5.0/evel/evel-library/bldjobs/Doxyfile
@@ -0,0 +1,1475 @@
+# Doxyfile 1.6.1
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+# TAG = value [value, ...]
+# For lists items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the
+# iconv built into libc) for the transcoding. See
+# http://www.gnu.org/software/libiconv for the list of possible encodings.
+
+DOXYFILE_ENCODING = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
+# by quotes) that should identify the project.
+
+PROJECT_NAME = "AT&T ECOMP Vendor Event Listener library"
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER = 0.1
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY = ../docs/source/evel
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
+# 4096 sub-directories (in 2 levels) under the output directory of each output
+# format and will distribute the generated files over these directories.
+# Enabling this option can be useful when feeding doxygen a huge amount of
+# source files, where putting all generated files in the same directory would
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
+# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German,
+# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English
+# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian,
+# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak,
+# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese.
+
+OUTPUT_LANGUAGE = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is
+# used as the annotated text. Otherwise, the brief description is used as-is.
+# If left blank, the following values are used ("$name" is automatically
+# replaced with the name of the entity): "The $name class" "The $name widget"
+# "The $name file" "is" "provides" "specifies" "contains"
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the
+# path to strip.
+
+STRIP_FROM_PATH =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful is your file systems
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like regular Qt-style comments
+# (thus requiring an explicit @brief command for a brief description.)
+
+JAVADOC_AUTOBRIEF = YES
+
+# If the QT_AUTOBRIEF tag is set to YES then Doxygen will
+# interpret the first line (until the first dot) of a Qt-style
+# comment as the brief description. If set to NO, the comments
+# will behave just like regular Qt-style comments (thus requiring
+# an explicit \brief command for a brief description.)
+
+QT_AUTOBRIEF = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# re-implements.
+
+INHERIT_DOCS = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
+# a new page for each member. If set to NO, the documentation of a member will
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE = 2
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
+# sources only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
+# sources only. Doxygen will then generate output that is more tailored for
+# Java. For instance, namespaces will be presented as packages, qualified
+# scopes will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources only. Doxygen will then generate output that is more tailored for
+# Fortran.
+
+OPTIMIZE_FOR_FORTRAN = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for
+# VHDL.
+
+OPTIMIZE_OUTPUT_VHDL = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it parses.
+# With this tag you can assign which parser to use for a given extension.
+# Doxygen has a built-in mapping, but you can override or extend it using this tag.
+# The format is ext=language, where ext is a file extension, and language is one of
+# the parsers supported by doxygen: IDL, Java, Javascript, C#, C, C++, D, PHP,
+# Objective-C, Python, Fortran, VHDL, C, C++. For instance to make doxygen treat
+# .inc files as Fortran files (default is PHP), and .f files as C (default is Fortran),
+# use: inc=Fortran f=C. Note that for custom extensions you also need to set FILE_PATTERNS otherwise the files are not read by doxygen.
+
+EXTENSION_MAPPING =
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should
+# set this tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
+# func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+
+CPP_CLI_SUPPORT = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only.
+# Doxygen will parse them like normal C++ but will assume all classes use public
+# instead of private inheritance when no explicit protection keyword is present.
+
+SIP_SUPPORT = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate getter
+# and setter methods for a property. Setting this option to YES (the default)
+# will make doxygen to replace the get and set methods by a property in the
+# documentation. This will only work if the methods are indeed getting or
+# setting a simple type. If this is not the case, or you want to show the
+# methods anyway, you should set this option to NO.
+
+IDL_PROPERTY_SUPPORT = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING = YES
+
+# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum
+# is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically
+# be useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+
+TYPEDEF_HIDES_STRUCT = NO
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES = NO
+
+# This flag is only useful for Objective-C code. When set to YES local
+# methods, which are defined in the implementation section but not in
+# the interface are included in the documentation.
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base
+# name of the file that contains the anonymous namespace. By default
+# anonymous namespace are hidden.
+
+EXTRACT_ANON_NSPACES = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
+# declaration order.
+
+SORT_BRIEF_DOCS = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the (brief and detailed) documentation of class members so that constructors and destructors are listed first. If set to NO (the default) the constructors will appear in the respective orders defined by SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the
+# hierarchy of group names into alphabetical order. If set to NO (the default)
+# the group names will appear in their defined order.
+
+SORT_GROUP_NAMES = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or define consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and defines in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES = YES
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
+# This will remove the Files entry from the Quick Index and from the
+# Folder Tree View (if specified). The default is YES.
+
+SHOW_FILES = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the
+# Namespaces page.
+# This will remove the Namespaces entry from the Quick Index
+# and from the Folder Tree View (if specified). The default is YES.
+
+SHOW_NAMESPACES = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command <command> <input-file>, where <command> is the value of
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
+# provided by doxygen. Whatever the program writes to standard output
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed by
+# doxygen. The layout file controls the global structure of the generated output files
+# in an output format independent way. The create the layout file that represents
+# doxygen's defaults, run doxygen with the -l option. You can optionally specify a
+# file name after the option, if omitted DoxygenLayout.xml will be used as the name
+# of the layout file.
+
+LAYOUT_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET = YES
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR = YES
+
+# This WARN_NO_PARAMDOC option can be abled to get warnings for
+# functions that are documented, but have no documentation for their parameters
+# or return value. If set to NO (the default) doxygen will only warn about
+# wrong or incomplete parameter documentation, but not about the absence of
+# documentation.
+
+WARN_NO_PARAMDOC = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text. Optionally the format may contain
+# $version, which will be replaced by the version of the file (if it could
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT = ../code/evel_library \
+ ../code/evel_demo
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
+# also the default input encoding. Doxygen uses libiconv (or the iconv built
+# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for
+# the list of possible encodings.
+
+INPUT_ENCODING = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
+# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90
+
+FILE_PATTERNS = *.h *.c *.md
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE =
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
+# directories that are symbolic links (a Unix filesystem feature) are excluded
+# from the input.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories. Note that the wildcards are matched
+# against the file with absolute path, so to exclude all test directories
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+
+EXCLUDE_SYMBOLS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output.
+# If FILTER_PATTERNS is specified, this tag will be
+# ignored.
+
+INPUT_FILTER =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis.
+# Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match.
+# The filters are a list of the form:
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
+# is applied to all files.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER = YES
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = NO
+
+# If the REFERENCES_RELATION tag is set to YES
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION = NO
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
+# link to the source code.
+# Otherwise they will link to the documentation.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code
+# will point to the HTML generated by the htags(1) tool instead of doxygen
+# built-in source browser. The htags tool is part of GNU's global source
+# tagging system (see http://www.gnu.org/software/global/global.html). You
+# will need version 4.8.6 or higher.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX = NO
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header.
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER =
+
+# If the HTML_TIMESTAMP tag is set to YES then the generated HTML
+# documentation will contain the timesstamp.
+
+HTML_TIMESTAMP = NO
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet. Note that doxygen will try to copy
+# the style sheet file to the HTML output directory, so don't put your own
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET =
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded. For this to work a browser that supports
+# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox
+# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
+
+HTML_DYNAMIC_SECTIONS = NO
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files
+# will be generated that can be used as input for Apple's Xcode 3
+# integrated development environment, introduced with OSX 10.5 (Leopard).
+# To create a documentation set, doxygen will generate a Makefile in the
+# HTML output directory. Running make will produce the docset in that
+# directory and running "make install" will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find
+# it at startup.
+# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html for more information.
+
+GENERATE_DOCSET = NO
+
+# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the
+# feed. A documentation feed provides an umbrella under which multiple
+# documentation sets from a single provider (such as a company or product suite)
+# can be grouped.
+
+DOCSET_FEEDNAME = "Doxygen generated docs"
+
+# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that
+# should uniquely identify the documentation set bundle. This should be a
+# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen
+# will append .docset to the name.
+
+DOCSET_BUNDLE_ID = org.doxygen.Project
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output directory.
+
+CHM_FILE =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING
+# is used to encode HtmlHelp index (hhk), content (hhc) and project file
+# content.
+
+CHM_INDEX_ENCODING =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and QHP_VIRTUAL_FOLDER
+# are set, an additional index file will be generated that can be used as input for
+# Qt's qhelpgenerator to generate a Qt Compressed Help (.qch) of the generated
+# HTML documentation.
+
+GENERATE_QHP = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can
+# be used to specify the file name of the resulting .qch file.
+# The path specified is relative to the HTML output folder.
+
+QCH_FILE =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#namespace
+
+QHP_NAMESPACE =
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#virtual-folders
+
+QHP_VIRTUAL_FOLDER = doc
+
+# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to add.
+# For more information please see
+# http://doc.trolltech.com/qthelpproject.html#custom-filters
+
+QHP_CUST_FILTER_NAME =
+
+# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the custom filter to add.For more information please see
+# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters">Qt Help Project / Custom Filters</a>.
+
+QHP_CUST_FILTER_ATTRS =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this project's
+# filter section matches.
+# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes">Qt Help Project / Filter Attributes</a>.
+
+QHP_SECT_FILTER_ATTRS =
+
+# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can
+# be used to specify the location of Qt's qhelpgenerator.
+# If non-empty doxygen will try to run qhelpgenerator on the generated
+# .qhp file.
+
+QHG_LOCATION =
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
+# top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it.
+
+DISABLE_INDEX = NO
+
+# This tag can be used to set the number of enum values (range [1..20])
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE = 4
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information.
+# If the tag value is set to YES, a side panel will be generated
+# containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser).
+# Windows users are probably better off using the HTML help feature.
+
+GENERATE_TREEVIEW = NO
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH = 250
+
+# Use this tag to change the font size of Latex formulas included
+# as images in the HTML documentation. The default is 10. Note that
+# when you change the font size after a successful doxygen run you need
+# to manually remove any form_*.png images from the HTML output directory
+# to force them to be regenerated.
+
+FORMULA_FONTSIZE = 10
+
+# When the SEARCHENGINE tag is enable doxygen will generate a search box for the HTML output. The underlying search engine uses javascript
+# and DHTML and should work on any modern browser. Note that when using HTML help (GENERATE_HTMLHELP) or Qt help (GENERATE_QHP)
+# there is already a search function so this one should typically
+# be disabled.
+
+SEARCHENGINE = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX = YES
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, a4wide, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS = YES
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
+# in the output.
+
+LATEX_HIDE_INDICES = NO
+
+# If LATEX_SOURCE_CODE is set to YES then doxygen will include source code with syntax highlighting in the LaTeX output. Note that which sources are shown also depends on other settings such as SOURCE_BROWSER.
+
+LATEX_SOURCE_CODE = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT = xml
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader.
+# This is useful
+# if you want to understand what is going on.
+# On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_DEFINED tags.
+
+EXPAND_ONLY_PREDEF = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed. To prevent a macro definition from being
+# undefined via #undef or recursively expanded use the := operator
+# instead of the = operator.
+
+PREDEFINED =
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all function-like macros that are alone
+# on a line, have an all uppercase name, and do not end with a semicolon. Such
+# function macros are typically used for boiler-plate code, and will confuse
+# the parser if not removed.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles.
+# Optionally an initial location of the external documentation
+# can be added for each tagfile. The format of a tag file without
+# this location is as follows:
+#
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+#
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths or
+# URLs. If a location is present for each tag, the installdox tool
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
+# or super classes. Setting the tag to NO turns the diagrams off. Note that
+# this option is superseded by the HAVE_DOT option below. This is only a
+# fallback. It is recommended to install and use dot, since it yields more
+# powerful graphs.
+
+CLASS_DIAGRAMS = YES
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see
+# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH =
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT = YES
+
+# By default doxygen will write a font called FreeSans.ttf to the output
+# directory and reference it in all dot files that doxygen generates. This
+# font does not include all possible unicode characters however, so when you need
+# these (or just want a differently looking font) you can specify the font name
+# using DOT_FONTNAME. You need need to make sure dot is able to find the font,
+# which can be done by putting it in a standard location or by setting the
+# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory
+# containing the font.
+
+DOT_FONTNAME =
+
+# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs.
+# The default size is 10pt.
+
+DOT_FONTSIZE = 10
+
+# By default doxygen will tell dot to use the output directory to look for the
+# FreeSans.ttf font (which doxygen will put there itself). If you specify a
+# different font using DOT_FONTNAME you can set the path where dot
+# can find it using this tag.
+
+DOT_FONTPATH =
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH and HAVE_DOT options are set to YES then
+# doxygen will generate a call dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable call graphs
+# for selected functions only using the \callgraph command.
+
+CALL_GRAPH = NO
+
+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then
+# doxygen will generate a caller dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable caller
+# graphs for selected functions only using the \callergraph command.
+
+CALLER_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY = YES
+
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
+# then doxygen will show the dependencies a directory has on other directories
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
+# nodes that will be shown in the graph. If the number of nodes in a graph
+# becomes larger than this value, doxygen will truncate the graph, which is
+# visualized by representing a node as a red box. Note that doxygen if the
+# number of direct children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note
+# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+
+DOT_GRAPH_MAX_NODES = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
+# graphs generated by dot. A depth value of 3 means that only nodes reachable
+# from the root by following a path via at most 3 edges will be shown. Nodes
+# that lay further from the root node will be omitted. Note that setting this
+# option to 1 or 2 may greatly reduce the computation time needed for large
+# code bases. Also note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+
+MAX_DOT_GRAPH_DEPTH = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not
+# seem to support this out of the box. Warning: Depending on the platform used,
+# enabling this option may lead to badly anti-aliased labels on the edges of
+# a graph (i.e. they become hard to read).
+
+DOT_TRANSPARENT = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10)
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS = NO
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP = YES
diff --git a/VES5.0/evel/evel-library/bldjobs/Makefile b/VES5.0/evel/evel-library/bldjobs/Makefile
new file mode 100644
index 00000000..ea30acca
--- /dev/null
+++ b/VES5.0/evel/evel-library/bldjobs/Makefile
@@ -0,0 +1,384 @@
+#******************************************************************************
+# 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.
+#
+# License
+# -------
+#
+# Copyright(c) <2016>, AT&T Intellectual Property. All other rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# 1. Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+# must display the following acknowledgement: This product includes
+# software developed by the AT&T.
+# 4. Neither the name of AT&T nor the names of its contributors may be used to
+# endorse or promote products derived from this software without specific
+# prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
+# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
+# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#******************************************************************************
+
+ARCH=$(shell getconf LONG_BIT)
+CODE_ROOT=$(CURDIR)/..
+EVELLIB_ROOT=$(CODE_ROOT)/code/evel_library
+EVELDEMO_ROOT=$(CODE_ROOT)/code/evel_demo
+EVELUNIT_ROOT=$(CODE_ROOT)/code/evel_unit
+EVELTRAINING_ROOT=$(CODE_ROOT)/code/evel_training
+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 \
+ evel_library_demo \
+ evel_library_training
+
+clean: api_library_clean \
+ evel_unit_clean \
+ evel_library_demo_clean \
+ evel_library_training_clean \
+ docs_clean
+
+install: evel_install_centos evel_install_ubuntu
+
+test: evel_test_centos evel_test_ubuntu
+
+docs: docs_clean doxygen_docs
+
+
+#******************************************************************************
+# Build the EVEL libraries. *
+#******************************************************************************
+API_SOURCES=$(EVELLIB_ROOT)/evel.c \
+ $(EVELLIB_ROOT)/metadata.c \
+ $(EVELLIB_ROOT)/ring_buffer.c \
+ $(EVELLIB_ROOT)/double_list.c \
+ $(EVELLIB_ROOT)/hashtable.c \
+ $(EVELLIB_ROOT)/evel_event.c \
+ $(EVELLIB_ROOT)/evel_fault.c \
+ $(EVELLIB_ROOT)/evel_mobile_flow.c \
+ $(EVELLIB_ROOT)/evel_option.c \
+ $(EVELLIB_ROOT)/evel_jsonobject.c \
+ $(EVELLIB_ROOT)/evel_other.c \
+ $(EVELLIB_ROOT)/evel_json_buffer.c \
+ $(EVELLIB_ROOT)/evel_reporting_measurement.c \
+ $(EVELLIB_ROOT)/evel_heartbeat_fields.c \
+ $(EVELLIB_ROOT)/evel_sipsignaling.c \
+ $(EVELLIB_ROOT)/evel_scaling_measurement.c \
+ $(EVELLIB_ROOT)/evel_state_change.c \
+ $(EVELLIB_ROOT)/evel_strings.c \
+ $(EVELLIB_ROOT)/evel_syslog.c \
+ $(EVELLIB_ROOT)/evel_throttle.c \
+ $(EVELLIB_ROOT)/evel_internal_event.c \
+ $(EVELLIB_ROOT)/evel_event_mgr.c \
+ $(EVELLIB_ROOT)/evel_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 demo. *
+#******************************************************************************
+DEMO_SOURCES=$(EVELDEMO_ROOT)/evel_demo.c $(EVELDEMO_ROOT)/evel_test_control.c
+DEMO_OBJECTS=$(DEMO_SOURCES:.c=.o)
+-include $(DEMO_SOURCES:.c=.d)
+
+evel_library_demo: api_library \
+ $(OUTPUT_DIR)/evel_demo
+
+$(OUTPUT_DIR)/evel_demo: $(DEMO_OBJECTS)
+ @echo Linking EVEL demo
+ @$(CC) $(CPPFLAGS) $(CFLAGS) -o $@ \
+ -L $(LIBS_DIR) \
+ $(DEMO_OBJECTS) \
+ -level \
+ -lpthread \
+ -lcurl
+
+evel_library_demo_clean:
+ @echo Cleaning EVEL demo
+ @$(RM) $(OUTPUT_DIR)/evel_demo
+ @$(RM) $(API_OBJECTS)
+ @$(RM) $(DEMO_OBJECTS)
+ @$(RM) $(EVELLIB_ROOT)/*.d
+ @$(RM) $(EVELDEMO_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
+
+#******************************************************************************
+# Build the EVEL library training files. *
+#******************************************************************************
+evel_library_training:
+ @echo Making EVEL training
+ @$(MAKE) -s -C $(EVELTRAINING_ROOT)/01-hello-world
+ @$(MAKE) -s -C $(EVELTRAINING_ROOT)/02-library-link
+ @$(MAKE) -s -C $(EVELTRAINING_ROOT)/03-include-header
+ @$(MAKE) -s -C $(EVELTRAINING_ROOT)/04-basic-lifecycle
+ @$(MAKE) -s -C $(EVELTRAINING_ROOT)/05-raise-event
+ @$(MAKE) -s -C $(EVELTRAINING_ROOT)/06-username-password
+ @$(MAKE) -s -C $(EVELTRAINING_ROOT)/07-raise-measurement
+ @$(MAKE) -s -C $(EVELTRAINING_ROOT)/08-raise-mobile-flow
+ @$(MAKE) -s -C $(EVELTRAINING_ROOT)/09-raise-state-change
+ @$(MAKE) -s -C $(EVELTRAINING_ROOT)/10-raise-syslog
+ @$(MAKE) -s -C $(EVELTRAINING_ROOT)/11-raise-other
+ @$(MAKE) -s -C $(EVELTRAINING_ROOT)/12-suppress-fault-fields
+ @$(MAKE) -s -C $(EVELTRAINING_ROOT)/13-suppress-fault-pairs
+ @$(MAKE) -s -C $(EVELTRAINING_ROOT)/14-measurement-interval
+ @$(MAKE) -s -C $(EVELTRAINING_ROOT)/15-raise-signaling
+ @$(MAKE) -s -C $(EVELTRAINING_ROOT)/16-raise-service
+
+evel_library_training_clean:
+ @echo Cleaning EVEL training
+ @$(RM) $(EVELTRAINING_ROOT)/*/hello_evel_world
+
+#******************************************************************************
+# 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 \
+ evel_library_demo_clean \
+ evel_library_training_clean \
+ docs
+ @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
+
+#******************************************************************************
+# Create project documentation. *
+#******************************************************************************
+doxygen_docs:
+ @echo Making Doxygen documentation
+ @$(DOXYGEN) Doxyfile
+
+pdf_docs: doxygen_docs # This target is slightly broken. Run manually.
+ @echo Making PDF...
+ @$(MAKE) -C $(DOCS_ROOT)/source/evel/latex
+
+docs_clean:
+ @echo Cleaning docs...
+ @$(RM) $(DOCS_ROOT)/*.svg
+ @$(RM) -r $(DOCS_ROOT)/source/evel/html \
+ $(DOCS_ROOT)/source/evel/latex
+
+docs_install: docs
+ @echo Copying docs to team web-server...
+ @$(SCP) -r $(DOCS_ROOT)/source/evel/html/* \
+ root@$(TEAM_DOCS_SERVER):$(DOCS_SERVER_PATH)
diff --git a/VES5.0/evel/evel-library/code/evel_demo/evel_demo.c b/VES5.0/evel/evel-library/code/evel_demo/evel_demo.c
new file mode 100644
index 00000000..f5cbc03e
--- /dev/null
+++ b/VES5.0/evel/evel-library/code/evel_demo/evel_demo.c
@@ -0,0 +1,1611 @@
+/**************************************************************************//**
+ * @file
+ * Utility providing example use of the ECOMP Vendor Event Listener API.
+ *
+ * This software is intended to show the essential elements of the library's
+ * use.
+ *
+ * License
+ * -------
+ *
+ * Copyright(c) <2016>, AT&T Intellectual Property. All other rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement: This product includes software
+ * developed by the AT&T.
+ * 4. Neither the name of AT&T nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <sys/signal.h>
+#include <pthread.h>
+#include <mcheck.h>
+#include <sys/time.h>
+
+#include "jsmn.h"
+#include "evel.h"
+#include "evel_demo.h"
+#include "evel_test_control.h"
+
+/**************************************************************************//**
+ * Definition of long options to the program.
+ *
+ * See the documentation for getopt_long() for details of the structure's use.
+ *****************************************************************************/
+static const struct option long_options[] = {
+ {"help", no_argument, 0, 'h'},
+ {"fqdn", required_argument, 0, 'f'},
+ {"port", required_argument, 0, 'n'},
+ {"path", required_argument, 0, 'p'},
+ {"topic", required_argument, 0, 't'},
+ {"https", no_argument, 0, 's'},
+ {"verbose", no_argument, 0, 'v'},
+ {"cycles", required_argument, 0, 'c'},
+ {"username", required_argument, 0, 'u'},
+ {"password", required_argument, 0, 'w'},
+ {"nothrott", no_argument, 0, 'x'},
+ {0, 0, 0, 0}
+ };
+
+/**************************************************************************//**
+ * Definition of short options to the program.
+ *****************************************************************************/
+static const char* short_options = "hf:n:p:t:sc:u:w:vx";
+
+/**************************************************************************//**
+ * Basic user help text describing the usage of the application.
+ *****************************************************************************/
+static const char* usage_text =
+"evel_demo [--help]\n"
+" --fqdn <domain>\n"
+" --port <port_number>\n"
+" [--path <path>]\n"
+" [--topic <topic>]\n"
+" [--username <username>]\n"
+" [--password <password>]\n"
+" [--https]\n"
+" [--cycles <cycles>]\n"
+" [--nothrott]\n"
+"\n"
+"Demonstrate use of the ECOMP Vendor Event Listener API.\n"
+"\n"
+" -h Display this usage message.\n"
+" --help\n"
+"\n"
+" -f The FQDN or IP address to the RESTful API.\n"
+" --fqdn\n"
+"\n"
+" -n The port number the RESTful API.\n"
+" --port\n"
+"\n"
+" -p The optional path prefix to the RESTful API.\n"
+" --path\n"
+"\n"
+" -t The optional topic part of the RESTful API.\n"
+" --topic\n"
+"\n"
+" -u The optional username for basic authentication of requests.\n"
+" --username\n"
+"\n"
+" -w The optional password for basic authentication of requests.\n"
+" --password\n"
+"\n"
+" -s Use HTTPS rather than HTTP for the transport.\n"
+" --https\n"
+"\n"
+" -c Loop <cycles> times round the main loop. Default = 1.\n"
+" --cycles\n"
+"\n"
+" -v Generate much chattier logs.\n"
+" --verbose\n"
+"\n"
+" -x Exclude throttling commands from demonstration.\n"
+" --nothrott\n";
+
+#define DEFAULT_SLEEP_SECONDS 3
+#define MINIMUM_SLEEP_SECONDS 1
+
+unsigned long long epoch_start = 0;
+
+typedef enum {
+ SERVICE_CODEC,
+ SERVICE_TRANSCODING,
+ SERVICE_RTCP,
+ SERVICE_EOC_VQM,
+ SERVICE_MARKER
+} SERVICE_EVENT;
+
+/*****************************************************************************/
+/* Local prototypes. */
+/*****************************************************************************/
+static void demo_heartbeat(void);
+static void demo_fault(void);
+static void demo_measurement(const int interval);
+static void demo_mobile_flow(void);
+static void demo_heartbeat_field_event(void);
+static void demo_signaling(void);
+static void demo_state_change(void);
+static void demo_syslog(void);
+static void demo_other(void);
+static void demo_voicequality(void);
+
+/**************************************************************************//**
+ * Global flag to initiate shutdown.
+ *****************************************************************************/
+static int glob_exit_now = 0;
+
+static char * api_fqdn = NULL;
+static int api_port = 0;
+static int api_secure = 0;
+
+static void show_usage(FILE* fp)
+{
+ fputs(usage_text, fp);
+}
+
+/**************************************************************************//**
+ * Main function.
+ *
+ * Parses the command-line then ...
+ *
+ * @param[in] argc Argument count.
+ * @param[in] argv Argument vector - for usage see usage_text.
+ *****************************************************************************/
+int main(int argc, char ** argv)
+{
+ sigset_t sig_set;
+ pthread_t thread_id;
+ int option_index = 0;
+ int param = 0;
+ char * api_path = NULL;
+ char * api_topic = NULL;
+ char * api_username = "";
+ char * api_password = "";
+ int verbose_mode = 0;
+ int exclude_throttling = 0;
+ int cycles = 1;
+ int cycle;
+ int measurement_interval = EVEL_MEASUREMENT_INTERVAL_UKNOWN;
+
+ /***************************************************************************/
+ /* We're very interested in memory management problems so check behavior. */
+ /***************************************************************************/
+ mcheck(NULL);
+
+ if (argc < 2)
+ {
+ show_usage(stderr);
+ exit(-1);
+ }
+ param = getopt_long(argc, argv,
+ short_options,
+ long_options,
+ &option_index);
+ while (param != -1)
+ {
+ switch (param)
+ {
+ case 'h':
+ show_usage(stdout);
+ exit(0);
+ break;
+
+ case 'f':
+ api_fqdn = optarg;
+ break;
+
+ case 'n':
+ api_port = atoi(optarg);
+ break;
+
+ case 'p':
+ api_path = optarg;
+ break;
+
+ case 't':
+ api_topic = optarg;
+ break;
+
+ case 'u':
+ api_username = optarg;
+ break;
+
+ case 'w':
+ api_password = optarg;
+ break;
+
+ case 's':
+ api_secure = 1;
+ break;
+
+ case 'c':
+ cycles = atoi(optarg);
+ break;
+
+ case 'v':
+ verbose_mode = 1;
+ break;
+
+ case 'x':
+ exclude_throttling = 1;
+ break;
+
+ case '?':
+ /*********************************************************************/
+ /* Unrecognized parameter - getopt_long already printed an error */
+ /* message. */
+ /*********************************************************************/
+ break;
+
+ default:
+ fprintf(stderr, "Code error: recognized but missing option (%d)!\n",
+ param);
+ exit(-1);
+ }
+
+ /*************************************************************************/
+ /* Extract next parameter. */
+ /*************************************************************************/
+ param = getopt_long(argc, argv,
+ short_options,
+ long_options,
+ &option_index);
+ }
+
+ /***************************************************************************/
+ /* All the command-line has parsed cleanly, so now check that the options */
+ /* are meaningful. */
+ /***************************************************************************/
+ if (api_fqdn == NULL)
+ {
+ fprintf(stderr, "FQDN of the Vendor Event Listener API server must be "
+ "specified.\n");
+ exit(1);
+ }
+ if (api_port <= 0 || api_port > 65535)
+ {
+ fprintf(stderr, "Port for the Vendor Event Listener API server must be "
+ "specified between 1 and 65535.\n");
+ exit(1);
+ }
+ if (cycles <= 0)
+ {
+ fprintf(stderr, "Number of cycles around the main loop must be an"
+ "integer greater than zero.\n");
+ exit(1);
+ }
+
+ /***************************************************************************/
+ /* Set up default signal behaviour. Block all signals we trap explicitly */
+ /* on the signal_watcher thread. */
+ /***************************************************************************/
+ sigemptyset(&sig_set);
+ sigaddset(&sig_set, SIGALRM);
+ sigaddset(&sig_set, SIGINT);
+ pthread_sigmask(SIG_BLOCK, &sig_set, NULL);
+
+ /***************************************************************************/
+ /* Start the signal watcher thread. */
+ /***************************************************************************/
+ if (pthread_create(&thread_id, NULL, signal_watcher, &sig_set) != 0)
+ {
+ fprintf(stderr, "Failed to start signal watcher thread.");
+ exit(1);
+ }
+ pthread_detach(thread_id);
+
+ /***************************************************************************/
+ /* Version info */
+ /***************************************************************************/
+ printf("%s built %s %s\n", argv[0], __DATE__, __TIME__);
+
+ /***************************************************************************/
+ /* Initialize the EVEL interface. */
+ /***************************************************************************/
+ if (evel_initialize(api_fqdn,
+ api_port,
+ api_path,
+ api_topic,
+ api_secure,
+ api_username,
+ api_password,
+ EVEL_SOURCE_VIRTUAL_MACHINE,
+ "EVEL demo client",
+ verbose_mode))
+ {
+ fprintf(stderr, "Failed to initialize the EVEL library!!!");
+ exit(-1);
+ }
+ else
+ {
+ EVEL_INFO("Initialization completed");
+ }
+
+ /***************************************************************************/
+ /* Work out a start time for measurements, and sleep for initial period. */
+ /***************************************************************************/
+ struct timeval tv_start;
+ gettimeofday(&tv_start, NULL);
+ epoch_start = tv_start.tv_usec + 1000000 * tv_start.tv_sec;
+ sleep(DEFAULT_SLEEP_SECONDS);
+
+ /***************************************************************************/
+ /* MAIN LOOP */
+ /***************************************************************************/
+ printf("Starting %d loops...\n", cycles);
+ cycle = 0;
+ while (cycle++ < cycles)
+ {
+ EVEL_INFO("MAI: Starting main loop");
+ printf("\nStarting main loop %d\n", cycle);
+
+ /*************************************************************************/
+ /* A 20s-long repeating cycle of behaviour. */
+ /*************************************************************************/
+ if (exclude_throttling == 0)
+ {
+ switch (cycle % 20)
+ {
+ case 1:
+ printf(" 1 - Resetting throttle specification for all domains\n");
+ evel_test_control_scenario(TC_RESET_ALL_DOMAINS,
+ api_secure,
+ api_fqdn,
+ api_port);
+ break;
+
+ case 2:
+ printf(" 2 - Switching measurement interval to 2s\n");
+ evel_test_control_meas_interval(2,
+ api_secure,
+ api_fqdn,
+ api_port);
+ break;
+
+ case 3:
+ printf(" 3 - Suppressing fault domain\n");
+ evel_test_control_scenario(TC_FAULT_SUPPRESS_FIELDS_AND_PAIRS,
+ api_secure,
+ api_fqdn,
+ api_port);
+ break;
+
+ case 4:
+ printf(" 4 - Suppressing measurement domain\n");
+ evel_test_control_scenario(TC_MEAS_SUPPRESS_FIELDS_AND_PAIRS,
+ api_secure,
+ api_fqdn,
+ api_port);
+ break;
+
+ case 5:
+ printf(" 5 - Switching measurement interval to 5s\n");
+ evel_test_control_meas_interval(5,
+ api_secure,
+ api_fqdn,
+ api_port);
+ break;
+
+ case 6:
+ printf(" 6 - Suppressing mobile flow domain\n");
+ evel_test_control_scenario(TC_MOBILE_SUPPRESS_FIELDS_AND_PAIRS,
+ api_secure,
+ api_fqdn,
+ api_port);
+ break;
+
+ case 7:
+ printf(" 7 - Suppressing state change domain\n");
+ evel_test_control_scenario(TC_STATE_SUPPRESS_FIELDS_AND_PAIRS,
+ api_secure,
+ api_fqdn,
+ api_port);
+ break;
+
+ case 8:
+ printf(" 8 - Suppressing signaling domain\n");
+ evel_test_control_scenario(TC_SIGNALING_SUPPRESS_FIELDS,
+ api_secure,
+ api_fqdn,
+ api_port);
+ break;
+
+ case 9:
+ printf(" 9 - Suppressing service event domain\n");
+ evel_test_control_scenario(TC_SERVICE_SUPPRESS_FIELDS_AND_PAIRS,
+ api_secure,
+ api_fqdn,
+ api_port);
+ break;
+
+ case 10:
+ printf(" 10 - Switching measurement interval to 20s\n");
+ evel_test_control_meas_interval(20,
+ api_secure,
+ api_fqdn,
+ api_port);
+ break;
+
+ case 11:
+ printf(" 11 - Suppressing syslog domain\n");
+ evel_test_control_scenario(TC_SYSLOG_SUPPRESS_FIELDS_AND_PAIRS,
+ api_secure,
+ api_fqdn,
+ api_port);
+ break;
+
+ case 12:
+ printf(" 12 - Switching measurement interval to 10s\n");
+ evel_test_control_meas_interval(10,
+ api_secure,
+ api_fqdn,
+ api_port);
+ break;
+
+ case 15:
+ printf(" Requesting provide throttling spec\n");
+ evel_test_control_scenario(TC_PROVIDE_THROTTLING_SPEC,
+ api_secure,
+ api_fqdn,
+ api_port);
+ break;
+ }
+ }
+ fflush(stdout);
+
+ /*************************************************************************/
+ /* Send a bunch of events. */
+ /*************************************************************************/
+ demo_heartbeat();
+ demo_fault();
+ demo_measurement((measurement_interval ==
+ EVEL_MEASUREMENT_INTERVAL_UKNOWN) ?
+ DEFAULT_SLEEP_SECONDS : measurement_interval);
+ demo_mobile_flow();
+ demo_heartbeat_field_event();
+ demo_signaling();
+ demo_state_change();
+ demo_syslog();
+ demo_other();
+ demo_voicequality();
+
+ /*************************************************************************/
+ /* MAIN RETRY LOOP. Check and implement the measurement interval. */
+ /*************************************************************************/
+ if (cycle <= cycles)
+ {
+ int sleep_time;
+
+ /***********************************************************************/
+ /* We have a minimum loop time. */
+ /***********************************************************************/
+ sleep(MINIMUM_SLEEP_SECONDS);
+
+ /***********************************************************************/
+ /* Get the latest measurement interval and sleep for the remainder. */
+ /***********************************************************************/
+ measurement_interval = evel_get_measurement_interval();
+ printf("Measurement Interval = %d\n", measurement_interval);
+
+ if (measurement_interval == EVEL_MEASUREMENT_INTERVAL_UKNOWN)
+ {
+ sleep_time = DEFAULT_SLEEP_SECONDS - MINIMUM_SLEEP_SECONDS;
+ }
+ else
+ {
+ sleep_time = measurement_interval - MINIMUM_SLEEP_SECONDS;
+ }
+ sleep(sleep_time);
+ }
+ }
+
+ /***************************************************************************/
+ /* We are exiting, but allow the final set of events to be dispatched */
+ /* properly first. */
+ /***************************************************************************/
+ sleep(2);
+ printf("All done - exiting!\n");
+ return 0;
+}
+
+/**************************************************************************//**
+ * Signal watcher.
+ *
+ * Signal catcher for incoming signal processing. Work out which signal has
+ * been received and process it accordingly.
+ *
+ * param[in] void_sig_set The signal mask to listen for.
+ *****************************************************************************/
+void *signal_watcher(void *void_sig_set)
+{
+ sigset_t *sig_set = (sigset_t *)void_sig_set;
+ int sig = 0;
+ int old_type = 0;
+ siginfo_t sig_info;
+
+ /***************************************************************************/
+ /* Set this thread to be cancellable immediately. */
+ /***************************************************************************/
+ pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &old_type);
+
+ while (!glob_exit_now)
+ {
+ /*************************************************************************/
+ /* Wait for a signal to be received. */
+ /*************************************************************************/
+ sig = sigwaitinfo(sig_set, &sig_info);
+ switch (sig)
+ {
+ case SIGALRM:
+ /*********************************************************************/
+ /* Failed to do something in the given amount of time. Exit. */
+ /*********************************************************************/
+ EVEL_ERROR( "Timeout alarm");
+ fprintf(stderr,"Timeout alarm - quitting!\n");
+ exit(2);
+ break;
+
+ case SIGINT:
+ EVEL_INFO( "Interrupted - quitting");
+ printf("\n\nInterrupted - quitting!\n");
+ glob_exit_now = 1;
+ break;
+ }
+ }
+
+ evel_terminate();
+ exit(0);
+ return(NULL);
+}
+
+/**************************************************************************//**
+ * Create and send a heartbeat event.
+ *****************************************************************************/
+void demo_heartbeat(void)
+{
+ EVENT_HEADER * heartbeat = NULL;
+ EVEL_ERR_CODES evel_rc = EVEL_SUCCESS;
+
+ /***************************************************************************/
+ /* Heartbeat */
+ /***************************************************************************/
+ heartbeat = evel_new_heartbeat();
+ if (heartbeat != NULL)
+ {
+ evel_rc = evel_post_event(heartbeat);
+ if (evel_rc != EVEL_SUCCESS)
+ {
+ EVEL_ERROR("Post failed %d (%s)", evel_rc, evel_error_string());
+ }
+ }
+ else
+ {
+ EVEL_ERROR("New Heartbeat failed");
+ }
+ printf(" Processed Heartbeat\n");
+}
+
+/**************************************************************************//**
+ * tap live cpu stats
+ *****************************************************************************/
+void evel_get_cpu_stats(EVENT_MEASUREMENT * measurement)
+{
+ FILE *fp;
+ char path[1024];
+ double usage;
+ double idle;
+ double intrpt;
+ double nice;
+ double softirq;
+ double steal;
+ double sys;
+ double user;
+ double wait;
+ MEASUREMENT_CPU_USE *cpu_use;
+
+ /* Open the command for reading. */
+ //fp = popen("/bin/ls /etc/", "r");
+ fp = popen("/usr/bin/top -bn 2 -d 0.01 | grep '^%Cpu' | tail -n 1 ", "r");
+ if (fp == NULL) {
+ printf("Failed to run command\n" );
+ exit(1);
+ }
+
+ /* Read the output a line at a time - output it. */
+ while (fgets(path, sizeof(path)-1, fp) != NULL) {
+ printf("%s", path+10);
+ sscanf(path+10," %lf us, %lf sy, %lf ni, %lf id, %lf wa, %lf hi, %lf si, %lf st",
+ &user,&sys,&nice,&idle,&wait,&intrpt,&softirq,&steal);
+ }
+
+ /* close */
+ pclose(fp);
+
+ cpu_use = evel_measurement_new_cpu_use_add(measurement, "cpu1", usage);
+ evel_measurement_cpu_use_idle_set(cpu_use,idle);
+ evel_measurement_cpu_use_interrupt_set(cpu_use,intrpt);
+ evel_measurement_cpu_use_nice_set(cpu_use,nice);
+ evel_measurement_cpu_use_softirq_set(cpu_use,softirq);
+ evel_measurement_cpu_use_steal_set(cpu_use,steal);
+ evel_measurement_cpu_use_system_set(cpu_use,sys);
+ evel_measurement_cpu_use_usageuser_set(cpu_use,user);
+ evel_measurement_cpu_use_wait_set(cpu_use,wait);
+ //evel_measurement_cpu_use_add(measurement, "cpu2", usage,idle,intrpt,nice,softirq,steal,sys,user,wait);
+}
+
+/**************************************************************************//**
+ * tap live disk stats
+ *****************************************************************************/
+void evel_get_disk_stats(EVENT_MEASUREMENT * measurement)
+{
+ FILE *fp;
+ char path[1024];
+ double rrqm;
+ double wrqm;
+ double rs;
+ double ws;
+ double rkbs;
+ double wkbs;
+ double avgrqs;
+ double avgqqs;
+ double wait;
+ double rawait;
+ double wawait;
+ double svctm;
+ double util;
+ MEASUREMENT_DISK_USE * disk_use = NULL;
+
+ /* Open the command for reading. */
+ //fp = popen("/bin/ls /etc/", "r");
+ fp = popen("/usr/bin/iostat -xtd | grep '^sda' | tail -n 1 ", "r");
+ if (fp == NULL) {
+ printf("Failed to run command\n" );
+ exit(1);
+ }
+
+ /* Read the output a line at a time - output it. */
+ while (fgets(path, sizeof(path)-1, fp) != NULL) {
+ printf("%s", path+10);
+ sscanf(path+10,"%lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf",
+ &rrqm,&wrqm,&rs,&ws,&rkbs,&wkbs,&avgrqs,&avgqqs,&wait,&rawait,&wawait,&svctm,&util);
+ }
+
+ /* close */
+ pclose(fp);
+
+ disk_use = evel_measurement_new_disk_use_add(measurement, "sda");
+ evel_measurement_disk_use_iotimeavg_set(disk_use, rrqm);
+ evel_measurement_disk_use_iotimelast_set(disk_use, wrqm);
+ evel_measurement_disk_use_iotimemax_set(disk_use, rs);
+ evel_measurement_disk_use_iotimemin_set(disk_use, ws);
+ evel_measurement_disk_use_mergereadavg_set(disk_use, rkbs);
+ evel_measurement_disk_use_mergereadlast_set(disk_use, wkbs);
+ evel_measurement_disk_use_mergereadmax_set(disk_use, avgrqs);
+ evel_measurement_disk_use_mergereadmin_set(disk_use, avgqqs);
+ evel_measurement_disk_use_mergewritelast_set(disk_use, wait);
+ evel_measurement_disk_use_mergewritemax_set(disk_use, rawait);
+ evel_measurement_disk_use_mergewritemin_set(disk_use, wawait);
+ evel_measurement_disk_use_octetsreadavg_set(disk_use, svctm);
+ evel_measurement_disk_use_octetsreadlast_set(disk_use, util);
+}
+
+
+/**************************************************************************//**
+ * tap live memory stats
+ *****************************************************************************/
+void evel_get_mem_stats(EVENT_MEASUREMENT * measurement)
+{
+char buffer[4096];
+char line[100];
+char c;
+int bcount=0,lcount=0;
+
+double membuffsz=0.0;
+double memcache=0.0;
+double memconfig=0.0;
+double memfree=0.0;
+double slab=0.0;
+double slabrecl=0.0;
+double slabunrecl=0.0;
+double memused=0.0;
+MEASUREMENT_MEM_USE *mem_use = NULL;
+
+
+FILE * filp = fopen("/proc/meminfo", "rb");
+int bytes_read = fread(buffer, sizeof(char), 4096, filp);
+fclose(filp);
+
+printf("meminfo %d\n",bytes_read);
+
+while ( bcount < bytes_read )
+{
+ for(lcount=0; buffer[bcount] != '\n';bcount++,lcount++)
+ {
+ line[lcount] = buffer[bcount];
+ }
+ if( lcount > 0 )
+ {
+ line[lcount] = '\0';
+ //printf("%s\n",line);
+ if(!strncmp(line,"Buffers:", strlen("Buffers:")))
+ {
+ sscanf(line+strlen("Buffers:"),"%lf",&membuffsz);
+ //printf("membuff %lf\n",membuffsz);
+ }
+ else if(!strncmp(line,"Cached:", strlen("Cached:")))
+ {
+ sscanf(line+strlen("Cached:"),"%lf",&memcache);
+ }
+ else if(!strncmp(line,"MemTotal:", strlen("MemTotal:")))
+ {
+ sscanf(line+strlen("MemTotal:"),"%lf",&memconfig);
+ }
+ else if(!strncmp(line,"MemFree:", strlen("MemFree:")))
+ {
+ sscanf(line+strlen("MemFree:"),"%lf",&memfree);
+ }
+ else if(!strncmp(line,"Slab:", strlen("Slab:")))
+ {
+ sscanf(line+strlen("Slab:"),"%lf",&slab);
+ }
+ else if(!strncmp(line,"SReclaimable:", strlen("SReclaimable:")))
+ {
+ sscanf(line+strlen("SReclaimable:"),"%lf",&slabrecl);
+ }
+ else if(!strncmp(line,"SUnreclaim:", strlen("SUnreclaim:")))
+ {
+ sscanf(line+strlen("SUnreclaim:"),"%lf",&slabunrecl);
+ }
+ }
+ bcount++;
+}
+
+memused = memconfig - memfree - membuffsz - memcache - slab;
+printf("memused %lf\n",memused);
+
+ mem_use = evel_measurement_new_mem_use_add(measurement, "RAM", "vm1", membuffsz);
+ evel_measurement_mem_use_memcache_set(mem_use,memcache);
+ evel_measurement_mem_use_memconfig_set(mem_use,memconfig);
+ evel_measurement_mem_use_memfree_set(mem_use,memfree);
+ evel_measurement_mem_use_slab_reclaimed_set(mem_use,slabrecl);
+ evel_measurement_mem_use_slab_unreclaimable_set(mem_use,slabunrecl);
+ evel_measurement_mem_use_usedup_set(mem_use,memused);
+
+}
+
+/**************************************************************************//**
+ * Create and send three fault events.
+ *****************************************************************************/
+void demo_fault(void)
+{
+ EVENT_FAULT * fault = NULL;
+ EVEL_ERR_CODES evel_rc = EVEL_SUCCESS;
+
+ /***************************************************************************/
+ /* Fault */
+ /***************************************************************************/
+ fault = evel_new_fault("An alarm condition",
+ "Things are broken",
+ EVEL_PRIORITY_NORMAL,
+ EVEL_SEVERITY_MAJOR,
+ EVEL_SOURCE_VIRTUAL_MACHINE,
+ EVEL_VF_STATUS_READY_TERMINATE);
+ if (fault != NULL)
+ {
+ evel_rc = evel_post_event((EVENT_HEADER *)fault);
+ if (evel_rc != EVEL_SUCCESS)
+ {
+ EVEL_ERROR("Post failed %d (%s)", evel_rc, evel_error_string());
+ }
+ }
+ else
+ {
+ EVEL_ERROR("New Fault failed");
+ }
+ printf(" Processed empty Fault\n");
+
+ fault = evel_new_fault("Another alarm condition",
+ "It broke badly",
+ EVEL_PRIORITY_NORMAL,
+ EVEL_SEVERITY_MAJOR,
+ EVEL_SOURCE_PORT,
+ EVEL_VF_STATUS_REQ_TERMINATE);
+ if (fault != NULL)
+ {
+ evel_fault_type_set(fault, "Bad things happening");
+ evel_fault_category_set(fault, "Failed category");
+ evel_fault_interface_set(fault, "An Interface Card");
+ evel_rc = evel_post_event((EVENT_HEADER *)fault);
+ if (evel_rc != EVEL_SUCCESS)
+ {
+ EVEL_ERROR("Post failed %d (%s)", evel_rc, evel_error_string());
+ }
+ }
+ else
+ {
+ EVEL_ERROR("New Fault failed");
+ }
+ printf(" Processed partial Fault\n");
+
+ 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);
+ 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());
+ }
+ }
+ else
+ {
+ EVEL_ERROR("New Fault failed");
+ }
+ printf(" Processed full Fault\n");
+}
+
+/**************************************************************************//**
+ * Create and send a measurement event.
+ *****************************************************************************/
+void demo_measurement(const int interval)
+{
+ EVENT_MEASUREMENT * measurement = NULL;
+ MEASUREMENT_LATENCY_BUCKET * bucket = NULL;
+ MEASUREMENT_VNIC_PERFORMANCE * vnic_performance = NULL;
+ EVEL_ERR_CODES evel_rc = EVEL_SUCCESS;
+
+ /***************************************************************************/
+ /* Measurement */
+ /***************************************************************************/
+ measurement = evel_new_measurement(interval);
+ if (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, 6);
+ //evel_measurement_cpu_use_add(measurement, "cpu1", 11.11);
+ //evel_measurement_cpu_use_add(measurement, "cpu2", 22.22);
+ evel_measurement_addl_info_add(measurement, "name1", "value1");
+ evel_measurement_addl_info_add(measurement, "name2", "value2");
+ evel_get_cpu_stats(measurement);
+ evel_get_disk_stats(measurement);
+ 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);
+
+ bucket = evel_new_meas_latency_bucket(20);
+ evel_meas_latency_bucket_low_end_set(bucket, 0.0);
+ evel_meas_latency_bucket_high_end_set(bucket, 10.0);
+ 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_performance = evel_measurement_new_vnic_performance("eth0", "true");
+
+ evel_vnic_performance_rx_bcast_pkt_acc_set(vnic_performance, 1000000.023);
+ evel_vnic_performance_rx_bcast_pkt_delta_set(vnic_performance,1234.767346);
+ evel_vnic_performance_rx_discard_pkt_acc_set(vnic_performance, 127146784.234738587);
+ evel_vnic_performance_rx_discard_pkt_delta_set(vnic_performance, 123445);
+ evel_vnic_performance_rx_error_pkt_acc_set(vnic_performance, 2736448376);
+ evel_vnic_performance_rx_error_pkt_delta_set(vnic_performance, 3474438764);
+ evel_vnic_performance_rx_mcast_pkt_acc_set(vnic_performance, 42464676);
+ evel_vnic_performance_rx_mcast_pkt_delta_set(vnic_performance, 42678657654);
+ evel_vnic_performance_rx_octets_acc_set(vnic_performance, 47658745);
+ evel_vnic_performance_rx_octets_delta_set(vnic_performance, 47656465465);
+ evel_vnic_performance_rx_total_pkt_acc_set(vnic_performance, 4765764654444);
+ evel_vnic_performance_rx_total_pkt_delta_set(vnic_performance, 4545665656);
+ evel_vnic_performance_rx_ucast_pkt_acc_set(vnic_performance, 4765745546.);
+ evel_vnic_performance_rx_ucast_pkt_delta_set(vnic_performance, 4768765.78347856);
+ evel_vnic_performance_tx_bcast_pkt_acc_set(vnic_performance, 747665.347647);
+ evel_vnic_performance_tx_bcast_pkt_delta_set(vnic_performance, 3468765.4774);
+ evel_vnic_performance_tx_discarded_pkt_acc_set(vnic_performance, 53625345.53);
+ evel_vnic_performance_tx_discarded_pkt_delta_set(vnic_performance, 5465345.72455);
+ evel_vnic_performance_tx_error_pkt_acc_set(vnic_performance, 7632754.754);
+ evel_vnic_performance_tx_error_pkt_delta_set(vnic_performance, 34646875444.);
+ evel_vnic_performance_tx_mcast_pkt_acc_set(vnic_performance, 2734875.5534);
+ evel_vnic_performance_tx_mcast_pkt_delta_set(vnic_performance, 562346534.654);
+ evel_vnic_performance_tx_octets_acc_set(vnic_performance, 2785845.76874);
+ evel_vnic_performance_tx_octets_delta_set(vnic_performance, 76532645.75);
+ evel_vnic_performance_tx_total_pkt_acc_set(vnic_performance, 652365.5435);
+ evel_vnic_performance_tx_total_pkt_delta_set(vnic_performance, 754354.456);
+ evel_vnic_performance_tx_ucast_pkt_acc_set(vnic_performance, 738254835);
+ evel_vnic_performance_tx_ucast_pkt_delta_set(vnic_performance, 763274);
+ evel_meas_vnic_performance_add(measurement, vnic_performance);
+
+ vnic_performance = evel_measurement_new_vnic_performance("eth1", "false");
+ evel_vnic_performance_rx_mcast_pkt_delta_set(vnic_performance, 42678657654);
+ evel_vnic_performance_rx_octets_acc_set(vnic_performance, 47658745);
+ evel_vnic_performance_rx_octets_delta_set(vnic_performance, 47656465465);
+ evel_vnic_performance_rx_total_pkt_acc_set(vnic_performance, 4765764654444);
+ evel_vnic_performance_rx_total_pkt_delta_set(vnic_performance, 4545665656);
+ evel_vnic_performance_rx_ucast_pkt_acc_set(vnic_performance, 4765745546.);
+ evel_vnic_performance_rx_ucast_pkt_delta_set(vnic_performance, 4768765.78347856);
+ evel_vnic_performance_tx_bcast_pkt_acc_set(vnic_performance, 747665.347647);
+ evel_vnic_performance_tx_bcast_pkt_delta_set(vnic_performance, 3468765.4774);
+ evel_vnic_performance_tx_discarded_pkt_acc_set(vnic_performance, 53625345.53);
+ evel_meas_vnic_performance_add(measurement, vnic_performance);
+
+ 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_get_mem_stats(measurement);
+ 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");
+
+ /*************************************************************************/
+ /* Work out the time, to use as end of measurement period. */
+ /*************************************************************************/
+ struct timeval tv_now;
+ gettimeofday(&tv_now, NULL);
+ unsigned long long epoch_now = tv_now.tv_usec + 1000000 * tv_now.tv_sec;
+ evel_start_epoch_set(&measurement->header, epoch_start);
+ evel_last_epoch_set(&measurement->header, epoch_now);
+ epoch_start = epoch_now;
+ evel_reporting_entity_name_set(&measurement->header, "measurer");
+ evel_reporting_entity_id_set(&measurement->header, "measurer_id");
+
+ evel_rc = evel_post_event((EVENT_HEADER *)measurement);
+ if (evel_rc != EVEL_SUCCESS)
+ {
+ EVEL_ERROR("Post Measurement failed %d (%s)",
+ evel_rc,
+ evel_error_string());
+ }
+ }
+ else
+ {
+ EVEL_ERROR("New Measurement failed");
+ }
+ printf(" Processed Measurement\n");
+}
+
+/**************************************************************************//**
+ * Create and send three mobile flow events.
+ *****************************************************************************/
+void demo_mobile_flow(void)
+{
+ MOBILE_GTP_PER_FLOW_METRICS * metrics = NULL;
+ EVENT_MOBILE_FLOW * mobile_flow = NULL;
+ EVEL_ERR_CODES evel_rc = EVEL_SUCCESS;
+
+ /***************************************************************************/
+ /* Mobile Flow */
+ /***************************************************************************/
+ 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);
+ if (metrics != NULL)
+ {
+ mobile_flow = evel_new_mobile_flow("Outbound",
+ metrics,
+ "TCP",
+ "IPv4",
+ "2.3.4.1",
+ 2341,
+ "4.2.3.1",
+ 4321);
+ if (mobile_flow != NULL)
+ {
+ evel_rc = evel_post_event((EVENT_HEADER *)mobile_flow);
+ if (evel_rc != EVEL_SUCCESS)
+ {
+ EVEL_ERROR("Post Mobile Flow failed %d (%s)",
+ evel_rc,
+ evel_error_string());
+ }
+ }
+ else
+ {
+ EVEL_ERROR("New Mobile Flow failed");
+ }
+ printf(" Processed empty Mobile Flow\n");
+ }
+ else
+ {
+ EVEL_ERROR("New GTP Per Flow Metrics failed - skipping Mobile Flow");
+ printf(" Skipped empty Mobile Flow\n");
+ }
+
+ 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);
+ if (metrics != NULL)
+ {
+ mobile_flow = evel_new_mobile_flow("Inbound",
+ metrics,
+ "UDP",
+ "IPv6",
+ "2.3.4.2",
+ 2342,
+ "4.2.3.2",
+ 4322);
+ if (mobile_flow != NULL)
+ {
+ 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");
+
+ evel_rc = evel_post_event((EVENT_HEADER *)mobile_flow);
+ if (evel_rc != EVEL_SUCCESS)
+ {
+ EVEL_ERROR("Post Mobile Flow failed %d (%s)",
+ evel_rc,
+ evel_error_string());
+ }
+ }
+ else
+ {
+ EVEL_ERROR("New Mobile Flow failed");
+ }
+ printf(" Processed partial Mobile Flow\n");
+ }
+ else
+ {
+ EVEL_ERROR("New GTP Per Flow Metrics failed - skipping Mobile Flow");
+ printf(" Skipped partial Mobile Flow\n");
+ }
+
+ metrics = evel_new_mobile_gtp_flow_metrics(12.32,
+ 3.122,
+ 1002,
+ 21002,
+ 5002,
+ 1470409423,
+ 9872,
+ 1470409433,
+ 112,
+ (time_t)1470409433,
+ "Failed",
+ 872,
+ 32,
+ 172,
+ 1236542,
+ 45612,
+ 2,
+ 122,
+ 102,
+ 12,
+ 32,
+ 72,
+ 8992,
+ 9012,
+ 3022,
+ 62,
+ 22,
+ 2,
+ 1102,
+ 2252);
+ if (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("Outbound",
+ metrics,
+ "RTP",
+ "IPv8",
+ "2.3.4.3",
+ 2343,
+ "4.2.3.3",
+ 4323);
+ if (mobile_flow != NULL)
+ {
+ evel_mobile_flow_addl_field_add(mobile_flow, "name1", "value1");
+ evel_mobile_flow_addl_field_add(mobile_flow, "name2", "value2");
+ evel_mobile_flow_addl_field_add(mobile_flow, "name3", "value3");
+
+ evel_mobile_flow_app_type_set(mobile_flow, "Demo application 2");
+ evel_mobile_flow_app_prot_type_set(mobile_flow, "GSM");
+ evel_mobile_flow_app_prot_ver_set(mobile_flow, "2");
+ evel_mobile_flow_cid_set(mobile_flow, "1");
+ evel_mobile_flow_con_type_set(mobile_flow, "S1-U");
+ evel_mobile_flow_ecgi_set(mobile_flow, "e1");
+ 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.google.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, "MMF");
+ evel_mobile_flow_rac_set(mobile_flow, "514");
+ evel_mobile_flow_radio_acc_tech_set(mobile_flow, "3G");
+ evel_mobile_flow_sac_set(mobile_flow, "1");
+ evel_mobile_flow_samp_alg_set(mobile_flow, 2);
+ evel_mobile_flow_tac_set(mobile_flow, "2099");
+ evel_mobile_flow_tunnel_id_set(mobile_flow, "Tunnel 2");
+ evel_mobile_flow_vlan_id_set(mobile_flow, "4096");
+
+ evel_rc = evel_post_event((EVENT_HEADER *)mobile_flow);
+ if (evel_rc != EVEL_SUCCESS)
+ {
+ EVEL_ERROR("Post Mobile Flow failed %d (%s)",
+ evel_rc,
+ evel_error_string());
+ }
+ }
+ else
+ {
+ EVEL_ERROR("New Mobile Flow failed");
+ }
+ printf(" Processed full Mobile Flow\n");
+ }
+ else
+ {
+ EVEL_ERROR("New GTP Per Flow Metrics failed - skipping Mobile Flow");
+ printf(" Skipped full Mobile Flow\n");
+ }
+}
+
+/**************************************************************************//**
+ * Create and send a Heartbeat field event.
+ *****************************************************************************/
+void demo_heartbeat_field_event(void)
+{
+ EVENT_HEARTBEAT_FIELD * event = NULL;
+ EVEL_ERR_CODES evel_rc = EVEL_SUCCESS;
+
+ event = evel_new_heartbeat_field(3);
+ if (event != NULL)
+ {
+ evel_hrtbt_interval_set(event, 10);
+ evel_hrtbt_field_addl_field_add(event, "Name1", "Value1");
+ evel_hrtbt_field_addl_field_add(event, "Name2", "Value2");
+
+ evel_rc = evel_post_event((EVENT_HEADER *) event);
+ if (evel_rc != EVEL_SUCCESS)
+ {
+ EVEL_ERROR("Post failed %d (%s)", evel_rc, evel_error_string());
+ }
+ }
+ else
+ {
+ EVEL_ERROR("New heartbeat field failed");
+ }
+ printf(" Processed heartbeat Events\n");
+}
+
+/**************************************************************************//**
+ * Create and send a Signaling event.
+ *****************************************************************************/
+void demo_signaling(void)
+{
+ EVENT_SIGNALING * event = NULL;
+ EVEL_ERR_CODES evel_rc = EVEL_SUCCESS;
+
+ event = evel_new_signaling("vendor_x", "correlator", "1.0.3.1", "1234", "192.168.1.3","3456");
+ if (event != NULL)
+ {
+ evel_signaling_addl_info_add(event, "name1", "value1");
+ evel_signaling_addl_info_add(event, "name2", "value2");
+ evel_signaling_type_set(event, "Signaling");
+ 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");
+ evel_signaling_vnfmodule_name_set(event, "vendor_x_module");
+ evel_signaling_vnfname_set(event, "vendor_x_vnf");
+ evel_rc = evel_post_event((EVENT_HEADER *) event);
+ if (evel_rc != EVEL_SUCCESS)
+ {
+ EVEL_ERROR("Post failed %d (%s)", evel_rc, evel_error_string());
+ }
+ }
+ else
+ {
+ EVEL_ERROR("New Signaling failed");
+ }
+ printf(" Processed Signaling\n");
+}
+
+/**************************************************************************//**
+ * Create and send a state change event.
+ *****************************************************************************/
+void demo_state_change(void)
+{
+ EVENT_STATE_CHANGE * state_change = NULL;
+ EVEL_ERR_CODES evel_rc = EVEL_SUCCESS;
+
+ /***************************************************************************/
+ /* State Change */
+ /***************************************************************************/
+ state_change = evel_new_state_change(EVEL_ENTITY_STATE_IN_SERVICE,
+ EVEL_ENTITY_STATE_OUT_OF_SERVICE,
+ "Interface");
+ if (state_change != NULL)
+ {
+ evel_state_change_type_set(state_change, "State Change");
+ evel_state_change_addl_field_add(state_change, "Name1", "Value1");
+ evel_state_change_addl_field_add(state_change, "Name2", "Value2");
+ evel_rc = evel_post_event((EVENT_HEADER *)state_change);
+ if (evel_rc != EVEL_SUCCESS)
+ {
+ EVEL_ERROR("Post failed %d (%s)", evel_rc, evel_error_string());
+ }
+ }
+ else
+ {
+ EVEL_ERROR("New State Change failed");
+ }
+ printf(" Processed State Change\n");
+}
+
+/**************************************************************************//**
+ * Create and send two syslog events.
+ *****************************************************************************/
+void demo_syslog(void)
+{
+ EVENT_SYSLOG * syslog = NULL;
+ EVEL_ERR_CODES evel_rc = EVEL_SUCCESS;
+
+ /***************************************************************************/
+ /* Syslog */
+ /***************************************************************************/
+ syslog = evel_new_syslog(EVEL_SOURCE_VIRTUAL_NETWORK_FUNCTION,
+ "EVEL library message",
+ "EVEL");
+ if (syslog != NULL)
+ {
+ evel_rc = evel_post_event((EVENT_HEADER *)syslog);
+ if (evel_rc != EVEL_SUCCESS)
+ {
+ EVEL_ERROR("Post failed %d (%s)", evel_rc, evel_error_string());
+ }
+ }
+ else
+ {
+ EVEL_ERROR("New Syslog failed");
+ }
+ printf(" Processed empty Syslog\n");
+
+ syslog = evel_new_syslog(EVEL_SOURCE_VIRTUAL_MACHINE,
+ "EVEL library message",
+ "EVEL");
+ if (syslog != NULL)
+ {
+ evel_syslog_event_source_host_set(syslog, "Virtual host");
+ evel_syslog_facility_set(syslog, EVEL_SYSLOG_FACILITY_LOCAL0);
+ evel_syslog_proc_set(syslog, "vnf_process");
+ evel_syslog_proc_id_set(syslog, 1423);
+ evel_syslog_version_set(syslog, 1);
+ evel_syslog_addl_filter_set(syslog, "Name1=Value1|Name2=Value2|Name3=Value3");
+ evel_syslog_sdid_set(syslog, "u354@876876");
+ evel_syslog_severity_set(syslog, "Error");
+ evel_rc = evel_post_event((EVENT_HEADER *)syslog);
+ if (evel_rc != EVEL_SUCCESS)
+ {
+ EVEL_ERROR("Post failed %d (%s)", evel_rc, evel_error_string());
+ }
+ }
+ else
+ {
+ EVEL_ERROR("New Syslog failed");
+ }
+ printf(" Processed full Syslog\n");
+}
+
+
+/**************************************************************************//**
+ * Create and send VoiceQuality events.
+ *****************************************************************************/
+void demo_voicequality(void)
+{
+ EVENT_VOICE_QUALITY * vq = NULL;
+ EVEL_ERR_CODES evel_rc = EVEL_SUCCESS;
+
+ /***************************************************************************/
+ /* Voice Quality */
+ /***************************************************************************/
+ vq = evel_new_voice_quality("calleeCodec", "callerCodec",
+ "correlator", "midrtcp",
+ "EVEL");
+ if (vq != NULL)
+ {
+ evel_rc = evel_post_event((EVENT_HEADER *)vq);
+ if (evel_rc != EVEL_SUCCESS)
+ {
+ EVEL_ERROR("Post failed %d (%s)", evel_rc, evel_error_string());
+ }
+ }
+ else
+ {
+ EVEL_ERROR("New Syslog failed");
+ }
+ printf(" Processed empty Syslog\n");
+
+ vq = evel_new_voice_quality("calleeCodec", "callerCodec",
+ "correlator", "midrtcp",
+ "EVEL");
+ if (vq != NULL)
+ {
+ evel_voice_quality_end_metrics_add(vq, "adjacent", EVEL_SERVICE_ENDPOINT_CALLER,
+ 0,1,2,3,4,5,6,7,8,9,10,11,12,13,4,15,16,17,18);
+ evel_voice_quality_end_metrics_add(vq, "adjacent", EVEL_SERVICE_ENDPOINT_CALLEE,
+ 0,1,2,3,4,5,6,7,8,9,10,11,12,13,4,15,16,17,18);
+
+ evel_voice_quality_vnfmodule_name_set(vq, "vnfmodule");
+ evel_voice_quality_vnfname_set(vq, "vFW");
+ evel_voice_quality_phone_number_set(vq, "123456789");
+
+
+ evel_rc = evel_post_event((EVENT_HEADER *)vq);
+ if (evel_rc != EVEL_SUCCESS)
+ {
+ EVEL_ERROR("Post failed %d (%s)", evel_rc, evel_error_string());
+ }
+ }
+ else
+ {
+ EVEL_ERROR("New Syslog failed");
+ }
+ printf(" Processed full Syslog\n");
+}
+
+/**************************************************************************//**
+ * Create and send two other events.
+ *****************************************************************************/
+void demo_other(void)
+{
+ EVENT_OTHER * other = NULL;
+ EVEL_ERR_CODES evel_rc = EVEL_SUCCESS;
+
+ /***************************************************************************/
+ /* Other */
+ /***************************************************************************/
+ other = evel_new_other();
+ if (other != NULL)
+ {
+ evel_rc = evel_post_event((EVENT_HEADER *)other);
+ if (evel_rc != EVEL_SUCCESS)
+ {
+ EVEL_ERROR("Post failed %d (%s)", evel_rc, evel_error_string());
+ }
+ }
+ else
+ {
+ EVEL_ERROR("New Other failed");
+ }
+ printf(" Processed empty Other\n");
+
+ other = evel_new_other();
+ if (other != NULL)
+ {
+
+
+ char * jsstr = "{"
+ "\"data1\":[1,2,3,4,5,6,7,8,9],"
+ "\"data2\":["
+ "[3,4,5,6,1],"
+ "[8,4,5,6,1],"
+ "[10,4,5,3,61],"
+ "[3,4,5,6,1],"
+ "[3,4,5,6,1],"
+ "[3,4,5,6,1]"
+ "]"
+ "}";
+
+
+char * jsstr2 = "{ \"employee\":{ \"name\":\"John\", \"age\":30, \"city\":\"New York\" } }";
+
+ evel_other_field_set_namedarraysize(other,50);
+ evel_other_field_add_namedarray(other,"name1", "disk1", "10000");
+ evel_other_field_add_namedarray(other,"name2", "disk2", "20000");
+ evel_other_field_add_namedarray(other,"name1", "disk2", "20000");
+ evel_other_field_add_namedarray(other,"name1", "disk1", "20000");
+
+ EVEL_JSON_OBJECT_INSTANCE * njinst = evel_new_jsonobjinstance(jsstr );
+ evel_epoch_microsec_set(njinst,9287578586767);
+ EVEL_INTERNAL_KEY * nkey = evel_new_internal_key("key1");
+ evel_internal_key_keyorder_set(nkey , 2);
+ evel_internal_key_keyvalue_set(nkey , "val1");
+ EVEL_INTERNAL_KEY * nkey2= evel_new_internal_key("key2");
+ evel_internal_key_keyorder_set(nkey2, 2);
+ evel_internal_key_keyvalue_set(nkey2, "val2");
+ evel_jsonobjinst_add_objectkey(njinst, nkey);
+ evel_jsonobjinst_add_objectkey(njinst, nkey2);
+
+ EVEL_JSON_OBJECT_INSTANCE * njinst2 = evel_new_jsonobjinstance(jsstr2 );
+ evel_epoch_microsec_set(njinst2,927578586767);
+
+ EVEL_JSON_OBJECT * myobj = evel_new_jsonobject("Myjobject");
+ evel_jsonobject_objectschema_set(myobj,"jsonschema5.0");
+ evel_jsonobject_objectschemaurl_set(myobj,"http://jsonschema5.0.att.com");
+ evel_jsonobject_nfsubscribedobjname_set(myobj,"nfobj1");
+ evel_jsonobject_nfsubscriptionid_set(myobj,"nfid1234");
+ evel_jsonobject_add_jsoninstance(myobj,njinst);
+ evel_jsonobject_add_jsoninstance(myobj,njinst2);
+ evel_other_field_add_jsonobj(other,myobj);
+
+ evel_other_field_add(other,
+ "Other field 1",
+ "Other value 1");
+
+
+ evel_rc = evel_post_event((EVENT_HEADER *)other);
+ if (evel_rc != EVEL_SUCCESS)
+ {
+ EVEL_ERROR("Post failed %d (%s)", evel_rc, evel_error_string());
+ }
+ }
+ else
+ {
+ EVEL_ERROR("New Other failed");
+ }
+ printf(" Processed small Other\n");
+ other = evel_new_other();
+ if (other != NULL)
+ {
+ evel_other_field_add(other,
+ "Other field A",
+ "Other value A");
+ evel_other_field_add(other,
+ "Other field B",
+ "Other value B");
+ evel_other_field_add(other,
+ "Other field C",
+ "Other value C");
+
+ evel_rc = evel_post_event((EVENT_HEADER *)other);
+ if (evel_rc != EVEL_SUCCESS)
+ {
+ EVEL_ERROR("Post failed %d (%s)", evel_rc, evel_error_string());
+ }
+ }
+ else
+ {
+ EVEL_ERROR("New Other failed");
+ }
+ printf(" Processed large Other\n");
+}
diff --git a/VES5.0/evel/evel-library/code/evel_demo/evel_demo.h b/VES5.0/evel/evel-library/code/evel_demo/evel_demo.h
new file mode 100644
index 00000000..e3aced4a
--- /dev/null
+++ b/VES5.0/evel/evel-library/code/evel_demo/evel_demo.h
@@ -0,0 +1,44 @@
+#ifndef EVEL_DEMO_INCLUDED
+#define EVEL_DEMO_INCLUDED
+
+/**************************************************************************//**
+ * @file
+ * Includes for the ECOMP Vendor Event Listener library demo.
+ *
+ * License
+ * -------
+ *
+ * Copyright(c) <2016>, AT&T Intellectual Property. All other rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement: This product includes software
+ * developed by the AT&T.
+ * 4. Neither the name of AT&T nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+* IN THE SOFTWARE.
+ *****************************************************************************/
+
+
+void *signal_watcher(void *);
+
+#endif
diff --git a/VES5.0/evel/evel-library/code/evel_demo/evel_test_control.c b/VES5.0/evel/evel-library/code/evel_demo/evel_test_control.c
new file mode 100644
index 00000000..5890dbec
--- /dev/null
+++ b/VES5.0/evel/evel-library/code/evel_demo/evel_test_control.c
@@ -0,0 +1,632 @@
+/**************************************************************************//**
+ * @file
+ * Utility to post test control commands to the test_collector testControl API.
+ *
+ * This software is a test capability, allowing test cases to trigger
+ * expected throttling behaviours at the test collector, for automated test
+ * capabilty.
+ *
+ * License
+ * -------
+ *
+ * Copyright(c) <2016>, AT&T Intellectual Property. All other rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement: This product includes software
+ * developed by the AT&T.
+ * 4. Neither the name of AT&T nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <curl/curl.h>
+#include <assert.h>
+
+#include "evel_test_control.h"
+#include "evel_internal.h" /* For MEMORY_CHUNK */
+
+/*****************************************************************************/
+/* Local prototypes. */
+/*****************************************************************************/
+static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *userp);
+
+/**************************************************************************//**
+ * POST provide JSON to the test_collector testControl API.
+ *
+ * This function does not take ownership of the json_buffer passed in.
+ *
+ * @param json_buffer Pointer to the JSON to POST
+ * @param json_size The number of bytes to POST
+ * @param secure Whether to use HTTPS (0=HTTP, 1=HTTPS)
+ * @param fqdn The test control API FQDN or IP address.
+ * @param port The test control API port.
+ *****************************************************************************/
+void evel_test_control(char * const json_buffer,
+ const int json_size,
+ const int secure,
+ const char * fqdn,
+ const int port)
+{
+ CURLcode curl_rc = CURLE_OK;
+ char curl_err_string[CURL_ERROR_SIZE] = "<NULL>";
+
+ /***************************************************************************/
+ /* Get a curl handle. */
+ /***************************************************************************/
+ CURL * curl_handle = curl_easy_init();
+ assert(curl_handle != NULL);
+
+ /***************************************************************************/
+ /* Prime the library to give friendly error codes. */
+ /***************************************************************************/
+ curl_rc = curl_easy_setopt(curl_handle,
+ CURLOPT_ERRORBUFFER,
+ curl_err_string);
+ assert(curl_rc == CURLE_OK);
+
+ /***************************************************************************/
+ /* Build and set the testControl API URL. */
+ /***************************************************************************/
+ char version_string[10] = {0};
+ int offset = sprintf(version_string, "%d", EVEL_API_MAJOR_VERSION);
+ if (EVEL_API_MINOR_VERSION != 0)
+ {
+ sprintf(version_string + offset, ".%d", EVEL_API_MINOR_VERSION);
+ }
+ char test_control_url[EVEL_MAX_URL_LEN + 1] = {0};
+ snprintf(test_control_url,
+ EVEL_MAX_URL_LEN,
+ "%s://%s:%d/testControl/v%s/commandList",
+ secure ? "https" : "http",
+ fqdn,
+ port,
+ version_string);
+ curl_rc = curl_easy_setopt(curl_handle, CURLOPT_URL, test_control_url);
+ assert(curl_rc == CURLE_OK);
+
+ /***************************************************************************/
+ /* 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");
+ assert(curl_rc == CURLE_OK);
+
+ /***************************************************************************/
+ /* Specify that we are going to POST data. */
+ /***************************************************************************/
+ curl_rc = curl_easy_setopt(curl_handle, CURLOPT_POST, 1L);
+ assert(curl_rc == CURLE_OK);
+
+ /***************************************************************************/
+ /* We want to use our own read function. */
+ /***************************************************************************/
+ curl_rc = curl_easy_setopt(curl_handle, CURLOPT_READFUNCTION, read_callback);
+ assert(curl_rc == CURLE_OK);
+
+ /***************************************************************************/
+ /* 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. */
+ /***************************************************************************/
+ static struct curl_slist * hdr_chunk = NULL;
+ 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);
+ assert(curl_rc == CURLE_OK);
+
+ /***************************************************************************/
+ /* Set the timeout for the operation. */
+ /***************************************************************************/
+ const int TEST_CTRL_TIMEOUT = 2;
+ curl_rc = curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, TEST_CTRL_TIMEOUT);
+ assert(curl_rc == CURLE_OK);
+
+ /***************************************************************************/
+ /* Create a common pointer to pass to our read function, on stack. */
+ /***************************************************************************/
+ MEMORY_CHUNK tx_chunk = {json_buffer, json_size};
+ curl_rc = curl_easy_setopt(curl_handle, CURLOPT_READDATA, &tx_chunk);
+ assert(curl_rc == CURLE_OK);
+
+ /***************************************************************************/
+ /* Set transmit size. */
+ /***************************************************************************/
+ curl_rc = curl_easy_setopt(curl_handle,
+ CURLOPT_POSTFIELDSIZE,
+ tx_chunk.size);
+ assert(curl_rc == CURLE_OK);
+
+ /***************************************************************************/
+ /* Perform the POST. */
+ /***************************************************************************/
+ curl_rc = curl_easy_perform(curl_handle);
+ assert(curl_rc == CURLE_OK);
+
+ /***************************************************************************/
+ /* Shut down the cURL library in a tidy manner. */
+ /***************************************************************************/
+ curl_easy_cleanup(curl_handle);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Callback function to provide POST data.
+ *
+ * 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)
+ {
+ 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;
+ }
+
+ EVEL_EXIT();
+
+ return rtn;
+}
+
+/**************************************************************************//**
+ * POST a pre-set test scenario to the test_collector testControl API.
+ *
+ * This function provides various pre-configured scenarios, purely to avoid
+ * duplicating them elsewhere.
+ *
+ * @param scenario The scenario to POST.
+ * @param secure Whether to use HTTPS (0=HTTP, 1=HTTPS)
+ * @param fqdn The test control API FQDN or IP address.
+ * @param port The test control API port.
+ *****************************************************************************/
+void evel_test_control_scenario(const EVEL_TEST_CONTROL_SCENARIO scenario,
+ const int secure,
+ const char * fqdn,
+ const int port)
+{
+ const int MAX_JSON = 10000;
+ char json_buffer[MAX_JSON];
+ int json_size = 0;
+
+ EVEL_ENTER();
+
+ switch (scenario)
+ {
+ case TC_RESET_ALL_DOMAINS:
+ json_size += snprintf(
+ json_buffer + json_size,
+ MAX_JSON - json_size,
+ "{"
+ " \"commandList\": ["
+ " {"
+ " \"command\": {"
+ " \"commandType\": \"throttlingSpecification\","
+ " \"eventDomainThrottleSpecification\": {"
+ " \"eventDomain\": \"fault\""
+ " }"
+ " }"
+ " },"
+ " {"
+ " \"command\": {"
+ " \"commandType\": \"throttlingSpecification\","
+ " \"eventDomainThrottleSpecification\": {"
+ " \"eventDomain\": \"measurementsForVfScaling\""
+ " }"
+ " }"
+ " },"
+ " {"
+ " \"command\": {"
+ " \"commandType\": \"throttlingSpecification\","
+ " \"eventDomainThrottleSpecification\": {"
+ " \"eventDomain\": \"mobileFlow\""
+ " }"
+ " }"
+ " },"
+ " {"
+ " \"command\": {"
+ " \"commandType\": \"throttlingSpecification\","
+ " \"eventDomainThrottleSpecification\": {"
+ " \"eventDomain\": \"serviceEvents\""
+ " }"
+ " }"
+ " },"
+ " {"
+ " \"command\": {"
+ " \"commandType\": \"throttlingSpecification\","
+ " \"eventDomainThrottleSpecification\": {"
+ " \"eventDomain\": \"signaling\""
+ " }"
+ " }"
+ " },"
+ " {"
+ " \"command\": {"
+ " \"commandType\": \"throttlingSpecification\","
+ " \"eventDomainThrottleSpecification\": {"
+ " \"eventDomain\": \"stateChange\""
+ " }"
+ " }"
+ " },"
+ " {"
+ " \"command\": {"
+ " \"commandType\": \"throttlingSpecification\","
+ " \"eventDomainThrottleSpecification\": {"
+ " \"eventDomain\": \"syslog\""
+ " }"
+ " }"
+ " }"
+ " ]"
+ "}");
+ break;
+
+ case TC_FAULT_SUPPRESS_FIELDS:
+ json_size += snprintf(
+ json_buffer + json_size,
+ MAX_JSON - json_size,
+ "{"
+ " \"commandList\": ["
+ " {"
+ " \"command\": {"
+ " \"commandType\": \"throttlingSpecification\","
+ " \"eventDomainThrottleSpecification\": {"
+ " \"suppressedFieldNames\": ["
+ " \"alarmInterfaceA\","
+ " \"alarmAdditionalInformation\""
+ " ],"
+ " \"eventDomain\": \"fault\""
+ " }"
+ " }"
+ " }"
+ " ]"
+ "}");
+ break;
+
+ case TC_FAULT_SUPPRESS_FIELDS_AND_PAIRS:
+ json_size += snprintf(
+ json_buffer + json_size,
+ MAX_JSON - json_size,
+ "{"
+ " \"commandList\": ["
+ " {"
+ " \"command\": {"
+ " \"commandType\": \"throttlingSpecification\","
+ " \"eventDomainThrottleSpecification\": {"
+ " \"suppressedNvPairsList\": ["
+ " {"
+ " \"nvPairFieldName\": \"alarmAdditionalInformation\","
+ " \"suppressedNvPairNames\": ["
+ " \"name1\","
+ " \"name2\""
+ " ]"
+ " }"
+ " ],"
+ " \"suppressedFieldNames\": ["
+ " \"alarmInterfaceA\""
+ " ],"
+ " \"eventDomain\": \"fault\""
+ " }"
+ " }"
+ " }"
+ " ]"
+ "}");
+ break;
+
+ case TC_FAULT_SUPPRESS_NOTHING:
+ json_size += snprintf(
+ json_buffer + json_size,
+ MAX_JSON - json_size,
+ "{"
+ " \"commandList\": ["
+ " {"
+ " \"command\": {"
+ " \"commandType\": \"throttlingSpecification\","
+ " \"eventDomainThrottleSpecification\": {"
+ " \"eventDomain\": \"fault\""
+ " }"
+ " }"
+ " }"
+ " ]"
+ "}");
+ break;
+
+ case TC_FAULT_SUPPRESS_PAIRS:
+ json_size += snprintf(
+ json_buffer + json_size,
+ MAX_JSON - json_size,
+ "{"
+ " \"commandList\": ["
+ " {"
+ " \"command\": {"
+ " \"commandType\": \"throttlingSpecification\","
+ " \"eventDomainThrottleSpecification\": {"
+ " \"suppressedNvPairsList\": ["
+ " {"
+ " \"nvPairFieldName\": \"alarmAdditionalInformation\","
+ " \"suppressedNvPairNames\": ["
+ " \"name1\","
+ " \"name2\""
+ " ]"
+ " }"
+ " ],"
+ " \"eventDomain\": \"fault\""
+ " }"
+ " }"
+ " }"
+ " ]"
+ "}");
+ break;
+
+ case TC_MEAS_SUPPRESS_FIELDS_AND_PAIRS:
+ json_size += snprintf(
+ json_buffer + json_size,
+ MAX_JSON - json_size,
+ "{"
+ " \"commandList\": ["
+ " {"
+ " \"command\": {"
+ " \"commandType\": \"throttlingSpecification\","
+ " \"eventDomainThrottleSpecification\": {"
+ " \"suppressedNvPairsList\": ["
+ " {"
+ " \"nvPairFieldName\": \"cpuUsageArray\","
+ " \"suppressedNvPairNames\": ["
+ " \"cpu1\","
+ " \"cpu3\""
+ " ]"
+ " }"
+ " ],"
+ " \"suppressedFieldNames\": ["
+ " \"numberOfMediaPortsInUse\""
+ " ],"
+ " \"eventDomain\": \"measurementsForVfScaling\""
+ " }"
+ " }"
+ " }"
+ " ]"
+ "}");
+ break;
+
+ case TC_MOBILE_SUPPRESS_FIELDS_AND_PAIRS:
+ json_size += snprintf(
+ json_buffer + json_size,
+ MAX_JSON - json_size,
+ "{"
+ " \"commandList\": ["
+ " {"
+ " \"command\": {"
+ " \"commandType\": \"throttlingSpecification\","
+ " \"eventDomainThrottleSpecification\": {"
+ " \"suppressedFieldNames\": ["
+ " \"radioAccessTechnology\","
+ " \"samplingAlgorithm\""
+ " ],"
+ " \"eventDomain\": \"mobileFlow\""
+ " }"
+ " }"
+ " }"
+ " ]"
+ "}");
+ break;
+
+ case TC_SERVICE_SUPPRESS_FIELDS_AND_PAIRS:
+ json_size += snprintf(
+ json_buffer + json_size,
+ MAX_JSON - json_size,
+ "{"
+ " \"commandList\": ["
+ " {"
+ " \"command\": {"
+ " \"commandType\": \"throttlingSpecification\","
+ " \"eventDomainThrottleSpecification\": {"
+ " \"suppressedNvPairsList\": ["
+ " {"
+ " \"nvPairFieldName\": \"additionalFields\","
+ " \"suppressedNvPairNames\": ["
+ " \"Name1\","
+ " \"Name3\""
+ " ]"
+ " }"
+ " ],"
+ " \"suppressedFieldNames\": ["
+ " \"reportingEntityId\","
+ " \"eventType\","
+ " \"sourceId\","
+ " \"midCallRtcp\","
+ " \"endOfCallVqmSummaries\","
+ " \"marker\""
+ " ],"
+ " \"eventDomain\": \"serviceEvents\""
+ " }"
+ " }"
+ " }"
+ " ]"
+ "}");
+ break;
+
+ case TC_SIGNALING_SUPPRESS_FIELDS:
+ json_size += snprintf(
+ json_buffer + json_size,
+ MAX_JSON - json_size,
+ "{"
+ " \"commandList\": ["
+ " {"
+ " \"command\": {"
+ " \"commandType\": \"throttlingSpecification\","
+ " \"eventDomainThrottleSpecification\": {"
+ " \"suppressedFieldNames\": ["
+ " \"reportingEntityId\","
+ " \"eventType\","
+ " \"sourceId\","
+ " \"localIpAddress\","
+ " \"localIpPort\","
+ " \"remoteIpAddress\","
+ " \"remotePort\","
+ " \"compressedSip\""
+ " ],"
+ " \"eventDomain\": \"signaling\""
+ " }"
+ " }"
+ " }"
+ " ]"
+ "}");
+ break;
+
+ case TC_STATE_SUPPRESS_FIELDS_AND_PAIRS:
+ json_size += snprintf(
+ json_buffer + json_size,
+ MAX_JSON - json_size,
+ "{"
+ " \"commandList\": ["
+ " {"
+ " \"command\": {"
+ " \"commandType\": \"throttlingSpecification\","
+ " \"eventDomainThrottleSpecification\": {"
+ " \"suppressedNvPairsList\": ["
+ " {"
+ " \"nvPairFieldName\": \"additionalFields\","
+ " \"suppressedNvPairNames\": ["
+ " \"Name1\""
+ " ]"
+ " }"
+ " ],"
+ " \"suppressedFieldNames\": ["
+ " \"reportingEntityId\","
+ " \"eventType\","
+ " \"sourceId\""
+ " ],"
+ " \"eventDomain\": \"stateChange\""
+ " }"
+ " }"
+ " }"
+ " ]"
+ "}");
+ break;
+
+ case TC_SYSLOG_SUPPRESS_FIELDS_AND_PAIRS:
+ json_size += snprintf(
+ json_buffer + json_size,
+ MAX_JSON - json_size,
+ "{"
+ " \"commandList\": ["
+ " {"
+ " \"command\": {"
+ " \"commandType\": \"throttlingSpecification\","
+ " \"eventDomainThrottleSpecification\": {"
+ " \"suppressedNvPairsList\": ["
+ " {"
+ " \"nvPairFieldName\": \"additionalFields\","
+ " \"suppressedNvPairNames\": ["
+ " \"Name1\","
+ " \"Name4\""
+ " ]"
+ " }"
+ " ],"
+ " \"suppressedFieldNames\": ["
+ " \"syslogFacility\","
+ " \"syslogProc\","
+ " \"syslogProcId\""
+ " ],"
+ " \"eventDomain\": \"syslog\""
+ " }"
+ " }"
+ " }"
+ " ]"
+ "}");
+ break;
+
+ case TC_PROVIDE_THROTTLING_SPEC:
+ json_size += snprintf(
+ json_buffer + json_size,
+ MAX_JSON - json_size,
+ "{"
+ " \"commandList\": ["
+ " {"
+ " \"command\": {"
+ " \"commandType\": \"provideThrottlingState\""
+ " }"
+ " }"
+ " ]"
+ "}");
+ break;
+
+ default:
+ break;
+ }
+
+ if (json_size != 0)
+ {
+ evel_test_control(json_buffer, json_size, secure, fqdn, port);
+ }
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * POST a measurement interval change to the test_collector testControl API.
+ *
+ * @param interval The measurement interval.
+ * @param secure Whether to use HTTPS (0=HTTP, 1=HTTPS)
+ * @param fqdn The test control API FQDN or IP address.
+ * @param port The test control API port.
+ *****************************************************************************/
+void evel_test_control_meas_interval(const int interval,
+ const int secure,
+ const char * fqdn,
+ const int port)
+{
+ const int MAX_JSON = 10000;
+ char json_buffer[MAX_JSON];
+ int json_size = 0;
+
+ EVEL_ENTER();
+
+ json_size += snprintf(
+ json_buffer + json_size,
+ MAX_JSON - json_size,
+ "{\"commandList\": [{\"command\": "
+ "{\"commandType\": \"measurementIntervalChange\", "
+ "\"measurementInterval\": %d}}]}",
+ interval);
+ evel_test_control(json_buffer, json_size, secure, fqdn, port);
+
+ EVEL_EXIT();
+}
diff --git a/VES5.0/evel/evel-library/code/evel_demo/evel_test_control.cbak b/VES5.0/evel/evel-library/code/evel_demo/evel_test_control.cbak
new file mode 100644
index 00000000..545eabfe
--- /dev/null
+++ b/VES5.0/evel/evel-library/code/evel_demo/evel_test_control.cbak
@@ -0,0 +1,599 @@
+/**************************************************************************//**
+ * @file
+ * Utility to post test control commands to the test_collector testControl API.
+ *
+ * This software is a test capability, allowing test cases to trigger
+ * expected throttling behaviours at the test collector, for automated test
+ * capabilty.
+ *
+ * License
+ * -------
+ *
+ * Copyright(c) <2016>, AT&T Intellectual Property. All other rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement: This product includes software
+ * developed by the AT&T.
+ * 4. Neither the name of AT&T nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <curl/curl.h>
+#include <assert.h>
+
+#include "evel_test_control.h"
+#include "evel_internal.h" /* For MEMORY_CHUNK */
+
+/*****************************************************************************/
+/* Local prototypes. */
+/*****************************************************************************/
+static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *userp);
+
+/**************************************************************************//**
+ * POST provide JSON to the test_collector testControl API.
+ *
+ * This function does not take ownership of the json_buffer passed in.
+ *
+ * @param json_buffer Pointer to the JSON to POST
+ * @param json_size The number of bytes to POST
+ * @param secure Whether to use HTTPS (0=HTTP, 1=HTTPS)
+ * @param fqdn The test control API FQDN or IP address.
+ * @param port The test control API port.
+ *****************************************************************************/
+void evel_test_control(char * const json_buffer,
+ const int json_size,
+ const int secure,
+ const char * fqdn,
+ const int port)
+{
+ CURLcode curl_rc = CURLE_OK;
+ char curl_err_string[CURL_ERROR_SIZE] = "<NULL>";
+
+ /***************************************************************************/
+ /* Get a curl handle. */
+ /***************************************************************************/
+ CURL * curl_handle = curl_easy_init();
+ assert(curl_handle != NULL);
+
+ /***************************************************************************/
+ /* Prime the library to give friendly error codes. */
+ /***************************************************************************/
+ curl_rc = curl_easy_setopt(curl_handle,
+ CURLOPT_ERRORBUFFER,
+ curl_err_string);
+ assert(curl_rc == CURLE_OK);
+
+ /***************************************************************************/
+ /* Build and set the testControl API URL. */
+ /***************************************************************************/
+ char version_string[10] = {0};
+ int offset = sprintf(version_string, "%d", EVEL_API_MAJOR_VERSION);
+ if (EVEL_API_MINOR_VERSION != 0)
+ {
+ sprintf(version_string + offset, ".%d", EVEL_API_MINOR_VERSION);
+ }
+ char test_control_url[EVEL_MAX_URL_LEN + 1] = {0};
+ snprintf(test_control_url,
+ EVEL_MAX_URL_LEN,
+ "%s://%s:%d/testControl/v%s/commandList",
+ secure ? "https" : "http",
+ fqdn,
+ port,
+ version_string);
+ curl_rc = curl_easy_setopt(curl_handle, CURLOPT_URL, test_control_url);
+ assert(curl_rc == CURLE_OK);
+
+ /***************************************************************************/
+ /* 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");
+ assert(curl_rc == CURLE_OK);
+
+ /***************************************************************************/
+ /* Specify that we are going to POST data. */
+ /***************************************************************************/
+ curl_rc = curl_easy_setopt(curl_handle, CURLOPT_POST, 1L);
+ assert(curl_rc == CURLE_OK);
+
+ /***************************************************************************/
+ /* We want to use our own read function. */
+ /***************************************************************************/
+ curl_rc = curl_easy_setopt(curl_handle, CURLOPT_READFUNCTION, read_callback);
+ assert(curl_rc == CURLE_OK);
+
+ /***************************************************************************/
+ /* 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. */
+ /***************************************************************************/
+ static struct curl_slist * hdr_chunk = NULL;
+ 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);
+ assert(curl_rc == CURLE_OK);
+
+ /***************************************************************************/
+ /* Set the timeout for the operation. */
+ /***************************************************************************/
+ const int TEST_CTRL_TIMEOUT = 2;
+ curl_rc = curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, TEST_CTRL_TIMEOUT);
+ assert(curl_rc == CURLE_OK);
+
+ /***************************************************************************/
+ /* Create a common pointer to pass to our read function, on stack. */
+ /***************************************************************************/
+ MEMORY_CHUNK tx_chunk = {json_buffer, json_size};
+ curl_rc = curl_easy_setopt(curl_handle, CURLOPT_READDATA, &tx_chunk);
+ assert(curl_rc == CURLE_OK);
+
+ /***************************************************************************/
+ /* Set transmit size. */
+ /***************************************************************************/
+ curl_rc = curl_easy_setopt(curl_handle,
+ CURLOPT_POSTFIELDSIZE,
+ tx_chunk.size);
+ assert(curl_rc == CURLE_OK);
+
+ /***************************************************************************/
+ /* Perform the POST. */
+ /***************************************************************************/
+ curl_rc = curl_easy_perform(curl_handle);
+ assert(curl_rc == CURLE_OK);
+
+ /***************************************************************************/
+ /* Shut down the cURL library in a tidy manner. */
+ /***************************************************************************/
+ curl_easy_cleanup(curl_handle);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Callback function to provide POST data.
+ *
+ * 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)
+ {
+ 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;
+ }
+
+ EVEL_EXIT();
+
+ return rtn;
+}
+
+/**************************************************************************//**
+ * POST a pre-set test scenario to the test_collector testControl API.
+ *
+ * This function provides various pre-configured scenarios, purely to avoid
+ * duplicating them elsewhere.
+ *
+ * @param scenario The scenario to POST.
+ * @param secure Whether to use HTTPS (0=HTTP, 1=HTTPS)
+ * @param fqdn The test control API FQDN or IP address.
+ * @param port The test control API port.
+ *****************************************************************************/
+void evel_test_control_scenario(const EVEL_TEST_CONTROL_SCENARIO scenario,
+ const int secure,
+ const char * fqdn,
+ const int port)
+{
+ const int MAX_JSON = 10000;
+ char json_buffer[MAX_JSON];
+ int json_size = 0;
+
+ EVEL_ENTER();
+
+ switch (scenario)
+ {
+ case TC_RESET_ALL_DOMAINS:
+ json_size += snprintf(
+ json_buffer + json_size,
+ MAX_JSON - json_size,
+ "{"
+ " \"commandList\": ["
+ " \"command\": {"
+ " \"commandType\": \"throttlingSpecification\","
+ " \"eventDomainThrottleSpecification\": {"
+ " \"eventDomain\": \"fault\""
+ " }"
+ " },"
+ " \"command\": {"
+ " \"commandType\": \"throttlingSpecification\","
+ " \"eventDomainThrottleSpecification\": {"
+ " \"eventDomain\": \"measurementsForVfScaling\""
+ " }"
+ " },"
+ " \"command\": {"
+ " \"commandType\": \"throttlingSpecification\","
+ " \"eventDomainThrottleSpecification\": {"
+ " \"eventDomain\": \"mobileFlow\""
+ " }"
+ " },"
+ " \"command\": {"
+ " \"commandType\": \"throttlingSpecification\","
+ " \"eventDomainThrottleSpecification\": {"
+ " \"eventDomain\": \"serviceEvents\""
+ " }"
+ " },"
+ " \"command\": {"
+ " \"commandType\": \"throttlingSpecification\","
+ " \"eventDomainThrottleSpecification\": {"
+ " \"eventDomain\": \"signaling\""
+ " }"
+ " },"
+ " \"command\": {"
+ " \"commandType\": \"throttlingSpecification\","
+ " \"eventDomainThrottleSpecification\": {"
+ " \"eventDomain\": \"stateChange\""
+ " }"
+ " },"
+ " \"command\": {"
+ " \"commandType\": \"throttlingSpecification\","
+ " \"eventDomainThrottleSpecification\": {"
+ " \"eventDomain\": \"syslog\""
+ " }"
+ " }"
+ " ]"
+ "}");
+ break;
+
+ case TC_FAULT_SUPPRESS_FIELDS:
+ json_size += snprintf(
+ json_buffer + json_size,
+ MAX_JSON - json_size,
+ "{"
+ " \"commandList\": ["
+ " \"command\": {"
+ " \"commandType\": \"throttlingSpecification\","
+ " \"eventDomainThrottleSpecification\": {"
+ " \"suppressedFieldNames\": ["
+ " \"alarmInterfaceA\","
+ " \"alarmAdditionalInformation\""
+ " ],"
+ " \"eventDomain\": \"fault\""
+ " }"
+ " }"
+ " ]"
+ "}");
+ break;
+
+ case TC_FAULT_SUPPRESS_FIELDS_AND_PAIRS:
+ json_size += snprintf(
+ json_buffer + json_size,
+ MAX_JSON - json_size,
+ "{"
+ " \"commandList\": ["
+ " \"command\": {"
+ " \"commandType\": \"throttlingSpecification\","
+ " \"eventDomainThrottleSpecification\": {"
+ " \"suppressedNvPairsList\": ["
+ " {"
+ " \"nvPairFieldName\": \"alarmAdditionalInformation\","
+ " \"suppressedNvPairNames\": ["
+ " \"name1\","
+ " \"name2\""
+ " ]"
+ " }"
+ " ],"
+ " \"suppressedFieldNames\": ["
+ " \"alarmInterfaceA\""
+ " ],"
+ " \"eventDomain\": \"fault\""
+ " }"
+ " }"
+ " ]"
+ "}");
+ break;
+
+ case TC_FAULT_SUPPRESS_NOTHING:
+ json_size += snprintf(
+ json_buffer + json_size,
+ MAX_JSON - json_size,
+ "{"
+ " \"commandList\": ["
+ " \"command\": {"
+ " \"commandType\": \"throttlingSpecification\","
+ " \"eventDomainThrottleSpecification\": {"
+ " \"eventDomain\": \"fault\""
+ " }"
+ " }"
+ " ]"
+ "}");
+ break;
+
+ case TC_FAULT_SUPPRESS_PAIRS:
+ json_size += snprintf(
+ json_buffer + json_size,
+ MAX_JSON - json_size,
+ "{"
+ " \"commandList\": ["
+ " \"command\": {"
+ " \"commandType\": \"throttlingSpecification\","
+ " \"eventDomainThrottleSpecification\": {"
+ " \"suppressedNvPairsList\": ["
+ " {"
+ " \"nvPairFieldName\": \"alarmAdditionalInformation\","
+ " \"suppressedNvPairNames\": ["
+ " \"name1\","
+ " \"name2\""
+ " ]"
+ " }"
+ " ],"
+ " \"eventDomain\": \"fault\""
+ " }"
+ " }"
+ " ]"
+ "}");
+ break;
+
+ case TC_MEAS_SUPPRESS_FIELDS_AND_PAIRS:
+ json_size += snprintf(
+ json_buffer + json_size,
+ MAX_JSON - json_size,
+ "{"
+ " \"commandList\": ["
+ " \"command\": {"
+ " \"commandType\": \"throttlingSpecification\","
+ " \"eventDomainThrottleSpecification\": {"
+ " \"suppressedNvPairsList\": ["
+ " {"
+ " \"nvPairFieldName\": \"cpuUsageArray\","
+ " \"suppressedNvPairNames\": ["
+ " \"cpu1\","
+ " \"cpu3\""
+ " ]"
+ " }"
+ " ],"
+ " \"suppressedFieldNames\": ["
+ " \"numberOfMediaPortsInUse\","
+ " \"aggregateCpuUsage\""
+ " ],"
+ " \"eventDomain\": \"measurementsForVfScaling\""
+ " }"
+ " }"
+ " ]"
+ "}");
+ break;
+
+ case TC_MOBILE_SUPPRESS_FIELDS_AND_PAIRS:
+ json_size += snprintf(
+ json_buffer + json_size,
+ MAX_JSON - json_size,
+ "{"
+ " \"commandList\": ["
+ " \"command\": {"
+ " \"commandType\": \"throttlingSpecification\","
+ " \"eventDomainThrottleSpecification\": {"
+ " \"suppressedFieldNames\": ["
+ " \"radioAccessTechnology\","
+ " \"samplingAlgorithm\""
+ " ],"
+ " \"eventDomain\": \"mobileFlow\""
+ " }"
+ " }"
+ " ]"
+ "}");
+ break;
+
+ case TC_SERVICE_SUPPRESS_FIELDS_AND_PAIRS:
+ json_size += snprintf(
+ json_buffer + json_size,
+ MAX_JSON - json_size,
+ "{"
+ " \"commandList\": ["
+ " \"command\": {"
+ " \"commandType\": \"throttlingSpecification\","
+ " \"eventDomainThrottleSpecification\": {"
+ " \"suppressedNvPairsList\": ["
+ " {"
+ " \"nvPairFieldName\": \"additionalFields\","
+ " \"suppressedNvPairNames\": ["
+ " \"Name1\","
+ " \"Name3\""
+ " ]"
+ " }"
+ " ],"
+ " \"suppressedFieldNames\": ["
+ " \"reportingEntityId\","
+ " \"eventType\","
+ " \"sourceId\","
+ " \"codecSelected\","
+ " \"codecSelectedTranscoding\","
+ " \"midCallRtcp\","
+ " \"endOfCallVqmSummaries\","
+ " \"marker\""
+ " ],"
+ " \"eventDomain\": \"serviceEvents\""
+ " }"
+ " }"
+ " ]"
+ "}");
+ break;
+
+ case TC_SIGNALING_SUPPRESS_FIELDS:
+ json_size += snprintf(
+ json_buffer + json_size,
+ MAX_JSON - json_size,
+ "{"
+ " \"commandList\": ["
+ " \"command\": {"
+ " \"commandType\": \"throttlingSpecification\","
+ " \"eventDomainThrottleSpecification\": {"
+ " \"suppressedFieldNames\": ["
+ " \"reportingEntityId\","
+ " \"eventType\","
+ " \"sourceId\","
+ " \"localIpAddress\","
+ " \"localIpPort\","
+ " \"remoteIpAddress\","
+ " \"remotePort\","
+ " \"compressedSip\""
+ " ],"
+ " \"eventDomain\": \"signaling\""
+ " }"
+ " }"
+ " ]"
+ "}");
+ break;
+
+ case TC_STATE_SUPPRESS_FIELDS_AND_PAIRS:
+ json_size += snprintf(
+ json_buffer + json_size,
+ MAX_JSON - json_size,
+ "{"
+ " \"commandList\": ["
+ " \"command\": {"
+ " \"commandType\": \"throttlingSpecification\","
+ " \"eventDomainThrottleSpecification\": {"
+ " \"suppressedNvPairsList\": ["
+ " {"
+ " \"nvPairFieldName\": \"additionalFields\","
+ " \"suppressedNvPairNames\": ["
+ " \"Name1\""
+ " ]"
+ " }"
+ " ],"
+ " \"suppressedFieldNames\": ["
+ " \"reportingEntityId\","
+ " \"eventType\","
+ " \"sourceId\""
+ " ],"
+ " \"eventDomain\": \"stateChange\""
+ " }"
+ " }"
+ " ]"
+ "}");
+ break;
+
+ case TC_SYSLOG_SUPPRESS_FIELDS_AND_PAIRS:
+ json_size += snprintf(
+ json_buffer + json_size,
+ MAX_JSON - json_size,
+ "{"
+ " \"commandList\": ["
+ " \"command\": {"
+ " \"commandType\": \"throttlingSpecification\","
+ " \"eventDomainThrottleSpecification\": {"
+ " \"suppressedNvPairsList\": ["
+ " {"
+ " \"nvPairFieldName\": \"additionalFields\","
+ " \"suppressedNvPairNames\": ["
+ " \"Name1\","
+ " \"Name4\""
+ " ]"
+ " }"
+ " ],"
+ " \"suppressedFieldNames\": ["
+ " \"syslogFacility\","
+ " \"syslogProc\","
+ " \"syslogProcId\""
+ " ],"
+ " \"eventDomain\": \"syslog\""
+ " }"
+ " }"
+ " ]"
+ "}");
+ break;
+
+ case TC_PROVIDE_THROTTLING_SPEC:
+ json_size += snprintf(
+ json_buffer + json_size,
+ MAX_JSON - json_size,
+ "{"
+ " \"commandList\": ["
+ " \"command\": {"
+ " \"commandType\": \"provideThrottlingState\""
+ " }"
+ " ]"
+ "}");
+ break;
+
+ default:
+ break;
+ }
+
+ if (json_size != 0)
+ {
+ evel_test_control(json_buffer, json_size, secure, fqdn, port);
+ }
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * POST a measurement interval change to the test_collector testControl API.
+ *
+ * @param interval The measurement interval.
+ * @param secure Whether to use HTTPS (0=HTTP, 1=HTTPS)
+ * @param fqdn The test control API FQDN or IP address.
+ * @param port The test control API port.
+ *****************************************************************************/
+void evel_test_control_meas_interval(const int interval,
+ const int secure,
+ const char * fqdn,
+ const int port)
+{
+ const int MAX_JSON = 10000;
+ char json_buffer[MAX_JSON];
+ int json_size = 0;
+
+ EVEL_ENTER();
+
+ json_size += snprintf(
+ json_buffer + json_size,
+ MAX_JSON - json_size,
+ "{\"commandList\": [\"command\": "
+ "{\"commandType\": \"measurementIntervalChange\", "
+ "\"measurementInterval\": %d}]}",
+ interval);
+ evel_test_control(json_buffer, json_size, secure, fqdn, port);
+
+ EVEL_EXIT();
+}
diff --git a/VES5.0/evel/evel-library/code/evel_demo/evel_test_control.h b/VES5.0/evel/evel-library/code/evel_demo/evel_test_control.h
new file mode 100644
index 00000000..2e348078
--- /dev/null
+++ b/VES5.0/evel/evel-library/code/evel_demo/evel_test_control.h
@@ -0,0 +1,104 @@
+#ifndef EVEL_TEST_CONTROL
+#define EVEL_TEST_CONTROL
+/**************************************************************************//**
+ * @file
+ * Utility to post test control commands to the test_collector testControl API.
+ *
+ * This software is a test capability, allowing test cases to trigger
+ * expected throttling behaviours at the test collector, for automated test
+ * capabilty.
+ *
+ * License
+ * -------
+ *
+ * Copyright(c) <2016>, AT&T Intellectual Property. All other rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement: This product includes software
+ * developed by the AT&T.
+ * 4. Neither the name of AT&T nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+/**************************************************************************//**
+ * POST provide JSON to the test_collector testControl API.
+ *
+ * This function does not take ownership of the json_buffer passed in.
+ *
+ * @param json_buffer Pointer to the JSON to POST
+ * @param json_size The number of bytes to POST
+ * @param secure Whether to use HTTPS (0=HTTP, 1=HTTPS)
+ * @param fqdn The test control API FQDN or IP address.
+ * @param port The test control API port.
+ *****************************************************************************/
+void evel_test_control(char * const json_buffer,
+ const int json_size,
+ const int secure,
+ const char * fqdn,
+ const int port);
+
+typedef enum {
+ TC_RESET_ALL_DOMAINS,
+ TC_FAULT_SUPPRESS_FIELDS,
+ TC_FAULT_SUPPRESS_FIELDS_AND_PAIRS,
+ TC_FAULT_SUPPRESS_NOTHING,
+ TC_FAULT_SUPPRESS_PAIRS,
+ TC_MEAS_SUPPRESS_FIELDS_AND_PAIRS,
+ TC_MOBILE_SUPPRESS_FIELDS_AND_PAIRS,
+ TC_SIGNALING_SUPPRESS_FIELDS,
+ TC_SERVICE_SUPPRESS_FIELDS_AND_PAIRS,
+ TC_STATE_SUPPRESS_FIELDS_AND_PAIRS,
+ TC_SYSLOG_SUPPRESS_FIELDS_AND_PAIRS,
+ TC_PROVIDE_THROTTLING_SPEC
+} EVEL_TEST_CONTROL_SCENARIO;
+
+/**************************************************************************//**
+ * POST a pre-set test scenario to the test_collector testControl API.
+ *
+ * This function provides various pre-configured scenarios, purely to avoid
+ * duplicating them elsewhere.
+ *
+ * @param scenario The scenario to POST.
+ * @param secure Whether to use HTTPS (0=HTTP, 1=HTTPS)
+ * @param fqdn The test control API FQDN or IP address.
+ * @param port The test control API port.
+ *****************************************************************************/
+void evel_test_control_scenario(const EVEL_TEST_CONTROL_SCENARIO scenario,
+ const int secure,
+ const char * fqdn,
+ const int port);
+
+/**************************************************************************//**
+ * POST a measurement interval change to the test_collector testControl API.
+ *
+ * @param interval The measurement interval.
+ * @param secure Whether to use HTTPS (0=HTTP, 1=HTTPS)
+ * @param fqdn The test control API FQDN or IP address.
+ * @param port The test control API port.
+ *****************************************************************************/
+void evel_test_control_meas_interval(const int interval,
+ const int secure,
+ const char * fqdn,
+ const int port);
+
+#endif
diff --git a/VES5.0/evel/evel-library/code/evel_library/a.out b/VES5.0/evel/evel-library/code/evel_library/a.out
new file mode 100755
index 00000000..10ce4e39
--- /dev/null
+++ b/VES5.0/evel/evel-library/code/evel_library/a.out
Binary files differ
diff --git a/VES5.0/evel/evel-library/code/evel_library/double_list.c b/VES5.0/evel/evel-library/code/evel_library/double_list.c
new file mode 100644
index 00000000..a480accb
--- /dev/null
+++ b/VES5.0/evel/evel-library/code/evel_library/double_list.c
@@ -0,0 +1,194 @@
+/**************************************************************************//**
+ * @file
+ * A simple double-linked list.
+ *
+ * @note No thread protection so you will need to use appropriate
+ * synchronization if use spans multiple threads.
+ *
+ * License
+ * -------
+ *
+ * Copyright(c) <2016>, AT&T Intellectual Property. All other rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement: This product includes
+ * software developed by the AT&T.
+ * 4. Neither the name of AT&T nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#include <assert.h>
+#include <malloc.h>
+
+#include "double_list.h"
+#include "evel.h"
+
+/**************************************************************************//**
+ * List initialization.
+ *
+ * Initialize the list supplied to be empty.
+ *
+ * @param list Pointer to the list to be initialized.
+
+ * @returns Nothing
+******************************************************************************/
+void dlist_initialize(DLIST * list)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check assumptions. */
+ /***************************************************************************/
+ assert(list != NULL);
+
+ /***************************************************************************/
+ /* Initialize the list as empty. */
+ /***************************************************************************/
+ list->head = NULL;
+ list->tail = NULL;
+
+ EVEL_EXIT();
+}
+
+void * dlist_pop_last(DLIST * list)
+{
+ void *item = NULL;
+ DLIST_ITEM *current_tail = NULL;
+ DLIST_ITEM *new_tail = NULL;
+
+ assert(list != NULL);
+
+ current_tail = list->tail;
+ if (current_tail != NULL)
+ {
+ item = current_tail->item;
+ new_tail = current_tail->previous;
+ if (new_tail == NULL)
+ {
+ list->head = NULL;
+ list->tail = NULL;
+ }
+ else
+ {
+ new_tail->next = NULL;
+ list->tail = new_tail;
+ }
+ free(current_tail);
+ }
+
+ return item;
+}
+
+void dlist_push_first(DLIST * list, void * item)
+{
+ DLIST_ITEM * new_element = NULL;
+ DLIST_ITEM * current_head = NULL;
+
+ /***************************************************************************/
+ /* Check assumptions. Note that we do allow putting NULL pointers into */
+ /* the list - not sure you'd want to, but let it happen. */
+ /***************************************************************************/
+ assert(list != NULL);
+
+ current_head = list->head;
+
+ new_element = malloc(sizeof(DLIST_ITEM));
+ assert(new_element != NULL);
+ new_element->next = current_head;
+ new_element->previous = NULL;
+ new_element->item = item;
+ list->head = new_element;
+
+ if (current_head != NULL)
+ {
+ current_head->previous = new_element;
+ }
+ else
+ {
+ list->tail = new_element;
+ }
+}
+
+void dlist_push_last(DLIST * list, void * item)
+{
+ DLIST_ITEM * new_element = NULL;
+ DLIST_ITEM * current_tail = NULL;
+
+ /***************************************************************************/
+ /* Check assumptions. Note that we do allow putting NULL pointers into */
+ /* the list - not sure you'd want to, but let it happen. */
+ /***************************************************************************/
+ assert(list != NULL);
+
+ current_tail = list->tail;
+
+ new_element = malloc(sizeof(DLIST_ITEM));
+ assert(new_element != NULL);
+ new_element->next = NULL;
+ new_element->previous = current_tail;
+ new_element->item = item;
+ list->tail = new_element;
+
+ if (current_tail != NULL)
+ {
+ current_tail->next = new_element;
+ }
+ else
+ {
+ list->head = new_element;
+ }
+}
+
+DLIST_ITEM * dlist_get_first(DLIST * list)
+{
+ return list->head;
+}
+
+DLIST_ITEM * dlist_get_last(DLIST * list)
+{
+ return list->tail;
+}
+
+DLIST_ITEM * dlist_get_next(DLIST_ITEM * item)
+{
+ return item->next;
+}
+
+int dlist_is_empty(DLIST * list)
+{
+ return (list->head == NULL);
+}
+
+int dlist_count(DLIST * list)
+{
+ int count = 0;
+ DLIST_ITEM * item = list->head;
+
+ while (item != NULL)
+ {
+ count++;
+ item = item->next;
+ }
+
+ return count;
+}
diff --git a/VES5.0/evel/evel-library/code/evel_library/double_list.h b/VES5.0/evel/evel-library/code/evel_library/double_list.h
new file mode 100644
index 00000000..e8bdd742
--- /dev/null
+++ b/VES5.0/evel/evel-library/code/evel_library/double_list.h
@@ -0,0 +1,70 @@
+#ifndef DOUBLE_LIST_INCLUDED
+#define DOUBLE_LIST_INCLUDED
+
+/**************************************************************************//**
+ * @file
+ * A simple double-linked list.
+ *
+ * @note No thread protection so you will need to use appropriate
+ * synchronization if use spans multiple threads.
+ *
+ * License
+ * -------
+ *
+ * Copyright(c) <2016>, AT&T Intellectual Property. All other rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement: This product includes
+ * software developed by the AT&T.
+ * 4. Neither the name of AT&T nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*****************************************************************************/
+
+typedef struct dlist_item
+{
+ struct dlist_item * previous;
+ struct dlist_item * next;
+ void * item;
+} DLIST_ITEM;
+
+/**************************************************************************//**
+ * Double-linked list structure
+ *****************************************************************************/
+typedef struct dlist
+{
+ DLIST_ITEM * head;
+ DLIST_ITEM * tail;
+} DLIST;
+
+
+void dlist_initialize(DLIST * list);
+void * dlist_pop_last(DLIST * list);
+void dlist_push_first(DLIST * list, void * item);
+void dlist_push_last(DLIST * list, void * item);
+DLIST_ITEM * dlist_get_first(DLIST * list);
+DLIST_ITEM * dlist_get_last(DLIST * list);
+DLIST_ITEM * dlist_get_next(DLIST_ITEM * item);
+int dlist_is_empty(DLIST * list);
+int dlist_count(DLIST * list);
+
+#endif
diff --git a/VES5.0/evel/evel-library/code/evel_library/evel.c b/VES5.0/evel/evel-library/code/evel_library/evel.c
new file mode 100644
index 00000000..3678d7d0
--- /dev/null
+++ b/VES5.0/evel/evel-library/code/evel_library/evel.c
@@ -0,0 +1,402 @@
+/**************************************************************************//**
+ * @file
+ * Source module isolating the ECOMP Vendor Event Listener (EVEL) API.
+ *
+ * This file implements the EVEL library which is intended to provide a
+ * simple wrapper around the complexity of AT&T's Vendor Event Listener API so
+ * that VNFs can use it without worrying about details of:
+ *
+ * * The API's encoding into JSON.
+ * * The API's transport over HTTP/HTTPS.
+ *
+ * License
+ * -------
+ *
+ * Copyright(c) <2016>, AT&T Intellectual Property. All other rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement: This product includes
+ * software developed by the AT&T.
+ * 4. Neither the name of AT&T nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include <curl/curl.h>
+
+#include "evel.h"
+#include "evel_internal.h"
+#include "evel_throttle.h"
+#include "metadata.h"
+
+/**************************************************************************//**
+ * The type of equipment represented by this VNF.
+ *****************************************************************************/
+EVEL_SOURCE_TYPES event_source_type = EVEL_SOURCE_OTHER;
+
+/**************************************************************************//**
+ * The Functional Role of the equipment represented by this VNF.
+ *****************************************************************************/
+char *functional_role = NULL;
+
+/**************************************************************************//**
+ * Library initialization.
+ *
+ * Initialize the EVEL library.
+ *
+ * @note This function initializes the cURL library. Applications making use
+ * of libcurl may need to pull the initialization out of here. Note
+ * also that this function is not threadsafe as a result - refer to
+ * libcurl's API documentation for relevant warnings.
+ *
+ * @sa Matching Term function.
+ *
+ * @param fqdn The API's FQDN or IP address.
+ * @param port The API's port.
+ * @param path The optional path (may be NULL).
+ * @param topic The optional topic part of the URL (may be NULL).
+ * @param secure Whether to use HTTPS (0=HTTP, 1=HTTPS)
+ * @param username Username for Basic Authentication of requests.
+ * @param password Password for Basic Authentication of requests.
+ * @param source_type The kind of node we represent.
+ * @param role The role this node undertakes.
+ * @param verbosity 0 for normal operation, positive values for chattier
+ * logs.
+ *
+ * @returns Status code
+ * @retval EVEL_SUCCESS On success
+ * @retval ::EVEL_ERR_CODES On failure.
+ *****************************************************************************/
+EVEL_ERR_CODES evel_initialize(const char * const fqdn,
+ int port,
+ const char * const path,
+ const char * const topic,
+ int secure,
+ const char * const username,
+ const char * const password,
+ EVEL_SOURCE_TYPES source_type,
+ const char * const role,
+ int verbosity
+ )
+{
+ EVEL_ERR_CODES rc = EVEL_SUCCESS;
+ char base_api_url[EVEL_MAX_URL_LEN + 1] = {0};
+ char event_api_url[EVEL_MAX_URL_LEN + 1] = {0};
+ char throt_api_url[EVEL_MAX_URL_LEN + 1] = {0};
+ char path_url[EVEL_MAX_URL_LEN + 1] = {0};
+ char topic_url[EVEL_MAX_URL_LEN + 1] = {0};
+ char version_string[10] = {0};
+ int offset;
+
+ /***************************************************************************/
+ /* Check assumptions. */
+ /***************************************************************************/
+ assert(fqdn != NULL);
+ assert(port > 0 && port <= 65535);
+ assert(source_type < EVEL_MAX_SOURCE_TYPES);
+ assert(role != NULL);
+
+ /***************************************************************************/
+ /* Start logging so we can report on progress. */
+ /***************************************************************************/
+ log_initialize(verbosity == 0 ? EVEL_LOG_INFO : EVEL_LOG_DEBUG, "EVEL");
+ EVEL_INFO("EVEL started");
+ EVEL_INFO("API server is: %s", fqdn);
+ EVEL_INFO("API port is: %d", port);
+
+ if (path != NULL)
+ {
+ EVEL_INFO("API path is: %s", path);
+ }
+ else
+ {
+ EVEL_INFO("No API path");
+ }
+
+ if (topic != NULL)
+ {
+ EVEL_INFO("API topic is: %s", topic);
+ }
+ else
+ {
+ EVEL_INFO("No API topic");
+ }
+
+ EVEL_INFO("API transport is: %s", secure ? "HTTPS" : "HTTP");
+ EVEL_INFO("Event Source Type is: %d", source_type);
+ EVEL_INFO("Functional Role is: %s", role);
+ EVEL_INFO("Log verbosity is: %d", verbosity);
+
+ /***************************************************************************/
+ /* Initialize event throttling to the default state. */
+ /***************************************************************************/
+ evel_throttle_initialize();
+
+ /***************************************************************************/
+ /* Save values we will need during operation. */
+ /***************************************************************************/
+ event_source_type = source_type;
+ functional_role = strdup(role);
+
+ /***************************************************************************/
+ /* Ensure there are no trailing zeroes and unnecessary decimal points in */
+ /* the version. */
+ /***************************************************************************/
+ offset = sprintf(version_string, "%d", EVEL_API_MAJOR_VERSION);
+
+ if (EVEL_API_MINOR_VERSION != 0)
+ {
+ sprintf(version_string + offset, ".%d", EVEL_API_MINOR_VERSION);
+ }
+
+ /***************************************************************************/
+ /* Build a common base of the API URLs. */
+ /***************************************************************************/
+ strcpy(path_url, "/");
+ snprintf(base_api_url,
+ EVEL_MAX_URL_LEN,
+ "%s://%s:%d%s/eventListener/v%s",
+ secure ? "https" : "http",
+ fqdn,
+ port,
+ (((path != NULL) && (strlen(path) > 0)) ?
+ strncat(path_url, path, EVEL_MAX_URL_LEN) : ""),
+ version_string);
+
+ /***************************************************************************/
+ /* Build the URL to the event API. */
+ /***************************************************************************/
+ strcpy(topic_url, "/");
+ snprintf(event_api_url,
+ EVEL_MAX_URL_LEN,
+ "%s%s",
+ base_api_url,
+ (((topic != NULL) && (strlen(topic) > 0)) ?
+ strncat(topic_url, topic, EVEL_MAX_URL_LEN) : ""));
+ EVEL_INFO("Vendor Event Listener API is located at: %s", event_api_url);
+
+ /***************************************************************************/
+ /* Build the URL to the throttling API. */
+ /***************************************************************************/
+ snprintf(throt_api_url,
+ EVEL_MAX_URL_LEN,
+ "%s/clientThrottlingState",
+ base_api_url);
+ EVEL_INFO("Vendor Event Throttling API is located at: %s", throt_api_url);
+
+ /***************************************************************************/
+ /* Spin-up the event-handler, which gets cURL readied for use. */
+ /***************************************************************************/
+ rc = event_handler_initialize(event_api_url,
+ throt_api_url,
+ username,
+ password,
+ verbosity);
+ if (rc != EVEL_SUCCESS)
+ {
+ log_error_state("Failed to initialize event handler (including cURL)");
+ goto exit_label;
+ }
+
+ /***************************************************************************/
+ /* Extract the metadata from OpenStack. If we fail to extract it, we */
+ /* record that in the logs, but carry on, assuming we're in a test */
+ /* without a metadata service. */
+ /***************************************************************************/
+ rc = openstack_metadata(verbosity);
+ if (rc != EVEL_SUCCESS)
+ {
+ EVEL_INFO("Failed to load OpenStack metadata - assuming test environment");
+ rc = EVEL_SUCCESS;
+ }
+
+ /***************************************************************************/
+ /* Start the event handler thread. */
+ /***************************************************************************/
+ rc = event_handler_run();
+ if (rc != EVEL_SUCCESS)
+ {
+ log_error_state("Failed to start event handler thread. "
+ "Error code=%d", rc);
+ goto exit_label;
+ }
+
+exit_label:
+ return(rc);
+}
+
+/**************************************************************************//**
+ * Clean up the EVEL library.
+ *
+ * @note that at present don't expect Init/Term cycling not to leak memory!
+ *
+ * @returns Status code
+ * @retval EVEL_SUCCESS On success
+ * @retval "One of ::EVEL_ERR_CODES" On failure.
+ *****************************************************************************/
+EVEL_ERR_CODES evel_terminate(void)
+{
+ int rc = EVEL_SUCCESS;
+
+ /***************************************************************************/
+ /* First terminate any pending transactions in the event-posting thread. */
+ /***************************************************************************/
+ rc = event_handler_terminate();
+ if (rc != EVEL_SUCCESS)
+ {
+ log_error_state("Failed to terminate EVEL library cleanly!");
+ }
+
+ /***************************************************************************/
+ /* Shut down the Event Handler library in a tidy manner. */
+ /***************************************************************************/
+ curl_global_cleanup();
+
+ /***************************************************************************/
+ /* Clean up allocated memory. */
+ /***************************************************************************/
+ free(functional_role);
+
+ /***************************************************************************/
+ /* Clean up event throttling. */
+ /***************************************************************************/
+ evel_throttle_terminate();
+
+ EVEL_INFO("EVEL stopped");
+ return(rc);
+}
+
+/**************************************************************************//**
+ * Free an event.
+ *
+ * Free off the event supplied. Will free all the contained allocated memory.
+ *
+ * @note It is safe to free a NULL pointer.
+ *****************************************************************************/
+void evel_free_event(void * event)
+{
+ EVENT_HEADER * evt_ptr = event;
+ EVEL_ENTER();
+
+ if (event != NULL)
+ {
+ /*************************************************************************/
+ /* Work out what kind of event we're dealing with so we can cast it */
+ /* appropriately. */
+ /*************************************************************************/
+ switch (evt_ptr->event_domain)
+ {
+ case EVEL_DOMAIN_INTERNAL:
+ EVEL_DEBUG("Event is an Internal event at %lp", evt_ptr);
+ evel_free_internal_event((EVENT_INTERNAL *) evt_ptr);
+ memset(evt_ptr, 0, sizeof(EVENT_INTERNAL));
+ free(evt_ptr);
+ break;
+
+ case EVEL_DOMAIN_HEARTBEAT:
+ EVEL_DEBUG("Event is a Heartbeat at %lp", evt_ptr);
+ evel_free_header(evt_ptr);
+ memset(evt_ptr, 0, sizeof(EVENT_HEADER));
+ free(evt_ptr);
+ break;
+
+ case EVEL_DOMAIN_FAULT:
+ EVEL_DEBUG("Event is a Fault at %lp", evt_ptr);
+ evel_free_fault((EVENT_FAULT *)evt_ptr);
+ memset(evt_ptr, 0, sizeof(EVENT_FAULT));
+ free(evt_ptr);
+ break;
+
+ case EVEL_DOMAIN_MEASUREMENT:
+ EVEL_DEBUG("Event is a Measurement at %lp", evt_ptr);
+ evel_free_measurement((EVENT_MEASUREMENT *)evt_ptr);
+ memset(evt_ptr, 0, sizeof(EVENT_MEASUREMENT));
+ free(evt_ptr);
+ break;
+
+ case EVEL_DOMAIN_MOBILE_FLOW:
+ EVEL_DEBUG("Event is a Mobile Flow at %lp", evt_ptr);
+ evel_free_mobile_flow((EVENT_MOBILE_FLOW *)evt_ptr);
+ memset(evt_ptr, 0, sizeof(EVENT_MOBILE_FLOW));
+ free(evt_ptr);
+ break;
+
+ case EVEL_DOMAIN_REPORT:
+ EVEL_DEBUG("Event is a Report at %lp", evt_ptr);
+ evel_free_report((EVENT_REPORT *)evt_ptr);
+ memset(evt_ptr, 0, sizeof(EVENT_REPORT));
+ free(evt_ptr);
+ break;
+
+ case EVEL_DOMAIN_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;
+
+ default:
+ EVEL_ERROR("Unexpected event domain (%d)", evt_ptr->event_domain);
+ assert(0);
+ }
+ }
+ EVEL_EXIT();
+}
diff --git a/VES5.0/evel/evel-library/code/evel_library/evel.h b/VES5.0/evel/evel-library/code/evel_library/evel.h
new file mode 100644
index 00000000..c824ca06
--- /dev/null
+++ b/VES5.0/evel/evel-library/code/evel_library/evel.h
@@ -0,0 +1,4204 @@
+#ifndef EVEL_INCLUDED
+#define EVEL_INCLUDED
+/**************************************************************************//**
+ * @file
+ * Header for EVEL library
+ *
+ * This file implements the EVEL library which is intended to provide a
+ * simple wrapper around the complexity of AT&T's Vendor Event Listener API so
+ * that VNFs can use it without worrying about details of the API transport.
+ *
+ * Zero return value is success (::EVEL_SUCCESS), non-zero is failure and will
+ * be one of ::EVEL_ERR_CODES.
+ *
+ * License
+ * -------
+ *
+ * Copyright(c) <2016>, AT&T Intellectual Property. All other rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement: This product includes
+ * software developed by the AT&T.
+ * 4. Neither the name of AT&T nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <time.h>
+
+#include "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_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;
+ int block_iops;
+ double block_used;
+ double ephemeral_configured;
+ int 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);
+
+/**************************************************************************//**
+ * Callback function to provide returned data.
+ *
+ * Copy data into the supplied buffer, write_callback::ptr, checking size
+ * limits.
+ *
+ * @returns Number of bytes placed into write_callback::ptr. 0 for EOF.
+ *****************************************************************************/
+size_t evel_write_callback(void *contents,
+ size_t size,
+ size_t nmemb,
+ void *userp);
+
+/*****************************************************************************/
+/*****************************************************************************/
+/* */
+/* HEARTBEAT - (includes common header, too) */
+/* */
+/*****************************************************************************/
+/*****************************************************************************/
+
+/**************************************************************************//**
+ * Create a new heartbeat event.
+ *
+ * @note that the heartbeat is just a "naked" commonEventHeader!
+ *
+ * @returns pointer to the newly manufactured ::EVENT_HEADER. If the event is
+ * not used it must be released using ::evel_free_event
+ * @retval NULL Failed to create the event.
+ *****************************************************************************/
+EVENT_HEADER * evel_new_heartbeat(void);
+
+/**************************************************************************//**
+ * Free an event header.
+ *
+ * Free off the event header supplied. Will free all the contained allocated
+ * memory.
+ *
+ * @note It does not free the header itself, since that may be part of a
+ * larger structure.
+ *****************************************************************************/
+void evel_free_header(EVENT_HEADER * const event);
+
+/**************************************************************************//**
+ * Initialize a newly created event header.
+ *
+ * @param header Pointer to the header being initialized.
+ *****************************************************************************/
+void evel_init_header(EVENT_HEADER * const header,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);
+
+/*****************************************************************************/
+/*****************************************************************************/
+/* */
+/* 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 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 * 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
+ *
+ * @returns pointer to the newly manufactured ::EVENT_MEASUREMENT. If the
+ * event is not used (i.e. posted) it must be released using
+ * ::evel_free_event.
+ * @retval NULL Failed to create the event.
+ *****************************************************************************/
+EVENT_MEASUREMENT * evel_new_measurement(double measurement_interval);
+
+/**************************************************************************//**
+ * Free a Measurement.
+ *
+ * Free off the Measurement supplied. Will free all the contained allocated
+ * memory.
+ *
+ * @note It does not free the Measurement itself, since that may be part of a
+ * larger structure.
+ *****************************************************************************/
+void evel_free_measurement(EVENT_MEASUREMENT * event);
+
+/**************************************************************************//**
+ * Set the Event Type property of the Measurement.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param measurement Pointer to the Measurement.
+ * @param type The Event Type to be set. ASCIIZ string. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_measurement_type_set(EVENT_MEASUREMENT * measurement,
+ const char * const type);
+
+/**************************************************************************//**
+ * Set the Concurrent Sessions property of the Measurement.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param measurement Pointer to the Measurement.
+ * @param concurrent_sessions The Concurrent Sessions to be set.
+ *****************************************************************************/
+void evel_measurement_conc_sess_set(EVENT_MEASUREMENT * measurement,
+ int concurrent_sessions);
+
+/**************************************************************************//**
+ * Set the Configured Entities property of the Measurement.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param measurement Pointer to the Measurement.
+ * @param configured_entities The Configured Entities to be set.
+ *****************************************************************************/
+void evel_measurement_cfg_ents_set(EVENT_MEASUREMENT * measurement,
+ int configured_entities);
+
+/**************************************************************************//**
+ * Add an additional set of Errors to the Measurement.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param measurement Pointer to the measurement.
+ * @param receive_discards The number of receive discards.
+ * @param receive_errors The number of receive errors.
+ * @param transmit_discards The number of transmit discards.
+ * @param transmit_errors The number of transmit errors.
+ *****************************************************************************/
+void evel_measurement_errors_set(EVENT_MEASUREMENT * measurement,
+ int receive_discards,
+ int receive_errors,
+ int transmit_discards,
+ int transmit_errors);
+
+/**************************************************************************//**
+ * Set the Mean Request Latency property of the Measurement.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param measurement Pointer to the Measurement.
+ * @param mean_request_latency The Mean Request Latency to be set.
+ *****************************************************************************/
+void evel_measurement_mean_req_lat_set(EVENT_MEASUREMENT * measurement,
+ double mean_request_latency);
+
+/**************************************************************************//**
+ * Set the 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,
+ int block_iops,
+ double ephemeral_configured,
+ double ephemeral_used,
+ int ephemeral_iops);
+
+/**************************************************************************//**
+ * Add a Feature usage value name/value pair to the Measurement.
+ *
+ * The name is null delimited ASCII string. The library takes
+ * a copy so the caller does not have to preserve values after the function
+ * returns.
+ *
+ * @param measurement Pointer to the measurement.
+ * @param feature ASCIIZ string with the feature's name.
+ * @param utilization Utilization of the feature.
+ *****************************************************************************/
+void evel_measurement_feature_use_add(EVENT_MEASUREMENT * measurement,
+ char * feature,
+ int utilization);
+
+/**************************************************************************//**
+ * Add a Additional Measurement value name/value pair to the Measurement.
+ *
+ * The name is null delimited ASCII string. The library takes
+ * a copy so the caller does not have to preserve values after the function
+ * returns.
+ *
+ * @param measurement Pointer to the Measurement.
+ * @param group ASCIIZ string with the measurement group's name.
+ * @param name ASCIIZ string containing the measurement's name.
+ * @param name ASCIIZ string containing the measurement's value.
+ *****************************************************************************/
+void evel_measurement_custom_measurement_add(EVENT_MEASUREMENT * measurement,
+ const char * const group,
+ const char * const name,
+ const char * const value);
+
+/**************************************************************************//**
+ * Add a Codec usage value name/value pair to the Measurement.
+ *
+ * The name is null delimited ASCII string. The library takes
+ * a copy so the caller does not have to preserve values after the function
+ * returns.
+ *
+ * @param measurement Pointer to the measurement.
+ * @param codec ASCIIZ string with the codec's name.
+ * @param utilization Utilization of the feature.
+ *****************************************************************************/
+void evel_measurement_codec_use_add(EVENT_MEASUREMENT * measurement,
+ char * codec,
+ int utilization);
+
+/**************************************************************************//**
+ * Set the 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
+ *
+ * @returns pointer to the newly manufactured ::EVENT_REPORT. If the event is
+ * not used (i.e. posted) it must be released using
+ * ::evel_free_report.
+ * @retval NULL Failed to create the event.
+ *****************************************************************************/
+EVENT_REPORT * evel_new_report(double measurement_interval);
+
+/**************************************************************************//**
+ * Free a Report.
+ *
+ * Free off the Report supplied. Will free all the contained allocated memory.
+ *
+ * @note It does not free the Report itself, since that may be part of a
+ * larger structure.
+ *****************************************************************************/
+void evel_free_report(EVENT_REPORT * event);
+
+/**************************************************************************//**
+ * Set the Event Type property of the Report.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param report Pointer to the Report.
+ * @param type The Event Type to be set. ASCIIZ string. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_report_type_set(EVENT_REPORT * report, const char * const type);
+
+/**************************************************************************//**
+ * Add a Feature usage value name/value pair to the Report.
+ *
+ * The name is null delimited ASCII string. The library takes
+ * a copy so the caller does not have to preserve values after the function
+ * returns.
+ *
+ * @param report Pointer to the report.
+ * @param feature ASCIIZ string with the feature's name.
+ * @param utilization Utilization of the feature.
+ *****************************************************************************/
+void evel_report_feature_use_add(EVENT_REPORT * report,
+ char * feature,
+ int utilization);
+
+/**************************************************************************//**
+ * Add a Additional Measurement value name/value pair to the Report.
+ *
+ * The name is null delimited ASCII string. The library takes
+ * a copy so the caller does not have to preserve values after the function
+ * returns.
+ *
+ * @param report Pointer to the report.
+ * @param group ASCIIZ string with the measurement group's name.
+ * @param name ASCIIZ string containing the measurement's name.
+ * @param value ASCIIZ string containing the measurement's value.
+ *****************************************************************************/
+void evel_report_custom_measurement_add(EVENT_REPORT * report,
+ const char * const group,
+ const char * const name,
+ const char * const value);
+
+/*****************************************************************************/
+/*****************************************************************************/
+/* */
+/* MOBILE_FLOW */
+/* */
+/*****************************************************************************/
+/*****************************************************************************/
+
+/**************************************************************************//**
+ * Create a new Mobile Flow event.
+ *
+ * @note The mandatory fields on the Mobile Flow must be supplied to this
+ * factory function and are immutable once set. Optional fields have
+ * explicit setter functions, but again values may only be set once so
+ * that the Mobile Flow has immutable properties.
+ *
+ * @param flow_direction
+ * @param gtp_per_flow_metrics
+ * @param ip_protocol_type
+ * @param ip_version
+ * @param other_endpoint_ip_address
+ * @param other_endpoint_port
+ * @param reporting_endpoint_ip_addr
+ * @param reporting_endpoint_port
+ *
+ * @returns pointer to the newly manufactured ::EVENT_MOBILE_FLOW. If the
+ * event is not used (i.e. posted) it must be released using
+ * ::evel_free_mobile_flow.
+ * @retval NULL Failed to create the event.
+ *****************************************************************************/
+EVENT_MOBILE_FLOW * evel_new_mobile_flow(
+ const char * const flow_direction,
+ MOBILE_GTP_PER_FLOW_METRICS * gtp_per_flow_metrics,
+ const char * const ip_protocol_type,
+ const char * const ip_version,
+ const char * const other_endpoint_ip_address,
+ int other_endpoint_port,
+ const char * const reporting_endpoint_ip_addr,
+ int reporting_endpoint_port);
+
+/**************************************************************************//**
+ * Free a Mobile Flow.
+ *
+ * Free off the Mobile Flow supplied. Will free all the contained allocated
+ * memory.
+ *
+ * @note It does not free the Mobile Flow itself, since that may be part of a
+ * larger structure.
+ *****************************************************************************/
+void evel_free_mobile_flow(EVENT_MOBILE_FLOW * event);
+
+/**************************************************************************//**
+ * Set the Event Type property of the Mobile Flow.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param mobile_flow Pointer to the Mobile Flow.
+ * @param type The Event Type to be set. ASCIIZ string. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_mobile_flow_type_set(EVENT_MOBILE_FLOW * mobile_flow,
+ const char * const type);
+
+/**************************************************************************//**
+ * Set the Application Type property of the Mobile Flow.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param mobile_flow Pointer to the Mobile Flow.
+ * @param type The Application Type to be set. ASCIIZ string. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_mobile_flow_app_type_set(EVENT_MOBILE_FLOW * mobile_flow,
+ const char * const type);
+
+/**************************************************************************//**
+ * Set the Application Protocol Type property of the Mobile Flow.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param mobile_flow Pointer to the Mobile Flow.
+ * @param type The Application Protocol Type to be set. ASCIIZ string.
+ * The caller does not need to preserve the value once the
+ * function returns.
+ *****************************************************************************/
+void evel_mobile_flow_app_prot_type_set(EVENT_MOBILE_FLOW * mobile_flow,
+ const char * const type);
+
+/**************************************************************************//**
+ * Set the Application Protocol Version property of the Mobile Flow.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param mobile_flow Pointer to the Mobile Flow.
+ * @param version The Application Protocol Version to be set. ASCIIZ
+ * string. The caller does not need to preserve the value
+ * once the function returns.
+ *****************************************************************************/
+void evel_mobile_flow_app_prot_ver_set(EVENT_MOBILE_FLOW * mobile_flow,
+ const char * const version);
+
+/**************************************************************************//**
+ * Set the CID property of the Mobile Flow.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param mobile_flow Pointer to the Mobile Flow.
+ * @param cid The CID to be set. ASCIIZ string. The caller does not
+ * need to preserve the value once the function returns.
+ *****************************************************************************/
+void evel_mobile_flow_cid_set(EVENT_MOBILE_FLOW * mobile_flow,
+ const char * const cid);
+
+/**************************************************************************//**
+ * Set the Connection Type property of the Mobile Flow.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param mobile_flow Pointer to the Mobile Flow.
+ * @param type The Connection Type to be set. ASCIIZ string. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_mobile_flow_con_type_set(EVENT_MOBILE_FLOW * mobile_flow,
+ const char * const type);
+
+/**************************************************************************//**
+ * Set the ECGI property of the Mobile Flow.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param mobile_flow Pointer to the Mobile Flow.
+ * @param ecgi The ECGI to be set. ASCIIZ string. The caller does not
+ * need to preserve the value once the function returns.
+ *****************************************************************************/
+void evel_mobile_flow_ecgi_set(EVENT_MOBILE_FLOW * mobile_flow,
+ const char * const ecgi);
+
+/**************************************************************************//**
+ * Set the GTP Protocol Type property of the Mobile Flow.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param mobile_flow Pointer to the Mobile Flow.
+ * @param type The GTP Protocol Type to be set. ASCIIZ string. The
+ * caller does not need to preserve the value once the
+ * function returns.
+ *****************************************************************************/
+void evel_mobile_flow_gtp_prot_type_set(EVENT_MOBILE_FLOW * mobile_flow,
+ const char * const type);
+
+/**************************************************************************//**
+ * Set the GTP Protocol Version property of the Mobile Flow.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param mobile_flow Pointer to the Mobile Flow.
+ * @param version The GTP Protocol Version to be set. ASCIIZ string. The
+ * caller does not need to preserve the value once the
+ * function returns.
+ *****************************************************************************/
+void evel_mobile_flow_gtp_prot_ver_set(EVENT_MOBILE_FLOW * mobile_flow,
+ const char * const version);
+
+/**************************************************************************//**
+ * Set the HTTP Header property of the Mobile Flow.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param mobile_flow Pointer to the Mobile Flow.
+ * @param header The HTTP header to be set. ASCIIZ string. The caller does
+ * not need to preserve the value once the function returns.
+ *****************************************************************************/
+void evel_mobile_flow_http_header_set(EVENT_MOBILE_FLOW * mobile_flow,
+ const char * const header);
+
+/**************************************************************************//**
+ * Set the IMEI property of the Mobile Flow.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param mobile_flow Pointer to the Mobile Flow.
+ * @param imei The IMEI to be set. ASCIIZ string. The caller does not
+ * need to preserve the value once the function returns.
+ *****************************************************************************/
+void evel_mobile_flow_imei_set(EVENT_MOBILE_FLOW * mobile_flow,
+ const char * const imei);
+
+/**************************************************************************//**
+ * Set the IMSI property of the Mobile Flow.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param mobile_flow Pointer to the Mobile Flow.
+ * @param imsi The IMSI to be set. ASCIIZ string. The caller does not
+ * need to preserve the value once the function returns.
+ *****************************************************************************/
+void evel_mobile_flow_imsi_set(EVENT_MOBILE_FLOW * mobile_flow,
+ const char * const imsi);
+
+/**************************************************************************//**
+ * Set the LAC property of the Mobile Flow.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param mobile_flow Pointer to the Mobile Flow.
+ * @param lac The LAC to be set. ASCIIZ string. The caller does not
+ * need to preserve the value once the function returns.
+ *****************************************************************************/
+void evel_mobile_flow_lac_set(EVENT_MOBILE_FLOW * mobile_flow,
+ const char * const lac);
+
+/**************************************************************************//**
+ * Set the MCC property of the Mobile Flow.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param mobile_flow Pointer to the Mobile Flow.
+ * @param mcc The MCC to be set. ASCIIZ string. The caller does not
+ * need to preserve the value once the function returns.
+ *****************************************************************************/
+void evel_mobile_flow_mcc_set(EVENT_MOBILE_FLOW * mobile_flow,
+ const char * const mcc);
+
+/**************************************************************************//**
+ * Set the MNC property of the Mobile Flow.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param mobile_flow Pointer to the Mobile Flow.
+ * @param mnc The MNC to be set. ASCIIZ string. The caller does not
+ * need to preserve the value once the function returns.
+ *****************************************************************************/
+void evel_mobile_flow_mnc_set(EVENT_MOBILE_FLOW * mobile_flow,
+ const char * const mnc);
+
+/**************************************************************************//**
+ * Set the MSISDN property of the Mobile Flow.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param mobile_flow Pointer to the Mobile Flow.
+ * @param msisdn The MSISDN to be set. ASCIIZ string. The caller does not
+ * need to preserve the value once the function returns.
+ *****************************************************************************/
+void evel_mobile_flow_msisdn_set(EVENT_MOBILE_FLOW * mobile_flow,
+ const char * const msisdn);
+
+/**************************************************************************//**
+ * Set the Other Functional Role property of the Mobile Flow.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param mobile_flow Pointer to the Mobile Flow.
+ * @param role The Other Functional Role to be set. ASCIIZ string. The
+ * caller does not need to preserve the value once the
+ * function returns.
+ *****************************************************************************/
+void evel_mobile_flow_other_func_role_set(EVENT_MOBILE_FLOW * mobile_flow,
+ const char * const role);
+
+/**************************************************************************//**
+ * Set the RAC property of the Mobile Flow.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param mobile_flow Pointer to the Mobile Flow.
+ * @param rac The RAC to be set. ASCIIZ string. The caller does not
+ * need to preserve the value once the function returns.
+ *****************************************************************************/
+void evel_mobile_flow_rac_set(EVENT_MOBILE_FLOW * mobile_flow,
+ const char * const rac);
+
+/**************************************************************************//**
+ * Set the Radio Access Technology property of the Mobile Flow.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param mobile_flow Pointer to the Mobile Flow.
+ * @param tech The Radio Access Technology to be set. ASCIIZ string. The
+ * caller does not need to preserve the value once the
+ * function returns.
+ *****************************************************************************/
+void evel_mobile_flow_radio_acc_tech_set(EVENT_MOBILE_FLOW * mobile_flow,
+ const char * const tech);
+
+/**************************************************************************//**
+ * Set the SAC property of the Mobile Flow.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param mobile_flow Pointer to the Mobile Flow.
+ * @param sac The SAC to be set. ASCIIZ string. The caller does not
+ * need to preserve the value once the function returns.
+ *****************************************************************************/
+void evel_mobile_flow_sac_set(EVENT_MOBILE_FLOW * mobile_flow,
+ const char * const sac);
+
+/**************************************************************************//**
+ * Set the Sampling Algorithm property of the Mobile Flow.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param mobile_flow Pointer to the Mobile Flow.
+ * @param algorithm The Sampling Algorithm to be set.
+ *****************************************************************************/
+void evel_mobile_flow_samp_alg_set(EVENT_MOBILE_FLOW * mobile_flow,
+ int algorithm);
+
+/**************************************************************************//**
+ * Set the TAC property of the Mobile Flow.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param mobile_flow Pointer to the Mobile Flow.
+ * @param tac The TAC to be set. ASCIIZ string. The caller does not
+ * need to preserve the value once the function returns.
+ *****************************************************************************/
+void evel_mobile_flow_tac_set(EVENT_MOBILE_FLOW * mobile_flow,
+ const char * const tac);
+
+/**************************************************************************//**
+ * Set the Tunnel ID property of the Mobile Flow.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param mobile_flow Pointer to the Mobile Flow.
+ * @param tunnel_id The Tunnel ID to be set. ASCIIZ string. The caller does
+ * not need to preserve the value once the function returns.
+ *****************************************************************************/
+void evel_mobile_flow_tunnel_id_set(EVENT_MOBILE_FLOW * mobile_flow,
+ const char * const tunnel_id);
+
+/**************************************************************************//**
+ * Set the VLAN ID property of the Mobile Flow.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param mobile_flow Pointer to the Mobile Flow.
+ * @param vlan_id The VLAN ID to be set. ASCIIZ string. The caller does
+ * not need to preserve the value once the function returns.
+ *****************************************************************************/
+void evel_mobile_flow_vlan_id_set(EVENT_MOBILE_FLOW * mobile_flow,
+ const char * const vlan_id);
+
+/**************************************************************************//**
+ * Create a new Mobile GTP Per Flow Metrics.
+ *
+ * @note The mandatory fields on the Mobile GTP Per Flow Metrics must be
+ * supplied to this factory function and are immutable once set.
+ * Optional fields have explicit setter functions, but again values
+ * may only be set once so that the Mobile GTP Per Flow Metrics has
+ * immutable properties.
+ *
+ * @param avg_bit_error_rate
+ * @param avg_packet_delay_variation
+ * @param avg_packet_latency
+ * @param avg_receive_throughput
+ * @param avg_transmit_throughput
+ * @param flow_activation_epoch
+ * @param flow_activation_microsec
+ * @param flow_deactivation_epoch
+ * @param flow_deactivation_microsec
+ * @param flow_deactivation_time
+ * @param flow_status
+ * @param max_packet_delay_variation
+ * @param num_activation_failures
+ * @param num_bit_errors
+ * @param num_bytes_received
+ * @param num_bytes_transmitted
+ * @param num_dropped_packets
+ * @param num_l7_bytes_received
+ * @param num_l7_bytes_transmitted
+ * @param num_lost_packets
+ * @param num_out_of_order_packets
+ * @param num_packet_errors
+ * @param num_packets_received_excl_retrans
+ * @param num_packets_received_incl_retrans
+ * @param num_packets_transmitted_incl_retrans
+ * @param num_retries
+ * @param num_timeouts
+ * @param num_tunneled_l7_bytes_received
+ * @param round_trip_time
+ * @param time_to_first_byte
+ *
+ * @returns pointer to the newly manufactured ::MOBILE_GTP_PER_FLOW_METRICS.
+ * If the structure is not used it must be released using
+ * ::evel_free_mobile_gtp_flow_metrics.
+ * @retval NULL Failed to create the event.
+ *****************************************************************************/
+MOBILE_GTP_PER_FLOW_METRICS * evel_new_mobile_gtp_flow_metrics(
+ double avg_bit_error_rate,
+ double avg_packet_delay_variation,
+ int avg_packet_latency,
+ int avg_receive_throughput,
+ int avg_transmit_throughput,
+ int flow_activation_epoch,
+ int flow_activation_microsec,
+ int flow_deactivation_epoch,
+ int flow_deactivation_microsec,
+ time_t flow_deactivation_time,
+ const char * const flow_status,
+ int max_packet_delay_variation,
+ int num_activation_failures,
+ int num_bit_errors,
+ int num_bytes_received,
+ int num_bytes_transmitted,
+ int num_dropped_packets,
+ int num_l7_bytes_received,
+ int num_l7_bytes_transmitted,
+ int num_lost_packets,
+ int num_out_of_order_packets,
+ int num_packet_errors,
+ int num_packets_received_excl_retrans,
+ int num_packets_received_incl_retrans,
+ int num_packets_transmitted_incl_retrans,
+ int num_retries,
+ int num_timeouts,
+ int num_tunneled_l7_bytes_received,
+ int round_trip_time,
+ int time_to_first_byte);
+
+/**************************************************************************//**
+ * Free a Mobile GTP Per Flow Metrics.
+ *
+ * Free off the Mobile GTP Per Flow Metrics supplied. Will free all the
+ * contained allocated memory.
+ *
+ * @note It does not free the Mobile GTP Per Flow Metrics itself, since that
+ * may be part of a larger structure.
+ *****************************************************************************/
+void evel_free_mobile_gtp_flow_metrics(MOBILE_GTP_PER_FLOW_METRICS * metrics);
+
+/**************************************************************************//**
+ * Set the Duration of Connection Failed Status property of the Mobile GTP Per
+ * Flow Metrics.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param metrics Pointer to the Mobile GTP Per Flow Metrics.
+ * @param duration The Duration of Connection Failed Status to be set.
+ *****************************************************************************/
+void evel_mobile_gtp_metrics_dur_con_fail_set(
+ MOBILE_GTP_PER_FLOW_METRICS * metrics,
+ int duration);
+
+/**************************************************************************//**
+ * Set the Duration of Tunnel Failed Status property of the Mobile GTP Per Flow
+ * Metrics.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param metrics Pointer to the Mobile GTP Per Flow Metrics.
+ * @param duration The Duration of Tunnel Failed Status to be set.
+ *****************************************************************************/
+void evel_mobile_gtp_metrics_dur_tun_fail_set(
+ MOBILE_GTP_PER_FLOW_METRICS * metrics,
+ int duration);
+
+/**************************************************************************//**
+ * Set the Activated By property of the Mobile GTP Per Flow metrics.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param metrics Pointer to the Mobile GTP Per Flow Metrics.
+ * @param act_by The Activated By to be set. ASCIIZ string. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_mobile_gtp_metrics_act_by_set(MOBILE_GTP_PER_FLOW_METRICS * metrics,
+ const char * const act_by);
+
+/**************************************************************************//**
+ * Set the Activation Time property of the Mobile GTP Per Flow metrics.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param metrics Pointer to the Mobile GTP Per Flow Metrics.
+ * @param act_time The Activation Time to be set. ASCIIZ string. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_mobile_gtp_metrics_act_time_set(
+ MOBILE_GTP_PER_FLOW_METRICS * metrics,
+ time_t act_time);
+
+/**************************************************************************//**
+ * Set the Deactivated By property of the Mobile GTP Per Flow metrics.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param metrics Pointer to the Mobile GTP Per Flow Metrics.
+ * @param deact_by The Deactivated By to be set. ASCIIZ string. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_mobile_gtp_metrics_deact_by_set(
+ MOBILE_GTP_PER_FLOW_METRICS * metrics,
+ const char * const deact_by);
+
+/**************************************************************************//**
+ * Set the GTP Connection Status property of the Mobile GTP Per Flow metrics.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param metrics Pointer to the Mobile GTP Per Flow Metrics.
+ * @param status The GTP Connection Status to be set. ASCIIZ string. The
+ * caller does not need to preserve the value once the
+ * function returns.
+ *****************************************************************************/
+void evel_mobile_gtp_metrics_con_status_set(
+ MOBILE_GTP_PER_FLOW_METRICS * metrics,
+ const char * const status);
+
+/**************************************************************************//**
+ * Set the GTP Tunnel Status property of the Mobile GTP Per Flow metrics.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param metrics Pointer to the Mobile GTP Per Flow Metrics.
+ * @param status The GTP Tunnel Status to be set. ASCIIZ string. The
+ * caller does not need to preserve the value once the
+ * function returns.
+ *****************************************************************************/
+void evel_mobile_gtp_metrics_tun_status_set(
+ MOBILE_GTP_PER_FLOW_METRICS * metrics,
+ const char * const status);
+
+/**************************************************************************//**
+ * Set an IP Type-of-Service count property of the Mobile GTP Per Flow metrics.
+ *
+ * @param metrics Pointer to the Mobile GTP Per Flow Metrics.
+ * @param index The index of the IP Type-of-Service.
+ * @param count The count.
+ *****************************************************************************/
+void evel_mobile_gtp_metrics_iptos_set(MOBILE_GTP_PER_FLOW_METRICS * metrics,
+ int index,
+ int count);
+
+/**************************************************************************//**
+ * Set the Large Packet Round-Trip Time property of the Mobile GTP Per Flow
+ * Metrics.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param metrics Pointer to the Mobile GTP Per Flow Metrics.
+ * @param rtt The Large Packet Round-Trip Time to be set.
+ *****************************************************************************/
+void evel_mobile_gtp_metrics_large_pkt_rtt_set(
+ MOBILE_GTP_PER_FLOW_METRICS * metrics,
+ int rtt);
+
+/**************************************************************************//**
+ * Set the Large Packet Threshold property of the Mobile GTP Per Flow Metrics.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param metrics Pointer to the Mobile GTP Per Flow Metrics.
+ * @param threshold The Large Packet Threshold to be set.
+ *****************************************************************************/
+void evel_mobile_gtp_metrics_large_pkt_thresh_set(
+ MOBILE_GTP_PER_FLOW_METRICS * metrics,
+ double threshold);
+
+/**************************************************************************//**
+ * Set the Max Receive Bit Rate property of the Mobile GTP Per Flow Metrics.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param metrics Pointer to the Mobile GTP Per Flow Metrics.
+ * @param rate The Max Receive Bit Rate to be set.
+ *****************************************************************************/
+void evel_mobile_gtp_metrics_max_rcv_bit_rate_set(
+ MOBILE_GTP_PER_FLOW_METRICS * metrics,
+ int rate);
+
+/**************************************************************************//**
+ * Set the Max Transmit Bit Rate property of the Mobile GTP Per Flow Metrics.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param metrics Pointer to the Mobile GTP Per Flow Metrics.
+ * @param rate The Max Transmit Bit Rate to be set.
+ *****************************************************************************/
+void evel_mobile_gtp_metrics_max_trx_bit_rate_set(
+ MOBILE_GTP_PER_FLOW_METRICS * metrics,
+ int rate);
+
+/**************************************************************************//**
+ * Set the Number of GTP Echo Failures property of the Mobile GTP Per Flow
+ * Metrics.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param metrics Pointer to the Mobile GTP Per Flow Metrics.
+ * @param num The Number of GTP Echo Failures to be set.
+ *****************************************************************************/
+void evel_mobile_gtp_metrics_num_echo_fail_set(
+ MOBILE_GTP_PER_FLOW_METRICS * metrics,
+ int num);
+
+/**************************************************************************//**
+ * Set the Number of GTP Tunnel Errors property of the Mobile GTP Per Flow
+ * Metrics.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param metrics Pointer to the Mobile GTP Per Flow Metrics.
+ * @param num The Number of GTP Tunnel Errors to be set.
+ *****************************************************************************/
+void evel_mobile_gtp_metrics_num_tun_fail_set(
+ MOBILE_GTP_PER_FLOW_METRICS * metrics,
+ int num);
+
+/**************************************************************************//**
+ * Set the Number of HTTP Errors property of the Mobile GTP Per Flow Metrics.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param metrics Pointer to the Mobile GTP Per Flow Metrics.
+ * @param num The Number of HTTP Errors to be set.
+ *****************************************************************************/
+void evel_mobile_gtp_metrics_num_http_errors_set(
+ MOBILE_GTP_PER_FLOW_METRICS * metrics,
+ int num);
+
+/**************************************************************************//**
+ * Add a TCP flag count to the metrics.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param metrics Pointer to the Mobile GTP Per Flow Metrics.
+ * @param tcp_flag The TCP flag count to be updated.
+ * @param count The associated flag count.
+ *****************************************************************************/
+void evel_mobile_gtp_metrics_tcp_flag_count_add(
+ MOBILE_GTP_PER_FLOW_METRICS * metrics,
+ const EVEL_TCP_FLAGS tcp_flag,
+ const int count);
+
+/**************************************************************************//**
+ * Add a QCI COS count to the metrics.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param metrics Pointer to the Mobile GTP Per Flow Metrics.
+ * @param qci_cos The QCI COS count to be updated.
+ * @param count The associated QCI COS count.
+ *****************************************************************************/
+void evel_mobile_gtp_metrics_qci_cos_count_add(
+ MOBILE_GTP_PER_FLOW_METRICS * metrics,
+ const EVEL_QCI_COS_TYPES qci_cos,
+ const int count);
+
+/*****************************************************************************/
+/*****************************************************************************/
+/* */
+/* SIGNALING */
+/* */
+/*****************************************************************************/
+/*****************************************************************************/
+
+/**************************************************************************//**
+ * Create a new Signaling event.
+ *
+ * @note The mandatory fields on the Signaling must be supplied to
+ * this factory function and are immutable once set. Optional fields
+ * have explicit setter functions, but again values may only be set
+ * once so that the event has immutable properties.
+ * @param vendor_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 * 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 new_state The new state of the reporting entity.
+ * @param old_state The old state of the reporting entity.
+ * @param interface The card or port name of the reporting entity.
+ *
+ * @returns pointer to the newly manufactured ::EVENT_STATE_CHANGE. If the
+ * event is not used it must be released using
+ * ::evel_free_state_change
+ * @retval NULL Failed to create the event.
+ *****************************************************************************/
+EVENT_STATE_CHANGE * evel_new_state_change(const EVEL_ENTITY_STATE new_state,
+ const EVEL_ENTITY_STATE old_state,
+ const char * const interface);
+
+/**************************************************************************//**
+ * Free a State Change.
+ *
+ * Free off the State Change supplied. Will free all the contained allocated
+ * memory.
+ *
+ * @note It does not free the State Change itself, since that may be part of a
+ * larger structure.
+ *****************************************************************************/
+void evel_free_state_change(EVENT_STATE_CHANGE * const state_change);
+
+/**************************************************************************//**
+ * Set the Event Type property of the State Change.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param state_change Pointer to the ::EVENT_STATE_CHANGE.
+ * @param type The Event Type to be set. ASCIIZ string. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_state_change_type_set(EVENT_STATE_CHANGE * const state_change,
+ const char * const type);
+
+/**************************************************************************//**
+ * Add an additional field name/value pair to the State Change.
+ *
+ * The name and value are null delimited ASCII strings. The library takes
+ * a copy so the caller does not have to preserve values after the function
+ * returns.
+ *
+ * @param state_change Pointer to the ::EVENT_STATE_CHANGE.
+ * @param name ASCIIZ string with the attribute's name. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ * @param value ASCIIZ string with the attribute's value. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_state_change_addl_field_add(EVENT_STATE_CHANGE * const state_change,
+ const char * const name,
+ const char * const value);
+
+/*****************************************************************************/
+/*****************************************************************************/
+/* */
+/* SYSLOG */
+/* */
+/*****************************************************************************/
+/*****************************************************************************/
+
+/**************************************************************************//**
+ * Create a new syslog event.
+ *
+ * @note The mandatory fields on the Syslog must be supplied to this factory
+ * function and are immutable once set. Optional fields have explicit
+ * setter functions, but again values may only be set once so that the
+ * Syslog has immutable properties.
+ *
+ * @param event_source_type
+ * @param syslog_msg
+ * @param syslog_tag
+ * @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(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.
+ *
+ *
+ * @returns pointer to the newly manufactured ::EVENT_OTHER. If the event is
+ * not used it must be released using ::evel_free_other.
+ * @retval NULL Failed to create the event.
+ *****************************************************************************/
+EVENT_OTHER * evel_new_other(void);
+
+/**************************************************************************//**
+ * Free an Other.
+ *
+ * Free off the Other supplied. Will free all the contained allocated memory.
+ *
+ * @note It does not free the Other itself, since that may be part of a
+ * larger structure.
+ *****************************************************************************/
+void evel_free_other(EVENT_OTHER * event);
+
+/**************************************************************************//**
+ * Set the Event Type property of the Other.
+ *
+ * @note The property is treated as immutable: it is only valid to call
+ * the setter once. However, we don't assert if the caller tries to
+ * overwrite, just ignoring the update instead.
+ *
+ * @param other Pointer to the Other.
+ * @param type The Event Type to be set. ASCIIZ string. The caller
+ * does not need to preserve the value once the function
+ * returns.
+ *****************************************************************************/
+void evel_other_type_set(EVENT_OTHER * other,
+ const char * const type);
+
+/**************************************************************************//**
+ * Add a value name/value pair to the Other.
+ *
+ * The name and value are null delimited ASCII strings. The library takes
+ * a copy so the caller does not have to preserve values after the function
+ * returns.
+ *
+ * @param other Pointer to the Other.
+ * @param name ASCIIZ string with the attribute's name.
+ * @param value ASCIIZ string with the attribute's value.
+ *****************************************************************************/
+void evel_other_field_add(EVENT_OTHER * other,
+ char * name,
+ char * value);
+
+/*****************************************************************************/
+/*****************************************************************************/
+/* */
+/* THROTTLING */
+/* */
+/*****************************************************************************/
+/*****************************************************************************/
+
+/**************************************************************************//**
+ * Return the current measurement interval provided by the Event Listener.
+ *
+ * @returns The current measurement interval
+ * @retval EVEL_MEASUREMENT_INTERVAL_UKNOWN (0) - interval has not been
+ * specified
+ *****************************************************************************/
+int evel_get_measurement_interval();
+
+/*****************************************************************************/
+/* Supported Report version. */
+/*****************************************************************************/
+#define EVEL_VOICEQ_MAJOR_VERSION 1
+#define EVEL_VOICEQ_MINOR_VERSION 1
+
+/**************************************************************************//**
+* 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;
+
+ /***************************************************************************/
+ /* Optional fields */
+ /***************************************************************************/
+ EVEL_OPTION_STRING phoneNumber;
+ DLIST additionalInformation;
+ DLIST endOfCallVqmSummaries;
+
+} EVENT_VOICE_QUALITY;
+
+/**************************************************************************//**
+ * 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 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 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 * 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);
+
+
+/*****************************************************************************/
+/*****************************************************************************/
+/* */
+/* 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/VES5.0/evel/evel-library/code/evel_library/evel_event.c b/VES5.0/evel/evel-library/code/evel_library/evel_event.c
new file mode 100644
index 00000000..9fbf3926
--- /dev/null
+++ b/VES5.0/evel/evel-library/code/evel_library/evel_event.c
@@ -0,0 +1,671 @@
+/**************************************************************************//**
+ * @file
+ * Implementation of EVEL functions relating to Event Headers - since
+ * Heartbeats only contain the Event Header, the Heartbeat factory function is
+ * here too.
+ *
+ * License
+ * -------
+ *
+ * Copyright(c) <2016>, AT&T Intellectual Property. All other rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement: This product includes
+ * software developed by the AT&T.
+ * 4. Neither the name of AT&T nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <sys/time.h>
+
+#include "evel.h"
+#include "evel_internal.h"
+#include "evel_throttle.h"
+#include "metadata.h"
+
+/**************************************************************************//**
+ * Unique sequence number for events from this VNF.
+ *****************************************************************************/
+static int event_sequence = 1;
+
+/**************************************************************************//**
+ * Set the next event_sequence to use.
+ *
+ * @param sequence The next sequence number to use.
+ *****************************************************************************/
+void evel_set_next_event_sequence(const int sequence)
+{
+ EVEL_ENTER();
+
+ EVEL_INFO("Setting event sequence to %d, was %d ", sequence, event_sequence);
+ event_sequence = sequence;
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Create a new heartbeat event.
+ *
+ * @note that the heartbeat is just a "naked" commonEventHeader!
+ *
+ * @returns pointer to the newly manufactured ::EVENT_HEADER. If the event is
+ * not used it must be released using ::evel_free_event
+ * @retval NULL Failed to create the event.
+ *****************************************************************************/
+EVENT_HEADER * evel_new_heartbeat()
+{
+ EVENT_HEADER * heartbeat = NULL;
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Allocate the header. */
+ /***************************************************************************/
+ heartbeat = malloc(sizeof(EVENT_HEADER));
+ if (heartbeat == NULL)
+ {
+ log_error_state("Out of memory");
+ goto exit_label;
+ }
+ memset(heartbeat, 0, sizeof(EVENT_HEADER));
+
+ /***************************************************************************/
+ /* Initialize the header. Get a new event sequence number. Note that if */
+ /* any memory allocation fails in here we will fail gracefully because */
+ /* everything downstream can cope with NULLs. */
+ /***************************************************************************/
+ evel_init_header(heartbeat,"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();
+}
+
+/**************************************************************************//**
+ * 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_other(jbuf, (EVENT_VOICE_QUALITY *)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, "vendorVnfNamedFields");
+
+ /***************************************************************************/
+ /* 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/VES5.0/evel/evel-library/code/evel_library/evel_event_mgr.c b/VES5.0/evel/evel-library/code/evel_library/evel_event_mgr.c
new file mode 100644
index 00000000..0cc049f5
--- /dev/null
+++ b/VES5.0/evel/evel-library/code/evel_library/evel_event_mgr.c
@@ -0,0 +1,1053 @@
+/**************************************************************************//**
+ * @file
+ * Event Manager
+ *
+ * Simple event manager that is responsible for taking events (Heartbeats,
+ * Faults and Measurements) from the ring-buffer and posting them to the API.
+ *
+ * License
+ * -------
+ *
+ * Copyright(c) <2016>, AT&T Intellectual Property. All other rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement: This product includes
+ * software developed by the AT&T.
+ * 4. Neither the name of AT&T nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*****************************************************************************/
+
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <pthread.h>
+
+#include <curl/curl.h>
+
+#include "evel.h"
+#include "evel_internal.h"
+#include "ring_buffer.h"
+#include "evel_throttle.h"
+
+/**************************************************************************//**
+ * How long we're prepared to wait for the API service to respond in
+ * seconds.
+ *****************************************************************************/
+static const int EVEL_API_TIMEOUT = 5;
+
+/*****************************************************************************/
+/* Prototypes of locally scoped functions. */
+/*****************************************************************************/
+static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *userp);
+static void * event_handler(void *arg);
+static bool evel_handle_response_tokens(const MEMORY_CHUNK * const chunk,
+ const jsmntok_t * const json_tokens,
+ const int num_tokens,
+ MEMORY_CHUNK * const post);
+static bool evel_tokens_match_command_list(const MEMORY_CHUNK * const chunk,
+ const jsmntok_t * const json_token,
+ const int num_tokens);
+static bool evel_token_equals_string(const MEMORY_CHUNK * const chunk,
+ const jsmntok_t * const json_token,
+ const char * check_string);
+
+/**************************************************************************//**
+ * Buffers for error strings from libcurl.
+ *****************************************************************************/
+static char curl_err_string[CURL_ERROR_SIZE] = "<NULL>";
+
+/**************************************************************************//**
+ * Handle for the API into libcurl.
+ *****************************************************************************/
+static CURL * curl_handle = NULL;
+
+/**************************************************************************//**
+ * Special headers that we send.
+ *****************************************************************************/
+static struct curl_slist * hdr_chunk = NULL;
+
+/**************************************************************************//**
+ * Message queue for sending events to the API.
+ *****************************************************************************/
+static ring_buffer event_buffer;
+
+/**************************************************************************//**
+ * Single pending priority post, which can be generated as a result of a
+ * response to an event. Currently only used to respond to a commandList.
+ *****************************************************************************/
+static MEMORY_CHUNK priority_post;
+
+/**************************************************************************//**
+ * The thread which is responsible for handling events off of the ring-buffer
+ * and posting them to the Event Handler API.
+ *****************************************************************************/
+static pthread_t evt_handler_thread;
+
+/**************************************************************************//**
+ * Variable to convey to the event handler thread what the foreground wants it
+ * to do.
+ *****************************************************************************/
+static EVT_HANDLER_STATE evt_handler_state = EVT_HANDLER_UNINITIALIZED;
+
+/**************************************************************************//**
+ * The configured API URL for event and throttling.
+ *****************************************************************************/
+static char * evel_event_api_url;
+static char * evel_throt_api_url;
+
+/**************************************************************************//**
+ * Initialize the event handler.
+ *
+ * Primarily responsible for getting CURL ready for use.
+ *
+ * @param[in] event_api_url
+ * The URL where the Vendor Event Listener API is expected
+ * to be.
+ * @param[in] throt_api_url
+ * The URL where the Throttling API is expected to be.
+ * @param[in] username The username for the Basic Authentication of requests.
+ * @param[in] password The password for the Basic Authentication of requests.
+ * @param verbosity 0 for normal operation, positive values for chattier
+ * logs.
+ *****************************************************************************/
+EVEL_ERR_CODES event_handler_initialize(const char * const event_api_url,
+ const char * const throt_api_url,
+ const char * const username,
+ const char * const password,
+ int verbosity)
+{
+ int rc = EVEL_SUCCESS;
+ CURLcode curl_rc = CURLE_OK;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check assumptions. */
+ /***************************************************************************/
+ assert(event_api_url != NULL);
+ assert(throt_api_url != NULL);
+ assert(username != NULL);
+ assert(password != NULL);
+
+ /***************************************************************************/
+ /* Store the API URLs. */
+ /***************************************************************************/
+ evel_event_api_url = strdup(event_api_url);
+ assert(evel_event_api_url != NULL);
+ evel_throt_api_url = strdup(throt_api_url);
+ assert(evel_throt_api_url != NULL);
+
+ /***************************************************************************/
+ /* Start the CURL library. Note that this initialization is not threadsafe */
+ /* which imposes a constraint that the EVEL library is initialized before */
+ /* any threads are started. */
+ /***************************************************************************/
+ curl_rc = curl_global_init(CURL_GLOBAL_SSL);
+ if (curl_rc != CURLE_OK)
+ {
+ rc = EVEL_CURL_LIBRARY_FAIL;
+ log_error_state("Failed to initialize libCURL. Error code=%d", curl_rc);
+ goto exit_label;
+ }
+
+ /***************************************************************************/
+ /* Get a curl handle which we'll use for all of our output. */
+ /***************************************************************************/
+ curl_handle = curl_easy_init();
+ if (curl_handle == NULL)
+ {
+ rc = EVEL_CURL_LIBRARY_FAIL;
+ log_error_state("Failed to get libCURL handle");
+ goto exit_label;
+ }
+
+ /***************************************************************************/
+ /* Prime the library to give friendly error codes. */
+ /***************************************************************************/
+ curl_rc = curl_easy_setopt(curl_handle,
+ CURLOPT_ERRORBUFFER,
+ curl_err_string);
+ if (curl_rc != CURLE_OK)
+ {
+ rc = EVEL_CURL_LIBRARY_FAIL;
+ log_error_state("Failed to initialize libCURL to provide friendly errors. "
+ "Error code=%d", curl_rc);
+ goto exit_label;
+ }
+
+ /***************************************************************************/
+ /* If running in verbose mode generate more output. */
+ /***************************************************************************/
+ if (verbosity > 0)
+ {
+ curl_rc = curl_easy_setopt(curl_handle, CURLOPT_VERBOSE, 1L);
+ if (curl_rc != CURLE_OK)
+ {
+ rc = EVEL_CURL_LIBRARY_FAIL;
+ log_error_state("Failed to initialize libCURL to be verbose. "
+ "Error code=%d", curl_rc);
+ goto exit_label;
+ }
+ }
+
+ /***************************************************************************/
+ /* Set the URL for the API. */
+ /***************************************************************************/
+ curl_rc = curl_easy_setopt(curl_handle, CURLOPT_URL, event_api_url);
+ if (curl_rc != CURLE_OK)
+ {
+ rc = EVEL_CURL_LIBRARY_FAIL;
+ log_error_state("Failed to initialize libCURL with the API URL. "
+ "Error code=%d (%s)", curl_rc, curl_err_string);
+ goto exit_label;
+ }
+ EVEL_INFO("Initializing CURL to send events to: %s", event_api_url);
+
+ /***************************************************************************/
+ /* send all data to this function. */
+ /***************************************************************************/
+ curl_rc = curl_easy_setopt(curl_handle,
+ CURLOPT_WRITEFUNCTION,
+ evel_write_callback);
+ if (curl_rc != CURLE_OK)
+ {
+ rc = EVEL_CURL_LIBRARY_FAIL;
+ log_error_state("Failed to initialize libCURL with the write callback. "
+ "Error code=%d (%s)", curl_rc, curl_err_string);
+ goto exit_label;
+ }
+
+ /***************************************************************************/
+ /* some servers don't like requests that are made without a user-agent */
+ /* field, so we provide one. */
+ /***************************************************************************/
+ curl_rc = curl_easy_setopt(curl_handle,
+ CURLOPT_USERAGENT,
+ "libcurl-agent/1.0");
+ if (curl_rc != CURLE_OK)
+ {
+ rc = EVEL_CURL_LIBRARY_FAIL;
+ log_error_state("Failed to initialize libCURL to upload. "
+ "Error code=%d (%s)", curl_rc, curl_err_string);
+ goto exit_label;
+ }
+
+ /***************************************************************************/
+ /* Specify that we are going to POST data. */
+ /***************************************************************************/
+ curl_rc = curl_easy_setopt(curl_handle, CURLOPT_POST, 1L);
+ if (curl_rc != CURLE_OK)
+ {
+ rc = EVEL_CURL_LIBRARY_FAIL;
+ log_error_state("Failed to initialize libCURL to upload. "
+ "Error code=%d (%s)", curl_rc, curl_err_string);
+ goto exit_label;
+ }
+
+ /***************************************************************************/
+ /* we want to use our own read function. */
+ /***************************************************************************/
+ curl_rc = curl_easy_setopt(curl_handle, CURLOPT_READFUNCTION, read_callback);
+ if (curl_rc != CURLE_OK)
+ {
+ rc = EVEL_CURL_LIBRARY_FAIL;
+ log_error_state("Failed to initialize libCURL to upload using read "
+ "function. Error code=%d (%s)", curl_rc, curl_err_string);
+ goto exit_label;
+ }
+
+ /***************************************************************************/
+ /* All of our events are JSON encoded. We also suppress the */
+ /* Expect: 100-continue header that we would otherwise get since it */
+ /* confuses some servers. */
+ /* */
+ /* @TODO: do AT&T want this behavior? */
+ /***************************************************************************/
+ hdr_chunk = curl_slist_append(hdr_chunk, "Content-type: application/json");
+ hdr_chunk = curl_slist_append(hdr_chunk, "Expect:");
+
+ /***************************************************************************/
+ /* set our custom set of headers. */
+ /***************************************************************************/
+ curl_rc = curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, hdr_chunk);
+ if (curl_rc != CURLE_OK)
+ {
+ rc = EVEL_CURL_LIBRARY_FAIL;
+ log_error_state("Failed to initialize libCURL to use custom headers. "
+ "Error code=%d (%s)", curl_rc, curl_err_string);
+ goto exit_label;
+ }
+
+ /***************************************************************************/
+ /* Set the timeout for the operation. */
+ /***************************************************************************/
+ curl_rc = curl_easy_setopt(curl_handle,
+ CURLOPT_TIMEOUT,
+ EVEL_API_TIMEOUT);
+ if (curl_rc != CURLE_OK)
+ {
+ rc = EVEL_CURL_LIBRARY_FAIL;
+ log_error_state("Failed to initialize libCURL for API timeout. "
+ "Error code=%d (%s)", curl_rc, curl_err_string);
+ goto exit_label;
+ }
+
+ /***************************************************************************/
+ /* Set that we want Basic authentication with username:password Base-64 */
+ /* encoded for the operation. */
+ /***************************************************************************/
+ curl_rc = curl_easy_setopt(curl_handle, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
+ if (curl_rc != CURLE_OK)
+ {
+ rc = EVEL_CURL_LIBRARY_FAIL;
+ log_error_state("Failed to initialize libCURL for Basic Authentication. "
+ "Error code=%d (%s)", curl_rc, curl_err_string);
+ goto exit_label;
+ }
+ curl_rc = curl_easy_setopt(curl_handle, CURLOPT_USERNAME, username);
+ if (curl_rc != CURLE_OK)
+ {
+ rc = EVEL_CURL_LIBRARY_FAIL;
+ log_error_state("Failed to initialize libCURL with username. "
+ "Error code=%d (%s)", curl_rc, curl_err_string);
+ goto exit_label;
+ }
+ curl_rc = curl_easy_setopt(curl_handle, CURLOPT_PASSWORD, password);
+ if (curl_rc != CURLE_OK)
+ {
+ rc = EVEL_CURL_LIBRARY_FAIL;
+ log_error_state("Failed to initialize libCURL with password. "
+ "Error code=%d (%s)", curl_rc, curl_err_string);
+ goto exit_label;
+ }
+
+ /***************************************************************************/
+ /* Initialize a message ring-buffer to be used between the foreground and */
+ /* the thread which sends the messages. This can't fail. */
+ /***************************************************************************/
+ ring_buffer_initialize(&event_buffer, EVEL_EVENT_BUFFER_DEPTH);
+
+ /***************************************************************************/
+ /* Initialize the priority post buffer to empty. */
+ /***************************************************************************/
+ priority_post.memory = NULL;
+
+exit_label:
+ EVEL_EXIT();
+
+ return(rc);
+}
+
+/**************************************************************************//**
+ * Run the event handler.
+ *
+ * Spawns the thread responsible for handling events and sending them to the
+ * API.
+ *
+ * @return Status code.
+ * @retval ::EVEL_SUCCESS if everything OK.
+ * @retval One of ::EVEL_ERR_CODES if there was a problem.
+ *****************************************************************************/
+EVEL_ERR_CODES event_handler_run()
+{
+ EVEL_ERR_CODES rc = EVEL_SUCCESS;
+ int pthread_rc = 0;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Start the event handler thread. */
+ /***************************************************************************/
+ evt_handler_state = EVT_HANDLER_INACTIVE;
+ pthread_rc = pthread_create(&evt_handler_thread, NULL, event_handler, NULL);
+ if (pthread_rc != 0)
+ {
+ rc = EVEL_PTHREAD_LIBRARY_FAIL;
+ log_error_state("Failed to start event handler thread. "
+ "Error code=%d", pthread_rc);
+ }
+
+ EVEL_EXIT()
+ return rc;
+}
+
+/**************************************************************************//**
+ * Terminate the event handler.
+ *
+ * Shuts down the event handler thread in as clean a way as possible. Sets the
+ * global exit flag and then signals the thread to interrupt it since it's
+ * most likely waiting on the ring-buffer.
+ *
+ * Having achieved an orderly shutdown of the event handler thread, clean up
+ * the cURL library's resources cleanly.
+ *
+ * @return Status code.
+ * @retval ::EVEL_SUCCESS if everything OK.
+ * @retval One of ::EVEL_ERR_CODES if there was a problem.
+ *****************************************************************************/
+EVEL_ERR_CODES event_handler_terminate()
+{
+ EVEL_ERR_CODES rc = EVEL_SUCCESS;
+
+ EVEL_ENTER();
+ EVENT_INTERNAL *event = NULL;
+
+ /***************************************************************************/
+ /* Make sure that we were initialized before trying to terminate the */
+ /* event handler thread. */
+ /***************************************************************************/
+ if (evt_handler_state != EVT_HANDLER_UNINITIALIZED)
+ {
+ /*************************************************************************/
+ /* Make sure that the event handler knows it's time to die. */
+ /*************************************************************************/
+ event = evel_new_internal_event(EVT_CMD_TERMINATE);
+ if (event == NULL)
+ {
+ /***********************************************************************/
+ /* We failed to get an event, but we don't bail out - we will just */
+ /* clean up what we can and continue on our way, since we're exiting */
+ /* anyway. */
+ /***********************************************************************/
+ EVEL_ERROR("Failed to get internal event - perform dirty exit instead!");
+ }
+ else
+ {
+ /***********************************************************************/
+ /* Post the event then wait for the Event Handler to exit. Set the */
+ /* global command, too, in case the ring-buffer is full. */
+ /***********************************************************************/
+ EVEL_DEBUG("Sending event to Event Hander to request it to exit.");
+ evt_handler_state = EVT_HANDLER_REQUEST_TERMINATE;
+ evel_post_event((EVENT_HEADER *) event);
+ pthread_join(evt_handler_thread, NULL);
+ EVEL_DEBUG("Event Handler thread has exited.");
+ }
+ }
+ else
+ {
+ EVEL_DEBUG("Event handler was not initialized, so no need to kill it");
+ }
+
+ /***************************************************************************/
+ /* Clean-up the cURL library. */
+ /***************************************************************************/
+ if (curl_handle != NULL)
+ {
+ curl_easy_cleanup(curl_handle);
+ curl_handle = NULL;
+ }
+ if (hdr_chunk != NULL)
+ {
+ curl_slist_free_all(hdr_chunk);
+ hdr_chunk = NULL;
+ }
+
+ /***************************************************************************/
+ /* Free off the stored API URL strings. */
+ /***************************************************************************/
+ if (evel_event_api_url != NULL)
+ {
+ free(evel_event_api_url);
+ evel_event_api_url = NULL;
+ }
+ if (evel_throt_api_url != NULL)
+ {
+ free(evel_throt_api_url);
+ evel_throt_api_url = NULL;
+ }
+
+ EVEL_EXIT();
+ return rc;
+}
+
+/**************************************************************************//**
+ * Post an event.
+ *
+ * @note So far as the caller is concerned, successfully posting the event
+ * relinquishes all responsibility for the event - the library will take care
+ * of freeing the event in due course.
+
+ * @param event The event to be posted.
+ *
+ * @returns Status code
+ * @retval EVEL_SUCCESS On success
+ * @retval "One of ::EVEL_ERR_CODES" On failure.
+ *****************************************************************************/
+EVEL_ERR_CODES evel_post_event(EVENT_HEADER * event)
+{
+ int rc = EVEL_SUCCESS;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(event != NULL);
+
+ /***************************************************************************/
+ /* We need to make sure that we are either initializing or running */
+ /* normally before writing the event into the buffer so that we can */
+ /* guarantee that the ring-buffer empties properly on exit. */
+ /***************************************************************************/
+ if ((evt_handler_state == EVT_HANDLER_ACTIVE) ||
+ (evt_handler_state == EVT_HANDLER_INACTIVE) ||
+ (evt_handler_state == EVT_HANDLER_REQUEST_TERMINATE))
+ {
+ if (ring_buffer_write(&event_buffer, event) == 0)
+ {
+ log_error_state("Failed to write event to buffer - event dropped!");
+ rc = EVEL_EVENT_BUFFER_FULL;
+ evel_free_event(event);
+ }
+ }
+ else
+ {
+ /*************************************************************************/
+ /* System is not in active operation, so reject the event. */
+ /*************************************************************************/
+ log_error_state("Event Handler system not active - event dropped!");
+ rc = EVEL_EVENT_HANDLER_INACTIVE;
+ evel_free_event(event);
+ }
+
+ EVEL_EXIT();
+ return (rc);
+}
+
+/**************************************************************************//**
+ * Post an event to the Vendor Event Listener API.
+ *
+ * @returns Status code
+ * @retval EVEL_SUCCESS On success
+ * @retval "One of ::EVEL_ERR_CODES" On failure.
+ *****************************************************************************/
+static EVEL_ERR_CODES evel_post_api(char * msg, size_t size)
+{
+ int rc = EVEL_SUCCESS;
+ CURLcode curl_rc = CURLE_OK;
+ MEMORY_CHUNK rx_chunk;
+ MEMORY_CHUNK tx_chunk;
+ int http_response_code = 0;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Create the memory chunk to be used for the response to the post. The */
+ /* will be realloced. */
+ /***************************************************************************/
+ rx_chunk.memory = malloc(1);
+ assert(rx_chunk.memory != NULL);
+ rx_chunk.size = 0;
+
+ /***************************************************************************/
+ /* Create the memory chunk to be sent as the body of the post. */
+ /***************************************************************************/
+ tx_chunk.memory = msg;
+ tx_chunk.size = size;
+ EVEL_DEBUG("Sending chunk of size %d", tx_chunk.size);
+
+ /***************************************************************************/
+ /* Point to the data to be received. */
+ /***************************************************************************/
+ curl_rc = curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, &rx_chunk);
+ if (curl_rc != CURLE_OK)
+ {
+ rc = EVEL_CURL_LIBRARY_FAIL;
+ log_error_state("Failed to initialize libCURL to upload. "
+ "Error code=%d (%s)", curl_rc, curl_err_string);
+ goto exit_label;
+ }
+ EVEL_DEBUG("Initialized data to receive");
+
+ /***************************************************************************/
+ /* Pointer to pass to our read function */
+ /***************************************************************************/
+ curl_rc = curl_easy_setopt(curl_handle, CURLOPT_READDATA, &tx_chunk);
+ if (curl_rc != CURLE_OK)
+ {
+ rc = EVEL_CURL_LIBRARY_FAIL;
+ log_error_state("Failed to set upload data for libCURL to upload. "
+ "Error code=%d (%s)", curl_rc, curl_err_string);
+ goto exit_label;
+ }
+ EVEL_DEBUG("Initialized data to send");
+
+ /***************************************************************************/
+ /* Size of the data to transmit. */
+ /***************************************************************************/
+ curl_rc = curl_easy_setopt(curl_handle,
+ CURLOPT_POSTFIELDSIZE,
+ tx_chunk.size);
+ if (curl_rc != CURLE_OK)
+ {
+ rc = EVEL_CURL_LIBRARY_FAIL;
+ log_error_state("Failed to set length of upload data for libCURL to "
+ "upload. Error code=%d (%s)", curl_rc, curl_err_string);
+ goto exit_label;
+ }
+ EVEL_DEBUG("Initialized length of data to send");
+
+ /***************************************************************************/
+ /* Now run off and do what you've been told! */
+ /***************************************************************************/
+ curl_rc = curl_easy_perform(curl_handle);
+ if (curl_rc != CURLE_OK)
+ {
+ rc = EVEL_CURL_LIBRARY_FAIL;
+ log_error_state("Failed to transfer an event to Vendor Event Listener! "
+ "Error code=%d (%s)", curl_rc, curl_err_string);
+ EVEL_ERROR("Dropped event: %s", msg);
+ goto exit_label;
+ }
+
+ /***************************************************************************/
+ /* See what response we got - any 2XX response is good. */
+ /***************************************************************************/
+ curl_easy_getinfo(curl_handle, CURLINFO_RESPONSE_CODE, &http_response_code);
+ EVEL_DEBUG("HTTP response code: %d", http_response_code);
+ if ((http_response_code / 100) == 2)
+ {
+ /*************************************************************************/
+ /* If the server responded with data it may be interesting but not a */
+ /* problem. */
+ /*************************************************************************/
+ if ((rx_chunk.size > 0) && (rx_chunk.memory != NULL))
+ {
+ EVEL_DEBUG("Server returned data = %d (%s)",
+ rx_chunk.size,
+ rx_chunk.memory);
+
+ /***********************************************************************/
+ /* If this is a response to priority post, then we're not interested. */
+ /***********************************************************************/
+ if (priority_post.memory != NULL)
+ {
+ EVEL_ERROR("Ignoring priority post response");
+ }
+ else
+ {
+ evel_handle_event_response(&rx_chunk, &priority_post);
+ }
+ }
+ }
+ else
+ {
+ EVEL_ERROR("Unexpected HTTP response code: %d with data size %d (%s)",
+ http_response_code,
+ rx_chunk.size,
+ rx_chunk.size > 0 ? rx_chunk.memory : "NONE");
+ EVEL_ERROR("Potentially dropped event: %s", msg);
+ }
+
+exit_label:
+ free(rx_chunk.memory);
+ EVEL_EXIT();
+ return(rc);
+}
+
+/**************************************************************************//**
+ * Callback function to provide data to send.
+ *
+ * Copy data into the supplied buffer, read_callback::ptr, checking size
+ * limits.
+ *
+ * @returns Number of bytes placed into read_callback::ptr. 0 for EOF.
+ *****************************************************************************/
+static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *userp)
+{
+ size_t rtn = 0;
+ size_t bytes_to_write = 0;
+ MEMORY_CHUNK *tx_chunk = (MEMORY_CHUNK *)userp;
+
+ EVEL_ENTER();
+
+ bytes_to_write = min(size*nmemb, tx_chunk->size);
+
+ if (bytes_to_write > 0)
+ {
+ EVEL_DEBUG("Going to try to write %d bytes", bytes_to_write);
+ strncpy((char *)ptr, tx_chunk->memory, bytes_to_write);
+ tx_chunk->memory += bytes_to_write;
+ tx_chunk->size -= bytes_to_write;
+ rtn = bytes_to_write;
+ }
+ else
+ {
+ EVEL_DEBUG("Reached EOF");
+ }
+
+ EVEL_EXIT();
+ return rtn;
+}
+
+/**************************************************************************//**
+ * Callback function to provide returned data.
+ *
+ * Copy data into the supplied buffer, write_callback::ptr, checking size
+ * limits.
+ *
+ * @returns Number of bytes placed into write_callback::ptr. 0 for EOF.
+ *****************************************************************************/
+size_t evel_write_callback(void *contents,
+ size_t size,
+ size_t nmemb,
+ void *userp)
+{
+ size_t realsize = size * nmemb;
+ MEMORY_CHUNK * rx_chunk = (MEMORY_CHUNK *)userp;
+
+ EVEL_ENTER();
+
+ EVEL_DEBUG("Called with %d chunks of %d size = %d", nmemb, size, realsize);
+ EVEL_DEBUG("rx chunk size is %d", rx_chunk->size);
+
+ rx_chunk->memory = realloc(rx_chunk->memory, rx_chunk->size + realsize + 1);
+ if(rx_chunk->memory == NULL) {
+ /* out of memory! */
+ printf("not enough memory (realloc returned NULL)\n");
+ return 0;
+ }
+
+ memcpy(&(rx_chunk->memory[rx_chunk->size]), contents, realsize);
+ rx_chunk->size += realsize;
+ rx_chunk->memory[rx_chunk->size] = 0;
+
+ EVEL_DEBUG("Rx data: %s", rx_chunk->memory);
+ EVEL_DEBUG("Returning: %d", realsize);
+
+ EVEL_EXIT();
+ return realsize;
+}
+
+/**************************************************************************//**
+ * Event Handler.
+ *
+ * Watch for messages coming on the internal queue and send them to the
+ * listener.
+ *
+ * param[in] arg Argument - unused.
+ *****************************************************************************/
+static void * event_handler(void * arg __attribute__ ((unused)))
+{
+ int old_type = 0;
+ EVENT_HEADER * msg = NULL;
+ EVENT_INTERNAL * internal_msg = NULL;
+ int json_size = 0;
+ char json_body[EVEL_MAX_JSON_BODY];
+ int rc = EVEL_SUCCESS;
+ CURLcode curl_rc;
+
+ EVEL_INFO("Event handler thread started");
+
+ /***************************************************************************/
+ /* Set this thread to be cancellable immediately. */
+ /***************************************************************************/
+ pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &old_type);
+
+ /***************************************************************************/
+ /* Set the handler as active, defending against weird situations like */
+ /* immediately shutting down after initializing the library so the */
+ /* handler never gets started up properly. */
+ /***************************************************************************/
+ if (evt_handler_state == EVT_HANDLER_INACTIVE)
+ {
+ evt_handler_state = EVT_HANDLER_ACTIVE;
+ }
+ else
+ {
+ EVEL_ERROR("Event Handler State was not INACTIVE at start-up - "
+ "Handler will exit immediately!");
+ }
+
+ while (evt_handler_state == EVT_HANDLER_ACTIVE)
+ {
+ /*************************************************************************/
+ /* Wait for a message to be received. */
+ /*************************************************************************/
+ EVEL_DEBUG("Event handler getting any messages");
+ msg = ring_buffer_read(&event_buffer);
+
+ /*************************************************************************/
+ /* Internal events get special treatment while regular events get posted */
+ /* to the far side. */
+ /*************************************************************************/
+ if (msg->event_domain != EVEL_DOMAIN_INTERNAL)
+ {
+ EVEL_DEBUG("External event received");
+
+ /***********************************************************************/
+ /* Encode the event in JSON. */
+ /***********************************************************************/
+ json_size = evel_json_encode_event(json_body, EVEL_MAX_JSON_BODY, msg);
+
+ /***********************************************************************/
+ /* Send the JSON across the API. */
+ /***********************************************************************/
+ EVEL_DEBUG("Sending JSON of size %d is: %s", json_size, json_body);
+ rc = evel_post_api(json_body, json_size);
+ if (rc != EVEL_SUCCESS)
+ {
+ EVEL_ERROR("Failed to transfer the data. Error code=%d", rc);
+ }
+ }
+ else
+ {
+ EVEL_DEBUG("Internal event received");
+ internal_msg = (EVENT_INTERNAL *) msg;
+ assert(internal_msg->command == EVT_CMD_TERMINATE);
+ evt_handler_state = EVT_HANDLER_TERMINATING;
+ }
+
+ /*************************************************************************/
+ /* We are responsible for freeing the memory. */
+ /*************************************************************************/
+ evel_free_event(msg);
+ msg = NULL;
+
+ /*************************************************************************/
+ /* There may be a single priority post to be sent. */
+ /*************************************************************************/
+ if (priority_post.memory != NULL)
+ {
+ EVEL_DEBUG("Priority Post");
+
+ /***********************************************************************/
+ /* Set the URL for the throttling API. */
+ /***********************************************************************/
+ curl_rc = curl_easy_setopt(curl_handle, CURLOPT_URL, evel_throt_api_url);
+ if (curl_rc != CURLE_OK)
+ {
+ /*********************************************************************/
+ /* This is only likely to happen with CURLE_OUT_OF_MEMORY, in which */
+ /* case we carry on regardless. */
+ /*********************************************************************/
+ EVEL_ERROR("Failed to set throttling URL. Error code=%d", rc);
+ }
+ else
+ {
+ rc = evel_post_api(priority_post.memory, priority_post.size);
+ if (rc != EVEL_SUCCESS)
+ {
+ EVEL_ERROR("Failed to transfer priority post. Error code=%d", rc);
+ }
+ }
+
+ /***********************************************************************/
+ /* Reinstate the URL for the event API. */
+ /***********************************************************************/
+ curl_rc = curl_easy_setopt(curl_handle, CURLOPT_URL, evel_event_api_url);
+ if (curl_rc != CURLE_OK)
+ {
+ /*********************************************************************/
+ /* This is only likely to happen with CURLE_OUT_OF_MEMORY, in which */
+ /* case we carry on regardless. */
+ /*********************************************************************/
+ EVEL_ERROR("Failed to reinstate events URL. Error code=%d", rc);
+ }
+
+ /***********************************************************************/
+ /* We are responsible for freeing the memory. */
+ /***********************************************************************/
+ free(priority_post.memory);
+ priority_post.memory = NULL;
+ }
+ }
+
+ /***************************************************************************/
+ /* The event handler is now exiting. The ring-buffer could contain events */
+ /* which have not been processed, so deplete those. Because we've been */
+ /* asked to exit we can be confident that the foreground will have stopped */
+ /* sending events in so we know that this process will conclude! */
+ /***************************************************************************/
+ evt_handler_state = EVT_HANDLER_TERMINATING;
+ while (!ring_buffer_is_empty(&event_buffer))
+ {
+ EVEL_DEBUG("Reading event from buffer");
+ msg = ring_buffer_read(&event_buffer);
+ evel_free_event(msg);
+ }
+ evt_handler_state = EVT_HANDLER_TERMINATED;
+ EVEL_INFO("Event handler thread stopped");
+
+ return (NULL);
+}
+
+/**************************************************************************//**
+ * Handle a JSON response from the listener, contained in a ::MEMORY_CHUNK.
+ *
+ * Tokenize the response, and decode any tokens found.
+ *
+ * @param chunk The memory chunk containing the response.
+ * @param post The memory chunk in which to place any resulting POST.
+ *****************************************************************************/
+void evel_handle_event_response(const MEMORY_CHUNK * const chunk,
+ MEMORY_CHUNK * const post)
+{
+ jsmn_parser json_parser;
+ jsmntok_t json_tokens[EVEL_MAX_RESPONSE_TOKENS];
+ int num_tokens = 0;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(chunk != NULL);
+ assert(priority_post.memory == NULL);
+
+ EVEL_DEBUG("Response size = %d", chunk->size);
+ EVEL_DEBUG("Response = %s", chunk->memory);
+
+ /***************************************************************************/
+ /* Initialize the parser and tokenize the response. */
+ /***************************************************************************/
+ jsmn_init(&json_parser);
+ num_tokens = jsmn_parse(&json_parser,
+ chunk->memory,
+ chunk->size,
+ json_tokens,
+ EVEL_MAX_RESPONSE_TOKENS);
+
+ if (num_tokens < 0)
+ {
+ EVEL_ERROR("Failed to parse JSON response. "
+ "Error code=%d", num_tokens);
+ }
+ else if (num_tokens == 0)
+ {
+ EVEL_DEBUG("No tokens found in JSON response");
+ }
+ else
+ {
+ EVEL_DEBUG("Decode JSON response tokens");
+ if (!evel_handle_response_tokens(chunk, json_tokens, num_tokens, post))
+ {
+ EVEL_ERROR("Failed to handle JSON response.");
+ }
+ }
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Handle a JSON response from the listener, as a list of tokens from JSMN.
+ *
+ * @param chunk Memory chunk containing the JSON buffer.
+ * @param json_tokens Array of tokens to handle.
+ * @param num_tokens The number of tokens to handle.
+ * @param post The memory chunk in which to place any resulting POST.
+ * @return true if we handled the response, false otherwise.
+ *****************************************************************************/
+bool evel_handle_response_tokens(const MEMORY_CHUNK * const chunk,
+ const jsmntok_t * const json_tokens,
+ const int num_tokens,
+ MEMORY_CHUNK * const post)
+{
+ bool json_ok = false;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(chunk != NULL);
+ assert(json_tokens != NULL);
+ assert(num_tokens < EVEL_MAX_RESPONSE_TOKENS);
+
+ /***************************************************************************/
+ /* Peek at the tokens to decide what the response it, then call the */
+ /* appropriate handler to handle it. There is only one handler at this */
+ /* point. */
+ /***************************************************************************/
+ if (evel_tokens_match_command_list(chunk, json_tokens, num_tokens))
+ {
+ json_ok = evel_handle_command_list(chunk, json_tokens, num_tokens, post);
+ }
+
+ EVEL_EXIT();
+
+ return json_ok;
+}
+
+/**************************************************************************//**
+ * Determine whether a list of tokens looks like a "commandList" response.
+ *
+ * @param chunk Memory chunk containing the JSON buffer.
+ * @param json_tokens Token to check.
+ * @param num_tokens The number of tokens to handle.
+ * @return true if the tokens look like a "commandList" match, or false.
+ *****************************************************************************/
+bool evel_tokens_match_command_list(const MEMORY_CHUNK * const chunk,
+ const jsmntok_t * const json_tokens,
+ const int num_tokens)
+{
+ bool result = false;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Make some checks on the basic layout of the commandList. */
+ /***************************************************************************/
+ if ((num_tokens > 3) &&
+ (json_tokens[0].type == JSMN_OBJECT) &&
+ (json_tokens[1].type == JSMN_STRING) &&
+ (json_tokens[2].type == JSMN_ARRAY) &&
+ (evel_token_equals_string(chunk, &json_tokens[1], "commandList")))
+ {
+ result = true;
+ }
+
+ EVEL_EXIT();
+
+ return result;
+}
+
+/**************************************************************************//**
+ * Check that a string token matches a given input string.
+ *
+ * @param chunk Memory chunk containing the JSON buffer.
+ * @param json_token Token to check.
+ * @param check_string String to check it against.
+ * @return true if the strings match, or false.
+ *****************************************************************************/
+bool evel_token_equals_string(const MEMORY_CHUNK * const chunk,
+ const jsmntok_t * json_token,
+ const char * check_string)
+{
+ bool result = false;
+
+ EVEL_ENTER();
+
+ const int token_length = json_token->end - json_token->start;
+ const char * const token_string = chunk->memory + json_token->start;
+
+ if (token_length == (int)strlen(check_string))
+ {
+ result = (strncmp(token_string, check_string, token_length) == 0);
+ }
+
+ EVEL_EXIT();
+
+ return result;
+}
diff --git a/VES5.0/evel/evel-library/code/evel_library/evel_fault.c b/VES5.0/evel/evel-library/code/evel_library/evel_fault.c
new file mode 100644
index 00000000..ddf6c0e6
--- /dev/null
+++ b/VES5.0/evel/evel-library/code/evel_library/evel_fault.c
@@ -0,0 +1,376 @@
+/**************************************************************************//**
+ * @file
+ * Implementation of EVEL functions relating to the Fault.
+ *
+ * License
+ * -------
+ *
+ * Copyright(c) <2016>, AT&T Intellectual Property. All other rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement: This product includes
+ * software developed by the AT&T.
+ * 4. Neither the name of AT&T nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+
+#include "evel.h"
+#include "evel_internal.h"
+#include "evel_throttle.h"
+
+/**************************************************************************//**
+ * Create a new fault event.
+ *
+ * @note The mandatory fields on the Fault must be supplied to this factory
+ * function and are immutable once set. Optional fields have explicit
+ * setter functions, but again values may only be set once so that the
+ * Fault has immutable properties.
+ * @param condition The condition indicated by the Fault.
+ * @param specific_problem The specific problem triggering the fault.
+ * @param priority The priority of the event.
+ * @param severity The severity of the Fault.
+ * @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 * 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(&fault->header,"Fault");
+ 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/VES5.0/evel/evel-library/code/evel_library/evel_heartbeat_fields.c b/VES5.0/evel/evel-library/code/evel_library/evel_heartbeat_fields.c
new file mode 100644
index 00000000..b1131449
--- /dev/null
+++ b/VES5.0/evel/evel-library/code/evel_library/evel_heartbeat_fields.c
@@ -0,0 +1,278 @@
+/**************************************************************************//**
+ * @file
+ * Implementation of EVEL functions relating to Heartbeat fields.
+ *
+ * License
+ * -------
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement: This product includes
+ * software developed by the AT&T.
+ * 4. Neither the name of AT&T nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+
+#include "evel.h"
+#include "evel_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 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)
+{
+ 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(&event->header,"HeartbeatFields");
+ 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/VES5.0/evel/evel-library/code/evel_library/evel_internal.h b/VES5.0/evel/evel-library/code/evel_library/evel_internal.h
new file mode 100644
index 00000000..2da246b3
--- /dev/null
+++ b/VES5.0/evel/evel-library/code/evel_library/evel_internal.h
@@ -0,0 +1,872 @@
+#ifndef EVEL_INTERNAL_INCLUDED
+#define EVEL_INTERNAL_INCLUDED
+
+/**************************************************************************//**
+ * @file
+ * EVEL internal definitions.
+ *
+ * These are internal definitions which need to be shared between modules
+ * within the library but are not intended for external consumption.
+ *
+ * License
+ * -------
+ *
+ * Copyright(c) <2016>, AT&T Intellectual Property. All other rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement: This product includes
+ * software developed by the AT&T.
+ * 4. Neither the name of AT&T nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#include "evel.h"
+
+/*****************************************************************************/
+/* Define some type-safe min/max macros. */
+/*****************************************************************************/
+#define max(a,b) \
+ ({ __typeof__ (a) _a = (a); \
+ __typeof__ (b) _b = (b); \
+ _a > _b ? _a : _b; })
+
+#define min(a,b) \
+ ({ __typeof__ (a) _a = (a); \
+ __typeof__ (b) _b = (b); \
+ _a < _b ? _a : _b; })
+
+
+/**************************************************************************//**
+ * Compile-time assertion.
+ *****************************************************************************/
+#define EVEL_CT_ASSERT(X) switch (0) {case 0: case (X):;}
+
+/**************************************************************************//**
+ * The Functional Role of the equipment represented by this VNF.
+ *****************************************************************************/
+extern char * functional_role;
+
+/**************************************************************************//**
+ * The type of equipment represented by this VNF.
+ *****************************************************************************/
+extern EVEL_SOURCE_TYPES event_source_type;
+
+/**************************************************************************//**
+ * A chunk of memory used in the cURL functions.
+ *****************************************************************************/
+typedef struct memory_chunk {
+ char * memory;
+ size_t size;
+} MEMORY_CHUNK;
+
+/**************************************************************************//**
+ * Global commands that may be sent to the Event Handler thread.
+ *****************************************************************************/
+typedef enum {
+ EVT_CMD_TERMINATE,
+ EVT_CMD_MAX_COMMANDS
+} EVT_HANDLER_COMMAND;
+
+/**************************************************************************//**
+ * State of the Event Handler thread.
+ *****************************************************************************/
+typedef enum {
+ EVT_HANDLER_UNINITIALIZED, /** The library cannot handle events. */
+ EVT_HANDLER_INACTIVE, /** The event handler thread not started. */
+ EVT_HANDLER_ACTIVE, /** The event handler thread is started. */
+ EVT_HANDLER_REQUEST_TERMINATE, /** Initial stages of shutdown. */
+ EVT_HANDLER_TERMINATING, /** The ring-buffer is being depleted. */
+ EVT_HANDLER_TERMINATED, /** The library is exited. */
+ EVT_HANDLER_MAX_STATES /** Maximum number of valid states. */
+} EVT_HANDLER_STATE;
+
+/**************************************************************************//**
+ * Internal event.
+ * Pseudo-event used for routing internal commands.
+ *****************************************************************************/
+typedef struct event_internal {
+ EVENT_HEADER header;
+ EVT_HANDLER_COMMAND command;
+} EVENT_INTERNAL;
+
+/**************************************************************************//**
+ * Suppressed NV pairs list entry.
+ * JSON equivalent field: suppressedNvPairs
+ *****************************************************************************/
+typedef struct evel_suppressed_nv_pairs {
+
+ /***************************************************************************/
+ /* Mandatory fields */
+ /* JSON equivalent field: nvPairFieldName */
+ /***************************************************************************/
+ char * nv_pair_field_name;
+
+ /***************************************************************************/
+ /* Optional fields */
+ /* JSON equivalent field: suppressedNvPairNames */
+ /* Type of each list entry: char * */
+ /***************************************************************************/
+ DLIST suppressed_nv_pair_names;
+
+ /***************************************************************************/
+ /* Hash table containing suppressed_nv_pair_names as keys. */
+ /***************************************************************************/
+ struct hsearch_data * hash_nv_pair_names;
+
+} EVEL_SUPPRESSED_NV_PAIRS;
+
+/**************************************************************************//**
+ * Event Throttling Specification for a domain which is in a throttled state.
+ * JSON equivalent object: eventThrottlingState
+ *****************************************************************************/
+typedef struct evel_throttle_spec {
+
+ /***************************************************************************/
+ /* List of field names to be suppressed. */
+ /* JSON equivalent field: suppressedFieldNames */
+ /* Type of each list entry: char * */
+ /***************************************************************************/
+ DLIST suppressed_field_names;
+
+ /***************************************************************************/
+ /* List of name-value pairs to be suppressed. */
+ /* JSON equivalent field: suppressedNvPairsList */
+ /* Type of each list entry: EVEL_SUPPRESSED_NV_PAIRS * */
+ /***************************************************************************/
+ DLIST suppressed_nv_pairs_list;
+
+ /***************************************************************************/
+ /* Hash table containing suppressed_nv_pair_names as keys. */
+ /***************************************************************************/
+ struct hsearch_data * hash_field_names;
+
+ /***************************************************************************/
+ /* Hash table containing nv_pair_field_name as keys, and */
+ /* suppressed_nv_pairs_list as values. */
+ /***************************************************************************/
+ struct hsearch_data * hash_nv_pairs_list;
+
+} EVEL_THROTTLE_SPEC;
+
+/*****************************************************************************/
+/* RFC2822 format string for strftime. */
+/*****************************************************************************/
+#define EVEL_RFC2822_STRFTIME_FORMAT "%a, %d %b %Y %T %z"
+
+/*****************************************************************************/
+/* EVEL_JSON_BUFFER depth at which we throttle fields. */
+/*****************************************************************************/
+#define EVEL_THROTTLE_FIELD_DEPTH 3
+
+/**************************************************************************//**
+ * Initialize the event handler.
+ *
+ * Primarily responsible for getting cURL ready for use.
+ *
+ * @param[in] event_api_url
+ * The URL where the Vendor Event Listener API is expected
+ * to be.
+ * @param[in] throt_api_url
+ * The URL where the Throttling API is expected to be.
+ * @param[in] username The username for the Basic Authentication of requests.
+ * @param[in] password The password for the Basic Authentication of requests.
+ * @param verbosity 0 for normal operation, positive values for chattier
+ * logs.
+ *****************************************************************************/
+EVEL_ERR_CODES event_handler_initialize(const char * const event_api_url,
+ const char * const throt_api_url,
+ const char * const username,
+ const char * const password,
+ int verbosity);
+
+/**************************************************************************//**
+ * Terminate the event handler.
+ *
+ * Shuts down the event handler thread in as clean a way as possible. Sets the
+ * global exit flag and then signals the thread to interrupt it since it's
+ * most likely waiting on the ring-buffer.
+ *
+ * Having achieved an orderly shutdown of the event handler thread, clean up
+ * the cURL library's resources cleanly.
+ *
+ * @return Status code.
+ * @retval ::EVEL_SUCCESS if everything OK.
+ * @retval One of ::EVEL_ERR_CODES if there was a problem.
+ *****************************************************************************/
+EVEL_ERR_CODES event_handler_terminate();
+
+/**************************************************************************//**
+ * Run the event handler.
+ *
+ * Spawns the thread responsible for handling events and sending them to the
+ * API.
+ *
+ * @return Status code.
+ * @retval ::EVEL_SUCCESS if everything OK.
+ * @retval One of ::EVEL_ERR_CODES if there was a problem.
+ *****************************************************************************/
+EVEL_ERR_CODES event_handler_run();
+
+/**************************************************************************//**
+ * Create a new internal event.
+ *
+ * @note The mandatory fields on the Fault must be supplied to this factory
+ * function and are immutable once set. Optional fields have explicit
+ * setter functions, but again values may only be set once so that the
+ * Fault has immutable properties.
+ * @param command The condition indicated by the event.
+ * @returns pointer to the newly manufactured ::EVENT_INTERNAL. If the event
+ * is not used (i.e. posted) it must be released using
+ * ::evel_free_event.
+ * @retval NULL Failed to create the event.
+ *****************************************************************************/
+EVENT_INTERNAL * evel_new_internal_event(EVT_HANDLER_COMMAND command);
+
+/**************************************************************************//**
+ * Free an internal event.
+ *
+ * Free off the event supplied. Will free all the contained* allocated memory.
+ *
+ * @note It does not free the internal event itself, since that may be part of
+ * a larger structure.
+ *****************************************************************************/
+void evel_free_internal_event(EVENT_INTERNAL * event);
+
+/*****************************************************************************/
+/* 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/VES5.0/evel/evel-library/code/evel_library/evel_internal_event.c b/VES5.0/evel/evel-library/code/evel_library/evel_internal_event.c
new file mode 100644
index 00000000..8fe15733
--- /dev/null
+++ b/VES5.0/evel/evel-library/code/evel_library/evel_internal_event.c
@@ -0,0 +1,124 @@
+/**************************************************************************//**
+ * @file
+ * Implementation of EVEL functions relating to the internal events.
+ *
+ * Internal events are never expected to be sent to the JSON API but comply
+ * with interfaces for regular event types. The primary use-case is to enable
+ * the foreground processing to communicate with the background event handling
+ * processing in an orderly fashion. At present the only use is to initiate an
+ * orderly shutdown of the Event Handler thread.
+ *
+ * License
+ * -------
+ *
+ * Copyright(c) <2016>, AT&T Intellectual Property. All other rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement: This product includes
+ * software developed by the AT&T.
+ * 4. Neither the name of AT&T nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+
+#include "evel.h"
+#include "evel_internal.h"
+
+
+/**************************************************************************//**
+ * Create a new internal event.
+ *
+ * @note The mandatory fields on the Fault must be supplied to this factory
+ * function and are immutable once set. Optional fields have explicit
+ * setter functions, but again values may only be set once so that the
+ * Fault has immutable properties.
+ * @param command The condition indicated by the event.
+ * @returns pointer to the newly manufactured ::EVENT_INTERNAL. If the event
+ * is not used (i.e. posted) it must be released using
+ * ::evel_free_event.
+ * @retval NULL Failed to create the event.
+ *****************************************************************************/
+EVENT_INTERNAL * evel_new_internal_event(EVT_HANDLER_COMMAND command)
+{
+ EVENT_INTERNAL * event = NULL;
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(command < EVT_CMD_MAX_COMMANDS);
+
+ /***************************************************************************/
+ /* Allocate the fault. */
+ /***************************************************************************/
+ event = malloc(sizeof(EVENT_INTERNAL));
+ if (event == NULL)
+ {
+ log_error_state("Out of memory");
+ goto exit_label;
+ }
+ memset(event, 0, sizeof(EVENT_INTERNAL));
+ EVEL_DEBUG("New internal event is at %lp", event);
+
+ /***************************************************************************/
+ /* Initialize the header & the event fields. */
+ /***************************************************************************/
+ evel_init_header(&event->header,NULL);
+ 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/VES5.0/evel/evel-library/code/evel_library/evel_json_buffer.c b/VES5.0/evel/evel-library/code/evel_library/evel_json_buffer.c
new file mode 100644
index 00000000..e0e119da
--- /dev/null
+++ b/VES5.0/evel/evel-library/code/evel_library/evel_json_buffer.c
@@ -0,0 +1,883 @@
+/**************************************************************************//**
+ * @file
+ * Source module relating to internal EVEL_JSON_BUFFER manipulation functions.
+ *
+ * License
+ * -------
+ *
+ * Copyright(c) <2016>, AT&T Intellectual Property. All other rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement: This product includes
+ * software developed by the AT&T.
+ * 4. Neither the name of AT&T nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#include <assert.h>
+#include <string.h>
+
+#include "evel_throttle.h"
+
+/*****************************************************************************/
+/* Local prototypes. */
+/*****************************************************************************/
+static char * evel_json_kv_comma(EVEL_JSON_BUFFER * jbuf);
+
+/**************************************************************************//**
+ * Initialize a ::EVEL_JSON_BUFFER.
+ *
+ * @param jbuf Pointer to the ::EVEL_JSON_BUFFER to initialise.
+ * @param json Pointer to the underlying working buffer to use.
+ * @param max_size Size of storage available in the JSON buffer.
+ * @param throttle_spec Pointer to throttle specification. Can be NULL.
+ *****************************************************************************/
+void evel_json_buffer_init(EVEL_JSON_BUFFER * jbuf,
+ char * const json,
+ const int max_size,
+ EVEL_THROTTLE_SPEC * throttle_spec)
+{
+ EVEL_ENTER();
+
+ assert(jbuf != NULL);
+ assert(json != NULL);
+ jbuf->json = json;
+ jbuf->max_size = max_size;
+ jbuf->offset = 0;
+ jbuf->throttle_spec = throttle_spec;
+ jbuf->depth = 0;
+ jbuf->checkpoint = -1;
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Encode an integer value to a JSON buffer.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ * @param value The integer to add to it.
+ *****************************************************************************/
+void evel_enc_int(EVEL_JSON_BUFFER * jbuf,
+ const int value)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(jbuf != NULL);
+
+ jbuf->offset += snprintf(jbuf->json + jbuf->offset,
+ jbuf->max_size - jbuf->offset,
+ "%d", value);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Encode a string key and string value to a ::EVEL_JSON_BUFFER.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ * @param key Pointer to the key to encode.
+ * @param option Pointer to holder of the corresponding value to encode.
+ * @return true if the key, value was added, false if it was suppressed.
+ *****************************************************************************/
+bool evel_enc_kv_opt_string(EVEL_JSON_BUFFER * jbuf,
+ const char * const key,
+ const EVEL_OPTION_STRING * const option)
+{
+ bool added = false;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(option != NULL);
+
+ if (option->is_set)
+ {
+ if ((jbuf->depth == EVEL_THROTTLE_FIELD_DEPTH) &&
+ (jbuf->throttle_spec != NULL) &&
+ evel_throttle_suppress_field(jbuf->throttle_spec, key))
+ {
+ EVEL_INFO("Suppressed: %s, %s", key, option->value);
+ }
+ else
+ {
+ EVEL_DEBUG("Encoded: %s, %s", key, option->value);
+ evel_enc_kv_string(jbuf, key, option->value);
+ added = true;
+ }
+ }
+
+ EVEL_EXIT();
+
+ return added;
+}
+
+/**************************************************************************//**
+ * Encode a string key and string value to a ::EVEL_JSON_BUFFER.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ * @param key Pointer to the key to encode.
+ * @param value Pointer to the corresponding value to encode.
+ *****************************************************************************/
+void evel_enc_kv_string(EVEL_JSON_BUFFER * jbuf,
+ const char * const key,
+ const char * const value)
+{
+ int index;
+ int length;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(jbuf != NULL);
+ assert(key != NULL);
+
+ jbuf->offset += snprintf(jbuf->json + jbuf->offset,
+ jbuf->max_size - jbuf->offset,
+ "%s\"%s\": \"",
+ evel_json_kv_comma(jbuf),
+ key);
+
+ /***************************************************************************/
+ /* We need to escape quotation marks and backslashes in the value. */
+ /***************************************************************************/
+ length = strlen(value);
+
+ for (index = 0; index < length; index++)
+ {
+ /*************************************************************************/
+ /* Drop out if no more space. */
+ /*************************************************************************/
+ if (jbuf->max_size - jbuf->offset < 2)
+ {
+ break;
+ }
+
+ /*************************************************************************/
+ /* Add an escape character if necessary, then write the character */
+ /* itself. */
+ /*************************************************************************/
+ if ((value[index] == '\"') || (value[index] == '\\'))
+ {
+ jbuf->json[jbuf->offset] = '\\';
+ jbuf->offset++;
+ }
+
+ jbuf->json[jbuf->offset] = value[index];
+ jbuf->offset++;
+ }
+
+ jbuf->offset += snprintf(jbuf->json + jbuf->offset,
+ jbuf->max_size - jbuf->offset,
+ "\"");
+
+ EVEL_EXIT();
+}
+
+
+/**************************************************************************//**
+ * Encode a string key and integer value to a ::EVEL_JSON_BUFFER.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ * @param key Pointer to the key to encode.
+ * @param option Pointer to holder of the corresponding value to encode.
+ * @return true if the key, value was added, false if it was suppressed.
+ *****************************************************************************/
+bool evel_enc_kv_opt_int(EVEL_JSON_BUFFER * jbuf,
+ const char * const key,
+ const EVEL_OPTION_INT * const option)
+{
+ bool added = false;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(option != NULL);
+
+ if (option->is_set)
+ {
+ if ((jbuf->depth == EVEL_THROTTLE_FIELD_DEPTH) &&
+ (jbuf->throttle_spec != NULL) &&
+ evel_throttle_suppress_field(jbuf->throttle_spec, key))
+ {
+ EVEL_INFO("Suppressed: %s, %d", key, option->value);
+ }
+ else
+ {
+ EVEL_DEBUG("Encoded: %s, %d", key, option->value);
+ evel_enc_kv_int(jbuf, key, option->value);
+ added = true;
+ }
+ }
+
+ EVEL_EXIT();
+
+ return added;
+}
+
+/**************************************************************************//**
+ * Encode a string key and integer value to a ::EVEL_JSON_BUFFER.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ * @param key Pointer to the key to encode.
+ * @param value The corresponding value to encode.
+ *****************************************************************************/
+void evel_enc_kv_int(EVEL_JSON_BUFFER * jbuf,
+ const char * const key,
+ const int value)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(jbuf != NULL);
+ assert(key != NULL);
+
+ jbuf->offset += snprintf(jbuf->json + jbuf->offset,
+ jbuf->max_size - jbuf->offset,
+ "%s\"%s\": %d",
+ evel_json_kv_comma(jbuf),
+ key,
+ value);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Encode a string key and 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/VES5.0/evel/evel-library/code/evel_library/evel_jsonobject.c b/VES5.0/evel/evel-library/code/evel_library/evel_jsonobject.c
new file mode 100644
index 00000000..65f5226e
--- /dev/null
+++ b/VES5.0/evel/evel-library/code/evel_library/evel_jsonobject.c
@@ -0,0 +1,459 @@
+/**************************************************************************//**
+ * @file
+ * Implementation of EVEL functions relating to json_object.
+ *
+ * License
+ * -------
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement: This product includes
+ * software developed by the AT&T.
+ * 4. Neither the name of AT&T nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+
+#include "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;
+ unsigned int length;
+ char *keyString = 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/VES5.0/evel/evel-library/code/evel_library/evel_logging.c b/VES5.0/evel/evel-library/code/evel_library/evel_logging.c
new file mode 100644
index 00000000..6dabc638
--- /dev/null
+++ b/VES5.0/evel/evel-library/code/evel_library/evel_logging.c
@@ -0,0 +1,181 @@
+/**************************************************************************//**
+ * @file
+ * Wrapper for event logging built on syslog.
+ *
+ * License
+ * -------
+ *
+ * Copyright(c) <2016>, AT&T Intellectual Property. All other rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement: This product includes
+ * software developed by the AT&T.
+ * 4. Neither the name of AT&T nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#include <string.h>
+#include <assert.h>
+#include <syslog.h>
+#include <stdlib.h>
+#include <sys/time.h>
+
+#include <curl/curl.h>
+
+#include "evel.h"
+
+
+/*****************************************************************************/
+/* Debug settings. Logging is done through macros so these need to be */
+/* externally visible. */
+/*****************************************************************************/
+EVEL_LOG_LEVELS debug_level = EVEL_LOG_DEBUG;
+//static char *syslog_ident = "evel";
+int debug_indent = 0;
+
+/*****************************************************************************/
+/* Buffers for error strings from this library. */
+/*****************************************************************************/
+static char evel_err_string[EVEL_MAX_ERROR_STRING_LEN] = "<NULL>";
+
+
+/**************************************************************************//**
+ * Initialize logging
+ *
+ * @param[in] level The debugging level - one of ::EVEL_LOG_LEVELS.
+ * @param[in] ident The identifier for our logs.
+ *****************************************************************************/
+void log_initialize(EVEL_LOG_LEVELS level, const char * ident)
+{
+ assert(level < EVEL_LOG_MAX);
+ assert(ident != NULL);
+
+ debug_level = level;
+ openlog(ident, LOG_PID, LOG_USER);
+}
+
+/**************************************************************************//**
+ * Descriptive text for library errors.
+ *
+ * Return a text error string that relates to the last failure. May be
+ * "<null>" but will never be NULL.
+ *
+ * @returns Text error string.
+ *
+ * @note Must not be freed!
+ *****************************************************************************/
+const char * evel_error_string(void)
+{
+ return(evel_err_string);
+}
+
+/***************************************************************************//*
+ * Store the formatted string into the static error string and log the error.
+ *
+ * @param format Error string in standard printf format.
+ * @param ... Variable parameters to be substituted into the format string.
+ *****************************************************************************/
+void log_error_state(char * format, ...)
+{
+ va_list largs;
+
+ assert(format != NULL);
+ va_start(largs, format);
+ vsnprintf(evel_err_string, EVEL_MAX_ERROR_STRING_LEN, format, largs);
+ va_end(largs);
+ EVEL_ERROR("%s", evel_err_string);
+}
+
+
+/**************************************************************************//**
+ * Generate a debug log.
+ *
+ * Provides an interface to syslog with formatting of the nesting level
+ * so that it's easier to see function entry/exit.
+ *
+ * @param[in] level The debug level - see ::EVEL_LOG_LEVELS.
+ * @param[in] format The output formatting in printf style.
+ * @param[in] ... Variable arguments as specified in the format string.
+ *****************************************************************************/
+void log_debug(EVEL_LOG_LEVELS level, char * format, ...)
+{
+ va_list largs;
+ int priority;
+ char indent_fmt[1024];
+ char *syslog_fmt = NULL;
+
+ /***************************************************************************/
+ /* Test assumptions. */
+ /***************************************************************************/
+ assert(format != NULL);
+ assert(level <= EVEL_LOG_MAX);
+
+ if (level >= debug_level)
+ {
+ if ((debug_level == EVEL_LOG_INFO) || (debug_indent == 0))
+ {
+ /***********************************************************************/
+ /* Just use the format as is. */
+ /***********************************************************************/
+ syslog_fmt = format;
+ }
+ else
+ {
+ /***********************************************************************/
+ /* Combine the format with a preceding number of indent markers. */
+ /***********************************************************************/
+ sprintf(indent_fmt, "%.*s%s",
+ debug_indent,
+ INDENT_SEPARATORS,
+ format);
+ syslog_fmt = indent_fmt;
+ }
+
+ /*************************************************************************/
+ /* Work out the syslog priority value. */
+ /*************************************************************************/
+ switch (level)
+ {
+ case EVEL_LOG_ERROR:
+ priority = LOG_ERR;
+ break;
+
+ case EVEL_LOG_INFO:
+ priority = LOG_INFO;
+ break;
+
+ case EVEL_LOG_DEBUG:
+ case EVEL_LOG_SPAMMY:
+ default:
+ priority = LOG_DEBUG;
+ break;
+ }
+
+ /*************************************************************************/
+ /* Write the log to the file next, which requires the var args list. */
+ /*************************************************************************/
+ va_start(largs, format);
+ vsyslog(priority, syslog_fmt, largs);
+ va_end(largs);
+ }
+} \ No newline at end of file
diff --git a/VES5.0/evel/evel-library/code/evel_library/evel_mobile_flow.c b/VES5.0/evel/evel-library/code/evel_library/evel_mobile_flow.c
new file mode 100644
index 00000000..1d4adb2e
--- /dev/null
+++ b/VES5.0/evel/evel-library/code/evel_library/evel_mobile_flow.c
@@ -0,0 +1,2132 @@
+/**************************************************************************//**
+ * @file
+ * Implementation of EVEL functions relating to the Mobile Flow.
+ *
+ * License
+ * -------
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement: This product includes
+ * software developed by the AT&T.
+ * 4. Neither the name of AT&T nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <time.h>
+
+#include "evel.h"
+#include "evel_internal.h"
+
+/*****************************************************************************/
+/* Array of strings to use when encoding TCP flags. */
+/*****************************************************************************/
+static char * evel_tcp_flag_strings[EVEL_MAX_TCP_FLAGS] = {
+ "NS",
+ "CWR",
+ "ECE",
+ "URG",
+ "ACK",
+ "PSH",
+ "RST",
+ "SYN",
+ "FIN"
+};
+
+/*****************************************************************************/
+/* Array of strings to use when encoding QCI COS. */
+/*****************************************************************************/
+static char * evel_qci_cos_strings[EVEL_MAX_QCI_COS_TYPES] = {
+ "conversational",
+ "streaming",
+ "interactive",
+ "background",
+ "1",
+ "2",
+ "3",
+ "4",
+ "65",
+ "66",
+ "5",
+ "6",
+ "7",
+ "8",
+ "9",
+ "69",
+ "70"
+};
+
+/*****************************************************************************/
+/* Local prototypes */
+/*****************************************************************************/
+void evel_json_encode_mobile_flow_gtp_flow_metrics(
+ EVEL_JSON_BUFFER * jbuf,
+ MOBILE_GTP_PER_FLOW_METRICS * metrics);
+
+/**************************************************************************//**
+ * Create a new Mobile Flow event.
+ *
+ * @note The mandatory fields on the Mobile Flow must be supplied to this
+ * factory function and are immutable once set. Optional fields have
+ * explicit setter functions, but again values may only be set once so
+ * that the Mobile Flow has immutable properties.
+ * @param flow_direction Flow direction.
+ * @param gtp_per_flow_metrics GTP per-flow metrics.
+ * @param ip_protocol_type IP protocol type.
+ * @param ip_version IP protocol version.
+ * @param other_endpoint_ip_address IP address of the other endpoint.
+ * @param other_endpoint_port IP port of the other endpoint.
+ * @param reporting_endpoint_ip_addr IP address of the reporting endpoint.
+ * @param reporting_endpoint_port IP port of the reporting endpoint.
+ * @returns pointer to the newly manufactured ::EVENT_MOBILE_FLOW. If the
+ * event is not used (i.e. posted) it must be released using
+ * ::evel_free_mobile_flow.
+ * @retval NULL Failed to create the event.
+ *****************************************************************************/
+EVENT_MOBILE_FLOW * evel_new_mobile_flow(
+ const char * const flow_direction,
+ MOBILE_GTP_PER_FLOW_METRICS * gtp_per_flow_metrics,
+ const char * const ip_protocol_type,
+ const char * const ip_version,
+ const char * const other_endpoint_ip_address,
+ int other_endpoint_port,
+ const char * const reporting_endpoint_ip_addr,
+ int reporting_endpoint_port)
+{
+ EVENT_MOBILE_FLOW * mobile_flow = NULL;
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(flow_direction != NULL);
+ assert(gtp_per_flow_metrics != NULL);
+ assert(ip_protocol_type != NULL);
+ assert(ip_version != NULL);
+ assert(other_endpoint_ip_address != NULL);
+ assert(other_endpoint_port > 0);
+ assert(reporting_endpoint_ip_addr != NULL);
+ assert(reporting_endpoint_port > 0);
+
+ /***************************************************************************/
+ /* Allocate the Mobile Flow. */
+ /***************************************************************************/
+ mobile_flow = malloc(sizeof(EVENT_MOBILE_FLOW));
+ if (mobile_flow == NULL)
+ {
+ log_error_state("Out of memory");
+ goto exit_label;
+ }
+ memset(mobile_flow, 0, sizeof(EVENT_MOBILE_FLOW));
+ EVEL_DEBUG("New Mobile Flow is at %lp", mobile_flow);
+
+ /***************************************************************************/
+ /* Initialize the header & the Mobile Flow fields. Optional string values */
+ /* are uninitialized (NULL). */
+ /***************************************************************************/
+ evel_init_header(&mobile_flow->header,"MobileFlow");
+ 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/VES5.0/evel/evel-library/code/evel_library/evel_option.c b/VES5.0/evel/evel-library/code/evel_library/evel_option.c
new file mode 100644
index 00000000..d9d9e607
--- /dev/null
+++ b/VES5.0/evel/evel-library/code/evel_library/evel_option.c
@@ -0,0 +1,540 @@
+/**************************************************************************//**
+ * @file
+ * Source module relating to EVEL_OPTION_ types.
+ *
+ * License
+ * -------
+ *
+ * Copyright(c) <2016>, AT&T Intellectual Property. All other rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement: This product includes
+ * software developed by the AT&T.
+ * 4. Neither the name of AT&T nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "evel_internal.h"
+
+/**************************************************************************//**
+ * Free the underlying resources of an ::EVEL_OPTION_STRING.
+ *
+ * @param option Pointer to the ::EVEL_OPTION_STRING.
+ *****************************************************************************/
+void evel_free_option_string(EVEL_OPTION_STRING * const option)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(option != NULL);
+
+ if (option->is_set)
+ {
+ free(option->value);
+ option->value = NULL;
+ option->is_set = EVEL_FALSE;
+ }
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Initialize an ::EVEL_OPTION_STRING to a not-set state.
+ *
+ * @param option Pointer to the ::EVEL_OPTION_STRING.
+ *****************************************************************************/
+void evel_init_option_string(EVEL_OPTION_STRING * const option)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(option != NULL);
+
+ option->value = NULL;
+ option->is_set = EVEL_FALSE;
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the value of an ::EVEL_OPTION_STRING.
+ *
+ * @param option Pointer to the ::EVEL_OPTION_STRING.
+ * @param value The value to set.
+ * @param description Description to be used in logging.
+ *****************************************************************************/
+void evel_set_option_string(EVEL_OPTION_STRING * const option,
+ const char * const value,
+ const char * const description)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(option != NULL);
+ assert(value != NULL);
+ assert(description != NULL);
+
+ if (option->is_set)
+ {
+ EVEL_ERROR("Ignoring attempt to update %s to %s. %s already set to %s",
+ description, value, description, option->value);
+ }
+ else
+ {
+ EVEL_DEBUG("Setting %s to %s", description, value);
+ option->value = strdup(value);
+ option->is_set = EVEL_TRUE;
+ }
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Force the value of an ::EVEL_OPTION_STRING.
+ *
+ * @param option Pointer to the ::EVEL_OPTION_STRING.
+ * @param value The value to set.
+ *****************************************************************************/
+void evel_force_option_string(EVEL_OPTION_STRING * const option,
+ const char * const value)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(option != NULL);
+ assert(option->is_set == EVEL_FALSE);
+ assert(option->value == NULL);
+
+ option->value = strdup(value);
+ option->is_set = EVEL_TRUE;
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Initialize an ::EVEL_OPTION_INT to a not-set state.
+ *
+ * @param option Pointer to the ::EVEL_OPTION_INT.
+ *****************************************************************************/
+void evel_init_option_int(EVEL_OPTION_INT * const option)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(option != NULL);
+
+ option->value = 0;
+ option->is_set = EVEL_FALSE;
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Force the value of an ::EVEL_OPTION_INT.
+ *
+ * @param option Pointer to the ::EVEL_OPTION_INT.
+ * @param value The value to set.
+ *****************************************************************************/
+void evel_force_option_int(EVEL_OPTION_INT * const option,
+ const int value)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(option != NULL);
+
+ option->value = value;
+ option->is_set = EVEL_TRUE;
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the value of an ::EVEL_OPTION_INT.
+ *
+ * @param option Pointer to the ::EVEL_OPTION_INT.
+ * @param value The value to set.
+ * @param description Description to be used in logging.
+ *****************************************************************************/
+void evel_set_option_int(EVEL_OPTION_INT * const option,
+ const int value,
+ const char * const description)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(option != NULL);
+ assert(description != NULL);
+
+ if (option->is_set)
+ {
+ EVEL_ERROR("Ignoring attempt to update %s to %d. %s already set to %d",
+ description, value, description, option->value);
+ }
+ else
+ {
+ EVEL_DEBUG("Setting %s to %d", description, value);
+ option->value = value;
+ option->is_set = EVEL_TRUE;
+ }
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Initialize an ::EVEL_OPTION_DOUBLE to a not-set state.
+ *
+ * @param option Pointer to the ::EVEL_OPTION_DOUBLE.
+ *****************************************************************************/
+void evel_init_option_double(EVEL_OPTION_DOUBLE * const option)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(option != NULL);
+
+ option->value = 0.0;
+ option->is_set = EVEL_FALSE;
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Force the value of an ::EVEL_OPTION_DOUBLE.
+ *
+ * @param option Pointer to the ::EVEL_OPTION_DOUBLE.
+ * @param value The value to set.
+ *****************************************************************************/
+void evel_force_option_double(EVEL_OPTION_DOUBLE * const option,
+ const double value)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(option != NULL);
+
+ option->value = value;
+ option->is_set = EVEL_TRUE;
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the value of an ::EVEL_OPTION_DOUBLE.
+ *
+ * @param option Pointer to the ::EVEL_OPTION_DOUBLE.
+ * @param value The value to set.
+ * @param description Description to be used in logging.
+ *****************************************************************************/
+void evel_set_option_double(EVEL_OPTION_DOUBLE * const option,
+ const double value,
+ const char * const description)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(option != NULL);
+ assert(description != NULL);
+
+ if (option->is_set)
+ {
+ EVEL_ERROR("Ignoring attempt to update %s to %lf. %s already set to %lf",
+ description, value, description, option->value);
+ }
+ else
+ {
+ EVEL_DEBUG("Setting %s to %lf", description, value);
+ option->value = value;
+ option->is_set = EVEL_TRUE;
+ }
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Initialize an ::EVEL_OPTION_ULL to a not-set state.
+ *
+ * @param option Pointer to the ::EVEL_OPTION_ULL.
+ *****************************************************************************/
+void evel_init_option_ull(EVEL_OPTION_ULL * const option)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(option != NULL);
+ option->value = 0;
+ option->is_set = EVEL_FALSE;
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Force the value of an ::EVEL_OPTION_ULL.
+ *
+ * @param option Pointer to the ::EVEL_OPTION_ULL.
+ * @param value The value to set.
+ *****************************************************************************/
+void evel_force_option_ull(EVEL_OPTION_ULL * const option,
+ const unsigned long long value)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(option != NULL);
+
+ option->value = value;
+ option->is_set = EVEL_TRUE;
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Set the value of an ::EVEL_OPTION_ULL.
+ *
+ * @param option Pointer to the ::EVEL_OPTION_ULL.
+ * @param value The value to set.
+ * @param description Description to be used in logging.
+ *****************************************************************************/
+void evel_set_option_ull(EVEL_OPTION_ULL * const option,
+ const unsigned long long value,
+ const char * const description)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(option != NULL);
+ assert(description != NULL);
+
+ if (option->is_set)
+ {
+ EVEL_ERROR("Ignoring attempt to update %s to %llu. %s already set to %llu",
+ description, value, description, option->value);
+ }
+ else
+ {
+ EVEL_DEBUG("Setting %s to %llu", description, value);
+ option->value = value;
+ option->is_set = EVEL_TRUE;
+ }
+ EVEL_EXIT();
+}
+
+
+/**************************************************************************//**
+ * Initialize an ::EVEL_OPTION_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/VES5.0/evel/evel-library/code/evel_library/evel_other.c b/VES5.0/evel/evel-library/code/evel_library/evel_other.c
new file mode 100644
index 00000000..f52e1888
--- /dev/null
+++ b/VES5.0/evel/evel-library/code/evel_library/evel_other.c
@@ -0,0 +1,503 @@
+/**************************************************************************//**
+ * @file
+ * Implementation of EVEL functions relating to Other.
+ *
+ * License
+ * -------
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement: This product includes
+ * software developed by the AT&T.
+ * 4. Neither the name of AT&T nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+
+#include "evel.h"
+#include "evel_internal.h"
+
+/**************************************************************************//**
+ * Create a new Other event.
+ *
+ * @note The mandatory fields on the Other must be supplied to this factory
+ * function and are immutable once set. Optional fields have explicit
+ * setter functions, but again values may only be set once so that the
+ * Other has immutable properties.
+ * @returns pointer to the newly manufactured ::EVENT_OTHER. If the event is
+ * not used (i.e. posted) it must be released using ::evel_free_other.
+ * @retval NULL Failed to create the event.
+ *****************************************************************************/
+EVENT_OTHER * evel_new_other()
+{
+ EVENT_OTHER * other = NULL;
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+
+ /***************************************************************************/
+ /* Allocate the Other. */
+ /***************************************************************************/
+ other = malloc(sizeof(EVENT_OTHER));
+ if (other == NULL)
+ {
+ log_error_state("Out of memory");
+ goto exit_label;
+ }
+ memset(other, 0, sizeof(EVENT_OTHER));
+ EVEL_DEBUG("New Other is at %lp", other);
+
+ /***************************************************************************/
+ /* Initialize the header & the Other fields. Optional string values are */
+ /* uninitialized (NULL). */
+ /***************************************************************************/
+ evel_init_header(&other->header,"OtherEvent");
+ 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/VES5.0/evel/evel-library/code/evel_library/evel_reporting_measurement.c b/VES5.0/evel/evel-library/code/evel_library/evel_reporting_measurement.c
new file mode 100644
index 00000000..265d9899
--- /dev/null
+++ b/VES5.0/evel/evel-library/code/evel_library/evel_reporting_measurement.c
@@ -0,0 +1,450 @@
+/**************************************************************************//**
+ * @file
+ * Implementation of EVEL functions relating to the Measurement for VF
+ * Reporting event.
+ *
+ * @note This is an experimental event tytpe and does not form part of the
+ * currently approved AT&T event schema. It is intended to allow a
+ * less-onerous event reporting mechanism because it avoids having to
+ * return all the platform statistics which are mandatory in the
+ * **measurementsForVfScaling** event.
+ *
+ * License
+ * -------
+ *
+ * Copyright(c) <2016>, AT&T Intellectual Property. All other rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement: This product includes
+ * software developed by the AT&T.
+ * 4. Neither the name of AT&T nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+
+#include "evel.h"
+#include "evel_internal.h"
+#include "evel_throttle.h"
+
+/**************************************************************************//**
+ * Create a new Report event.
+ *
+ * @note The mandatory fields on the Report must be supplied to this
+ * factory function and are immutable once set. Optional fields have
+ * explicit setter functions, but again values may only be set once so
+ * that the Report has immutable properties.
+ *
+ * @param measurement_interval
+
+ * @returns pointer to the newly manufactured ::EVENT_REPORT. If the event is
+ * not used (i.e. posted) it must be released using ::evel_free_event.
+ * @retval NULL Failed to create the event.
+ *****************************************************************************/
+EVENT_REPORT * evel_new_report(double measurement_interval)
+{
+ EVENT_REPORT * report = NULL;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(measurement_interval >= 0.0);
+
+ /***************************************************************************/
+ /* Allocate the report. */
+ /***************************************************************************/
+ report = malloc(sizeof(EVENT_REPORT));
+ if (report == NULL)
+ {
+ log_error_state("Out of memory for Report");
+ goto exit_label;
+ }
+ memset(report, 0, sizeof(EVENT_REPORT));
+ EVEL_DEBUG("New report is at %lp", report);
+
+ /***************************************************************************/
+ /* Initialize the header & the report fields. */
+ /***************************************************************************/
+ evel_init_header(&report->header,"Report");
+ 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/VES5.0/evel/evel-library/code/evel_library/evel_scaling_measurement.c b/VES5.0/evel/evel-library/code/evel_library/evel_scaling_measurement.c
new file mode 100644
index 00000000..2ad5e66d
--- /dev/null
+++ b/VES5.0/evel/evel-library/code/evel_library/evel_scaling_measurement.c
@@ -0,0 +1,3727 @@
+/**************************************************************************//**
+ * @file
+ * Implementation of EVEL functions relating to the Measurement.
+ *
+ * License
+ * -------
+ *
+ * Copyright(c) <2016>, AT&T Intellectual Property. All other rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement: This product includes
+ * software developed by the AT&T.
+ * 4. Neither the name of AT&T nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+
+#include "evel.h"
+#include "evel_internal.h"
+#include "evel_throttle.h"
+
+/**************************************************************************//**
+ * Create a new Measurement event.
+ *
+ * @note The mandatory fields on the Measurement must be supplied to this
+ * factory function and are immutable once set. Optional fields have
+ * explicit setter functions, but again values may only be set once so
+ * that the Measurement has immutable properties.
+ *
+ * @param measurement_interval
+ *
+ * @returns pointer to the newly manufactured ::EVENT_MEASUREMENT. If the
+ * event is not used (i.e. posted) it must be released using
+ * ::evel_free_event.
+ * @retval NULL Failed to create the event.
+ *****************************************************************************/
+EVENT_MEASUREMENT * evel_new_measurement(double measurement_interval)
+{
+ EVENT_MEASUREMENT * measurement = NULL;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(measurement_interval >= 0.0);
+
+ /***************************************************************************/
+ /* Allocate the measurement. */
+ /***************************************************************************/
+ measurement = malloc(sizeof(EVENT_MEASUREMENT));
+ if (measurement == NULL)
+ {
+ log_error_state("Out of memory for Measurement");
+ goto exit_label;
+ }
+ memset(measurement, 0, sizeof(EVENT_MEASUREMENT));
+ EVEL_DEBUG("New measurement is at %lp", measurement);
+
+ /***************************************************************************/
+ /* Initialize the header & the measurement fields. */
+ /***************************************************************************/
+ evel_init_header(&measurement->header,"vnfScalingMeasurement");
+ 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,
+ int block_iops,
+ double ephemeral_configured,
+ double ephemeral_used,
+ int ephemeral_iops)
+{
+ MEASUREMENT_FSYS_USE * fsys_use = NULL;
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check assumptions. */
+ /***************************************************************************/
+ assert(measurement != NULL);
+ assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT);
+ assert(filesystem_name != NULL);
+ assert(block_configured >= 0.0);
+ assert(block_used >= 0.0);
+ assert(block_iops >= 0);
+ assert(ephemeral_configured >= 0.0);
+ assert(ephemeral_used >= 0.0);
+ assert(ephemeral_iops >= 0);
+
+ /***************************************************************************/
+ /* Allocate a container for the value and push onto the list. */
+ /***************************************************************************/
+ EVEL_DEBUG("Adding filesystem_name=%s", filesystem_name);
+ fsys_use = malloc(sizeof(MEASUREMENT_FSYS_USE));
+ assert(fsys_use != NULL);
+ memset(fsys_use, 0, sizeof(MEASUREMENT_FSYS_USE));
+ fsys_use->filesystem_name = strdup(filesystem_name);
+ fsys_use->block_configured = block_configured;
+ fsys_use->block_used = block_used;
+ fsys_use->block_iops = block_iops;
+ fsys_use->ephemeral_configured = block_configured;
+ fsys_use->ephemeral_used = ephemeral_used;
+ fsys_use->ephemeral_iops = ephemeral_iops;
+
+ dlist_push_last(&measurement->filesystem_usage, fsys_use);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Add a Feature usage value name/value pair to the Measurement.
+ *
+ * The name is null delimited ASCII string. The library takes
+ * a copy so the caller does not have to preserve values after the function
+ * returns.
+ *
+ * @param measurement Pointer to the measurement.
+ * @param feature ASCIIZ string with the feature's name.
+ * @param utilization Utilization of the feature.
+ *****************************************************************************/
+void evel_measurement_feature_use_add(EVENT_MEASUREMENT * measurement,
+ char * feature,
+ int utilization)
+{
+ MEASUREMENT_FEATURE_USE * feature_use = NULL;
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check assumptions. */
+ /***************************************************************************/
+ assert(measurement != NULL);
+ assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT);
+ assert(feature != NULL);
+ assert(utilization >= 0);
+
+ /***************************************************************************/
+ /* Allocate a container for the value and push onto the list. */
+ /***************************************************************************/
+ EVEL_DEBUG("Adding Feature=%s Use=%d", feature, utilization);
+ feature_use = malloc(sizeof(MEASUREMENT_FEATURE_USE));
+ assert(feature_use != NULL);
+ memset(feature_use, 0, sizeof(MEASUREMENT_FEATURE_USE));
+ feature_use->feature_id = strdup(feature);
+ assert(feature_use->feature_id != NULL);
+ feature_use->feature_utilization = utilization;
+
+ dlist_push_last(&measurement->feature_usage, feature_use);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Add a Additional Measurement value name/value pair to the Report.
+ *
+ * The name is null delimited ASCII string. The library takes
+ * a copy so the caller does not have to preserve values after the function
+ * returns.
+ *
+ * @param measurement Pointer to the Measaurement.
+ * @param group ASCIIZ string with the measurement group's name.
+ * @param name ASCIIZ string containing the measurement's name.
+ * @param value ASCIIZ string containing the measurement's value.
+ *****************************************************************************/
+void evel_measurement_custom_measurement_add(EVENT_MEASUREMENT * measurement,
+ const char * const group,
+ const char * const name,
+ const char * const value)
+{
+ MEASUREMENT_GROUP * measurement_group = NULL;
+ CUSTOM_MEASUREMENT * custom_measurement = NULL;
+ DLIST_ITEM * item = NULL;
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check assumptions. */
+ /***************************************************************************/
+ assert(measurement != NULL);
+ assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT);
+ assert(group != NULL);
+ assert(name != NULL);
+ assert(value != NULL);
+
+ /***************************************************************************/
+ /* Allocate a container for the name/value pair. */
+ /***************************************************************************/
+ EVEL_DEBUG("Adding Measurement Group=%s Name=%s Value=%s",
+ group, name, value);
+ custom_measurement = malloc(sizeof(CUSTOM_MEASUREMENT));
+ assert(custom_measurement != NULL);
+ memset(custom_measurement, 0, sizeof(CUSTOM_MEASUREMENT));
+ custom_measurement->name = strdup(name);
+ assert(custom_measurement->name != NULL);
+ custom_measurement->value = strdup(value);
+ assert(custom_measurement->value != NULL);
+
+ /***************************************************************************/
+ /* See if we have that group already. */
+ /***************************************************************************/
+ item = dlist_get_first(&measurement->additional_measurements);
+ while (item != NULL)
+ {
+ measurement_group = (MEASUREMENT_GROUP *) item->item;
+ assert(measurement_group != NULL);
+
+ EVEL_DEBUG("Got measurement group %s", measurement_group->name);
+ if (strcmp(group, measurement_group->name) == 0)
+ {
+ EVEL_DEBUG("Found existing Measurement Group");
+ break;
+ }
+ item = dlist_get_next(item);
+ }
+
+ /***************************************************************************/
+ /* If we didn't have the group already, create it. */
+ /***************************************************************************/
+ if (item == NULL)
+ {
+ EVEL_DEBUG("Creating new Measurement Group");
+ measurement_group = malloc(sizeof(MEASUREMENT_GROUP));
+ assert(measurement_group != NULL);
+ memset(measurement_group, 0, sizeof(MEASUREMENT_GROUP));
+ measurement_group->name = strdup(group);
+ assert(measurement_group->name != NULL);
+ dlist_initialize(&measurement_group->measurements);
+ dlist_push_last(&measurement->additional_measurements, measurement_group);
+ }
+
+ /***************************************************************************/
+ /* If we didn't have the group already, create it. */
+ /***************************************************************************/
+ dlist_push_last(&measurement_group->measurements, custom_measurement);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Add a Codec usage value name/value pair to the Measurement.
+ *
+ * The name is null delimited ASCII string. The library takes
+ * a copy so the caller does not have to preserve values after the function
+ * returns.
+ *
+ * @param measurement Pointer to the measurement.
+ * @param codec ASCIIZ string with the codec's name.
+ * @param utilization Number of codecs in use.
+ *****************************************************************************/
+void evel_measurement_codec_use_add(EVENT_MEASUREMENT * measurement,
+ char * codec,
+ int utilization)
+{
+ MEASUREMENT_CODEC_USE * codec_use = NULL;
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check assumptions. */
+ /***************************************************************************/
+ assert(measurement != NULL);
+ assert(measurement->header.event_domain == EVEL_DOMAIN_MEASUREMENT);
+ assert(codec != NULL);
+ assert(utilization >= 0.0);
+
+ /***************************************************************************/
+ /* Allocate a container for the value and push onto the list. */
+ /***************************************************************************/
+ EVEL_DEBUG("Adding Codec=%s Use=%d", codec, utilization);
+ codec_use = malloc(sizeof(MEASUREMENT_CODEC_USE));
+ assert(codec_use != NULL);
+ memset(codec_use, 0, sizeof(MEASUREMENT_CODEC_USE));
+ codec_use->codec_id = strdup(codec);
+ assert(codec_use->codec_id != NULL);
+ codec_use->number_in_use = utilization;
+
+ dlist_push_last(&measurement->codec_usage, codec_use);
+
+ EVEL_EXIT();
+}
+
+
+/**************************************************************************//**
+ * Set the 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_double(
+ jbuf, "blockConfigured", fsys_use->block_configured);
+ evel_enc_kv_int(jbuf, "blockIops", fsys_use->block_iops);
+ evel_enc_kv_double(jbuf, "blockUsed", fsys_use->block_used);
+ evel_enc_kv_double(
+ jbuf, "ephemeralConfigured", fsys_use->ephemeral_configured);
+ evel_enc_kv_int(jbuf, "ephemeralIops", fsys_use->ephemeral_iops);
+ evel_enc_kv_double(jbuf, "ephemeralUsed", fsys_use->ephemeral_used);
+ evel_enc_kv_string(jbuf, "filesystemName", fsys_use->filesystem_name);
+ evel_json_close_object(jbuf);
+ item_added = true;
+ }
+ item = dlist_get_next(item);
+ }
+ evel_json_close_list(jbuf);
+
+ /*************************************************************************/
+ /* If we've not written anything, rewind to before we opened the list. */
+ /*************************************************************************/
+ if (!item_added)
+ {
+ evel_json_rewind(jbuf);
+ }
+ }
+
+ /***************************************************************************/
+ /* Latency distribution. */
+ /***************************************************************************/
+ item = dlist_get_first(&event->latency_distribution);
+ if ((item != NULL) &&
+ evel_json_open_opt_named_list(jbuf, "latencyDistribution"))
+ {
+ while (item != NULL)
+ {
+ bucket = (MEASUREMENT_LATENCY_BUCKET*) item->item;
+ assert(bucket != NULL);
+
+ evel_json_open_object(jbuf);
+ evel_enc_kv_opt_double(
+ jbuf, "lowEndOfLatencyBucket", &bucket->low_end);
+ evel_enc_kv_opt_double(
+ jbuf, "highEndOfLatencyBucket", &bucket->high_end);
+ evel_enc_kv_int(jbuf, "countsInTheBucket", bucket->count);
+ evel_json_close_object(jbuf);
+ item = dlist_get_next(item);
+ }
+ evel_json_close_list(jbuf);
+ }
+
+ evel_enc_kv_opt_double(
+ jbuf, "meanRequestLatency", &event->mean_request_latency);
+ evel_enc_kv_opt_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/VES5.0/evel/evel-library/code/evel_library/evel_sipsignaling.c b/VES5.0/evel/evel-library/code/evel_library/evel_sipsignaling.c
new file mode 100644
index 00000000..66d01cb4
--- /dev/null
+++ b/VES5.0/evel/evel-library/code/evel_library/evel_sipsignaling.c
@@ -0,0 +1,583 @@
+/**************************************************************************//**
+ * @file
+ * Implementation of EVEL functions relating to Signaling.
+ *
+ * License
+ * -------
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement: This product includes
+ * software developed by the AT&T.
+ * 4. Neither the name of AT&T nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+
+#include "evel_throttle.h"
+
+/**************************************************************************//**
+ * Create a new Signaling event.
+ *
+ * @note The mandatory fields on the Signaling must be supplied to
+ * this factory function and are immutable once set. Optional fields
+ * have explicit setter functions, but again values may only be set
+ * once so that the event has immutable properties.
+ * @param vendor_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 * 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(&event->header,"SipSignaling");
+ 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/VES5.0/evel/evel-library/code/evel_library/evel_state_change.c b/VES5.0/evel/evel-library/code/evel_library/evel_state_change.c
new file mode 100644
index 00000000..11a1ea24
--- /dev/null
+++ b/VES5.0/evel/evel-library/code/evel_library/evel_state_change.c
@@ -0,0 +1,294 @@
+/**************************************************************************//**
+ * @file
+ * Implementation of EVEL functions relating to the State Change.
+ *
+ * License
+ * -------
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement: This product includes
+ * software developed by the AT&T.
+ * 4. Neither the name of AT&T nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+
+#include "evel_throttle.h"
+
+/**************************************************************************//**
+ * Create a new State Change event.
+ *
+ * @note The mandatory fields on the State Change must be supplied to this
+ * factory function and are immutable once set. Optional fields have
+ * explicit setter functions, but again values may only be set once
+ * so that the State Change has immutable properties.
+ *
+ * @param new_state The new state of the reporting entity.
+ * @param old_state The old state of the reporting entity.
+ * @param interface The card or port name of the reporting entity.
+ *
+ * @returns pointer to the newly manufactured ::EVENT_STATE_CHANGE. If the
+ * event is not used it must be released using
+ * ::evel_free_state_change
+ * @retval NULL Failed to create the event.
+ *****************************************************************************/
+EVENT_STATE_CHANGE * evel_new_state_change(const EVEL_ENTITY_STATE new_state,
+ const EVEL_ENTITY_STATE old_state,
+ const char * const interface)
+{
+ EVENT_STATE_CHANGE * state_change = NULL;
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(new_state < EVEL_MAX_ENTITY_STATES);
+ assert(old_state < EVEL_MAX_ENTITY_STATES);
+ assert(interface != NULL);
+
+ /***************************************************************************/
+ /* Allocate the State Change. */
+ /***************************************************************************/
+ state_change = malloc(sizeof(EVENT_STATE_CHANGE));
+ if (state_change == NULL)
+ {
+ log_error_state("Out of memory");
+ goto exit_label;
+ }
+ memset(state_change, 0, sizeof(EVENT_STATE_CHANGE));
+ EVEL_DEBUG("New State Change is at %lp", state_change);
+
+ /***************************************************************************/
+ /* Initialize the header & the State Change fields. Optional string */
+ /* values are uninitialized (NULL). */
+ /***************************************************************************/
+ evel_init_header(&state_change->header,"StateChange");
+ 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/VES5.0/evel/evel-library/code/evel_library/evel_strings.c b/VES5.0/evel/evel-library/code/evel_library/evel_strings.c
new file mode 100644
index 00000000..33375f3e
--- /dev/null
+++ b/VES5.0/evel/evel-library/code/evel_library/evel_strings.c
@@ -0,0 +1,481 @@
+/**************************************************************************//**
+ * @file
+ * Implementation of EVEL functions to convert common enum types to strings.
+ *
+ * License
+ * -------
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement: This product includes
+ * software developed by the AT&T.
+ * 4. Neither the name of AT&T nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+
+#include "evel_internal.h"
+
+/**************************************************************************//**
+ * Map an ::EVEL_COUNTER_CRITICALITIES enum value to the equivalent string.
+ *
+ * @param criticality The criticality to convert.
+ * @returns The equivalent string.
+ *****************************************************************************/
+char * evel_criticality(const EVEL_COUNTER_CRITICALITIES criticality)
+{
+ char * result;
+
+ EVEL_ENTER();
+
+ switch (criticality)
+ {
+ case EVEL_COUNTER_CRITICALITY_CRIT:
+ result = "CRIT";
+ break;
+
+ case EVEL_COUNTER_CRITICALITY_MAJ:
+ result = "MAJ";
+ break;
+
+ default:
+ EVEL_ERROR("Unexpected counter criticality %d", criticality);
+ assert(0);
+ }
+
+ EVEL_EXIT();
+
+ return result;
+}
+
+/**************************************************************************//**
+ * Map an ::EVEL_SEVERITIES enum value to the equivalent string.
+ *
+ * @param severity The severity to convert.
+ * @returns The equivalent string.
+ *****************************************************************************/
+char * evel_severity(const EVEL_SEVERITIES severity)
+{
+ char * result;
+
+ EVEL_ENTER();
+
+ switch (severity)
+ {
+ case EVEL_SEVERITY_CRITICAL:
+ result = "CRITICAL";
+ break;
+
+ case EVEL_SEVERITY_MAJOR:
+ result = "MAJOR";
+ break;
+
+ case EVEL_SEVERITY_MINOR:
+ result = "MINOR";
+ break;
+
+ case EVEL_SEVERITY_WARNING:
+ result = "WARNING";
+ break;
+
+ case EVEL_SEVERITY_NORMAL:
+ result = "NORMAL";
+ break;
+
+ default:
+ EVEL_ERROR("Unexpected event severity %d", severity);
+ assert(0);
+ }
+
+ EVEL_EXIT();
+
+ return result;
+}
+
+/**************************************************************************//**
+ * Map an ::EVEL_ALERT_ACTIONS enum value to the equivalent string.
+ *
+ * @param alert_action The alert_action to convert.
+ * @returns The equivalent string.
+ *****************************************************************************/
+char * evel_alert_action(const EVEL_ALERT_ACTIONS alert_action)
+{
+ char * result;
+
+ EVEL_ENTER();
+
+ switch (alert_action)
+ {
+ case EVEL_ALERT_ACTION_CLEAR:
+ result = "CLEAR";
+ break;
+
+ case EVEL_ALERT_ACTION_CONT:
+ result = "CONT";
+ break;
+
+ case EVEL_ALERT_ACTION_SET:
+ result = "SET";
+ break;
+
+ default:
+ EVEL_ERROR("Unexpected alert action %d", alert_action);
+ assert(0);
+ }
+
+ EVEL_EXIT();
+
+ return result;
+}
+
+/**************************************************************************//**
+ * Map an ::EVEL_ALERT_TYPES enum value to the equivalent string.
+ *
+ * @param alert_type The alert_type to convert.
+ * @returns The equivalent string.
+ *****************************************************************************/
+char * evel_alert_type(const EVEL_ALERT_TYPES alert_type)
+{
+ char * result;
+
+ EVEL_ENTER();
+
+ switch (alert_type)
+ {
+ case EVEL_ALERT_TYPE_CARD:
+ result = "CARD-ANOMALY";
+ break;
+
+ case EVEL_ALERT_TYPE_ELEMENT:
+ result = "ELEMENT-ANOMALY";
+ break;
+
+ case EVEL_ALERT_TYPE_INTERFACE:
+ result = "INTERFACE-ANOMALY";
+ break;
+
+ case EVEL_ALERT_TYPE_SERVICE:
+ result = "SERVICE-ANOMALY";
+ break;
+
+ default:
+ EVEL_ERROR("Unexpected alert type %d", alert_type);
+ assert(0);
+ }
+
+ EVEL_EXIT();
+
+ return result;
+}
+
+/**************************************************************************//**
+ * Map an ::EVEL_EVENT_DOMAINS enum value to the equivalent string.
+ *
+ * @param domain The domain to convert.
+ * @returns The equivalent string.
+ *****************************************************************************/
+char * evel_event_domain(const EVEL_EVENT_DOMAINS domain)
+{
+ char * result;
+
+ EVEL_ENTER();
+
+ switch (domain)
+ {
+ case EVEL_DOMAIN_HEARTBEAT:
+ result = "heartbeat";
+ break;
+
+ case EVEL_DOMAIN_FAULT:
+ result = "fault";
+ break;
+
+ case EVEL_DOMAIN_MEASUREMENT:
+ result = "measurementsForVfScaling";
+ break;
+
+ case EVEL_DOMAIN_REPORT:
+ result = "measurementsForVfReporting";
+ break;
+
+ case EVEL_DOMAIN_MOBILE_FLOW:
+ result = "mobileFlow";
+ break;
+
+ case EVEL_DOMAIN_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;
+
+ 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/VES5.0/evel/evel-library/code/evel_library/evel_syslog.c b/VES5.0/evel/evel-library/code/evel_library/evel_syslog.c
new file mode 100644
index 00000000..b1267065
--- /dev/null
+++ b/VES5.0/evel/evel-library/code/evel_library/evel_syslog.c
@@ -0,0 +1,514 @@
+/**************************************************************************//**
+ * @file
+ * Implementation of EVEL functions relating to the Syslog.
+ *
+ * License
+ * -------
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement: This product includes
+ * software developed by the AT&T.
+ * 4. Neither the name of AT&T nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+
+#include "evel_throttle.h"
+
+/**************************************************************************//**
+ * Create a new Syslog event.
+ *
+ * @note The mandatory fields on the Syslog must be supplied to this factory
+ * function and are immutable once set. Optional fields have explicit
+ * setter functions, but again values may only be set once so that the
+ * Syslog has immutable properties.
+ * @param event_source_type The type of Syslog event source.
+ * @param syslog_msg The Syslog event message.
+ * @param syslog_tag The messgaeId identifying the type of message.
+ * @returns pointer to the newly manufactured ::EVENT_SYSLOG. If the event is
+ * not used (i.e. posted) it must be released using
+ * ::evel_free_syslog.
+ * @retval NULL Failed to create the event.
+ *****************************************************************************/
+EVENT_SYSLOG * evel_new_syslog(EVEL_SOURCE_TYPES event_source_type,
+ const char * const syslog_msg,
+ const char * const syslog_tag)
+{
+ EVENT_SYSLOG * syslog = NULL;
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(event_source_type < EVEL_MAX_SOURCE_TYPES);
+ assert(syslog_msg != NULL);
+ assert(syslog_tag != NULL);
+
+ /***************************************************************************/
+ /* Allocate the Syslog. */
+ /***************************************************************************/
+ syslog = malloc(sizeof(EVENT_SYSLOG));
+ if (syslog == NULL)
+ {
+ log_error_state("Out of memory");
+ goto exit_label;
+ }
+ memset(syslog, 0, sizeof(EVENT_SYSLOG));
+ EVEL_DEBUG("New Syslog is at %lp", syslog);
+
+ /***************************************************************************/
+ /* Initialize the header & the Syslog fields. Optional string values are */
+ /* uninitialized (NULL). */
+ /***************************************************************************/
+ evel_init_header(&syslog->header,"Syslog");
+ 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/VES5.0/evel/evel-library/code/evel_library/evel_throttle.c b/VES5.0/evel/evel-library/code/evel_library/evel_throttle.c
new file mode 100644
index 00000000..351c7da7
--- /dev/null
+++ b/VES5.0/evel/evel-library/code/evel_library/evel_throttle.c
@@ -0,0 +1,2116 @@
+/**************************************************************************//**
+ * @file
+ * Event Manager
+ *
+ * Simple event manager that is responsible for taking events (Heartbeats,
+ * Faults and Measurements) from the ring-buffer and posting them to the API.
+ *
+ * License
+ * -------
+ *
+ * Copyright(c) <2016>, AT&T Intellectual Property. All other rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement: This product includes
+ * software developed by the AT&T.
+ * 4. Neither the name of AT&T nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*****************************************************************************/
+
+#define _GNU_SOURCE
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <pthread.h>
+#include <search.h>
+
+#include "evel_throttle.h"
+
+/*****************************************************************************/
+/* The Event Throttling State for all domains, indexed by */
+/* ::EVEL_EVENT_DOMAINS, corresponding to JSON eventDomain. */
+/* */
+/* A given domain is in a throttled state if ::evel_throttle_spec is */
+/* non-NULL. */
+/*****************************************************************************/
+static EVEL_THROTTLE_SPEC * evel_throttle_spec[EVEL_MAX_DOMAINS];
+
+/*****************************************************************************/
+/* The current measurement interval. Default: MEASUREMENT_INTERVAL_UKNOWN. */
+/* Must be protected by evel_measurement_interval_mutex. */
+/*****************************************************************************/
+static int evel_measurement_interval;
+
+/*****************************************************************************/
+/* Mutex protecting evel_measurement_interval from contention between an */
+/* EVEL client reading it, and the EVEL event handler updating it. */
+/*****************************************************************************/
+static pthread_mutex_t evel_measurement_interval_mutex;
+
+/*****************************************************************************/
+/* Flag stating that we have received a "provideThrottlingState" command. */
+/* Set during JSON processing and cleared on sending the throttling state. */
+/*****************************************************************************/
+static bool evel_provide_throttling_state;
+
+/*****************************************************************************/
+/* Holder for the "commandType" value during JSON processing. */
+/*****************************************************************************/
+static char * evel_command_type_value;
+
+/*****************************************************************************/
+/* Holder for the "measurementInterval" value during JSON processing. */
+/*****************************************************************************/
+static char * evel_measurement_interval_value;
+
+/*****************************************************************************/
+/* Holder for the "eventDomain" value during JSON processing. */
+/*****************************************************************************/
+static char * evel_throttle_spec_domain_value;
+
+/*****************************************************************************/
+/* Decoded version of ::evel_throttle_spec_domain_value. */
+/*****************************************************************************/
+static EVEL_EVENT_DOMAINS evel_throttle_spec_domain;
+
+/*****************************************************************************/
+/* During JSON processing of a single throttling specification, we collect */
+/* parameters in this working ::EVEL_THROTTLE_SPEC */
+/*****************************************************************************/
+static EVEL_THROTTLE_SPEC * evel_temp_throttle;
+
+/*****************************************************************************/
+/* State tracking our progress through the command list */
+/*****************************************************************************/
+EVEL_JSON_COMMAND_STATE evel_json_command_state;
+
+/*****************************************************************************/
+/* Debug strings for ::EVEL_JSON_COMMAND_STATE. */
+/*****************************************************************************/
+static const char * const evel_jcs_strings[EVEL_JCS_MAX] = {
+ "EVEL_JCS_START",
+ "EVEL_JCS_COMMAND_LIST",
+ "EVEL_JCS_COMMAND_LIST_ENTRY",
+ "EVEL_JCS_COMMAND",
+ "EVEL_JCS_SPEC",
+ "EVEL_JCS_FIELD_NAMES",
+ "EVEL_JCS_PAIRS_LIST",
+ "EVEL_JCS_PAIRS_LIST_ENTRY",
+ "EVEL_JCS_NV_PAIR_NAMES"
+};
+
+/*****************************************************************************/
+/* Debug strings for JSON token type. */
+/*****************************************************************************/
+#define JSON_TOKEN_TYPES (JSMN_PRIMITIVE + 1)
+static const char * const evel_json_token_strings[JSON_TOKEN_TYPES] = {
+ "JSMN_UNDEFINED",
+ "JSMN_OBJECT",
+ "JSMN_ARRAY",
+ "JSMN_STRING",
+ "JSMN_PRIMITIVE"
+};
+
+/*****************************************************************************/
+/* Debug strings for JSON domains. */
+/*****************************************************************************/
+static const char * evel_domain_strings[EVEL_MAX_DOMAINS] = {
+ "internal",
+ "heartbeat",
+ "fault",
+ "measurementsForVfScaling",
+ "mobileFlow",
+ "report",
+ "serviceEvents",
+ "signaling",
+ "stateChange",
+ "syslog",
+ "other"
+ "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/VES5.0/evel/evel-library/code/evel_library/evel_throttle.h b/VES5.0/evel/evel-library/code/evel_library/evel_throttle.h
new file mode 100644
index 00000000..5f02cd2f
--- /dev/null
+++ b/VES5.0/evel/evel-library/code/evel_library/evel_throttle.h
@@ -0,0 +1,228 @@
+#ifndef EVEL_THROTTLE_INCLUDED
+#define EVEL_THROTTLE_INCLUDED
+
+/**************************************************************************//**
+ * @file
+ * EVEL throttle definitions.
+ *
+ * These are internal definitions related to throttling specicications, which
+ * are required within the library but are not intended for external
+ * consumption.
+ *
+ * License
+ * -------
+ *
+ * Copyright(c) <2016>, AT&T Intellectual Property. All other rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement: This product includes
+ * software developed by the AT&T.
+ * 4. Neither the name of AT&T nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#include "evel_internal.h"
+#include "jsmn.h"
+
+/*****************************************************************************/
+/* Maximum depth of JSON response that we can handle. */
+/*****************************************************************************/
+#define EVEL_JSON_STACK_DEPTH 10
+
+/**************************************************************************//**
+ * Maximum number of tokens that we allow for in a JSON response.
+ *****************************************************************************/
+#define EVEL_MAX_RESPONSE_TOKENS 1024
+
+/**************************************************************************//**
+ * The nature of the next token that we are iterating through. Within an
+ * object, we alternate between collecting keys and values. Within an array,
+ * we only collect items.
+ *****************************************************************************/
+typedef enum {
+ EVEL_JSON_KEY,
+ EVEL_JSON_VALUE,
+ EVEL_JSON_ITEM
+} EVEL_JSON_STATE;
+
+/**************************************************************************//**
+ * States which we move through during JSON processing, tracking our way
+ * through the supported JSON structure.
+ *****************************************************************************/
+typedef enum
+{
+ /***************************************************************************/
+ /* Initial state. */
+ /***************************************************************************/
+ EVEL_JCS_START,
+
+ /***************************************************************************/
+ /* {"commandList": [ */
+ /***************************************************************************/
+ EVEL_JCS_COMMAND_LIST,
+
+ /***************************************************************************/
+ /* {"commandList": [{ */
+ /***************************************************************************/
+ EVEL_JCS_COMMAND_LIST_ENTRY,
+
+ /***************************************************************************/
+ /* {"commandList": [{"command": { */
+ /***************************************************************************/
+ EVEL_JCS_COMMAND,
+
+ /***************************************************************************/
+ /* ... "eventDomainThrottleSpecification": { */
+ /***************************************************************************/
+ EVEL_JCS_SPEC,
+
+ /***************************************************************************/
+ /* ... "suppressedFieldNames": [ */
+ /***************************************************************************/
+ EVEL_JCS_FIELD_NAMES,
+
+ /***************************************************************************/
+ /* ... "suppressedNvPairsList": [ */
+ /***************************************************************************/
+ EVEL_JCS_PAIRS_LIST,
+
+ /***************************************************************************/
+ /* ... "suppressedNvPairsList": [{ */
+ /***************************************************************************/
+ EVEL_JCS_PAIRS_LIST_ENTRY,
+
+ /***************************************************************************/
+ /* ... "suppressedNvPairNames": [ */
+ /***************************************************************************/
+ EVEL_JCS_NV_PAIR_NAMES,
+
+ EVEL_JCS_MAX
+} EVEL_JSON_COMMAND_STATE;
+
+/**************************************************************************//**
+ * An entry in the JSON stack.
+ *****************************************************************************/
+typedef struct evel_json_stack_entry {
+
+ /***************************************************************************/
+ /* The number of elements required at this level. */
+ /***************************************************************************/
+ int num_required;
+
+ /***************************************************************************/
+ /* The number of elements collected at this level. */
+ /***************************************************************************/
+ int json_count;
+
+ /***************************************************************************/
+ /* The collection state at this level in the JSON stack. */
+ /***************************************************************************/
+ EVEL_JSON_STATE json_state;
+
+ /***************************************************************************/
+ /* The key being collected (if json_state is EVEL_JSON_VALUE), or NULL. */
+ /***************************************************************************/
+ char * json_key;
+
+} EVEL_JSON_STACK_ENTRY;
+
+/**************************************************************************//**
+ * The JSON stack.
+ *****************************************************************************/
+typedef struct evel_json_stack {
+
+ /***************************************************************************/
+ /* The current position of the stack - starting at zero. */
+ /***************************************************************************/
+ int level;
+
+ /***************************************************************************/
+ /* The stack itself. */
+ /***************************************************************************/
+ EVEL_JSON_STACK_ENTRY entry[EVEL_JSON_STACK_DEPTH];
+
+ /***************************************************************************/
+ /* The underlying memory chunk. */
+ /***************************************************************************/
+ const MEMORY_CHUNK * chunk;
+
+} EVEL_JSON_STACK;
+
+/**************************************************************************//**
+ * Initialize event throttling to the default state.
+ *
+ * Called from ::evel_initialize.
+ *****************************************************************************/
+void evel_throttle_initialize();
+
+/**************************************************************************//**
+ * Clean up event throttling.
+ *
+ * Called from ::evel_terminate.
+ *****************************************************************************/
+void evel_throttle_terminate();
+
+/**************************************************************************//**
+ * Handle a JSON response from the listener, as a list of tokens from JSMN.
+ *
+ * @param chunk Memory chunk containing the JSON buffer.
+ * @param json_tokens Array of tokens to handle.
+ * @param num_tokens The number of tokens to handle.
+ * @param post The memory chunk in which to place any resulting POST.
+ * @return true if the command was handled, false otherwise.
+ *****************************************************************************/
+bool evel_handle_command_list(const MEMORY_CHUNK * const chunk,
+ const jsmntok_t * const json_tokens,
+ const int num_tokens,
+ MEMORY_CHUNK * const post);
+
+/**************************************************************************//**
+ * Return the ::EVEL_THROTTLE_SPEC for a given domain.
+ *
+ * @param domain The domain for which to return state.
+ *****************************************************************************/
+EVEL_THROTTLE_SPEC * evel_get_throttle_spec(EVEL_EVENT_DOMAINS domain);
+
+/**************************************************************************//**
+ * Determine whether a field_name should be suppressed.
+ *
+ * @param throttle_spec Throttle specification for the domain being encoded.
+ * @param field_name The field name to encoded or suppress.
+ * @return true if the field_name should be suppressed, false otherwise.
+ *****************************************************************************/
+bool evel_throttle_suppress_field(EVEL_THROTTLE_SPEC * throttle_spec,
+ const char * const field_name);
+
+/**************************************************************************//**
+ * Determine whether a name-value pair should be allowed (not suppressed).
+ *
+ * @param throttle_spec Throttle specification for the domain being encoded.
+ * @param field_name The field name holding the name-value pairs.
+ * @param name The name of the name-value pair to encoded or suppress.
+ * @return true if the name-value pair should be suppressed, false otherwise.
+ *****************************************************************************/
+bool evel_throttle_suppress_nv_pair(EVEL_THROTTLE_SPEC * throttle_spec,
+ const char * const field_name,
+ const char * const name);
+
+#endif
diff --git a/VES5.0/evel/evel-library/code/evel_library/evel_voicequality.c b/VES5.0/evel/evel-library/code/evel_library/evel_voicequality.c
new file mode 100644
index 00000000..b99cfbb6
--- /dev/null
+++ b/VES5.0/evel/evel-library/code/evel_library/evel_voicequality.c
@@ -0,0 +1,661 @@
+/**************************************************************************//**
+ * @file
+ * Implementation of EVEL functions relating to the Voice Quality.
+ *
+ * License
+ * -------
+ *
+ * Copyright(c) <2016>, AT&T Intellectual Property. All other rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement: This product includes
+ * software developed by the AT&T.
+ * 4. Neither the name of AT&T nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+
+#include "evel.h"
+#include "evel_internal.h"
+#include "evel_throttle.h"
+
+/**************************************************************************//**
+ * Create a new 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 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 * 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(&voiceQuality->header,"voiceQuality");
+ 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);
+ dlist_initialize(&voiceQuality->endOfCallVqmSummaries);
+ 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);
+
+ /***************************************************************************/
+ /* 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 ");
+
+ dlist_push_last(&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);
+ }
+
+ //endOfCallVqmSummaries
+ evel_json_checkpoint(jbuf);
+ if (evel_json_open_opt_named_list(jbuf, "endOfCallVqmSummaries"))
+ {
+ vQMetricsItem = dlist_get_first(&event->endOfCallVqmSummaries);
+ while (vQMetricsItem != NULL)
+ {
+ vQMetrics = (END_OF_CALL_VOICE_QUALITY_METRICS *)vQMetricsItem->item;
+ assert(vQMetrics != NULL);
+
+ if (!evel_throttle_suppress_nv_pair(jbuf->throttle_spec,
+ "endOfCallVqmSummaries",
+ vQMetrics->adjacencyName))
+ {
+ evel_json_open_object(jbuf);
+ 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);
+ item_added = true;
+ }
+ vQMetricsItem = dlist_get_next(vQMetricsItem);
+ }
+ 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 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
+ vQMetrices = dlist_pop_last(&voiceQuality->endOfCallVqmSummaries);
+ while (vQMetrices != NULL)
+ {
+ EVEL_DEBUG("Freeing End of Call Voice Measurements Info (%s, %s)",
+ vQMetrices->adjacencyName,
+ vQMetrices->endpointDescription);
+ free(vQMetrices->adjacencyName);
+ free(vQMetrices);
+ vQMetrices = dlist_pop_last(&voiceQuality->endOfCallVqmSummaries);
+ }
+
+ //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/VES5.0/evel/evel-library/code/evel_library/hashtable.c b/VES5.0/evel/evel-library/code/evel_library/hashtable.c
new file mode 100644
index 00000000..9dc5cba3
--- /dev/null
+++ b/VES5.0/evel/evel-library/code/evel_library/hashtable.c
@@ -0,0 +1,236 @@
+/**************************************************************************//**
+ * @file
+ * A simple Hashtable.
+ *
+ * @note No thread protection so you will need to use appropriate
+ * synchronization if use spans multiple threads.
+ *
+ * License
+ * -------
+ *
+ * Copyright(c) <2016>, AT&T Intellectual Property. All other rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement: This product includes
+ * software developed by the AT&T.
+ * 4. Neither the name of AT&T nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#include <limits.h>
+#include <assert.h>
+#include <malloc.h>
+#include <string.h>
+
+#include "hashtable.h"
+
+/**************************************************************************//**
+ * Hashtable initialization.
+ *
+ * Initialize the list supplied to be empty.
+ *
+ * @param size Size of hashtable
+
+ * @returns Hashtable pointer
+******************************************************************************/
+/* Create a new hashtable. */
+HASHTABLE_T *ht_create( size_t size ) {
+
+ HASHTABLE_T *hashtable = NULL;
+ size_t i;
+
+ if( size < 1 ) return NULL;
+
+ /* Allocate the table itself. */
+ if( ( hashtable = malloc( sizeof( HASHTABLE_T ) ) ) == NULL ) {
+ return NULL;
+ }
+
+ /* Allocate pointers to the head nodes. */
+ if( ( hashtable->table = malloc( sizeof( ENTRY_T * ) * size ) ) == NULL ) {
+ return NULL;
+ }
+ for( i = 0; i < size; i++ ) {
+ hashtable->table[i] = NULL;
+ }
+
+ hashtable->size = size;
+
+ return hashtable;
+}
+
+/**************************************************************************//**
+ * Hash a string for a particular hash table.
+ *
+ * Initialize the list supplied to be empty.
+ *
+ * @param hashtable Pointer to the hashtable
+ * @param key String
+
+ * @returns hashvalue
+******************************************************************************/
+size_t ht_hash( HASHTABLE_T *hashtable, char *key )
+{
+
+ size_t hash, i;
+
+#ifdef HASHTABLE_USE_SIMPLE_HASH
+ for ( hash = i = 0; i < strlen(key); hash = hash << 8, hash += key[ i++ ] );
+#else /* Use: Jenkins' "One At a Time Hash" === Perl "Like" Hashing */
+ // http://en.wikipedia.org/wiki/Jenkins_hash_function
+ for ( hash = i = 0; i < strlen(key); ++i ) {
+ hash += key[i], hash += ( hash << 10 ), hash ^= ( hash >> 6 );
+ }
+ hash += ( hash << 3 ), hash ^= ( hash >> 11 ), hash += ( hash << 15 );
+#endif
+
+ return hash % hashtable->size;
+
+}
+
+/**************************************************************************//**
+ * Create a key-value pair.
+ *
+ * @param key key string
+ * @param value value string
+ *
+ * @returns hashtable entry
+******************************************************************************/
+ENTRY_T *ht_newpair( char *key, void *value )
+{
+ ENTRY_T *newpair;
+
+ if( ( newpair = malloc( sizeof( ENTRY_T ) ) ) == NULL ) {
+ return NULL;
+ }
+
+ if( ( newpair->key = strdup( key ) ) == NULL ) {
+ return NULL;
+ }
+
+ if( ( newpair->value = value ) == NULL ) {
+ return NULL;
+ }
+
+ newpair->next = NULL;
+
+ return newpair;
+}
+
+/**************************************************************************//**
+ * Insert a key-value pair into a hash table.
+ *
+ * @param key key string
+ * @param value value string
+ *
+ * @returns Nothing
+******************************************************************************/
+void ht_set( HASHTABLE_T *hashtable, char *key, void *value ) {
+ size_t bin = 0;
+ ENTRY_T *newpair = NULL;
+ ENTRY_T *next = NULL;
+ ENTRY_T *last = NULL;
+
+ bin = ht_hash( hashtable, key );
+
+ next = hashtable->table[ bin ];
+
+ while( next != NULL && next->key != NULL && strcmp( key, next->key ) > 0 ) {
+ last = next;
+ next = next->next;
+ }
+
+ /* There's already a pair. Let's replace that string. */
+ if( next != NULL && next->key != NULL && strcmp( key, next->key ) == 0 ) {
+
+ free( next->value );
+ next->value = value ;
+
+ /* Nope, could't find it. Time to grow a pair. */
+ } else {
+ newpair = ht_newpair( key, value );
+
+ /* We're at the start of the linked list in this bin. */
+ if( next == hashtable->table[ bin ] ) {
+ newpair->next = next;
+ hashtable->table[ bin ] = newpair;
+
+ /* We're at the end of the linked list in this bin. */
+ } else if ( next == NULL ) {
+ last->next = newpair;
+
+ /* We're in the middle of the list. */
+ } else {
+ newpair->next = next;
+ last->next = newpair;
+ }
+ }
+}
+
+/**************************************************************************//**
+ * Retrieve a key-value pair from a hash table.
+ *
+ * @param key key string
+ *
+ * @returns value string
+******************************************************************************/
+void *ht_get( HASHTABLE_T *hashtable, char *key ) {
+ size_t bin = 0;
+ ENTRY_T *pair;
+
+ bin = ht_hash( hashtable, key );
+
+ /* Step through the bin, looking for our value. */
+ pair = hashtable->table[ bin ];
+ while( pair != NULL && pair->key != NULL && strcmp( key, pair->key ) > 0 ) {
+ pair = pair->next;
+ }
+
+ /* Did we actually find anything? */
+ if( pair == NULL || pair->key == NULL || strcmp( key, pair->key ) != 0 ) {
+ return NULL;
+
+ } else {
+ return pair->value;
+ }
+
+}
+
+/*
+int main( int argc, char **argv ) {
+
+ HASHTABLE_T *hashtable = ht_create( 65536 );
+
+ ht_set( hashtable, "key1", "inky" );
+ ht_set( hashtable, "key2", "pinky" );
+ ht_set( hashtable, "key3", "blinky" );
+ ht_set( hashtable, "key4", "floyd" );
+
+ printf( "%s\n", ht_get( hashtable, "key1" ) );
+ printf( "%s\n", ht_get( hashtable, "key2" ) );
+ printf( "%s\n", ht_get( hashtable, "key3" ) );
+ printf( "%s\n", ht_get( hashtable, "key4" ) );
+
+ return 0;
+}
+*/
diff --git a/VES5.0/evel/evel-library/code/evel_library/hashtable.h b/VES5.0/evel/evel-library/code/evel_library/hashtable.h
new file mode 100644
index 00000000..6be61375
--- /dev/null
+++ b/VES5.0/evel/evel-library/code/evel_library/hashtable.h
@@ -0,0 +1,58 @@
+#ifndef HASHTABLE_INCLUDED
+#define HASHTABLE_INCLUDED
+
+/**************************************************************************//**
+ * @file
+ * A simple hashtable.
+ *
+ * @note No thread protection so you will need to use appropriate
+ * synchronization if use spans multiple threads.
+ *
+ * License
+ * -------
+ *
+ * Copyright(c) <2016>, AT&T Intellectual Property. All other rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement: This product includes
+ * software developed by the AT&T.
+ * 4. Neither the name of AT&T nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*****************************************************************************/
+
+typedef struct 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;
+
+#endif
diff --git a/VES5.0/evel/evel-library/code/evel_library/jsmn.c b/VES5.0/evel/evel-library/code/evel_library/jsmn.c
new file mode 100644
index 00000000..e7765eb1
--- /dev/null
+++ b/VES5.0/evel/evel-library/code/evel_library/jsmn.c
@@ -0,0 +1,311 @@
+#include "jsmn.h"
+
+/**
+ * Allocates a fresh unused token from the token pull.
+ */
+static jsmntok_t *jsmn_alloc_token(jsmn_parser *parser,
+ jsmntok_t *tokens, size_t num_tokens) {
+ jsmntok_t *tok;
+ if (parser->toknext >= num_tokens) {
+ return NULL;
+ }
+ tok = &tokens[parser->toknext++];
+ tok->start = tok->end = -1;
+ tok->size = 0;
+#ifdef JSMN_PARENT_LINKS
+ tok->parent = -1;
+#endif
+ return tok;
+}
+
+/**
+ * Fills token type and boundaries.
+ */
+static void jsmn_fill_token(jsmntok_t *token, jsmntype_t type,
+ int start, int end) {
+ token->type = type;
+ token->start = start;
+ token->end = end;
+ token->size = 0;
+}
+
+/**
+ * Fills next available token with JSON primitive.
+ */
+static int jsmn_parse_primitive(jsmn_parser *parser, const char *js,
+ size_t len, jsmntok_t *tokens, size_t num_tokens) {
+ jsmntok_t *token;
+ int start;
+
+ start = parser->pos;
+
+ for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
+ switch (js[parser->pos]) {
+#ifndef JSMN_STRICT
+ /* In strict mode primitive must be followed by "," or "}" or "]" */
+ case ':':
+#endif
+ case '\t' : case '\r' : case '\n' : case ' ' :
+ case ',' : case ']' : case '}' :
+ goto found;
+ }
+ if (js[parser->pos] < 32 || js[parser->pos] >= 127) {
+ parser->pos = start;
+ return JSMN_ERROR_INVAL;
+ }
+ }
+#ifdef JSMN_STRICT
+ /* In strict mode primitive must be followed by a comma/object/array */
+ parser->pos = start;
+ return JSMN_ERROR_PART;
+#endif
+
+found:
+ if (tokens == NULL) {
+ parser->pos--;
+ return 0;
+ }
+ token = jsmn_alloc_token(parser, tokens, num_tokens);
+ if (token == NULL) {
+ parser->pos = start;
+ return JSMN_ERROR_NOMEM;
+ }
+ jsmn_fill_token(token, JSMN_PRIMITIVE, start, parser->pos);
+#ifdef JSMN_PARENT_LINKS
+ token->parent = parser->toksuper;
+#endif
+ parser->pos--;
+ return 0;
+}
+
+/**
+ * Fills next token with JSON string.
+ */
+static int jsmn_parse_string(jsmn_parser *parser, const char *js,
+ size_t len, jsmntok_t *tokens, size_t num_tokens) {
+ jsmntok_t *token;
+
+ int start = parser->pos;
+
+ parser->pos++;
+
+ /* Skip starting quote */
+ for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
+ char c = js[parser->pos];
+
+ /* Quote: end of string */
+ if (c == '\"') {
+ if (tokens == NULL) {
+ return 0;
+ }
+ token = jsmn_alloc_token(parser, tokens, num_tokens);
+ if (token == NULL) {
+ parser->pos = start;
+ return JSMN_ERROR_NOMEM;
+ }
+ jsmn_fill_token(token, JSMN_STRING, start+1, parser->pos);
+#ifdef JSMN_PARENT_LINKS
+ token->parent = parser->toksuper;
+#endif
+ return 0;
+ }
+
+ /* Backslash: Quoted symbol expected */
+ if (c == '\\' && parser->pos + 1 < len) {
+ int i;
+ parser->pos++;
+ switch (js[parser->pos]) {
+ /* Allowed escaped symbols */
+ case '\"': case '/' : case '\\' : case 'b' :
+ case 'f' : case 'r' : case 'n' : case 't' :
+ break;
+ /* Allows escaped symbol \uXXXX */
+ case 'u':
+ parser->pos++;
+ for(i = 0; i < 4 && parser->pos < len && js[parser->pos] != '\0'; i++) {
+ /* If it isn't a hex character we have an error */
+ if(!((js[parser->pos] >= 48 && js[parser->pos] <= 57) || /* 0-9 */
+ (js[parser->pos] >= 65 && js[parser->pos] <= 70) || /* A-F */
+ (js[parser->pos] >= 97 && js[parser->pos] <= 102))) { /* a-f */
+ parser->pos = start;
+ return JSMN_ERROR_INVAL;
+ }
+ parser->pos++;
+ }
+ parser->pos--;
+ break;
+ /* Unexpected symbol */
+ default:
+ parser->pos = start;
+ return JSMN_ERROR_INVAL;
+ }
+ }
+ }
+ parser->pos = start;
+ return JSMN_ERROR_PART;
+}
+
+/**
+ * Parse JSON string and fill tokens.
+ */
+int jsmn_parse(jsmn_parser *parser, const char *js, size_t len,
+ jsmntok_t *tokens, unsigned int num_tokens) {
+ int r;
+ int i;
+ jsmntok_t *token;
+ int count = parser->toknext;
+
+ for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
+ char c;
+ jsmntype_t type;
+
+ c = js[parser->pos];
+ switch (c) {
+ case '{': case '[':
+ count++;
+ if (tokens == NULL) {
+ break;
+ }
+ token = jsmn_alloc_token(parser, tokens, num_tokens);
+ if (token == NULL)
+ return JSMN_ERROR_NOMEM;
+ if (parser->toksuper != -1) {
+ tokens[parser->toksuper].size++;
+#ifdef JSMN_PARENT_LINKS
+ token->parent = parser->toksuper;
+#endif
+ }
+ token->type = (c == '{' ? JSMN_OBJECT : JSMN_ARRAY);
+ token->start = parser->pos;
+ parser->toksuper = parser->toknext - 1;
+ break;
+ case '}': case ']':
+ if (tokens == NULL)
+ break;
+ type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY);
+#ifdef JSMN_PARENT_LINKS
+ if (parser->toknext < 1) {
+ return JSMN_ERROR_INVAL;
+ }
+ token = &tokens[parser->toknext - 1];
+ for (;;) {
+ if (token->start != -1 && token->end == -1) {
+ if (token->type != type) {
+ return JSMN_ERROR_INVAL;
+ }
+ token->end = parser->pos + 1;
+ parser->toksuper = token->parent;
+ break;
+ }
+ if (token->parent == -1) {
+ break;
+ }
+ token = &tokens[token->parent];
+ }
+#else
+ for (i = parser->toknext - 1; i >= 0; i--) {
+ token = &tokens[i];
+ if (token->start != -1 && token->end == -1) {
+ if (token->type != type) {
+ return JSMN_ERROR_INVAL;
+ }
+ parser->toksuper = -1;
+ token->end = parser->pos + 1;
+ break;
+ }
+ }
+ /* Error if unmatched closing bracket */
+ if (i == -1) return JSMN_ERROR_INVAL;
+ for (; i >= 0; i--) {
+ token = &tokens[i];
+ if (token->start != -1 && token->end == -1) {
+ parser->toksuper = i;
+ break;
+ }
+ }
+#endif
+ break;
+ case '\"':
+ r = jsmn_parse_string(parser, js, len, tokens, num_tokens);
+ if (r < 0) return r;
+ count++;
+ if (parser->toksuper != -1 && tokens != NULL)
+ tokens[parser->toksuper].size++;
+ break;
+ case '\t' : case '\r' : case '\n' : case ' ':
+ break;
+ case ':':
+ parser->toksuper = parser->toknext - 1;
+ break;
+ case ',':
+ if (tokens != NULL && parser->toksuper != -1 &&
+ tokens[parser->toksuper].type != JSMN_ARRAY &&
+ tokens[parser->toksuper].type != JSMN_OBJECT) {
+#ifdef JSMN_PARENT_LINKS
+ parser->toksuper = tokens[parser->toksuper].parent;
+#else
+ for (i = parser->toknext - 1; i >= 0; i--) {
+ if (tokens[i].type == JSMN_ARRAY || tokens[i].type == JSMN_OBJECT) {
+ if (tokens[i].start != -1 && tokens[i].end == -1) {
+ parser->toksuper = i;
+ break;
+ }
+ }
+ }
+#endif
+ }
+ break;
+#ifdef JSMN_STRICT
+ /* In strict mode primitives are: numbers and booleans */
+ case '-': case '0': case '1' : case '2': case '3' : case '4':
+ case '5': case '6': case '7' : case '8': case '9':
+ case 't': case 'f': case 'n' :
+ /* And they must not be keys of the object */
+ if (tokens != NULL && parser->toksuper != -1) {
+ jsmntok_t *t = &tokens[parser->toksuper];
+ if (t->type == JSMN_OBJECT ||
+ (t->type == JSMN_STRING && t->size != 0)) {
+ return JSMN_ERROR_INVAL;
+ }
+ }
+#else
+ /* In non-strict mode every unquoted value is a primitive */
+ default:
+#endif
+ r = jsmn_parse_primitive(parser, js, len, tokens, num_tokens);
+ if (r < 0) return r;
+ count++;
+ if (parser->toksuper != -1 && tokens != NULL)
+ tokens[parser->toksuper].size++;
+ break;
+
+#ifdef JSMN_STRICT
+ /* Unexpected char in strict mode */
+ default:
+ return JSMN_ERROR_INVAL;
+#endif
+ }
+ }
+
+ if (tokens != NULL) {
+ for (i = parser->toknext - 1; i >= 0; i--) {
+ /* Unmatched opened object or array */
+ if (tokens[i].start != -1 && tokens[i].end == -1) {
+ return JSMN_ERROR_PART;
+ }
+ }
+ }
+
+ return count;
+}
+
+/**
+ * Creates a new parser based over a given buffer with an array of tokens
+ * available.
+ */
+void jsmn_init(jsmn_parser *parser) {
+ parser->pos = 0;
+ parser->toknext = 0;
+ parser->toksuper = -1;
+}
+
diff --git a/VES5.0/evel/evel-library/code/evel_library/jsmn.h b/VES5.0/evel/evel-library/code/evel_library/jsmn.h
new file mode 100644
index 00000000..01ca99c8
--- /dev/null
+++ b/VES5.0/evel/evel-library/code/evel_library/jsmn.h
@@ -0,0 +1,76 @@
+#ifndef __JSMN_H_
+#define __JSMN_H_
+
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * JSON type identifier. Basic types are:
+ * o Object
+ * o Array
+ * o String
+ * o Other primitive: number, boolean (true/false) or null
+ */
+typedef enum {
+ JSMN_UNDEFINED = 0,
+ JSMN_OBJECT = 1,
+ JSMN_ARRAY = 2,
+ JSMN_STRING = 3,
+ JSMN_PRIMITIVE = 4
+} jsmntype_t;
+
+enum jsmnerr {
+ /* Not enough tokens were provided */
+ JSMN_ERROR_NOMEM = -1,
+ /* Invalid character inside JSON string */
+ JSMN_ERROR_INVAL = -2,
+ /* The string is not a full JSON packet, more bytes expected */
+ JSMN_ERROR_PART = -3
+};
+
+/**
+ * JSON token description.
+ * @param type type (object, array, string etc.)
+ * @param start start position in JSON data string
+ * @param end end position in JSON data string
+ */
+typedef struct {
+ jsmntype_t type;
+ int start;
+ int end;
+ int size;
+#ifdef JSMN_PARENT_LINKS
+ int parent;
+#endif
+} jsmntok_t;
+
+/**
+ * JSON parser. Contains an array of token blocks available. Also stores
+ * the string being parsed now and current position in that string
+ */
+typedef struct {
+ unsigned int pos; /* offset in the JSON string */
+ unsigned int toknext; /* next token to allocate */
+ int toksuper; /* superior token node, e.g parent object or array */
+} jsmn_parser;
+
+/**
+ * Create JSON parser over an array of tokens
+ */
+void jsmn_init(jsmn_parser *parser);
+
+/**
+ * Run JSON parser. It parses a JSON data string into and array of tokens, each describing
+ * a single JSON object.
+ */
+int jsmn_parse(jsmn_parser *parser, const char *js, size_t len,
+ jsmntok_t *tokens, unsigned int num_tokens);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __JSMN_H_ */
diff --git a/VES5.0/evel/evel-library/code/evel_library/license.md b/VES5.0/evel/evel-library/code/evel_library/license.md
new file mode 100644
index 00000000..9851dcac
--- /dev/null
+++ b/VES5.0/evel/evel-library/code/evel_library/license.md
@@ -0,0 +1,95 @@
+# Licensing {#licensing}
+
+# Introduction {#lic_intro}
+
+This Licensing section describes licensing of IPR in the EVEL Library.
+
+# Licensed Software {#lic_software}
+
+## EVEL Library {#lic_evel}
+
+Copyright(c) <2016>, AT&T Intellectual Property. All other rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+3. All advertising materials mentioning features or use of this software
+ must display the following acknowledgement: This product includes
+ software developed by the AT&T.
+4. Neither the name of AT&T nor the names of its contributors may be used to
+ endorse or promote products derived from this software without specific
+ prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+## libcurl {#lic_libcurl}
+
+The EVEL Library makes use of the the [cURL Library]
+(https://curl.haxx.se/libcurl/) in order to send and receive HTTP data.
+
+### License
+
+COPYRIGHT AND PERMISSION NOTICE
+
+Copyright (c) 1996 - 2016, Daniel Stenberg, daniel@haxx.se, and many
+contributors, see the THANKS file.
+
+All rights reserved.
+
+Permission to use, copy, modify, and distribute this software for any purpose
+with or without fee is hereby granted, provided that the above copyright notice
+and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN
+NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
+OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of a copyright holder shall not be
+used in advertising or otherwise to promote the sale, use or other dealings in
+this Software without prior written authorization of the copyright holder.
+
+## JSMN {#lic_jsmn}
+
+The EVEL Library makes use of the [JSMN library](http://zserge.com/jsmn.html)
+in order to decode JSON data.
+
+### License {#lic_jsmn_license}
+
+Copyright (c) 2010 Serge A. Zaitsev
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+ \ No newline at end of file
diff --git a/VES5.0/evel/evel-library/code/evel_library/metadata.c b/VES5.0/evel/evel-library/code/evel_library/metadata.c
new file mode 100644
index 00000000..dfdca052
--- /dev/null
+++ b/VES5.0/evel/evel-library/code/evel_library/metadata.c
@@ -0,0 +1,607 @@
+/**************************************************************************//**
+ * @file
+ * Wrap the OpenStack metadata service.
+ *
+ * License
+ * -------
+ *
+ * Copyright(c) <2016>, AT&T Intellectual Property. All other rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement: This product includes
+ * software developed by the AT&T.
+ * 4. Neither the name of AT&T nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#include <string.h>
+#include <assert.h>
+#include <malloc.h>
+
+#include <curl/curl.h>
+
+#include "evel.h"
+#include "evel_internal.h"
+#include "jsmn.h"
+#include "metadata.h"
+
+/**************************************************************************//**
+ * URL on the link-local IP address where we can get the metadata in
+ * machine-friendly format.
+ *****************************************************************************/
+static const char * OPENSTACK_METADATA_URL =
+ "http://169.254.169.254/openstack/latest/meta_data.json";
+
+/**************************************************************************//**
+ * How long we're prepared to wait for the metadata service to respond in
+ * seconds.
+ *****************************************************************************/
+static const int OPENSTACK_METADATA_TIMEOUT = 2;
+
+/**************************************************************************//**
+ * Size of fields extracted from metadata service.
+ *****************************************************************************/
+#define MAX_METADATA_STRING 64
+
+/**************************************************************************//**
+ * UUID of the VM extracted from the OpenStack metadata service.
+ *****************************************************************************/
+static char vm_uuid[MAX_METADATA_STRING+1] = {0};
+
+/**************************************************************************//**
+ * Name of the VM extracted from the OpenStack metadata service.
+ *****************************************************************************/
+static char vm_name[MAX_METADATA_STRING+1] = {0};
+
+/**************************************************************************//**
+ * How many metadata elements we allow for in the retrieved JSON.
+ *****************************************************************************/
+static const int MAX_METADATA_TOKENS = 128;
+
+/*****************************************************************************/
+/* Local prototypes. */
+/*****************************************************************************/
+static EVEL_ERR_CODES json_get_top_level_string(const char * json_string,
+ const jsmntok_t *tokens,
+ int json_token_count,
+ const char * key,
+ char * value);
+static EVEL_ERR_CODES json_get_string(const char * json_string,
+ const jsmntok_t *tokens,
+ int json_token_count,
+ const char * key,
+ char * value);
+static int jsoneq(const char *json, const jsmntok_t *tok, const char *s);
+
+/**************************************************************************//**
+ * Download metadata from the OpenStack metadata service.
+ *
+ * @param verbosity Controls whether to generate debug to stdout. Zero:
+ * none. Non-zero: generate debug.
+ * @returns Status code
+ * @retval EVEL_SUCCESS On success
+ * @retval ::EVEL_ERR_CODES On failure.
+ *****************************************************************************/
+EVEL_ERR_CODES openstack_metadata(int verbosity)
+{
+ int rc = EVEL_SUCCESS;
+ CURLcode curl_rc = CURLE_OK;
+ CURL * curl_handle = NULL;
+ MEMORY_CHUNK rx_chunk;
+ char curl_err_string[CURL_ERROR_SIZE] = "<NULL>";
+ jsmn_parser json_parser;
+ jsmntok_t tokens[MAX_METADATA_TOKENS];
+ int json_token_count = 0;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Initialize dummy values for the metadata - needed for test */
+ /* environments. */
+ /***************************************************************************/
+ openstack_metadata_initialize();
+
+ /***************************************************************************/
+ /* Get a curl handle which we'll use for accessing the metadata service. */
+ /***************************************************************************/
+ curl_handle = curl_easy_init();
+ if (curl_handle == NULL)
+ {
+ rc = EVEL_CURL_LIBRARY_FAIL;
+ EVEL_ERROR("Failed to get libcurl handle");
+ goto exit_label;
+ }
+
+ /***************************************************************************/
+ /* Prime the library to give friendly error codes. */
+ /***************************************************************************/
+ curl_rc = curl_easy_setopt(curl_handle,
+ CURLOPT_ERRORBUFFER,
+ curl_err_string);
+ if (curl_rc != CURLE_OK)
+ {
+ rc = EVEL_CURL_LIBRARY_FAIL;
+ EVEL_ERROR("Failed to initialize libcurl to provide friendly errors. "
+ "Error code=%d", curl_rc);
+ goto exit_label;
+ }
+
+ /***************************************************************************/
+ /* Set the URL for the metadata API. */
+ /***************************************************************************/
+ curl_rc = curl_easy_setopt(curl_handle, CURLOPT_URL, OPENSTACK_METADATA_URL);
+ if (curl_rc != CURLE_OK)
+ {
+ rc = EVEL_CURL_LIBRARY_FAIL;
+ EVEL_ERROR("Failed to initialize libcurl with the API URL. "
+ "Error code=%d (%s)", curl_rc, curl_err_string);
+ goto exit_label;
+ }
+
+ /***************************************************************************/
+ /* send all data to this function. */
+ /***************************************************************************/
+ curl_rc = curl_easy_setopt(curl_handle,
+ CURLOPT_WRITEFUNCTION,
+ evel_write_callback);
+ if (curl_rc != CURLE_OK)
+ {
+ rc = EVEL_CURL_LIBRARY_FAIL;
+ EVEL_ERROR("Failed to initialize libcurl with the write callback. "
+ "Error code=%d (%s)", curl_rc, curl_err_string);
+ goto exit_label;
+ }
+
+ /***************************************************************************/
+ /* some servers don't like requests that are made without a user-agent */
+ /* field, so we provide one. */
+ /***************************************************************************/
+ curl_rc = curl_easy_setopt(curl_handle,
+ CURLOPT_USERAGENT,
+ "libcurl-agent/1.0");
+ if (curl_rc != CURLE_OK)
+ {
+ rc = EVEL_CURL_LIBRARY_FAIL;
+ EVEL_ERROR("Failed to initialize libcurl to upload. Error code=%d (%s)",
+ curl_rc, curl_err_string);
+ goto exit_label;
+ }
+
+ /***************************************************************************/
+ /* Set the timeout for the operation. */
+ /***************************************************************************/
+ curl_rc = curl_easy_setopt(curl_handle,
+ CURLOPT_TIMEOUT,
+ OPENSTACK_METADATA_TIMEOUT);
+ if (curl_rc != CURLE_OK)
+ {
+ rc = EVEL_NO_METADATA;
+ EVEL_ERROR("Failed to initialize libcurl to set timeout. "
+ "Error code=%d (%s)", curl_rc, curl_err_string);
+ goto exit_label;
+ }
+
+ /***************************************************************************/
+ /* Create the memory chunk to be used for the response to the post. The */
+ /* will be realloced. */
+ /***************************************************************************/
+ rx_chunk.memory = malloc(1);
+ assert(rx_chunk.memory != NULL);
+ rx_chunk.size = 0;
+
+ /***************************************************************************/
+ /* Point to the data to be received. */
+ /***************************************************************************/
+ curl_rc = curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)&rx_chunk);
+ if (curl_rc != CURLE_OK)
+ {
+ rc = EVEL_CURL_LIBRARY_FAIL;
+ EVEL_ERROR("Failed to initialize libcurl to receive metadata. "
+ "Error code=%d (%s)", curl_rc, curl_err_string);
+ goto exit_label;
+ }
+ EVEL_DEBUG("Initialized data to receive");
+
+ /***************************************************************************/
+ /* If running in verbose mode generate more output. */
+ /***************************************************************************/
+ if (verbosity > 0)
+ {
+ curl_rc = curl_easy_setopt(curl_handle, CURLOPT_VERBOSE, 1L);
+ if (curl_rc != CURLE_OK)
+ {
+ rc = EVEL_CURL_LIBRARY_FAIL;
+ log_error_state("Failed to initialize libcurl to be verbose. "
+ "Error code=%d", curl_rc);
+ goto exit_label;
+ }
+ }
+
+ /***************************************************************************/
+ /* Now run off and do what you've been told! */
+ /***************************************************************************/
+ curl_rc = curl_easy_perform(curl_handle);
+ if (curl_rc != CURLE_OK)
+ {
+ rc = EVEL_CURL_LIBRARY_FAIL;
+ EVEL_ERROR("Failed to transfer the data from metadata service. "
+ "Error code=%d (%s)", curl_rc, curl_err_string);
+ }
+ else
+ {
+ /*************************************************************************/
+ /* We have some metadata available, so break it out into tokens. */
+ /*************************************************************************/
+ EVEL_DEBUG("Received metadata size = %d", rx_chunk.size);
+ EVEL_INFO("Received metadata = %s", rx_chunk.memory);
+ jsmn_init(&json_parser);
+ json_token_count = jsmn_parse(&json_parser,
+ rx_chunk.memory, rx_chunk.size,
+ tokens, MAX_METADATA_TOKENS);
+
+ /*************************************************************************/
+ /* Check that we parsed some data and that the top level is as expected. */
+ /*************************************************************************/
+ if (json_token_count < 0 || tokens[0].type != JSMN_OBJECT)
+ {
+ rc = EVEL_BAD_METADATA;
+ EVEL_ERROR("Failed to parse received JSON OpenStack metadata. "
+ "Error code=%d", json_token_count);
+ goto exit_label;
+ }
+ else
+ {
+ EVEL_DEBUG("Extracted %d tokens from the JSON OpenStack metadata. ",
+ json_token_count);
+ }
+
+ /*************************************************************************/
+ /* Find the keys we want from the metadata. */
+ /*************************************************************************/
+ if (json_get_string(rx_chunk.memory,
+ tokens,
+ json_token_count,
+ "uuid",
+ vm_uuid) != EVEL_SUCCESS)
+ {
+ rc = EVEL_BAD_METADATA;
+ EVEL_ERROR("Failed to extract UUID from OpenStack metadata");
+ }
+ else
+ {
+ EVEL_DEBUG("UUID: %s", vm_uuid);
+ }
+ if (json_get_top_level_string(rx_chunk.memory,
+ tokens,
+ json_token_count,
+ "name",
+ vm_name) != EVEL_SUCCESS)
+ {
+ rc = EVEL_BAD_METADATA;
+ EVEL_ERROR("Failed to extract VM Name from OpenStack metadata");
+ }
+ else
+ {
+ EVEL_DEBUG("VM Name: %s", vm_name);
+ }
+ }
+
+exit_label:
+
+ /***************************************************************************/
+ /* Shut down the cURL library in a tidy manner. */
+ /***************************************************************************/
+ if (curl_handle != NULL)
+ {
+ curl_easy_cleanup(curl_handle);
+ curl_handle = NULL;
+ }
+ free(rx_chunk.memory);
+
+ EVEL_EXIT();
+ return rc;
+}
+
+/**************************************************************************//**
+ * Initialize default values for vm_name and vm_uuid - for testing purposes.
+ *****************************************************************************/
+void openstack_metadata_initialize()
+{
+ strncpy(vm_uuid,
+ "Dummy VM UUID - No Metadata available",
+ MAX_METADATA_STRING);
+ strncpy(vm_name,
+ "Dummy VM name - No Metadata available",
+ MAX_METADATA_STRING);
+}
+
+/**************************************************************************//**
+ * Get a string value from supplied JSON by matching the key.
+ *
+ * As the structure of the metadata we're looking at is pretty straightforward
+ * we don't do anything complex (a la XPath) to extract nested keys with the
+ * same leaf name, for example. Simply walk the structure until we find a
+ * string with the correct value.
+ *
+ * @param[in] json_string The string which contains the JSON and has already
+ * been parsed.
+ * @param[in] tokens The tokens which the JSON parser found in the JSON.
+ * @param[in] json_token_count How many tokens were found.
+ * @param[in] key The key we're looking for.
+ * @param[out] value The string we found at @p key.
+ *
+ * @returns Status code
+ * @retval EVEL_SUCCESS On success - contents of @p value updated.
+ * @retval EVEL_JSON_KEY_NOT_FOUND Key not found - @p value not updated.
+ * @retval EVEL_BAD_JSON Parser hit unexpected data - @p value not
+ * updated.
+ *****************************************************************************/
+static EVEL_ERR_CODES json_get_string(const char * json_string,
+ const jsmntok_t * tokens,
+ int json_token_count,
+ const char * key,
+ char * value)
+{
+ EVEL_ERR_CODES rc = EVEL_JSON_KEY_NOT_FOUND;
+ int token_num = 0;
+ int token_len = 0;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check assumptions. */
+ /***************************************************************************/
+ assert(json_string != NULL);
+ assert(tokens != NULL);
+ assert(json_token_count >= 0);
+ assert(key != NULL);
+ assert(value != NULL);
+
+ for (token_num = 0; token_num < json_token_count; token_num++)
+ {
+ switch(tokens[token_num].type)
+ {
+ case JSMN_OBJECT:
+ EVEL_DEBUG("Skipping object");
+ break;
+
+ case JSMN_ARRAY:
+ EVEL_DEBUG("Skipping array");
+ break;
+
+ case JSMN_STRING:
+ /***********************************************************************/
+ /* This is a string, so may be what we want. Compare keys. */
+ /***********************************************************************/
+ if (jsoneq(json_string, &tokens[token_num], key) == 0)
+ {
+ token_len = tokens[token_num + 1].end - tokens[token_num + 1].start;
+ EVEL_DEBUG("Token %d len %d matches at %d to %d", token_num,
+ tokens[token_num + 1].start,
+ tokens[token_num + 1].end);
+ strncpy(value, json_string + tokens[token_num + 1].start, token_len);
+ value[token_len] = '\0';
+ EVEL_DEBUG("Extracted key: \"%s\" Value: \"%s\"", key, value);
+ rc = EVEL_SUCCESS;
+ goto exit_label;
+ }
+ else
+ {
+ EVEL_DEBUG("String key did not match");
+ }
+
+ /***********************************************************************/
+ /* Step over the value, whether we used it or not. */
+ /***********************************************************************/
+ token_num++;
+ break;
+
+ case JSMN_PRIMITIVE:
+ EVEL_INFO("Skipping primitive");
+ break;
+
+ case JSMN_UNDEFINED:
+ default:
+ rc = EVEL_BAD_JSON_FORMAT;
+ EVEL_ERROR("Unexpected JSON format at token %d (%d)",
+ token_num,
+ tokens[token_num].type);
+ goto exit_label;
+ }
+ }
+
+exit_label:
+ EVEL_EXIT();
+ return rc;
+}
+
+/**************************************************************************//**
+ * Get a top-level string value from supplied JSON by matching the key.
+ *
+ * Unlike json_get_string, this only returns a value that is in the top-level
+ * JSON object.
+ *
+ * @param[in] json_string The string which contains the JSON and has already
+ * been parsed.
+ * @param[in] tokens The tokens which the JSON parser found in the JSON.
+ * @param[in] json_token_count How many tokens were found.
+ * @param[in] key The key we're looking for.
+ * @param[out] value The string we found at @p key.
+ *
+ * @returns Status code
+ * @retval EVEL_SUCCESS On success - contents of @p value updated.
+ * @retval EVEL_JSON_KEY_NOT_FOUND Key not found - @p value not updated.
+ * @retval EVEL_BAD_JSON Parser hit unexpected data - @p value not
+ * updated.
+ *****************************************************************************/
+static EVEL_ERR_CODES json_get_top_level_string(const char * json_string,
+ const jsmntok_t * tokens,
+ int json_token_count,
+ const char * key,
+ char * value)
+{
+ EVEL_ERR_CODES rc = EVEL_JSON_KEY_NOT_FOUND;
+ int token_num = 0;
+ int token_len = 0;
+ int bracket_count = 0;
+ int string_index = 0;
+ int increment = 0;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check assumptions. */
+ /***************************************************************************/
+ assert(json_string != NULL);
+ assert(tokens != NULL);
+ assert(json_token_count >= 0);
+ assert(key != NULL);
+ assert(value != NULL);
+
+ for (token_num = 0; token_num < json_token_count; token_num++)
+ {
+ switch(tokens[token_num].type)
+ {
+ case JSMN_OBJECT:
+ EVEL_DEBUG("Skipping object");
+ break;
+
+ case JSMN_ARRAY:
+ EVEL_DEBUG("Skipping array");
+ break;
+
+ case JSMN_STRING:
+ /***********************************************************************/
+ /* This is a string, so may be what we want. Compare keys. */
+ /***********************************************************************/
+ if (jsoneq(json_string, &tokens[token_num], key) == 0)
+ {
+ /*********************************************************************/
+ /* Count the difference in the number of opening and closing */
+ /* brackets up to this token. This needs to be 1 for a top-level */
+ /* string. Let's just hope we don't have any strings containing */
+ /* brackets. */
+ /*********************************************************************/
+ increment = ((string_index < tokens[token_num].start) ? 1 : -1);
+
+ while (string_index != tokens[token_num].start)
+ {
+ if (json_string[string_index] == '{')
+ {
+ bracket_count += increment;
+ }
+ else if (json_string[string_index] == '}')
+ {
+ bracket_count -= increment;
+ }
+
+ string_index += increment;
+ }
+
+ if (bracket_count == 1)
+ {
+ token_len = tokens[token_num + 1].end - tokens[token_num + 1].start;
+ EVEL_DEBUG("Token %d len %d matches at top level at %d to %d",
+ token_num,
+ tokens[token_num + 1].start,
+ tokens[token_num + 1].end);
+ strncpy(value, json_string + tokens[token_num + 1].start, token_len);
+ value[token_len] = '\0';
+ EVEL_DEBUG("Extracted key: \"%s\" Value: \"%s\"", key, value);
+ rc = EVEL_SUCCESS;
+ goto exit_label;
+ }
+ else
+ {
+ EVEL_DEBUG("String key did match, but not at top level");
+ }
+ }
+ else
+ {
+ EVEL_DEBUG("String key did not match");
+ }
+
+ /***********************************************************************/
+ /* Step over the value, whether we used it or not. */
+ /***********************************************************************/
+ token_num++;
+ break;
+
+ case JSMN_PRIMITIVE:
+ EVEL_INFO("Skipping primitive");
+ break;
+
+ case JSMN_UNDEFINED:
+ default:
+ rc = EVEL_BAD_JSON_FORMAT;
+ EVEL_ERROR("Unexpected JSON format at token %d (%d)",
+ token_num,
+ tokens[token_num].type);
+ goto exit_label;
+ }
+ }
+
+exit_label:
+ EVEL_EXIT();
+ return rc;
+}
+
+/**************************************************************************//**
+ * Compare a JSON string token with a value.
+ *
+ * @param[in] json The string which contains the JSON and has already been
+ * parsed.
+ * @param[in] tok The token which the JSON parser found in the JSON.
+ * @param[in] s The string we're looking for.
+ *
+ * @returns Whether the token matches the string or not.
+ * @retval 0 Value matches
+ * @retval -1 Value does not match.
+ *****************************************************************************/
+static int jsoneq(const char *json, const jsmntok_t *tok, const char *s) {
+ if (tok->type == JSMN_STRING && (int) strlen(s) == tok->end - tok->start &&
+ strncmp(json + tok->start, s, tok->end - tok->start) == 0) {
+ return 0;
+ }
+ return -1;
+}
+
+/**************************************************************************//**
+ * Get the VM name provided by the metadata service.
+ *
+ * @returns VM name
+ *****************************************************************************/
+const char *openstack_vm_name()
+{
+ return vm_name;
+}
+
+/**************************************************************************//**
+ * Get the VM UUID provided by the metadata service.
+ *
+ * @returns VM UUID
+ *****************************************************************************/
+const char *openstack_vm_uuid()
+{
+ return vm_uuid;
+}
diff --git a/VES5.0/evel/evel-library/code/evel_library/metadata.h b/VES5.0/evel/evel-library/code/evel_library/metadata.h
new file mode 100644
index 00000000..d9d0cc1a
--- /dev/null
+++ b/VES5.0/evel/evel-library/code/evel_library/metadata.h
@@ -0,0 +1,72 @@
+#ifndef METADATA_INCLUDED
+#define METADATA_INCLUDED
+/**************************************************************************//**
+ * @file
+ * Wrap the OpenStack metadata service.
+ *
+ * License
+ * -------
+ *
+ * Copyright(c) <2016>, AT&T Intellectual Property. All other rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement: This product includes
+ * software developed by the AT&T.
+ * 4. Neither the name of AT&T nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+
+#include "evel.h"
+
+/**************************************************************************//**
+ * Download metadata from the OpenStack metadata service.
+ *
+ * @param verbosity Controls whether to generate debug to stdout. Zero:
+ * none. Non-zero: generate debug.
+ * @returns Status code
+ * @retval EVEL_SUCCESS On success
+ * @retval ::EVEL_ERR_CODES On failure.
+ *****************************************************************************/
+EVEL_ERR_CODES openstack_metadata(int verbosity);
+
+/**************************************************************************//**
+ * Initialize default values for vm_name and vm_uuid - for testing purposes.
+ *****************************************************************************/
+void openstack_metadata_initialize();
+
+/**************************************************************************//**
+ * Get the VM name provided by the metadata service.
+ *
+ * @returns VM name
+ *****************************************************************************/
+const char *openstack_vm_name();
+
+/**************************************************************************//**
+ * Get the VM UUID provided by the metadata service.
+ *
+ * @returns VM UUID
+ *****************************************************************************/
+const char *openstack_vm_uuid();
+
+#endif
diff --git a/VES5.0/evel/evel-library/code/evel_library/quickstart.md b/VES5.0/evel/evel-library/code/evel_library/quickstart.md
new file mode 100644
index 00000000..1c735cc4
--- /dev/null
+++ b/VES5.0/evel/evel-library/code/evel_library/quickstart.md
@@ -0,0 +1,445 @@
+# Quick Start Guide {#quickstart}
+
+# Introduction {#qs_intro}
+
+This Quick-Start section describes how to:
+
+ * Install and compile the supplied library code
+ * Integrate an existing project to use the EVEL library
+
+# Installation {#qs_install}
+
+The library is supplied as a source-code compressed-tar file. It is
+straightforward to install and build to integrate with an existing or new
+development project.
+
+## Unpack the Source Code {#qs_unpack}
+
+The file should unpacked into your development environment:
+```
+$ mkdir evel
+$ cd evel
+$ tar zxvf evel-library-package.tgz
+```
+### Satisfy Dependencies {#qs_depend}
+
+Note that all commands in this section are based on CentOS package management
+tools and you may need to substitute the appropriate tools/packages for your
+distribution, for example `apt-get` for Ubuntu.
+
+Ensure that GCC development tools are available.
+
+```
+$ sudo yum install gcc
+```
+Additionally, the library has a dependency on the cURL library, so you'll need
+the development tools for libCurl installed. (At runtime, only the runtime
+library is required, of course.)
+
+```
+$ sudo yum install libcurl-devel
+```
+If you wish to make the project documentation, then Doxygen and Graphviz are
+required. (Again, this is only in the development environment, not the runtime
+environment!)
+
+```
+$ sudo yum install doxygen graphviz
+```
+
+Note that some distributions have quite old versions of Doxygen by default and
+it may be necessary to install a later version to use all the features.
+
+If you want to build PDFs from the LaTeX you will need a texlive install.
+
+```
+$ sudo yum install texlive
+```
+
+### Test Build {#qs_build}
+Make sure that the library makes cleanly:
+
+```
+$ cd bldjobs
+$ make
+Making dependency file evel_unit.d for evel_unit.c
+Making dependency file evel_test_control.d for evel_test_control.c
+Making dependency file evel_demo.d for evel_demo.c
+Making dependency file jsmn.d for jsmn.c
+Making dependency file evel_logging.d for evel_logging.c
+Making dependency file evel_event_mgr.d for evel_event_mgr.c
+Making dependency file evel_internal_event.d for evel_internal_event.c
+Making dependency file evel_throttle.d for evel_throttle.c
+Making dependency file evel_syslog.d for evel_syslog.c
+Making dependency file evel_strings.d for evel_strings.c
+Making dependency file evel_state_change.d for evel_state_change.c
+Making dependency file evel_scaling_measurement.d for evel_scaling_measurement.c
+Making dependency file evel_signaling.d for evel_signaling.c
+Making dependency file evel_service.d for evel_service.c
+Making dependency file evel_reporting_measurement.d for evel_reporting_measurement.c
+Making dependency file evel_json_buffer.d for evel_json_buffer.c
+Making dependency file evel_other.d for evel_other.c
+Making dependency file evel_option.d for evel_option.c
+Making dependency file evel_mobile_flow.d for evel_mobile_flow.c
+Making dependency file evel_fault.d for evel_fault.c
+Making dependency file evel_event.d for evel_event.c
+Making dependency file double_list.d for double_list.c
+Making dependency file ring_buffer.d for ring_buffer.c
+Making dependency file metadata.d for metadata.c
+Making dependency file evel.d for evel.c
+Making evel.o from evel.c
+Making metadata.o from metadata.c
+Making ring_buffer.o from ring_buffer.c
+Making double_list.o from double_list.c
+Making evel_event.o from evel_event.c
+Making evel_fault.o from evel_fault.c
+Making evel_mobile_flow.o from evel_mobile_flow.c
+Making evel_option.o from evel_option.c
+Making evel_other.o from evel_other.c
+Making evel_json_buffer.o from evel_json_buffer.c
+Making evel_reporting_measurement.o from evel_reporting_measurement.c
+Making evel_service.o from evel_service.c
+Making evel_signaling.o from evel_signaling.c
+Making evel_scaling_measurement.o from evel_scaling_measurement.c
+Making evel_state_change.o from evel_state_change.c
+Making evel_strings.o from evel_strings.c
+Making evel_syslog.o from evel_syslog.c
+Making evel_throttle.o from evel_throttle.c
+Making evel_internal_event.o from evel_internal_event.c
+Making evel_event_mgr.o from evel_event_mgr.c
+Making evel_logging.o from evel_logging.c
+Making jsmn.o from jsmn.c
+Linking API Shared Library
+Linking API Static Library
+Making evel_demo.o from evel_demo.c
+Making evel_test_control.o from evel_test_control.c
+Linking EVEL demo
+Making EVEL training
+$
+```
+You should now be able to run the demo CLI application. Since it will want to
+dynamically link to the library that you've just made, you will need to set
+your `LD_LIBRARY_PATH` appropriately first. Make sure that you specify
+your actual directory paths correctly in the following:
+
+```
+$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/centos/evel/libs/x86_64
+$ ../output/x86_64/evel_demo
+evel_demo [--help]
+ --fqdn <domain>
+ --port <port_number>
+ [--path <path>]
+ [--topic <topic>]
+ [--username <username>]
+ [--password <password>]
+ [--https]
+ [--cycles <cycles>]
+ [--nothrott]
+
+Demonstrate use of the ECOMP Vendor Event Listener API.
+
+ -h Display this usage message.
+ --help
+
+ -f The FQDN or IP address to the RESTful API.
+ --fqdn
+
+ -n The port number the RESTful API.
+ --port
+
+ -p The optional path prefix to the RESTful API.
+ --path
+
+ -t The optional topic part of the RESTful API.
+ --topic
+
+ -u The optional username for basic authentication of requests.
+ --username
+
+ -w The optional password for basic authentication of requests.
+ --password
+
+ -s Use HTTPS rather than HTTP for the transport.
+ --https
+
+ -c Loop <cycles> times round the main loop. Default = 1.
+ --cycles
+
+ -v Generate much chattier logs.
+ --verbose
+
+ -x Exclude throttling commands from demonstration.
+ --nothrott
+
+$
+```
+Assuming that all worked as expected, you are ready to start integrating with
+your application. It probably makes sense to make the LD_LIBRARY_PATH change
+above permanent by incorporating it into your `.bash_profile` file.
+
+### Project Documentation {#qs_build_docs}
+
+The source comes with its own documentation included. The documentation can be
+built using the `docs` target in the Makefile. By default this builds HTML
+and LaTeX documentation, the latter being used to prepare PDFs.
+
+To make the documentation:
+```
+$ cd bldjobs
+$ make docs
+Cleaning docs...
+Making Doxygen documentation
+$
+```
+
+There is a make target that is intended to install the documentation on a
+"team server" - it will need adaptation for your team's environment - see the
+`docs_install` target in the Makefile:
+
+```
+$ make docs_install
+Cleaning docs...
+Making Doxygen documentation
+Copying docs to team web-server...
+Enter passphrase for key '/data/home/.ssh/id_rsa':
+annotated.html 100% 8088 7.9KB/s 00:00
+arrowdown.png 100% 246 0.2KB/s 00:00
+arrowright.png 100% 229 0.2KB/s 00:00
+ ...
+$
+```
+
+# Project Integration {#qs_integrate}
+
+There are two key steps to the integration which have to be undertaken:
+
+ * Initialization/Termination of the library.
+ * Creation & posting of individual events.
+
+Additionally, it may be necessary to consider changes to the EVEL library's
+source code if assumptions made by the library are either not satisfied or
+inconvenient. In particular:
+
+ * If the project already uses libcurl then the global initialization of the
+ library should be removed from the _EVEL Library_.
+ * The _EVEL Library_ uses `syslog` for event logging. If the project uses a
+ different event logging process, then EVEL's event logging macros should be
+ rewritten appropriately.
+
+These steps are considered in the [Normal Use](@ref qs_normal_use) and
+[EVEL Adaptation](@ref qs_adaptation) sections below.
+
+## Normal Use {#qs_normal_use}
+
+The _EVEL Library_ should be integrated with your project at a per-process
+level: each process is an independent client of the ECOMP Vendor Event Listener
+API.
+
+### Initialization {#qs_initialize}
+
+The _EVEL Library_ should be initialized before the process becomes
+multi-threaded. This constraint arises from the use of libcurl which imposes
+the constraint that initialization occurs before the system is multi-threaded.
+This is described in more detail in the libcurl documentation for the
+[curl_global_init](https://curl.haxx.se/libcurl/c/curl_global_init.html)
+function.
+
+Initialization stores configuration of the Vendor Event Listener API's details,
+such as the FQDN or IP address of the service, so the initializing process must
+have either extracted this information from its configuration or have this
+information "hard-wired" into the application, so that it is available at the
+point the `evel_initialize()` function is called:
+
+```C
+ #include "evel.h"
+ ...
+ if (evel_initialize(api_fqdn,
+ api_port,
+ api_path,
+ api_topic,
+ api_secure,
+ "Alice",
+ "This isn't very secure!",
+ EVEL_SOURCE_VIRTUAL_MACHINE,
+ "EVEL demo client",
+ verbose_mode))
+ {
+ fprintf(stderr, "Failed to initialize the EVEL library!!!");
+ exit(-1);
+ }
+ ...
+```
+Once initialization has occurred successfully, the application may raise events
+and may also use the logging functions such as EVEL_INFO().
+
+Initialization is entirely local (there is no interaction with the service) so
+it is very unlikely to fail, unless the application environment is seriously
+degraded.
+
+### Event Generation {#qs_generate}
+
+Generating events is a two stage process:
+
+ 1. Firstly, the _EVEL Library_ is called to allocate an event of the correct
+ type.
+ * If this is successful, the caller is given a pointer to the event.
+ * All mandatory fields on the event are provided to this factory function
+ and are thereafter immutable.
+ * The application may add any necessary optional fields to the event, using
+ the pointer previously returned.
+ 2. The event is sent to the JSON API using the evel_post_event() function.
+ * At this point, the application relinquishes all responsibility for the
+ event:
+ * It will be posted to the JSON API, if possible.
+ * Whether or not the posting is successful, the memory used will be
+ freed.
+
+In practice this looks like:
+
+```C
+ #include "evel.h"
+ ...
+
+ /***************************************************************************/
+ /* Create a new Fault object, setting mandatory fields as we do so... */
+ /***************************************************************************/
+ fault = evel_new_fault("My alarm condition",
+ "It broke very badly",
+ EVEL_PRIORITY_NORMAL,
+ EVEL_SEVERITY_MAJOR);
+ if (fault != NULL)
+ {
+ /*************************************************************************/
+ /* We have a Fault object - add some optional fields to it... */
+ /*************************************************************************/
+ evel_fault_type_set(fault, "Bad things happen...");
+ evel_fault_interface_set(fault, "My Interface Card");
+ evel_fault_addl_info_add(fault, "name1", "value1");
+ evel_fault_addl_info_add(fault, "name2", "value2");
+
+ /*************************************************************************/
+ /* Finally, post the Fault. In practice this will only ever fail if */
+ /* local ring-buffer is full because of event overload. */
+ /*************************************************************************/
+ evel_rc = evel_post_event((EVENT_HEADER *)fault);
+ if (evel_rc != EVEL_SUCCESS)
+ {
+ EVEL_ERROR("Post failed %d (%s)", evel_rc, evel_error_string());
+ }
+ }
+ ...
+```
+### Event Types {#qs_event_types}
+
+The _EVEL Library_ supports the following types of events:
+
+ 1. Faults
+
+ These represent the **fault** domain in the event schema.
+
+ 2. Measurements
+
+ These represent the **measurementsForVfScaling** domain in the event
+ schema.
+
+ 3. Reports
+
+ This is an experimental type, designed to allow VNFs to report
+ application-level statistics unencumbered with platform measurements.
+ The formal AT&T schema has been updated to include this experimental
+ type as **measurementsForVfReporting**.
+
+ 4. Mobile Flow
+
+ These represent the **mobileFlow** domain in the event schema.
+
+ 5. Other
+
+ These represent the **other** domain in the event schema.
+
+ 6. Service Events
+
+ These represent the **serviceEvents** domain in the event schema.
+
+ 7. Signaling
+
+ These represent the **signaling** domain in the event schema.
+
+ 8. State Change
+
+ These represent the **stateChange** domain in the event schema.
+
+ 9. Syslog
+
+ These represent the **syslog** domain in the event schema.
+
+### Throttling {#qs_throttling}
+
+The _EVEL library_ supports the following command types as defined in the JSON API:
+
+ 1. commandType: throttlingSpecification
+
+ This is handled internally by the EVEL library, which stores the provided
+ throttling specification internally and applies it to all subsequent events.
+
+ 2. commandType: provideThrottlingState
+
+ This is handled internally by the EVEL library, which returns the current
+ throttling specification for each domain.
+
+ 3. commandType: measurementIntervalChange
+
+ This is handled by the EVEL library, which makes the latest measurement
+ interval available via the ::evel_get_measurement_interval function.
+ The application is responsible for checking and adhering to the latest
+ provided interval.
+
+### Termination {#qs_termination}
+
+Termination of the _EVEL Library_ is swift and brutal! Events in the buffer
+at the time are "dropped on the floor" rather than waiting for the buffer to
+deplete first.
+
+```C
+ #include "evel.h"
+ ...
+
+ /***************************************************************************/
+ /* Shutdown the library. */
+ /***************************************************************************/
+ evel_terminate();
+
+ ...
+```
+
+## EVEL Adaptation {#qs_adaptation}
+
+The _EVEL Library_ is relatively simple and should be easy to adapt into other
+project environments.
+
+### LibcURL Lifecycle
+
+There are two circumstances where initialization of libcurl may be required:
+
+ 1. If libcurl is used by the project already, and therefore already takes
+ responsibility of its initialization, then the libcurl initialization and
+ termination functions should be removed from evel_initialize() and
+ evel_terminate() respectively.
+ 2. If the project is unable to satisfy the constraint that libcurl
+ initialization takes place in a single-threaded environment at the point
+ that the _EVEL Library_ can be initialized (for example, if MT code is
+ necessary to read the configuration parameters required for
+ _EVEL Library_ initialization) then it may be necessary to extract the
+ libcurl functions and call them separately, earlier in the program's
+ operation.
+
+### Event Logging
+
+The _EVEL Library_ uses `syslog` for logging. If this is inappropriate then
+the log_debug() and log_initialize() functions should be rewritten accordingly.
+
+**Note**: it would be a really bad idea to use the _EVEL Library_ itself for this
+logging function.
+[Turtles all the way down...](https://en.wikipedia.org/wiki/Turtles_all_the_way_down)
+
+ \ No newline at end of file
diff --git a/VES5.0/evel/evel-library/code/evel_library/readme.md b/VES5.0/evel/evel-library/code/evel_library/readme.md
new file mode 100644
index 00000000..3cf57083
--- /dev/null
+++ b/VES5.0/evel/evel-library/code/evel_library/readme.md
@@ -0,0 +1,236 @@
+# EVEL Library Overview {#mainpage}
+
+# Introduction
+
+The ECOMP Vendor Event Listener ("EVEL") library encapsulates the use of
+AT&T's JSON API to the collector function within the ECOMP infrastructure.
+
+As such, it provides a reference implementation of the EVEL JSON API which
+can either be directly as part of a project or can be used to inform the
+independent implementation of an equivalent binding to the API in another
+development environment.
+
+This section provides an overview of the library and how it is integrated
+into the target application. If all you want is a set of instructions to
+get you started, the @ref quickstart "Quick Start" section is for you. If
+you want a more in-depth understanding of the _EVEL Library_ then this section
+provides an overview and then you can read the detailed API documentation for
+each function. The documentation for evel.h is a good starting point, since
+that defines the public API of the _EVEL Library_.
+
+# Library Structure
+
+The API is designed to be used on multi-process platforms where each process
+may be multi-threaded. Each process using this library will create an
+independent HTTP client (using libcURL). Each process will have a single
+thread running the HTTP client but that thread receives work on a
+ring-buffer from however may threads are required to implement the function.
+
+**Note**: libcurl imposes a constraint that it is initialized before
+the process starts multi-threaded operation.
+
+# Typical Usage
+
+The library is designed to be very straightforward to use and lightweight to
+integrate into projects. The only serious external dependency is on libcURL.
+
+The supplied Makefile produces a single library **libevel.so** or
+**libevel.a** which your application needs to be linked against.
+
+Each process within the application which wants to generate events needs to
+call ::evel_initialize at the start of day (observing the above warning
+about not being MT safe at this stage.) The initialization specifies the
+details of where the API is located. Management of configuration is the
+responsibility of the client.
+
+Once initialized, and now MT-safe, there are factory functions to produce
+new events:
+- Faults - ::evel_new_fault
+- Measurements - ::evel_new_measurement
+- Report - ::evel_new_report
+- State Change - ::evel_new_state_change
+- Syslog - ::evel_new_syslog
+- Other - ::evel_new_other
+- Mobile Flow - ::evel_new_mobile_flow
+
+There is also a factory function ::evel_new_mobile_gtp_flow_metrics to create
+the parameter gtp_per_flow_metrics, which is then configured and passed to the
+::evel_new_mobile_flow factory function.
+
+The event structures are initialized with mandatory fields at the point of
+creation and optional fields may be added thereafter. Once set, values in
+the structures are immutable.
+
+Once the event is prepared, it may be posted, using ::evel_post_event, at
+which point the calling thread relinquishes all responsibility for the
+event. It will be freed once successfully or unsuccessfully posted to the
+API. If, for any reason, you change your mind and don't want to post a
+created event, it must be destroyed with ::evel_free_event.
+
+Finally, at the end of day, the library can be terminated cleanly by calling
+::evel_terminate.
+
+## Example Code
+
+The following fragment illustrates the above usage:
+
+```C
+
+ if (evel_initialize(api_fqdn,
+ api_port,
+ api_path,
+ api_topic,
+ api_secure,
+ "Alice",
+ "This isn't very secure!",
+ EVEL_SOURCE_VIRTUAL_MACHINE,
+ "EVEL demo client",
+ verbose_mode))
+ {
+ fprintf(stderr, "Failed to initialize the EVEL library!!!");
+ exit(-1);
+ }
+
+ ...
+
+ fault = evel_new_fault("My alarm condition",
+ "It broke very badly",
+ EVEL_PRIORITY_NORMAL,
+ EVEL_SEVERITY_MAJOR);
+ if (fault != NULL)
+ {
+ evel_fault_type_set(fault, "Bad things happen...");
+ evel_fault_interface_set(fault, "My Interface Card");
+ evel_fault_addl_info_add(fault, "name1", "value1");
+ evel_fault_addl_info_add(fault, "name2", "value2");
+ evel_rc = evel_post_event((EVENT_HEADER *)fault);
+ if (evel_rc != EVEL_SUCCESS)
+ {
+ EVEL_ERROR("Post failed %d (%s)", evel_rc, evel_error_string());
+ }
+ }
+
+```
+
+The public API to the library is defined in evel.h. The internal APIs
+within library are defined in separate headers (<em>e.g.</em>
+evel_internal.h), but these should not need to be included by the code
+using the library.
+
+# Example Application
+
+A simple command-line application to generate events is provided as part of
+the source package (the above code fragment is taken from that application).
+
+The following illustrates its operation to a co-located "test-collector":
+```
+$ ./evel_demo --fqdn 127.0.0.1 --port 30000 --path vendor_event_listener --topic example_vnf --verbose
+./evel_demo built Feb 26 2016 18:14:48
+* About to connect() to 169.254.169.254 port 80 (#0)
+* Trying 169.254.169.254... * Timeout
+* connect() timed out!
+* Closing connection #0
+* About to connect() to 127.0.0.1 port 30000 (#0)
+* Trying 127.0.0.1... * connected
+* Connected to 127.0.0.1 (127.0.0.1) port 30000 (#0)
+* Server auth using Basic with user 'Alice'
+> POST /vendor_event_listener/eventListener/v1/example_vnf HTTP/1.1
+Authorization: Basic QWxpY2U6VGhpcyBpc24ndCB2ZXJ5IHNlY3VyZSE=
+User-Agent: libcurl-agent/1.0
+Host: 127.0.0.1:30000
+Accept: */*
+Content-type: application/json
+Content-Length: 510
+
+* HTTP 1.0, assume close after body
+< HTTP/1.0 204 No Content
+< Date: Fri, 04 Mar 2016 15:37:22 GMT
+< Server: WSGIServer/0.1 Python/2.6.6
+<
+* Closing connection #0
+* About to connect() to 127.0.0.1 port 30000 (#0)
+* Trying 127.0.0.1... * connected
+* Connected to 127.0.0.1 (127.0.0.1) port 30000 (#0)
+* Server auth using Basic with user 'Alice'
+> POST /vendor_event_listener/eventListener/v1/example_vnf HTTP/1.1
+Authorization: Basic QWxpY2U6VGhpcyBpc24ndCB2ZXJ5IHNlY3VyZSE=
+User-Agent: libcurl-agent/1.0
+Host: 127.0.0.1:30000
+Accept: */*
+Content-type: application/json
+Content-Length: 865
+
+* HTTP 1.0, assume close after body
+< HTTP/1.0 204 No Content
+< Date: Fri, 04 Mar 2016 15:37:22 GMT
+< Server: WSGIServer/0.1 Python/2.6.6
+<
+* Closing connection #0
+* About to connect() to 127.0.0.1 port 30000 (#0)
+* Trying 127.0.0.1... * connected
+* Connected to 127.0.0.1 (127.0.0.1) port 30000 (#0)
+* Server auth using Basic with user 'Alice'
+> POST /vendor_event_listener/eventListener/v1/example_vnf HTTP/1.1
+Authorization: Basic QWxpY2U6VGhpcyBpc24ndCB2ZXJ5IHNlY3VyZSE=
+User-Agent: libcurl-agent/1.0
+Host: 127.0.0.1:30000
+Accept: */*
+Content-type: application/json
+Content-Length: 2325
+
+* HTTP 1.0, assume close after body
+< HTTP/1.0 204 No Content
+< Date: Fri, 04 Mar 2016 15:37:22 GMT
+< Server: WSGIServer/0.1 Python/2.6.6
+<
+* Closing connection #0
+^C
+
+Interrupted - quitting!
+$
+```
+
+# Restrictions and Limitations
+
+## Constraint Validation
+
+The _EVEL Library_ has been designed to be production-safe code with the
+emphasis at this stage being in correctness of operation rather than
+raw performance.
+
+The API tries to check as much information as possible to avoid misuse and
+will **assert()** if constraints are not satisfied. This is likely to lead
+to the rapid discovery of coding errors by programmers, but does mean that
+the application can fail abruptly if the library is misused in any way.
+
+## Performance
+
+The default Makefile avoids aggressive optimizations so that any core-files
+are easy to interpret. Production code should use greater optimization
+levels.
+
+As described above, the HTTP client is single threaded and will run all
+transactions synchronously. As transactions are serialized, a client that
+generates a lot of events will be paced by the round-trip time.
+
+It would be a straightforward enhancement to use the multi-thread API into
+libcurl and use a pool of client threads to run transactions in parallel if
+this ever became a bottleneck.
+
+## Logging
+
+The initialization of the library includes the log verbosity. The verbose
+operation makes the library very chatty so syslog may get rather clogged
+with detailed diagnostics. It is possible to configure syslog to put these
+events into a separate file. A trivial syslog.conf file would be:
+
+```
+
+# Log all user messages so debug information is captured.
+
+user.* /var/log/debug
+```
+
+If verbose logging is enabled, the cURL library will generate information
+about the HTTP operations on **stdout**.
+
diff --git a/VES5.0/evel/evel-library/code/evel_library/ring_buffer.c b/VES5.0/evel/evel-library/code/evel_library/ring_buffer.c
new file mode 100644
index 00000000..3795ed36
--- /dev/null
+++ b/VES5.0/evel/evel-library/code/evel_library/ring_buffer.c
@@ -0,0 +1,206 @@
+/**************************************************************************//**
+ * @file
+ * A ring buffer with multi-threaded synchronization.
+ *
+ * License
+ * -------
+ *
+ * Copyright(c) <2016>, AT&T Intellectual Property. All other rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement: This product includes
+ * software developed by the AT&T.
+ * 4. Neither the name of AT&T nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#include <assert.h>
+#include <malloc.h>
+
+#include "ring_buffer.h"
+#include "evel.h"
+
+/**************************************************************************//**
+ * Ring buffer initialization.
+ *
+ * Initialize the buffer supplied to the specified size.
+ *
+ * @param buffer Pointer to the ring-buffer to be initialized.
+ * @param size How many elements to be stored in the ring-buffer.
+ *
+ * @returns Nothing
+******************************************************************************/
+void ring_buffer_initialize(ring_buffer * buffer, int size)
+{
+ int pthread_rc = 0;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check assumptions. */
+ /***************************************************************************/
+ assert(buffer != NULL);
+ assert(size > 0);
+
+ /***************************************************************************/
+ /* Initialize the synchronization objects. */
+ /***************************************************************************/
+ pthread_rc = pthread_mutex_init(&buffer->ring_mutex, NULL);
+ assert(pthread_rc == 0);
+ pthread_rc = pthread_cond_init(&buffer->ring_cv, NULL);
+ assert(pthread_rc == 0);
+
+ /***************************************************************************/
+ /* Allocate the ring buffer itself. */
+ /***************************************************************************/
+ buffer->ring = malloc(size * sizeof(void *));
+ assert(buffer->ring != NULL);
+
+ /***************************************************************************/
+ /* Initialize the ring as empty. */
+ /***************************************************************************/
+ buffer->next_write = 0;
+ buffer->next_read = 0;
+ buffer->size = size;
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Read an element from a ring_buffer.
+ *
+ * Reads an element from the ring_buffer, advancing the next-read position.
+ * Operation is synchronized and therefore MT-safe. Blocks if no data is
+ * available.
+ *
+ * @param buffer Pointer to the ring-buffer to be read.
+ *
+ * @returns Pointer to the element read from the buffer.
+******************************************************************************/
+void * ring_buffer_read(ring_buffer * buffer)
+{
+ void *msg = NULL;
+ EVEL_DEBUG("RBR: Ring buffer read");
+
+ pthread_mutex_lock(&buffer->ring_mutex);
+ while (1)
+ {
+ EVEL_DEBUG("RBR: got lock. NR=%d NW=%d",
+ buffer->next_read,
+ buffer->next_write);
+ if(buffer->next_read != buffer->next_write)
+ {
+ EVEL_DEBUG("RBR: buffer has item available");
+ msg = (buffer->ring)[buffer->next_read];
+ buffer->ring[buffer->next_read] = NULL;
+ buffer->next_read = (buffer->next_read + 1) % buffer->size;
+ EVEL_DEBUG("RBR: next read location is %d", buffer->next_read);
+ pthread_mutex_unlock(&buffer->ring_mutex);
+ break;
+ }
+ else
+ {
+ EVEL_DEBUG("RBR: Waiting for condition variable");
+ pthread_cond_wait(&buffer->ring_cv, &buffer->ring_mutex);
+ EVEL_DEBUG("RBR: Condition variable wait completed");
+ }
+ }
+ EVEL_DEBUG("RBR: Ring buffer read returning data at %lp", msg);
+ return msg;
+}
+
+/**************************************************************************//**
+ * Write an element into a ring_buffer.
+ *
+ * Writes an element into the ring_buffer, advancing the next-write position.
+ * Operation is synchronized and therefore MT-safe. Fails if the buffer is
+ * full without blocking.
+ *
+ * @param buffer Pointer to the ring-buffer to be written.
+ * @param msg Pointer to data to be stored in the ring_buffer.
+ *
+ * @returns Number of items written.
+ * @retval 1 The data was written successfully.
+ * @retval 0 The ring_buffer was full so no data written.
+******************************************************************************/
+int ring_buffer_write(ring_buffer * buffer, void * msg)
+{
+ int item_count = 0;
+ int items_written = 0;
+ EVEL_DEBUG("RBW: Ring Buffer Write message at %lp", msg);
+
+ pthread_mutex_lock(&buffer->ring_mutex);
+ EVEL_DEBUG("RBW: got lock. NR=%d NW=%d SZ=%d",
+ buffer->next_read,
+ buffer->next_write,
+ buffer->size);
+
+ item_count = (buffer->next_write - buffer->next_read) % buffer->size;
+ if (item_count < 0)
+ {
+ item_count += buffer->size;
+ }
+ if (item_count < buffer->size - 1)
+ {
+ EVEL_DEBUG("RBW: %d items in buffer", item_count);
+ buffer->ring[buffer->next_write] = msg;
+ buffer->next_write = (buffer->next_write + 1) % buffer->size;
+ EVEL_DEBUG("RBW: next write location is %d", buffer->next_write);
+ items_written = 1;
+ }
+ else
+ {
+ EVEL_ERROR("RBW: ring buffer full - unable to write event");
+ }
+
+ pthread_mutex_unlock(&buffer->ring_mutex);
+ EVEL_DEBUG("RBW: released lock");
+ pthread_cond_signal(&buffer->ring_cv);
+
+ return items_written;
+}
+
+/**************************************************************************//**
+ * Tests whether there is data in the ring_buffer.
+ *
+ * Tests whether there is currently data in the ring_buffer without blocking.
+ *
+ * @param buffer Pointer to the ring-buffer to be tested.
+ *
+ * @returns Whether there is data in the ring_buffer.
+ * @retval 0 There isn't any data in the ring_buffer.
+ * @retval 1 There is data in the ring_buffer.
+******************************************************************************/
+int ring_buffer_is_empty(ring_buffer * buffer)
+{
+ int is_empty = 0;
+ EVEL_DEBUG("RBE: Ring empty check");
+
+ pthread_mutex_lock(&buffer->ring_mutex);
+ is_empty = (buffer->next_read == buffer->next_write);
+ pthread_mutex_unlock(&buffer->ring_mutex);
+
+ EVEL_DEBUG("RBE: Ring state= %d", is_empty);
+ return is_empty;
+}
+
diff --git a/VES5.0/evel/evel-library/code/evel_library/ring_buffer.h b/VES5.0/evel/evel-library/code/evel_library/ring_buffer.h
new file mode 100644
index 00000000..c6870508
--- /dev/null
+++ b/VES5.0/evel/evel-library/code/evel_library/ring_buffer.h
@@ -0,0 +1,109 @@
+#ifndef RING_BUFFER_INCLUDED
+#define RING_BUFFER_INCLUDED
+
+/**************************************************************************//**
+ * @file
+ * A ring buffer.
+ *
+ * License
+ * -------
+ *
+ * Copyright(c) <2016>, AT&T Intellectual Property. All other rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement: This product includes
+ * software developed by the AT&T.
+ * 4. Neither the name of AT&T nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#include <pthread.h>
+
+/**************************************************************************//**
+ * Ring buffer structure.
+ *****************************************************************************/
+typedef struct ring_buffer
+{
+ int size;
+ int next_write;
+ int next_read;
+ void ** ring;
+ pthread_cond_t ring_cv;
+ pthread_mutex_t ring_mutex;
+} ring_buffer;
+
+/**************************************************************************//**
+ * Ring buffer initialization.
+ *
+ * Initialize the buffer supplied to the specified size.
+ *
+ * @param buffer Pointer to the ring-buffer to be initialized.
+ * @param size How many elements to be stored in the ring-buffer.
+ *
+ * @returns Nothing
+******************************************************************************/
+void ring_buffer_initialize(ring_buffer * buffer, int size);
+
+/**************************************************************************//**
+ * Read an element from a ring_buffer.
+ *
+ * Reads an element from the ring_buffer, advancing the next-read position.
+ * Operation is synchronized and therefore MT-safe. Blocks if no data is
+ * available.
+ *
+ * @param buffer Pointer to the ring-buffer to be read.
+ *
+ * @returns Pointer to the element read from the buffer.
+******************************************************************************/
+void * ring_buffer_read(ring_buffer * buffer);
+
+/**************************************************************************//**
+ * Write an element into a ring_buffer.
+ *
+ * Writes an element into the ring_buffer, advancing the next-write position.
+ * Operation is synchronized and therefore MT-safe. Fails if the buffer is
+ * full without blocking.
+ *
+ * @param buffer Pointer to the ring-buffer to be written.
+ * @param msg Pointer to data to be stored in the ring_buffer.
+ *
+ * @returns Number of items written.
+ * @retval 1 The data was written successfully.
+ * @retval 0 The ring_buffer was full so no data written.
+******************************************************************************/
+int ring_buffer_write(ring_buffer * buffer, void * msg);
+
+/**************************************************************************//**
+ * Tests whether there is data in the ring_buffer.
+ *
+ * Tests whether there is currently data in the ring_buffer without blocking.
+ *
+ * @param buffer Pointer to the ring-buffer to be tested.
+ *
+ * @returns Whether there is data in the ring_buffer.
+ * @retval 0 There isn't any data in the ring_buffer.
+ * @retval 1 There is data in the ring_buffer.
+******************************************************************************/
+int ring_buffer_is_empty(ring_buffer * buffer);
+
+#endif
diff --git a/VES5.0/evel/evel-library/code/evel_training/01-hello-world/Makefile b/VES5.0/evel/evel-library/code/evel_training/01-hello-world/Makefile
new file mode 100644
index 00000000..eae417d8
--- /dev/null
+++ b/VES5.0/evel/evel-library/code/evel_training/01-hello-world/Makefile
@@ -0,0 +1,13 @@
+CC=gcc
+
+#******************************************************************************
+# Standard compiler flags. *
+#******************************************************************************
+CPPFLAGS=
+CFLAGS=-Wall -g -fPIC
+
+all: hello_evel_world
+
+hello_evel_world: hello_evel_world.c
+ $(CC) $(CPPFLAGS) $(CFLAGS) -o hello_evel_world hello_evel_world.c
+
diff --git a/VES5.0/evel/evel-library/code/evel_training/01-hello-world/hello_evel_world.c b/VES5.0/evel/evel-library/code/evel_training/01-hello-world/hello_evel_world.c
new file mode 100644
index 00000000..4048c4ea
--- /dev/null
+++ b/VES5.0/evel/evel-library/code/evel_training/01-hello-world/hello_evel_world.c
@@ -0,0 +1,7 @@
+#include <stdio.h>
+
+int main(int argc, char ** argv)
+{
+ printf("Hello AT&T world!!!\n");
+ return 0;
+}
diff --git a/VES5.0/evel/evel-library/code/evel_training/02-library-link/Makefile b/VES5.0/evel/evel-library/code/evel_training/02-library-link/Makefile
new file mode 100644
index 00000000..a6013de3
--- /dev/null
+++ b/VES5.0/evel/evel-library/code/evel_training/02-library-link/Makefile
@@ -0,0 +1,22 @@
+CC=gcc
+
+#******************************************************************************
+# Standard compiler flags. *
+#******************************************************************************
+CPPFLAGS=
+CFLAGS=-Wall -g -fPIC
+
+ARCH=$(shell getconf LONG_BIT)
+CODE_ROOT=$(CURDIR)/../../..
+LIBS_DIR=$(CODE_ROOT)/libs/x86_$(ARCH)
+
+all: hello_evel_world
+
+hello_evel_world: hello_evel_world.c
+ $(CC) $(CPPFLAGS) $(CFLAGS) -o hello_evel_world \
+ -L $(LIBS_DIR) \
+ hello_evel_world.c \
+ -lpthread \
+ -level \
+ -lcurl
+
diff --git a/VES5.0/evel/evel-library/code/evel_training/02-library-link/hello_evel_world.c b/VES5.0/evel/evel-library/code/evel_training/02-library-link/hello_evel_world.c
new file mode 100644
index 00000000..ab1ae83e
--- /dev/null
+++ b/VES5.0/evel/evel-library/code/evel_training/02-library-link/hello_evel_world.c
@@ -0,0 +1,7 @@
+#include <stdio.h>
+
+int main(int argc, char ** argv)
+{
+ printf("Hello AT&T Vendor Event world!\n");
+ return 0;
+}
diff --git a/VES5.0/evel/evel-library/code/evel_training/03-include-header/Makefile b/VES5.0/evel/evel-library/code/evel_training/03-include-header/Makefile
new file mode 100644
index 00000000..1fccf915
--- /dev/null
+++ b/VES5.0/evel/evel-library/code/evel_training/03-include-header/Makefile
@@ -0,0 +1,24 @@
+CC=gcc
+
+ARCH=$(shell getconf LONG_BIT)
+CODE_ROOT=$(CURDIR)/../../..
+LIBS_DIR=$(CODE_ROOT)/libs/x86_$(ARCH)
+INCLUDE_DIR=$(CODE_ROOT)/code/evel_library
+
+#******************************************************************************
+# Standard compiler flags. *
+#******************************************************************************
+CPPFLAGS=
+CFLAGS=-Wall -g -fPIC
+
+all: hello_evel_world
+
+hello_evel_world: hello_evel_world.c
+ $(CC) $(CPPFLAGS) $(CFLAGS) -o hello_evel_world \
+ -L $(LIBS_DIR) \
+ -I $(INCLUDE_DIR) \
+ hello_evel_world.c \
+ -lpthread \
+ -level \
+ -lcurl
+
diff --git a/VES5.0/evel/evel-library/code/evel_training/03-include-header/hello_evel_world.c b/VES5.0/evel/evel-library/code/evel_training/03-include-header/hello_evel_world.c
new file mode 100644
index 00000000..1a80aa15
--- /dev/null
+++ b/VES5.0/evel/evel-library/code/evel_training/03-include-header/hello_evel_world.c
@@ -0,0 +1,9 @@
+#include <stdio.h>
+
+#include "evel.h"
+
+int main(int argc, char ** argv)
+{
+ printf("Hello AT&T Vendor Event world!\n");
+ return 0;
+}
diff --git a/VES5.0/evel/evel-library/code/evel_training/04-basic-lifecycle/Makefile b/VES5.0/evel/evel-library/code/evel_training/04-basic-lifecycle/Makefile
new file mode 100644
index 00000000..1fccf915
--- /dev/null
+++ b/VES5.0/evel/evel-library/code/evel_training/04-basic-lifecycle/Makefile
@@ -0,0 +1,24 @@
+CC=gcc
+
+ARCH=$(shell getconf LONG_BIT)
+CODE_ROOT=$(CURDIR)/../../..
+LIBS_DIR=$(CODE_ROOT)/libs/x86_$(ARCH)
+INCLUDE_DIR=$(CODE_ROOT)/code/evel_library
+
+#******************************************************************************
+# Standard compiler flags. *
+#******************************************************************************
+CPPFLAGS=
+CFLAGS=-Wall -g -fPIC
+
+all: hello_evel_world
+
+hello_evel_world: hello_evel_world.c
+ $(CC) $(CPPFLAGS) $(CFLAGS) -o hello_evel_world \
+ -L $(LIBS_DIR) \
+ -I $(INCLUDE_DIR) \
+ hello_evel_world.c \
+ -lpthread \
+ -level \
+ -lcurl
+
diff --git a/VES5.0/evel/evel-library/code/evel_training/04-basic-lifecycle/hello_evel_world.c b/VES5.0/evel/evel-library/code/evel_training/04-basic-lifecycle/hello_evel_world.c
new file mode 100644
index 00000000..169a7e4f
--- /dev/null
+++ b/VES5.0/evel/evel-library/code/evel_training/04-basic-lifecycle/hello_evel_world.c
@@ -0,0 +1,69 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "evel.h"
+
+int main(int argc, char ** argv)
+{
+ EVEL_ERR_CODES evel_rc = EVEL_SUCCESS;
+ EVENT_HEADER * heartbeat = NULL;
+
+ printf("\nHello AT&T Vendor Event world!\n");
+ fflush(stdout);
+
+ if (argc != 3)
+ {
+ fprintf(stderr, "Usage: %s <FQDN>|<IP address> <port>\n", argv[0]);
+ exit(-1);
+ }
+
+ /***************************************************************************/
+ /* Initialize */
+ /***************************************************************************/
+ if (evel_initialize(argv[1], /* FQDN */
+ atoi(argv[2]), /* Port */
+ NULL, /* optional path */
+ NULL, /* optional topic */
+ 0, /* HTTPS? */
+ "", /* Username */
+ "", /* Password */
+ EVEL_SOURCE_VIRTUAL_MACHINE, /* Source type */
+ "EVEL training demo", /* Role */
+ 0)) /* Verbosity */
+ {
+ fprintf(stderr, "\nFailed to initialize the EVEL library!!!\n");
+ exit(-1);
+ }
+ else
+ {
+ printf("Initialization completed\n");
+ }
+
+ /***************************************************************************/
+ /* Send a heartbeat just to show we're alive! */
+ /***************************************************************************/
+ heartbeat = evel_new_heartbeat();
+ if (heartbeat != NULL)
+ {
+ evel_rc = evel_post_event(heartbeat);
+ if (evel_rc != EVEL_SUCCESS)
+ {
+ printf("Post failed %d (%s)", evel_rc, evel_error_string());
+ }
+ }
+ else
+ {
+ printf("New heartbeat failed");
+ }
+
+ /***************************************************************************/
+ /* Terminate */
+ /***************************************************************************/
+ sleep(1);
+ evel_terminate();
+ printf("Terminated\n");
+
+ return 0;
+}
+
diff --git a/VES5.0/evel/evel-library/code/evel_training/05-raise-event/Makefile b/VES5.0/evel/evel-library/code/evel_training/05-raise-event/Makefile
new file mode 100644
index 00000000..1fccf915
--- /dev/null
+++ b/VES5.0/evel/evel-library/code/evel_training/05-raise-event/Makefile
@@ -0,0 +1,24 @@
+CC=gcc
+
+ARCH=$(shell getconf LONG_BIT)
+CODE_ROOT=$(CURDIR)/../../..
+LIBS_DIR=$(CODE_ROOT)/libs/x86_$(ARCH)
+INCLUDE_DIR=$(CODE_ROOT)/code/evel_library
+
+#******************************************************************************
+# Standard compiler flags. *
+#******************************************************************************
+CPPFLAGS=
+CFLAGS=-Wall -g -fPIC
+
+all: hello_evel_world
+
+hello_evel_world: hello_evel_world.c
+ $(CC) $(CPPFLAGS) $(CFLAGS) -o hello_evel_world \
+ -L $(LIBS_DIR) \
+ -I $(INCLUDE_DIR) \
+ hello_evel_world.c \
+ -lpthread \
+ -level \
+ -lcurl
+
diff --git a/VES5.0/evel/evel-library/code/evel_training/05-raise-event/hello_evel_world.c b/VES5.0/evel/evel-library/code/evel_training/05-raise-event/hello_evel_world.c
new file mode 100644
index 00000000..298665bf
--- /dev/null
+++ b/VES5.0/evel/evel-library/code/evel_training/05-raise-event/hello_evel_world.c
@@ -0,0 +1,96 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "evel.h"
+
+int main(int argc, char ** argv)
+{
+ EVEL_ERR_CODES evel_rc = EVEL_SUCCESS;
+ EVENT_HEADER * heartbeat = NULL;
+ EVENT_FAULT * fault = NULL;
+
+ printf("\nHello AT&T Vendor Event world!\n");
+ fflush(stdout);
+
+ if (argc != 3)
+ {
+ fprintf(stderr, "Usage: %s <FQDN>|<IP address> <port>\n", argv[0]);
+ exit(-1);
+ }
+
+ /***************************************************************************/
+ /* Initialize */
+ /***************************************************************************/
+ if (evel_initialize(argv[1], /* FQDN */
+ atoi(argv[2]), /* Port */
+ NULL, /* optional path */
+ NULL, /* optional topic */
+ 0, /* HTTPS? */
+ "", /* Username */
+ "", /* Password */
+ EVEL_SOURCE_VIRTUAL_MACHINE, /* Source type */
+ "EVEL training demo", /* Role */
+ 0)) /* Verbosity */
+ {
+ fprintf(stderr, "\nFailed to initialize the EVEL library!!!\n");
+ exit(-1);
+ }
+ else
+ {
+ printf("\nInitialization completed\n");
+ }
+
+ /***************************************************************************/
+ /* Send a heartbeat just to show we're alive! */
+ /***************************************************************************/
+ heartbeat = evel_new_heartbeat();
+ if (heartbeat != NULL)
+ {
+ evel_rc = evel_post_event(heartbeat);
+ if (evel_rc != EVEL_SUCCESS)
+ {
+ printf("Post failed %d (%s)", evel_rc, evel_error_string());
+ }
+ }
+ else
+ {
+ printf("New heartbeat failed");
+ }
+
+ /***************************************************************************/
+ /* Raise a 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);
+ if (fault != NULL)
+ {
+ printf("New fault created...\n");
+ evel_rc = evel_post_event((EVENT_HEADER *)fault);
+ if (evel_rc == EVEL_SUCCESS)
+ {
+ printf("Fault posted OK!\n");
+ }
+ else
+ {
+ printf("Post failed %d (%s)\n", evel_rc, evel_error_string());
+ }
+ }
+ else
+ {
+ printf("New fault failed (%s)\n", evel_error_string());
+ }
+
+ /***************************************************************************/
+ /* Terminate */
+ /***************************************************************************/
+ sleep(1);
+ evel_terminate();
+ printf("Terminated\n");
+
+ return 0;
+}
diff --git a/VES5.0/evel/evel-library/code/evel_training/06-username-password/Makefile b/VES5.0/evel/evel-library/code/evel_training/06-username-password/Makefile
new file mode 100644
index 00000000..977c0732
--- /dev/null
+++ b/VES5.0/evel/evel-library/code/evel_training/06-username-password/Makefile
@@ -0,0 +1,31 @@
+CC=gcc
+
+ARCH=$(shell getconf LONG_BIT)
+CODE_ROOT=$(CURDIR)/../../..
+LIBS_DIR=$(CODE_ROOT)/libs/x86_$(ARCH)
+INCLUDE_DIR=$(CODE_ROOT)/code/evel_library
+
+#******************************************************************************
+# Standard compiler flags. *
+#******************************************************************************
+CPPFLAGS=
+CFLAGS=-Wall -g -fPIC
+
+all: hello_evel_world
+
+hello_evel_world: hello_evel_world.c
+ $(CC) $(CPPFLAGS) $(CFLAGS) -o hello_evel_world \
+ -L $(LIBS_DIR) \
+ -I $(INCLUDE_DIR) \
+ hello_evel_world.c \
+ -lpthread \
+ -level \
+ -lcurl
+
+#******************************************************************************
+# Configure the vel_username and vel_password to
+# vel_username = username
+# vel_password = password
+#******************************************************************************
+run:
+ ./hello_evel_world localhost 30000 username password
diff --git a/VES5.0/evel/evel-library/code/evel_training/06-username-password/hello_evel_world.c b/VES5.0/evel/evel-library/code/evel_training/06-username-password/hello_evel_world.c
new file mode 100644
index 00000000..37ab5cb0
--- /dev/null
+++ b/VES5.0/evel/evel-library/code/evel_training/06-username-password/hello_evel_world.c
@@ -0,0 +1,98 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "evel.h"
+
+int main(int argc, char ** argv)
+{
+ EVEL_ERR_CODES evel_rc = EVEL_SUCCESS;
+ EVENT_HEADER * heartbeat = NULL;
+ EVENT_FAULT * fault = NULL;
+
+ printf("\nHello AT&T Vendor Event world!\n");
+ fflush(stdout);
+
+ if (argc != 5)
+ {
+ fprintf(stderr,
+ "Usage: %s <FQDN>|<IP address> <port> "
+ "<username> <password>\n", argv[0]);
+ exit(-1);
+ }
+
+ /***************************************************************************/
+ /* Initialize */
+ /***************************************************************************/
+ if (evel_initialize(argv[1], /* FQDN */
+ atoi(argv[2]), /* Port */
+ NULL, /* optional path */
+ NULL, /* optional topic */
+ 0, /* HTTPS? */
+ argv[3], /* Username */
+ argv[4], /* Password */
+ EVEL_SOURCE_VIRTUAL_MACHINE, /* Source type */
+ "EVEL training demo", /* Role */
+ 0)) /* Verbosity */
+ {
+ fprintf(stderr, "\nFailed to initialize the EVEL library!!!\n");
+ exit(-1);
+ }
+ else
+ {
+ printf("\nInitialization completed\n");
+ }
+
+ /***************************************************************************/
+ /* Send a heartbeat just to show we're alive! */
+ /***************************************************************************/
+ heartbeat = evel_new_heartbeat();
+ if (heartbeat != NULL)
+ {
+ evel_rc = evel_post_event(heartbeat);
+ if (evel_rc != EVEL_SUCCESS)
+ {
+ printf("Post failed %d (%s)", evel_rc, evel_error_string());
+ }
+ }
+ else
+ {
+ printf("New heartbeat failed");
+ }
+
+ /***************************************************************************/
+ /* Raise a 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);
+ if (fault != NULL)
+ {
+ printf("New fault created...\n");
+ evel_rc = evel_post_event((EVENT_HEADER *)fault);
+ if (evel_rc == EVEL_SUCCESS)
+ {
+ printf("Fault posted OK!\n");
+ }
+ else
+ {
+ printf("Post failed %d (%s)\n", evel_rc, evel_error_string());
+ }
+ }
+ else
+ {
+ printf("New fault failed (%s)\n", evel_error_string());
+ }
+
+ /***************************************************************************/
+ /* Terminate */
+ /***************************************************************************/
+ sleep(1);
+ evel_terminate();
+ printf("Terminated\n");
+
+ return 0;
+}
diff --git a/VES5.0/evel/evel-library/code/evel_training/07-raise-measurement/Makefile b/VES5.0/evel/evel-library/code/evel_training/07-raise-measurement/Makefile
new file mode 100644
index 00000000..6acfdd42
--- /dev/null
+++ b/VES5.0/evel/evel-library/code/evel_training/07-raise-measurement/Makefile
@@ -0,0 +1,31 @@
+CC=gcc
+
+ARCH=$(shell getconf LONG_BIT)
+CODE_ROOT=$(CURDIR)/../../..
+LIBS_DIR=$(CODE_ROOT)/libs/x86_$(ARCH)
+INCLUDE_DIR=$(CODE_ROOT)/code/evel_library
+
+#******************************************************************************
+# Standard compiler flags. *
+#******************************************************************************
+CPPFLAGS=
+CFLAGS=-Wall -g -fPIC
+
+all: hello_evel_world
+
+hello_evel_world: hello_evel_world.c
+ $(CC) $(CPPFLAGS) $(CFLAGS) -o hello_evel_world \
+ -L $(LIBS_DIR) \
+ -I $(INCLUDE_DIR) \
+ hello_evel_world.c \
+ -lpthread \
+ -level \
+ -lcurl
+
+#******************************************************************************
+# Configure the vel_username and vel_password to
+# vel_username = username
+# vel_password = password
+#******************************************************************************
+run: all
+ ./hello_evel_world localhost 30000 username password
diff --git a/VES5.0/evel/evel-library/code/evel_training/07-raise-measurement/hello_evel_world.c b/VES5.0/evel/evel-library/code/evel_training/07-raise-measurement/hello_evel_world.c
new file mode 100644
index 00000000..03b8c145
--- /dev/null
+++ b/VES5.0/evel/evel-library/code/evel_training/07-raise-measurement/hello_evel_world.c
@@ -0,0 +1,196 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "evel.h"
+
+/*****************************************************************************/
+/* Local prototypes. */
+/*****************************************************************************/
+static void demo_measurement(void);
+
+int main(int argc, char ** argv)
+{
+ EVEL_ERR_CODES evel_rc = EVEL_SUCCESS;
+ EVENT_HEADER * heartbeat = NULL;
+
+ printf("\nHello AT&T Vendor Event world!\n");
+ fflush(stdout);
+
+ if (argc != 5)
+ {
+ fprintf(stderr,
+ "Usage: %s <FQDN>|<IP address> <port> "
+ "<username> <password>\n", argv[0]);
+ exit(-1);
+ }
+
+ /***************************************************************************/
+ /* Initialize */
+ /***************************************************************************/
+ if (evel_initialize(argv[1], /* FQDN */
+ atoi(argv[2]), /* Port */
+ NULL, /* optional path */
+ NULL, /* optional topic */
+ 0, /* HTTPS? */
+ argv[3], /* Username */
+ argv[4], /* Password */
+ EVEL_SOURCE_VIRTUAL_MACHINE, /* Source type */
+ "EVEL training demo", /* Role */
+ 0)) /* Verbosity */
+ {
+ fprintf(stderr, "\nFailed to initialize the EVEL library!!!\n");
+ exit(-1);
+ }
+ else
+ {
+ printf("\nInitialization completed\n");
+ }
+
+ /***************************************************************************/
+ /* Send a heartbeat just to show we're alive! */
+ /***************************************************************************/
+ heartbeat = evel_new_heartbeat();
+ if (heartbeat != NULL)
+ {
+ evel_rc = evel_post_event(heartbeat);
+ if (evel_rc != EVEL_SUCCESS)
+ {
+ printf("Post failed %d (%s)", evel_rc, evel_error_string());
+ }
+ }
+ else
+ {
+ printf("New heartbeat failed");
+ }
+
+ /***************************************************************************/
+ /* Raise a measurement */
+ /***************************************************************************/
+ demo_measurement();
+
+ /***************************************************************************/
+ /* Terminate */
+ /***************************************************************************/
+ sleep(1);
+ evel_terminate();
+ printf("Terminated\n");
+
+ return 0;
+}
+
+/**************************************************************************//**
+ * Create and send a measurement event.
+ *****************************************************************************/
+void demo_measurement(void)
+{
+ EVENT_MEASUREMENT * measurement = NULL;
+ MEASUREMENT_LATENCY_BUCKET * bucket = NULL;
+ MEASUREMENT_VNIC_PERFORMANCE * vnic_use = NULL;
+ EVEL_ERR_CODES evel_rc = EVEL_SUCCESS;
+ MEASUREMENT_CPU_USE * cpu_use = NULL;
+
+ /***************************************************************************/
+ /* Measurement */
+ /***************************************************************************/
+ measurement = evel_new_measurement(5.5);
+ if (measurement != NULL)
+ {
+ printf("New measurement created...\n");
+ 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, 6);
+
+ 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);
+
+ bucket = evel_new_meas_latency_bucket(20);
+ evel_meas_latency_bucket_low_end_set(bucket, 0.0);
+ evel_meas_latency_bucket_high_end_set(bucket, 10.0);
+ 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_measurement_new_vnic_performance("eth0", "true");
+ evel_vnic_performance_rx_octets_delta_set(vnic_use, 47656465465);
+ evel_vnic_performance_rx_total_pkt_acc_set(vnic_use, 4765764654444);
+ evel_vnic_performance_rx_total_pkt_delta_set(vnic_use, 4545665656);
+ evel_vnic_performance_rx_ucast_pkt_acc_set(vnic_use, 4765745546.);
+ evel_vnic_performance_rx_ucast_pkt_delta_set(vnic_use, 4768765.78347856);
+ evel_vnic_performance_tx_bcast_pkt_acc_set(vnic_use, 747665.347647);
+ evel_vnic_performance_tx_bcast_pkt_delta_set(vnic_use, 3468765.4774);
+ evel_vnic_performance_tx_discarded_pkt_acc_set(vnic_use, 53625345.53);
+ evel_vnic_performance_tx_discarded_pkt_delta_set(vnic_use, 5465345.72455);
+ evel_meas_vnic_performance_add(measurement, vnic_use);
+
+ vnic_use = evel_measurement_new_vnic_performance("eth1", "false");
+ evel_vnic_performance_rx_total_pkt_acc_set(vnic_use, 4765764654444);
+ evel_vnic_performance_rx_total_pkt_delta_set(vnic_use, 4545665656);
+ evel_vnic_performance_rx_ucast_pkt_acc_set(vnic_use, 4765745546.);
+ evel_vnic_performance_rx_ucast_pkt_delta_set(vnic_use, 4768765.78347856);
+ evel_vnic_performance_tx_bcast_pkt_acc_set(vnic_use, 747665.347647);
+ evel_meas_vnic_performance_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");
+
+ evel_rc = evel_post_event((EVENT_HEADER *)measurement);
+ if (evel_rc == EVEL_SUCCESS)
+ {
+ printf("Post OK!\n");
+ }
+ else
+ {
+ printf("Post Failed %d (%s)\n", evel_rc, evel_error_string());
+ }
+ }
+ else
+ {
+ printf("Failed to create event (%s)\n", evel_error_string());
+ }
+
+ printf(" Processed Measurement\n");
+}
diff --git a/VES5.0/evel/evel-library/code/evel_training/08-raise-mobile-flow/Makefile b/VES5.0/evel/evel-library/code/evel_training/08-raise-mobile-flow/Makefile
new file mode 100644
index 00000000..6acfdd42
--- /dev/null
+++ b/VES5.0/evel/evel-library/code/evel_training/08-raise-mobile-flow/Makefile
@@ -0,0 +1,31 @@
+CC=gcc
+
+ARCH=$(shell getconf LONG_BIT)
+CODE_ROOT=$(CURDIR)/../../..
+LIBS_DIR=$(CODE_ROOT)/libs/x86_$(ARCH)
+INCLUDE_DIR=$(CODE_ROOT)/code/evel_library
+
+#******************************************************************************
+# Standard compiler flags. *
+#******************************************************************************
+CPPFLAGS=
+CFLAGS=-Wall -g -fPIC
+
+all: hello_evel_world
+
+hello_evel_world: hello_evel_world.c
+ $(CC) $(CPPFLAGS) $(CFLAGS) -o hello_evel_world \
+ -L $(LIBS_DIR) \
+ -I $(INCLUDE_DIR) \
+ hello_evel_world.c \
+ -lpthread \
+ -level \
+ -lcurl
+
+#******************************************************************************
+# Configure the vel_username and vel_password to
+# vel_username = username
+# vel_password = password
+#******************************************************************************
+run: all
+ ./hello_evel_world localhost 30000 username password
diff --git a/VES5.0/evel/evel-library/code/evel_training/08-raise-mobile-flow/hello_evel_world.c b/VES5.0/evel/evel-library/code/evel_training/08-raise-mobile-flow/hello_evel_world.c
new file mode 100644
index 00000000..597d5da0
--- /dev/null
+++ b/VES5.0/evel/evel-library/code/evel_training/08-raise-mobile-flow/hello_evel_world.c
@@ -0,0 +1,201 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "evel.h"
+
+/*****************************************************************************/
+/* Local prototypes. */
+/*****************************************************************************/
+static void demo_mobile_flow(void);
+
+int main(int argc, char ** argv)
+{
+ EVEL_ERR_CODES evel_rc = EVEL_SUCCESS;
+ EVENT_HEADER * heartbeat = NULL;
+
+ printf("\nHello AT&T Vendor Event world!\n");
+ fflush(stdout);
+
+ if (argc != 5)
+ {
+ fprintf(stderr,
+ "Usage: %s <FQDN>|<IP address> <port> "
+ "<username> <password>\n", argv[0]);
+ exit(-1);
+ }
+
+ /***************************************************************************/
+ /* Initialize */
+ /***************************************************************************/
+ if (evel_initialize(argv[1], /* FQDN */
+ atoi(argv[2]), /* Port */
+ NULL, /* optional path */
+ NULL, /* optional topic */
+ 0, /* HTTPS? */
+ argv[3], /* Username */
+ argv[4], /* Password */
+ EVEL_SOURCE_VIRTUAL_MACHINE, /* Source type */
+ "EVEL training demo", /* Role */
+ 0)) /* Verbosity */
+ {
+ fprintf(stderr, "\nFailed to initialize the EVEL library!!!\n");
+ exit(-1);
+ }
+ else
+ {
+ printf("\nInitialization completed\n");
+ }
+
+ /***************************************************************************/
+ /* Send a heartbeat just to show we're alive! */
+ /***************************************************************************/
+ heartbeat = evel_new_heartbeat();
+ if (heartbeat != NULL)
+ {
+ evel_rc = evel_post_event(heartbeat);
+ if (evel_rc != EVEL_SUCCESS)
+ {
+ printf("Post failed %d (%s)", evel_rc, evel_error_string());
+ }
+ }
+ else
+ {
+ printf("New heartbeat failed");
+ }
+
+ /***************************************************************************/
+ /* Raise a measurement */
+ /***************************************************************************/
+ demo_mobile_flow();
+
+ /***************************************************************************/
+ /* Terminate */
+ /***************************************************************************/
+ sleep(1);
+ evel_terminate();
+ printf("Terminated\n");
+
+ return 0;
+}
+
+/**************************************************************************//**
+ * Create and send three mobile flow events.
+ *****************************************************************************/
+void demo_mobile_flow(void)
+{
+ MOBILE_GTP_PER_FLOW_METRICS * metrics = NULL;
+ EVENT_MOBILE_FLOW * mobile_flow = NULL;
+ EVEL_ERR_CODES evel_rc = EVEL_SUCCESS;
+
+ metrics = evel_new_mobile_gtp_flow_metrics(12.32,
+ 3.122,
+ 1002,
+ 21002,
+ 5002,
+ 1470409423,
+ 9872,
+ 1470409433,
+ 112,
+ (time_t)1470409433,
+ "Failed",
+ 872,
+ 32,
+ 172,
+ 1236542,
+ 45612,
+ 2,
+ 122,
+ 102,
+ 12,
+ 32,
+ 72,
+ 8992,
+ 9012,
+ 3022,
+ 62,
+ 22,
+ 2,
+ 1102,
+ 2252);
+ if (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("Outbound",
+ metrics,
+ "RTP",
+ "IPv8",
+ "2.3.4.3",
+ 2343,
+ "4.2.3.3",
+ 4323);
+ if (mobile_flow != NULL)
+ {
+ evel_mobile_flow_app_type_set(mobile_flow, "Demo application 2");
+ evel_mobile_flow_app_prot_type_set(mobile_flow, "GSM");
+ evel_mobile_flow_app_prot_ver_set(mobile_flow, "2");
+ evel_mobile_flow_cid_set(mobile_flow, "1");
+ evel_mobile_flow_con_type_set(mobile_flow, "S1-U");
+ evel_mobile_flow_ecgi_set(mobile_flow, "e1");
+ 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.google.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, "MMF");
+ evel_mobile_flow_rac_set(mobile_flow, "514");
+ evel_mobile_flow_radio_acc_tech_set(mobile_flow, "3G");
+ evel_mobile_flow_sac_set(mobile_flow, "1");
+ evel_mobile_flow_samp_alg_set(mobile_flow, 2);
+ evel_mobile_flow_tac_set(mobile_flow, "2099");
+ evel_mobile_flow_tunnel_id_set(mobile_flow, "Tunnel 2");
+ evel_mobile_flow_vlan_id_set(mobile_flow, "4096");
+
+ evel_rc = evel_post_event((EVENT_HEADER *)mobile_flow);
+ if (evel_rc == EVEL_SUCCESS)
+ {
+ printf("Post OK!\n");
+ }
+ else
+ {
+ printf("Post Failed %d (%s)\n", evel_rc, evel_error_string());
+ }
+ }
+ else
+ {
+ printf("Failed to create event (%s)\n", evel_error_string());
+ }
+ printf(" Processed full Mobile Flow\n");
+ }
+ else
+ {
+ printf("New GTP Per Flow Metrics failed\n");
+ }
+}
diff --git a/VES5.0/evel/evel-library/code/evel_training/09-raise-state-change/Makefile b/VES5.0/evel/evel-library/code/evel_training/09-raise-state-change/Makefile
new file mode 100644
index 00000000..6acfdd42
--- /dev/null
+++ b/VES5.0/evel/evel-library/code/evel_training/09-raise-state-change/Makefile
@@ -0,0 +1,31 @@
+CC=gcc
+
+ARCH=$(shell getconf LONG_BIT)
+CODE_ROOT=$(CURDIR)/../../..
+LIBS_DIR=$(CODE_ROOT)/libs/x86_$(ARCH)
+INCLUDE_DIR=$(CODE_ROOT)/code/evel_library
+
+#******************************************************************************
+# Standard compiler flags. *
+#******************************************************************************
+CPPFLAGS=
+CFLAGS=-Wall -g -fPIC
+
+all: hello_evel_world
+
+hello_evel_world: hello_evel_world.c
+ $(CC) $(CPPFLAGS) $(CFLAGS) -o hello_evel_world \
+ -L $(LIBS_DIR) \
+ -I $(INCLUDE_DIR) \
+ hello_evel_world.c \
+ -lpthread \
+ -level \
+ -lcurl
+
+#******************************************************************************
+# Configure the vel_username and vel_password to
+# vel_username = username
+# vel_password = password
+#******************************************************************************
+run: all
+ ./hello_evel_world localhost 30000 username password
diff --git a/VES5.0/evel/evel-library/code/evel_training/09-raise-state-change/hello_evel_world.c b/VES5.0/evel/evel-library/code/evel_training/09-raise-state-change/hello_evel_world.c
new file mode 100644
index 00000000..db0ab8b6
--- /dev/null
+++ b/VES5.0/evel/evel-library/code/evel_training/09-raise-state-change/hello_evel_world.c
@@ -0,0 +1,117 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "evel.h"
+
+/*****************************************************************************/
+/* Local prototypes. */
+/*****************************************************************************/
+static void demo_state_change(void);
+
+int main(int argc, char ** argv)
+{
+ EVEL_ERR_CODES evel_rc = EVEL_SUCCESS;
+ EVENT_HEADER * heartbeat = NULL;
+
+ printf("\nHello AT&T Vendor Event world!\n");
+ fflush(stdout);
+
+ if (argc != 5)
+ {
+ fprintf(stderr,
+ "Usage: %s <FQDN>|<IP address> <port> "
+ "<username> <password>\n", argv[0]);
+ exit(-1);
+ }
+
+ /***************************************************************************/
+ /* Initialize */
+ /***************************************************************************/
+ if (evel_initialize(argv[1], /* FQDN */
+ atoi(argv[2]), /* Port */
+ NULL, /* optional path */
+ NULL, /* optional topic */
+ 0, /* HTTPS? */
+ argv[3], /* Username */
+ argv[4], /* Password */
+ EVEL_SOURCE_VIRTUAL_MACHINE, /* Source type */
+ "EVEL training demo", /* Role */
+ 0)) /* Verbosity */
+ {
+ fprintf(stderr, "\nFailed to initialize the EVEL library!!!\n");
+ exit(-1);
+ }
+ else
+ {
+ printf("\nInitialization completed\n");
+ }
+
+ /***************************************************************************/
+ /* Send a heartbeat just to show we're alive! */
+ /***************************************************************************/
+ heartbeat = evel_new_heartbeat();
+ if (heartbeat != NULL)
+ {
+ evel_rc = evel_post_event(heartbeat);
+ if (evel_rc != EVEL_SUCCESS)
+ {
+ printf("Post failed %d (%s)", evel_rc, evel_error_string());
+ }
+ }
+ else
+ {
+ printf("New heartbeat failed");
+ }
+
+ /***************************************************************************/
+ /* Raise a state change */
+ /***************************************************************************/
+ demo_state_change();
+
+ /***************************************************************************/
+ /* Terminate */
+ /***************************************************************************/
+ sleep(1);
+ evel_terminate();
+ printf("Terminated\n");
+
+ return 0;
+}
+
+/**************************************************************************//**
+ * Create and send a state change event.
+ *****************************************************************************/
+void demo_state_change(void)
+{
+ EVENT_STATE_CHANGE * state_change = NULL;
+ EVEL_ERR_CODES evel_rc = EVEL_SUCCESS;
+
+ /***************************************************************************/
+ /* State Change */
+ /***************************************************************************/
+ state_change = evel_new_state_change(EVEL_ENTITY_STATE_IN_SERVICE,
+ EVEL_ENTITY_STATE_OUT_OF_SERVICE,
+ "Interface");
+ if (state_change != NULL)
+ {
+ evel_state_change_type_set(state_change, "State Change");
+ evel_state_change_addl_field_add(state_change, "Name1", "Value1");
+ evel_state_change_addl_field_add(state_change, "Name2", "Value2");
+ evel_rc = evel_post_event((EVENT_HEADER *)state_change);
+ if (evel_rc == EVEL_SUCCESS)
+ {
+ printf("Post OK!\n");
+ }
+ else
+ {
+ printf("Post Failed %d (%s)\n", evel_rc, evel_error_string());
+ }
+ }
+ else
+ {
+ printf("Failed to create event (%s)\n", evel_error_string());
+ }
+
+ printf(" Processed State Change\n");
+}
diff --git a/VES5.0/evel/evel-library/code/evel_training/10-raise-syslog/Makefile b/VES5.0/evel/evel-library/code/evel_training/10-raise-syslog/Makefile
new file mode 100644
index 00000000..6acfdd42
--- /dev/null
+++ b/VES5.0/evel/evel-library/code/evel_training/10-raise-syslog/Makefile
@@ -0,0 +1,31 @@
+CC=gcc
+
+ARCH=$(shell getconf LONG_BIT)
+CODE_ROOT=$(CURDIR)/../../..
+LIBS_DIR=$(CODE_ROOT)/libs/x86_$(ARCH)
+INCLUDE_DIR=$(CODE_ROOT)/code/evel_library
+
+#******************************************************************************
+# Standard compiler flags. *
+#******************************************************************************
+CPPFLAGS=
+CFLAGS=-Wall -g -fPIC
+
+all: hello_evel_world
+
+hello_evel_world: hello_evel_world.c
+ $(CC) $(CPPFLAGS) $(CFLAGS) -o hello_evel_world \
+ -L $(LIBS_DIR) \
+ -I $(INCLUDE_DIR) \
+ hello_evel_world.c \
+ -lpthread \
+ -level \
+ -lcurl
+
+#******************************************************************************
+# Configure the vel_username and vel_password to
+# vel_username = username
+# vel_password = password
+#******************************************************************************
+run: all
+ ./hello_evel_world localhost 30000 username password
diff --git a/VES5.0/evel/evel-library/code/evel_training/10-raise-syslog/hello_evel_world.c b/VES5.0/evel/evel-library/code/evel_training/10-raise-syslog/hello_evel_world.c
new file mode 100644
index 00000000..7557743e
--- /dev/null
+++ b/VES5.0/evel/evel-library/code/evel_training/10-raise-syslog/hello_evel_world.c
@@ -0,0 +1,117 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "evel.h"
+
+/*****************************************************************************/
+/* Local prototypes. */
+/*****************************************************************************/
+static void demo_syslog(void);
+
+int main(int argc, char ** argv)
+{
+ EVEL_ERR_CODES evel_rc = EVEL_SUCCESS;
+ EVENT_HEADER * heartbeat = NULL;
+
+ printf("\nHello AT&T Vendor Event world!\n");
+ fflush(stdout);
+
+ if (argc != 5)
+ {
+ fprintf(stderr,
+ "Usage: %s <FQDN>|<IP address> <port> "
+ "<username> <password>\n", argv[0]);
+ exit(-1);
+ }
+
+ /***************************************************************************/
+ /* Initialize */
+ /***************************************************************************/
+ if (evel_initialize(argv[1], /* FQDN */
+ atoi(argv[2]), /* Port */
+ NULL, /* optional path */
+ NULL, /* optional topic */
+ 0, /* HTTPS? */
+ argv[3], /* Username */
+ argv[4], /* Password */
+ EVEL_SOURCE_VIRTUAL_MACHINE, /* Source type */
+ "EVEL training demo", /* Role */
+ 0)) /* Verbosity */
+ {
+ fprintf(stderr, "\nFailed to initialize the EVEL library!!!\n");
+ exit(-1);
+ }
+ else
+ {
+ printf("\nInitialization completed\n");
+ }
+
+ /***************************************************************************/
+ /* Send a heartbeat just to show we're alive! */
+ /***************************************************************************/
+ heartbeat = evel_new_heartbeat();
+ if (heartbeat != NULL)
+ {
+ evel_rc = evel_post_event(heartbeat);
+ if (evel_rc != EVEL_SUCCESS)
+ {
+ printf("Post failed %d (%s)", evel_rc, evel_error_string());
+ }
+ }
+ else
+ {
+ printf("New heartbeat failed");
+ }
+
+ /***************************************************************************/
+ /* Raise a syslog */
+ /***************************************************************************/
+ demo_syslog();
+
+ /***************************************************************************/
+ /* Terminate */
+ /***************************************************************************/
+ sleep(1);
+ evel_terminate();
+ printf("Terminated\n");
+
+ return 0;
+}
+
+/**************************************************************************//**
+ * Create and send a syslog event.
+ *****************************************************************************/
+void demo_syslog(void)
+{
+ EVENT_SYSLOG * syslog = NULL;
+ EVEL_ERR_CODES evel_rc = EVEL_SUCCESS;
+
+ syslog = evel_new_syslog(EVEL_SOURCE_VIRTUAL_MACHINE,
+ "EVEL library message",
+ "EVEL");
+ if (syslog != NULL)
+ {
+ evel_syslog_event_source_host_set(syslog, "Virtual host");
+ evel_syslog_facility_set(syslog, EVEL_SYSLOG_FACILITY_LOCAL0);
+ evel_syslog_proc_set(syslog, "vnf_process");
+ evel_syslog_proc_id_set(syslog, 1423);
+ evel_syslog_version_set(syslog, 1);
+ evel_syslog_addl_filter_set(syslog, "Name1=Value1|Name2=Value2|Name3=Value3");
+ evel_rc = evel_post_event((EVENT_HEADER *)syslog);
+ if (evel_rc == EVEL_SUCCESS)
+ {
+ printf("Post OK!\n");
+ }
+ else
+ {
+ printf("Post Failed %d (%s)\n", evel_rc, evel_error_string());
+ }
+ }
+ else
+ {
+ printf("Failed to create event (%s)\n", evel_error_string());
+ }
+
+ printf(" Processed Syslog\n");
+}
diff --git a/VES5.0/evel/evel-library/code/evel_training/11-raise-other/Makefile b/VES5.0/evel/evel-library/code/evel_training/11-raise-other/Makefile
new file mode 100644
index 00000000..6acfdd42
--- /dev/null
+++ b/VES5.0/evel/evel-library/code/evel_training/11-raise-other/Makefile
@@ -0,0 +1,31 @@
+CC=gcc
+
+ARCH=$(shell getconf LONG_BIT)
+CODE_ROOT=$(CURDIR)/../../..
+LIBS_DIR=$(CODE_ROOT)/libs/x86_$(ARCH)
+INCLUDE_DIR=$(CODE_ROOT)/code/evel_library
+
+#******************************************************************************
+# Standard compiler flags. *
+#******************************************************************************
+CPPFLAGS=
+CFLAGS=-Wall -g -fPIC
+
+all: hello_evel_world
+
+hello_evel_world: hello_evel_world.c
+ $(CC) $(CPPFLAGS) $(CFLAGS) -o hello_evel_world \
+ -L $(LIBS_DIR) \
+ -I $(INCLUDE_DIR) \
+ hello_evel_world.c \
+ -lpthread \
+ -level \
+ -lcurl
+
+#******************************************************************************
+# Configure the vel_username and vel_password to
+# vel_username = username
+# vel_password = password
+#******************************************************************************
+run: all
+ ./hello_evel_world localhost 30000 username password
diff --git a/VES5.0/evel/evel-library/code/evel_training/11-raise-other/hello_evel_world.c b/VES5.0/evel/evel-library/code/evel_training/11-raise-other/hello_evel_world.c
new file mode 100644
index 00000000..b03260b9
--- /dev/null
+++ b/VES5.0/evel/evel-library/code/evel_training/11-raise-other/hello_evel_world.c
@@ -0,0 +1,118 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "evel.h"
+
+/*****************************************************************************/
+/* Local prototypes. */
+/*****************************************************************************/
+static void demo_other(void);
+
+int main(int argc, char ** argv)
+{
+ EVEL_ERR_CODES evel_rc = EVEL_SUCCESS;
+ EVENT_HEADER * heartbeat = NULL;
+
+ printf("\nHello AT&T Vendor Event world!\n");
+ fflush(stdout);
+
+ if (argc != 5)
+ {
+ fprintf(stderr,
+ "Usage: %s <FQDN>|<IP address> <port> "
+ "<username> <password>\n", argv[0]);
+ exit(-1);
+ }
+
+ /***************************************************************************/
+ /* Initialize */
+ /***************************************************************************/
+ if (evel_initialize(argv[1], /* FQDN */
+ atoi(argv[2]), /* Port */
+ NULL, /* optional path */
+ NULL, /* optional topic */
+ 0, /* HTTPS? */
+ argv[3], /* Username */
+ argv[4], /* Password */
+ EVEL_SOURCE_VIRTUAL_MACHINE, /* Source type */
+ "EVEL training demo", /* Role */
+ 0)) /* Verbosity */
+ {
+ fprintf(stderr, "\nFailed to initialize the EVEL library!!!\n");
+ exit(-1);
+ }
+ else
+ {
+ printf("\nInitialization completed\n");
+ }
+
+ /***************************************************************************/
+ /* Send a heartbeat just to show we're alive! */
+ /***************************************************************************/
+ heartbeat = evel_new_heartbeat();
+ if (heartbeat != NULL)
+ {
+ evel_rc = evel_post_event(heartbeat);
+ if (evel_rc != EVEL_SUCCESS)
+ {
+ printf("Post failed %d (%s)", evel_rc, evel_error_string());
+ }
+ }
+ else
+ {
+ printf("New heartbeat failed");
+ }
+
+ /***************************************************************************/
+ /* Raise a state change */
+ /***************************************************************************/
+ demo_other();
+
+ /***************************************************************************/
+ /* Terminate */
+ /***************************************************************************/
+ sleep(1);
+ evel_terminate();
+ printf("Terminated\n");
+
+ return 0;
+}
+
+/**************************************************************************//**
+ * Create and send an other event.
+ *****************************************************************************/
+void demo_other(void)
+{
+ EVENT_OTHER * other = NULL;
+ EVEL_ERR_CODES evel_rc = EVEL_SUCCESS;
+
+ other = evel_new_other();
+ if (other != NULL)
+ {
+ evel_other_field_add(other,
+ "Other field A",
+ "Other value A");
+ evel_other_field_add(other,
+ "Other field B",
+ "Other value B");
+ evel_other_field_add(other,
+ "Other field C",
+ "Other value C");
+ evel_rc = evel_post_event((EVENT_HEADER *)other);
+ if (evel_rc == EVEL_SUCCESS)
+ {
+ printf("Post OK!\n");
+ }
+ else
+ {
+ printf("Post Failed %d (%s)\n", evel_rc, evel_error_string());
+ }
+ }
+ else
+ {
+ printf("Failed to create event (%s)\n", evel_error_string());
+ }
+
+ printf(" Processed Other\n");
+}
diff --git a/VES5.0/evel/evel-library/code/evel_training/12-suppress-fault-fields/Makefile b/VES5.0/evel/evel-library/code/evel_training/12-suppress-fault-fields/Makefile
new file mode 100644
index 00000000..ee8c3461
--- /dev/null
+++ b/VES5.0/evel/evel-library/code/evel_training/12-suppress-fault-fields/Makefile
@@ -0,0 +1,35 @@
+CC=gcc
+
+ARCH=$(shell getconf LONG_BIT)
+CODE_ROOT=$(CURDIR)/../../..
+LIBS_DIR=$(CODE_ROOT)/libs/x86_$(ARCH)
+INCLUDE_DIR=$(CODE_ROOT)/code/evel_library
+EVEL_DEMO=$(CURDIR)/../../evel_demo
+TEST_CONTROL=$(EVEL_DEMO)/evel_test_control.c
+
+#******************************************************************************
+# Standard compiler flags. *
+#******************************************************************************
+CPPFLAGS=
+CFLAGS=-Wall -g -fPIC
+
+all: hello_evel_world
+
+hello_evel_world: hello_evel_world.c $(TEST_CONTROL)
+ $(CC) $(CPPFLAGS) $(CFLAGS) -o hello_evel_world \
+ -L $(LIBS_DIR) \
+ -I $(INCLUDE_DIR) \
+ -I $(EVEL_DEMO) \
+ hello_evel_world.c \
+ $(TEST_CONTROL) \
+ -lpthread \
+ -level \
+ -lcurl
+
+#******************************************************************************
+# Configure the vel_username and vel_password to
+# vel_username = username
+# vel_password = password
+#******************************************************************************
+run: all
+ ./hello_evel_world 127.0.0.1 30000 username password
diff --git a/VES5.0/evel/evel-library/code/evel_training/12-suppress-fault-fields/hello_evel_world.c b/VES5.0/evel/evel-library/code/evel_training/12-suppress-fault-fields/hello_evel_world.c
new file mode 100644
index 00000000..8943d57b
--- /dev/null
+++ b/VES5.0/evel/evel-library/code/evel_training/12-suppress-fault-fields/hello_evel_world.c
@@ -0,0 +1,180 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "evel.h"
+#include "evel_test_control.h"
+
+/*****************************************************************************/
+/* Local prototypes. */
+/*****************************************************************************/
+static void demo_heartbeat();
+static void demo_fault(void);
+
+int main(int argc, char ** argv)
+{
+ printf("\nHello AT&T Vendor Event world!\n");
+ fflush(stdout);
+
+ if (argc != 5)
+ {
+ fprintf(stderr,
+ "Usage: %s <FQDN>|<IP address> <port> "
+ "<username> <password>\n", argv[0]);
+ exit(-1);
+ }
+
+ char * api_fqdn = argv[1];
+ int api_port = atoi(argv[2]);
+ int api_secure = 0;
+
+ /***************************************************************************/
+ /* Initialize */
+ /***************************************************************************/
+ if (evel_initialize(api_fqdn, /* FQDN */
+ api_port, /* Port */
+ NULL, /* optional path */
+ NULL, /* optional topic */
+ api_secure, /* HTTPS? */
+ argv[3], /* Username */
+ argv[4], /* Password */
+ EVEL_SOURCE_VIRTUAL_MACHINE, /* Source type */
+ "EVEL training demo", /* Role */
+ 0)) /* Verbosity */
+ {
+ fprintf(stderr, "\nFailed to initialize the EVEL library!!!\n");
+ exit(-1);
+ }
+ else
+ {
+ printf("\nInitialization completed\n");
+ }
+
+ /***************************************************************************/
+ /* Raise a fault. */
+ /***************************************************************************/
+ printf("Raise normal fault ...\n");
+ fflush(stdout);
+ demo_fault();
+ sleep(1);
+
+ /***************************************************************************/
+ /* Ask for suppression of alarmInterfaceA and alarmAdditionalInformation. */
+ /***************************************************************************/
+ printf("TestControl: test collector suppress fault fields\n");
+ fflush(stdout);
+ evel_test_control_scenario(TC_FAULT_SUPPRESS_FIELDS,
+ api_secure,
+ api_fqdn,
+ api_port);
+ sleep(1);
+
+ /***************************************************************************/
+ /* Heartbeat to pick up the suppression change. */
+ /***************************************************************************/
+ demo_heartbeat();
+
+ /***************************************************************************/
+ /* Raise the same fault. */
+ /***************************************************************************/
+ printf("Raise normal fault ...\n");
+ fflush(stdout);
+ demo_fault();
+ sleep(1);
+
+ /***************************************************************************/
+ /* Ask for removal of fault suppression. */
+ /***************************************************************************/
+ printf("TestControl: test collector remove fault suppression\n");
+ fflush(stdout);
+ evel_test_control_scenario(TC_FAULT_SUPPRESS_NOTHING,
+ api_secure,
+ api_fqdn,
+ api_port);
+ sleep(1);
+
+ /***************************************************************************/
+ /* Heartbeat to pick up the suppression change. */
+ /***************************************************************************/
+ demo_heartbeat();
+
+ /***************************************************************************/
+ /* Raise the same fault. */
+ /***************************************************************************/
+ printf("Raise normal fault ...\n");
+ fflush(stdout);
+ demo_fault();
+ sleep(1);
+
+ /***************************************************************************/
+ /* Terminate */
+ /***************************************************************************/
+ sleep(1);
+ evel_terminate();
+ printf("Terminated\n");
+
+ return 0;
+}
+
+/**************************************************************************//**
+ * Create and send a heatbeat.
+ *****************************************************************************/
+void demo_heartbeat()
+{
+ EVENT_HEADER * heartbeat = NULL;
+ EVEL_ERR_CODES evel_rc = EVEL_SUCCESS;
+
+ heartbeat = evel_new_heartbeat();
+ if (heartbeat != NULL)
+ {
+ evel_rc = evel_post_event(heartbeat);
+ if (evel_rc != EVEL_SUCCESS)
+ {
+ printf("Post failed %d (%s)", evel_rc, evel_error_string());
+ }
+ }
+ else
+ {
+ printf("New heartbeat failed");
+ }
+}
+
+/**************************************************************************//**
+ * Create and send a fault event.
+ *****************************************************************************/
+void demo_fault(void)
+{
+ EVENT_FAULT * fault = NULL;
+ EVEL_ERR_CODES evel_rc = EVEL_SUCCESS;
+
+ 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);
+ 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_fault_addl_info_add(fault, "name3", "value3");
+ evel_fault_addl_info_add(fault, "name4", "value4");
+ evel_rc = evel_post_event((EVENT_HEADER *)fault);
+ if (evel_rc == EVEL_SUCCESS)
+ {
+ printf("Post OK!\n");
+ }
+ else
+ {
+ printf("Post Failed %d (%s)\n", evel_rc, evel_error_string());
+ }
+ }
+ else
+ {
+ printf("Failed to create event (%s)\n", evel_error_string());
+ }
+
+ printf(" Processed Fault\n");
+}
diff --git a/VES5.0/evel/evel-library/code/evel_training/13-suppress-fault-pairs/Makefile b/VES5.0/evel/evel-library/code/evel_training/13-suppress-fault-pairs/Makefile
new file mode 100644
index 00000000..ee8c3461
--- /dev/null
+++ b/VES5.0/evel/evel-library/code/evel_training/13-suppress-fault-pairs/Makefile
@@ -0,0 +1,35 @@
+CC=gcc
+
+ARCH=$(shell getconf LONG_BIT)
+CODE_ROOT=$(CURDIR)/../../..
+LIBS_DIR=$(CODE_ROOT)/libs/x86_$(ARCH)
+INCLUDE_DIR=$(CODE_ROOT)/code/evel_library
+EVEL_DEMO=$(CURDIR)/../../evel_demo
+TEST_CONTROL=$(EVEL_DEMO)/evel_test_control.c
+
+#******************************************************************************
+# Standard compiler flags. *
+#******************************************************************************
+CPPFLAGS=
+CFLAGS=-Wall -g -fPIC
+
+all: hello_evel_world
+
+hello_evel_world: hello_evel_world.c $(TEST_CONTROL)
+ $(CC) $(CPPFLAGS) $(CFLAGS) -o hello_evel_world \
+ -L $(LIBS_DIR) \
+ -I $(INCLUDE_DIR) \
+ -I $(EVEL_DEMO) \
+ hello_evel_world.c \
+ $(TEST_CONTROL) \
+ -lpthread \
+ -level \
+ -lcurl
+
+#******************************************************************************
+# Configure the vel_username and vel_password to
+# vel_username = username
+# vel_password = password
+#******************************************************************************
+run: all
+ ./hello_evel_world 127.0.0.1 30000 username password
diff --git a/VES5.0/evel/evel-library/code/evel_training/13-suppress-fault-pairs/hello_evel_world.c b/VES5.0/evel/evel-library/code/evel_training/13-suppress-fault-pairs/hello_evel_world.c
new file mode 100644
index 00000000..625daa9c
--- /dev/null
+++ b/VES5.0/evel/evel-library/code/evel_training/13-suppress-fault-pairs/hello_evel_world.c
@@ -0,0 +1,181 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "evel.h"
+#include "evel_test_control.h"
+
+/*****************************************************************************/
+/* Local prototypes. */
+/*****************************************************************************/
+static void demo_heartbeat();
+static void demo_fault(void);
+
+int main(int argc, char ** argv)
+{
+ printf("\nHello AT&T Vendor Event world!\n");
+ fflush(stdout);
+
+ if (argc != 5)
+ {
+ fprintf(stderr,
+ "Usage: %s <FQDN>|<IP address> <port> "
+ "<username> <password>\n", argv[0]);
+ exit(-1);
+ }
+
+ char * api_fqdn = argv[1];
+ int api_port = atoi(argv[2]);
+ int api_secure = 0;
+
+ /***************************************************************************/
+ /* Initialize */
+ /***************************************************************************/
+ if (evel_initialize(api_fqdn, /* FQDN */
+ api_port, /* Port */
+ NULL, /* optional path */
+ NULL, /* optional topic */
+ api_secure, /* HTTPS? */
+ argv[3], /* Username */
+ argv[4], /* Password */
+ EVEL_SOURCE_VIRTUAL_MACHINE, /* Source type */
+ "EVEL training demo", /* Role */
+ 0)) /* Verbosity */
+ {
+ fprintf(stderr, "\nFailed to initialize the EVEL library!!!\n");
+ exit(-1);
+ }
+ else
+ {
+ printf("\nInitialization completed\n");
+ }
+
+ /***************************************************************************/
+ /* Raise a fault. */
+ /***************************************************************************/
+ printf("Raise normal fault ...\n");
+ fflush(stdout);
+ demo_fault();
+ sleep(1);
+
+ /***************************************************************************/
+ /* Ask for suppression of pairs (under "alarmAdditionalInformation") with */
+ /* names "name1" and "name2". */
+ /***************************************************************************/
+ printf("TestControl: test collector suppress fault pairs\n");
+ fflush(stdout);
+ evel_test_control_scenario(TC_FAULT_SUPPRESS_PAIRS,
+ api_secure,
+ api_fqdn,
+ api_port);
+ sleep(1);
+
+ /***************************************************************************/
+ /* Heartbeat to pick up the suppression change. */
+ /***************************************************************************/
+ demo_heartbeat();
+
+ /***************************************************************************/
+ /* Raise the same fault. */
+ /***************************************************************************/
+ printf("Raise normal fault ...\n");
+ fflush(stdout);
+ demo_fault();
+ sleep(1);
+
+ /***************************************************************************/
+ /* Ask for removal of fault suppression. */
+ /***************************************************************************/
+ printf("TestControl: test collector remove fault suppression\n");
+ fflush(stdout);
+ evel_test_control_scenario(TC_FAULT_SUPPRESS_NOTHING,
+ api_secure,
+ api_fqdn,
+ api_port);
+ sleep(1);
+
+ /***************************************************************************/
+ /* Heartbeat to pick up the suppression change. */
+ /***************************************************************************/
+ demo_heartbeat();
+
+ /***************************************************************************/
+ /* Raise the same fault. */
+ /***************************************************************************/
+ printf("Raise normal fault ...\n");
+ fflush(stdout);
+ demo_fault();
+ sleep(1);
+
+ /***************************************************************************/
+ /* Terminate */
+ /***************************************************************************/
+ sleep(1);
+ evel_terminate();
+ printf("Terminated\n");
+
+ return 0;
+}
+
+/**************************************************************************//**
+ * Create and send a heatbeat.
+ *****************************************************************************/
+void demo_heartbeat()
+{
+ EVENT_HEADER * heartbeat = NULL;
+ EVEL_ERR_CODES evel_rc = EVEL_SUCCESS;
+
+ heartbeat = evel_new_heartbeat();
+ if (heartbeat != NULL)
+ {
+ evel_rc = evel_post_event(heartbeat);
+ if (evel_rc != EVEL_SUCCESS)
+ {
+ printf("Post failed %d (%s)", evel_rc, evel_error_string());
+ }
+ }
+ else
+ {
+ printf("New heartbeat failed");
+ }
+}
+
+/**************************************************************************//**
+ * Create and send a fault event.
+ *****************************************************************************/
+void demo_fault(void)
+{
+ EVENT_FAULT * fault = NULL;
+ EVEL_ERR_CODES evel_rc = EVEL_SUCCESS;
+
+ 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);
+ 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_fault_addl_info_add(fault, "name3", "value3");
+ evel_fault_addl_info_add(fault, "name4", "value4");
+ evel_rc = evel_post_event((EVENT_HEADER *)fault);
+ if (evel_rc == EVEL_SUCCESS)
+ {
+ printf("Post OK!\n");
+ }
+ else
+ {
+ printf("Post Failed %d (%s)\n", evel_rc, evel_error_string());
+ }
+ }
+ else
+ {
+ printf("Failed to create event (%s)\n", evel_error_string());
+ }
+
+ printf(" Processed Fault\n");
+}
diff --git a/VES5.0/evel/evel-library/code/evel_training/14-measurement-interval/Makefile b/VES5.0/evel/evel-library/code/evel_training/14-measurement-interval/Makefile
new file mode 100644
index 00000000..ee8c3461
--- /dev/null
+++ b/VES5.0/evel/evel-library/code/evel_training/14-measurement-interval/Makefile
@@ -0,0 +1,35 @@
+CC=gcc
+
+ARCH=$(shell getconf LONG_BIT)
+CODE_ROOT=$(CURDIR)/../../..
+LIBS_DIR=$(CODE_ROOT)/libs/x86_$(ARCH)
+INCLUDE_DIR=$(CODE_ROOT)/code/evel_library
+EVEL_DEMO=$(CURDIR)/../../evel_demo
+TEST_CONTROL=$(EVEL_DEMO)/evel_test_control.c
+
+#******************************************************************************
+# Standard compiler flags. *
+#******************************************************************************
+CPPFLAGS=
+CFLAGS=-Wall -g -fPIC
+
+all: hello_evel_world
+
+hello_evel_world: hello_evel_world.c $(TEST_CONTROL)
+ $(CC) $(CPPFLAGS) $(CFLAGS) -o hello_evel_world \
+ -L $(LIBS_DIR) \
+ -I $(INCLUDE_DIR) \
+ -I $(EVEL_DEMO) \
+ hello_evel_world.c \
+ $(TEST_CONTROL) \
+ -lpthread \
+ -level \
+ -lcurl
+
+#******************************************************************************
+# Configure the vel_username and vel_password to
+# vel_username = username
+# vel_password = password
+#******************************************************************************
+run: all
+ ./hello_evel_world 127.0.0.1 30000 username password
diff --git a/VES5.0/evel/evel-library/code/evel_training/14-measurement-interval/hello_evel_world.c b/VES5.0/evel/evel-library/code/evel_training/14-measurement-interval/hello_evel_world.c
new file mode 100644
index 00000000..269262aa
--- /dev/null
+++ b/VES5.0/evel/evel-library/code/evel_training/14-measurement-interval/hello_evel_world.c
@@ -0,0 +1,293 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/time.h>
+
+#include "evel.h"
+#include "evel_test_control.h"
+
+/*****************************************************************************/
+/* Local prototypes. */
+/*****************************************************************************/
+static void demo_heartbeat();
+static void demo_measurement(const int interval);
+
+unsigned long long epoch_start = 0;
+
+int main(int argc, char ** argv)
+{
+ printf("\nHello AT&T Vendor Event world!\n");
+ fflush(stdout);
+
+ if (argc != 5)
+ {
+ fprintf(stderr,
+ "Usage: %s <FQDN>|<IP address> <port> "
+ "<username> <password>\n", argv[0]);
+ exit(-1);
+ }
+
+ char * api_fqdn = argv[1];
+ int api_port = atoi(argv[2]);
+ int api_secure = 0;
+
+ /***************************************************************************/
+ /* Initialize */
+ /***************************************************************************/
+ if (evel_initialize(api_fqdn, /* FQDN */
+ api_port, /* Port */
+ NULL, /* optional path */
+ NULL, /* optional topic */
+ api_secure, /* HTTPS? */
+ argv[3], /* Username */
+ argv[4], /* Password */
+ EVEL_SOURCE_VIRTUAL_MACHINE, /* Source type */
+ "EVEL training demo", /* Role */
+ 0)) /* Verbosity */
+ {
+ fprintf(stderr, "\nFailed to initialize the EVEL library!!!\n");
+ exit(-1);
+ }
+ else
+ {
+ printf("\nInitialization completed\n");
+ }
+
+ /***************************************************************************/
+ /* Work out a start time for measurements, and sleep for initial period. */
+ /***************************************************************************/
+ int sleep_time = 1;
+ struct timeval tv_start;
+ gettimeofday(&tv_start, NULL);
+ epoch_start = tv_start.tv_usec + 1000000 * tv_start.tv_sec;
+ sleep(sleep_time);
+
+ int index;
+ for (index = 0; index < 10; index++)
+ {
+ /*************************************************************************/
+ /* On the second and fifth iteration, get the test_collector to change */
+ /* the interval. */
+ /*************************************************************************/
+ if (index == 2)
+ {
+ printf("TestControl: measurement interval -> 2s\n");
+ evel_test_control_meas_interval(2, api_secure, api_fqdn, api_port);
+ }
+ if (index == 5)
+ {
+ printf("TestControl: measurement interval -> 5s\n");
+ evel_test_control_meas_interval(5, api_secure, api_fqdn, api_port);
+ }
+
+ /*************************************************************************/
+ /* Heartbeat to pick up the suppression change. */
+ /*************************************************************************/
+ demo_heartbeat();
+
+ /*************************************************************************/
+ /* Raise a measurement and sleep. */
+ /*************************************************************************/
+ printf("Report measurements\n");
+ fflush(stdout);
+ demo_measurement(sleep_time);
+ printf("Sleeping for %ds\n", sleep_time);
+ fflush(stdout);
+ sleep(sleep_time);
+
+ /*************************************************************************/
+ /* Update measurement interval. */
+ /*************************************************************************/
+ int measurement_interval;
+ measurement_interval = evel_get_measurement_interval();
+ if (measurement_interval == EVEL_MEASUREMENT_INTERVAL_UKNOWN)
+ {
+ sleep_time = 1;
+ }
+ else
+ {
+ sleep_time = measurement_interval;
+ }
+ printf("EVEL measurement interval = %d\n\n", measurement_interval);
+ }
+
+ /***************************************************************************/
+ /* Terminate */
+ /***************************************************************************/
+ sleep(1);
+ evel_terminate();
+ printf("Terminated\n");
+
+ return 0;
+}
+
+/**************************************************************************//**
+ * Create and send a heatbeat.
+ *****************************************************************************/
+void demo_heartbeat()
+{
+ EVENT_HEADER * heartbeat = NULL;
+ EVEL_ERR_CODES evel_rc = EVEL_SUCCESS;
+
+ heartbeat = evel_new_heartbeat();
+ if (heartbeat != NULL)
+ {
+ evel_rc = evel_post_event(heartbeat);
+ if (evel_rc != EVEL_SUCCESS)
+ {
+ printf("Post failed %d (%s)", evel_rc, evel_error_string());
+ }
+ }
+ else
+ {
+ printf("New heartbeat failed");
+ }
+}
+
+/**************************************************************************//**
+ * Create and send a measurement event.
+ *****************************************************************************/
+void demo_measurement(const int interval)
+{
+ EVENT_MEASUREMENT * measurement = NULL;
+ MEASUREMENT_LATENCY_BUCKET * bucket = NULL;
+ MEASUREMENT_VNIC_PERFORMANCE * vnic_performance = NULL;
+ EVEL_ERR_CODES evel_rc = EVEL_SUCCESS;
+ MEASUREMENT_CPU_USE *cpu_use;
+
+ /***************************************************************************/
+ /* Measurement */
+ /***************************************************************************/
+ measurement = evel_new_measurement(interval);
+ if (measurement != NULL)
+ {
+ printf("New measurement created...\n");
+ 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, 6);
+
+ 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);
+
+ bucket = evel_new_meas_latency_bucket(20);
+ evel_meas_latency_bucket_low_end_set(bucket, 0.0);
+ evel_meas_latency_bucket_high_end_set(bucket, 10.0);
+ 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_performance = evel_measurement_new_vnic_performance("eth0", "true");
+
+ evel_vnic_performance_rx_bcast_pkt_acc_set(vnic_performance, 1000000.023);
+ evel_vnic_performance_rx_bcast_pkt_delta_set(vnic_performance,1234.767346);
+ evel_vnic_performance_rx_discard_pkt_acc_set(vnic_performance, 127146784.234738587);
+ evel_vnic_performance_rx_discard_pkt_delta_set(vnic_performance, 123445);
+ evel_vnic_performance_rx_error_pkt_acc_set(vnic_performance, 2736448376);
+ evel_vnic_performance_rx_error_pkt_delta_set(vnic_performance, 3474438764);
+ evel_vnic_performance_rx_mcast_pkt_acc_set(vnic_performance, 42464676);
+ evel_vnic_performance_rx_mcast_pkt_delta_set(vnic_performance, 42678657654);
+ evel_vnic_performance_rx_octets_acc_set(vnic_performance, 47658745);
+ evel_vnic_performance_rx_octets_delta_set(vnic_performance, 47656465465);
+ evel_vnic_performance_rx_total_pkt_acc_set(vnic_performance, 4765764654444);
+ evel_vnic_performance_rx_total_pkt_delta_set(vnic_performance, 4545665656);
+ evel_vnic_performance_rx_ucast_pkt_acc_set(vnic_performance, 4765745546.);
+ evel_vnic_performance_rx_ucast_pkt_delta_set(vnic_performance, 4768765.78347856);
+ evel_vnic_performance_tx_bcast_pkt_acc_set(vnic_performance, 747665.347647);
+ evel_vnic_performance_tx_bcast_pkt_delta_set(vnic_performance, 3468765.4774);
+ evel_vnic_performance_tx_discarded_pkt_acc_set(vnic_performance, 53625345.53);
+ evel_vnic_performance_tx_discarded_pkt_delta_set(vnic_performance, 5465345.72455);
+ evel_vnic_performance_tx_error_pkt_acc_set(vnic_performance, 7632754.754);
+ evel_vnic_performance_tx_error_pkt_delta_set(vnic_performance, 34646875444.);
+ evel_vnic_performance_tx_mcast_pkt_acc_set(vnic_performance, 2734875.5534);
+ evel_vnic_performance_tx_mcast_pkt_delta_set(vnic_performance, 562346534.654);
+ evel_vnic_performance_tx_octets_acc_set(vnic_performance, 2785845.76874);
+ evel_meas_vnic_performance_add(measurement, vnic_performance);
+
+ vnic_performance = evel_measurement_new_vnic_performance("eth1", "false");
+ evel_vnic_performance_rx_mcast_pkt_delta_set(vnic_performance, 42678657654);
+ evel_vnic_performance_rx_octets_acc_set(vnic_performance, 47658745);
+ evel_vnic_performance_rx_octets_delta_set(vnic_performance, 47656465465);
+ evel_vnic_performance_rx_total_pkt_acc_set(vnic_performance, 4765764654444);
+ evel_vnic_performance_rx_total_pkt_delta_set(vnic_performance, 4545665656);
+ evel_vnic_performance_rx_ucast_pkt_acc_set(vnic_performance, 4765745546.);
+ evel_vnic_performance_rx_ucast_pkt_delta_set(vnic_performance, 4768765.78347856);
+ evel_vnic_performance_tx_bcast_pkt_acc_set(vnic_performance, 747665.347647);
+ evel_vnic_performance_tx_bcast_pkt_delta_set(vnic_performance, 3468765.4774);
+ evel_vnic_performance_tx_discarded_pkt_acc_set(vnic_performance, 53625345.53);
+ evel_meas_vnic_performance_add(measurement, vnic_performance);
+
+ 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");
+
+ /*************************************************************************/
+ /* Work out the time, to use as end of measurement period. */
+ /*************************************************************************/
+ struct timeval tv_now;
+ gettimeofday(&tv_now, NULL);
+ unsigned long long epoch_now = tv_now.tv_usec + 1000000 * tv_now.tv_sec;
+ evel_start_epoch_set(&measurement->header, epoch_start);
+ evel_last_epoch_set(&measurement->header, epoch_now);
+ epoch_start = epoch_now;
+ evel_reporting_entity_name_set(&measurement->header, "measurer");
+ evel_reporting_entity_id_set(&measurement->header, "measurer_id");
+
+ evel_rc = evel_post_event((EVENT_HEADER *)measurement);
+ if (evel_rc == EVEL_SUCCESS)
+ {
+ printf("Post OK!\n");
+ }
+ else
+ {
+ printf("Post Failed %d (%s)\n", evel_rc, evel_error_string());
+ }
+ }
+ else
+ {
+ printf("Failed to create event (%s)\n", evel_error_string());
+ }
+
+ printf(" Processed Measurement\n");
+}
diff --git a/VES5.0/evel/evel-library/code/evel_training/15-raise-signaling/Makefile b/VES5.0/evel/evel-library/code/evel_training/15-raise-signaling/Makefile
new file mode 100644
index 00000000..6acfdd42
--- /dev/null
+++ b/VES5.0/evel/evel-library/code/evel_training/15-raise-signaling/Makefile
@@ -0,0 +1,31 @@
+CC=gcc
+
+ARCH=$(shell getconf LONG_BIT)
+CODE_ROOT=$(CURDIR)/../../..
+LIBS_DIR=$(CODE_ROOT)/libs/x86_$(ARCH)
+INCLUDE_DIR=$(CODE_ROOT)/code/evel_library
+
+#******************************************************************************
+# Standard compiler flags. *
+#******************************************************************************
+CPPFLAGS=
+CFLAGS=-Wall -g -fPIC
+
+all: hello_evel_world
+
+hello_evel_world: hello_evel_world.c
+ $(CC) $(CPPFLAGS) $(CFLAGS) -o hello_evel_world \
+ -L $(LIBS_DIR) \
+ -I $(INCLUDE_DIR) \
+ hello_evel_world.c \
+ -lpthread \
+ -level \
+ -lcurl
+
+#******************************************************************************
+# Configure the vel_username and vel_password to
+# vel_username = username
+# vel_password = password
+#******************************************************************************
+run: all
+ ./hello_evel_world localhost 30000 username password
diff --git a/VES5.0/evel/evel-library/code/evel_training/15-raise-signaling/hello_evel_world.c b/VES5.0/evel/evel-library/code/evel_training/15-raise-signaling/hello_evel_world.c
new file mode 100644
index 00000000..c97290ac
--- /dev/null
+++ b/VES5.0/evel/evel-library/code/evel_training/15-raise-signaling/hello_evel_world.c
@@ -0,0 +1,115 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "evel.h"
+
+/*****************************************************************************/
+/* Local prototypes. */
+/*****************************************************************************/
+static void demo_signaling(void);
+
+int main(int argc, char ** argv)
+{
+ EVEL_ERR_CODES evel_rc = EVEL_SUCCESS;
+ EVENT_HEADER * heartbeat = NULL;
+
+ printf("\nHello AT&T Vendor Event world!\n");
+ fflush(stdout);
+
+ if (argc != 5)
+ {
+ fprintf(stderr,
+ "Usage: %s <FQDN>|<IP address> <port> "
+ "<username> <password>\n", argv[0]);
+ exit(-1);
+ }
+
+ /***************************************************************************/
+ /* Initialize */
+ /***************************************************************************/
+ if (evel_initialize(argv[1], /* FQDN */
+ atoi(argv[2]), /* Port */
+ NULL, /* optional path */
+ NULL, /* optional topic */
+ 0, /* HTTPS? */
+ argv[3], /* Username */
+ argv[4], /* Password */
+ EVEL_SOURCE_VIRTUAL_MACHINE, /* Source type */
+ "EVEL training demo", /* Role */
+ 0)) /* Verbosity */
+ {
+ fprintf(stderr, "\nFailed to initialize the EVEL library!!!\n");
+ exit(-1);
+ }
+ else
+ {
+ printf("\nInitialization completed\n");
+ }
+
+ /***************************************************************************/
+ /* Send a heartbeat just to show we're alive! */
+ /***************************************************************************/
+ heartbeat = evel_new_heartbeat();
+ if (heartbeat != NULL)
+ {
+ evel_rc = evel_post_event(heartbeat);
+ if (evel_rc != EVEL_SUCCESS)
+ {
+ printf("Post failed %d (%s)", evel_rc, evel_error_string());
+ }
+ }
+ else
+ {
+ printf("New heartbeat failed");
+ }
+
+ /***************************************************************************/
+ /* Raise a Signaling event */
+ /***************************************************************************/
+ demo_signaling();
+
+ /***************************************************************************/
+ /* Terminate */
+ /***************************************************************************/
+ sleep(1);
+ evel_terminate();
+ printf("Terminated\n");
+
+ return 0;
+}
+
+/**************************************************************************//**
+ * Create and send a Signaling event.
+ *****************************************************************************/
+void demo_signaling(void)
+{
+ EVENT_SIGNALING * event = NULL;
+ EVEL_ERR_CODES evel_rc = EVEL_SUCCESS;
+
+ event = evel_new_signaling("vendor_x_id",
+ "correlator", "1.0.3.1", "1234", "192.168.1.3","3456");
+ if (event != NULL)
+ {
+ evel_signaling_type_set(event, "Signaling");
+ evel_signaling_vnfmodule_name_set(event, "vendor_x_module");
+ evel_signaling_vnfname_set(event, "vendor_x_vnf");
+ 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");
+ evel_rc = evel_post_event((EVENT_HEADER *) event);
+ if (evel_rc != EVEL_SUCCESS)
+ {
+ EVEL_ERROR("Post failed %d (%s)", evel_rc, evel_error_string());
+ }
+ }
+ else
+ {
+ EVEL_ERROR("New Signaling failed");
+ }
+ printf(" Processed Signaling\n");
+}
diff --git a/VES5.0/evel/evel-library/code/evel_training/16-raise-service/Makefile b/VES5.0/evel/evel-library/code/evel_training/16-raise-service/Makefile
new file mode 100644
index 00000000..6acfdd42
--- /dev/null
+++ b/VES5.0/evel/evel-library/code/evel_training/16-raise-service/Makefile
@@ -0,0 +1,31 @@
+CC=gcc
+
+ARCH=$(shell getconf LONG_BIT)
+CODE_ROOT=$(CURDIR)/../../..
+LIBS_DIR=$(CODE_ROOT)/libs/x86_$(ARCH)
+INCLUDE_DIR=$(CODE_ROOT)/code/evel_library
+
+#******************************************************************************
+# Standard compiler flags. *
+#******************************************************************************
+CPPFLAGS=
+CFLAGS=-Wall -g -fPIC
+
+all: hello_evel_world
+
+hello_evel_world: hello_evel_world.c
+ $(CC) $(CPPFLAGS) $(CFLAGS) -o hello_evel_world \
+ -L $(LIBS_DIR) \
+ -I $(INCLUDE_DIR) \
+ hello_evel_world.c \
+ -lpthread \
+ -level \
+ -lcurl
+
+#******************************************************************************
+# Configure the vel_username and vel_password to
+# vel_username = username
+# vel_password = password
+#******************************************************************************
+run: all
+ ./hello_evel_world localhost 30000 username password
diff --git a/VES5.0/evel/evel-library/code/evel_training/16-raise-service/hello_evel_world.c b/VES5.0/evel/evel-library/code/evel_training/16-raise-service/hello_evel_world.c
new file mode 100644
index 00000000..53a7bd7e
--- /dev/null
+++ b/VES5.0/evel/evel-library/code/evel_training/16-raise-service/hello_evel_world.c
@@ -0,0 +1,119 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "evel.h"
+
+/*****************************************************************************/
+/* Local prototypes. */
+/*****************************************************************************/
+static void demo_service(void);
+
+int main(int argc, char ** argv)
+{
+ EVEL_ERR_CODES evel_rc = EVEL_SUCCESS;
+ EVENT_HEADER * heartbeat = NULL;
+
+ printf("\nHello AT&T Vendor Event world!\n");
+ fflush(stdout);
+
+ if (argc != 5)
+ {
+ fprintf(stderr,
+ "Usage: %s <FQDN>|<IP address> <port> "
+ "<username> <password>\n", argv[0]);
+ exit(-1);
+ }
+
+ /***************************************************************************/
+ /* Initialize */
+ /***************************************************************************/
+ if (evel_initialize(argv[1], /* FQDN */
+ atoi(argv[2]), /* Port */
+ NULL, /* optional path */
+ NULL, /* optional topic */
+ 0, /* HTTPS? */
+ argv[3], /* Username */
+ argv[4], /* Password */
+ EVEL_SOURCE_VIRTUAL_MACHINE, /* Source type */
+ "EVEL training demo", /* Role */
+ 0)) /* Verbosity */
+ {
+ fprintf(stderr, "\nFailed to initialize the EVEL library!!!\n");
+ exit(-1);
+ }
+ else
+ {
+ printf("\nInitialization completed\n");
+ }
+
+ /***************************************************************************/
+ /* Send a heartbeat just to show we're alive! */
+ /***************************************************************************/
+ heartbeat = evel_new_heartbeat();
+ if (heartbeat != NULL)
+ {
+ evel_rc = evel_post_event(heartbeat);
+ if (evel_rc != EVEL_SUCCESS)
+ {
+ printf("Post failed %d (%s)", evel_rc, evel_error_string());
+ }
+ }
+ else
+ {
+ printf("New heartbeat failed");
+ }
+
+ /***************************************************************************/
+ /* Raise a service event */
+ /***************************************************************************/
+ demo_service();
+
+ /***************************************************************************/
+ /* Terminate */
+ /***************************************************************************/
+ sleep(1);
+ evel_terminate();
+ printf("Terminated\n");
+
+ return 0;
+}
+
+/**************************************************************************//**
+ * Create and send a Service event.
+ *****************************************************************************/
+void demo_service(void)
+{
+ EVENT_SIGNALING * event = NULL;
+ EVEL_ERR_CODES evel_rc = EVEL_SUCCESS;
+
+ event = evel_new_signaling("vendor_x_id",
+ "correlator", "1.0.3.1", "1234", "192.168.1.3","3456");
+ if (event != NULL)
+ {
+ evel_signaling_vnfmodule_name_set(event, "vendor_x_module");
+ evel_signaling_vnfname_set(event, "vendor_x_vnf");
+ evel_signaling_type_set(event, "Service Event");
+ evel_signaling_correlator_set(event, "vendor_x_correlator");
+ evel_signaling_addl_info_add(event, "prodid", "vendor_x_product_id");
+ evel_signaling_addl_info_add(event, "subsys", "vendor_x_subsystem_id");
+ evel_signaling_addl_info_add(event, "friendly_name", "vendor_x_friend");
+
+ evel_signaling_addl_info_add(event, "callee", "PCMA");
+ evel_signaling_addl_info_add(event, "caller", "G729A");
+
+ evel_signaling_addl_info_add(event, "Name1", "Value1");
+ evel_signaling_addl_info_add(event, "Name2", "Value2");
+
+ evel_rc = evel_post_event((EVENT_HEADER *) event);
+ if (evel_rc != EVEL_SUCCESS)
+ {
+ EVEL_ERROR("Post failed %d (%s)", evel_rc, evel_error_string());
+ }
+ }
+ else
+ {
+ EVEL_ERROR("New Service failed");
+ }
+ printf(" Processed Service Events\n");
+}
diff --git a/VES5.0/evel/evel-library/code/evel_training/_gitignore b/VES5.0/evel/evel-library/code/evel_training/_gitignore
new file mode 100644
index 00000000..ee7aeafd
--- /dev/null
+++ b/VES5.0/evel/evel-library/code/evel_training/_gitignore
@@ -0,0 +1 @@
+*/hello_evel_world
diff --git a/VES5.0/evel/evel-library/code/evel_unit/evel_unit.c b/VES5.0/evel/evel-library/code/evel_unit/evel_unit.c
new file mode 100644
index 00000000..ba4739b0
--- /dev/null
+++ b/VES5.0/evel/evel-library/code/evel_unit/evel_unit.c
@@ -0,0 +1,3498 @@
+/**************************************************************************//**
+ * @file
+ * Unit tests for JSON encoding and throttling.
+ *
+ * This software is intended to show the essential elements of the library's
+ * use.
+ *
+ * License
+ * -------
+ *
+ * Copyright(c) <2016>, AT&T Intellectual Property. All other rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement: This product includes software
+ * developed by the AT&T.
+ * 4. Neither the name of AT&T nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <sys/time.h>
+
+#include "evel.h"
+#include "evel_internal.h"
+#include "evel_throttle.h"
+#include "metadata.h"
+
+typedef enum {
+ SERVICE_NONE,
+ SERVICE_CODEC,
+ SERVICE_TRANSCODING,
+ SERVICE_RTCP,
+ SERVICE_EOC_VQM,
+ SERVICE_MARKER
+} SERVICE_TEST;
+
+/*****************************************************************************/
+/* Local prototypes. */
+/*****************************************************************************/
+static void test_encode_heartbeat();
+static void test_encode_header_overrides();
+static void test_encode_fault();
+static void test_encode_fault_with_escaping();
+static void test_encode_measurement();
+static void test_encode_mobile_mand();
+static void test_encode_mobile_opts();
+static void test_encode_other();
+static void test_encode_report();
+static void test_encode_service();
+static void test_encode_service_subset(const SERVICE_TEST service_test);
+static void test_encode_signaling();
+static void test_encode_state_change();
+static void test_encode_syslog();
+static void test_json_response_junk();
+static void test_json_provide_throttle_state();
+static void test_json_measurement_interval();
+static void test_json_throttle_spec_field();
+static void test_json_throttle_spec_nv_pair();
+static void test_json_throttle_spec_two_domains();
+static void test_json_throttle_spec_bad_command_type();
+static void test_encode_fault_throttled();
+static void test_encode_measurement_throttled();
+static void test_encode_mobile_throttled();
+static void test_encode_other_throttled();
+static void test_encode_report_throttled();
+static void test_encode_service_throttled();
+static void test_encode_signaling_throttled();
+static void test_encode_state_change_throttled();
+static void test_encode_syslog_throttled();
+static void compare_strings(char * expected,
+ char * actual,
+ int max_size,
+ char * description);
+
+/**************************************************************************//**
+ * Main function.
+ *
+ * Runs all unit test cases, and fails hard on the first failure.
+ *
+ * @param[in] argc Argument count.
+ * @param[in] argv Argument vector - for usage see usage_text.
+ *****************************************************************************/
+int main(int argc, char ** argv)
+{
+ assert(argc >= 0);
+ assert(argv != NULL);
+
+ /***************************************************************************/
+ /* Fix our timezone to UTC. */
+ /***************************************************************************/
+ putenv("TZ=UTC");
+
+ /***************************************************************************/
+ /* Initialize metadata. */
+ /***************************************************************************/
+ openstack_metadata_initialize();
+
+ /***************************************************************************/
+ /* Minimal initialisation to exercise the encoders. */
+ /***************************************************************************/
+ functional_role = "UNIT TEST";
+ log_initialize(EVEL_LOG_DEBUG, "EVEL");
+
+ /***************************************************************************/
+ /* Test each encoder. */
+ /***************************************************************************/
+ test_encode_heartbeat();
+ test_encode_header_overrides();
+ test_encode_fault();
+ test_encode_measurement();
+ test_encode_mobile_mand();
+ test_encode_mobile_opts();
+ test_encode_other();
+ test_encode_report();
+ test_encode_service();
+ test_encode_signaling();
+ test_encode_state_change();
+ test_encode_syslog();
+
+ /***************************************************************************/
+ /* Test JSON Throttle. */
+ /***************************************************************************/
+ test_json_response_junk();
+ test_json_provide_throttle_state();
+ test_json_measurement_interval();
+ test_json_throttle_spec_field();
+ test_json_throttle_spec_nv_pair();
+ test_json_throttle_spec_two_domains();
+ test_json_throttle_spec_bad_command_type();
+
+ /***************************************************************************/
+ /* Test each encoder with throttling applied. */
+ /***************************************************************************/
+ test_encode_fault_throttled();
+ test_encode_measurement_throttled();
+ test_encode_mobile_throttled();
+ test_encode_other_throttled();
+ test_encode_report_throttled();
+ test_encode_service_throttled();
+ test_encode_signaling_throttled();
+ test_encode_state_change_throttled();
+ test_encode_syslog_throttled();
+
+ /***************************************************************************/
+ /* Test character escaping. */
+ /***************************************************************************/
+ test_encode_fault_with_escaping();
+
+ printf ("\nAll Tests Passed\n");
+
+ return 0;
+}
+
+/*****************************************************************************/
+/* We link with this gettimeofday so that we get a fixed result */
+/*****************************************************************************/
+int gettimeofday(struct timeval *tv,
+ struct timezone *tz __attribute__((unused)))
+{
+ tv->tv_sec = 1;
+ tv->tv_usec = 2;
+ return 0;
+}
+
+void test_encode_heartbeat()
+{
+ char * expected =
+ "{\"event\": {"
+ "\"commonEventHeader\": {"
+ "\"domain\": \"heartbeat\", "
+ "\"eventId\": \"121\", "
+ "\"functionalRole\": \"UNIT TEST\", "
+ "\"lastEpochMicrosec\": 1000002, "
+ "\"priority\": \"Normal\", "
+ "\"reportingEntityName\": \"Dummy VM name - No Metadata available\", "
+ "\"sequence\": 121, "
+ "\"sourceName\": \"Dummy VM name - No Metadata available\", "
+ "\"startEpochMicrosec\": 1000002, "
+ "\"version\": 1.2, "
+ "\"eventType\": \"Autonomous heartbeat\", "
+ "\"reportingEntityId\": \"Dummy VM UUID - No Metadata available\", "
+ "\"sourceId\": \"Dummy VM UUID - No Metadata available\""
+ "}}}";
+
+ size_t json_size = 0;
+ char json_body[EVEL_MAX_JSON_BODY];
+
+ /***************************************************************************/
+ /* Test the VM name/uuid once. */
+ /***************************************************************************/
+ evel_set_next_event_sequence(121);
+
+ EVENT_HEADER * heartbeat = evel_new_heartbeat();
+ assert(heartbeat != NULL);
+
+ json_size = evel_json_encode_event(
+ json_body, EVEL_MAX_JSON_BODY, (EVENT_HEADER *) heartbeat);
+ compare_strings(expected, json_body, EVEL_MAX_JSON_BODY, "Heartbeat");
+ assert((json_size == strlen(json_body)) && "Bad size returned");
+
+ evel_free_event(heartbeat);
+}
+
+void test_encode_header_overrides()
+{
+ char * expected =
+ "{\"event\": {"
+ "\"commonEventHeader\": {"
+ "\"domain\": \"heartbeat\", "
+ "\"eventId\": \"121\", "
+ "\"functionalRole\": \"UNIT TEST\", "
+ "\"lastEpochMicrosec\": 1000, "
+ "\"priority\": \"Normal\", "
+ "\"reportingEntityName\": \"entity_name_override\", "
+ "\"sequence\": 121, "
+ "\"sourceName\": \"Dummy VM name - No Metadata available\", "
+ "\"startEpochMicrosec\": 1001, "
+ "\"version\": 1.2, "
+ "\"eventType\": \"Autonomous heartbeat\", "
+ "\"reportingEntityId\": \"entity_id_override\", "
+ "\"sourceId\": \"Dummy VM UUID - No Metadata available\""
+ "}}}";
+
+ size_t json_size = 0;
+ char json_body[EVEL_MAX_JSON_BODY];
+
+ /***************************************************************************/
+ /* Test the VM name/uuid once. */
+ /***************************************************************************/
+ evel_set_next_event_sequence(121);
+
+ EVENT_HEADER * heartbeat = evel_new_heartbeat();
+ assert(heartbeat != NULL);
+
+ evel_start_epoch_set(heartbeat, 1001);
+ evel_last_epoch_set(heartbeat, 1000);
+ evel_reporting_entity_name_set(heartbeat, "entity_name_override");
+ evel_reporting_entity_id_set(heartbeat, "entity_id_override");
+
+ json_size = evel_json_encode_event(
+ json_body, EVEL_MAX_JSON_BODY, (EVENT_HEADER *) heartbeat);
+ compare_strings(expected, json_body, EVEL_MAX_JSON_BODY, "Heartbeat");
+ assert((json_size == strlen(json_body)) && "Bad size returned");
+
+ evel_free_event(heartbeat);
+}
+
+void test_encode_fault()
+{
+ char * expected =
+ "{\"event\": {"
+ "\"commonEventHeader\": {"
+ "\"domain\": \"fault\", "
+ "\"eventId\": \"122\", "
+ "\"functionalRole\": \"UNIT TEST\", "
+ "\"lastEpochMicrosec\": 1000002, "
+ "\"priority\": \"Normal\", "
+ "\"reportingEntityName\": \"Dummy VM name - No Metadata available\", "
+ "\"sequence\": 122, "
+ "\"sourceName\": \"Dummy VM name - No Metadata available\", "
+ "\"startEpochMicrosec\": 1000002, "
+ "\"version\": 1.2, "
+ "\"eventType\": \"Bad things happen...\", "
+ "\"reportingEntityId\": \"Dummy VM UUID - No Metadata available\", "
+ "\"sourceId\": \"Dummy VM UUID - No Metadata available\""
+ "}, "
+ "\"faultFields\": {"
+ "\"alarmCondition\": \"My alarm condition\", "
+ "\"eventSeverity\": \"MAJOR\", "
+ "\"eventSourceType\": \"other\", "
+ "\"specificProblem\": \"It broke very badly\", "
+ "\"eventCategory\": \"link\", "
+ "\"vfStatus\": \"Active\", "
+ "\"faultFieldsVersion\": 1.1, "
+ "\"alarmAdditionalInformation\": ["
+ "{\"name\": \"name1\", "
+ "\"value\": \"value1\"}, "
+ "{\"name\": \"name2\", "
+ "\"value\": \"value2\"}], "
+ "\"alarmInterfaceA\": \"My Interface Card\""
+ "}}}";
+
+ size_t json_size = 0;
+ char json_body[EVEL_MAX_JSON_BODY];
+ evel_set_next_event_sequence(122);
+ EVENT_FAULT * fault = evel_new_fault("My alarm condition",
+ "It broke very badly",
+ EVEL_PRIORITY_NORMAL,
+ EVEL_SEVERITY_MAJOR,
+ EVEL_SOURCE_HOST,
+ EVEL_VF_STATUS_PREP_TERMINATE);
+ assert(fault != NULL);
+ evel_fault_type_set(fault, "Bad things happen...");
+ evel_fault_interface_set(fault, "My Interface Card");
+ evel_fault_addl_info_add(fault, "name1", "value1");
+ evel_fault_addl_info_add(fault, "name2", "value2");
+
+ json_size = evel_json_encode_event(
+ json_body, EVEL_MAX_JSON_BODY, (EVENT_HEADER *) fault);
+ compare_strings(expected, json_body, EVEL_MAX_JSON_BODY, "Fault");
+ assert((json_size == strlen(json_body)) && "Bad size returned");
+
+ evel_free_event(fault);
+}
+
+void test_encode_measurement()
+{
+ char * expected =
+ "{\"event\": "
+ "{\"commonEventHeader\": {"
+ "\"domain\": \"measurementsForVfScaling\", "
+ "\"eventId\": \"123\", "
+ "\"functionalRole\": \"UNIT TEST\", "
+ "\"lastEpochMicrosec\": 3000, "
+ "\"priority\": \"Normal\", "
+ "\"reportingEntityName\": \"entity_name\", "
+ "\"sequence\": 123, "
+ "\"sourceName\": \"Dummy VM name - No Metadata available\", "
+ "\"startEpochMicrosec\": 2000, "
+ "\"version\": 1.2, "
+ "\"eventType\": \"Perf management...\", "
+ "\"reportingEntityId\": \"entity_id\", "
+ "\"sourceId\": \"Dummy VM UUID - No Metadata available\""
+ "}, "
+ "\"measurementsForVfScalingFields\": "
+ "{"
+ "\"measurementInterval\": 5.500000, "
+ "\"concurrentSessions\": 1, "
+ "\"configuredEntities\": 2, "
+ "\"cpuUsageArray\": ["
+ "{\"cpuIdentifier\": \"cpu1\", "
+ "\"percentUsage\": 11.110000}, "
+ "{\"cpuIdentifier\": \"cpu2\", "
+ "\"percentUsage\": 22.220000}], "
+ "\"filesystemUsageArray\": ["
+ "{\"blockConfigured\": 100.110000, "
+ "\"blockIops\": 33, "
+ "\"blockUsed\": 100.220000, "
+ "\"ephemeralConfigured\": 100.110000, "
+ "\"ephemeralIops\": 44, "
+ "\"ephemeralUsed\": 200.220000, "
+ "\"filesystemName\": \"00-11-22\"}, "
+ "{\"blockConfigured\": 300.110000, "
+ "\"blockIops\": 55, "
+ "\"blockUsed\": 300.220000, "
+ "\"ephemeralConfigured\": 300.110000, "
+ "\"ephemeralIops\": 66, "
+ "\"ephemeralUsed\": 400.220000, "
+ "\"filesystemName\": \"33-44-55\"}], "
+ "\"latencyDistribution\": ["
+ "{\"countsInTheBucket\": 20}, "
+ "{\"lowEndOfLatencyBucket\": 10.000000, "
+ "\"highEndOfLatencyBucket\": 20.000000, "
+ "\"countsInTheBucket\": 30}], "
+ "\"meanRequestLatency\": 4.400000, "
+ "\"memoryConfigured\": 6.600000, "
+ "\"memoryUsed\": 3.300000, "
+ "\"requestRate\": 7, "
+ "\"vNicUsageArray\": ["
+ "{"
+ "\"bytesIn\": 3, "
+ "\"bytesOut\": 4, "
+ "\"packetsIn\": 100, "
+ "\"packetsOut\": 200, "
+ "\"vNicIdentifier\": \"eth0\""
+ "}, "
+ "{"
+ "\"bytesIn\": 13, "
+ "\"bytesOut\": 14, "
+ "\"packetsIn\": 110, "
+ "\"packetsOut\": 240, "
+ "\"vNicIdentifier\": \"eth1\", "
+ "\"broadcastPacketsIn\": 11, "
+ "\"broadcastPacketsOut\": 12, "
+ "\"multicastPacketsIn\": 15, "
+ "\"multicastPacketsOut\": 16, "
+ "\"unicastPacketsIn\": 17, "
+ "\"unicastPacketsOut\": 18"
+ "}"
+ "], "
+ "\"aggregateCpuUsage\": 8.800000, "
+ "\"numberOfMediaPortsInUse\": 1234, "
+ "\"vnfcScalingMetric\": 1234.567800, "
+ "\"errors\": {"
+ "\"receiveDiscards\": 1, "
+ "\"receiveErrors\": 0, "
+ "\"transmitDiscards\": 2, "
+ "\"transmitErrors\": 1}, "
+ "\"featureUsageArray\": ["
+ "{\"featureIdentifier\": \"FeatureA\", "
+ "\"featureUtilization\": 123}, "
+ "{\"featureIdentifier\": \"FeatureB\", "
+ "\"featureUtilization\": 567}], "
+ "\"codecUsageArray\": ["
+ "{\"codecIdentifier\": \"G711a\", "
+ "\"numberInUse\": 91}, "
+ "{\"codecIdentifier\": \"G729ab\", "
+ "\"numberInUse\": 92}], "
+ "\"additionalMeasurements\": ["
+ "{\"name\": \"Group1\", "
+ "\"measurements\": ["
+ "{\"name\": \"Name1\", "
+ "\"value\": \"Value1\"}]}, "
+ "{\"name\": \"Group2\", "
+ "\"measurements\": ["
+ "{\"name\": \"Name1\", "
+ "\"value\": \"Value1\"}, "
+ "{\"name\": \"Name2\", "
+ "\"value\": \"Value2\"}]}], "
+ "\"measurementsForVfScalingVersion\": 1.1}}}";
+
+ size_t json_size = 0;
+ char json_body[EVEL_MAX_JSON_BODY];
+ EVENT_MEASUREMENT * measurement = NULL;
+ MEASUREMENT_LATENCY_BUCKET * bucket = NULL;
+ MEASUREMENT_VNIC_PERFORMANCE * vnic_use = NULL;
+ MEASUREMENT_CPU_USE *cpu_use;
+
+ /***************************************************************************/
+ /* Measurement. */
+ /***************************************************************************/
+ evel_set_next_event_sequence(123);
+ measurement = evel_new_measurement(5.5);
+ assert(measurement != NULL);
+ evel_measurement_type_set(measurement, "Perf management...");
+ evel_measurement_conc_sess_set(measurement, 1);
+ evel_measurement_cfg_ents_set(measurement, 2);
+ evel_measurement_mean_req_lat_set(measurement, 4.4);
+ evel_measurement_request_rate_set(measurement, 7);
+
+ cpu_use = evel_measurement_new_cpu_use_add(measurement, "cpu1", 11.11);
+ evel_measurement_cpu_use_idle_set(cpu_use,22.22);
+ evel_measurement_cpu_use_interrupt_set(cpu_use,33.33);
+ evel_measurement_cpu_use_nice_set(cpu_use,44.44);
+ evel_measurement_cpu_use_softirq_set(cpu_use,55.55);
+ evel_measurement_cpu_use_steal_set(cpu_use,66.66);
+ evel_measurement_cpu_use_system_set(cpu_use,77.77);
+ evel_measurement_cpu_use_usageuser_set(cpu_use,88.88);
+ evel_measurement_cpu_use_wait_set(cpu_use,99.99);
+
+ cpu_use = evel_measurement_new_cpu_use_add(measurement, "cpu2", 22.22);
+ evel_measurement_cpu_use_idle_set(cpu_use,12.22);
+ evel_measurement_cpu_use_interrupt_set(cpu_use,33.33);
+ evel_measurement_cpu_use_nice_set(cpu_use,44.44);
+ evel_measurement_cpu_use_softirq_set(cpu_use,55.55);
+ evel_measurement_cpu_use_steal_set(cpu_use,66.66);
+ evel_measurement_cpu_use_system_set(cpu_use,77.77);
+ evel_measurement_cpu_use_usageuser_set(cpu_use,88.88);
+ evel_measurement_cpu_use_wait_set(cpu_use,19.99);
+
+
+ evel_measurement_fsys_use_add(measurement,"00-11-22",100.11, 100.22, 33,
+ 200.11, 200.22, 44);
+ evel_measurement_fsys_use_add(measurement,"33-44-55",300.11, 300.22, 55,
+ 400.11, 400.22, 66);
+ evel_start_epoch_set(&measurement->header, 2000);
+ evel_last_epoch_set(&measurement->header, 3000);
+ evel_reporting_entity_name_set(&measurement->header, "entity_name");
+ evel_reporting_entity_id_set(&measurement->header, "entity_id");
+
+ /***************************************************************************/
+ /* Latency Bucket with no optional parameters. */
+ /***************************************************************************/
+ bucket = evel_new_meas_latency_bucket(20);
+ evel_meas_latency_bucket_add(measurement, bucket);
+
+ /***************************************************************************/
+ /* Latency Bucket with all optional parameters. */
+ /***************************************************************************/
+ bucket = evel_new_meas_latency_bucket(30);
+ evel_meas_latency_bucket_low_end_set(bucket, 10.0);
+ evel_meas_latency_bucket_high_end_set(bucket, 20.0);
+ evel_meas_latency_bucket_add(measurement, bucket);
+
+ /***************************************************************************/
+ /* vNIC Use with no optional parameters. */
+ /***************************************************************************/
+ vnic_use = evel_new_measurement_vnic_use("eth0", 100, 200, 3, 4);
+ evel_meas_vnic_use_add(measurement, vnic_use);
+
+ /***************************************************************************/
+ /* vNIC Use with all optional parameters. */
+ /***************************************************************************/
+ vnic_use = evel_new_measurement_vnic_use("eth1", 110, 240, 13, 14);
+ evel_vnic_use_bcast_pkt_in_set(vnic_use, 11);
+ evel_vnic_use_bcast_pkt_out_set(vnic_use, 12);
+ evel_vnic_use_mcast_pkt_in_set(vnic_use, 15);
+ evel_vnic_use_mcast_pkt_out_set(vnic_use, 16);
+ evel_vnic_use_ucast_pkt_in_set(vnic_use, 17);
+ evel_vnic_use_ucast_pkt_out_set(vnic_use, 18);
+ evel_meas_vnic_use_add(measurement, vnic_use);
+
+ evel_measurement_errors_set(measurement, 1, 0, 2, 1);
+
+ evel_measurement_feature_use_add(measurement, "FeatureA", 123);
+ evel_measurement_feature_use_add(measurement, "FeatureB", 567);
+
+ evel_measurement_codec_use_add(measurement, "G711a", 91);
+ evel_measurement_codec_use_add(measurement, "G729ab", 92);
+
+ evel_measurement_media_port_use_set(measurement, 1234);
+
+ evel_measurement_vnfc_scaling_metric_set(measurement, 1234.5678);
+
+ evel_measurement_custom_measurement_add(measurement,
+ "Group1", "Name1", "Value1");
+ evel_measurement_custom_measurement_add(measurement,
+ "Group2", "Name1", "Value1");
+ evel_measurement_custom_measurement_add(measurement,
+ "Group2", "Name2", "Value2");
+
+ json_size = evel_json_encode_event(
+ json_body, EVEL_MAX_JSON_BODY, (EVENT_HEADER *) measurement);
+ compare_strings(expected, json_body, EVEL_MAX_JSON_BODY, "Measurement");
+ assert((json_size == strlen(json_body)) && "Bad size returned");
+
+ evel_free_event(measurement);
+}
+
+void test_encode_mobile_mand()
+{
+ char * expected =
+ "{\"event\": "
+ "{\"commonEventHeader\": {"
+ "\"domain\": \"mobileFlow\", "
+ "\"eventId\": \"1241\", "
+ "\"functionalRole\": \"UNIT TEST\", "
+ "\"lastEpochMicrosec\": 1000002, "
+ "\"priority\": \"Normal\", "
+ "\"reportingEntityName\": \"Dummy VM name - No Metadata available\", "
+ "\"sequence\": 1241, "
+ "\"sourceName\": \"Dummy VM name - No Metadata available\", "
+ "\"startEpochMicrosec\": 1000002, "
+ "\"version\": 1.2, "
+ "\"reportingEntityId\": \"Dummy VM UUID - No Metadata available\", "
+ "\"sourceId\": \"Dummy VM UUID - No Metadata available\""
+ "}, "
+ "\"mobileFlowFields\": {"
+ "\"flowDirection\": \"Outbound\", "
+ "\"gtpPerFlowMetrics\": {"
+ "\"avgBitErrorRate\": 12.300000, "
+ "\"avgPacketDelayVariation\": 3.120000, "
+ "\"avgPacketLatency\": 100, "
+ "\"avgReceiveThroughput\": 2100, "
+ "\"avgTransmitThroughput\": 500, "
+ "\"flowActivationEpoch\": 1470409421, "
+ "\"flowActivationMicrosec\": 987, "
+ "\"flowDeactivationEpoch\": 1470409431, "
+ "\"flowDeactivationMicrosec\": 11, "
+ "\"flowDeactivationTime\": \"Fri, 05 Aug 2016 15:03:51 +0000\", "
+ "\"flowStatus\": \"Working\", "
+ "\"maxPacketDelayVariation\": 87, "
+ "\"numActivationFailures\": 3, "
+ "\"numBitErrors\": 17, "
+ "\"numBytesReceived\": 123654, "
+ "\"numBytesTransmitted\": 4561, "
+ "\"numDroppedPackets\": 0, "
+ "\"numL7BytesReceived\": 12, "
+ "\"numL7BytesTransmitted\": 10, "
+ "\"numLostPackets\": 1, "
+ "\"numOutOfOrderPackets\": 3, "
+ "\"numPacketErrors\": 7, "
+ "\"numPacketsReceivedExclRetrans\": 899, "
+ "\"numPacketsReceivedInclRetrans\": 901, "
+ "\"numPacketsTransmittedInclRetrans\": 302, "
+ "\"numRetries\": 6, "
+ "\"numTimeouts\": 2, "
+ "\"numTunneledL7BytesReceived\": 0, "
+ "\"roundTripTime\": 110, "
+ "\"timeToFirstByte\": 225"
+ "}, "
+ "\"ipProtocolType\": \"TCP\", "
+ "\"ipVersion\": \"IPv4\", "
+ "\"otherEndpointIpAddress\": \"2.3.4.1\", "
+ "\"otherEndpointPort\": 2341, "
+ "\"reportingEndpointIpAddr\": \"4.2.3.1\", "
+ "\"reportingEndpointPort\": 4321"
+ "}}}";
+
+ size_t json_size = 0;
+ char json_body[EVEL_MAX_JSON_BODY];
+ MOBILE_GTP_PER_FLOW_METRICS * metrics = NULL;
+ EVENT_MOBILE_FLOW * mobile_flow = NULL;
+
+ /***************************************************************************/
+ /* Mobile. */
+ /***************************************************************************/
+ evel_set_next_event_sequence(1241);
+
+ metrics = evel_new_mobile_gtp_flow_metrics(12.3,
+ 3.12,
+ 100,
+ 2100,
+ 500,
+ 1470409421,
+ 987,
+ 1470409431,
+ 11,
+ (time_t)1470409431,
+ "Working",
+ 87,
+ 3,
+ 17,
+ 123654,
+ 4561,
+ 0,
+ 12,
+ 10,
+ 1,
+ 3,
+ 7,
+ 899,
+ 901,
+ 302,
+ 6,
+ 2,
+ 0,
+ 110,
+ 225);
+ assert(metrics != NULL);
+ mobile_flow = evel_new_mobile_flow("Outbound",
+ metrics,
+ "TCP",
+ "IPv4",
+ "2.3.4.1",
+ 2341,
+ "4.2.3.1",
+ 4321);
+ assert(mobile_flow != NULL);
+
+ json_size = evel_json_encode_event(
+ json_body, EVEL_MAX_JSON_BODY, (EVENT_HEADER *) mobile_flow);
+ compare_strings(expected, json_body, EVEL_MAX_JSON_BODY, "Mobile");
+ assert((json_size == strlen(json_body)) && "Bad size returned");
+
+ evel_free_event(mobile_flow);
+}
+
+void test_encode_mobile_opts()
+{
+ char * expected =
+ "{\"event\": "
+ "{\"commonEventHeader\": {"
+ "\"domain\": \"mobileFlow\", "
+ "\"eventId\": \"1242\", "
+ "\"functionalRole\": \"UNIT TEST\", "
+ "\"lastEpochMicrosec\": 1000002, "
+ "\"priority\": \"Normal\", "
+ "\"reportingEntityName\": \"Dummy VM name - No Metadata available\", "
+ "\"sequence\": 1242, "
+ "\"sourceName\": \"Dummy VM name - No Metadata available\", "
+ "\"startEpochMicrosec\": 1000002, "
+ "\"version\": 1.2, "
+ "\"eventType\": \"Mobile flow...\", "
+ "\"reportingEntityId\": \"Dummy VM UUID - No Metadata available\", "
+ "\"sourceId\": \"Dummy VM UUID - No Metadata available\""
+ "}, "
+ "\"mobileFlowFields\": {"
+ "\"flowDirection\": \"Inbound\", "
+ "\"gtpPerFlowMetrics\": {"
+ "\"avgBitErrorRate\": 132.000100, "
+ "\"avgPacketDelayVariation\": 31.200000, "
+ "\"avgPacketLatency\": 101, "
+ "\"avgReceiveThroughput\": 2101, "
+ "\"avgTransmitThroughput\": 501, "
+ "\"flowActivationEpoch\": 1470409422, "
+ "\"flowActivationMicrosec\": 988, "
+ "\"flowDeactivationEpoch\": 1470409432, "
+ "\"flowDeactivationMicrosec\": 12, "
+ "\"flowDeactivationTime\": \"Fri, 05 Aug 2016 15:03:52 +0000\", "
+ "\"flowStatus\": \"Inactive\", "
+ "\"maxPacketDelayVariation\": 88, "
+ "\"numActivationFailures\": 4, "
+ "\"numBitErrors\": 18, "
+ "\"numBytesReceived\": 123655, "
+ "\"numBytesTransmitted\": 4562, "
+ "\"numDroppedPackets\": 1, "
+ "\"numL7BytesReceived\": 13, "
+ "\"numL7BytesTransmitted\": 11, "
+ "\"numLostPackets\": 2, "
+ "\"numOutOfOrderPackets\": 4, "
+ "\"numPacketErrors\": 8, "
+ "\"numPacketsReceivedExclRetrans\": 900, "
+ "\"numPacketsReceivedInclRetrans\": 902, "
+ "\"numPacketsTransmittedInclRetrans\": 303, "
+ "\"numRetries\": 7, "
+ "\"numTimeouts\": 3, "
+ "\"numTunneledL7BytesReceived\": 1, "
+ "\"roundTripTime\": 111, "
+ "\"timeToFirstByte\": 226, "
+ "\"ipTosCountList\": ["
+ "[\"1\", 13], "
+ "[\"4\", 99], "
+ "[\"17\", 1]], "
+ "\"ipTosList\": [\"1\", \"4\", \"17\"], "
+ "\"tcpFlagList\": [\"CWR\", \"URG\"], "
+ "\"tcpFlagCountList\": [[\"CWR\", 10], [\"URG\", 121]], "
+ "\"mobileQciCosList\": [\"conversational\", \"65\"], "
+ "\"mobileQciCosCountList\": [[\"conversational\", 11], [\"65\", 122]], "
+ "\"durConnectionFailedStatus\": 12, "
+ "\"durTunnelFailedStatus\": 13, "
+ "\"flowActivatedBy\": \"Remote\", "
+ "\"flowActivationTime\": \"Fri, 05 Aug 2016 15:03:43 +0000\", "
+ "\"flowDeactivatedBy\": \"Remote\", "
+ "\"gtpConnectionStatus\": \"Connected\", "
+ "\"gtpTunnelStatus\": \"Not tunneling\", "
+ "\"largePacketRtt\": 80, "
+ "\"largePacketThreshold\": 600.000000, "
+ "\"maxReceiveBitRate\": 1357924680, "
+ "\"maxTransmitBitRate\": 235711, "
+ "\"numGtpEchoFailures\": 1, "
+ "\"numGtpTunnelErrors\": 4, "
+ "\"numHttpErrors\": 2"
+ "}, "
+ "\"ipProtocolType\": \"UDP\", "
+ "\"ipVersion\": \"IPv6\", "
+ "\"otherEndpointIpAddress\": \"2.3.4.2\", "
+ "\"otherEndpointPort\": 2342, "
+ "\"reportingEndpointIpAddr\": \"4.2.3.2\", "
+ "\"reportingEndpointPort\": 4322, "
+ "\"applicationType\": \"Demo application\", "
+ "\"appProtocolType\": \"GSM\", "
+ "\"appProtocolVersion\": \"1\", "
+ "\"cid\": \"65535\", "
+ "\"connectionType\": \"S1-U\", "
+ "\"ecgi\": \"e65535\", "
+ "\"gtpProtocolType\": \"GTP-U\", "
+ "\"gtpVersion\": \"1\", "
+ "\"httpHeader\": \"http://www.something.com\", "
+ "\"imei\": \"209917614823\", "
+ "\"imsi\": \"355251/05/850925/8\", "
+ "\"lac\": \"1\", "
+ "\"mcc\": \"410\", "
+ "\"mnc\": \"04\", "
+ "\"msisdn\": \"6017123456789\", "
+ "\"otherFunctionalRole\": \"MME\", "
+ "\"rac\": \"514\", "
+ "\"radioAccessTechnology\": \"LTE\", "
+ "\"sac\": \"1\", "
+ "\"samplingAlgorithm\": 1, "
+ "\"tac\": \"2099\", "
+ "\"tunnelId\": \"Tunnel 1\", "
+ "\"vlanId\": \"15\""
+ "}}}";
+
+ size_t json_size = 0;
+ char json_body[EVEL_MAX_JSON_BODY];
+ MOBILE_GTP_PER_FLOW_METRICS * metrics = NULL;
+ EVENT_MOBILE_FLOW * mobile_flow = NULL;
+
+ /***************************************************************************/
+ /* Mobile. */
+ /***************************************************************************/
+ evel_set_next_event_sequence(1242);
+
+ metrics = evel_new_mobile_gtp_flow_metrics(132.0001,
+ 31.2,
+ 101,
+ 2101,
+ 501,
+ 1470409422,
+ 988,
+ 1470409432,
+ 12,
+ (time_t)1470409432,
+ "Inactive",
+ 88,
+ 4,
+ 18,
+ 123655,
+ 4562,
+ 1,
+ 13,
+ 11,
+ 2,
+ 4,
+ 8,
+ 900,
+ 902,
+ 303,
+ 7,
+ 3,
+ 1,
+ 111,
+ 226);
+ assert(metrics != NULL);
+
+ evel_mobile_gtp_metrics_dur_con_fail_set(metrics, 12);
+ evel_mobile_gtp_metrics_dur_tun_fail_set(metrics, 13);
+ evel_mobile_gtp_metrics_act_by_set(metrics, "Remote");
+ evel_mobile_gtp_metrics_act_time_set(metrics, (time_t)1470409423);
+ evel_mobile_gtp_metrics_deact_by_set(metrics, "Remote");
+ evel_mobile_gtp_metrics_con_status_set(metrics, "Connected");
+ evel_mobile_gtp_metrics_tun_status_set(metrics, "Not tunneling");
+ evel_mobile_gtp_metrics_iptos_set(metrics, 1, 13);
+ evel_mobile_gtp_metrics_iptos_set(metrics, 17, 1);
+ evel_mobile_gtp_metrics_iptos_set(metrics, 4, 99);
+ evel_mobile_gtp_metrics_large_pkt_rtt_set(metrics, 80);
+ evel_mobile_gtp_metrics_large_pkt_thresh_set(metrics, 600.0);
+ evel_mobile_gtp_metrics_max_rcv_bit_rate_set(metrics, 1357924680);
+ evel_mobile_gtp_metrics_max_trx_bit_rate_set(metrics, 235711);
+ evel_mobile_gtp_metrics_num_echo_fail_set(metrics, 1);
+ evel_mobile_gtp_metrics_num_tun_fail_set(metrics, 4);
+ evel_mobile_gtp_metrics_num_http_errors_set(metrics, 2);
+ evel_mobile_gtp_metrics_tcp_flag_count_add(metrics, EVEL_TCP_CWR, 10);
+ evel_mobile_gtp_metrics_tcp_flag_count_add(metrics, EVEL_TCP_URG, 121);
+ evel_mobile_gtp_metrics_qci_cos_count_add(
+ metrics, EVEL_QCI_COS_UMTS_CONVERSATIONAL, 11);
+ evel_mobile_gtp_metrics_qci_cos_count_add(
+ metrics, EVEL_QCI_COS_LTE_65, 122);
+
+ mobile_flow = evel_new_mobile_flow("Inbound",
+ metrics,
+ "UDP",
+ "IPv6",
+ "2.3.4.2",
+ 2342,
+ "4.2.3.2",
+ 4322);
+ assert(mobile_flow != NULL);
+
+ evel_mobile_flow_type_set(mobile_flow, "Mobile flow...");
+ evel_mobile_flow_app_type_set(mobile_flow, "Demo application");
+ evel_mobile_flow_app_prot_type_set(mobile_flow, "GSM");
+ evel_mobile_flow_app_prot_ver_set(mobile_flow, "1");
+ evel_mobile_flow_cid_set(mobile_flow, "65535");
+ evel_mobile_flow_con_type_set(mobile_flow, "S1-U");
+ evel_mobile_flow_ecgi_set(mobile_flow, "e65535");
+ evel_mobile_flow_gtp_prot_type_set(mobile_flow, "GTP-U");
+ evel_mobile_flow_gtp_prot_ver_set(mobile_flow, "1");
+ evel_mobile_flow_http_header_set(mobile_flow,
+ "http://www.something.com");
+ evel_mobile_flow_imei_set(mobile_flow, "209917614823");
+ evel_mobile_flow_imsi_set(mobile_flow, "355251/05/850925/8");
+ evel_mobile_flow_lac_set(mobile_flow, "1");
+ evel_mobile_flow_mcc_set(mobile_flow, "410");
+ evel_mobile_flow_mnc_set(mobile_flow, "04");
+ evel_mobile_flow_msisdn_set(mobile_flow, "6017123456789");
+ evel_mobile_flow_other_func_role_set(mobile_flow, "MME");
+ evel_mobile_flow_rac_set(mobile_flow, "514");
+ evel_mobile_flow_radio_acc_tech_set(mobile_flow, "LTE");
+ evel_mobile_flow_sac_set(mobile_flow, "1");
+ evel_mobile_flow_samp_alg_set(mobile_flow, 1);
+ evel_mobile_flow_tac_set(mobile_flow, "2099");
+ evel_mobile_flow_tunnel_id_set(mobile_flow, "Tunnel 1");
+ evel_mobile_flow_vlan_id_set(mobile_flow, "15");
+
+ json_size = evel_json_encode_event(
+ json_body, EVEL_MAX_JSON_BODY, (EVENT_HEADER *) mobile_flow);
+ compare_strings(expected, json_body, EVEL_MAX_JSON_BODY, "Mobile");
+ assert((json_size == strlen(json_body)) && "Bad size returned");
+
+ evel_free_event(mobile_flow);
+}
+
+void test_encode_report()
+{
+ char * expected =
+ "{\"event\": "
+ "{\"commonEventHeader\": {"
+ "\"domain\": \"measurementsForVfReporting\", "
+ "\"eventId\": \"125\", "
+ "\"functionalRole\": \"UNIT TEST\", "
+ "\"lastEpochMicrosec\": 1000002, "
+ "\"priority\": \"Normal\", "
+ "\"reportingEntityName\": \"Dummy VM name - No Metadata available\", "
+ "\"sequence\": 125, "
+ "\"sourceName\": \"Dummy VM name - No Metadata available\", "
+ "\"startEpochMicrosec\": 1000002, "
+ "\"version\": 1.2, "
+ "\"eventType\": \"Perf reporting...\", "
+ "\"reportingEntityId\": \"Dummy VM UUID - No Metadata available\", "
+ "\"sourceId\": \"Dummy VM UUID - No Metadata available\""
+ "}, "
+ "\"measurementsForVfReportingFields\": "
+ "{\"measurementInterval\": 1.100000, "
+ "\"featureUsageArray\": ["
+ "{\"featureIdentifier\": \"FeatureA\", "
+ "\"featureUtilization\": 123}, "
+ "{\"featureIdentifier\": \"FeatureB\", "
+ "\"featureUtilization\": 567}], "
+ "\"additionalMeasurements\": ["
+ "{\"name\": \"Group1\", "
+ "\"measurements\": ["
+ "{\"name\": \"Name1\", "
+ "\"value\": \"Value1\"}]}, "
+ "{\"name\": \"Group2\", "
+ "\"measurements\": ["
+ "{\"name\": \"Name1\", "
+ "\"value\": \"Value1\"}, "
+ "{\"name\": \"Name2\", "
+ "\"value\": \"Value2\"}]}], "
+ "\"measurementFieldsVersion\": 1.1}}}";
+
+ size_t json_size = 0;
+ char json_body[EVEL_MAX_JSON_BODY];
+ EVENT_REPORT * report = NULL;
+
+ /***************************************************************************/
+ /* Report. */
+ /***************************************************************************/
+ evel_set_next_event_sequence(125);
+ report = evel_new_report(1.1);
+ assert(report != NULL);
+ evel_report_type_set(report, "Perf reporting...");
+ evel_report_feature_use_add(report, "FeatureA", 123);
+ evel_report_feature_use_add(report, "FeatureB", 567);
+ evel_report_custom_measurement_add(report, "Group1", "Name1", "Value1");
+ evel_report_custom_measurement_add(report, "Group2", "Name1", "Value1");
+ evel_report_custom_measurement_add(report, "Group2", "Name2", "Value2");
+
+ json_size = evel_json_encode_event(
+ json_body, EVEL_MAX_JSON_BODY, (EVENT_HEADER *) report);
+ compare_strings(expected, json_body, EVEL_MAX_JSON_BODY, "Report");
+ assert((json_size == strlen(json_body)) && "Bad size returned");
+
+ evel_free_event(report);
+}
+
+void test_encode_service()
+{
+ test_encode_service_subset(SERVICE_NONE);
+ test_encode_service_subset(SERVICE_CODEC);
+ test_encode_service_subset(SERVICE_TRANSCODING);
+ test_encode_service_subset(SERVICE_RTCP);
+ test_encode_service_subset(SERVICE_EOC_VQM);
+ test_encode_service_subset(SERVICE_MARKER);
+}
+
+void test_encode_service_subset(const SERVICE_TEST service_test)
+{
+ char * expected_start =
+ "{\"event\": "
+ "{\"commonEventHeader\": {"
+ "\"domain\": \"serviceEvents\", "
+ "\"eventId\": \"2000\", "
+ "\"functionalRole\": \"UNIT TEST\", "
+ "\"lastEpochMicrosec\": 1000002, "
+ "\"priority\": \"Normal\", "
+ "\"reportingEntityName\": \"Dummy VM name - No Metadata available\", "
+ "\"sequence\": 2000, "
+ "\"sourceName\": \"Dummy VM name - No Metadata available\", "
+ "\"startEpochMicrosec\": 1000002, "
+ "\"version\": 1.2, "
+ "\"eventType\": \"Service Event\", "
+ "\"reportingEntityId\": \"Dummy VM UUID - No Metadata available\", "
+ "\"sourceId\": \"Dummy VM UUID - No Metadata available\""
+ "}, "
+ "\"serviceEventsFields\": {"
+ "\"eventInstanceIdentifier\": "
+ "{"
+ "\"vendorId\": \"vendor_x_id\", "
+ "\"eventId\": \"vendor_x_event_id\", "
+ "\"productId\": \"vendor_x_product_id\", "
+ "\"subsystemId\": \"vendor_x_subsystem_id\", "
+ "\"eventFriendlyName\": \"vendor_x_frieldly_name\""
+ "}, "
+ "\"serviceEventsFieldsVersion\": 1.1, "
+ "\"correlator\": \"vendor_x_correlator\", "
+ "\"additionalFields\": ["
+ "{\"name\": \"Name1\", \"value\": \"Value1\"}, "
+ "{\"name\": \"Name2\", \"value\": \"Value2\"}, "
+ "{\"name\": \"Name3\", \"value\": \"Value3\"}, "
+ "{\"name\": \"Name4\", \"value\": \"Value4\"}]";
+ char * expected_codec =
+ ", "
+ "\"codecSelected\": {"
+ "\"codec\": \"PCMA\""
+ "}";
+ char * expected_transcoding =
+ ", "
+ "\"codecSelectedTranscoding\": {"
+ "\"calleeSideCodec\": \"PCMA\", "
+ "\"callerSideCodec\": \"G729A\""
+ "}";
+ char * expected_rtcp =
+ ", "
+ "\"midCallRtcp\": {"
+ "\"rtcpData\": \"some_rtcp_data\""
+ "}";
+ char * expected_eoc_vqm =
+ ", "
+ "\"endOfCallVqmSummaries\": {"
+ "\"adjacencyName\": \"vendor_x_adjacency\", "
+ "\"endpointDescription\": \"Caller\", "
+ "\"endpointJitter\": 66, "
+ "\"endpointRtpOctetsDiscarded\": 100, "
+ "\"endpointRtpOctetsReceived\": 200, "
+ "\"endpointRtpOctetsSent\": 300, "
+ "\"endpointRtpPacketsDiscarded\": 400, "
+ "\"endpointRtpPacketsReceived\": 500, "
+ "\"endpointRtpPacketsSent\": 600, "
+ "\"localJitter\": 99, "
+ "\"localRtpOctetsDiscarded\": 150, "
+ "\"localRtpOctetsReceived\": 250, "
+ "\"localRtpOctetsSent\": 350, "
+ "\"localRtpPacketsDiscarded\": 450, "
+ "\"localRtpPacketsReceived\": 550, "
+ "\"localRtpPacketsSent\": 650, "
+ "\"mosCqe\": 12.255000, "
+ "\"packetsLost\": 157, "
+ "\"packetLossPercent\": 0.232000, "
+ "\"rFactor\": 11, "
+ "\"roundTripDelay\": 15"
+ "}";
+ char * expected_marker =
+ ", "
+ "\"marker\": {"
+ "\"phoneNumber\": \"0888888888\""
+ "}";
+ char * expected_end =
+ "}}}";
+
+ char * expected_middle = NULL;
+ switch (service_test)
+ {
+ case SERVICE_NONE:
+ expected_middle = "";
+ break;
+ case SERVICE_CODEC:
+ expected_middle = expected_codec;
+ break;
+ case SERVICE_TRANSCODING:
+ expected_middle = expected_transcoding;
+ break;
+ case SERVICE_RTCP:
+ expected_middle = expected_rtcp;
+ break;
+ case SERVICE_EOC_VQM:
+ expected_middle = expected_eoc_vqm;
+ break;
+ case SERVICE_MARKER:
+ expected_middle = expected_marker;
+ break;
+ }
+ assert(expected_middle != NULL);
+
+ int offset = 0;
+ char expected[EVEL_MAX_JSON_BODY];
+ offset = snprintf(expected + offset,
+ EVEL_MAX_JSON_BODY - offset,
+ "%s%s%s",
+ expected_start,
+ expected_middle,
+ expected_end);
+
+ size_t json_size = 0;
+ char json_body[EVEL_MAX_JSON_BODY];
+ EVENT_SGNALING * event = NULL;
+ evel_set_next_event_sequence(2000);
+ event = evel_new_signaling("vendor_x_id",
+ "correlator", "1.0.3.1", "1234", "192.168.1.3","3456");
+ assert(event != NULL);
+ evel_signaling_type_set(event, "Signaling");
+ evel_signaling_correlator_set(event, "vendor_x_correlator");
+ evel_signaling_vnfmodule_name_set(event, "vendor_x_module");
+ evel_signaling_vnfname_set(event, "vendor_x_vnf");
+
+ switch (service_test)
+ {
+ case SERVICE_NONE:
+ break;
+ case SERVICE_CODEC:
+ evel_signaling_addl_info_add(event, "codec", "PCMA");
+ break;
+ case SERVICE_TRANSCODING:
+ evel_signaling_addl_info_add(event, "calleecodec", "PCMA");
+ evel_signaling_addl_info_add(event, "callercodec", "G729A");
+ break;
+ case SERVICE_RTCP:
+ evel_signaling_addl_info_add(event, "rtcpdata", "abcdefgh");
+ break;
+ case SERVICE_EOC_VQM:
+ evel_signaling_addl_info_add(event, "adjacency", "vendor_x");
+ /*evel_service_adjacency_name_set(event, "vendor_x_adjacency");
+ evel_service_endpoint_desc_set(event, EVEL_SERVICE_ENDPOINT_CALLER);
+ evel_service_endpoint_jitter_set(event, 66);
+ evel_service_endpoint_rtp_oct_disc_set(event, 100);
+ evel_service_endpoint_rtp_oct_recv_set(event, 200);
+ evel_service_endpoint_rtp_oct_sent_set(event, 300);
+ evel_service_endpoint_rtp_pkt_disc_set(event, 400);
+ evel_service_endpoint_rtp_pkt_recv_set(event, 500);
+ evel_service_endpoint_rtp_pkt_sent_set(event, 600);
+ evel_service_local_jitter_set(event, 99);
+ evel_service_local_rtp_oct_disc_set(event, 150);
+ evel_service_local_rtp_oct_recv_set(event, 250);
+ evel_service_local_rtp_oct_sent_set(event, 350);
+ evel_service_local_rtp_pkt_disc_set(event, 450);
+ evel_service_local_rtp_pkt_recv_set(event, 550);
+ evel_service_local_rtp_pkt_sent_set(event, 650);
+ evel_service_mos_cqe_set(event, 12.255);
+ evel_service_packets_lost_set(event, 157);
+ evel_service_packet_loss_percent_set(event, 0.232);
+ evel_service_r_factor_set(event, 11);
+ evel_service_round_trip_delay_set(event, 15);*/
+ break;
+ case SERVICE_MARKER:
+ evel_signaling_addl_info_add(event, "service_phone", "0888888888");
+ break;
+ }
+
+ json_size = evel_json_encode_event(
+ json_body, EVEL_MAX_JSON_BODY, (EVENT_HEADER *) event);
+ compare_strings(expected, json_body, EVEL_MAX_JSON_BODY, "Service");
+ assert((json_size == strlen(json_body)) && "Bad size returned");
+
+ evel_free_event(event);
+}
+
+void test_encode_signaling()
+{
+ char * expected =
+ "{\"event\": "
+ "{\"commonEventHeader\": {"
+ "\"domain\": \"signaling\", "
+ "\"eventId\": \"2001\", "
+ "\"functionalRole\": \"UNIT TEST\", "
+ "\"lastEpochMicrosec\": 1000002, "
+ "\"priority\": \"Normal\", "
+ "\"reportingEntityName\": \"Dummy VM name - No Metadata available\", "
+ "\"sequence\": 2001, "
+ "\"sourceName\": \"Dummy VM name - No Metadata available\", "
+ "\"startEpochMicrosec\": 1000002, "
+ "\"version\": 1.2, "
+ "\"eventType\": \"Signaling\", "
+ "\"reportingEntityId\": \"Dummy VM UUID - No Metadata available\", "
+ "\"sourceId\": \"Dummy VM UUID - No Metadata available\""
+ "}, "
+ "\"signalingFields\": {"
+ "\"eventInstanceIdentifier\": "
+ "{"
+ "\"vendorId\": \"vendor_x_id\", "
+ "\"eventId\": \"vendor_x_event_id\", "
+ "\"productId\": \"vendor_x_product_id\", "
+ "\"subsystemId\": \"vendor_x_subsystem_id\", "
+ "\"eventFriendlyName\": \"vendor_x_frieldly_name\""
+ "}, "
+ "\"signalingFieldsVersion\": 1.1, "
+ "\"correlator\": \"vendor_x_correlator\", "
+ "\"localIpAddress\": \"1.0.3.1\", "
+ "\"localPort\": \"1031\", "
+ "\"remoteIpAddress\": \"5.3.3.0\", "
+ "\"remotePort\": \"5330\", "
+ "\"compressedSip\": \"compressed_sip\", "
+ "\"summarySip\": \"summary_sip\""
+ "}}}";
+
+ size_t json_size = 0;
+ char json_body[EVEL_MAX_JSON_BODY];
+ EVENT_SIGNALING * event = NULL;
+ evel_set_next_event_sequence(2001);
+ event = evel_new_signaling("vendor_x_id",
+ "correlator", "1.0.3.1", "1234", "192.168.1.3","3456");
+ assert(event != NULL);
+ evel_signaling_vnfmodule_name_set(event, "vendor_x_module");
+ evel_signaling_vnfname_set(event, "vendor_x_vnf");
+ evel_signaling_type_set(event, "Signaling");
+ evel_signaling_product_id_set(event, "vendor_x_product_id");
+ evel_signaling_subsystem_id_set(event, "vendor_x_subsystem_id");
+ evel_signaling_friendly_name_set(event, "vendor_x_frieldly_name");
+ evel_signaling_correlator_set(event, "vendor_x_correlator");
+ evel_signaling_local_ip_address_set(event, "1.0.3.1");
+ evel_signaling_local_port_set(event, "1031");
+ evel_signaling_remote_ip_address_set(event, "5.3.3.0");
+ evel_signaling_remote_port_set(event, "5330");
+ evel_signaling_compressed_sip_set(event, "compressed_sip");
+ evel_signaling_summary_sip_set(event, "summary_sip");
+ json_size = evel_json_encode_event(
+ json_body, EVEL_MAX_JSON_BODY, (EVENT_HEADER *) event);
+ compare_strings(expected, json_body, EVEL_MAX_JSON_BODY, "Signaling");
+ assert((json_size == strlen(json_body)) && "Bad size returned");
+
+ evel_free_event(event);
+}
+
+void test_encode_state_change()
+{
+ char * expected =
+ "{\"event\": "
+ "{\"commonEventHeader\": {"
+ "\"domain\": \"stateChange\", "
+ "\"eventId\": \"128\", "
+ "\"functionalRole\": \"UNIT TEST\", "
+ "\"lastEpochMicrosec\": 1000002, "
+ "\"priority\": \"Normal\", "
+ "\"reportingEntityName\": \"Dummy VM name - No Metadata available\", "
+ "\"sequence\": 128, "
+ "\"sourceName\": \"Dummy VM name - No Metadata available\", "
+ "\"startEpochMicrosec\": 1000002, "
+ "\"version\": 1.2, "
+ "\"eventType\": \"SC Type\", "
+ "\"reportingEntityId\": \"Dummy VM UUID - No Metadata available\", "
+ "\"sourceId\": \"Dummy VM UUID - No Metadata available\""
+ "}, "
+ "\"stateChangeFields\": {"
+ "\"newState\": \"inService\", "
+ "\"oldState\": \"outOfService\", "
+ "\"stateInterface\": \"An Interface\", "
+ "\"additionalFields\": ["
+ "{\"name\": \"Name1\", "
+ "\"value\": \"Value1\"}, "
+ "{\"name\": \"Name2\", "
+ "\"value\": \"Value2\"}"
+ "], "
+ "\"stateChangeFieldsVersion\": 1.1"
+ "}}}";
+
+ size_t json_size = 0;
+ char json_body[EVEL_MAX_JSON_BODY];
+ EVENT_STATE_CHANGE * state_change = NULL;
+ evel_set_next_event_sequence(128);
+ state_change = evel_new_state_change(EVEL_ENTITY_STATE_IN_SERVICE,
+ EVEL_ENTITY_STATE_OUT_OF_SERVICE,
+ "An Interface");
+ assert(state_change != NULL);
+ evel_state_change_type_set(state_change, "SC Type");
+ evel_state_change_addl_field_add(state_change, "Name1", "Value1");
+ evel_state_change_addl_field_add(state_change, "Name2", "Value2");
+
+ json_size = evel_json_encode_event(
+ json_body, EVEL_MAX_JSON_BODY, (EVENT_HEADER *) state_change);
+ compare_strings(expected, json_body, EVEL_MAX_JSON_BODY, "StateChange");
+ assert((json_size == strlen(json_body)) && "Bad size returned");
+
+ evel_free_event(state_change);
+}
+
+void test_encode_syslog()
+{
+ char * expected =
+ "{\"event\": "
+ "{\"commonEventHeader\": {"
+ "\"domain\": \"syslog\", "
+ "\"eventId\": \"126\", "
+ "\"functionalRole\": \"UNIT TEST\", "
+ "\"lastEpochMicrosec\": 1000002, "
+ "\"priority\": \"Normal\", "
+ "\"reportingEntityName\": \"Dummy VM name - No Metadata available\", "
+ "\"sequence\": 126, "
+ "\"sourceName\": \"Dummy VM name - No Metadata available\", "
+ "\"startEpochMicrosec\": 1000002, "
+ "\"version\": 1.2, "
+ "\"eventType\": \"SL Type\", "
+ "\"reportingEntityId\": \"Dummy VM UUID - No Metadata available\", "
+ "\"sourceId\": \"Dummy VM UUID - No Metadata available\""
+ "}, "
+ "\"syslogFields\": {"
+ "\"eventSourceType\": \"virtualNetworkFunction\", "
+ "\"syslogMsg\": \"SL Message\", "
+ "\"syslogTag\": \"SL Tag\", "
+ "\"syslogFieldsVersion\": 1.1, "
+ "\"eventSourceHost\": \"SL Host\", "
+ "\"syslogFacility\": 6, "
+ "\"syslogProc\": \"SL Proc\", "
+ "\"syslogProcId\": 2, "
+ "\"syslogSData\": \"SL SDATA\", "
+ "\"syslogVer\": 1"
+ "}}}";
+ size_t json_size = 0;
+ char json_body[EVEL_MAX_JSON_BODY];
+ EVENT_SYSLOG * syslog = NULL;
+ evel_set_next_event_sequence(126);
+ syslog = evel_new_syslog(EVEL_SOURCE_VIRTUAL_NETWORK_FUNCTION,
+ "SL Message",
+ "SL Tag");
+ assert(syslog != NULL);
+ evel_syslog_type_set(syslog, "SL Type");
+ evel_syslog_event_source_host_set(syslog, "SL Host");
+ evel_syslog_facility_set(syslog, EVEL_SYSLOG_FACILITY_LINE_PRINTER);
+ evel_syslog_proc_set(syslog, "SL Proc");
+ evel_syslog_proc_id_set(syslog, 2);
+ evel_syslog_version_set(syslog, 1);
+ evel_syslog_s_data_set(syslog, "SL SDATA");
+
+ json_size = evel_json_encode_event(
+ json_body, EVEL_MAX_JSON_BODY, (EVENT_HEADER *) syslog);
+ compare_strings(expected, json_body, EVEL_MAX_JSON_BODY, "Syslog");
+ assert((json_size == strlen(json_body)) && "Bad size returned");
+
+ evel_free_event(syslog);
+}
+
+void test_encode_other()
+{
+ char * expected =
+ "{\"event\": "
+ "{\"commonEventHeader\": {"
+ "\"domain\": \"other\", "
+ "\"eventId\": \"129\", "
+ "\"functionalRole\": \"UNIT TEST\", "
+ "\"lastEpochMicrosec\": 1000002, "
+ "\"priority\": \"Normal\", "
+ "\"reportingEntityName\": \"Dummy VM name - No Metadata available\", "
+ "\"sequence\": 129, "
+ "\"sourceName\": \"Dummy VM name - No Metadata available\", "
+ "\"startEpochMicrosec\": 1000002, "
+ "\"version\": 1.2, "
+ "\"eventType\": \"Other Type\", "
+ "\"reportingEntityId\": \"Dummy VM UUID - No Metadata available\", "
+ "\"sourceId\": \"Dummy VM UUID - No Metadata available\""
+ "}, "
+ "\"otherFields\": ["
+ "{\"name\": \"Other field 1\", "
+ "\"value\": \"Other value 1\"}, "
+ "{\"name\": \"Other field 2\", "
+ "\"value\": \"Other value 2\"}"
+ "]"
+ "}}";
+
+ size_t json_size = 0;
+ char json_body[EVEL_MAX_JSON_BODY];
+ EVENT_OTHER * other = NULL;
+ evel_set_next_event_sequence(129);
+ other = evel_new_other();
+ assert(other != NULL);
+ evel_other_type_set(other, "Other Type");
+ evel_other_field_add(other,
+ "Other field 1",
+ "Other value 1");
+ evel_other_field_add(other,
+ "Other field 2",
+ "Other value 2");
+
+ json_size = evel_json_encode_event(
+ json_body, EVEL_MAX_JSON_BODY, (EVENT_HEADER *) other);
+ compare_strings(expected, json_body, EVEL_MAX_JSON_BODY, "Other");
+ assert((json_size == strlen(json_body)) && "Bad size returned");
+
+ evel_free_event(other);
+}
+
+void compare_strings(char * expected,
+ char * actual,
+ int max_size,
+ char * description)
+{
+ if (strncmp(expected, actual, max_size) != 0)
+ {
+ int diff = 0;
+ while (diff < max_size)
+ {
+ if (expected[diff] != actual[diff])
+ {
+ break;
+ }
+ diff++;
+ }
+
+ printf("Comparison Failure at Offset %d\n\n", diff);
+ printf("Expected:\n%s\n", expected);
+ printf("Actual:\n%s\n", actual);
+ printf("Description: %s\n", description);
+ assert(0);
+ }
+}
+
+/**************************************************************************//**
+ * Copy a json string to a ::MEMORY_CHUNK for testing.
+ *
+ * @param chunk The memory chunk.
+ * @param string The json string.
+ *****************************************************************************/
+void copy_string_to_chunk(MEMORY_CHUNK * chunk, char * string)
+{
+ int mem_size;
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(chunk != NULL);
+ assert(string != NULL);
+
+ mem_size = strlen(string) + 1;
+ chunk->memory = malloc(mem_size);
+ memcpy(chunk->memory, string, mem_size);
+ chunk->size = mem_size;
+}
+
+/**************************************************************************//**
+ * Copy a json string to a ::MEMORY_CHUNK for testing.
+ *
+ * @param json The JSON string.
+ * @param post Memory chunk to post a response.
+ *****************************************************************************/
+void handle_json_response(char * json, MEMORY_CHUNK * post)
+{
+ MEMORY_CHUNK chunk;
+ post->memory = NULL;
+ post->size = 0;
+ copy_string_to_chunk(&chunk, json);
+ evel_handle_event_response(&chunk, post);
+ free(chunk.memory);
+}
+
+/**************************************************************************//**
+ * Test that a non-"commandList" JSON buffer leaves the throttle state off.
+ *****************************************************************************/
+void test_json_response_junk()
+{
+ MEMORY_CHUNK post;
+ int domain;
+ char * json_junk =
+ "{"
+ "\"junk1\": ["
+ "\"1\", \"2\", \"3\"], "
+ "\"junk2\": ["
+ "\"1\", \"2\", \"3\"]"
+ "}";
+
+ evel_throttle_initialize();
+ handle_json_response(json_junk, &post);
+
+ /***************************************************************************/
+ /* Check that all domains are not throttled. */
+ /***************************************************************************/
+ for (domain = EVEL_DOMAIN_FAULT; domain < EVEL_MAX_DOMAINS; domain++)
+ {
+ assert(evel_get_throttle_spec(domain) == NULL);
+ }
+
+ /***************************************************************************/
+ /* Check that we generated no post. */
+ /***************************************************************************/
+ assert(post.memory == NULL);
+
+ evel_throttle_terminate();
+}
+
+char * json_command_list_provide =
+ "{"
+ "\"commandList\": ["
+ "{"
+ "\"command\": {"
+ "\"commandType\": \"provideThrottlingState\""
+ "}"
+ "}"
+ "]"
+ "}";
+
+char * json_command_list_fault_clear =
+ "{"
+ "\"commandList\": ["
+ "{"
+ "\"command\": {"
+ "\"commandType\": \"throttlingSpecification\", "
+ "\"eventDomainThrottleSpecification\": {"
+ "\"eventDomain\": \"fault\""
+ "}"
+ "}"
+ "}"
+ "]"
+ "}";
+
+char * json_command_list_syslog_clear =
+ "{"
+ "\"commandList\": ["
+ "{"
+ "\"command\": {"
+ "\"commandType\": \"throttlingSpecification\", "
+ "\"eventDomainThrottleSpecification\": {"
+ "\"eventDomain\": \"syslog\""
+ "}"
+ "}"
+ "}"
+ "]"
+ "}";
+
+char * expected_throttle_state_normal =
+ "{"
+ "\"eventThrottlingState\": {"
+ "\"eventThrottlingMode\": \"normal\"}"
+ "}";
+
+/**************************************************************************//**
+ * Test that we can return the default throttling state.
+ *****************************************************************************/
+void test_json_provide_throttle_state()
+{
+ MEMORY_CHUNK post;
+ int domain;
+
+ char * expected_post = expected_throttle_state_normal;
+
+ evel_throttle_initialize();
+ handle_json_response(json_command_list_provide, &post);
+
+ /***************************************************************************/
+ /* Check that all domains are not throttled. */
+ /***************************************************************************/
+ for (domain = EVEL_DOMAIN_FAULT; domain < EVEL_MAX_DOMAINS; domain++)
+ {
+ assert(evel_get_throttle_spec(domain) == NULL);
+ }
+
+ /***************************************************************************/
+ /* Check that we generated a throttling specification post. */
+ /***************************************************************************/
+ assert(post.memory != NULL);
+ compare_strings(expected_post, post.memory, strlen(expected_post),
+ "Throttle State Normal");
+ free(post.memory);
+
+ evel_throttle_terminate();
+}
+
+/**************************************************************************//**
+ * Test the measurement interval handling and API.
+ *****************************************************************************/
+void test_json_measurement_interval()
+{
+ MEMORY_CHUNK post;
+ char * json_command_list_interval_only =
+ "{"
+ "\"commandList\": ["
+ "{"
+ "\"command\": {"
+ "\"measurementInterval\": 60"
+ "}"
+ "}"
+ "]"
+ "}";
+
+ char * json_command_list_interval_first =
+ "{"
+ "\"commandList\": ["
+ "{"
+ "\"command\": {"
+ "\"measurementInterval\": 30, "
+ "\"commandType\": \"measurementIntervalChange\""
+ "}"
+ "}"
+ "]"
+ "}";
+
+ char * json_command_list_command_first =
+ "{"
+ "\"commandList\": ["
+ "{"
+ "\"command\": {"
+ "\"commandType\": \"measurementIntervalChange\", "
+ "\"measurementInterval\": 60"
+ "}"
+ "}"
+ "]"
+ "}";
+
+ evel_throttle_initialize();
+ assert(evel_get_measurement_interval() == EVEL_MEASUREMENT_INTERVAL_UKNOWN);
+
+ /***************************************************************************/
+ /* Check that we're not handling stuff when we shouldn't. */
+ /***************************************************************************/
+ handle_json_response(json_command_list_interval_only, &post);
+ assert(post.memory == NULL);
+ assert(evel_get_measurement_interval() == EVEL_MEASUREMENT_INTERVAL_UKNOWN);
+
+ /***************************************************************************/
+ /* Check that we're OK with the interval coming first. */
+ /***************************************************************************/
+ handle_json_response(json_command_list_interval_first, &post);
+ assert(post.memory == NULL);
+ assert(evel_get_measurement_interval() == 30);
+
+ /***************************************************************************/
+ /* Check that we're OK with the command type coming first. */
+ /***************************************************************************/
+ handle_json_response(json_command_list_command_first, &post);
+ assert(post.memory == NULL);
+ assert(evel_get_measurement_interval() == 60);
+
+ evel_throttle_terminate();
+}
+
+/**************************************************************************//**
+ * Test a single domain, single field suppression.
+ *****************************************************************************/
+void test_json_throttle_spec_field()
+{
+ MEMORY_CHUNK post;
+ int domain;
+
+ char * json_command_list_fault_single =
+ "{"
+ "\"commandList\": ["
+ "{"
+ "\"command\": {"
+ "\"commandType\": \"throttlingSpecification\", "
+ "\"eventDomainThrottleSpecification\": {"
+ "\"eventDomain\": \"fault\", "
+ "\"suppressedFieldNames\": [\"alarmInterfaceA\"]"
+ "}"
+ "}"
+ "}"
+ "]"
+ "}";
+
+ char * json_command_list_fault_double =
+ "{"
+ "\"commandList\": ["
+ "{"
+ "\"command\": {"
+ "\"commandType\": \"throttlingSpecification\", "
+ "\"eventDomainThrottleSpecification\": {"
+ "\"eventDomain\": \"fault\", "
+ "\"suppressedFieldNames\": ["
+ "\"alarmInterfaceA\", \"alarmAdditionalInformation\"]"
+ "}"
+ "}"
+ "}"
+ "]"
+ "}";
+
+ char * expected_post_fault_single =
+ "{"
+ "\"eventThrottlingState\": {"
+ "\"eventThrottlingMode\": \"throttled\", "
+ "\"eventDomainThrottleSpecificationList\": ["
+ "{"
+ "\"eventDomain\": \"fault\", "
+ "\"suppressedFieldNames\": [\"alarmInterfaceA\"]"
+ "}"
+ "]"
+ "}"
+ "}";
+
+ char * expected_post_fault_double =
+ "{"
+ "\"eventThrottlingState\": {"
+ "\"eventThrottlingMode\": \"throttled\", "
+ "\"eventDomainThrottleSpecificationList\": ["
+ "{"
+ "\"eventDomain\": \"fault\", "
+ "\"suppressedFieldNames\": ["
+ "\"alarmInterfaceA\", \"alarmAdditionalInformation\"]"
+ "}"
+ "]"
+ "}"
+ "}";
+
+ /***************************************************************************/
+ /* Initialize and provide a specification with a single fault suppressed. */
+ /***************************************************************************/
+ evel_throttle_initialize();
+ handle_json_response(json_command_list_fault_single, &post);
+
+ /***************************************************************************/
+ /* Check that the FAULT domain is throttled. */
+ /***************************************************************************/
+ assert(evel_get_throttle_spec(EVEL_DOMAIN_FAULT) != NULL);
+ for (domain = EVEL_DOMAIN_MEASUREMENT; domain < EVEL_MAX_DOMAINS; domain++)
+ {
+ if (domain != EVEL_DOMAIN_FAULT)
+ {
+ assert(evel_get_throttle_spec(domain) == NULL);
+ }
+ }
+ assert(post.memory == NULL);
+
+ /***************************************************************************/
+ /* Request and verify the throttling state. */
+ /***************************************************************************/
+ handle_json_response(json_command_list_provide, &post);
+ assert(post.memory != NULL);
+ compare_strings(expected_post_fault_single,
+ post.memory,
+ strlen(expected_post_fault_single),
+ "Fault - Single Field");
+ free(post.memory);
+ post.memory = NULL;
+
+ /***************************************************************************/
+ /* Update a specification with two faults suppressed. */
+ /***************************************************************************/
+ handle_json_response(json_command_list_fault_double, &post);
+
+ /***************************************************************************/
+ /* Check that the FAULT domain is throttled. */
+ /***************************************************************************/
+ assert(evel_get_throttle_spec(EVEL_DOMAIN_FAULT) != NULL);
+ for (domain = EVEL_DOMAIN_MEASUREMENT; domain < EVEL_MAX_DOMAINS; domain++)
+ {
+ if (domain != EVEL_DOMAIN_FAULT)
+ {
+ assert(evel_get_throttle_spec(domain) == NULL);
+ }
+ }
+ assert(post.memory == NULL);
+
+ /***************************************************************************/
+ /* Request and verify the throttling state. */
+ /***************************************************************************/
+ handle_json_response(json_command_list_provide, &post);
+ assert(post.memory != NULL);
+ compare_strings(expected_post_fault_double,
+ post.memory,
+ strlen(expected_post_fault_double),
+ "Fault - Double Field");
+ free(post.memory);
+ post.memory = NULL;
+
+ /***************************************************************************/
+ /* Now clear the FAULT domain. */
+ /***************************************************************************/
+ handle_json_response(json_command_list_fault_clear, &post);
+ for (domain = EVEL_DOMAIN_FAULT; domain < EVEL_MAX_DOMAINS; domain++)
+ {
+ assert(evel_get_throttle_spec(domain) == NULL);
+ }
+
+ evel_throttle_terminate();
+}
+
+/**************************************************************************//**
+ * Test a single domain, nv_pair suppression.
+ *****************************************************************************/
+void test_json_throttle_spec_nv_pair()
+{
+ MEMORY_CHUNK post;
+ int domain;
+
+ char * json_command_list_fault_pair_single =
+ "{"
+ "\"commandList\": ["
+ "{"
+ "\"command\": {"
+ "\"commandType\": \"throttlingSpecification\", "
+ "\"eventDomainThrottleSpecification\": {"
+ "\"eventDomain\": \"fault\", "
+ "\"suppressedNvPairsList\": ["
+ "{"
+ "\"nvPairFieldName\": \"alarmAdditionalInformation\", "
+ "\"suppressedNvPairNames\": [\"name1\"]"
+ "}"
+ "]"
+ "}"
+ "}"
+ "}"
+ "]"
+ "}";
+
+ char * json_command_list_fault_pair_double =
+ "{"
+ "\"commandList\": ["
+ "{"
+ "\"command\": {"
+ "\"commandType\": \"throttlingSpecification\", "
+ "\"eventDomainThrottleSpecification\": {"
+ "\"eventDomain\": \"fault\", "
+ "\"suppressedNvPairsList\": ["
+ "{"
+ "\"nvPairFieldName\": \"alarmAdditionalInformation\", "
+ "\"suppressedNvPairNames\": [\"name1\", \"name2\"]"
+ "}"
+ "]"
+ "}"
+ "}"
+ "}"
+ "]"
+ "}";
+
+ char * expected_post_fault_pair_single =
+ "{"
+ "\"eventThrottlingState\": {"
+ "\"eventThrottlingMode\": \"throttled\", "
+ "\"eventDomainThrottleSpecificationList\": ["
+ "{"
+ "\"eventDomain\": \"fault\", "
+ "\"suppressedNvPairsList\": ["
+ "{"
+ "\"nvPairFieldName\": \"alarmAdditionalInformation\", "
+ "\"suppressedNvPairNames\": [\"name1\"]"
+ "}"
+ "]"
+ "}"
+ "]"
+ "}"
+ "}";
+
+ char * expected_post_fault_pair_double =
+ "{"
+ "\"eventThrottlingState\": {"
+ "\"eventThrottlingMode\": \"throttled\", "
+ "\"eventDomainThrottleSpecificationList\": ["
+ "{"
+ "\"eventDomain\": \"fault\", "
+ "\"suppressedNvPairsList\": ["
+ "{"
+ "\"nvPairFieldName\": \"alarmAdditionalInformation\", "
+ "\"suppressedNvPairNames\": [\"name1\", \"name2\"]"
+ "}"
+ "]"
+ "}"
+ "]"
+ "}"
+ "}";
+
+ /***************************************************************************/
+ /* Initialize and provide a specification with a single nvpair with a */
+ /* single sub-field suppressed. */
+ /***************************************************************************/
+ evel_throttle_initialize();
+ handle_json_response(json_command_list_fault_pair_single, &post);
+
+ /***************************************************************************/
+ /* Check that the FAULT domain is throttled. */
+ /***************************************************************************/
+ assert(evel_get_throttle_spec(EVEL_DOMAIN_FAULT) != NULL);
+ for (domain = EVEL_DOMAIN_MEASUREMENT; domain < EVEL_MAX_DOMAINS; domain++)
+ {
+ if (domain != EVEL_DOMAIN_FAULT)
+ {
+ assert(evel_get_throttle_spec(domain) == NULL);
+ }
+ }
+ assert(post.memory == NULL);
+
+ /***************************************************************************/
+ /* Request and verify the throttling state. */
+ /***************************************************************************/
+ handle_json_response(json_command_list_provide, &post);
+ assert(post.memory != NULL);
+ compare_strings(expected_post_fault_pair_single,
+ post.memory,
+ strlen(expected_post_fault_pair_single),
+ "Fault - Single Pair, Single Field");
+ free(post.memory);
+ post.memory = NULL;
+
+ /***************************************************************************/
+ /* Update a specification with a single nvpair with two sub-fields */
+ /* suppressed. */
+ /***************************************************************************/
+ handle_json_response(json_command_list_fault_pair_double, &post);
+
+ /***************************************************************************/
+ /* Check that the FAULT domain is throttled. */
+ /***************************************************************************/
+ assert(evel_get_throttle_spec(EVEL_DOMAIN_FAULT) != NULL);
+ for (domain = EVEL_DOMAIN_MEASUREMENT; domain < EVEL_MAX_DOMAINS; domain++)
+ {
+ if (domain != EVEL_DOMAIN_FAULT)
+ {
+ assert(evel_get_throttle_spec(domain) == NULL);
+ }
+ }
+ assert(post.memory == NULL);
+
+ /***************************************************************************/
+ /* Request and verify the throttling state. */
+ /***************************************************************************/
+ handle_json_response(json_command_list_provide, &post);
+ assert(post.memory != NULL);
+ compare_strings(expected_post_fault_pair_double,
+ post.memory,
+ strlen(expected_post_fault_pair_double),
+ "Fault - Double Field");
+ free(post.memory);
+ post.memory = NULL;
+
+ /***************************************************************************/
+ /* Now clear the FAULT domain. */
+ /***************************************************************************/
+ handle_json_response(json_command_list_fault_clear, &post);
+ for (domain = EVEL_DOMAIN_FAULT; domain < EVEL_MAX_DOMAINS; domain++)
+ {
+ assert(evel_get_throttle_spec(domain) == NULL);
+ }
+
+ evel_throttle_terminate();
+}
+
+/**************************************************************************//**
+ * Test two domains, nv_pair suppression.
+ *****************************************************************************/
+void test_json_throttle_spec_two_domains()
+{
+ MEMORY_CHUNK post;
+ int domain;
+
+ char * json_command_list_two_domains =
+ "{"
+ "\"commandList\": ["
+ "{"
+ "\"command\": {"
+ "\"commandType\": \"throttlingSpecification\", "
+ "\"eventDomainThrottleSpecification\": {"
+ "\"eventDomain\": \"fault\", "
+ "\"suppressedFieldNames\": [\"alarmInterfaceA\"], "
+ "\"suppressedNvPairsList\": ["
+ "{"
+ "\"nvPairFieldName\": \"alarmAdditionalInformation\", "
+ "\"suppressedNvPairNames\": [\"name1\"]"
+ "}]}}}, "
+ "{"
+ "\"command\": {"
+ "\"commandType\": \"throttlingSpecification\", "
+ "\"eventDomainThrottleSpecification\": {"
+ "\"eventDomain\": \"syslog\", "
+ "\"suppressedFieldNames\": [\"syslogProcId\"], "
+ "\"suppressedNvPairsList\": ["
+ "{"
+ "\"nvPairFieldName\": \"additionalFields\", "
+ "\"suppressedNvPairNames\": [\"name1\"]"
+ "}]}}}"
+ "]"
+ "}";
+
+ char * expected_post_two_domains =
+ "{"
+ "\"eventThrottlingState\": {"
+ "\"eventThrottlingMode\": \"throttled\", "
+ "\"eventDomainThrottleSpecificationList\": ["
+ "{"
+ "\"eventDomain\": \"fault\", "
+ "\"suppressedFieldNames\": [\"alarmInterfaceA\"], "
+ "\"suppressedNvPairsList\": ["
+ "{"
+ "\"nvPairFieldName\": \"alarmAdditionalInformation\", "
+ "\"suppressedNvPairNames\": [\"name1\"]"
+ "}]}, "
+ "{"
+ "\"eventDomain\": \"syslog\", "
+ "\"suppressedFieldNames\": [\"syslogProcId\"], "
+ "\"suppressedNvPairsList\": ["
+ "{"
+ "\"nvPairFieldName\": \"additionalFields\", "
+ "\"suppressedNvPairNames\": [\"name1\"]"
+ "}]}"
+ "]"
+ "}"
+ "}";
+
+ /***************************************************************************/
+ /* Initialize and provide a specification with a single nvpair with a */
+ /* single sub-field suppressed. */
+ /***************************************************************************/
+ evel_throttle_initialize();
+ handle_json_response(json_command_list_two_domains, &post);
+
+ /***************************************************************************/
+ /* Check that the FAULT and SYSLOG domains are throttled. */
+ /***************************************************************************/
+ assert(evel_get_throttle_spec(EVEL_DOMAIN_FAULT) != NULL);
+ assert(evel_get_throttle_spec(EVEL_DOMAIN_SYSLOG) != NULL);
+ for (domain = EVEL_DOMAIN_MEASUREMENT; domain < EVEL_MAX_DOMAINS; domain++)
+ {
+ if ((domain != EVEL_DOMAIN_FAULT) && (domain != EVEL_DOMAIN_SYSLOG))
+ {
+ assert(evel_get_throttle_spec(domain) == NULL);
+ }
+ }
+ assert(post.memory == NULL);
+
+ /***************************************************************************/
+ /* Request and verify the throttling state. */
+ /***************************************************************************/
+ handle_json_response(json_command_list_provide, &post);
+ assert(post.memory != NULL);
+ compare_strings(expected_post_two_domains,
+ post.memory,
+ strlen(expected_post_two_domains),
+ "Fault - Two Domains");
+ free(post.memory);
+ post.memory = NULL;
+
+ /***************************************************************************/
+ /* Now clear the FAULT and SYSLOG domains. */
+ /***************************************************************************/
+ handle_json_response(json_command_list_fault_clear, &post);
+ assert(evel_get_throttle_spec(EVEL_DOMAIN_FAULT) == NULL);
+ assert(evel_get_throttle_spec(EVEL_DOMAIN_SYSLOG) != NULL);
+ handle_json_response(json_command_list_syslog_clear, &post);
+ for (domain = EVEL_DOMAIN_FAULT; domain < EVEL_MAX_DOMAINS; domain++)
+ {
+ assert(evel_get_throttle_spec(domain) == NULL);
+ }
+
+ evel_throttle_terminate();
+}
+
+/**************************************************************************//**
+ * Test bad command type.
+ *****************************************************************************/
+void test_json_throttle_spec_bad_command_type()
+{
+ MEMORY_CHUNK post;
+ int domain;
+
+ /***************************************************************************/
+ /* Search for "dodgy" in the JSON, and you will see the dodgy bits we're */
+ /* handling in these tests. */
+ /***************************************************************************/
+ #define NUM_BAD_COMMANDS 8
+ char * json_command_list_dodgy_command =
+ "{"
+ "\"commandList\": ["
+ "{"
+ "\"command\": {"
+ "\"commandType\": \"dodgyCommand\", "
+ "\"eventDomainThrottleSpecification\": {"
+ "\"eventDomain\": \"fault\", "
+ "\"suppressedFieldNames\": [\"alarmInterfaceA\"], "
+ "\"suppressedNvPairsList\": ["
+ "{"
+ "\"nvPairFieldName\": \"alarmAdditionalInformation\", "
+ "\"suppressedNvPairNames\": [\"name1\"]"
+ "}]}}}"
+ "]"
+ "}";
+
+ char * json_command_list_dodgy_spec =
+ "{"
+ "\"commandList\": ["
+ "{"
+ "\"command\": {"
+ "\"commandType\": \"throttlingSpecification\", "
+ "\"dodgyEventDomainThrottleSpecification\": {"
+ "\"eventDomain\": \"fault\", "
+ "\"suppressedFieldNames\": [\"alarmInterfaceA\"], "
+ "\"suppressedNvPairsList\": ["
+ "{"
+ "\"nvPairFieldName\": \"alarmAdditionalInformation\", "
+ "\"suppressedNvPairNames\": [\"name1\"]"
+ "}]}}}"
+ "]"
+ "}";
+
+ char * json_command_list_dodgy_event_domain_key =
+ "{"
+ "\"commandList\": ["
+ "{"
+ "\"command\": {"
+ "\"commandType\": \"throttlingSpecification\", "
+ "\"eventDomainThrottleSpecification\": {"
+ "\"dodgyEventDomainKey\": \"fault\", "
+ "\"suppressedFieldNames\": [\"alarmInterfaceA\"], "
+ "\"suppressedNvPairsList\": ["
+ "{"
+ "\"nvPairFieldName\": \"alarmAdditionalInformation\", "
+ "\"suppressedNvPairNames\": [\"name1\"]"
+ "}]}}}"
+ "]"
+ "}";
+
+ char * json_command_list_dodgy_event_domain =
+ "{"
+ "\"commandList\": ["
+ "{"
+ "\"command\": {"
+ "\"commandType\": \"throttlingSpecification\", "
+ "\"eventDomainThrottleSpecification\": {"
+ "\"eventDomain\": \"dodgyEventDomain\", "
+ "\"suppressedFieldNames\": [\"alarmInterfaceA\"], "
+ "\"suppressedNvPairsList\": ["
+ "{"
+ "\"nvPairFieldName\": \"alarmAdditionalInformation\", "
+ "\"suppressedNvPairNames\": [\"name1\"]"
+ "}]}}}"
+ "]"
+ "}";
+
+ char * json_command_list_dodgy_field_names_key =
+ "{"
+ "\"commandList\": ["
+ "{"
+ "\"command\": {"
+ "\"commandType\": \"throttlingSpecification\", "
+ "\"eventDomainThrottleSpecification\": {"
+ "\"eventDomain\": \"fault\", "
+ "\"suppressedNvPairsList\": ["
+ "{"
+ "\"nvPairFieldName\": \"alarmAdditionalInformation\", "
+ "\"suppressedNvPairNames\": [\"name1\"]"
+ "}]}}}"
+ "]"
+ "}";
+
+ char * json_command_list_dodgy_pair_names_list_key =
+ "{"
+ "\"commandList\": ["
+ "{"
+ "\"command\": {"
+ "\"commandType\": \"throttlingSpecification\", "
+ "\"eventDomainThrottleSpecification\": {"
+ "\"eventDomain\": \"fault\", "
+ "\"suppressedFieldNames\": [\"alarmInterfaceA\"], "
+ "\"dodgySuppressedNvPairsListKey\": ["
+ "{"
+ "\"nvPairFieldName\": \"alarmAdditionalInformation\", "
+ "\"suppressedNvPairNames\": [\"name1\"]"
+ "}]}}}"
+ "]"
+ "}";
+
+ char * json_command_list_dodgy_pair_field_name_key =
+ "{"
+ "\"commandList\": ["
+ "{"
+ "\"command\": {"
+ "\"commandType\": \"throttlingSpecification\", "
+ "\"eventDomainThrottleSpecification\": {"
+ "\"eventDomain\": \"fault\", "
+ "\"suppressedFieldNames\": [\"alarmInterfaceA\"], "
+ "\"suppressedNvPairsList\": ["
+ "{"
+ "\"dodgyNvPairFieldNameKey\": \"alarmAdditionalInformation\", "
+ "\"suppressedNvPairNames\": [\"name1\"]"
+ "}]}}}"
+ "]"
+ "}";
+
+ char * json_command_list_dodgy_pair_names_key =
+ "{"
+ "\"commandList\": ["
+ "{"
+ "\"command\": {"
+ "\"commandType\": \"throttlingSpecification\", "
+ "\"eventDomainThrottleSpecification\": {"
+ "\"eventDomain\": \"fault\", "
+ "\"suppressedFieldNames\": [\"alarmInterfaceA\"], "
+ "\"suppressedNvPairsList\": ["
+ "{"
+ "\"nvPairFieldName\": \"alarmAdditionalInformation\", "
+ "\"dodgySuppressedNvPairNamesKey\": [\"name1\"]"
+ "}]}}}"
+ "]"
+ "}";
+
+ char * json_command_list_dodgy_depth =
+ "{"
+ "\"commandList\": ["
+ "{"
+ "\"command\": {"
+ "\"commandType\": \"throttlingSpecification\", "
+ "\"eventDomainThrottleSpecification\": {"
+ "\"eventDomain\": \"fault\", "
+ "\"suppressedFieldNames\": [\"alarmInterfaceA\"], "
+ "\"suppressedNvPairsList\": ["
+ "{"
+ "\"nvPairFieldName\": \"alarmAdditionalInformation\", "
+ "\"dodgySuppressedNvPairNamesKey\": "
+ "[\"name1\", [[[[[[[[]]]]]]]]]"
+ "}]}}}"
+ "]"
+ "}";
+
+ char * expected_throttle_state_dodgy_field_names_key =
+ "{"
+ "\"eventThrottlingState\": {"
+ "\"eventThrottlingMode\": \"throttled\", "
+ "\"eventDomainThrottleSpecificationList\": ["
+ "{"
+ "\"eventDomain\": \"fault\", "
+ "\"suppressedNvPairsList\": ["
+ "{"
+ "\"nvPairFieldName\": \"alarmAdditionalInformation\", "
+ "\"suppressedNvPairNames\": [\"name1\"]"
+ "}]}"
+ "]"
+ "}"
+ "}";
+
+ char * expected_throttle_state_dodgy_pair_names_list_key =
+ "{"
+ "\"eventThrottlingState\": {"
+ "\"eventThrottlingMode\": \"throttled\", "
+ "\"eventDomainThrottleSpecificationList\": ["
+ "{"
+ "\"eventDomain\": \"fault\", "
+ "\"suppressedFieldNames\": [\"alarmInterfaceA\"]"
+ "}"
+ "]"
+ "}"
+ "}";
+
+ char * expected_throttle_state_dodgy_pair_field_name_key =
+ "{"
+ "\"eventThrottlingState\": {"
+ "\"eventThrottlingMode\": \"throttled\", "
+ "\"eventDomainThrottleSpecificationList\": ["
+ "{"
+ "\"eventDomain\": \"fault\", "
+ "\"suppressedFieldNames\": [\"alarmInterfaceA\"]"
+ "}"
+ "]"
+ "}"
+ "}";
+
+ char * expected_throttle_state_dodgy_pair_names_key =
+ "{"
+ "\"eventThrottlingState\": {"
+ "\"eventThrottlingMode\": \"throttled\", "
+ "\"eventDomainThrottleSpecificationList\": ["
+ "{"
+ "\"eventDomain\": \"fault\", "
+ "\"suppressedFieldNames\": [\"alarmInterfaceA\"]"
+ "}"
+ "]"
+ "}"
+ "}";
+
+ char * json_command_lists[] = {
+ json_command_list_dodgy_command,
+ json_command_list_dodgy_spec,
+ json_command_list_dodgy_event_domain_key,
+ json_command_list_dodgy_event_domain,
+ json_command_list_dodgy_depth,
+ json_command_list_dodgy_field_names_key,
+ json_command_list_dodgy_pair_names_list_key,
+ json_command_list_dodgy_pair_field_name_key,
+ json_command_list_dodgy_pair_names_key
+ };
+
+ char * expected_posts[] = {
+ expected_throttle_state_normal,
+ expected_throttle_state_normal,
+ expected_throttle_state_normal,
+ expected_throttle_state_normal,
+ expected_throttle_state_normal,
+ expected_throttle_state_dodgy_field_names_key,
+ expected_throttle_state_dodgy_pair_names_list_key,
+ expected_throttle_state_dodgy_pair_field_name_key,
+ expected_throttle_state_dodgy_pair_names_key
+ };
+
+ const int num_commands =
+ sizeof(json_command_lists) / sizeof(json_command_lists[0]);
+ const int num_posts =
+ sizeof(expected_posts) / sizeof(expected_posts[0]);
+ assert(num_commands == num_posts);
+
+ /***************************************************************************/
+ /* Initialize and provide a specification with a single nvpair with a */
+ /* single sub-field suppressed. */
+ /***************************************************************************/
+ evel_throttle_initialize();
+
+ int ii;
+ for (ii = 0; ii < num_commands; ii++)
+ {
+ EVEL_DEBUG("Testing commandList[%d] = %s\n", ii, json_command_lists[ii]);
+ handle_json_response(json_command_lists[ii], &post);
+
+ /*************************************************************************/
+ /* Check that throttling is in a normal state - because we ignored the */
+ /* command / ..... */
+ /*************************************************************************/
+ for (domain = EVEL_DOMAIN_MEASUREMENT; domain < EVEL_MAX_DOMAINS; domain++)
+ {
+ assert(evel_get_throttle_spec(domain) == NULL);
+ }
+ if (expected_posts[ii] == expected_throttle_state_normal)
+ {
+ assert(evel_get_throttle_spec(EVEL_DOMAIN_FAULT) == NULL);
+ }
+ else
+ {
+ assert(evel_get_throttle_spec(EVEL_DOMAIN_FAULT) != NULL);
+ }
+ assert(post.memory == NULL);
+
+ /*************************************************************************/
+ /* Request and verify the throttling state. */
+ /*************************************************************************/
+ handle_json_response(json_command_list_provide, &post);
+ assert(post.memory != NULL);
+ compare_strings(expected_posts[ii],
+ post.memory,
+ strlen(expected_posts[ii]),
+ "Throttle State Normal");
+ free(post.memory);
+ post.memory = NULL;
+ }
+
+ evel_throttle_terminate();
+}
+
+void test_encode_fault_throttled()
+{
+ MEMORY_CHUNK post;
+
+ /***************************************************************************/
+ /* We also test suppression of the event header parameters here. */
+ /***************************************************************************/
+ char * json_command_list =
+ "{"
+ "\"commandList\": ["
+ "{"
+ "\"command\": {"
+ "\"commandType\": \"throttlingSpecification\", "
+ "\"eventDomainThrottleSpecification\": {"
+ "\"eventDomain\": \"fault\", "
+ "\"suppressedFieldNames\": ["
+ "\"alarmInterfaceA\", "
+ "\"eventType\", "
+ "\"reportingEntityId\", "
+ "\"sourceId\"], "
+ "\"suppressedNvPairsList\": ["
+ "{"
+ "\"nvPairFieldName\": \"alarmAdditionalInformation\", "
+ "\"suppressedNvPairNames\": [\"name3\", \"name4\"]"
+ "}]}}}"
+ "]"
+ "}";
+
+ char * expected =
+ "{\"event\": {"
+ "\"commonEventHeader\": {"
+ "\"domain\": \"fault\", "
+ "\"eventId\": \"122\", "
+ "\"functionalRole\": \"UNIT TEST\", "
+ "\"lastEpochMicrosec\": 1000002, "
+ "\"priority\": \"Normal\", "
+ "\"reportingEntityName\": \"Dummy VM name - No Metadata available\", "
+ "\"sequence\": 122, "
+ "\"sourceName\": \"Dummy VM name - No Metadata available\", "
+ "\"startEpochMicrosec\": 1000002, "
+ "\"version\": 1.2"
+ "}, "
+ "\"faultFields\": {"
+ "\"alarmCondition\": \"My alarm condition\", "
+ "\"eventSeverity\": \"MAJOR\", "
+ "\"eventSourceType\": \"other\", "
+ "\"specificProblem\": \"It broke very badly\", "
+ "\"vfStatus\": \"Active\", "
+ "\"faultFieldsVersion\": 1.1, "
+ "\"alarmAdditionalInformation\": ["
+ "{\"name\": \"name1\", "
+ "\"value\": \"value1\"}, "
+ "{\"name\": \"name2\", "
+ "\"value\": \"value2\"}]"
+ "}}}";
+
+ /***************************************************************************/
+ /* Initialize and provide a specification with a single fault suppressed. */
+ /***************************************************************************/
+ evel_throttle_initialize();
+ handle_json_response(json_command_list, &post);
+
+ /***************************************************************************/
+ /* Check that the domain is throttled. */
+ /***************************************************************************/
+ assert(evel_get_throttle_spec(EVEL_DOMAIN_FAULT) != NULL);
+ assert(post.memory == NULL);
+
+ size_t json_size = 0;
+ char json_body[EVEL_MAX_JSON_BODY];
+ evel_set_next_event_sequence(122);
+ EVENT_FAULT * fault = evel_new_fault("My alarm condition",
+ "It broke very badly",
+ EVEL_PRIORITY_NORMAL,
+ EVEL_SEVERITY_MAJOR,
+ EVEL_SOURCE_HOST,
+ EVEL_VF_STATUS_PREP_TERMINATE);
+ assert(fault != NULL);
+ evel_fault_type_set(fault, "Bad things happen...");
+ evel_fault_addl_info_add(fault, "name1", "value1");
+ evel_fault_addl_info_add(fault, "name2", "value2");
+
+ /***************************************************************************/
+ /* Suppressed fields. */
+ /***************************************************************************/
+ evel_fault_interface_set(fault, "My Interface Card");
+ evel_fault_addl_info_add(fault, "name3", "value3");
+ evel_fault_addl_info_add(fault, "name4", "value4");
+
+ json_size = evel_json_encode_event(
+ json_body, EVEL_MAX_JSON_BODY, (EVENT_HEADER *) fault);
+ compare_strings(expected, json_body, EVEL_MAX_JSON_BODY, "Fault");
+ assert((json_size == strlen(json_body)) && "Bad size returned");
+
+ evel_free_event(fault);
+ evel_throttle_terminate();
+}
+
+void test_encode_measurement_throttled()
+{
+ MEMORY_CHUNK post;
+
+ /***************************************************************************/
+ /* We also test suppression of the event header parameters here. */
+ /***************************************************************************/
+ char * json_command_list =
+ "{"
+ "\"commandList\": ["
+ "{"
+ "\"command\": {"
+ "\"commandType\": \"throttlingSpecification\", "
+ "\"eventDomainThrottleSpecification\": {"
+ "\"eventDomain\": \"measurementsForVfScaling\", "
+ "\"suppressedFieldNames\": ["
+ "\"errors\", "
+ "\"vnfcScalingMetric\", "
+ "\"numberOfMediaPortsInUse\", "
+ "\"aggregateCpuUsage\", "
+ "\"requestRate\", "
+ "\"memoryUsed\", "
+ "\"memoryConfigured\", "
+ "\"meanRequestLatency\", "
+ "\"latencyDistribution\", "
+ "\"concurrentSessions\", "
+ "\"configuredEntities\", "
+ "\"eventType\", "
+ "\"reportingEntityId\", "
+ "\"sourceId\"], "
+ "\"suppressedNvPairsList\": ["
+ "{"
+ "\"nvPairFieldName\": \"cpuUsageArray\", "
+ "\"suppressedNvPairNames\": [\"cpu3\", \"cpu4\"]"
+ "}, "
+ "{"
+ "\"nvPairFieldName\": \"filesystemUsageArray\", "
+ "\"suppressedNvPairNames\": [\"00-11-22\", \"33-44-55\"]"
+ "}, "
+ "{"
+ "\"nvPairFieldName\": \"vNicUsageArray\", "
+ "\"suppressedNvPairNames\": [\"eth1\", \"eth0\"]"
+ "}, "
+ "{"
+ "\"nvPairFieldName\": \"featureUsageArray\", "
+ "\"suppressedNvPairNames\": [\"FeatureB\", \"FeatureC\"]"
+ "},"
+ "{"
+ "\"nvPairFieldName\": \"codecUsageArray\", "
+ "\"suppressedNvPairNames\": [\"G729ab\"]"
+ "},"
+ "{"
+ "\"nvPairFieldName\": \"additionalMeasurements\", "
+ "\"suppressedNvPairNames\": [\"Group2\"]"
+ "}"
+ "]}}}"
+ "]"
+ "}";
+
+ char * expected =
+ "{\"event\": "
+ "{\"commonEventHeader\": {"
+ "\"domain\": \"measurementsForVfScaling\", "
+ "\"eventId\": \"123\", "
+ "\"functionalRole\": \"UNIT TEST\", "
+ "\"lastEpochMicrosec\": 1000002, "
+ "\"priority\": \"Normal\", "
+ "\"reportingEntityName\": \"Dummy VM name - No Metadata available\", "
+ "\"sequence\": 123, "
+ "\"sourceName\": \"Dummy VM name - No Metadata available\", "
+ "\"startEpochMicrosec\": 1000002, "
+ "\"version\": 1.2"
+ "}, "
+ "\"measurementsForVfScalingFields\": "
+ "{"
+ "\"measurementInterval\": 5.500000, "
+ "\"cpuUsageArray\": ["
+ "{\"cpuIdentifier\": \"cpu1\", "
+ "\"percentUsage\": 11.110000}, "
+ "{\"cpuIdentifier\": \"cpu2\", "
+ "\"percentUsage\": 22.220000}], "
+ "\"filesystemUsageArray\": ["
+ "{\"blockConfigured\": 500.110000, "
+ "\"blockIops\": 77, "
+ "\"blockUsed\": 500.220000, "
+ "\"ephemeralConfigured\": 500.110000, "
+ "\"ephemeralIops\": 88, "
+ "\"ephemeralUsed\": 600.220000, "
+ "\"filesystemName\": \"66-77-88\"}], "
+ "\"featureUsageArray\": ["
+ "{\"featureIdentifier\": \"FeatureA\", "
+ "\"featureUtilization\": 123}], "
+ "\"codecUsageArray\": ["
+ "{\"codecIdentifier\": \"G711a\", "
+ "\"numberInUse\": 91}], "
+ "\"additionalMeasurements\": ["
+ "{\"name\": \"Group1\", "
+ "\"measurements\": ["
+ "{\"name\": \"Name1\", "
+ "\"value\": \"Value1\"}]}], "
+ "\"measurementsForVfScalingVersion\": 1.1}}}";
+ MEASUREMENT_CPU_USE *cpu_use;
+
+ /***************************************************************************/
+ /* Initialize and provide a specification with a single fault suppressed. */
+ /***************************************************************************/
+ evel_throttle_initialize();
+ handle_json_response(json_command_list, &post);
+
+ /***************************************************************************/
+ /* Check that the domain is throttled. */
+ /***************************************************************************/
+ assert(evel_get_throttle_spec(EVEL_DOMAIN_MEASUREMENT) != NULL);
+ assert(post.memory == NULL);
+
+ size_t json_size = 0;
+ char json_body[EVEL_MAX_JSON_BODY];
+ evel_set_next_event_sequence(123);
+ EVENT_MEASUREMENT * measurement = evel_new_measurement(5.5);
+ MEASUREMENT_LATENCY_BUCKET * bucket = NULL;
+ MEASUREMENT_VNIC_PERFORMANCE * vnic_use = NULL;
+ assert(measurement != NULL);
+
+ evel_measurement_type_set(measurement, "Perf management...");
+ evel_measurement_conc_sess_set(measurement, 1);
+ evel_measurement_cfg_ents_set(measurement, 2);
+ evel_measurement_mean_req_lat_set(measurement, 4.4);
+ evel_measurement_mem_cfg_set(measurement, 6.6);
+ evel_measurement_mem_used_set(measurement, 3.3);
+ evel_measurement_request_rate_set(measurement, 7);
+
+ cpu_use = evel_measurement_new_cpu_use_add(measurement, "cpu1", 11.11);
+ evel_measurement_cpu_use_idle_set(cpu_use,22.22);
+ evel_measurement_cpu_use_interrupt_set(cpu_use,33.33);
+ evel_measurement_cpu_use_nice_set(cpu_use,44.44);
+ evel_measurement_cpu_use_softirq_set(cpu_use,55.55);
+ evel_measurement_cpu_use_steal_set(cpu_use,66.66);
+ evel_measurement_cpu_use_system_set(cpu_use,77.77);
+ evel_measurement_cpu_use_usageuser_set(cpu_use,88.88);
+ evel_measurement_cpu_use_wait_set(cpu_use,99.99);
+
+ cpu_use = evel_measurement_new_cpu_use_add(measurement, "cpu2", 22.22);
+ evel_measurement_cpu_use_idle_set(cpu_use,12.22);
+ evel_measurement_cpu_use_interrupt_set(cpu_use,33.33);
+ evel_measurement_cpu_use_nice_set(cpu_use,44.44);
+ evel_measurement_cpu_use_softirq_set(cpu_use,55.55);
+ evel_measurement_cpu_use_steal_set(cpu_use,66.66);
+ evel_measurement_cpu_use_system_set(cpu_use,77.77);
+ evel_measurement_cpu_use_usageuser_set(cpu_use,88.88);
+ evel_measurement_cpu_use_wait_set(cpu_use,19.99);
+
+ evel_measurement_fsys_use_add(measurement, "00-11-22",
+ 100.11, 100.22, 33,
+ 200.11, 200.22, 44);
+ evel_measurement_fsys_use_add(measurement, "33-44-55",
+ 300.11, 300.22, 55,
+ 400.11, 400.22, 66);
+ evel_measurement_fsys_use_add(measurement, "66-77-88",
+ 500.11, 500.22, 77,
+ 600.11, 600.22, 88);
+
+ bucket = evel_new_meas_latency_bucket(20);
+ evel_meas_latency_bucket_add(measurement, bucket);
+
+ bucket = evel_new_meas_latency_bucket(30);
+ evel_meas_latency_bucket_low_end_set(bucket, 10.0);
+ evel_meas_latency_bucket_high_end_set(bucket, 20.0);
+ evel_meas_latency_bucket_add(measurement, bucket);
+
+ vnic_use = evel_new_measurement_vnic_use("eth0", 100, 200, 3, 4);
+ evel_vnic_use_bcast_pkt_in_set(vnic_use, 1);
+ evel_vnic_use_bcast_pkt_out_set(vnic_use, 2);
+ evel_vnic_use_mcast_pkt_in_set(vnic_use, 5);
+ evel_vnic_use_mcast_pkt_out_set(vnic_use, 6);
+ evel_vnic_use_ucast_pkt_in_set(vnic_use, 7);
+ evel_vnic_use_ucast_pkt_out_set(vnic_use, 8);
+ evel_meas_vnic_use_add(measurement, vnic_use);
+
+ vnic_use = evel_new_measurement_vnic_use("eth1", 110, 240, 13, 14);
+ evel_vnic_use_bcast_pkt_in_set(vnic_use, 11);
+ evel_vnic_use_bcast_pkt_out_set(vnic_use, 12);
+ evel_vnic_use_mcast_pkt_in_set(vnic_use, 15);
+ evel_vnic_use_mcast_pkt_out_set(vnic_use, 16);
+ evel_vnic_use_ucast_pkt_in_set(vnic_use, 17);
+ evel_vnic_use_ucast_pkt_out_set(vnic_use, 18);
+ evel_meas_vnic_use_add(measurement, vnic_use);
+
+ evel_measurement_errors_set(measurement, 1, 0, 2, 1);
+ evel_measurement_feature_use_add(measurement, "FeatureA", 123);
+ evel_measurement_feature_use_add(measurement, "FeatureB", 567);
+ evel_measurement_codec_use_add(measurement, "G711a", 91);
+ evel_measurement_codec_use_add(measurement, "G729ab", 92);
+ evel_measurement_media_port_use_set(measurement, 1234);
+ evel_measurement_vnfc_scaling_metric_set(measurement, 1234.5678);
+ evel_measurement_custom_measurement_add(measurement,
+ "Group1", "Name1", "Value1");
+ evel_measurement_custom_measurement_add(measurement,
+ "Group2", "Name1", "Value1");
+ evel_measurement_custom_measurement_add(measurement,
+ "Group2", "Name2", "Value2");
+
+ json_size = evel_json_encode_event(
+ json_body, EVEL_MAX_JSON_BODY, (EVENT_HEADER *) measurement);
+ compare_strings(expected, json_body, EVEL_MAX_JSON_BODY, "Measurement");
+ assert((json_size == strlen(json_body)) && "Bad size returned");
+
+ evel_free_event(measurement);
+ evel_throttle_terminate();
+}
+
+void test_encode_mobile_throttled()
+{
+ MEMORY_CHUNK post;
+
+ /***************************************************************************/
+ /* We also test suppression of the event header parameters here. */
+ /***************************************************************************/
+ char * json_command_list =
+ "{"
+ "\"commandList\": ["
+ "{"
+ "\"command\": {"
+ "\"commandType\": \"throttlingSpecification\", "
+ "\"eventDomainThrottleSpecification\": {"
+ "\"eventDomain\": \"mobileFlow\", "
+ "\"suppressedFieldNames\": ["
+ "\"applicationType\", "
+ "\"appProtocolType\", "
+ "\"appProtocolVersion\", "
+ "\"cid\", "
+ "\"connectionType\", "
+ "\"ecgi\", "
+ "\"gtpProtocolType\", "
+ "\"gtpVersion\", "
+ "\"httpHeader\", "
+ "\"imei\", "
+ "\"imsi\", "
+ "\"lac\", "
+ "\"mcc\", "
+ "\"mnc\", "
+ "\"msisdn\", "
+ "\"otherFunctionalRole\", "
+ "\"rac\", "
+ "\"radioAccessTechnology\", "
+ "\"sac\", "
+ "\"samplingAlgorithm\", "
+ "\"tac\", "
+ "\"tunnelId\", "
+ "\"vlanId\", "
+ "\"eventType\", "
+ "\"reportingEntityId\", "
+ "\"sourceId\"], "
+ "\"suppressedNvPairsList\": ["
+ "]}}}"
+ "]"
+ "}";
+
+ char * expected =
+ "{\"event\": "
+ "{\"commonEventHeader\": {"
+ "\"domain\": \"mobileFlow\", "
+ "\"eventId\": \"1242\", "
+ "\"functionalRole\": \"UNIT TEST\", "
+ "\"lastEpochMicrosec\": 1000002, "
+ "\"priority\": \"Normal\", "
+ "\"reportingEntityName\": \"Dummy VM name - No Metadata available\", "
+ "\"sequence\": 1242, "
+ "\"sourceName\": \"Dummy VM name - No Metadata available\", "
+ "\"startEpochMicrosec\": 1000002, "
+ "\"version\": 1.2"
+ "}, "
+ "\"mobileFlowFields\": {"
+ "\"flowDirection\": \"Inbound\", "
+ "\"gtpPerFlowMetrics\": {"
+ "\"avgBitErrorRate\": 132.000100, "
+ "\"avgPacketDelayVariation\": 31.200000, "
+ "\"avgPacketLatency\": 101, "
+ "\"avgReceiveThroughput\": 2101, "
+ "\"avgTransmitThroughput\": 501, "
+ "\"flowActivationEpoch\": 1470409422, "
+ "\"flowActivationMicrosec\": 988, "
+ "\"flowDeactivationEpoch\": 1470409432, "
+ "\"flowDeactivationMicrosec\": 12, "
+ "\"flowDeactivationTime\": \"Fri, 05 Aug 2016 15:03:52 +0000\", "
+ "\"flowStatus\": \"Inactive\", "
+ "\"maxPacketDelayVariation\": 88, "
+ "\"numActivationFailures\": 4, "
+ "\"numBitErrors\": 18, "
+ "\"numBytesReceived\": 123655, "
+ "\"numBytesTransmitted\": 4562, "
+ "\"numDroppedPackets\": 1, "
+ "\"numL7BytesReceived\": 13, "
+ "\"numL7BytesTransmitted\": 11, "
+ "\"numLostPackets\": 2, "
+ "\"numOutOfOrderPackets\": 4, "
+ "\"numPacketErrors\": 8, "
+ "\"numPacketsReceivedExclRetrans\": 900, "
+ "\"numPacketsReceivedInclRetrans\": 902, "
+ "\"numPacketsTransmittedInclRetrans\": 303, "
+ "\"numRetries\": 7, "
+ "\"numTimeouts\": 3, "
+ "\"numTunneledL7BytesReceived\": 1, "
+ "\"roundTripTime\": 111, "
+ "\"timeToFirstByte\": 226, "
+ "\"ipTosCountList\": ["
+ "[\"1\", 13], "
+ "[\"4\", 99], "
+ "[\"17\", 1]], "
+ "\"ipTosList\": [\"1\", \"4\", \"17\"], "
+ "\"tcpFlagList\": [\"CWR\", \"URG\"], "
+ "\"tcpFlagCountList\": [[\"CWR\", 10], [\"URG\", 121]], "
+ "\"mobileQciCosList\": [\"conversational\", \"65\"], "
+ "\"mobileQciCosCountList\": [[\"conversational\", 11], [\"65\", 122]], "
+ "\"durConnectionFailedStatus\": 12, "
+ "\"durTunnelFailedStatus\": 13, "
+ "\"flowActivatedBy\": \"Remote\", "
+ "\"flowActivationTime\": \"Fri, 05 Aug 2016 15:03:43 +0000\", "
+ "\"flowDeactivatedBy\": \"Remote\", "
+ "\"gtpConnectionStatus\": \"Connected\", "
+ "\"gtpTunnelStatus\": \"Not tunneling\", "
+ "\"largePacketRtt\": 80, "
+ "\"largePacketThreshold\": 600.000000, "
+ "\"maxReceiveBitRate\": 1357924680, "
+ "\"maxTransmitBitRate\": 235711, "
+ "\"numGtpEchoFailures\": 1, "
+ "\"numGtpTunnelErrors\": 4, "
+ "\"numHttpErrors\": 2"
+ "}, "
+ "\"ipProtocolType\": \"UDP\", "
+ "\"ipVersion\": \"IPv6\", "
+ "\"otherEndpointIpAddress\": \"2.3.4.2\", "
+ "\"otherEndpointPort\": 2342, "
+ "\"reportingEndpointIpAddr\": \"4.2.3.2\", "
+ "\"reportingEndpointPort\": 4322"
+ "}}}";
+
+ /***************************************************************************/
+ /* Initialize and provide a specification with a single fault suppressed. */
+ /***************************************************************************/
+ evel_throttle_initialize();
+ handle_json_response(json_command_list, &post);
+
+ /***************************************************************************/
+ /* Check that the domain is throttled. */
+ /***************************************************************************/
+ assert(evel_get_throttle_spec(EVEL_DOMAIN_MOBILE_FLOW) != NULL);
+ assert(post.memory == NULL);
+
+ size_t json_size = 0;
+ char json_body[EVEL_MAX_JSON_BODY];
+ MOBILE_GTP_PER_FLOW_METRICS * metrics = NULL;
+ EVENT_MOBILE_FLOW * mobile_flow = NULL;
+
+ /***************************************************************************/
+ /* Mobile. */
+ /***************************************************************************/
+ evel_set_next_event_sequence(1242);
+
+ metrics = evel_new_mobile_gtp_flow_metrics(132.0001,
+ 31.2,
+ 101,
+ 2101,
+ 501,
+ 1470409422,
+ 988,
+ 1470409432,
+ 12,
+ (time_t)1470409432,
+ "Inactive",
+ 88,
+ 4,
+ 18,
+ 123655,
+ 4562,
+ 1,
+ 13,
+ 11,
+ 2,
+ 4,
+ 8,
+ 900,
+ 902,
+ 303,
+ 7,
+ 3,
+ 1,
+ 111,
+ 226);
+ assert(metrics != NULL);
+
+ evel_mobile_gtp_metrics_dur_con_fail_set(metrics, 12);
+ evel_mobile_gtp_metrics_dur_tun_fail_set(metrics, 13);
+ evel_mobile_gtp_metrics_act_by_set(metrics, "Remote");
+ evel_mobile_gtp_metrics_act_time_set(metrics, (time_t)1470409423);
+ evel_mobile_gtp_metrics_deact_by_set(metrics, "Remote");
+ evel_mobile_gtp_metrics_con_status_set(metrics, "Connected");
+ evel_mobile_gtp_metrics_tun_status_set(metrics, "Not tunneling");
+ evel_mobile_gtp_metrics_iptos_set(metrics, 1, 13);
+ evel_mobile_gtp_metrics_iptos_set(metrics, 17, 1);
+ evel_mobile_gtp_metrics_iptos_set(metrics, 4, 99);
+ evel_mobile_gtp_metrics_large_pkt_rtt_set(metrics, 80);
+ evel_mobile_gtp_metrics_large_pkt_thresh_set(metrics, 600.0);
+ evel_mobile_gtp_metrics_max_rcv_bit_rate_set(metrics, 1357924680);
+ evel_mobile_gtp_metrics_max_trx_bit_rate_set(metrics, 235711);
+ evel_mobile_gtp_metrics_num_echo_fail_set(metrics, 1);
+ evel_mobile_gtp_metrics_num_tun_fail_set(metrics, 4);
+ evel_mobile_gtp_metrics_num_http_errors_set(metrics, 2);
+ evel_mobile_gtp_metrics_tcp_flag_count_add(metrics, EVEL_TCP_CWR, 10);
+ evel_mobile_gtp_metrics_tcp_flag_count_add(metrics, EVEL_TCP_URG, 121);
+ evel_mobile_gtp_metrics_qci_cos_count_add(
+ metrics, EVEL_QCI_COS_UMTS_CONVERSATIONAL, 11);
+ evel_mobile_gtp_metrics_qci_cos_count_add(
+ metrics, EVEL_QCI_COS_LTE_65, 122);
+
+ mobile_flow = evel_new_mobile_flow("Inbound",
+ metrics,
+ "UDP",
+ "IPv6",
+ "2.3.4.2",
+ 2342,
+ "4.2.3.2",
+ 4322);
+ assert(mobile_flow != NULL);
+
+ evel_mobile_flow_type_set(mobile_flow, "Mobile flow...");
+ evel_mobile_flow_app_type_set(mobile_flow, "Demo application");
+ evel_mobile_flow_app_prot_type_set(mobile_flow, "GSM");
+ evel_mobile_flow_app_prot_ver_set(mobile_flow, "1");
+ evel_mobile_flow_cid_set(mobile_flow, "65535");
+ evel_mobile_flow_con_type_set(mobile_flow, "S1-U");
+ evel_mobile_flow_ecgi_set(mobile_flow, "e65535");
+ evel_mobile_flow_gtp_prot_type_set(mobile_flow, "GTP-U");
+ evel_mobile_flow_gtp_prot_ver_set(mobile_flow, "1");
+ evel_mobile_flow_http_header_set(mobile_flow,
+ "http://www.something.com");
+ evel_mobile_flow_imei_set(mobile_flow, "209917614823");
+ evel_mobile_flow_imsi_set(mobile_flow, "355251/05/850925/8");
+ evel_mobile_flow_lac_set(mobile_flow, "1");
+ evel_mobile_flow_mcc_set(mobile_flow, "410");
+ evel_mobile_flow_mnc_set(mobile_flow, "04");
+ evel_mobile_flow_msisdn_set(mobile_flow, "6017123456789");
+ evel_mobile_flow_other_func_role_set(mobile_flow, "MME");
+ evel_mobile_flow_rac_set(mobile_flow, "514");
+ evel_mobile_flow_radio_acc_tech_set(mobile_flow, "LTE");
+ evel_mobile_flow_sac_set(mobile_flow, "1");
+ evel_mobile_flow_samp_alg_set(mobile_flow, 1);
+ evel_mobile_flow_tac_set(mobile_flow, "2099");
+ evel_mobile_flow_tunnel_id_set(mobile_flow, "Tunnel 1");
+ evel_mobile_flow_vlan_id_set(mobile_flow, "15");
+
+ json_size = evel_json_encode_event(
+ json_body, EVEL_MAX_JSON_BODY, (EVENT_HEADER *) mobile_flow);
+ compare_strings(expected, json_body, EVEL_MAX_JSON_BODY, "Mobile");
+ assert((json_size == strlen(json_body)) && "Bad size returned");
+
+ evel_free_event(mobile_flow);
+ evel_throttle_terminate();
+}
+
+void test_encode_other_throttled()
+{
+ MEMORY_CHUNK post;
+
+ /***************************************************************************/
+ /* We also test suppression of the event header parameters here. */
+ /***************************************************************************/
+ char * json_command_list =
+ "{"
+ "\"commandList\": ["
+ "{"
+ "\"command\": {"
+ "\"commandType\": \"throttlingSpecification\", "
+ "\"eventDomainThrottleSpecification\": {"
+ "\"eventDomain\": \"other\", "
+ "\"suppressedFieldNames\": ["
+ "\"eventType\", "
+ "\"reportingEntityId\", "
+ "\"sourceId\"], "
+ "\"suppressedNvPairsList\": ["
+ "]}}}"
+ "]"
+ "}";
+
+ char * expected =
+ "{\"event\": "
+ "{\"commonEventHeader\": {"
+ "\"domain\": \"other\", "
+ "\"eventId\": \"129\", "
+ "\"functionalRole\": \"UNIT TEST\", "
+ "\"lastEpochMicrosec\": 1000002, "
+ "\"priority\": \"Normal\", "
+ "\"reportingEntityName\": \"Dummy VM name - No Metadata available\", "
+ "\"sequence\": 129, "
+ "\"sourceName\": \"Dummy VM name - No Metadata available\", "
+ "\"startEpochMicrosec\": 1000002, "
+ "\"version\": 1.2"
+ "}, "
+ "\"otherFields\": ["
+ "{\"name\": \"Other field 1\", "
+ "\"value\": \"Other value 1\"}, "
+ "{\"name\": \"Other field 2\", "
+ "\"value\": \"Other value 2\"}"
+ "]"
+ "}}";
+
+ /***************************************************************************/
+ /* Initialize and provide a specification with a single fault suppressed. */
+ /***************************************************************************/
+ evel_throttle_initialize();
+ handle_json_response(json_command_list, &post);
+
+ /***************************************************************************/
+ /* Check that the domain is throttled. */
+ /***************************************************************************/
+ assert(evel_get_throttle_spec(EVEL_DOMAIN_OTHER) != NULL);
+ assert(post.memory == NULL);
+
+ size_t json_size = 0;
+ char json_body[EVEL_MAX_JSON_BODY];
+ EVENT_OTHER * other = NULL;
+ evel_set_next_event_sequence(129);
+ other = evel_new_other();
+ assert(other != NULL);
+ evel_other_type_set(other, "Other Type");
+ evel_other_field_add(other,
+ "Other field 1",
+ "Other value 1");
+ evel_other_field_add(other,
+ "Other field 2",
+ "Other value 2");
+
+ json_size = evel_json_encode_event(
+ json_body, EVEL_MAX_JSON_BODY, (EVENT_HEADER *) other);
+ compare_strings(expected, json_body, EVEL_MAX_JSON_BODY, "Other");
+ assert((json_size == strlen(json_body)) && "Bad size returned");
+
+ evel_free_event(other);
+ evel_throttle_terminate();
+}
+
+void test_encode_report_throttled()
+{
+ MEMORY_CHUNK post;
+
+ /***************************************************************************/
+ /* We also test suppression of the event header parameters here. */
+ /***************************************************************************/
+ char * json_command_list =
+ "{"
+ "\"commandList\": ["
+ "{"
+ "\"command\": {"
+ "\"commandType\": \"throttlingSpecification\", "
+ "\"eventDomainThrottleSpecification\": {"
+ "\"eventDomain\": \"report\", "
+ "\"suppressedFieldNames\": ["
+ "\"eventType\", "
+ "\"reportingEntityId\", "
+ "\"sourceId\"], "
+ "\"suppressedNvPairsList\": ["
+ "{"
+ "\"nvPairFieldName\": \"featureUsageArray\", "
+ "\"suppressedNvPairNames\": [\"FeatureB\", \"FeatureC\"]"
+ "},"
+ "{"
+ "\"nvPairFieldName\": \"additionalMeasurements\", "
+ "\"suppressedNvPairNames\": [\"Group2\"]"
+ "}"
+ "]}}}"
+ "]"
+ "}";
+
+ char * expected =
+ "{\"event\": "
+ "{\"commonEventHeader\": {"
+ "\"domain\": \"measurementsForVfReporting\", "
+ "\"eventId\": \"125\", "
+ "\"functionalRole\": \"UNIT TEST\", "
+ "\"lastEpochMicrosec\": 1000002, "
+ "\"priority\": \"Normal\", "
+ "\"reportingEntityName\": \"Dummy VM name - No Metadata available\", "
+ "\"sequence\": 125, "
+ "\"sourceName\": \"Dummy VM name - No Metadata available\", "
+ "\"startEpochMicrosec\": 1000002, "
+ "\"version\": 1.2"
+ "}, "
+ "\"measurementsForVfReportingFields\": "
+ "{\"measurementInterval\": 1.100000, "
+ "\"featureUsageArray\": ["
+ "{\"featureIdentifier\": \"FeatureA\", "
+ "\"featureUtilization\": 123}], "
+ "\"additionalMeasurements\": ["
+ "{\"name\": \"Group1\", "
+ "\"measurements\": ["
+ "{\"name\": \"Name1\", "
+ "\"value\": \"Value1\"}]}], "
+ "\"measurementFieldsVersion\": 1.1}}}";
+
+ /***************************************************************************/
+ /* Initialize and provide a specification with a single fault suppressed. */
+ /***************************************************************************/
+ evel_throttle_initialize();
+ handle_json_response(json_command_list, &post);
+
+ /***************************************************************************/
+ /* Check that the domain is throttled. */
+ /***************************************************************************/
+ assert(evel_get_throttle_spec(EVEL_DOMAIN_REPORT) != NULL);
+ assert(post.memory == NULL);
+
+ size_t json_size = 0;
+ char json_body[EVEL_MAX_JSON_BODY];
+ EVENT_REPORT * report = NULL;
+
+ /***************************************************************************/
+ /* Report. */
+ /***************************************************************************/
+ evel_set_next_event_sequence(125);
+ report = evel_new_report(1.1);
+ assert(report != NULL);
+ evel_report_type_set(report, "Perf reporting...");
+ evel_report_feature_use_add(report, "FeatureA", 123);
+ evel_report_feature_use_add(report, "FeatureB", 567);
+ evel_report_custom_measurement_add(report, "Group1", "Name1", "Value1");
+ evel_report_custom_measurement_add(report, "Group2", "Name1", "Value1");
+ evel_report_custom_measurement_add(report, "Group2", "Name2", "Value2");
+
+ json_size = evel_json_encode_event(
+ json_body, EVEL_MAX_JSON_BODY, (EVENT_HEADER *) report);
+ compare_strings(expected, json_body, EVEL_MAX_JSON_BODY, "Report");
+ assert((json_size == strlen(json_body)) && "Bad size returned");
+
+ evel_free_event(report);
+ evel_throttle_terminate();
+}
+
+void test_encode_service_throttled()
+{
+ MEMORY_CHUNK post;
+
+ /***************************************************************************/
+ /* We also test suppression of the event header parameters here. */
+ /***************************************************************************/
+ char * json_command_list =
+ "{"
+ "\"commandList\": ["
+ "{"
+ "\"command\": {"
+ "\"commandType\": \"throttlingSpecification\", "
+ "\"eventDomainThrottleSpecification\": {"
+ "\"eventDomain\": \"serviceEvents\", "
+ "\"suppressedFieldNames\": ["
+ "\"eventType\", "
+ "\"correlator\", "
+ "\"codecSelected\", "
+ "\"codecSelectedTranscoding\", "
+ "\"endOfCallVqmSummaries\", "
+ "\"midCallRtcp\", "
+ "\"marker\", "
+ "\"reportingEntityId\", "
+ "\"sourceId\"], "
+ "\"suppressedNvPairsList\": ["
+ "{"
+ "\"nvPairFieldName\": \"additionalFields\", "
+ "\"suppressedNvPairNames\": [\"Name1\", \"Name3\"]"
+ "}"
+ "]}}}"
+ "]"
+ "}";
+
+ char * expected =
+ "{\"event\": "
+ "{\"commonEventHeader\": {"
+ "\"domain\": \"serviceEvents\", "
+ "\"eventId\": \"2000\", "
+ "\"functionalRole\": \"UNIT TEST\", "
+ "\"lastEpochMicrosec\": 1000002, "
+ "\"priority\": \"Normal\", "
+ "\"reportingEntityName\": \"Dummy VM name - No Metadata available\", "
+ "\"sequence\": 2000, "
+ "\"sourceName\": \"Dummy VM name - No Metadata available\", "
+ "\"startEpochMicrosec\": 1000002, "
+ "\"version\": 1.2"
+ "}, "
+ "\"serviceEventsFields\": {"
+ "\"eventInstanceIdentifier\": "
+ "{"
+ "\"vendorId\": \"vendor_x_id\", "
+ "\"eventId\": \"vendor_x_event_id\", "
+ "\"productId\": \"vendor_x_product_id\", "
+ "\"subsystemId\": \"vendor_x_subsystem_id\", "
+ "\"eventFriendlyName\": \"vendor_x_frieldly_name\""
+ "}, "
+ "\"serviceEventsFieldsVersion\": 1.1, "
+ "\"additionalFields\": ["
+ "{\"name\": \"Name2\", \"value\": \"Value2\"}, "
+ "{\"name\": \"Name4\", \"value\": \"Value4\"}]"
+ "}}}";
+
+ /***************************************************************************/
+ /* Initialize and provide a specification with a single fault suppressed. */
+ /***************************************************************************/
+ evel_throttle_initialize();
+ handle_json_response(json_command_list, &post);
+
+ /***************************************************************************/
+ /* Check that the domain is throttled. */
+ /***************************************************************************/
+ assert(evel_get_throttle_spec(EVEL_DOMAIN_SERVICE) != NULL);
+ assert(post.memory == NULL);
+
+ size_t json_size = 0;
+ char json_body[EVEL_MAX_JSON_BODY];
+ EVENT_SERVICE * event = NULL;
+ evel_set_next_event_sequence(2000);
+ event = evel_new_service("vendor_x_id", "vendor_x_event_id");
+ assert(event != NULL);
+ evel_service_type_set(event, "Service Event");
+ evel_service_product_id_set(event, "vendor_x_product_id");
+ evel_service_subsystem_id_set(event, "vendor_x_subsystem_id");
+ evel_service_friendly_name_set(event, "vendor_x_frieldly_name");
+ evel_service_correlator_set(event, "vendor_x_correlator");
+ evel_service_codec_set(event, "PCMA");
+ evel_service_codec_set(event, "PCMA");
+ evel_service_callee_codec_set(event, "PCMA");
+ evel_service_caller_codec_set(event, "G729A");
+ evel_service_rtcp_data_set(event, "some_rtcp_data");
+ evel_service_adjacency_name_set(event, "vendor_x_adjacency");
+ evel_service_endpoint_desc_set(event, EVEL_SERVICE_ENDPOINT_CALLER);
+ evel_service_endpoint_jitter_set(event, 66);
+ evel_service_endpoint_rtp_oct_disc_set(event, 100);
+ evel_service_endpoint_rtp_oct_recv_set(event, 200);
+ evel_service_endpoint_rtp_oct_sent_set(event, 300);
+ evel_service_endpoint_rtp_pkt_disc_set(event, 400);
+ evel_service_endpoint_rtp_pkt_recv_set(event, 500);
+ evel_service_endpoint_rtp_pkt_sent_set(event, 600);
+ evel_service_local_jitter_set(event, 99);
+ evel_service_local_rtp_oct_disc_set(event, 150);
+ evel_service_local_rtp_oct_recv_set(event, 250);
+ evel_service_local_rtp_oct_sent_set(event, 350);
+ evel_service_local_rtp_pkt_disc_set(event, 450);
+ evel_service_local_rtp_pkt_recv_set(event, 550);
+ evel_service_local_rtp_pkt_sent_set(event, 650);
+ evel_service_mos_cqe_set(event, 12.255);
+ evel_service_packets_lost_set(event, 157);
+ evel_service_packet_loss_percent_set(event, 0.232);
+ evel_service_r_factor_set(event, 11);
+ evel_service_round_trip_delay_set(event, 15);
+ evel_service_phone_number_set(event, "0888888888");
+ evel_service_addl_field_add(event, "Name1", "Value1");
+ evel_service_addl_field_add(event, "Name2", "Value2");
+ evel_service_addl_field_add(event, "Name3", "Value3");
+ evel_service_addl_field_add(event, "Name4", "Value4");
+ json_size = evel_json_encode_event(
+ json_body, EVEL_MAX_JSON_BODY, (EVENT_HEADER *) event);
+ compare_strings(expected, json_body, EVEL_MAX_JSON_BODY, "Service");
+ assert((json_size == strlen(json_body)) && "Bad size returned");
+
+ evel_free_event(event);
+ evel_throttle_terminate();
+}
+
+void test_encode_signaling_throttled()
+{
+ MEMORY_CHUNK post;
+
+ /***************************************************************************/
+ /* We also test suppression of the event header parameters here. */
+ /***************************************************************************/
+ char * json_command_list =
+ "{"
+ "\"commandList\": ["
+ "{"
+ "\"command\": {"
+ "\"commandType\": \"throttlingSpecification\", "
+ "\"eventDomainThrottleSpecification\": {"
+ "\"eventDomain\": \"signaling\", "
+ "\"suppressedFieldNames\": ["
+ "\"correlator\", "
+ "\"eventType\", "
+ "\"reportingEntityId\", "
+ "\"sourceId\", "
+ "\"localIpAddress\", "
+ "\"localPort\", "
+ "\"remoteIpAddress\", "
+ "\"remotePort\", "
+ "\"compressedSip\", "
+ "\"summarySip\"], "
+ "\"suppressedNvPairsList\": ["
+ "]}}}"
+ "]"
+ "}";
+
+ char * expected =
+ "{\"event\": "
+ "{\"commonEventHeader\": {"
+ "\"domain\": \"signaling\", "
+ "\"eventId\": \"2001\", "
+ "\"functionalRole\": \"UNIT TEST\", "
+ "\"lastEpochMicrosec\": 1000002, "
+ "\"priority\": \"Normal\", "
+ "\"reportingEntityName\": \"Dummy VM name - No Metadata available\", "
+ "\"sequence\": 2001, "
+ "\"sourceName\": \"Dummy VM name - No Metadata available\", "
+ "\"startEpochMicrosec\": 1000002, "
+ "\"version\": 1.2"
+ "}, "
+ "\"signalingFields\": {"
+ "\"eventInstanceIdentifier\": "
+ "{"
+ "\"vendorId\": \"vendor_x_id\", "
+ "\"eventId\": \"vendor_x_event_id\", "
+ "\"productId\": \"vendor_x_product_id\", "
+ "\"subsystemId\": \"vendor_x_subsystem_id\", "
+ "\"eventFriendlyName\": \"vendor_x_frieldly_name\""
+ "}, "
+ "\"signalingFieldsVersion\": 1.1"
+ "}}}";
+
+ /***************************************************************************/
+ /* Initialize and provide a specification with a single fault suppressed. */
+ /***************************************************************************/
+ evel_throttle_initialize();
+ handle_json_response(json_command_list, &post);
+
+ /***************************************************************************/
+ /* Check that the domain is throttled. */
+ /***************************************************************************/
+ assert(evel_get_throttle_spec(EVEL_DOMAIN_SIGNALING) != NULL);
+ assert(post.memory == NULL);
+
+ size_t json_size = 0;
+ char json_body[EVEL_MAX_JSON_BODY];
+ EVENT_SIGNALING * event = NULL;
+ evel_set_next_event_sequence(2001);
+ event = evel_new_signaling("vendor_x_id",
+ "correlator", "1.0.3.1", "1234", "192.168.1.3","3456");
+ assert(event != NULL);
+ evel_signaling_vnfmodule_name_set(event, "vendor_x_module");
+ evel_signaling_vnfname_set(event, "vendor_x_vnf");
+ evel_signaling_type_set(event, "Signaling");
+ evel_signaling_product_id_set(event, "vendor_x_product_id");
+ evel_signaling_subsystem_id_set(event, "vendor_x_subsystem_id");
+ evel_signaling_friendly_name_set(event, "vendor_x_frieldly_name");
+ evel_signaling_correlator_set(event, "vendor_x_correlator");
+ evel_signaling_local_ip_address_set(event, "1.0.3.1");
+ evel_signaling_local_port_set(event, "1031");
+ evel_signaling_remote_ip_address_set(event, "5.3.3.0");
+ evel_signaling_remote_port_set(event, "5330");
+ evel_signaling_compressed_sip_set(event, "compressed_sip");
+ evel_signaling_summary_sip_set(event, "summary_sip");
+ json_size = evel_json_encode_event(
+ json_body, EVEL_MAX_JSON_BODY, (EVENT_HEADER *) event);
+ compare_strings(expected, json_body, EVEL_MAX_JSON_BODY, "Signaling");
+ assert((json_size == strlen(json_body)) && "Bad size returned");
+
+ evel_free_event(event);
+ evel_throttle_terminate();
+}
+
+void test_encode_state_change_throttled()
+{
+ MEMORY_CHUNK post;
+
+ /***************************************************************************/
+ /* We also test suppression of the event header parameters here. */
+ /***************************************************************************/
+ char * json_command_list =
+ "{"
+ "\"commandList\": ["
+ "{"
+ "\"command\": {"
+ "\"commandType\": \"throttlingSpecification\", "
+ "\"eventDomainThrottleSpecification\": {"
+ "\"eventDomain\": \"stateChange\", "
+ "\"suppressedFieldNames\": ["
+ "\"eventType\", "
+ "\"reportingEntityId\", "
+ "\"sourceId\"], "
+ "\"suppressedNvPairsList\": ["
+ "{"
+ "\"nvPairFieldName\": \"additionalFields\", "
+ "\"suppressedNvPairNames\": [\"Name1\"]"
+ "},"
+ "]}}}"
+ "]"
+ "}";
+
+ char * expected =
+ "{\"event\": "
+ "{\"commonEventHeader\": {"
+ "\"domain\": \"stateChange\", "
+ "\"eventId\": \"128\", "
+ "\"functionalRole\": \"UNIT TEST\", "
+ "\"lastEpochMicrosec\": 1000002, "
+ "\"priority\": \"Normal\", "
+ "\"reportingEntityName\": \"Dummy VM name - No Metadata available\", "
+ "\"sequence\": 128, "
+ "\"sourceName\": \"Dummy VM name - No Metadata available\", "
+ "\"startEpochMicrosec\": 1000002, "
+ "\"version\": 1.2"
+ "}, "
+ "\"stateChangeFields\": {"
+ "\"newState\": \"inService\", "
+ "\"oldState\": \"outOfService\", "
+ "\"stateInterface\": \"An Interface\", "
+ "\"additionalFields\": ["
+ "{\"name\": \"Name2\", "
+ "\"value\": \"Value2\"}"
+ "], "
+ "\"stateChangeFieldsVersion\": 1.1"
+ "}}}";
+
+ /***************************************************************************/
+ /* Initialize and provide a specification with a single fault suppressed. */
+ /***************************************************************************/
+ evel_throttle_initialize();
+ handle_json_response(json_command_list, &post);
+
+ /***************************************************************************/
+ /* Check that the domain is throttled. */
+ /***************************************************************************/
+ assert(evel_get_throttle_spec(EVEL_DOMAIN_STATE_CHANGE) != NULL);
+ assert(post.memory == NULL);
+
+ size_t json_size = 0;
+ char json_body[EVEL_MAX_JSON_BODY];
+ EVENT_STATE_CHANGE * state_change = NULL;
+ evel_set_next_event_sequence(128);
+ state_change = evel_new_state_change(EVEL_ENTITY_STATE_IN_SERVICE,
+ EVEL_ENTITY_STATE_OUT_OF_SERVICE,
+ "An Interface");
+ assert(state_change != NULL);
+ evel_state_change_type_set(state_change, "SC Type");
+ evel_state_change_addl_field_add(state_change, "Name1", "Value1");
+ evel_state_change_addl_field_add(state_change, "Name2", "Value2");
+
+ json_size = evel_json_encode_event(
+ json_body, EVEL_MAX_JSON_BODY, (EVENT_HEADER *) state_change);
+ compare_strings(expected, json_body, EVEL_MAX_JSON_BODY, "StateChange");
+ assert((json_size == strlen(json_body)) && "Bad size returned");
+
+ evel_free_event(state_change);
+ evel_throttle_terminate();
+}
+
+void test_encode_syslog_throttled()
+{
+ MEMORY_CHUNK post;
+
+ /***************************************************************************/
+ /* We also test suppression of the event header parameters here. */
+ /***************************************************************************/
+ char * json_command_list =
+ "{"
+ "\"commandList\": ["
+ "{"
+ "\"command\": {"
+ "\"commandType\": \"throttlingSpecification\", "
+ "\"eventDomainThrottleSpecification\": {"
+ "\"eventDomain\": \"syslog\", "
+ "\"suppressedFieldNames\": ["
+ "\"eventSourceHost\", "
+ "\"syslogFacility\", "
+ "\"syslogProc\", "
+ "\"syslogProcId\", "
+ "\"syslogSData\", "
+ "\"syslogVer\", "
+ "\"eventType\", "
+ "\"reportingEntityId\", "
+ "\"sourceId\"], "
+ "\"suppressedNvPairsList\": ["
+ "{"
+ "\"nvPairFieldName\": \"additionalFields\", "
+ "\"suppressedNvPairNames\": [\"Name2\"]"
+ "},"
+ "]}}}"
+ "]"
+ "}";
+
+ char * expected =
+ "{\"event\": "
+ "{\"commonEventHeader\": {"
+ "\"domain\": \"syslog\", "
+ "\"eventId\": \"126\", "
+ "\"functionalRole\": \"UNIT TEST\", "
+ "\"lastEpochMicrosec\": 1000002, "
+ "\"priority\": \"Normal\", "
+ "\"reportingEntityName\": \"Dummy VM name - No Metadata available\", "
+ "\"sequence\": 126, "
+ "\"sourceName\": \"Dummy VM name - No Metadata available\", "
+ "\"startEpochMicrosec\": 1000002, "
+ "\"version\": 1.2"
+ "}, "
+ "\"syslogFields\": {"
+ "\"eventSourceType\": \"virtualNetworkFunction\", "
+ "\"syslogMsg\": \"SL Message\", "
+ "\"syslogTag\": \"SL Tag\", "
+ "\"syslogFieldsVersion\": 1.1, "
+ "\"additionalFields\": ["
+ "{\"name\": \"Name1\", "
+ "\"value\": \"Value1\"}"
+ "]"
+ "}}}";
+
+ /***************************************************************************/
+ /* Initialize and provide a specification with a single fault suppressed. */
+ /***************************************************************************/
+ evel_throttle_initialize();
+ handle_json_response(json_command_list, &post);
+
+ /***************************************************************************/
+ /* Check that the domain is throttled. */
+ /***************************************************************************/
+ assert(evel_get_throttle_spec(EVEL_DOMAIN_SYSLOG) != NULL);
+ assert(post.memory == NULL);
+
+ size_t json_size = 0;
+ char json_body[EVEL_MAX_JSON_BODY];
+ EVENT_SYSLOG * syslog = NULL;
+ evel_set_next_event_sequence(126);
+ syslog = evel_new_syslog(EVEL_SOURCE_VIRTUAL_NETWORK_FUNCTION,
+ "SL Message",
+ "SL Tag");
+ assert(syslog != NULL);
+ evel_syslog_type_set(syslog, "SL Type");
+ evel_syslog_event_source_host_set(syslog, "SL Host");
+ evel_syslog_facility_set(syslog, EVEL_SYSLOG_FACILITY_LINE_PRINTER);
+ evel_syslog_proc_set(syslog, "SL Proc");
+ evel_syslog_proc_id_set(syslog, 2);
+ evel_syslog_version_set(syslog, 1);
+ evel_syslog_s_data_set(syslog, "SL SDATA");
+ evel_syslog_addl_field_add(syslog, "Name1", "Value1");
+ evel_syslog_addl_field_add(syslog, "Name2", "Value2");
+
+ json_size = evel_json_encode_event(
+ json_body, EVEL_MAX_JSON_BODY, (EVENT_HEADER *) syslog);
+ compare_strings(expected, json_body, EVEL_MAX_JSON_BODY, "Syslog");
+ assert((json_size == strlen(json_body)) && "Bad size returned");
+
+ evel_free_event(syslog);
+ evel_throttle_terminate();
+}
+
+void test_encode_fault_with_escaping()
+{
+ char * expected =
+ "{\"event\": {"
+ "\"commonEventHeader\": {"
+ "\"domain\": \"fault\", "
+ "\"eventId\": \"122\", "
+ "\"functionalRole\": \"UNIT TEST\", "
+ "\"lastEpochMicrosec\": 1000002, "
+ "\"priority\": \"Normal\", "
+ "\"reportingEntityName\": \"Dummy VM name - No Metadata available\", "
+ "\"sequence\": 122, "
+ "\"sourceName\": \"Dummy VM name - No Metadata available\", "
+ "\"startEpochMicrosec\": 1000002, "
+ "\"version\": 1.2, "
+ "\"eventType\": \"Bad things happen...\\\\\", "
+ "\"reportingEntityId\": \"Dummy VM UUID - No Metadata available\", "
+ "\"sourceId\": \"Dummy VM UUID - No Metadata available\""
+ "}, "
+ "\"faultFields\": {"
+ "\"alarmCondition\": \"My alarm condition\", "
+ "\"eventSeverity\": \"MAJOR\", "
+ "\"eventSourceType\": \"other\", "
+ "\"specificProblem\": \"It broke \\\"very\\\" badly\", "
+ "\"vfStatus\": \"Active\", "
+ "\"faultFieldsVersion\": 1.1, "
+ "\"alarmAdditionalInformation\": ["
+ "{\"name\": \"name1\", "
+ "\"value\": \"value1\"}, "
+ "{\"name\": \"name2\", "
+ "\"value\": \"value2\"}], "
+ "\"alarmInterfaceA\": \"My Interface Card\""
+ "}}}";
+
+ size_t json_size = 0;
+ char json_body[EVEL_MAX_JSON_BODY];
+ evel_set_next_event_sequence(122);
+ EVENT_FAULT * fault = evel_new_fault("My alarm condition",
+ "It broke \"very\" badly",
+ EVEL_PRIORITY_NORMAL,
+ EVEL_SEVERITY_MAJOR,
+ EVEL_SOURCE_HOST,
+ EVEL_VF_STATUS_PREP_TERMINATE);
+ assert(fault != NULL);
+ evel_fault_type_set(fault, "Bad things happen...\\");
+ evel_fault_interface_set(fault, "My Interface Card");
+ evel_fault_addl_info_add(fault, "name1", "value1");
+ evel_fault_addl_info_add(fault, "name2", "value2");
+
+ json_size = evel_json_encode_event(
+ json_body, EVEL_MAX_JSON_BODY, (EVENT_HEADER *) fault);
+ compare_strings(expected, json_body, EVEL_MAX_JSON_BODY, "Fault");
+ assert((json_size == strlen(json_body)) && "Bad size returned");
+
+ evel_free_event(fault);
+}
diff --git a/VES5.0/evel/evel-library/docs/source/evel/README b/VES5.0/evel/evel-library/docs/source/evel/README
new file mode 100644
index 00000000..89e7a3ad
--- /dev/null
+++ b/VES5.0/evel/evel-library/docs/source/evel/README
@@ -0,0 +1 @@
+Generated source code documentation. \ No newline at end of file
diff --git a/VES5.0/evel/evel-library/libs/x86_64/README b/VES5.0/evel/evel-library/libs/x86_64/README
new file mode 100644
index 00000000..760fdc13
--- /dev/null
+++ b/VES5.0/evel/evel-library/libs/x86_64/README
@@ -0,0 +1 @@
+Generated libraries. \ No newline at end of file
diff --git a/VES5.0/evel/evel-library/libs/x86_64/libevel.a b/VES5.0/evel/evel-library/libs/x86_64/libevel.a
new file mode 100755
index 00000000..96f947c5
--- /dev/null
+++ b/VES5.0/evel/evel-library/libs/x86_64/libevel.a
Binary files differ
diff --git a/VES5.0/evel/evel-library/output/x86_64/README b/VES5.0/evel/evel-library/output/x86_64/README
new file mode 100644
index 00000000..d1c9f1f1
--- /dev/null
+++ b/VES5.0/evel/evel-library/output/x86_64/README
@@ -0,0 +1 @@
+Generated executables. \ No newline at end of file
diff --git a/VES5.0/evel/evel-library/readme.md b/VES5.0/evel/evel-library/readme.md
new file mode 100644
index 00000000..65ce4ef5
--- /dev/null
+++ b/VES5.0/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