summaryrefslogtreecommitdiffstats
path: root/pceplib/pcep_session_logic_counters.c
diff options
context:
space:
mode:
Diffstat (limited to 'pceplib/pcep_session_logic_counters.c')
-rw-r--r--pceplib/pcep_session_logic_counters.c454
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);
+}