]>
Commit | Line | Data |
---|---|---|
74971473 JG |
1 | /* |
2 | * This file is part of the PCEPlib, a PCEP protocol library. | |
3 | * | |
4 | * Copyright (C) 2020 Volta Networks https://voltanet.io/ | |
5 | * | |
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. | |
10 | * | |
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. | |
15 | * | |
16 | * You should have received a copy of the GNU General Public License | |
17 | * along with this program. If not, see <https://www.gnu.org/licenses/>. | |
18 | * | |
19 | * Author : Brady Johnson <brady@voltanet.io> | |
20 | * | |
21 | */ | |
22 | ||
23 | ||
24 | #ifndef INCLUDE_PCEPSESSIONLOGIC_H_ | |
25 | #define INCLUDE_PCEPSESSIONLOGIC_H_ | |
26 | ||
27 | #include <stdbool.h> | |
28 | #include <netinet/tcp.h> | |
29 | ||
30 | #include "pcep_msg_encoding.h" | |
31 | #include "pcep_socket_comm.h" | |
32 | #include "pcep_msg_objects.h" | |
33 | #include "pcep_msg_tools.h" | |
34 | #include "pcep_timers.h" | |
35 | #include "pcep_utils_queue.h" | |
36 | #include "pcep_utils_memory.h" | |
37 | ||
38 | #define PCEP_TCP_PORT 4189 | |
39 | ||
40 | typedef struct pcep_configuration_ { | |
41 | /* These are the configuration values that will | |
42 | * be sent to the PCE in the PCEP Open message */ | |
43 | int keep_alive_seconds; | |
44 | int dead_timer_seconds; | |
45 | int dead_timer_pce_negotiated_seconds; /* Config data negotiated with | |
46 | PCE */ | |
47 | int keep_alive_pce_negotiated_timer_seconds; /* Config data negotiated | |
48 | with PCE */ | |
49 | int request_time_seconds; | |
50 | ||
51 | /* These are the acceptable ranges of values received by | |
52 | * the PCE in the initial PCEP Open Message. If a value is | |
53 | * received outside of these ranges, then the Open message | |
54 | * will be rejected. */ | |
55 | int min_keep_alive_seconds; | |
56 | int max_keep_alive_seconds; | |
57 | int min_dead_timer_seconds; | |
58 | int max_dead_timer_seconds; | |
59 | ||
60 | /* If more than this many unknown messages/requests are received | |
61 | * per minute, then the session will be closed. */ | |
62 | int max_unknown_messages; | |
63 | int max_unknown_requests; | |
64 | ||
65 | /* Maximum amount of time to wait to connect to the | |
66 | * PCE TCP socket before failing, in milliseconds. */ | |
67 | uint32_t socket_connect_timeout_millis; | |
68 | ||
69 | /* Set if the PCE/PCC will support stateful PCE LSP Updates | |
70 | * according to RCF8231, section 7.1.1, defaults to true. | |
71 | * Will cause an additional TLV to be sent from the PCC in | |
72 | * the PCEP Open */ | |
73 | bool support_stateful_pce_lsp_update; | |
74 | ||
75 | /* RFC 8281: I-bit, the PCC allows instantiation of an LSP by a PCE */ | |
76 | bool support_pce_lsp_instantiation; | |
77 | ||
78 | /* RFC 8232: S-bit, the PCC will include the LSP-DB-VERSION | |
79 | * TLV in each LSP object */ | |
80 | bool support_include_db_version; | |
81 | ||
82 | /* Only set if support_include_db_version is true and if the LSP-DB | |
83 | * survived a restart and is available. If this has a value other than | |
84 | * 0, then a LSP-DB-VERSION TLV will be sent in the OPEN object. This | |
85 | * value will be copied over to the pcep_session upon init. */ | |
86 | uint64_t lsp_db_version; | |
87 | ||
88 | /* RFC 8232: T-bit, the PCE can trigger resynchronization of | |
89 | * LSPs at any point in the life of the session */ | |
90 | bool support_lsp_triggered_resync; | |
91 | ||
92 | /* RFC 8232: D-bit, the PCEP speaker allows incremental (delta) | |
93 | * State Synchronization */ | |
94 | bool support_lsp_delta_sync; | |
95 | ||
96 | /* RFC 8232: F-bit, the PCE SHOULD trigger initial (first) | |
97 | * State Synchronization */ | |
98 | bool support_pce_triggered_initial_sync; | |
99 | ||
100 | /* draft-ietf-pce-segment-routing-16: Send a SR PCE Capability | |
101 | * sub-TLV in a Path Setup Type Capability TLV with a PST = 1, | |
102 | * Path is setup using SR TE. */ | |
103 | bool support_sr_te_pst; | |
104 | /* Used in the SR PCE Capability sub-TLV */ | |
105 | bool pcc_can_resolve_nai_to_sid; | |
106 | /* Used in the SR TE Capability sub-TLV, 0 means there are no max sid | |
107 | * limits */ | |
108 | uint8_t max_sid_depth; | |
109 | ||
110 | /* If set to 0, then the default 4189 PCEP port will be used */ | |
111 | uint16_t dst_pcep_port; | |
112 | ||
113 | /* If set to 0, then the default 4189 PCEP port will be used. | |
114 | * This is according to the RFC5440, Section 5 */ | |
115 | uint16_t src_pcep_port; | |
116 | ||
117 | union src_ip { | |
118 | struct in_addr src_ipv4; | |
119 | struct in6_addr src_ipv6; | |
120 | } src_ip; | |
121 | bool is_src_ipv6; | |
122 | ||
123 | struct pcep_versioning *pcep_msg_versioning; | |
124 | ||
2a034138 | 125 | char tcp_authentication_str[PCEP_MD5SIG_MAXKEYLEN]; |
74971473 JG |
126 | bool is_tcp_auth_md5; /* true: RFC 2385, false: RFC 5925 */ |
127 | ||
128 | } pcep_configuration; | |
129 | ||
130 | ||
131 | typedef enum pcep_session_state_ { | |
132 | SESSION_STATE_UNKNOWN = 0, | |
133 | SESSION_STATE_INITIALIZED = 1, | |
134 | SESSION_STATE_PCEP_CONNECTING = 2, | |
135 | SESSION_STATE_PCEP_CONNECTED = 3 | |
136 | ||
137 | } pcep_session_state; | |
138 | ||
139 | ||
140 | typedef struct pcep_session_ { | |
141 | int session_id; | |
142 | pcep_session_state session_state; | |
143 | int timer_id_open_keep_wait; | |
144 | int timer_id_open_keep_alive; | |
145 | int timer_id_dead_timer; | |
146 | int timer_id_keep_alive; | |
147 | bool pce_open_received; | |
148 | bool pce_open_rejected; | |
149 | bool pce_open_accepted; | |
150 | bool pce_open_keep_alive_sent; | |
151 | bool pcc_open_rejected; | |
152 | bool pcc_open_accepted; | |
153 | bool stateful_pce; | |
154 | time_t time_connected; | |
155 | uint64_t lsp_db_version; | |
156 | queue_handle *num_unknown_messages_time_queue; | |
157 | /* set this flag when finalizing the session */ | |
158 | bool destroy_session_after_write; | |
159 | pcep_socket_comm_session *socket_comm_session; | |
160 | /* Configuration sent from the PCC to the PCE */ | |
161 | pcep_configuration pcc_config; | |
162 | /* Configuration received from the PCE, to be used in the PCC */ | |
163 | pcep_configuration pce_config; | |
164 | struct counters_group *pcep_session_counters; | |
165 | ||
166 | } pcep_session; | |
167 | ||
168 | ||
169 | typedef enum pcep_event_type { | |
170 | MESSAGE_RECEIVED = 0, | |
171 | PCE_CLOSED_SOCKET = 1, | |
172 | PCE_SENT_PCEP_CLOSE = 2, | |
173 | PCE_DEAD_TIMER_EXPIRED = 3, | |
174 | PCE_OPEN_KEEP_WAIT_TIMER_EXPIRED = 4, | |
175 | PCC_CONNECTED_TO_PCE = 100, | |
176 | PCC_CONNECTION_FAILURE = 101, | |
177 | PCC_PCEP_SESSION_CLOSED = 102, | |
178 | PCC_RCVD_INVALID_OPEN = 103, | |
179 | PCC_SENT_INVALID_OPEN = 104, | |
180 | PCC_RCVD_MAX_INVALID_MSGS = 105, | |
181 | PCC_RCVD_MAX_UNKOWN_MSGS = 106 | |
182 | ||
183 | } pcep_event_type; | |
184 | ||
185 | ||
186 | typedef struct pcep_event { | |
187 | enum pcep_event_type event_type; | |
188 | time_t event_time; | |
189 | struct pcep_message *message; | |
190 | pcep_session *session; | |
191 | ||
192 | } pcep_event; | |
193 | ||
194 | typedef void (*pceplib_pcep_event_callback)(void *cb_data, pcep_event *); | |
195 | typedef int (*pthread_create_callback)(pthread_t *pthread_id, | |
196 | const pthread_attr_t *attr, | |
197 | void *(*start_routine)(void *), | |
198 | void *data, const char *thread_name); | |
199 | ||
200 | ||
201 | typedef struct pcep_event_queue { | |
202 | /* The event_queue and event_callback are mutually exclusive. | |
203 | * If the event_callback is configured, then the event_queue | |
204 | * will not be used. */ | |
205 | queue_handle *event_queue; | |
206 | pthread_mutex_t event_queue_mutex; | |
207 | pceplib_pcep_event_callback event_callback; | |
208 | void *event_callback_data; | |
209 | ||
210 | } pcep_event_queue; | |
211 | ||
212 | ||
213 | typedef struct pceplib_infra_config { | |
214 | /* Memory infrastructure */ | |
215 | void *pceplib_infra_mt; | |
216 | void *pceplib_messages_mt; | |
217 | pceplib_malloc_func malloc_func; | |
218 | pceplib_calloc_func calloc_func; | |
219 | pceplib_realloc_func realloc_func; | |
220 | pceplib_strdup_func strdup_func; | |
221 | pceplib_free_func free_func; | |
222 | ||
223 | /* External Timer and Socket infrastructure */ | |
224 | void *external_infra_data; | |
225 | ext_timer_create timer_create_func; | |
226 | ext_timer_cancel timer_cancel_func; | |
227 | ext_socket_write socket_write_func; | |
228 | ext_socket_read socket_read_func; | |
229 | ||
230 | /* External pcep_event infrastructure */ | |
231 | pceplib_pcep_event_callback pcep_event_func; | |
232 | ||
233 | /* Callback to create pthreads */ | |
234 | pthread_create_callback pthread_create_func; | |
235 | ||
236 | } pceplib_infra_config; | |
237 | ||
238 | /* | |
239 | * Counters Sub-groups definitions | |
240 | */ | |
241 | typedef enum pcep_session_counters_subgroup_ids { | |
242 | COUNTER_SUBGROUP_ID_RX_MSG = 0, | |
243 | COUNTER_SUBGROUP_ID_TX_MSG = 1, | |
244 | COUNTER_SUBGROUP_ID_RX_OBJ = 2, | |
245 | COUNTER_SUBGROUP_ID_TX_OBJ = 3, | |
246 | COUNTER_SUBGROUP_ID_RX_SUBOBJ = 4, | |
247 | COUNTER_SUBGROUP_ID_TX_SUBOBJ = 5, | |
248 | COUNTER_SUBGROUP_ID_RX_RO_SR_SUBOBJ = 6, | |
249 | COUNTER_SUBGROUP_ID_TX_RO_SR_SUBOBJ = 7, | |
250 | COUNTER_SUBGROUP_ID_RX_TLV = 8, | |
251 | COUNTER_SUBGROUP_ID_TX_TLV = 9, | |
252 | COUNTER_SUBGROUP_ID_EVENT = 10 | |
253 | ||
254 | } pcep_session_counters_subgroup_ids; | |
255 | ||
256 | bool run_session_logic(void); | |
257 | bool run_session_logic_with_infra(pceplib_infra_config *infra_config); | |
258 | ||
259 | bool run_session_logic_wait_for_completion(void); | |
260 | ||
261 | bool stop_session_logic(void); | |
262 | ||
263 | /* Uses the standard PCEP TCP dest port = 4189 and an ephemeral src port. | |
264 | * To use a specific dest or src port, set them other than 0 in the | |
265 | * pcep_configuration. */ | |
266 | pcep_session *create_pcep_session(pcep_configuration *config, | |
267 | struct in_addr *pce_ip); | |
268 | pcep_session *create_pcep_session_ipv6(pcep_configuration *config, | |
269 | struct in6_addr *pce_ip); | |
270 | ||
271 | /* Send a PCEP close for this pcep_session */ | |
272 | void close_pcep_session(pcep_session *session); | |
273 | void close_pcep_session_with_reason(pcep_session *session, | |
274 | enum pcep_close_reason); | |
275 | ||
276 | /* Destroy the PCEP session, a PCEP close should have | |
277 | * already been sent with close_pcep_session() */ | |
278 | void destroy_pcep_session(pcep_session *session); | |
279 | ||
280 | void pcep_session_cancel_timers(pcep_session *session); | |
281 | ||
282 | /* Increments transmitted message counters, additionally counters for the | |
283 | * objects, sub-objects, and TLVs in the message will be incremented. Received | |
284 | * counters are incremented internally. */ | |
285 | void increment_message_tx_counters(pcep_session *session, | |
286 | struct pcep_message *message); | |
287 | ||
288 | bool session_exists(pcep_session *session); | |
289 | ||
290 | #endif /* INCLUDE_PCEPSESSIONLOGIC_H_ */ |