diff options
Diffstat (limited to '')
-rw-r--r-- | pceplib/pcep_session_logic_counters.c | 454 |
1 files changed, 454 insertions, 0 deletions
diff --git a/pceplib/pcep_session_logic_counters.c b/pceplib/pcep_session_logic_counters.c new file mode 100644 index 0000000..fceb15a --- /dev/null +++ b/pceplib/pcep_session_logic_counters.c @@ -0,0 +1,454 @@ +/* + * This file is part of the PCEPlib, a PCEP protocol library. + * + * Copyright (C) 2020 Volta Networks https://voltanet.io/ + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + * Author : Brady Johnson <brady@voltanet.io> + * + */ + + +/* + * PCEP session logic counters configuration. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdio.h> +#include <time.h> + +#include "pcep_session_logic.h" +#include "pcep_session_logic_internals.h" +#include "pcep_utils_counters.h" +#include "pcep_utils_logging.h" + +void increment_message_counters(pcep_session *session, + struct pcep_message *message, bool is_rx); + +void create_session_counters(pcep_session *session) +{ + /* + * Message RX and TX counters + */ + struct counters_subgroup *rx_msg_subgroup = create_counters_subgroup( + "RX Message counters", COUNTER_SUBGROUP_ID_RX_MSG, + PCEP_TYPE_MAX + 1); + create_subgroup_counter(rx_msg_subgroup, PCEP_TYPE_OPEN, + "Message Open"); + create_subgroup_counter(rx_msg_subgroup, PCEP_TYPE_KEEPALIVE, + "Message KeepAlive"); + create_subgroup_counter(rx_msg_subgroup, PCEP_TYPE_PCREQ, + "Message PcReq"); + create_subgroup_counter(rx_msg_subgroup, PCEP_TYPE_PCREP, + "Message PcRep"); + create_subgroup_counter(rx_msg_subgroup, PCEP_TYPE_PCNOTF, + "Message Notify"); + create_subgroup_counter(rx_msg_subgroup, PCEP_TYPE_ERROR, + "Message Error"); + create_subgroup_counter(rx_msg_subgroup, PCEP_TYPE_CLOSE, + "Message Close"); + create_subgroup_counter(rx_msg_subgroup, PCEP_TYPE_REPORT, + "Message Report"); + create_subgroup_counter(rx_msg_subgroup, PCEP_TYPE_UPDATE, + "Message Update"); + create_subgroup_counter(rx_msg_subgroup, PCEP_TYPE_INITIATE, + "Message Initiate"); + create_subgroup_counter(rx_msg_subgroup, PCEP_TYPE_START_TLS, + "Message StartTls"); + create_subgroup_counter(rx_msg_subgroup, PCEP_TYPE_MAX, + "Message Erroneous"); + + struct counters_subgroup *tx_msg_subgroup = + clone_counters_subgroup(rx_msg_subgroup, "TX Message counters", + COUNTER_SUBGROUP_ID_TX_MSG); + + /* + * Object RX and TX counters + */ + + /* For the Endpoints, the ID will be either 64 or 65, so setting + * num_counters to 100 */ + struct counters_subgroup *rx_obj_subgroup = create_counters_subgroup( + "RX Object counters", COUNTER_SUBGROUP_ID_RX_OBJ, 100); + create_subgroup_counter(rx_obj_subgroup, PCEP_OBJ_CLASS_OPEN, + "Object Open"); + create_subgroup_counter(rx_obj_subgroup, PCEP_OBJ_CLASS_RP, + "Object RP"); + create_subgroup_counter(rx_obj_subgroup, PCEP_OBJ_CLASS_NOPATH, + "Object Nopath"); + create_subgroup_counter( + rx_obj_subgroup, + ((PCEP_OBJ_CLASS_ENDPOINTS << 4) | PCEP_OBJ_TYPE_ENDPOINT_IPV4), + "Object Endpoint IPv4"); + create_subgroup_counter( + rx_obj_subgroup, + ((PCEP_OBJ_CLASS_ENDPOINTS << 4) | PCEP_OBJ_TYPE_ENDPOINT_IPV6), + "Object Endpoint IPv6"); + create_subgroup_counter(rx_obj_subgroup, PCEP_OBJ_CLASS_BANDWIDTH, + "Object Bandwidth"); + create_subgroup_counter(rx_obj_subgroup, PCEP_OBJ_CLASS_METRIC, + "Object Metric"); + create_subgroup_counter(rx_obj_subgroup, PCEP_OBJ_CLASS_ERO, + "Object ERO"); + create_subgroup_counter(rx_obj_subgroup, PCEP_OBJ_CLASS_RRO, + "Object RRO"); + create_subgroup_counter(rx_obj_subgroup, PCEP_OBJ_CLASS_LSPA, + "Object LSPA"); + create_subgroup_counter(rx_obj_subgroup, PCEP_OBJ_CLASS_IRO, + "Object IRO"); + create_subgroup_counter(rx_obj_subgroup, PCEP_OBJ_CLASS_SVEC, + "Object SVEC"); + create_subgroup_counter(rx_obj_subgroup, PCEP_OBJ_CLASS_NOTF, + "Object Notify"); + create_subgroup_counter(rx_obj_subgroup, PCEP_OBJ_CLASS_ERROR, + "Object Error"); + create_subgroup_counter(rx_obj_subgroup, PCEP_OBJ_CLASS_CLOSE, + "Object Close"); + create_subgroup_counter(rx_obj_subgroup, PCEP_OBJ_CLASS_LSP, + "Object LSP"); + create_subgroup_counter(rx_obj_subgroup, PCEP_OBJ_CLASS_SRP, + "Object SRP"); + create_subgroup_counter(rx_obj_subgroup, PCEP_OBJ_CLASS_VENDOR_INFO, + "Object Vendor Info"); + create_subgroup_counter(rx_obj_subgroup, PCEP_OBJ_CLASS_INTER_LAYER, + "Object Inter-Layer"); + create_subgroup_counter(rx_obj_subgroup, PCEP_OBJ_CLASS_SWITCH_LAYER, + "Object Switch-Layer"); + create_subgroup_counter(rx_obj_subgroup, PCEP_OBJ_CLASS_REQ_ADAP_CAP, + "Object Requested Adap-Cap"); + create_subgroup_counter(rx_obj_subgroup, PCEP_OBJ_CLASS_SERVER_IND, + "Object Server-Indication"); + create_subgroup_counter(rx_obj_subgroup, PCEP_OBJ_CLASS_ASSOCIATION, + "Object Association"); + create_subgroup_counter(rx_obj_subgroup, PCEP_OBJ_CLASS_MAX, + "Object Unknown"); + create_subgroup_counter(rx_obj_subgroup, PCEP_OBJ_CLASS_MAX + 1, + "Object Erroneous"); + + struct counters_subgroup *tx_obj_subgroup = + clone_counters_subgroup(rx_obj_subgroup, "TX Object counters", + COUNTER_SUBGROUP_ID_TX_OBJ); + + /* + * Sub-Object RX and TX counters + */ + struct counters_subgroup *rx_subobj_subgroup = create_counters_subgroup( + "RX RO Sub-Object counters", COUNTER_SUBGROUP_ID_RX_SUBOBJ, + RO_SUBOBJ_UNKNOWN + 2); + create_subgroup_counter(rx_subobj_subgroup, RO_SUBOBJ_TYPE_IPV4, + "RO Sub-Object IPv4"); + create_subgroup_counter(rx_subobj_subgroup, RO_SUBOBJ_TYPE_IPV6, + "RO Sub-Object IPv6"); + create_subgroup_counter(rx_subobj_subgroup, RO_SUBOBJ_TYPE_LABEL, + "RO Sub-Object Label"); + create_subgroup_counter(rx_subobj_subgroup, RO_SUBOBJ_TYPE_UNNUM, + "RO Sub-Object Unnum"); + create_subgroup_counter(rx_subobj_subgroup, RO_SUBOBJ_TYPE_ASN, + "RO Sub-Object ASN"); + create_subgroup_counter(rx_subobj_subgroup, RO_SUBOBJ_TYPE_SR, + "RO Sub-Object SR"); + create_subgroup_counter(rx_subobj_subgroup, RO_SUBOBJ_UNKNOWN, + "RO Sub-Object Unknown"); + create_subgroup_counter(rx_subobj_subgroup, RO_SUBOBJ_UNKNOWN + 1, + "RO Sub-Object Erroneous"); + + struct counters_subgroup *tx_subobj_subgroup = clone_counters_subgroup( + rx_subobj_subgroup, "TX RO Sub-Object counters", + COUNTER_SUBGROUP_ID_TX_SUBOBJ); + + /* + * RO SR Sub-Object RX and TX counters + */ + struct counters_subgroup *rx_subobj_sr_nai_subgroup = + create_counters_subgroup("RX RO SR NAI Sub-Object counters", + COUNTER_SUBGROUP_ID_RX_RO_SR_SUBOBJ, + PCEP_SR_SUBOBJ_NAI_UNKNOWN + 1); + create_subgroup_counter(rx_subobj_sr_nai_subgroup, + PCEP_SR_SUBOBJ_NAI_ABSENT, + "RO Sub-Object SR NAI absent"); + create_subgroup_counter(rx_subobj_sr_nai_subgroup, + PCEP_SR_SUBOBJ_NAI_IPV4_NODE, + "RO Sub-Object SR NAI IPv4 Node"); + create_subgroup_counter(rx_subobj_sr_nai_subgroup, + PCEP_SR_SUBOBJ_NAI_IPV6_NODE, + "RO Sub-Object SR NAI IPv6 Node"); + create_subgroup_counter(rx_subobj_sr_nai_subgroup, + PCEP_SR_SUBOBJ_NAI_IPV4_ADJACENCY, + "RO Sub-Object SR NAI IPv4 Adj"); + create_subgroup_counter(rx_subobj_sr_nai_subgroup, + PCEP_SR_SUBOBJ_NAI_IPV6_ADJACENCY, + "RO Sub-Object SR NAI IPv6 Adj"); + create_subgroup_counter(rx_subobj_sr_nai_subgroup, + PCEP_SR_SUBOBJ_NAI_UNNUMBERED_IPV4_ADJACENCY, + "RO Sub-Object SR NAI Unnumbered IPv4 Adj"); + create_subgroup_counter(rx_subobj_sr_nai_subgroup, + PCEP_SR_SUBOBJ_NAI_LINK_LOCAL_IPV6_ADJACENCY, + "RO Sub-Object SR NAI Link Local IPv6 Adj"); + create_subgroup_counter(rx_subobj_sr_nai_subgroup, + PCEP_SR_SUBOBJ_NAI_UNKNOWN, + "RO Sub-Object SR NAI Unknown"); + + struct counters_subgroup *tx_subobj_sr_nai_subgroup = + clone_counters_subgroup(rx_subobj_sr_nai_subgroup, + "TX RO SR NAI Sub-Object counters", + COUNTER_SUBGROUP_ID_TX_RO_SR_SUBOBJ); + + /* + * TLV RX and TX counters + */ + struct counters_subgroup *rx_tlv_subgroup = create_counters_subgroup( + "RX TLV counters", COUNTER_SUBGROUP_ID_RX_TLV, + PCEP_OBJ_TLV_TYPE_UNKNOWN + 1); + create_subgroup_counter(rx_tlv_subgroup, + PCEP_OBJ_TLV_TYPE_NO_PATH_VECTOR, + "TLV No Path Vector"); + create_subgroup_counter(rx_tlv_subgroup, PCEP_OBJ_TLV_TYPE_VENDOR_INFO, + "TLV Vendor Info"); + create_subgroup_counter(rx_tlv_subgroup, + PCEP_OBJ_TLV_TYPE_STATEFUL_PCE_CAPABILITY, + "TLV Stateful PCE Capability"); + create_subgroup_counter(rx_tlv_subgroup, + PCEP_OBJ_TLV_TYPE_SYMBOLIC_PATH_NAME, + "TLV Symbolic Path Name"); + create_subgroup_counter(rx_tlv_subgroup, + PCEP_OBJ_TLV_TYPE_IPV4_LSP_IDENTIFIERS, + "TLV IPv4 LSP Identifier"); + create_subgroup_counter(rx_tlv_subgroup, + PCEP_OBJ_TLV_TYPE_IPV6_LSP_IDENTIFIERS, + "TLV IPv6 LSP Identifier"); + create_subgroup_counter(rx_tlv_subgroup, + PCEP_OBJ_TLV_TYPE_LSP_ERROR_CODE, + "TLV LSP Error Code"); + create_subgroup_counter(rx_tlv_subgroup, + PCEP_OBJ_TLV_TYPE_RSVP_ERROR_SPEC, + "TLV RSVP Error Spec"); + create_subgroup_counter(rx_tlv_subgroup, + PCEP_OBJ_TLV_TYPE_LSP_DB_VERSION, + "TLV LSP DB Version"); + create_subgroup_counter(rx_tlv_subgroup, + PCEP_OBJ_TLV_TYPE_SPEAKER_ENTITY_ID, + "TLV Speaker Entity ID"); + create_subgroup_counter(rx_tlv_subgroup, + PCEP_OBJ_TLV_TYPE_SR_PCE_CAPABILITY, + "TLV SR PCE Capability"); + create_subgroup_counter(rx_tlv_subgroup, + PCEP_OBJ_TLV_TYPE_PATH_SETUP_TYPE, + "TLV Path Setup Type"); + create_subgroup_counter(rx_tlv_subgroup, + PCEP_OBJ_TLV_TYPE_PATH_SETUP_TYPE_CAPABILITY, + "TLV Path Setup Type Capability"); + create_subgroup_counter(rx_tlv_subgroup, + PCEP_OBJ_TLV_TYPE_SRPOLICY_POL_ID, + "TLV SR Policy PolId"); + create_subgroup_counter(rx_tlv_subgroup, + PCEP_OBJ_TLV_TYPE_SRPOLICY_POL_NAME, + "TLV SR Policy PolName"); + create_subgroup_counter(rx_tlv_subgroup, + PCEP_OBJ_TLV_TYPE_SRPOLICY_CPATH_ID, + "TLV SR Policy CpathId"); + create_subgroup_counter(rx_tlv_subgroup, + PCEP_OBJ_TLV_TYPE_SRPOLICY_CPATH_PREFERENCE, + "TLV SR Policy CpathRef"); + create_subgroup_counter(rx_tlv_subgroup, PCEP_OBJ_TLV_TYPE_UNKNOWN, + "TLV Unknown"); + + struct counters_subgroup *tx_tlv_subgroup = clone_counters_subgroup( + rx_tlv_subgroup, "TX TLV counters", COUNTER_SUBGROUP_ID_TX_TLV); + + /* + * PCEP Event counters + */ + struct counters_subgroup *events_subgroup = create_counters_subgroup( + "Events counters", COUNTER_SUBGROUP_ID_EVENT, MAX_COUNTERS); + create_subgroup_counter(events_subgroup, + PCEP_EVENT_COUNTER_ID_PCC_CONNECT, + "PCC connect"); + create_subgroup_counter(events_subgroup, + PCEP_EVENT_COUNTER_ID_PCE_CONNECT, + "PCE connect"); + create_subgroup_counter(events_subgroup, + PCEP_EVENT_COUNTER_ID_PCC_DISCONNECT, + "PCC disconnect"); + create_subgroup_counter(events_subgroup, + PCEP_EVENT_COUNTER_ID_PCE_DISCONNECT, + "PCE disconnect"); + create_subgroup_counter(events_subgroup, + PCEP_EVENT_COUNTER_ID_TIMER_KEEPALIVE, + "Timer KeepAlive expired"); + create_subgroup_counter(events_subgroup, + PCEP_EVENT_COUNTER_ID_TIMER_DEADTIMER, + "Timer DeadTimer expired"); + create_subgroup_counter(events_subgroup, + PCEP_EVENT_COUNTER_ID_TIMER_OPENKEEPWAIT, + "Timer OpenKeepWait expired"); + create_subgroup_counter(events_subgroup, + PCEP_EVENT_COUNTER_ID_TIMER_OPENKEEPALIVE, + "Timer OpenKeepAlive expired"); + + /* + * Create the parent counters group + */ + time_t now = time(NULL); + char counters_name[MAX_COUNTER_STR_LENGTH] = {0}; + char ip_str[40] = {0}; + if (session->socket_comm_session->is_ipv6) { + inet_ntop(AF_INET6, + &session->socket_comm_session->dest_sock_addr + .dest_sock_addr_ipv6.sin6_addr, + ip_str, 40); + } else { + inet_ntop(AF_INET, + &session->socket_comm_session->dest_sock_addr + .dest_sock_addr_ipv4.sin_addr, + ip_str, 40); + } + snprintf(counters_name, MAX_COUNTER_STR_LENGTH, + "PCEP Session [%d], connected to [%s] for [%u seconds]", + session->session_id, ip_str, + (uint32_t)(now - session->time_connected)); + /* The (time(NULL) - session->time_connected) will probably be 0, + * so the group name will be updated when the counters are dumped */ + session->pcep_session_counters = + create_counters_group(counters_name, MAX_COUNTER_GROUPS); + + /* + * Add all the subgroups to the parent counters group + */ + add_counters_subgroup(session->pcep_session_counters, rx_msg_subgroup); + add_counters_subgroup(session->pcep_session_counters, tx_msg_subgroup); + add_counters_subgroup(session->pcep_session_counters, rx_obj_subgroup); + add_counters_subgroup(session->pcep_session_counters, tx_obj_subgroup); + add_counters_subgroup(session->pcep_session_counters, + rx_subobj_subgroup); + add_counters_subgroup(session->pcep_session_counters, + tx_subobj_subgroup); + add_counters_subgroup(session->pcep_session_counters, + rx_subobj_sr_nai_subgroup); + add_counters_subgroup(session->pcep_session_counters, + tx_subobj_sr_nai_subgroup); + add_counters_subgroup(session->pcep_session_counters, rx_tlv_subgroup); + add_counters_subgroup(session->pcep_session_counters, tx_tlv_subgroup); + add_counters_subgroup(session->pcep_session_counters, events_subgroup); +} + +/* Internal util function used by increment_message_rx_counters or + * increment_message_tx_counters */ +void increment_message_counters(pcep_session *session, + struct pcep_message *message, bool is_rx) +{ + uint16_t counter_subgroup_id_msg = (is_rx ? COUNTER_SUBGROUP_ID_RX_MSG + : COUNTER_SUBGROUP_ID_TX_MSG); + uint16_t counter_subgroup_id_obj = (is_rx ? COUNTER_SUBGROUP_ID_RX_OBJ + : COUNTER_SUBGROUP_ID_TX_OBJ); + uint16_t counter_subgroup_id_subobj = + (is_rx ? COUNTER_SUBGROUP_ID_RX_SUBOBJ + : COUNTER_SUBGROUP_ID_TX_SUBOBJ); + uint16_t counter_subgroup_id_ro_sr_subobj = + (is_rx ? COUNTER_SUBGROUP_ID_RX_RO_SR_SUBOBJ + : COUNTER_SUBGROUP_ID_TX_RO_SR_SUBOBJ); + uint16_t counter_subgroup_id_tlv = (is_rx ? COUNTER_SUBGROUP_ID_RX_TLV + : COUNTER_SUBGROUP_ID_TX_TLV); + + increment_counter(session->pcep_session_counters, + counter_subgroup_id_msg, message->msg_header->type); + + /* Iterate the objects */ + double_linked_list_node *obj_node = + (message->obj_list == NULL ? NULL : message->obj_list->head); + for (; obj_node != NULL; obj_node = obj_node->next_node) { + struct pcep_object_header *obj = + (struct pcep_object_header *)obj_node->data; + + /* Handle class: PCEP_OBJ_CLASS_ENDPOINTS, + * type: PCEP_OBJ_TYPE_ENDPOINT_IPV4 or + * PCEP_OBJ_TYPE_ENDPOINT_IPV6 */ + uint16_t obj_counter_id = + (obj->object_class == PCEP_OBJ_CLASS_ENDPOINTS + ? (obj->object_class << 4) | obj->object_type + : obj->object_class); + + increment_counter(session->pcep_session_counters, + counter_subgroup_id_obj, obj_counter_id); + + /* Iterate the RO Sub-objects */ + if (obj->object_class == PCEP_OBJ_CLASS_ERO + || obj->object_class == PCEP_OBJ_CLASS_IRO + || obj->object_class == PCEP_OBJ_CLASS_RRO) { + struct pcep_object_ro *ro_obj = + (struct pcep_object_ro *)obj; + + double_linked_list_node *ro_subobj_node = + (ro_obj->sub_objects == NULL + ? NULL + : ro_obj->sub_objects->head); + for (; ro_subobj_node != NULL; + ro_subobj_node = ro_subobj_node->next_node) { + struct pcep_object_ro_subobj *ro_subobj = + (struct pcep_object_ro_subobj *) + ro_subobj_node->data; + increment_counter( + session->pcep_session_counters, + counter_subgroup_id_subobj, + ro_subobj->ro_subobj_type); + + /* Handle the ro subobj type RO_SUBOBJ_TYPE_SR + * different NAI types */ + if (ro_subobj->ro_subobj_type + == RO_SUBOBJ_TYPE_SR) { + struct pcep_ro_subobj_sr *ro_sr_subobj = + (struct pcep_ro_subobj_sr *) + ro_subobj; + increment_counter( + session->pcep_session_counters, + counter_subgroup_id_ro_sr_subobj, + ro_sr_subobj->nai_type); + } + } + } + + /* Iterate the TLVs */ + double_linked_list_node *tlv_node = + (obj->tlv_list == NULL ? NULL : obj->tlv_list->head); + for (; tlv_node != NULL; tlv_node = tlv_node->next_node) { + struct pcep_object_tlv_header *tlv = + (struct pcep_object_tlv_header *)tlv_node->data; + increment_counter(session->pcep_session_counters, + counter_subgroup_id_tlv, tlv->type); + } + } +} + +void increment_message_rx_counters(pcep_session *session, + struct pcep_message *message) +{ + increment_message_counters(session, message, true); +} + +void increment_message_tx_counters(pcep_session *session, + struct pcep_message *message) +{ + increment_message_counters(session, message, false); +} + +void increment_event_counters( + pcep_session *session, + pcep_session_counters_event_counter_ids counter_id) +{ + increment_counter(session->pcep_session_counters, + COUNTER_SUBGROUP_ID_EVENT, counter_id); +} |