]> git.proxmox.com Git - mirror_frr.git/blame - pceplib/pcep_pcc_api.c
Merge pull request #12830 from anlancs/fix/doc-ripd-rst
[mirror_frr.git] / pceplib / pcep_pcc_api.c
CommitLineData
acddc0ed 1// SPDX-License-Identifier: LGPL-2.1-or-later
74971473
JG
2/*
3 * This file is part of the PCEPlib, a PCEP protocol library.
4 *
5 * Copyright (C) 2020 Volta Networks https://voltanet.io/
6 *
74971473
JG
7 * Author : Brady Johnson <brady@voltanet.io>
8 *
9 */
10
11
12/*
13 * Public PCEPlib PCC API implementation
14 */
15
16#include <zebra.h>
17
18#include <pthread.h>
19#include <stdbool.h>
20#include <stdio.h>
21#include <string.h>
22
23#include "pcep_msg_messages.h"
24#include "pcep_pcc_api.h"
25#include "pcep_utils_counters.h"
26#include "pcep_utils_logging.h"
27
28/* Not using an array here since the enum pcep_event_type indeces go into the
29 * 100's */
30const char MESSAGE_RECEIVED_STR[] = "MESSAGE_RECEIVED";
31const char PCE_CLOSED_SOCKET_STR[] = "PCE_CLOSED_SOCKET";
32const char PCE_SENT_PCEP_CLOSE_STR[] = "PCE_SENT_PCEP_CLOSE";
33const char PCE_DEAD_TIMER_EXPIRED_STR[] = "PCE_DEAD_TIMER_EXPIRED";
34const char PCE_OPEN_KEEP_WAIT_TIMER_EXPIRED_STR[] =
35 "PCE_OPEN_KEEP_WAIT_TIMER_EXPIRED";
36const char PCC_CONNECTED_TO_PCE_STR[] = "PCC_CONNECTED_TO_PCE";
37const char PCC_PCEP_SESSION_CLOSED_STR[] = "PCC_PCEP_SESSION_CLOSED";
38const char PCC_RCVD_INVALID_OPEN_STR[] = "PCC_RCVD_INVALID_OPEN";
39const char PCC_RCVD_MAX_INVALID_MSGS_STR[] = "PCC_RCVD_MAX_INVALID_MSGS";
40const char PCC_RCVD_MAX_UNKOWN_MSGS_STR[] = "PCC_RCVD_MAX_UNKOWN_MSGS";
41const char UNKNOWN_EVENT_STR[] = "UNKNOWN Event Type";
42
43/* Session Logic Handle managed in pcep_session_logic.c */
44extern pcep_event_queue *session_logic_event_queue_;
45
2816045a 46bool initialize_pcc(void)
74971473
JG
47{
48 if (!run_session_logic()) {
49 pcep_log(LOG_ERR, "%s: Error initializing PCC session logic.",
50 __func__);
51 return false;
52 }
53
54 return true;
55}
56
57
58bool initialize_pcc_infra(struct pceplib_infra_config *infra_config)
59{
60 if (infra_config == NULL) {
61 return initialize_pcc();
62 }
63
64 if (!run_session_logic_with_infra(infra_config)) {
65 pcep_log(LOG_ERR,
66 "%s: Error initializing PCC session logic with infra.",
67 __func__);
68 return false;
69 }
70
71 return true;
72}
73
74
75/* this function is blocking */
2816045a 76bool initialize_pcc_wait_for_completion(void)
74971473
JG
77{
78 return run_session_logic_wait_for_completion();
79}
80
81
2816045a 82bool destroy_pcc(void)
74971473
JG
83{
84 if (!stop_session_logic()) {
85 pcep_log(LOG_WARNING, "%s: Error stopping PCC session logic.",
86 __func__);
87 return false;
88 }
89
90 return true;
91}
92
93
2816045a 94pcep_configuration *create_default_pcep_configuration(void)
74971473
JG
95{
96 pcep_configuration *config =
97 pceplib_malloc(PCEPLIB_INFRA, sizeof(pcep_configuration));
98 memset(config, 0, sizeof(pcep_configuration));
99
100 config->keep_alive_seconds = DEFAULT_CONFIG_KEEP_ALIVE;
101 /* This value will possibly be overwritten later with PCE config data */
102 config->keep_alive_pce_negotiated_timer_seconds =
103 DEFAULT_CONFIG_KEEP_ALIVE;
104 config->min_keep_alive_seconds = DEFAULT_MIN_CONFIG_KEEP_ALIVE;
105 config->max_keep_alive_seconds = DEFAULT_MAX_CONFIG_KEEP_ALIVE;
106
107 config->dead_timer_seconds = DEFAULT_CONFIG_DEAD_TIMER;
108 /* This value will be overwritten later with PCE config data */
109 config->dead_timer_pce_negotiated_seconds = DEFAULT_CONFIG_DEAD_TIMER;
110 config->min_dead_timer_seconds = DEFAULT_MIN_CONFIG_DEAD_TIMER;
111 config->max_dead_timer_seconds = DEFAULT_MAX_CONFIG_DEAD_TIMER;
112
113 config->request_time_seconds = DEFAULT_CONFIG_REQUEST_TIME;
114 config->max_unknown_messages = DEFAULT_CONFIG_MAX_UNKNOWN_MESSAGES;
115 config->max_unknown_requests = DEFAULT_CONFIG_MAX_UNKNOWN_REQUESTS;
116
117 config->socket_connect_timeout_millis =
118 DEFAULT_TCP_CONNECT_TIMEOUT_MILLIS;
119 config->support_stateful_pce_lsp_update = true;
120 config->support_pce_lsp_instantiation = true;
121 config->support_include_db_version = true;
122 config->lsp_db_version = 0;
123 config->support_lsp_triggered_resync = true;
124 config->support_lsp_delta_sync = true;
125 config->support_pce_triggered_initial_sync = true;
126 config->support_sr_te_pst = true;
127 config->pcc_can_resolve_nai_to_sid = true;
128 config->max_sid_depth = 0;
129 config->dst_pcep_port = 0;
130 config->src_pcep_port = 0;
131 config->src_ip.src_ipv4.s_addr = INADDR_ANY;
132 config->is_src_ipv6 = false;
133 config->pcep_msg_versioning = create_default_pcep_versioning();
134 config->tcp_authentication_str[0] = '\0';
135 config->is_tcp_auth_md5 = true;
136
137 return config;
138}
139
140void destroy_pcep_configuration(pcep_configuration *config)
141{
142 destroy_pcep_versioning(config->pcep_msg_versioning);
143 pceplib_free(PCEPLIB_INFRA, config);
144}
145
146pcep_session *connect_pce(pcep_configuration *config, struct in_addr *pce_ip)
147{
148 return create_pcep_session(config, pce_ip);
149}
150
151pcep_session *connect_pce_ipv6(pcep_configuration *config,
152 struct in6_addr *pce_ip)
153{
154 return create_pcep_session_ipv6(config, pce_ip);
155}
156
157void disconnect_pce(pcep_session *session)
158{
159 if (session_exists(session) == false) {
160 pcep_log(
161 LOG_WARNING,
162 "%s: disconnect_pce session [%p] has already been deleted",
163 __func__, session);
164 return;
165 }
166
167 if (session->socket_comm_session == NULL
168 || session->socket_comm_session->socket_fd < 0) {
169 /* If the socket has already been closed, just destroy the
170 * session */
171 destroy_pcep_session(session);
172 } else {
173 /* This will cause the session to be destroyed AFTER the close
174 * message is sent */
175 session->destroy_session_after_write = true;
176
177 /* Send a PCEP close message */
178 close_pcep_session(session);
179 }
180}
181
182void send_message(pcep_session *session, struct pcep_message *msg,
183 bool free_after_send)
184{
185 if (session == NULL || msg == NULL) {
186 pcep_log(LOG_DEBUG,
187 "%s: send_message NULL params session [%p] msg [%p]",
188 __func__, session, msg);
189
190 return;
191 }
192
193 if (session_exists(session) == false) {
194 pcep_log(
195 LOG_WARNING,
196 "%s: send_message session [%p] has already been deleted",
197 __func__, session);
198 return;
199 }
200
201 pcep_encode_message(msg, session->pcc_config.pcep_msg_versioning);
202 socket_comm_session_send_message(
203 session->socket_comm_session, (char *)msg->encoded_message,
204 msg->encoded_message_length, free_after_send);
205
206 increment_message_tx_counters(session, msg);
207
208 if (free_after_send == true) {
209 /* The encoded_message will be deleted once sent, so everything
210 * else in the message will be freed */
211 msg->encoded_message = NULL;
212 pcep_msg_free_message(msg);
213 }
214}
215
216/* Returns true if the queue is empty, false otherwise */
2816045a 217bool event_queue_is_empty(void)
74971473
JG
218{
219 if (session_logic_event_queue_ == NULL) {
220 pcep_log(
221 LOG_WARNING,
222 "%s: event_queue_is_empty Session Logic is not initialized yet",
223 __func__);
224 return false;
225 }
226
227 pthread_mutex_lock(&session_logic_event_queue_->event_queue_mutex);
228 bool is_empty =
229 (session_logic_event_queue_->event_queue->num_entries == 0);
230 pthread_mutex_unlock(&session_logic_event_queue_->event_queue_mutex);
231
232 return is_empty;
233}
234
235
236/* Return the number of events on the queue, 0 if empty */
2816045a 237uint32_t event_queue_num_events_available(void)
74971473
JG
238{
239 if (session_logic_event_queue_ == NULL) {
240 pcep_log(
241 LOG_WARNING,
242 "%s: event_queue_num_events_available Session Logic is not initialized yet",
243 __func__);
244 return 0;
245 }
246
247 pthread_mutex_lock(&session_logic_event_queue_->event_queue_mutex);
248 uint32_t num_events =
249 session_logic_event_queue_->event_queue->num_entries;
250 pthread_mutex_unlock(&session_logic_event_queue_->event_queue_mutex);
251
252 return num_events;
253}
254
255
256/* Return the next event on the queue, NULL if empty */
2816045a 257struct pcep_event *event_queue_get_event(void)
74971473
JG
258{
259 if (session_logic_event_queue_ == NULL) {
260 pcep_log(
261 LOG_WARNING,
262 "%s: event_queue_get_event Session Logic is not initialized yet",
263 __func__);
264 return NULL;
265 }
266
267 pthread_mutex_lock(&session_logic_event_queue_->event_queue_mutex);
268 struct pcep_event *event = (struct pcep_event *)queue_dequeue(
269 session_logic_event_queue_->event_queue);
270 pthread_mutex_unlock(&session_logic_event_queue_->event_queue_mutex);
271
272 return event;
273}
274
275
276/* Free the PCEP Event resources, including the PCEP message */
277void destroy_pcep_event(struct pcep_event *event)
278{
279 if (event == NULL) {
280 pcep_log(LOG_WARNING,
281 "%s: destroy_pcep_event cannot destroy NULL event",
282 __func__);
283 return;
284 }
285
286 if (event->event_type == MESSAGE_RECEIVED && event->message != NULL) {
287 pcep_msg_free_message(event->message);
288 }
289
290 pceplib_free(PCEPLIB_INFRA, event);
291}
292
293const char *get_event_type_str(int event_type)
294{
295 switch (event_type) {
296 case MESSAGE_RECEIVED:
297 return MESSAGE_RECEIVED_STR;
298 break;
299 case PCE_CLOSED_SOCKET:
300 return PCE_CLOSED_SOCKET_STR;
301 break;
302 case PCE_SENT_PCEP_CLOSE:
303 return PCE_SENT_PCEP_CLOSE_STR;
304 break;
305 case PCE_DEAD_TIMER_EXPIRED:
306 return PCE_DEAD_TIMER_EXPIRED_STR;
307 break;
308 case PCE_OPEN_KEEP_WAIT_TIMER_EXPIRED:
309 return PCE_OPEN_KEEP_WAIT_TIMER_EXPIRED_STR;
310 break;
311 case PCC_CONNECTED_TO_PCE:
312 return PCC_CONNECTED_TO_PCE_STR;
313 break;
314 case PCC_PCEP_SESSION_CLOSED:
315 return PCC_PCEP_SESSION_CLOSED_STR;
316 break;
317 case PCC_RCVD_INVALID_OPEN:
318 return PCC_RCVD_INVALID_OPEN_STR;
319 break;
320 case PCC_RCVD_MAX_INVALID_MSGS:
321 return PCC_RCVD_MAX_INVALID_MSGS_STR;
322 break;
323 case PCC_RCVD_MAX_UNKOWN_MSGS:
324 return PCC_RCVD_MAX_UNKOWN_MSGS_STR;
325 break;
326 default:
327 return UNKNOWN_EVENT_STR;
328 break;
329 }
330}
331
332void dump_pcep_session_counters(pcep_session *session)
333{
334 if (session_exists(session) == false) {
335 pcep_log(
336 LOG_WARNING,
337 "%s: dump_pcep_session_counters session [%p] has already been deleted",
338 __func__, session);
339 return;
340 }
341
342 /* Update the counters group name so that the PCE session connected time
343 * is accurate */
344 time_t now = time(NULL);
345 char counters_name[MAX_COUNTER_STR_LENGTH] = {0};
346 char ip_str[40] = {0};
347 if (session->socket_comm_session->is_ipv6) {
348 inet_ntop(AF_INET6,
349 &session->socket_comm_session->dest_sock_addr
350 .dest_sock_addr_ipv6.sin6_addr,
351 ip_str, 40);
352 } else {
353 inet_ntop(AF_INET,
354 &session->socket_comm_session->dest_sock_addr
355 .dest_sock_addr_ipv4.sin_addr,
356 ip_str, 40);
357 }
358 snprintf(counters_name, MAX_COUNTER_STR_LENGTH,
359 "PCEP Session [%d], connected to [%s] for [%u seconds]",
360 session->session_id, ip_str,
361 (uint32_t)(now - session->time_connected));
362 strlcpy(session->pcep_session_counters->counters_group_name,
363 counters_name,
364 sizeof(session->pcep_session_counters->counters_group_name));
365
366 dump_counters_group_to_log(session->pcep_session_counters);
367}
368
369void reset_pcep_session_counters(pcep_session *session)
370{
371 if (session_exists(session) == false) {
372 pcep_log(
373 LOG_WARNING,
374 "%s: reset_pcep_session_counters session [%p] has already been deleted",
375 session);
376 return;
377 }
378
379 reset_group_counters(session->pcep_session_counters);
380}