diff options
Diffstat (limited to 'VES5.0/evel/evel-library/code/evel_library/evel_mobile_flow.c')
-rw-r--r-- | VES5.0/evel/evel-library/code/evel_library/evel_mobile_flow.c | 2132 |
1 files changed, 2132 insertions, 0 deletions
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(); +} |