/* * 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 . * * Author : Brady Johnson * */ /* * PCEP session logic counters configuration. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #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); }