]>
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 Lesser 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 | * This is a High Level PCEP message object API. | |
25 | */ | |
26 | ||
27 | #ifndef PCEP_OBJECTS_H | |
28 | #define PCEP_OBJECTS_H | |
29 | ||
30 | #include <stdbool.h> | |
31 | #include <stdint.h> | |
32 | ||
33 | #include "pcep.h" | |
34 | #include "pcep_utils_double_linked_list.h" | |
35 | #include "pcep_msg_object_error_types.h" | |
36 | #include "pcep_msg_tlvs.h" | |
37 | ||
38 | #ifdef __cplusplus | |
39 | extern "C" { | |
40 | #endif | |
41 | ||
42 | /* | |
43 | * Regarding memory usage: | |
44 | * When creating objects, any objects passed into these APIs will be free'd when | |
45 | * the enclosing pcep_message is free'd. That includes the double_linked_list's. | |
46 | * So, just create the objects and TLVs, put them in their double_linked_list's, | |
47 | * and everything will be managed internally. The enclosing message will be | |
48 | * deleted by pcep_msg_free_message() or pcep_msg_free_message_list() which, | |
49 | * in turn will call one of: pcep_obj_free_object() and pcep_obj_free_tlv(). | |
50 | * For received messages with objects, call pcep_msg_free_message() to free | |
51 | * them. | |
52 | */ | |
53 | ||
54 | enum pcep_object_classes { | |
55 | PCEP_OBJ_CLASS_OPEN = 1, | |
56 | PCEP_OBJ_CLASS_RP = 2, | |
57 | PCEP_OBJ_CLASS_NOPATH = 3, | |
58 | PCEP_OBJ_CLASS_ENDPOINTS = 4, | |
59 | PCEP_OBJ_CLASS_BANDWIDTH = 5, | |
60 | PCEP_OBJ_CLASS_METRIC = 6, | |
61 | PCEP_OBJ_CLASS_ERO = 7, | |
62 | PCEP_OBJ_CLASS_RRO = 8, | |
63 | PCEP_OBJ_CLASS_LSPA = 9, | |
64 | PCEP_OBJ_CLASS_IRO = 10, | |
65 | PCEP_OBJ_CLASS_SVEC = 11, | |
66 | PCEP_OBJ_CLASS_NOTF = 12, | |
67 | PCEP_OBJ_CLASS_ERROR = 13, | |
68 | PCEP_OBJ_CLASS_CLOSE = 15, | |
69 | PCEP_OBJ_CLASS_OF = 21, | |
70 | PCEP_OBJ_CLASS_LSP = 32, | |
71 | PCEP_OBJ_CLASS_SRP = 33, | |
72 | PCEP_OBJ_CLASS_VENDOR_INFO = 34, | |
73 | PCEP_OBJ_CLASS_INTER_LAYER = 36, /* RFC 8282 */ | |
74 | PCEP_OBJ_CLASS_SWITCH_LAYER = 37, /* RFC 8282 */ | |
75 | PCEP_OBJ_CLASS_REQ_ADAP_CAP = 38, /* RFC 8282 */ | |
76 | PCEP_OBJ_CLASS_SERVER_IND = 39, /* RFC 8282 */ | |
77 | PCEP_OBJ_CLASS_ASSOCIATION = 40, /*draft-ietf-pce-association-group-10*/ | |
78 | PCEP_OBJ_CLASS_MAX, | |
79 | }; | |
80 | ||
81 | enum pcep_object_types { | |
82 | PCEP_OBJ_TYPE_OPEN = 1, | |
83 | PCEP_OBJ_TYPE_RP = 1, | |
84 | PCEP_OBJ_TYPE_NOPATH = 1, | |
85 | PCEP_OBJ_TYPE_ENDPOINT_IPV4 = 1, | |
86 | PCEP_OBJ_TYPE_ENDPOINT_IPV6 = 2, | |
87 | PCEP_OBJ_TYPE_BANDWIDTH_REQ = 1, | |
88 | PCEP_OBJ_TYPE_BANDWIDTH_TELSP = 2, | |
89 | PCEP_OBJ_TYPE_BANDWIDTH_CISCO = | |
90 | 5, /* IANA unassigned, but rcvd from Cisco PCE */ | |
91 | PCEP_OBJ_TYPE_SRP = 1, | |
92 | PCEP_OBJ_TYPE_VENDOR_INFO = 1, | |
93 | PCEP_OBJ_TYPE_LSP = 1, | |
94 | PCEP_OBJ_TYPE_METRIC = 1, | |
95 | PCEP_OBJ_TYPE_ERO = 1, | |
96 | PCEP_OBJ_TYPE_RRO = 1, | |
97 | PCEP_OBJ_TYPE_LSPA = 1, | |
98 | PCEP_OBJ_TYPE_IRO = 1, | |
99 | PCEP_OBJ_TYPE_SVEC = 1, | |
100 | PCEP_OBJ_TYPE_NOTF = 1, | |
101 | PCEP_OBJ_TYPE_ERROR = 1, | |
102 | PCEP_OBJ_TYPE_CLOSE = 1, | |
103 | PCEP_OBJ_TYPE_INTER_LAYER = 1, | |
104 | PCEP_OBJ_TYPE_SWITCH_LAYER = 1, | |
105 | PCEP_OBJ_TYPE_REQ_ADAP_CAP = 1, | |
106 | PCEP_OBJ_TYPE_SERVER_IND = 1, | |
107 | PCEP_OBJ_TYPE_ASSOCIATION_IPV4 = | |
108 | 1, /*draft-ietf-pce-association-group-10*/ | |
109 | PCEP_OBJ_TYPE_ASSOCIATION_IPV6 = | |
110 | 2, /*draft-ietf-pce-association-group-10*/ | |
111 | PCEP_OBJ_TYPE_OF = 1, | |
112 | PCEP_OBJ_TYPE_MAX = 2, | |
113 | }; | |
114 | ||
115 | #define OBJECT_HEADER_FLAG_I 0x01 | |
116 | #define OBJECT_HEADER_FLAG_P 0x02 | |
117 | ||
118 | /* The flag_p and flag_i arent set via the APIs, if they need to be set, just | |
119 | * set them on the returned object once it has been created. */ | |
120 | struct pcep_object_header { | |
121 | enum pcep_object_classes object_class; | |
122 | enum pcep_object_types object_type; | |
123 | bool flag_p; /* PCC Processing rule bit: When set, the object MUST be | |
124 | taken into account, when cleared the object is optional. | |
125 | */ | |
126 | bool flag_i; /* PCE Ignore bit: indicates to a PCC whether or not an | |
127 | optional object was processed */ | |
128 | double_linked_list *tlv_list; | |
129 | /* Pointer into encoded_message field from the pcep_message */ | |
130 | const uint8_t *encoded_object; | |
131 | uint16_t encoded_object_length; | |
132 | }; | |
133 | ||
134 | #define PCEP_OBJECT_OPEN_VERSION 1 | |
135 | ||
136 | struct pcep_object_open { | |
137 | struct pcep_object_header header; | |
138 | uint8_t open_version; /* PCEP version. Current version is 1 */ | |
139 | uint8_t open_keepalive; /* Maximum period of time between two | |
140 | consecutive PCEP messages sent by the sender. | |
141 | */ | |
142 | uint8_t open_deadtimer; /* Specifies the amount of time before closing | |
143 | the session down. */ | |
144 | uint8_t open_sid; /* PCEP session number that identifies the current | |
145 | session. */ | |
146 | }; | |
147 | ||
148 | #define OBJECT_RP_FLAG_R 0x08 | |
149 | #define OBJECT_RP_FLAG_B 0x10 | |
150 | #define OBJECT_RP_FLAG_O 0x20 | |
151 | #define OBJECT_RP_FLAG_OF 0x80 | |
152 | #define OBJECT_RP_MAX_PRIORITY 0x07 | |
153 | ||
154 | struct pcep_object_rp { | |
155 | struct pcep_object_header header; | |
156 | uint8_t priority; /* 3 bit priority, max priority is 7 */ | |
157 | bool flag_reoptimization; | |
158 | bool flag_bidirectional; | |
159 | bool flag_strict; /* when set, a loose path is acceptable */ | |
160 | bool flag_of; /* Supply Objective Function on Response */ | |
161 | uint32_t request_id; /* The Request-id-number value combined with the | |
162 | source for PCC & PCE creates a uniquely number. | |
163 | */ | |
164 | }; | |
165 | ||
166 | enum pcep_notification_types { | |
167 | PCEP_NOTIFY_TYPE_PENDING_REQUEST_CANCELLED = 1, | |
168 | PCEP_NOTIFY_TYPE_PCE_OVERLOADED = 2 | |
169 | }; | |
170 | ||
171 | enum pcep_notification_values { | |
172 | PCEP_NOTIFY_VALUE_PCC_CANCELLED_REQUEST = 1, | |
173 | PCEP_NOTIFY_VALUE_PCE_CANCELLED_REQUEST = 2, | |
174 | PCEP_NOTIFY_VALUE_PCE_CURRENTLY_OVERLOADED = 1, | |
175 | PCEP_NOTIFY_VALUE_PCE_NO_LONGER_OVERLOADED = 2 | |
176 | }; | |
177 | ||
178 | struct pcep_object_notify { | |
179 | struct pcep_object_header header; | |
180 | enum pcep_notification_types notification_type; | |
181 | enum pcep_notification_values notification_value; | |
182 | }; | |
183 | ||
184 | enum pcep_association_type { | |
185 | PCEP_ASSOCIATION_TYPE_PATH_PROTECTION_ASSOCIATION = | |
186 | 1, // iana unique value define as 2020-01-08! | |
187 | PCEP_ASSOCIATION_TYPE_SR_POLICY_ASSOCIATION_TYPE = | |
188 | 65535 // TBD1 draft-barth-pce-segment-routing-policy-cp-04 | |
189 | }; | |
190 | #define OBJECT_ASSOCIATION_FLAG_R 0x01 | |
191 | struct pcep_object_association_ipv4 { // draft-ietf-pce-association-group-10 | |
192 | struct pcep_object_header header; | |
193 | bool R_flag; | |
194 | uint16_t association_type; | |
195 | uint16_t association_id; | |
196 | struct in_addr src; | |
197 | }; | |
198 | ||
199 | struct pcep_object_association_ipv6 { // draft-ietf-pce-association-group-10 | |
200 | struct pcep_object_header header; | |
201 | bool R_flag; | |
202 | uint16_t association_type; | |
203 | uint16_t association_id; | |
204 | struct in6_addr src; | |
205 | }; | |
206 | ||
207 | ||
208 | enum pcep_nopath_nature_of_issue { | |
209 | PCEP_NOPATH_NI_NO_PATH_FOUND = 0, | |
210 | PCEP_NOPATH_NI_PCE_CHAIN_BROKEN = 1, | |
211 | }; | |
212 | ||
213 | enum pcep_nopath_tlv_err_codes { | |
214 | PCEP_NOPATH_TLV_ERR_NO_TLV = 0, | |
215 | PCEP_NOPATH_TLV_ERR_PCE_UNAVAILABLE = 1, | |
216 | PCEP_NOPATH_TLV_ERR_UNKNOWN_DST = 2, | |
217 | PCEP_NOPATH_TLV_ERR_UNKNOWN_SRC = 3 | |
218 | }; | |
219 | ||
220 | #define OBJECT_NOPATH_FLAG_C 0x80 | |
221 | ||
222 | struct pcep_object_nopath { | |
223 | struct pcep_object_header header; | |
224 | uint8_t ni; /* Nature of Issue, reports the nature of the issue that led | |
225 | to a negative reply */ | |
226 | bool flag_c; /* when set, indicates the unsatisfied constraints by | |
227 | including relevant PCEP objects. */ | |
228 | enum pcep_nopath_tlv_err_codes | |
229 | err_code; /* When set other than 0, an appropriate TLV will be | |
230 | included */ | |
231 | }; | |
232 | ||
233 | struct pcep_object_endpoints_ipv4 { | |
234 | struct pcep_object_header header; | |
235 | struct in_addr src_ipv4; | |
236 | struct in_addr dst_ipv4; | |
237 | }; | |
238 | ||
239 | struct pcep_object_endpoints_ipv6 { | |
240 | struct pcep_object_header header; | |
241 | struct in6_addr src_ipv6; | |
242 | struct in6_addr dst_ipv6; | |
243 | }; | |
244 | ||
245 | /* PCEP floats are encoded according to: | |
246 | * https://en.wikipedia.org/wiki/IEEE_754-1985 | |
247 | * Luckily, this is the same encoding used by C */ | |
248 | struct pcep_object_bandwidth { | |
249 | struct pcep_object_header header; | |
250 | float bandwidth; | |
251 | }; | |
252 | ||
253 | enum pcep_metric_types { | |
254 | /* RFC 5440 */ | |
255 | PCEP_METRIC_IGP = 1, | |
256 | PCEP_METRIC_TE = 2, | |
257 | PCEP_METRIC_HOP_COUNT = 3, | |
258 | /* RFC 5541 */ | |
259 | PCEP_METRIC_AGGREGATE_BW = 4, | |
260 | PCEP_METRIC_MOST_LOADED_LINK = 5, | |
261 | PCEP_METRIC_CUMULATIVE_IGP = 6, | |
262 | PCEP_METRIC_CUMULATIVE_TE = 7, | |
263 | /* RFC 8306 */ | |
264 | PCEP_METRIC_P2MP_IGP = 8, | |
265 | PCEP_METRIC_P2MP_TE = 9, | |
266 | PCEP_METRIC_P2MP_HOP_COUNT = 10, | |
267 | /* RFC 8864 */ | |
268 | PCEP_METRIC_SEGMENT_ID_DEPTH = 11, | |
269 | /* RFC 8233 */ | |
270 | PCEP_METRIC_PATH_DELAY = 12, | |
271 | PCEP_METRIC_PATH_DELAY_VARIATION = 13, | |
272 | PCEP_METRIC_PATH_LOSS = 14, | |
273 | PCEP_METRIC_P2MP_PATH_DELAY = 15, | |
274 | PCEP_METRIC_P2MP_PATH_DELAY_VARIATION = 16, | |
275 | PCEP_METRIC_P2MP_PATH_LOSS = 17, | |
276 | /* RFC 8282 */ | |
277 | PCEP_METRIC_NUM_PATH_ADAPTATIONS = 18, | |
278 | PCEP_METRIC_NUM_PATH_LAYERS = 19, | |
279 | /* RFC 8685 */ | |
280 | PCEP_METRIC_DOMAIN_COUNT = 20, | |
281 | PCEP_METRIC_BORDER_NODE_COUNT = 21, | |
282 | }; | |
283 | ||
284 | #define OBJECT_METRIC_FLAC_B 0x01 | |
285 | #define OBJECT_METRIC_FLAC_C 0x02 | |
286 | ||
287 | /* PCEP floats are encoded according to: | |
288 | * https://en.wikipedia.org/wiki/IEEE_754-1985 | |
289 | * Luckily, this is the same encoding used by C */ | |
290 | struct pcep_object_metric { | |
291 | struct pcep_object_header header; | |
292 | enum pcep_metric_types type; | |
293 | bool flag_b; /* Bound flag */ | |
294 | bool flag_c; /* Computed metric */ | |
295 | float value; /* Metric value in 32 bits */ | |
296 | }; | |
297 | ||
298 | #define OBJECT_LSPA_FLAG_L 0x01 | |
299 | ||
300 | struct pcep_object_lspa { | |
301 | struct pcep_object_header header; | |
302 | uint32_t lspa_exclude_any; | |
303 | uint32_t lspa_include_any; | |
304 | uint32_t lspa_include_all; | |
305 | uint8_t setup_priority; | |
306 | uint8_t holding_priority; | |
307 | bool flag_local_protection; /* Local protection desired bit */ | |
308 | }; | |
309 | ||
310 | /* The SVEC object with some custom extensions. */ | |
311 | #define OBJECT_SVEC_FLAG_L 0x01 | |
312 | #define OBJECT_SVEC_FLAG_N 0x02 | |
313 | #define OBJECT_SVEC_FLAG_S 0x04 | |
314 | ||
315 | struct pcep_object_svec { | |
316 | struct pcep_object_header header; | |
317 | bool flag_link_diverse; | |
318 | bool flag_node_diverse; | |
319 | bool flag_srlg_diverse; | |
320 | double_linked_list | |
321 | *request_id_list; /* list of 32-bit request ID pointers */ | |
322 | }; | |
323 | ||
324 | struct pcep_object_error { | |
325 | struct pcep_object_header header; | |
326 | enum pcep_error_type error_type; | |
327 | enum pcep_error_value error_value; | |
328 | }; | |
329 | ||
330 | struct pcep_object_load_balancing { | |
331 | struct pcep_object_header header; | |
332 | uint8_t load_maxlsp; /* Maximum number of TE LSPs in the set */ | |
333 | uint32_t load_minband; /* Specifies the minimum bandwidth of each | |
334 | element */ | |
335 | }; | |
336 | ||
337 | enum pcep_close_reason { | |
338 | PCEP_CLOSE_REASON_NO = 1, | |
339 | PCEP_CLOSE_REASON_DEADTIMER = 2, | |
340 | PCEP_CLOSE_REASON_FORMAT = 3, | |
341 | PCEP_CLOSE_REASON_UNKNOWN_REQ = 4, | |
342 | PCEP_CLOSE_REASON_UNREC_MSG = 5 | |
343 | }; | |
344 | ||
345 | struct pcep_object_close { | |
346 | struct pcep_object_header header; | |
347 | enum pcep_close_reason reason; | |
348 | }; | |
349 | ||
350 | /* Stateful PCE Request Parameters RFC 8231, 8281 */ | |
351 | ||
352 | #define OBJECT_SRP_FLAG_R 0x01 | |
353 | ||
354 | struct pcep_object_srp { | |
355 | struct pcep_object_header header; | |
356 | bool flag_lsp_remove; /* RFC 8281 */ | |
357 | uint32_t srp_id_number; | |
358 | }; | |
359 | ||
360 | /* Label Switched Path Object RFC 8231 */ | |
361 | enum pcep_lsp_operational_status { | |
362 | PCEP_LSP_OPERATIONAL_DOWN = 0, | |
363 | PCEP_LSP_OPERATIONAL_UP = 1, | |
364 | PCEP_LSP_OPERATIONAL_ACTIVE = 2, | |
365 | PCEP_LSP_OPERATIONAL_GOING_DOWN = 3, | |
366 | PCEP_LSP_OPERATIONAL_GOING_UP = 4, | |
367 | }; | |
368 | ||
369 | #define MAX_PLSP_ID 0x000fffff /* The plsp_id is only 20 bits */ | |
370 | #define MAX_LSP_STATUS 0x0007 /* The status is only 3 bits */ | |
371 | #define OBJECT_LSP_FLAG_D 0x01 | |
372 | #define OBJECT_LSP_FLAG_S 0x02 | |
373 | #define OBJECT_LSP_FLAG_R 0x04 | |
374 | #define OBJECT_LSP_FLAG_A 0x08 | |
375 | #define OBJECT_LSP_FLAG_C 0x80 | |
376 | ||
377 | struct pcep_object_lsp { | |
378 | struct pcep_object_header header; | |
379 | uint32_t plsp_id; /* plsp_id is 20 bits, must be <= MAX_PLSP_ID*/ | |
380 | enum pcep_lsp_operational_status operational_status; /* max 3 bits */ | |
381 | bool flag_d; | |
382 | bool flag_s; | |
383 | bool flag_r; | |
384 | bool flag_a; | |
385 | bool flag_c; | |
386 | }; | |
387 | ||
388 | /* RFC 7470 */ | |
389 | struct pcep_object_vendor_info { | |
390 | struct pcep_object_header header; | |
391 | uint32_t enterprise_number; | |
392 | uint32_t enterprise_specific_info; | |
393 | }; | |
394 | ||
395 | /* RFC 8282 */ | |
396 | #define OBJECT_INTER_LAYER_FLAG_I 0x01 | |
397 | #define OBJECT_INTER_LAYER_FLAG_M 0x02 | |
398 | #define OBJECT_INTER_LAYER_FLAG_T 0x04 | |
399 | ||
400 | struct pcep_object_inter_layer { | |
401 | struct pcep_object_header header; | |
402 | bool flag_i; | |
403 | bool flag_m; | |
404 | bool flag_t; | |
405 | }; | |
406 | ||
407 | /* RFC 8282 */ | |
408 | #define OBJECT_SWITCH_LAYER_FLAG_I 0x01 | |
409 | enum pcep_lsp_encoding_type { | |
410 | /* Values taken from RFC 3471 as suggested by RFC 8282 */ | |
411 | PCEP_LSP_ENC_PACKET = 1, | |
412 | PCEP_LSP_ENC_ETHERNET = 2, | |
413 | PCEP_LSP_ENC_PDH = 3, | |
414 | PCEP_LSP_ENC_RESERVED4 = 4, | |
415 | PCEP_LSP_ENC_SDH_SONET = 5, | |
416 | PCEP_LSP_ENC_RESERVED6 = 6, | |
417 | PCEP_LSP_ENC_DIG_WRAPPER = 7, | |
418 | PCEP_LSP_ENC_LAMBDA = 8, | |
419 | PCEP_LSP_ENC_FIBER = 9, | |
420 | PCEP_LSP_ENC_RESERVED10 = 10, | |
421 | PCEP_LSP_ENC_FIBER_CHAN = 11 | |
422 | }; | |
423 | ||
424 | enum pcep_switching_capability { | |
425 | /* Switching capability values taken from RFC 4203/3471 as suggested by | |
426 | RFC 8282 */ | |
427 | PCEP_SW_CAP_PSC1 = 1, /* Packet-Switch Capable-1 (PSC-1) */ | |
428 | PCEP_SW_CAP_PSC2 = 2, | |
429 | PCEP_SW_CAP_PSC3 = 3, | |
430 | PCEP_SW_CAP_PSC4 = 4, | |
431 | PCEP_SW_CAP_L2SC = 51, /* Layer-2 Switch Capable */ | |
432 | PCEP_SW_CAP_TDM = 100, /* Time-Division-Multiplex Capable */ | |
433 | PCEP_SW_CAP_LSC = 150, /* Lambda-Switch Capable */ | |
434 | PCEP_SW_CAP_FSC = 200 /* Fiber-Switch Capable */ | |
435 | }; | |
436 | ||
437 | struct pcep_object_switch_layer_row { | |
438 | enum pcep_lsp_encoding_type lsp_encoding_type; | |
439 | enum pcep_switching_capability switching_type; | |
440 | bool flag_i; | |
441 | }; | |
442 | ||
443 | struct pcep_object_switch_layer { | |
444 | struct pcep_object_header header; | |
445 | double_linked_list | |
446 | *switch_layer_rows; /* list of struct | |
447 | pcep_object_switch_layer_row */ | |
448 | }; | |
449 | ||
450 | /* RFC 8282 | |
451 | * Requested Adaptation capability */ | |
452 | ||
453 | struct pcep_object_req_adap_cap { | |
454 | struct pcep_object_header header; | |
455 | enum pcep_switching_capability switching_capability; | |
456 | enum pcep_lsp_encoding_type encoding; | |
457 | }; | |
458 | ||
459 | /* RFC 8282 */ | |
460 | ||
461 | struct pcep_object_server_indication { | |
462 | struct pcep_object_header header; | |
463 | enum pcep_switching_capability switching_capability; | |
464 | enum pcep_lsp_encoding_type encoding; | |
465 | /* This object is identical to req_adap_cap, except it allows TLVs */ | |
466 | }; | |
467 | ||
468 | /* Objective Function Object: RFC 5541 */ | |
469 | ||
470 | struct pcep_object_objective_function { | |
471 | struct pcep_object_header header; | |
472 | uint16_t of_code; | |
473 | }; | |
474 | ||
475 | /* | |
476 | * Common Route Object sub-object definitions | |
477 | * used by ERO, IRO, and RRO | |
478 | */ | |
479 | ||
480 | /* Common Route Object sub-object types | |
481 | * used by ERO, IRO, and RRO */ | |
482 | enum pcep_ro_subobj_types { | |
483 | RO_SUBOBJ_TYPE_IPV4 = 1, /* RFC 3209 */ | |
484 | RO_SUBOBJ_TYPE_IPV6 = 2, /* RFC 3209 */ | |
485 | RO_SUBOBJ_TYPE_LABEL = 3, /* RFC 3209 */ | |
486 | RO_SUBOBJ_TYPE_UNNUM = 4, /* RFC 3477 */ | |
487 | RO_SUBOBJ_TYPE_ASN = 32, /* RFC 3209, Section 4.3.3.4 */ | |
488 | RO_SUBOBJ_TYPE_SR = 36, /* RFC 8408, draft-ietf-pce-segment-routing-16. | |
489 | Type 5 for draft07 has been assigned to | |
490 | something else. */ | |
491 | RO_SUBOBJ_UNKNOWN | |
492 | }; | |
493 | ||
494 | struct pcep_object_ro { | |
495 | struct pcep_object_header header; | |
496 | double_linked_list | |
497 | *sub_objects; /* list of struct pcep_object_ro_subobj */ | |
498 | }; | |
499 | ||
500 | struct pcep_object_ro_subobj { | |
501 | bool flag_subobj_loose_hop; /* L subobj flag */ | |
502 | enum pcep_ro_subobj_types ro_subobj_type; | |
503 | }; | |
504 | ||
505 | #define OBJECT_SUBOBJ_IP_FLAG_LOCAL_PROT 0x01 | |
506 | ||
507 | struct pcep_ro_subobj_ipv4 { | |
508 | struct pcep_object_ro_subobj ro_subobj; | |
509 | struct in_addr ip_addr; | |
510 | uint8_t prefix_length; | |
511 | bool flag_local_protection; | |
512 | }; | |
513 | ||
514 | struct pcep_ro_subobj_ipv6 { | |
515 | struct pcep_object_ro_subobj ro_subobj; | |
516 | struct in6_addr ip_addr; | |
517 | uint8_t prefix_length; | |
518 | bool flag_local_protection; | |
519 | }; | |
520 | ||
521 | struct pcep_ro_subobj_unnum { | |
522 | struct pcep_object_ro_subobj ro_subobj; | |
523 | struct in_addr router_id; | |
524 | uint32_t interface_id; | |
525 | }; | |
526 | ||
527 | #define OBJECT_SUBOBJ_LABEL_FLAG_GLOGAL 0x01 | |
528 | struct pcep_ro_subobj_32label { | |
529 | struct pcep_object_ro_subobj ro_subobj; | |
530 | bool flag_global_label; | |
531 | uint8_t class_type; /* label class-type (generalized label = 2) */ | |
532 | uint32_t label; /* label supported */ | |
533 | }; | |
534 | ||
535 | struct pcep_ro_subobj_asn { | |
536 | struct pcep_object_ro_subobj ro_subobj; | |
537 | uint16_t asn; /* Autonomous system number */ | |
538 | }; | |
539 | ||
540 | /* The SR ERO and SR RRO subojbects are the same, except | |
541 | * the SR-RRO does not have the L flag in the Type field. | |
542 | * Defined in draft-ietf-pce-segment-routing-16 */ | |
543 | enum pcep_sr_subobj_nai { | |
544 | PCEP_SR_SUBOBJ_NAI_ABSENT = 0, | |
545 | PCEP_SR_SUBOBJ_NAI_IPV4_NODE = 1, | |
546 | PCEP_SR_SUBOBJ_NAI_IPV6_NODE = 2, | |
547 | PCEP_SR_SUBOBJ_NAI_IPV4_ADJACENCY = 3, | |
548 | PCEP_SR_SUBOBJ_NAI_IPV6_ADJACENCY = 4, | |
549 | PCEP_SR_SUBOBJ_NAI_UNNUMBERED_IPV4_ADJACENCY = 5, | |
550 | PCEP_SR_SUBOBJ_NAI_LINK_LOCAL_IPV6_ADJACENCY = 6, | |
551 | PCEP_SR_SUBOBJ_NAI_UNKNOWN | |
552 | }; | |
553 | ||
554 | #define OBJECT_SUBOBJ_SR_FLAG_M 0x01 | |
555 | #define OBJECT_SUBOBJ_SR_FLAG_C 0x02 | |
556 | #define OBJECT_SUBOBJ_SR_FLAG_S 0x04 | |
557 | #define OBJECT_SUBOBJ_SR_FLAG_F 0x08 | |
558 | ||
559 | struct pcep_ro_subobj_sr { | |
560 | struct pcep_object_ro_subobj ro_subobj; | |
561 | enum pcep_sr_subobj_nai nai_type; | |
562 | bool flag_f; | |
563 | bool flag_s; | |
564 | bool flag_c; | |
565 | bool flag_m; | |
566 | ||
567 | /* The SID and NAI are optional depending on the flags, | |
568 | * and the NAI can be variable length */ | |
569 | uint32_t sid; | |
570 | double_linked_list | |
571 | *nai_list; /* double linked list of in_addr or in6_addr */ | |
572 | }; | |
573 | ||
574 | /* Macros to make a SID Label | |
575 | * | |
576 | * 0 1 2 3 | |
577 | 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 | |
578 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Label | |
579 | | Label | TC |S| TTL | Stack | |
580 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Entry | |
581 | */ | |
582 | #define ENCODE_SR_ERO_SID(label_20bits, tc_3bits, stack_bottom_bit, ttl_8bits) \ | |
583 | ((((label_20bits) << 12) & 0xfffff000) \ | |
584 | | (((tc_3bits) << 9) & 0x00000e00) \ | |
585 | | (((stack_bottom_bit) << 8) & 0x00000100) | ((ttl_8bits)&0xff)) | |
586 | #define GET_SR_ERO_SID_LABEL(SID) ((SID & 0xfffff000) >> 12) | |
587 | #define GET_SR_ERO_SID_TC(SID) ((SID & 0x00000e00) >> 9) | |
588 | #define GET_SR_ERO_SID_S(SID) ((SID & 0x00000100) >> 8) | |
589 | #define GET_SR_ERO_SID_TTL(SID) ((SID & 0x000000ff)) | |
590 | ||
591 | /* | |
592 | * All created objects will be in Host byte order, except for IPs. | |
593 | * All IP addresses are expected to be passed-in in Network byte order, | |
594 | * and any objects received will have their IPs in Network byte order. | |
595 | * The message containing the objects should be converted to Network byte order | |
596 | * with pcep_encode_msg_header() before sending, which will also convert the | |
597 | * Objects, TLVs, and sub-objects. | |
598 | */ | |
599 | ||
600 | struct pcep_object_open *pcep_obj_create_open(uint8_t keepalive, | |
601 | uint8_t deadtimer, uint8_t sid, | |
602 | double_linked_list *tlv_list); | |
603 | struct pcep_object_rp *pcep_obj_create_rp(uint8_t priority, bool flag_r, | |
604 | bool flag_b, bool flag_s, | |
605 | bool flag_of, uint32_t reqid, | |
606 | double_linked_list *tlv_list); | |
607 | struct pcep_object_notify * | |
608 | pcep_obj_create_notify(enum pcep_notification_types notification_type, | |
609 | enum pcep_notification_values notification_value); | |
610 | struct pcep_object_nopath * | |
611 | pcep_obj_create_nopath(uint8_t ni, bool flag_c, | |
612 | enum pcep_nopath_tlv_err_codes error_code); | |
613 | struct pcep_object_association_ipv4 * | |
614 | pcep_obj_create_association_ipv4(bool r_flag, uint16_t association_type, | |
615 | uint16_t association_id, struct in_addr src); | |
616 | struct pcep_object_association_ipv6 * | |
617 | pcep_obj_create_association_ipv6(bool r_flag, uint16_t association_type, | |
618 | uint16_t association_id, struct in6_addr src); | |
619 | struct pcep_object_endpoints_ipv4 * | |
620 | pcep_obj_create_endpoint_ipv4(const struct in_addr *src_ipv4, | |
621 | const struct in_addr *dst_ipv4); | |
622 | struct pcep_object_endpoints_ipv6 * | |
623 | pcep_obj_create_endpoint_ipv6(const struct in6_addr *src_ipv6, | |
624 | const struct in6_addr *dst_ipv6); | |
625 | struct pcep_object_bandwidth *pcep_obj_create_bandwidth(float bandwidth); | |
626 | struct pcep_object_metric *pcep_obj_create_metric(enum pcep_metric_types type, | |
627 | bool flag_b, bool flag_c, | |
628 | float value); | |
629 | struct pcep_object_lspa * | |
630 | pcep_obj_create_lspa(uint32_t exclude_any, uint32_t include_any, | |
631 | uint32_t include_all, uint8_t setup_priority, | |
632 | uint8_t holding_priority, bool flag_local_protection); | |
633 | struct pcep_object_svec * | |
634 | pcep_obj_create_svec(bool srlg, bool node, bool link, | |
635 | double_linked_list *request_id_list); | |
636 | struct pcep_object_error * | |
637 | pcep_obj_create_error(enum pcep_error_type error_type, | |
638 | enum pcep_error_value error_value); | |
639 | struct pcep_object_close *pcep_obj_create_close(enum pcep_close_reason reason); | |
640 | struct pcep_object_srp *pcep_obj_create_srp(bool lsp_remove, | |
641 | uint32_t srp_id_number, | |
642 | double_linked_list *tlv_list); | |
643 | struct pcep_object_lsp * | |
644 | pcep_obj_create_lsp(uint32_t plsp_id, enum pcep_lsp_operational_status status, | |
645 | bool c_flag, bool a_flag, bool r_flag, bool s_flag, | |
646 | bool d_flag, double_linked_list *tlv_list); | |
647 | struct pcep_object_vendor_info * | |
648 | pcep_obj_create_vendor_info(uint32_t enterprise_number, | |
649 | uint32_t enterprise_spec_info); | |
650 | struct pcep_object_inter_layer * | |
651 | pcep_obj_create_inter_layer(bool flag_i, bool flag_m, bool flag_t); | |
652 | struct pcep_object_switch_layer * | |
653 | pcep_obj_create_switch_layer(double_linked_list *switch_layer_rows); | |
654 | struct pcep_object_req_adap_cap * | |
655 | pcep_obj_create_req_adap_cap(enum pcep_switching_capability sw_cap, | |
656 | enum pcep_lsp_encoding_type encoding); | |
657 | struct pcep_object_server_indication * | |
658 | pcep_obj_create_server_indication(enum pcep_switching_capability sw_cap, | |
659 | enum pcep_lsp_encoding_type encoding, | |
660 | double_linked_list *tlv_list); | |
661 | struct pcep_object_objective_function * | |
662 | pcep_obj_create_objective_function(uint16_t of_code, | |
663 | double_linked_list *tlv_list); | |
664 | ||
665 | /* Route Object (Explicit ero, Reported rro, and Include iro) functions | |
666 | * First, the sub-objects should be created and appended to a | |
667 | * double_linked_list, then call one of these Route Object creation functions | |
668 | * with the subobj list */ | |
669 | struct pcep_object_ro *pcep_obj_create_ero(double_linked_list *ero_list); | |
670 | struct pcep_object_ro *pcep_obj_create_rro(double_linked_list *rro_list); | |
671 | struct pcep_object_ro *pcep_obj_create_iro(double_linked_list *iro_list); | |
672 | /* Route Object sub-object creation functions */ | |
673 | struct pcep_ro_subobj_ipv4 * | |
674 | pcep_obj_create_ro_subobj_ipv4(bool loose_hop, const struct in_addr *ro_ipv4, | |
675 | uint8_t prefix_len, bool flag_local_prot); | |
676 | struct pcep_ro_subobj_ipv6 * | |
677 | pcep_obj_create_ro_subobj_ipv6(bool loose_hop, const struct in6_addr *ro_ipv6, | |
678 | uint8_t prefix_len, bool flag_local_prot); | |
679 | struct pcep_ro_subobj_unnum * | |
680 | pcep_obj_create_ro_subobj_unnum(struct in_addr *router_id, uint32_t if_id); | |
681 | struct pcep_ro_subobj_32label * | |
682 | pcep_obj_create_ro_subobj_32label(bool flag_global_label, uint8_t class_type, | |
683 | uint32_t label); | |
684 | struct pcep_ro_subobj_asn *pcep_obj_create_ro_subobj_asn(uint16_t asn); | |
685 | ||
686 | /* SR ERO and SR RRO creation functions for different NAI (Node/Adj ID) types. | |
687 | * - The loose_hop is only used for sr ero and must always be false for sr rro. | |
688 | * - The NAI value will be set internally, depending on which function is used. | |
689 | * m_flag: | |
690 | * - If this flag is true, the SID value represents an MPLS label stack | |
691 | * entry as specified in [RFC3032]. Otherwise, the SID value is an | |
692 | * administratively configured value which represents an index into | |
693 | * an MPLS label space (either SRGB or SRLB) per [RFC8402]. | |
694 | * c_flag: | |
695 | * - If the M flag and the C flag are both true, then the TC, S, and TTL | |
696 | * fields in the MPLS label stack entry are specified by the PCE. However, | |
697 | * a PCC MAY choose to override these values according to its local policy | |
698 | * and MPLS forwarding rules. | |
699 | * - If the M flag is true but the C flag is false, then the TC, S, and TTL | |
700 | * fields MUST be ignored by the PCC. | |
701 | * - The PCC MUST set these fields according to its local policy and MPLS | |
702 | * forwarding rules. | |
703 | * - If the M flag is false then the C bit MUST be false. */ | |
704 | struct pcep_ro_subobj_sr *pcep_obj_create_ro_subobj_sr_nonai(bool loose_hop, | |
705 | uint32_t sid, | |
706 | bool c_flag, | |
707 | bool m_flag); | |
708 | ||
709 | /* The ipv4_node_id will be copied internally */ | |
710 | struct pcep_ro_subobj_sr * | |
711 | pcep_obj_create_ro_subobj_sr_ipv4_node(bool loose_hop, bool sid_absent, | |
712 | bool c_flag, bool m_flag, uint32_t sid, | |
713 | struct in_addr *ipv4_node_id); | |
714 | /* The ipv6_node_id will be copied internally */ | |
715 | struct pcep_ro_subobj_sr * | |
716 | pcep_obj_create_ro_subobj_sr_ipv6_node(bool loose_hop, bool sid_absent, | |
717 | bool c_flag, bool m_flag, uint32_t sid, | |
718 | struct in6_addr *ipv6_node_id); | |
719 | /* The local_ipv4 and remote_ipv4 will be copied internally */ | |
720 | struct pcep_ro_subobj_sr *pcep_obj_create_ro_subobj_sr_ipv4_adj( | |
721 | bool loose_hop, bool sid_absent, bool c_flag, bool m_flag, uint32_t sid, | |
722 | struct in_addr *local_ipv4, struct in_addr *remote_ipv4); | |
723 | /* The local_ipv6 and remote_ipv6 will be copied internally */ | |
724 | struct pcep_ro_subobj_sr *pcep_obj_create_ro_subobj_sr_ipv6_adj( | |
725 | bool loose_hop, bool sid_absent, bool c_flag, bool m_flag, uint32_t sid, | |
726 | struct in6_addr *local_ipv6, struct in6_addr *remote_ipv6); | |
727 | struct pcep_ro_subobj_sr *pcep_obj_create_ro_subobj_sr_unnumbered_ipv4_adj( | |
728 | bool loose_hop, bool sid_absent, bool c_flag, bool m_flag, uint32_t sid, | |
729 | uint32_t local_node_id, uint32_t local_if_id, uint32_t remote_node_id, | |
730 | uint32_t remote_if_id); | |
731 | /* The local_ipv6 and remote_ipv6 will be copied internally */ | |
732 | struct pcep_ro_subobj_sr *pcep_obj_create_ro_subobj_sr_linklocal_ipv6_adj( | |
733 | bool loose_hop, bool sid_absent, bool c_flag, bool m_flag, uint32_t sid, | |
734 | struct in6_addr *local_ipv6, uint32_t local_if_id, | |
735 | struct in6_addr *remote_ipv6, uint32_t remote_if_id); | |
736 | ||
737 | #ifdef __cplusplus | |
738 | } | |
739 | #endif | |
740 | ||
741 | #endif |