2 * This file is part of the PCEPlib, a PCEP protocol library.
4 * Copyright (C) 2020 Volta Networks https://voltanet.io/
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 * Author : Brady Johnson <brady@voltanet.io>
25 * PCEP session logic counters configuration.
31 #include "pcep_session_logic.h"
32 #include "pcep_session_logic_internals.h"
33 #include "pcep_utils_counters.h"
34 #include "pcep_utils_logging.h"
36 void increment_message_counters(pcep_session
*session
,
37 struct pcep_message
*message
, bool is_rx
);
39 void create_session_counters(pcep_session
*session
)
42 * Message RX and TX counters
44 struct counters_subgroup
*rx_msg_subgroup
= create_counters_subgroup(
45 "RX Message counters", COUNTER_SUBGROUP_ID_RX_MSG
,
47 create_subgroup_counter(rx_msg_subgroup
, PCEP_TYPE_OPEN
,
49 create_subgroup_counter(rx_msg_subgroup
, PCEP_TYPE_KEEPALIVE
,
51 create_subgroup_counter(rx_msg_subgroup
, PCEP_TYPE_PCREQ
,
53 create_subgroup_counter(rx_msg_subgroup
, PCEP_TYPE_PCREP
,
55 create_subgroup_counter(rx_msg_subgroup
, PCEP_TYPE_PCNOTF
,
57 create_subgroup_counter(rx_msg_subgroup
, PCEP_TYPE_ERROR
,
59 create_subgroup_counter(rx_msg_subgroup
, PCEP_TYPE_CLOSE
,
61 create_subgroup_counter(rx_msg_subgroup
, PCEP_TYPE_REPORT
,
63 create_subgroup_counter(rx_msg_subgroup
, PCEP_TYPE_UPDATE
,
65 create_subgroup_counter(rx_msg_subgroup
, PCEP_TYPE_INITIATE
,
67 create_subgroup_counter(rx_msg_subgroup
, PCEP_TYPE_START_TLS
,
69 create_subgroup_counter(rx_msg_subgroup
, PCEP_TYPE_MAX
,
72 struct counters_subgroup
*tx_msg_subgroup
=
73 clone_counters_subgroup(rx_msg_subgroup
, "TX Message counters",
74 COUNTER_SUBGROUP_ID_TX_MSG
);
77 * Object RX and TX counters
80 /* For the Endpoints, the ID will be either 64 or 65, so setting
81 * num_counters to 100 */
82 struct counters_subgroup
*rx_obj_subgroup
= create_counters_subgroup(
83 "RX Object counters", COUNTER_SUBGROUP_ID_RX_OBJ
, 100);
84 create_subgroup_counter(rx_obj_subgroup
, PCEP_OBJ_CLASS_OPEN
,
86 create_subgroup_counter(rx_obj_subgroup
, PCEP_OBJ_CLASS_RP
,
88 create_subgroup_counter(rx_obj_subgroup
, PCEP_OBJ_CLASS_NOPATH
,
90 create_subgroup_counter(
92 ((PCEP_OBJ_CLASS_ENDPOINTS
<< 4) | PCEP_OBJ_TYPE_ENDPOINT_IPV4
),
93 "Object Endpoint IPv4");
94 create_subgroup_counter(
96 ((PCEP_OBJ_CLASS_ENDPOINTS
<< 4) | PCEP_OBJ_TYPE_ENDPOINT_IPV6
),
97 "Object Endpoint IPv6");
98 create_subgroup_counter(rx_obj_subgroup
, PCEP_OBJ_CLASS_BANDWIDTH
,
100 create_subgroup_counter(rx_obj_subgroup
, PCEP_OBJ_CLASS_METRIC
,
102 create_subgroup_counter(rx_obj_subgroup
, PCEP_OBJ_CLASS_ERO
,
104 create_subgroup_counter(rx_obj_subgroup
, PCEP_OBJ_CLASS_RRO
,
106 create_subgroup_counter(rx_obj_subgroup
, PCEP_OBJ_CLASS_LSPA
,
108 create_subgroup_counter(rx_obj_subgroup
, PCEP_OBJ_CLASS_IRO
,
110 create_subgroup_counter(rx_obj_subgroup
, PCEP_OBJ_CLASS_SVEC
,
112 create_subgroup_counter(rx_obj_subgroup
, PCEP_OBJ_CLASS_NOTF
,
114 create_subgroup_counter(rx_obj_subgroup
, PCEP_OBJ_CLASS_ERROR
,
116 create_subgroup_counter(rx_obj_subgroup
, PCEP_OBJ_CLASS_CLOSE
,
118 create_subgroup_counter(rx_obj_subgroup
, PCEP_OBJ_CLASS_LSP
,
120 create_subgroup_counter(rx_obj_subgroup
, PCEP_OBJ_CLASS_SRP
,
122 create_subgroup_counter(rx_obj_subgroup
, PCEP_OBJ_CLASS_VENDOR_INFO
,
123 "Object Vendor Info");
124 create_subgroup_counter(rx_obj_subgroup
, PCEP_OBJ_CLASS_INTER_LAYER
,
125 "Object Inter-Layer");
126 create_subgroup_counter(rx_obj_subgroup
, PCEP_OBJ_CLASS_SWITCH_LAYER
,
127 "Object Switch-Layer");
128 create_subgroup_counter(rx_obj_subgroup
, PCEP_OBJ_CLASS_REQ_ADAP_CAP
,
129 "Object Requested Adap-Cap");
130 create_subgroup_counter(rx_obj_subgroup
, PCEP_OBJ_CLASS_SERVER_IND
,
131 "Object Server-Indication");
132 create_subgroup_counter(rx_obj_subgroup
, PCEP_OBJ_CLASS_ASSOCIATION
,
133 "Object Association");
134 create_subgroup_counter(rx_obj_subgroup
, PCEP_OBJ_CLASS_MAX
,
136 create_subgroup_counter(rx_obj_subgroup
, PCEP_OBJ_CLASS_MAX
+ 1,
139 struct counters_subgroup
*tx_obj_subgroup
=
140 clone_counters_subgroup(rx_obj_subgroup
, "TX Object counters",
141 COUNTER_SUBGROUP_ID_TX_OBJ
);
144 * Sub-Object RX and TX counters
146 struct counters_subgroup
*rx_subobj_subgroup
= create_counters_subgroup(
147 "RX RO Sub-Object counters", COUNTER_SUBGROUP_ID_RX_SUBOBJ
,
148 RO_SUBOBJ_UNKNOWN
+ 2);
149 create_subgroup_counter(rx_subobj_subgroup
, RO_SUBOBJ_TYPE_IPV4
,
150 "RO Sub-Object IPv4");
151 create_subgroup_counter(rx_subobj_subgroup
, RO_SUBOBJ_TYPE_IPV6
,
152 "RO Sub-Object IPv6");
153 create_subgroup_counter(rx_subobj_subgroup
, RO_SUBOBJ_TYPE_LABEL
,
154 "RO Sub-Object Label");
155 create_subgroup_counter(rx_subobj_subgroup
, RO_SUBOBJ_TYPE_UNNUM
,
156 "RO Sub-Object Unnum");
157 create_subgroup_counter(rx_subobj_subgroup
, RO_SUBOBJ_TYPE_ASN
,
158 "RO Sub-Object ASN");
159 create_subgroup_counter(rx_subobj_subgroup
, RO_SUBOBJ_TYPE_SR
,
161 create_subgroup_counter(rx_subobj_subgroup
, RO_SUBOBJ_UNKNOWN
,
162 "RO Sub-Object Unknown");
163 create_subgroup_counter(rx_subobj_subgroup
, RO_SUBOBJ_UNKNOWN
+ 1,
164 "RO Sub-Object Erroneous");
166 struct counters_subgroup
*tx_subobj_subgroup
= clone_counters_subgroup(
167 rx_subobj_subgroup
, "TX RO Sub-Object counters",
168 COUNTER_SUBGROUP_ID_TX_SUBOBJ
);
171 * RO SR Sub-Object RX and TX counters
173 struct counters_subgroup
*rx_subobj_sr_nai_subgroup
=
174 create_counters_subgroup("RX RO SR NAI Sub-Object counters",
175 COUNTER_SUBGROUP_ID_RX_RO_SR_SUBOBJ
,
176 PCEP_SR_SUBOBJ_NAI_UNKNOWN
+ 1);
177 create_subgroup_counter(rx_subobj_sr_nai_subgroup
,
178 PCEP_SR_SUBOBJ_NAI_ABSENT
,
179 "RO Sub-Object SR NAI absent");
180 create_subgroup_counter(rx_subobj_sr_nai_subgroup
,
181 PCEP_SR_SUBOBJ_NAI_IPV4_NODE
,
182 "RO Sub-Object SR NAI IPv4 Node");
183 create_subgroup_counter(rx_subobj_sr_nai_subgroup
,
184 PCEP_SR_SUBOBJ_NAI_IPV6_NODE
,
185 "RO Sub-Object SR NAI IPv6 Node");
186 create_subgroup_counter(rx_subobj_sr_nai_subgroup
,
187 PCEP_SR_SUBOBJ_NAI_IPV4_ADJACENCY
,
188 "RO Sub-Object SR NAI IPv4 Adj");
189 create_subgroup_counter(rx_subobj_sr_nai_subgroup
,
190 PCEP_SR_SUBOBJ_NAI_IPV6_ADJACENCY
,
191 "RO Sub-Object SR NAI IPv6 Adj");
192 create_subgroup_counter(rx_subobj_sr_nai_subgroup
,
193 PCEP_SR_SUBOBJ_NAI_UNNUMBERED_IPV4_ADJACENCY
,
194 "RO Sub-Object SR NAI Unnumbered IPv4 Adj");
195 create_subgroup_counter(rx_subobj_sr_nai_subgroup
,
196 PCEP_SR_SUBOBJ_NAI_LINK_LOCAL_IPV6_ADJACENCY
,
197 "RO Sub-Object SR NAI Link Local IPv6 Adj");
198 create_subgroup_counter(rx_subobj_sr_nai_subgroup
,
199 PCEP_SR_SUBOBJ_NAI_UNKNOWN
,
200 "RO Sub-Object SR NAI Unknown");
202 struct counters_subgroup
*tx_subobj_sr_nai_subgroup
=
203 clone_counters_subgroup(rx_subobj_sr_nai_subgroup
,
204 "TX RO SR NAI Sub-Object counters",
205 COUNTER_SUBGROUP_ID_TX_RO_SR_SUBOBJ
);
208 * TLV RX and TX counters
210 struct counters_subgroup
*rx_tlv_subgroup
= create_counters_subgroup(
211 "RX TLV counters", COUNTER_SUBGROUP_ID_RX_TLV
,
212 PCEP_OBJ_TLV_TYPE_UNKNOWN
+ 1);
213 create_subgroup_counter(rx_tlv_subgroup
,
214 PCEP_OBJ_TLV_TYPE_NO_PATH_VECTOR
,
215 "TLV No Path Vector");
216 create_subgroup_counter(rx_tlv_subgroup
, PCEP_OBJ_TLV_TYPE_VENDOR_INFO
,
218 create_subgroup_counter(rx_tlv_subgroup
,
219 PCEP_OBJ_TLV_TYPE_STATEFUL_PCE_CAPABILITY
,
220 "TLV Stateful PCE Capability");
221 create_subgroup_counter(rx_tlv_subgroup
,
222 PCEP_OBJ_TLV_TYPE_SYMBOLIC_PATH_NAME
,
223 "TLV Symbolic Path Name");
224 create_subgroup_counter(rx_tlv_subgroup
,
225 PCEP_OBJ_TLV_TYPE_IPV4_LSP_IDENTIFIERS
,
226 "TLV IPv4 LSP Identifier");
227 create_subgroup_counter(rx_tlv_subgroup
,
228 PCEP_OBJ_TLV_TYPE_IPV6_LSP_IDENTIFIERS
,
229 "TLV IPv6 LSP Identifier");
230 create_subgroup_counter(rx_tlv_subgroup
,
231 PCEP_OBJ_TLV_TYPE_LSP_ERROR_CODE
,
232 "TLV LSP Error Code");
233 create_subgroup_counter(rx_tlv_subgroup
,
234 PCEP_OBJ_TLV_TYPE_RSVP_ERROR_SPEC
,
235 "TLV RSVP Error Spec");
236 create_subgroup_counter(rx_tlv_subgroup
,
237 PCEP_OBJ_TLV_TYPE_LSP_DB_VERSION
,
238 "TLV LSP DB Version");
239 create_subgroup_counter(rx_tlv_subgroup
,
240 PCEP_OBJ_TLV_TYPE_SPEAKER_ENTITY_ID
,
241 "TLV Speaker Entity ID");
242 create_subgroup_counter(rx_tlv_subgroup
,
243 PCEP_OBJ_TLV_TYPE_SR_PCE_CAPABILITY
,
244 "TLV SR PCE Capability");
245 create_subgroup_counter(rx_tlv_subgroup
,
246 PCEP_OBJ_TLV_TYPE_PATH_SETUP_TYPE
,
247 "TLV Path Setup Type");
248 create_subgroup_counter(rx_tlv_subgroup
,
249 PCEP_OBJ_TLV_TYPE_PATH_SETUP_TYPE_CAPABILITY
,
250 "TLV Path Setup Type Capability");
251 create_subgroup_counter(rx_tlv_subgroup
,
252 PCEP_OBJ_TLV_TYPE_SRPOLICY_POL_ID
,
253 "TLV SR Policy PolId");
254 create_subgroup_counter(rx_tlv_subgroup
,
255 PCEP_OBJ_TLV_TYPE_SRPOLICY_POL_NAME
,
256 "TLV SR Policy PolName");
257 create_subgroup_counter(rx_tlv_subgroup
,
258 PCEP_OBJ_TLV_TYPE_SRPOLICY_CPATH_ID
,
259 "TLV SR Policy CpathId");
260 create_subgroup_counter(rx_tlv_subgroup
,
261 PCEP_OBJ_TLV_TYPE_SRPOLICY_CPATH_PREFERENCE
,
262 "TLV SR Policy CpathRef");
263 create_subgroup_counter(rx_tlv_subgroup
, PCEP_OBJ_TLV_TYPE_UNKNOWN
,
266 struct counters_subgroup
*tx_tlv_subgroup
= clone_counters_subgroup(
267 rx_tlv_subgroup
, "TX TLV counters", COUNTER_SUBGROUP_ID_TX_TLV
);
270 * PCEP Event counters
272 struct counters_subgroup
*events_subgroup
= create_counters_subgroup(
273 "Events counters", COUNTER_SUBGROUP_ID_EVENT
, MAX_COUNTERS
);
274 create_subgroup_counter(events_subgroup
,
275 PCEP_EVENT_COUNTER_ID_PCC_CONNECT
,
277 create_subgroup_counter(events_subgroup
,
278 PCEP_EVENT_COUNTER_ID_PCE_CONNECT
,
280 create_subgroup_counter(events_subgroup
,
281 PCEP_EVENT_COUNTER_ID_PCC_DISCONNECT
,
283 create_subgroup_counter(events_subgroup
,
284 PCEP_EVENT_COUNTER_ID_PCE_DISCONNECT
,
286 create_subgroup_counter(events_subgroup
,
287 PCEP_EVENT_COUNTER_ID_TIMER_KEEPALIVE
,
288 "Timer KeepAlive expired");
289 create_subgroup_counter(events_subgroup
,
290 PCEP_EVENT_COUNTER_ID_TIMER_DEADTIMER
,
291 "Timer DeadTimer expired");
292 create_subgroup_counter(events_subgroup
,
293 PCEP_EVENT_COUNTER_ID_TIMER_OPENKEEPWAIT
,
294 "Timer OpenKeepWait expired");
295 create_subgroup_counter(events_subgroup
,
296 PCEP_EVENT_COUNTER_ID_TIMER_OPENKEEPALIVE
,
297 "Timer OpenKeepAlive expired");
300 * Create the parent counters group
302 time_t now
= time(NULL
);
303 char counters_name
[MAX_COUNTER_STR_LENGTH
] = {0};
304 char ip_str
[40] = {0};
305 if (session
->socket_comm_session
->is_ipv6
) {
307 &session
->socket_comm_session
->dest_sock_addr
308 .dest_sock_addr_ipv6
.sin6_addr
,
312 &session
->socket_comm_session
->dest_sock_addr
313 .dest_sock_addr_ipv4
.sin_addr
,
316 snprintf(counters_name
, MAX_COUNTER_STR_LENGTH
,
317 "PCEP Session [%d], connected to [%s] for [%u seconds]",
318 session
->session_id
, ip_str
,
319 (uint32_t)(now
- session
->time_connected
));
320 /* The (time(NULL) - session->time_connected) will probably be 0,
321 * so the group name will be updated when the counters are dumped */
322 session
->pcep_session_counters
=
323 create_counters_group(counters_name
, MAX_COUNTER_GROUPS
);
326 * Add all the subgroups to the parent counters group
328 add_counters_subgroup(session
->pcep_session_counters
, rx_msg_subgroup
);
329 add_counters_subgroup(session
->pcep_session_counters
, tx_msg_subgroup
);
330 add_counters_subgroup(session
->pcep_session_counters
, rx_obj_subgroup
);
331 add_counters_subgroup(session
->pcep_session_counters
, tx_obj_subgroup
);
332 add_counters_subgroup(session
->pcep_session_counters
,
334 add_counters_subgroup(session
->pcep_session_counters
,
336 add_counters_subgroup(session
->pcep_session_counters
,
337 rx_subobj_sr_nai_subgroup
);
338 add_counters_subgroup(session
->pcep_session_counters
,
339 tx_subobj_sr_nai_subgroup
);
340 add_counters_subgroup(session
->pcep_session_counters
, rx_tlv_subgroup
);
341 add_counters_subgroup(session
->pcep_session_counters
, tx_tlv_subgroup
);
342 add_counters_subgroup(session
->pcep_session_counters
, events_subgroup
);
345 /* Internal util function used by increment_message_rx_counters or
346 * increment_message_tx_counters */
347 void increment_message_counters(pcep_session
*session
,
348 struct pcep_message
*message
, bool is_rx
)
350 uint16_t counter_subgroup_id_msg
= (is_rx
? COUNTER_SUBGROUP_ID_RX_MSG
351 : COUNTER_SUBGROUP_ID_TX_MSG
);
352 uint16_t counter_subgroup_id_obj
= (is_rx
? COUNTER_SUBGROUP_ID_RX_OBJ
353 : COUNTER_SUBGROUP_ID_TX_OBJ
);
354 uint16_t counter_subgroup_id_subobj
=
355 (is_rx
? COUNTER_SUBGROUP_ID_RX_SUBOBJ
356 : COUNTER_SUBGROUP_ID_TX_SUBOBJ
);
357 uint16_t counter_subgroup_id_ro_sr_subobj
=
358 (is_rx
? COUNTER_SUBGROUP_ID_RX_RO_SR_SUBOBJ
359 : COUNTER_SUBGROUP_ID_TX_RO_SR_SUBOBJ
);
360 uint16_t counter_subgroup_id_tlv
= (is_rx
? COUNTER_SUBGROUP_ID_RX_TLV
361 : COUNTER_SUBGROUP_ID_TX_TLV
);
363 increment_counter(session
->pcep_session_counters
,
364 counter_subgroup_id_msg
, message
->msg_header
->type
);
366 /* Iterate the objects */
367 double_linked_list_node
*obj_node
=
368 (message
->obj_list
== NULL
? NULL
: message
->obj_list
->head
);
369 for (; obj_node
!= NULL
; obj_node
= obj_node
->next_node
) {
370 struct pcep_object_header
*obj
=
371 (struct pcep_object_header
*)obj_node
->data
;
373 /* Handle class: PCEP_OBJ_CLASS_ENDPOINTS,
374 * type: PCEP_OBJ_TYPE_ENDPOINT_IPV4 or
375 * PCEP_OBJ_TYPE_ENDPOINT_IPV6 */
376 uint16_t obj_counter_id
=
377 (obj
->object_class
== PCEP_OBJ_CLASS_ENDPOINTS
378 ? (obj
->object_class
<< 4) | obj
->object_type
379 : obj
->object_class
);
381 increment_counter(session
->pcep_session_counters
,
382 counter_subgroup_id_obj
, obj_counter_id
);
384 /* Iterate the RO Sub-objects */
385 if (obj
->object_class
== PCEP_OBJ_CLASS_ERO
386 || obj
->object_class
== PCEP_OBJ_CLASS_IRO
387 || obj
->object_class
== PCEP_OBJ_CLASS_RRO
) {
388 struct pcep_object_ro
*ro_obj
=
389 (struct pcep_object_ro
*)obj
;
391 double_linked_list_node
*ro_subobj_node
=
392 (ro_obj
->sub_objects
== NULL
394 : ro_obj
->sub_objects
->head
);
395 for (; ro_subobj_node
!= NULL
;
396 ro_subobj_node
= ro_subobj_node
->next_node
) {
397 struct pcep_object_ro_subobj
*ro_subobj
=
398 (struct pcep_object_ro_subobj
*)
399 ro_subobj_node
->data
;
401 session
->pcep_session_counters
,
402 counter_subgroup_id_subobj
,
403 ro_subobj
->ro_subobj_type
);
405 /* Handle the ro subobj type RO_SUBOBJ_TYPE_SR
406 * different NAI types */
407 if (ro_subobj
->ro_subobj_type
408 == RO_SUBOBJ_TYPE_SR
) {
409 struct pcep_ro_subobj_sr
*ro_sr_subobj
=
410 (struct pcep_ro_subobj_sr
*)
413 session
->pcep_session_counters
,
414 counter_subgroup_id_ro_sr_subobj
,
415 ro_sr_subobj
->nai_type
);
420 /* Iterate the TLVs */
421 double_linked_list_node
*tlv_node
=
422 (obj
->tlv_list
== NULL
? NULL
: obj
->tlv_list
->head
);
423 for (; tlv_node
!= NULL
; tlv_node
= tlv_node
->next_node
) {
424 struct pcep_object_tlv_header
*tlv
=
425 (struct pcep_object_tlv_header
*)tlv_node
->data
;
426 increment_counter(session
->pcep_session_counters
,
427 counter_subgroup_id_tlv
, tlv
->type
);
432 void increment_message_rx_counters(pcep_session
*session
,
433 struct pcep_message
*message
)
435 increment_message_counters(session
, message
, true);
438 void increment_message_tx_counters(pcep_session
*session
,
439 struct pcep_message
*message
)
441 increment_message_counters(session
, message
, false);
444 void increment_event_counters(
445 pcep_session
*session
,
446 pcep_session_counters_event_counter_ids counter_id
)
448 increment_counter(session
->pcep_session_counters
,
449 COUNTER_SUBGROUP_ID_EVENT
, counter_id
);