]> git.proxmox.com Git - mirror_frr.git/blob - pathd/pathd.c
Merge pull request #12392 from patrasar/pimv6_bsm_cli
[mirror_frr.git] / pathd / pathd.c
1 /*
2 * Copyright (C) 2020 NetDEF, Inc.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the Free
6 * Software Foundation; either version 2 of the License, or (at your option)
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; see the file COPYING; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19 #include <zebra.h>
20
21 #include "memory.h"
22 #include "log.h"
23 #include "lib_errors.h"
24 #include "network.h"
25 #include "libfrr.h"
26 #include <debug.h>
27 #include <hook.h>
28
29 #include "pathd/pathd.h"
30 #include "pathd/path_zebra.h"
31 #include "pathd/path_debug.h"
32 #include "pathd/path_ted.h"
33
34 #define HOOK_DELAY 3
35
36 DEFINE_MGROUP(PATHD, "pathd");
37
38 DEFINE_MTYPE_STATIC(PATHD, PATH_SEGMENT_LIST, "Segment List");
39 DEFINE_MTYPE_STATIC(PATHD, PATH_SR_POLICY, "SR Policy");
40 DEFINE_MTYPE_STATIC(PATHD, PATH_SR_CANDIDATE, "SR Policy candidate path");
41
42 DEFINE_HOOK(pathd_candidate_created, (struct srte_candidate * candidate),
43 (candidate));
44 DEFINE_HOOK(pathd_candidate_updated, (struct srte_candidate * candidate),
45 (candidate));
46 DEFINE_HOOK(pathd_candidate_removed, (struct srte_candidate * candidate),
47 (candidate));
48
49 struct debug path_policy_debug;
50
51 #define PATH_POLICY_DEBUG(fmt, ...) \
52 do { \
53 if (DEBUG_FLAGS_CHECK(&path_policy_debug, \
54 PATH_POLICY_DEBUG_BASIC)) \
55 DEBUGD(&path_policy_debug, "policy: " fmt, \
56 ##__VA_ARGS__); \
57 } while (0)
58
59
60 static void trigger_pathd_candidate_created(struct srte_candidate *candidate);
61 static void trigger_pathd_candidate_created_timer(struct thread *thread);
62 static void trigger_pathd_candidate_updated(struct srte_candidate *candidate);
63 static void trigger_pathd_candidate_updated_timer(struct thread *thread);
64 static void trigger_pathd_candidate_removed(struct srte_candidate *candidate);
65 static const char *
66 srte_candidate_metric_name(enum srte_candidate_metric_type type);
67
68 static void srte_set_metric(struct srte_metric *metric, float value,
69 bool required, bool is_bound, bool is_computed);
70 static void srte_unset_metric(struct srte_metric *metric);
71
72
73 /* Generate rb-tree of Segment List Segment instances. */
74 static inline int srte_segment_entry_compare(const struct srte_segment_entry *a,
75 const struct srte_segment_entry *b)
76 {
77 return a->index - b->index;
78 }
79 RB_GENERATE(srte_segment_entry_head, srte_segment_entry, entry,
80 srte_segment_entry_compare)
81
82 /* Generate rb-tree of Segment List instances. */
83 static inline int srte_segment_list_compare(const struct srte_segment_list *a,
84 const struct srte_segment_list *b)
85 {
86 return strcmp(a->name, b->name);
87 }
88 RB_GENERATE(srte_segment_list_head, srte_segment_list, entry,
89 srte_segment_list_compare)
90
91 struct srte_segment_list_head srte_segment_lists =
92 RB_INITIALIZER(&srte_segment_lists);
93
94 /* Generate rb-tree of Candidate Path instances. */
95 static inline int srte_candidate_compare(const struct srte_candidate *a,
96 const struct srte_candidate *b)
97 {
98 return a->preference - b->preference;
99 }
100 RB_GENERATE(srte_candidate_head, srte_candidate, entry, srte_candidate_compare)
101
102 /* Generate rb-tree of SR Policy instances. */
103 static inline int srte_policy_compare(const struct srte_policy *a,
104 const struct srte_policy *b)
105 {
106 return sr_policy_compare(&a->endpoint, &b->endpoint, a->color,
107 b->color);
108 }
109 RB_GENERATE(srte_policy_head, srte_policy, entry, srte_policy_compare)
110
111 struct srte_policy_head srte_policies = RB_INITIALIZER(&srte_policies);
112
113 static void srte_policy_status_log(struct srte_policy *policy)
114 {
115 char endpoint[ENDPOINT_STR_LENGTH];
116
117 ipaddr2str(&policy->endpoint, endpoint, sizeof(endpoint));
118 if (policy->status == SRTE_POLICY_STATUS_DOWN) {
119 PATH_POLICY_DEBUG("SR-TE(%s, %u): policy is DOWN", endpoint,
120 policy->color);
121 } else if (policy->status == SRTE_POLICY_STATUS_UP) {
122 PATH_POLICY_DEBUG("SR-TE(%s, %u): policy is UP", endpoint,
123 policy->color);
124 }
125 }
126
127 /**
128 * Adds a segment list to pathd.
129 *
130 * @param name The name of the segment list to add
131 * @return The added segment list
132 */
133 struct srte_segment_list *srte_segment_list_add(const char *name)
134 {
135 struct srte_segment_list *segment_list;
136
137 segment_list = XCALLOC(MTYPE_PATH_SEGMENT_LIST, sizeof(*segment_list));
138 strlcpy(segment_list->name, name, sizeof(segment_list->name));
139 RB_INIT(srte_segment_entry_head, &segment_list->segments);
140 RB_INSERT(srte_segment_list_head, &srte_segment_lists, segment_list);
141
142 return segment_list;
143 }
144
145 /**
146 * Deletes a segment list from pathd.
147 *
148 * The given segment list structure will be freed and should not be used anymore
149 * after calling this function.
150 *
151 * @param segment_list the segment list to remove from pathd.
152 */
153 void srte_segment_list_del(struct srte_segment_list *segment_list)
154 {
155 struct srte_segment_entry *segment, *safe_seg;
156 RB_FOREACH_SAFE (segment, srte_segment_entry_head,
157 &segment_list->segments, safe_seg) {
158 srte_segment_entry_del(segment);
159 }
160 RB_REMOVE(srte_segment_list_head, &srte_segment_lists, segment_list);
161 XFREE(MTYPE_PATH_SEGMENT_LIST, segment_list);
162 }
163
164 /**
165 * Search for a segment list by name.
166 *
167 * @param name The name of the segment list to look for
168 * @return The segment list if found, NULL otherwise
169 */
170 struct srte_segment_list *srte_segment_list_find(const char *name)
171 {
172 struct srte_segment_list search;
173
174 strlcpy(search.name, name, sizeof(search.name));
175 return RB_FIND(srte_segment_list_head, &srte_segment_lists, &search);
176 }
177
178 /**
179 * Adds a segment to a segment list.
180 *
181 * @param segment_list The segment list the segment should be added to
182 * @param index The index of the added segment in the segment list
183 * @return The added segment
184 */
185 struct srte_segment_entry *
186 srte_segment_entry_add(struct srte_segment_list *segment_list, uint32_t index)
187 {
188 struct srte_segment_entry *segment;
189
190 segment = XCALLOC(MTYPE_PATH_SEGMENT_LIST, sizeof(*segment));
191 segment->segment_list = segment_list;
192 segment->index = index;
193 RB_INSERT(srte_segment_entry_head, &segment_list->segments, segment);
194
195 return segment;
196 }
197
198 /**
199 * Deletes a segment from a segment list.
200 *
201 * @param segment The segment to be removed
202 */
203 void srte_segment_entry_del(struct srte_segment_entry *segment)
204 {
205 RB_REMOVE(srte_segment_entry_head, &segment->segment_list->segments,
206 segment);
207 XFREE(MTYPE_PATH_SEGMENT_LIST, segment);
208 }
209
210 /**
211 * Set the node or adjacency identifier of a segment.
212 *
213 * @param segment The segment for which the NAI should be set
214 * @param type The type of the NAI
215 * @param type The address of the node or the local address of the adjacency
216 * @param type The local interface index of the unumbered adjacency
217 * @param type The remote address of the adjacency
218 * @param type The remote interface index of the unumbered adjacency
219 */
220 int srte_segment_entry_set_nai(struct srte_segment_entry *segment,
221 enum srte_segment_nai_type type,
222 struct ipaddr *local_ip, uint32_t local_iface,
223 struct ipaddr *remote_ip, uint32_t remote_iface,
224 uint8_t algo, uint8_t pref_len)
225 {
226
227 int32_t status = 0;
228 struct prefix pre = {0};
229
230 if (!segment || !local_ip || !remote_ip)
231 return 1;
232
233 segment->nai_type = type;
234 memcpy(&segment->nai_local_addr, local_ip, sizeof(struct ipaddr));
235
236 switch (type) {
237 case SRTE_SEGMENT_NAI_TYPE_IPV4_NODE:
238 case SRTE_SEGMENT_NAI_TYPE_IPV6_NODE:
239 break;
240 case SRTE_SEGMENT_NAI_TYPE_IPV4_ADJACENCY:
241 case SRTE_SEGMENT_NAI_TYPE_IPV6_ADJACENCY:
242 memcpy(&segment->nai_remote_addr, remote_ip,
243 sizeof(struct ipaddr));
244 status = srte_ted_do_query_type_f(segment, local_ip, remote_ip);
245 break;
246 case SRTE_SEGMENT_NAI_TYPE_IPV4_UNNUMBERED_ADJACENCY:
247 memcpy(&segment->nai_remote_addr, remote_ip,
248 sizeof(struct ipaddr));
249 segment->nai_local_iface = local_iface;
250 segment->nai_remote_iface = remote_iface;
251 break;
252 case SRTE_SEGMENT_NAI_TYPE_IPV6_ALGORITHM:
253 pre.family = AF_INET6;
254 pre.prefixlen = pref_len;
255 pre.u.prefix6 = local_ip->ip._v6_addr;
256 segment->nai_local_prefix_len = pref_len;
257 segment->nai_algorithm = algo;
258 status = srte_ted_do_query_type_c(segment, &pre, algo);
259 break;
260 case SRTE_SEGMENT_NAI_TYPE_IPV4_ALGORITHM:
261 pre.family = AF_INET;
262 pre.prefixlen = pref_len;
263 pre.u.prefix4 = local_ip->ip._v4_addr;
264 segment->nai_local_prefix_len = pref_len;
265 segment->nai_algorithm = algo;
266 status = srte_ted_do_query_type_c(segment, &pre, algo);
267 break;
268 case SRTE_SEGMENT_NAI_TYPE_IPV6_LOCAL_IFACE:
269 pre.family = AF_INET6;
270 pre.prefixlen = pref_len;
271 pre.u.prefix6 = local_ip->ip._v6_addr;
272 segment->nai_local_prefix_len = pref_len;
273 segment->nai_local_iface = local_iface;
274 status = srte_ted_do_query_type_e(segment, &pre, local_iface);
275 break;
276 case SRTE_SEGMENT_NAI_TYPE_IPV4_LOCAL_IFACE:
277 pre.family = AF_INET;
278 pre.prefixlen = pref_len;
279 pre.u.prefix4 = local_ip->ip._v4_addr;
280 segment->nai_local_prefix_len = pref_len;
281 segment->nai_local_iface = local_iface;
282 status = srte_ted_do_query_type_e(segment, &pre, local_iface);
283 break;
284 default:
285 segment->nai_local_addr.ipa_type = IPADDR_NONE;
286 segment->nai_local_iface = 0;
287 segment->nai_remote_addr.ipa_type = IPADDR_NONE;
288 segment->nai_remote_iface = 0;
289 }
290 return status;
291 }
292
293 /**
294 * Mark segment as modified depending in protocol and sid conditions
295 *
296 * @param protocol_origin Origin of the segment list
297 * @param s_list Ptr to segment list with flags,sid to modidy
298 * @param s_entry Ptr to segment entry with sid to modidy
299 * @param ted_sid The sid from ted query
300 * @return void
301 */
302 void srte_segment_set_local_modification(struct srte_segment_list *s_list,
303 struct srte_segment_entry *s_entry,
304 uint32_t ted_sid)
305 {
306 if (!s_list || !s_entry)
307 return;
308
309 if (s_list->protocol_origin == SRTE_ORIGIN_LOCAL
310 && s_entry->sid_value != ted_sid) {
311 s_entry->sid_value = ted_sid;
312 SET_FLAG(s_list->flags, F_SEGMENT_LIST_MODIFIED);
313 }
314 }
315
316 /**
317 * Add a policy to pathd.
318 *
319 * WARNING: The color 0 is a special case as it is the no-color.
320 *
321 * @param color The color of the policy.
322 * @param endpoint The IP address of the policy endpoint
323 * @return The created policy
324 */
325 struct srte_policy *srte_policy_add(uint32_t color, struct ipaddr *endpoint,
326 enum srte_protocol_origin origin,
327 const char *originator)
328 {
329 struct srte_policy *policy;
330
331 policy = XCALLOC(MTYPE_PATH_SR_POLICY, sizeof(*policy));
332 policy->color = color;
333 policy->endpoint = *endpoint;
334 policy->binding_sid = MPLS_LABEL_NONE;
335 policy->protocol_origin = origin;
336 if (originator != NULL)
337 strlcpy(policy->originator, originator,
338 sizeof(policy->originator));
339
340 RB_INIT(srte_candidate_head, &policy->candidate_paths);
341 RB_INSERT(srte_policy_head, &srte_policies, policy);
342
343 return policy;
344 }
345
346 /**
347 * Delete a policy from pathd.
348 *
349 * The given policy structure will be freed and should never be used again
350 * after calling this function.
351 *
352 * @param policy The policy to be removed
353 */
354 void srte_policy_del(struct srte_policy *policy)
355 {
356 struct srte_candidate *candidate;
357
358 path_zebra_delete_sr_policy(policy);
359
360 path_zebra_release_label(policy->binding_sid);
361
362 while (!RB_EMPTY(srte_candidate_head, &policy->candidate_paths)) {
363 candidate =
364 RB_ROOT(srte_candidate_head, &policy->candidate_paths);
365 trigger_pathd_candidate_removed(candidate);
366 srte_candidate_del(candidate);
367 }
368
369 RB_REMOVE(srte_policy_head, &srte_policies, policy);
370 XFREE(MTYPE_PATH_SR_POLICY, policy);
371 }
372
373 /**
374 * Search for a policy by color and endpoint.
375 *
376 * WARNING: The color 0 is a special case as it is the no-color.
377 *
378 * @param color The color of the policy to look for
379 * @param endpoint The endpoint of the policy to look for
380 * @return The policy if found, NULL otherwise
381 */
382 struct srte_policy *srte_policy_find(uint32_t color, struct ipaddr *endpoint)
383 {
384 struct srte_policy search;
385
386 search.color = color;
387 search.endpoint = *endpoint;
388 return RB_FIND(srte_policy_head, &srte_policies, &search);
389 }
390
391 /*
392 * After new data from igp,local and pce the segment list :
393 * Mark as invalid for origin pce if cannot be validated
394 * Updated for origin local
395 */
396 int srte_policy_update_ted_sid(void)
397 {
398
399 int number_of_sid_clashed = 0;
400 struct srte_segment_list *s_list;
401 struct srte_segment_entry *s_entry;
402
403 if (!path_ted_is_initialized())
404 return 0;
405 if (RB_EMPTY(srte_segment_list_head, &srte_segment_lists))
406 return 0;
407
408 RB_FOREACH (s_list, srte_segment_list_head, &srte_segment_lists) {
409 if (CHECK_FLAG(s_list->flags, F_SEGMENT_LIST_DELETED))
410 continue;
411 RB_FOREACH (s_entry, srte_segment_entry_head,
412 &s_list->segments) {
413 PATH_TED_DEBUG(
414 "%s:PATHD-TED: SL: Name: %s index:(%d) sid:(%d) prefix_len:(%d) local iface:(%d) algorithm:(%d)",
415 __func__, s_list->name, s_entry->index,
416 s_entry->sid_value,
417 s_entry->nai_local_prefix_len,
418 s_entry->nai_local_iface,
419 s_entry->nai_algorithm);
420 struct prefix prefix_cli = {0};
421
422 switch (s_entry->nai_type) {
423 case SRTE_SEGMENT_NAI_TYPE_IPV6_ADJACENCY:
424 case SRTE_SEGMENT_NAI_TYPE_IPV4_ADJACENCY:
425 number_of_sid_clashed +=
426 srte_ted_do_query_type_f(
427 s_entry,
428 &s_entry->nai_local_addr,
429 &s_entry->nai_remote_addr);
430 break;
431 case SRTE_SEGMENT_NAI_TYPE_IPV6_LOCAL_IFACE:
432 prefix_cli.family = AF_INET6;
433 prefix_cli.prefixlen =
434 s_entry->nai_local_prefix_len;
435 prefix_cli.u.prefix6 =
436 s_entry->nai_local_addr.ip._v6_addr;
437 number_of_sid_clashed +=
438 srte_ted_do_query_type_e(
439 s_entry, &prefix_cli,
440 s_entry->nai_local_iface);
441 break;
442 case SRTE_SEGMENT_NAI_TYPE_IPV4_LOCAL_IFACE:
443 prefix_cli.family = AF_INET;
444 prefix_cli.prefixlen =
445 s_entry->nai_local_prefix_len;
446 prefix_cli.u.prefix4 =
447 s_entry->nai_local_addr.ip._v4_addr;
448 number_of_sid_clashed +=
449 srte_ted_do_query_type_e(
450 s_entry, &prefix_cli,
451 s_entry->nai_local_iface);
452 break;
453 case SRTE_SEGMENT_NAI_TYPE_IPV6_ALGORITHM:
454 prefix_cli.family = AF_INET6;
455 prefix_cli.prefixlen =
456 s_entry->nai_local_prefix_len;
457 prefix_cli.u.prefix6 =
458 s_entry->nai_local_addr.ip._v6_addr;
459 number_of_sid_clashed +=
460 srte_ted_do_query_type_c(
461 s_entry, &prefix_cli,
462 s_entry->nai_algorithm);
463 break;
464 case SRTE_SEGMENT_NAI_TYPE_IPV4_ALGORITHM:
465 prefix_cli.family = AF_INET;
466 prefix_cli.prefixlen =
467 s_entry->nai_local_prefix_len;
468 prefix_cli.u.prefix4 =
469 s_entry->nai_local_addr.ip._v4_addr;
470 number_of_sid_clashed +=
471 srte_ted_do_query_type_c(
472 s_entry, &prefix_cli,
473 s_entry->nai_algorithm);
474 break;
475 default:
476 break;
477 }
478 }
479 if (number_of_sid_clashed) {
480 SET_FLAG(s_list->flags, F_SEGMENT_LIST_SID_CONFLICT);
481 number_of_sid_clashed = 0;
482 } else
483 UNSET_FLAG(s_list->flags, F_SEGMENT_LIST_SID_CONFLICT);
484 }
485 srte_apply_changes();
486
487 return 0;
488 }
489
490 /**
491 * Update a policy binding SID.
492 *
493 * @param policy The policy for which the SID should be updated
494 * @param binding_sid The new binding SID for the given policy
495 */
496 void srte_policy_update_binding_sid(struct srte_policy *policy,
497 uint32_t binding_sid)
498 {
499 if (policy->binding_sid != MPLS_LABEL_NONE)
500 path_zebra_release_label(policy->binding_sid);
501
502 policy->binding_sid = binding_sid;
503
504 /* Reinstall the Binding-SID if necessary. */
505 if (policy->best_candidate)
506 path_zebra_add_sr_policy(
507 policy, policy->best_candidate->lsp->segment_list);
508 }
509
510 /**
511 * Gives the policy best candidate path.
512 *
513 * @param policy The policy we want the best candidate path from
514 * @return The best candidate path
515 */
516 static struct srte_candidate *
517 srte_policy_best_candidate(const struct srte_policy *policy)
518 {
519 struct srte_candidate *candidate;
520
521 RB_FOREACH_REVERSE (candidate, srte_candidate_head,
522 &policy->candidate_paths) {
523 /* search for highest preference with existing segment list */
524 if (!CHECK_FLAG(candidate->flags, F_CANDIDATE_DELETED)
525 && candidate->lsp->segment_list
526 && (!CHECK_FLAG(candidate->lsp->segment_list->flags,
527 F_SEGMENT_LIST_SID_CONFLICT)))
528 return candidate;
529 }
530
531 return NULL;
532 }
533
534 void srte_clean_zebra(void)
535 {
536 struct srte_policy *policy, *safe_pol;
537
538 RB_FOREACH_SAFE (policy, srte_policy_head, &srte_policies, safe_pol)
539 srte_policy_del(policy);
540
541 path_zebra_stop();
542 }
543
544 /**
545 * Apply changes defined by setting the policies, candidate paths
546 * and segment lists modification flags NEW, MODIFIED and DELETED.
547 *
548 * This allows the northbound code to delay all the side effects of adding
549 * modifying and deleting them to the end.
550 *
551 * Example of marking an object as modified:
552 * `SET_FLAG(obj->flags, F_XXX_MODIFIED)`
553 */
554 void srte_apply_changes(void)
555 {
556 struct srte_policy *policy, *safe_pol;
557 struct srte_segment_list *segment_list, *safe_sl;
558
559 RB_FOREACH_SAFE (policy, srte_policy_head, &srte_policies, safe_pol) {
560 if (CHECK_FLAG(policy->flags, F_POLICY_DELETED)) {
561 if (policy->status != SRTE_POLICY_STATUS_DOWN) {
562 policy->status = SRTE_POLICY_STATUS_DOWN;
563 srte_policy_status_log(policy);
564 }
565 srte_policy_del(policy);
566 continue;
567 }
568 srte_policy_apply_changes(policy);
569 UNSET_FLAG(policy->flags, F_POLICY_NEW);
570 UNSET_FLAG(policy->flags, F_POLICY_MODIFIED);
571 }
572
573 RB_FOREACH_SAFE (segment_list, srte_segment_list_head,
574 &srte_segment_lists, safe_sl) {
575 if (CHECK_FLAG(segment_list->flags, F_SEGMENT_LIST_DELETED)) {
576 srte_segment_list_del(segment_list);
577 continue;
578 }
579 UNSET_FLAG(segment_list->flags, F_SEGMENT_LIST_NEW);
580 UNSET_FLAG(segment_list->flags, F_SEGMENT_LIST_MODIFIED);
581 }
582 }
583
584 /**
585 * Apply changes defined by setting the given policy and its candidate paths
586 * modification flags NEW, MODIFIED and DELETED.
587 *
588 * In moste cases `void srte_apply_changes(void)` should be used instead,
589 * this function will not handle the changes of segment lists used by the
590 * policy.
591 *
592 * @param policy The policy changes has to be applied to.
593 */
594 void srte_policy_apply_changes(struct srte_policy *policy)
595 {
596 struct srte_candidate *candidate, *safe;
597 struct srte_candidate *old_best_candidate;
598 struct srte_candidate *new_best_candidate;
599 char endpoint[ENDPOINT_STR_LENGTH];
600
601 ipaddr2str(&policy->endpoint, endpoint, sizeof(endpoint));
602
603 /* Get old and new best candidate path. */
604 old_best_candidate = policy->best_candidate;
605 new_best_candidate = srte_policy_best_candidate(policy);
606
607 if (new_best_candidate != old_best_candidate) {
608 PATH_POLICY_DEBUG(
609 "SR-TE(%s, %u): best candidate changed from %s to %s",
610 endpoint, policy->color,
611 old_best_candidate ? old_best_candidate->name : "none",
612 new_best_candidate ? new_best_candidate->name : "none");
613
614 if (old_best_candidate) {
615 policy->best_candidate = NULL;
616 UNSET_FLAG(old_best_candidate->flags, F_CANDIDATE_BEST);
617 SET_FLAG(old_best_candidate->flags,
618 F_CANDIDATE_MODIFIED);
619
620 /*
621 * Rely on replace semantics if there's a new best
622 * candidate.
623 */
624 if (!new_best_candidate)
625 path_zebra_delete_sr_policy(policy);
626 }
627 if (new_best_candidate) {
628 policy->best_candidate = new_best_candidate;
629 SET_FLAG(new_best_candidate->flags, F_CANDIDATE_BEST);
630 SET_FLAG(new_best_candidate->flags,
631 F_CANDIDATE_MODIFIED);
632
633 path_zebra_add_sr_policy(
634 policy, new_best_candidate->lsp->segment_list);
635 }
636 } else if (new_best_candidate) {
637 /* The best candidate path did not change, but some of its
638 * attributes or its segment list may have changed.
639 */
640
641 bool candidate_changed = CHECK_FLAG(new_best_candidate->flags,
642 F_CANDIDATE_MODIFIED);
643 bool segment_list_changed =
644 new_best_candidate->lsp->segment_list
645 && CHECK_FLAG(
646 new_best_candidate->lsp->segment_list->flags,
647 F_SEGMENT_LIST_MODIFIED);
648
649 if (candidate_changed || segment_list_changed) {
650 PATH_POLICY_DEBUG(
651 "SR-TE(%s, %u): best candidate %s changed",
652 endpoint, policy->color,
653 new_best_candidate->name);
654
655 path_zebra_add_sr_policy(
656 policy, new_best_candidate->lsp->segment_list);
657 }
658 }
659
660 RB_FOREACH_SAFE (candidate, srte_candidate_head,
661 &policy->candidate_paths, safe) {
662 if (CHECK_FLAG(candidate->flags, F_CANDIDATE_DELETED)) {
663 trigger_pathd_candidate_removed(candidate);
664 srte_candidate_del(candidate);
665 continue;
666 } else if (CHECK_FLAG(candidate->flags, F_CANDIDATE_NEW)) {
667 trigger_pathd_candidate_created(candidate);
668 } else if (CHECK_FLAG(candidate->flags, F_CANDIDATE_MODIFIED)) {
669 trigger_pathd_candidate_updated(candidate);
670 } else if (candidate->lsp->segment_list
671 && CHECK_FLAG(candidate->lsp->segment_list->flags,
672 F_SEGMENT_LIST_MODIFIED)) {
673 trigger_pathd_candidate_updated(candidate);
674 }
675
676 UNSET_FLAG(candidate->flags, F_CANDIDATE_NEW);
677 UNSET_FLAG(candidate->flags, F_CANDIDATE_MODIFIED);
678 }
679 }
680
681 /**
682 * Adds a candidate path to a policy.
683 *
684 * @param policy The policy the candidate path should be added to
685 * @param preference The preference of the candidate path to be added
686 * @return The added candidate path
687 */
688 struct srte_candidate *srte_candidate_add(struct srte_policy *policy,
689 uint32_t preference,
690 enum srte_protocol_origin origin,
691 const char *originator)
692 {
693 struct srte_candidate *candidate;
694 struct srte_lsp *lsp;
695
696 candidate = XCALLOC(MTYPE_PATH_SR_CANDIDATE, sizeof(*candidate));
697 lsp = XCALLOC(MTYPE_PATH_SR_CANDIDATE, sizeof(*lsp));
698
699 candidate->preference = preference;
700 candidate->policy = policy;
701 candidate->type = SRTE_CANDIDATE_TYPE_UNDEFINED;
702 candidate->discriminator = frr_weak_random();
703 candidate->protocol_origin = origin;
704 if (originator != NULL) {
705 strlcpy(candidate->originator, originator,
706 sizeof(candidate->originator));
707 lsp->protocol_origin = origin;
708 }
709
710 if (candidate->protocol_origin == SRTE_ORIGIN_PCEP
711 || candidate->protocol_origin == SRTE_ORIGIN_BGP) {
712 candidate->type = SRTE_CANDIDATE_TYPE_DYNAMIC;
713 }
714 lsp->candidate = candidate;
715 candidate->lsp = lsp;
716
717 RB_INSERT(srte_candidate_head, &policy->candidate_paths, candidate);
718
719 return candidate;
720 }
721
722 /**
723 * Deletes a candidate.
724 *
725 * The corresponding LSP will be removed alongside the candidate path.
726 * The given candidate will be freed and shouldn't be used anymore after the
727 * calling this function.
728 *
729 * @param candidate The candidate path to delete
730 */
731 void srte_candidate_del(struct srte_candidate *candidate)
732 {
733 struct srte_policy *srte_policy = candidate->policy;
734
735 RB_REMOVE(srte_candidate_head, &srte_policy->candidate_paths,
736 candidate);
737
738 XFREE(MTYPE_PATH_SR_CANDIDATE, candidate->lsp);
739 XFREE(MTYPE_PATH_SR_CANDIDATE, candidate);
740 }
741
742 /**
743 * Sets the bandwidth constraint of given candidate path.
744 *
745 * The corresponding LSP will be changed too.
746 *
747 * @param candidate The candidate path of which the bandwidth should be changed
748 * @param bandwidth The Bandwidth constraint to set to the candidate path
749 * @param required If the constraint is required (true) or only desired (false)
750 */
751 void srte_candidate_set_bandwidth(struct srte_candidate *candidate,
752 float bandwidth, bool required)
753 {
754 struct srte_policy *policy = candidate->policy;
755 char endpoint[ENDPOINT_STR_LENGTH];
756
757 ipaddr2str(&policy->endpoint, endpoint, sizeof(endpoint));
758 PATH_POLICY_DEBUG(
759 "SR-TE(%s, %u): candidate %s %sconfig bandwidth set to %f B/s",
760 endpoint, policy->color, candidate->name,
761 required ? "required " : "", bandwidth);
762 SET_FLAG(candidate->flags, F_CANDIDATE_HAS_BANDWIDTH);
763 COND_FLAG(candidate->flags, F_CANDIDATE_REQUIRED_BANDWIDTH, required);
764 candidate->bandwidth = bandwidth;
765
766 srte_lsp_set_bandwidth(candidate->lsp, bandwidth, required);
767 }
768
769 /**
770 * Sets the bandwidth constraint of the given LSP.
771 *
772 * The changes will not be shown as part of the running configuration.
773 *
774 * @param lsp The lsp of which the bandwidth should be changed
775 * @param bandwidth The Bandwidth constraint to set to the candidate path
776 * @param required If the constraint is required (true) or only desired (false)
777 */
778 void srte_lsp_set_bandwidth(struct srte_lsp *lsp, float bandwidth,
779 bool required)
780 {
781 struct srte_candidate *candidate = lsp->candidate;
782 struct srte_policy *policy = candidate->policy;
783 char endpoint[ENDPOINT_STR_LENGTH];
784
785 ipaddr2str(&policy->endpoint, endpoint, sizeof(endpoint));
786 PATH_POLICY_DEBUG(
787 "SR-TE(%s, %u): candidate %s %slsp bandwidth set to %f B/s",
788 endpoint, policy->color, candidate->name,
789 required ? "required" : "", bandwidth);
790 SET_FLAG(lsp->flags, F_CANDIDATE_HAS_BANDWIDTH);
791 COND_FLAG(lsp->flags, F_CANDIDATE_REQUIRED_BANDWIDTH, required);
792 lsp->bandwidth = bandwidth;
793 }
794
795 /**
796 * Remove a candidate path bandwidth constraint.
797 *
798 * The corresponding LSP will be changed too.
799 *
800 * @param candidate The candidate path of which the bandwidth should be removed
801 */
802 void srte_candidate_unset_bandwidth(struct srte_candidate *candidate)
803 {
804 struct srte_policy *policy = candidate->policy;
805 char endpoint[ENDPOINT_STR_LENGTH];
806
807 ipaddr2str(&policy->endpoint, endpoint, sizeof(endpoint));
808 PATH_POLICY_DEBUG("SR-TE(%s, %u): candidate %s config bandwidth unset",
809 endpoint, policy->color, candidate->name);
810 UNSET_FLAG(candidate->flags, F_CANDIDATE_HAS_BANDWIDTH);
811 UNSET_FLAG(candidate->flags, F_CANDIDATE_REQUIRED_BANDWIDTH);
812 candidate->bandwidth = 0;
813 SET_FLAG(candidate->flags, F_CANDIDATE_MODIFIED);
814 srte_lsp_unset_bandwidth(candidate->lsp);
815 }
816
817 /**
818 * Remove an LSP bandwidth constraint.
819 *
820 * The changes will not be shown as part of the running configuration.
821 *
822 * @param lsp The lsp of which the bandwidth should be changed
823 */
824 void srte_lsp_unset_bandwidth(struct srte_lsp *lsp)
825 {
826 struct srte_candidate *candidate = lsp->candidate;
827 struct srte_policy *policy = candidate->policy;
828 char endpoint[ENDPOINT_STR_LENGTH];
829
830 ipaddr2str(&policy->endpoint, endpoint, sizeof(endpoint));
831 PATH_POLICY_DEBUG("SR-TE(%s, %u): candidate %s lsp bandwidth unset",
832 endpoint, policy->color, candidate->name);
833 UNSET_FLAG(lsp->flags, F_CANDIDATE_HAS_BANDWIDTH);
834 UNSET_FLAG(lsp->flags, F_CANDIDATE_REQUIRED_BANDWIDTH);
835 SET_FLAG(candidate->flags, F_CANDIDATE_MODIFIED);
836 lsp->bandwidth = 0;
837 }
838
839 /**
840 * Sets a candidate path metric constraint.
841 *
842 * The corresponding LSP will be changed too.
843 *
844 * @param candidate The candidate path of which the metric should be changed
845 * @param type The metric type
846 * @param value The metric value
847 * @param required If the constraint is required (true) or only desired (false)
848 * @param is_bound If the metric is an indicative value or a strict upper bound
849 * @param is_computed If the metric was computed or configured
850 */
851 void srte_candidate_set_metric(struct srte_candidate *candidate,
852 enum srte_candidate_metric_type type,
853 float value, bool required, bool is_bound,
854 bool is_computed)
855 {
856 struct srte_policy *policy = candidate->policy;
857 char endpoint[ENDPOINT_STR_LENGTH];
858
859 ipaddr2str(&policy->endpoint, endpoint, sizeof(endpoint));
860 PATH_POLICY_DEBUG(
861 "SR-TE(%s, %u): candidate %s %sconfig metric %s (%u) set to %f (is-bound: %s; is_computed: %s)",
862 endpoint, policy->color, candidate->name,
863 required ? "required " : "", srte_candidate_metric_name(type),
864 type, value, is_bound ? "true" : "false",
865 is_computed ? "true" : "false");
866 assert((type > 0) && (type <= MAX_METRIC_TYPE));
867 srte_set_metric(&candidate->metrics[type - 1], value, required,
868 is_bound, is_computed);
869 srte_lsp_set_metric(candidate->lsp, type, value, required, is_bound,
870 is_computed);
871 SET_FLAG(candidate->flags, F_CANDIDATE_MODIFIED);
872 }
873
874 /**
875 * Sets an LSP metric constraint.
876 *
877 * The changes will not be shown as part of the running configuration.
878 *
879 * @param lsp The LSP of which the metric should be changed
880 * @param type The metric type
881 * @param value The metric value
882 * @param required If the constraint is required (true) or only desired (false)
883 * @param is_bound If the metric is an indicative value or a strict upper bound
884 * @param is_computed If the metric was computed or configured
885 */
886 void srte_lsp_set_metric(struct srte_lsp *lsp,
887 enum srte_candidate_metric_type type, float value,
888 bool required, bool is_bound, bool is_computed)
889 {
890 struct srte_candidate *candidate = lsp->candidate;
891 struct srte_policy *policy = candidate->policy;
892 char endpoint[ENDPOINT_STR_LENGTH];
893
894 ipaddr2str(&policy->endpoint, endpoint, sizeof(endpoint));
895 PATH_POLICY_DEBUG(
896 "SR-TE(%s, %u): candidate %s %slsp metric %s (%u) set to %f (is-bound: %s; is_computed: %s)",
897 endpoint, policy->color, candidate->name,
898 required ? "required " : "", srte_candidate_metric_name(type),
899 type, value, is_bound ? "true" : "false",
900 is_computed ? "true" : "false");
901 assert((type > 0) && (type <= MAX_METRIC_TYPE));
902 srte_set_metric(&lsp->metrics[type - 1], value, required, is_bound,
903 is_computed);
904 }
905
906 void srte_set_metric(struct srte_metric *metric, float value, bool required,
907 bool is_bound, bool is_computed)
908 {
909 SET_FLAG(metric->flags, F_METRIC_IS_DEFINED);
910 COND_FLAG(metric->flags, F_METRIC_IS_REQUIRED, required);
911 COND_FLAG(metric->flags, F_METRIC_IS_BOUND, is_bound);
912 COND_FLAG(metric->flags, F_METRIC_IS_COMPUTED, is_computed);
913 metric->value = value;
914 }
915
916 /**
917 * Removes a candidate path metric constraint.
918 *
919 * The corresponding LSP will be changed too.
920 *
921 * @param candidate The candidate path from which the metric should be removed
922 * @param type The metric type
923 */
924 void srte_candidate_unset_metric(struct srte_candidate *candidate,
925 enum srte_candidate_metric_type type)
926 {
927 struct srte_policy *policy = candidate->policy;
928 char endpoint[ENDPOINT_STR_LENGTH];
929
930 ipaddr2str(&policy->endpoint, endpoint, sizeof(endpoint));
931 PATH_POLICY_DEBUG(
932 "SR-TE(%s, %u): candidate %s config metric %s (%u) unset",
933 endpoint, policy->color, candidate->name,
934 srte_candidate_metric_name(type), type);
935 assert((type > 0) && (type <= MAX_METRIC_TYPE));
936 srte_unset_metric(&candidate->metrics[type - 1]);
937 srte_lsp_unset_metric(candidate->lsp, type);
938 SET_FLAG(candidate->flags, F_CANDIDATE_MODIFIED);
939 }
940
941 /**
942 * Removes a candidate path metric constraint.
943 *
944 * The changes will not be shown as part of the running configuration.
945 *
946 * @param lsp The LSP from which the metric should be removed
947 * @param type The metric type
948 */
949 void srte_lsp_unset_metric(struct srte_lsp *lsp,
950 enum srte_candidate_metric_type type)
951 {
952 struct srte_candidate *candidate = lsp->candidate;
953 struct srte_policy *policy = candidate->policy;
954 char endpoint[ENDPOINT_STR_LENGTH];
955
956 ipaddr2str(&policy->endpoint, endpoint, sizeof(endpoint));
957 PATH_POLICY_DEBUG(
958 "SR-TE(%s, %u): candidate %s lsp metric %s (%u) unset",
959 endpoint, policy->color, candidate->name,
960 srte_candidate_metric_name(type), type);
961 assert((type > 0) && (type <= MAX_METRIC_TYPE));
962 srte_unset_metric(&lsp->metrics[type - 1]);
963 }
964
965 void srte_unset_metric(struct srte_metric *metric)
966 {
967 UNSET_FLAG(metric->flags, F_METRIC_IS_DEFINED);
968 UNSET_FLAG(metric->flags, F_METRIC_IS_BOUND);
969 UNSET_FLAG(metric->flags, F_METRIC_IS_COMPUTED);
970 metric->value = 0;
971 }
972
973 /**
974 * Sets a candidate path objective function.
975 *
976 * @param candidate The candidate path of which the OF should be changed
977 * @param required If the constraint is required (true) or only desired (false)
978 * @param type The objective function type
979 */
980 void srte_candidate_set_objfun(struct srte_candidate *candidate, bool required,
981 enum objfun_type type)
982 {
983 struct srte_policy *policy = candidate->policy;
984 char endpoint[ENDPOINT_STR_LENGTH];
985
986 ipaddr2str(&policy->endpoint, endpoint, sizeof(endpoint));
987
988 candidate->objfun = type;
989 SET_FLAG(candidate->flags, F_CANDIDATE_HAS_OBJFUN);
990 COND_FLAG(candidate->flags, F_CANDIDATE_REQUIRED_OBJFUN, required);
991 SET_FLAG(candidate->flags, F_CANDIDATE_MODIFIED);
992 PATH_POLICY_DEBUG(
993 "SR-TE(%s, %u): candidate %s %sobjective function set to %s",
994 endpoint, policy->color, candidate->name,
995 required ? "required " : "", objfun_type_name(type));
996 }
997
998 /**
999 * Removed the objective function constraint from a candidate path.
1000 *
1001 * @param candidate The candidate path from which the OF should be removed
1002 */
1003 void srte_candidate_unset_objfun(struct srte_candidate *candidate)
1004 {
1005 struct srte_policy *policy = candidate->policy;
1006 char endpoint[ENDPOINT_STR_LENGTH];
1007
1008 ipaddr2str(&policy->endpoint, endpoint, sizeof(endpoint));
1009
1010 UNSET_FLAG(candidate->flags, F_CANDIDATE_HAS_OBJFUN);
1011 UNSET_FLAG(candidate->flags, F_CANDIDATE_REQUIRED_OBJFUN);
1012 SET_FLAG(candidate->flags, F_CANDIDATE_MODIFIED);
1013 candidate->objfun = OBJFUN_UNDEFINED;
1014 PATH_POLICY_DEBUG(
1015 "SR-TE(%s, %u): candidate %s objective functions preferences unset",
1016 endpoint, policy->color, candidate->name);
1017 }
1018
1019 static uint32_t filter_type_to_flag(enum affinity_filter_type type)
1020 {
1021 switch (type) {
1022 case AFFINITY_FILTER_EXCLUDE_ANY:
1023 return F_CANDIDATE_HAS_EXCLUDE_ANY;
1024 case AFFINITY_FILTER_INCLUDE_ANY:
1025 return F_CANDIDATE_HAS_INCLUDE_ANY;
1026 case AFFINITY_FILTER_INCLUDE_ALL:
1027 return F_CANDIDATE_HAS_INCLUDE_ALL;
1028 default:
1029 return 0;
1030 }
1031 }
1032
1033 static const char *filter_type_name(enum affinity_filter_type type)
1034 {
1035 switch (type) {
1036 case AFFINITY_FILTER_EXCLUDE_ANY:
1037 return "exclude-any";
1038 case AFFINITY_FILTER_INCLUDE_ANY:
1039 return "include-any";
1040 case AFFINITY_FILTER_INCLUDE_ALL:
1041 return "include-all";
1042 default:
1043 return "unknown";
1044 }
1045 }
1046
1047 /**
1048 * Sets a candidate path affinity filter constraint.
1049 *
1050 * @param candidate The candidate path of which the constraint should be changed
1051 * @param type The affinity constraint type to set
1052 * @param filter The bitmask filter of the constraint
1053 */
1054 void srte_candidate_set_affinity_filter(struct srte_candidate *candidate,
1055 enum affinity_filter_type type,
1056 uint32_t filter)
1057 {
1058 struct srte_policy *policy = candidate->policy;
1059 char endpoint[ENDPOINT_STR_LENGTH];
1060
1061 ipaddr2str(&policy->endpoint, endpoint, sizeof(endpoint));
1062
1063 assert(type > AFFINITY_FILTER_UNDEFINED);
1064 assert(type <= MAX_AFFINITY_FILTER_TYPE);
1065 SET_FLAG(candidate->flags, filter_type_to_flag(type));
1066 SET_FLAG(candidate->flags, F_CANDIDATE_MODIFIED);
1067 candidate->affinity_filters[type - 1] = filter;
1068 PATH_POLICY_DEBUG(
1069 "SR-TE(%s, %u): candidate %s affinity filter %s set to 0x%08x",
1070 endpoint, policy->color, candidate->name,
1071 filter_type_name(type), filter);
1072 }
1073
1074 /**
1075 * Removes a candidate path affinity filter constraint.
1076 *
1077 * @param candidate The candidate path from which the constraint should be
1078 * removed
1079 * @param type The affinity constraint type to remove
1080 */
1081 void srte_candidate_unset_affinity_filter(struct srte_candidate *candidate,
1082 enum affinity_filter_type type)
1083 {
1084 struct srte_policy *policy = candidate->policy;
1085 char endpoint[ENDPOINT_STR_LENGTH];
1086
1087 ipaddr2str(&policy->endpoint, endpoint, sizeof(endpoint));
1088
1089 assert(type > AFFINITY_FILTER_UNDEFINED);
1090 assert(type <= MAX_AFFINITY_FILTER_TYPE);
1091 UNSET_FLAG(candidate->flags, filter_type_to_flag(type));
1092 SET_FLAG(candidate->flags, F_CANDIDATE_MODIFIED);
1093 candidate->affinity_filters[type - 1] = 0;
1094 PATH_POLICY_DEBUG(
1095 "SR-TE(%s, %u): candidate %s affinity filter %s unset",
1096 endpoint, policy->color, candidate->name,
1097 filter_type_name(type));
1098 }
1099
1100 /**
1101 * Searches for a candidate path of the given policy.
1102 *
1103 * @param policy The policy to search for candidate path
1104 * @param preference The preference of the candidate path you are looking for
1105 * @return The candidate path if found, NULL otherwise
1106 */
1107 struct srte_candidate *srte_candidate_find(struct srte_policy *policy,
1108 uint32_t preference)
1109 {
1110 struct srte_candidate search;
1111
1112 search.preference = preference;
1113 return RB_FIND(srte_candidate_head, &policy->candidate_paths, &search);
1114 }
1115
1116 /**
1117 * Searches for a an entry of a given segment list.
1118 *
1119 * @param segment_list The segment list to search for the entry
1120 * @param index The index of the entry you are looking for
1121 * @return The segment list entry if found, NULL otherwise.
1122 */
1123 struct srte_segment_entry *
1124 srte_segment_entry_find(struct srte_segment_list *segment_list, uint32_t index)
1125 {
1126 struct srte_segment_entry search;
1127
1128 search.index = index;
1129 return RB_FIND(srte_segment_entry_head, &segment_list->segments,
1130 &search);
1131 }
1132
1133 /**
1134 * Updates a candidate status.
1135 *
1136 * @param candidate The candidate of which the status should be updated
1137 * @param status The new candidate path status
1138 */
1139 void srte_candidate_status_update(struct srte_candidate *candidate, int status)
1140 {
1141 struct srte_policy *policy = candidate->policy;
1142 char endpoint[ENDPOINT_STR_LENGTH];
1143
1144 ipaddr2str(&policy->endpoint, endpoint, sizeof(endpoint));
1145 PATH_POLICY_DEBUG("SR-TE(%s, %u): zebra updated status to %d", endpoint,
1146 policy->color, status);
1147 switch (status) {
1148 case ZEBRA_SR_POLICY_DOWN:
1149 switch (policy->status) {
1150 /* If the policy is GOING_UP, and zebra faild
1151 to install it, we wait for zebra to retry */
1152 /* TODO: Add some timeout after which we would
1153 get is back to DOWN and remove the
1154 policy */
1155 case SRTE_POLICY_STATUS_GOING_UP:
1156 case SRTE_POLICY_STATUS_DOWN:
1157 return;
1158 default:
1159 policy->status = SRTE_POLICY_STATUS_DOWN;
1160 srte_policy_status_log(policy);
1161 break;
1162 }
1163 break;
1164 case ZEBRA_SR_POLICY_UP:
1165 switch (policy->status) {
1166 case SRTE_POLICY_STATUS_UP:
1167 return;
1168 default:
1169 policy->status = SRTE_POLICY_STATUS_UP;
1170 srte_policy_status_log(policy);
1171 break;
1172 }
1173 break;
1174 }
1175
1176 trigger_pathd_candidate_updated(candidate);
1177 }
1178
1179 /**
1180 * Flags the segment lists from give originator for removal.
1181 *
1182 * The function srte_apply_changes must be called afterward for
1183 * the segment list to be removed.
1184 *
1185 * @param originator The originator tag of the segment list to be marked
1186 * @param force If the unset should be forced regardless of the originator
1187 */
1188 void srte_candidate_unset_segment_list(const char *originator, bool force)
1189 {
1190 if (originator == NULL) {
1191 zlog_warn(
1192 "Cannot unset segment list because originator is NULL");
1193 return;
1194 }
1195
1196 PATH_POLICY_DEBUG("Unset segment lists for originator %s", originator);
1197
1198 /* Iterate the policies, then iterate each policy's candidate path
1199 * to check the candidate path's segment list originator */
1200 struct srte_policy *policy;
1201 RB_FOREACH (policy, srte_policy_head, &srte_policies) {
1202 PATH_POLICY_DEBUG("Unset segment lists checking policy %s",
1203 policy->name);
1204 struct srte_candidate *candidate;
1205 RB_FOREACH (candidate, srte_candidate_head,
1206 &policy->candidate_paths) {
1207 PATH_POLICY_DEBUG(
1208 "Unset segment lists checking candidate %s",
1209 candidate->name);
1210 if (candidate->lsp == NULL) {
1211 continue;
1212 }
1213
1214 /* The candidate->lsp->segment_list is operational data,
1215 * configured by the PCE. We dont want to modify the
1216 * candidate->segment_list,
1217 * which is configuration data. */
1218 struct srte_segment_list *segment_list =
1219 candidate->lsp->segment_list;
1220 if (segment_list == NULL) {
1221 continue;
1222 }
1223
1224 if (segment_list->protocol_origin
1225 == SRTE_ORIGIN_LOCAL) {
1226 zlog_warn(
1227 "Cannot unset segment list %s because it was created locally",
1228 segment_list->name);
1229 continue;
1230 }
1231
1232 /* In the case of last pce,we force the unset
1233 * because we don't have pce by prefix (TODO) is all
1234 * 'global' */
1235 if (strncmp(segment_list->originator, originator,
1236 sizeof(segment_list->originator))
1237 == 0
1238 || force) {
1239 PATH_POLICY_DEBUG("Unset segment list %s",
1240 segment_list->name);
1241 SET_FLAG(segment_list->flags,
1242 F_SEGMENT_LIST_DELETED);
1243 SET_FLAG(candidate->flags,
1244 F_CANDIDATE_MODIFIED);
1245 candidate->lsp->segment_list = NULL;
1246 }
1247 }
1248 }
1249 }
1250
1251 /**
1252 * Gives a string representation of given protocol origin enum.
1253 *
1254 * @param origin The enum you want a string representation of
1255 * @return The string representation of given enum
1256 */
1257 const char *srte_origin2str(enum srte_protocol_origin origin)
1258 {
1259 switch (origin) {
1260 case SRTE_ORIGIN_PCEP:
1261 return "PCEP";
1262 case SRTE_ORIGIN_BGP:
1263 return "BGP";
1264 case SRTE_ORIGIN_LOCAL:
1265 return "Local";
1266 default:
1267 return "Unknown";
1268 }
1269 }
1270
1271 void path_policy_show_debugging(struct vty *vty)
1272 {
1273 if (DEBUG_FLAGS_CHECK(&path_policy_debug, PATH_POLICY_DEBUG_BASIC))
1274 vty_out(vty, " Path policy debugging is on\n");
1275 }
1276
1277 void pathd_shutdown(void)
1278 {
1279 path_ted_teardown();
1280 srte_clean_zebra();
1281 frr_fini();
1282 }
1283
1284 void trigger_pathd_candidate_created(struct srte_candidate *candidate)
1285 {
1286 /* The hook is called asynchronously to let the PCEP module
1287 time to send a response to the PCE before receiving any updates from
1288 pathd. In addition, a minimum amount of time need to pass before
1289 the hook is called to prevent the hook to be called multiple times
1290 from changing the candidate by hand with the console */
1291 if (candidate->hook_timer != NULL)
1292 return;
1293 thread_add_timer(master, trigger_pathd_candidate_created_timer,
1294 (void *)candidate, HOOK_DELAY, &candidate->hook_timer);
1295 }
1296
1297 void trigger_pathd_candidate_created_timer(struct thread *thread)
1298 {
1299 struct srte_candidate *candidate = THREAD_ARG(thread);
1300 candidate->hook_timer = NULL;
1301 hook_call(pathd_candidate_created, candidate);
1302 }
1303
1304 void trigger_pathd_candidate_updated(struct srte_candidate *candidate)
1305 {
1306 /* The hook is called asynchronously to let the PCEP module
1307 time to send a response to the PCE before receiving any updates from
1308 pathd. In addition, a minimum amount of time need to pass before
1309 the hook is called to prevent the hook to be called multiple times
1310 from changing the candidate by hand with the console */
1311 if (candidate->hook_timer != NULL)
1312 return;
1313 thread_add_timer(master, trigger_pathd_candidate_updated_timer,
1314 (void *)candidate, HOOK_DELAY, &candidate->hook_timer);
1315 }
1316
1317 void trigger_pathd_candidate_updated_timer(struct thread *thread)
1318 {
1319 struct srte_candidate *candidate = THREAD_ARG(thread);
1320 candidate->hook_timer = NULL;
1321 hook_call(pathd_candidate_updated, candidate);
1322 }
1323
1324 void trigger_pathd_candidate_removed(struct srte_candidate *candidate)
1325 {
1326 /* The hook needs to be call synchronously, otherwise the candidate
1327 path will be already deleted when the handler is called */
1328 if (candidate->hook_timer != NULL) {
1329 thread_cancel(&candidate->hook_timer);
1330 candidate->hook_timer = NULL;
1331 }
1332 hook_call(pathd_candidate_removed, candidate);
1333 }
1334
1335 const char *srte_candidate_metric_name(enum srte_candidate_metric_type type)
1336 {
1337 switch (type) {
1338 case SRTE_CANDIDATE_METRIC_TYPE_IGP:
1339 return "IGP";
1340 case SRTE_CANDIDATE_METRIC_TYPE_TE:
1341 return "TE";
1342 case SRTE_CANDIDATE_METRIC_TYPE_HC:
1343 return "HC";
1344 case SRTE_CANDIDATE_METRIC_TYPE_ABC:
1345 return "ABC";
1346 case SRTE_CANDIDATE_METRIC_TYPE_LMLL:
1347 return "LMLL";
1348 case SRTE_CANDIDATE_METRIC_TYPE_CIGP:
1349 return "CIGP";
1350 case SRTE_CANDIDATE_METRIC_TYPE_CTE:
1351 return "CTE";
1352 case SRTE_CANDIDATE_METRIC_TYPE_PIGP:
1353 return "PIGP";
1354 case SRTE_CANDIDATE_METRIC_TYPE_PTE:
1355 return "PTE";
1356 case SRTE_CANDIDATE_METRIC_TYPE_PHC:
1357 return "PHC";
1358 case SRTE_CANDIDATE_METRIC_TYPE_MSD:
1359 return "MSD";
1360 case SRTE_CANDIDATE_METRIC_TYPE_PD:
1361 return "PD";
1362 case SRTE_CANDIDATE_METRIC_TYPE_PDV:
1363 return "PDV";
1364 case SRTE_CANDIDATE_METRIC_TYPE_PL:
1365 return "PL";
1366 case SRTE_CANDIDATE_METRIC_TYPE_PPD:
1367 return "PPD";
1368 case SRTE_CANDIDATE_METRIC_TYPE_PPDV:
1369 return "PPDV";
1370 case SRTE_CANDIDATE_METRIC_TYPE_PPL:
1371 return "PPL";
1372 case SRTE_CANDIDATE_METRIC_TYPE_NAP:
1373 return "NAP";
1374 case SRTE_CANDIDATE_METRIC_TYPE_NLP:
1375 return "NLP";
1376 case SRTE_CANDIDATE_METRIC_TYPE_DC:
1377 return "DC";
1378 case SRTE_CANDIDATE_METRIC_TYPE_BNC:
1379 return "BNC";
1380 default:
1381 return "UNKNOWN";
1382 }
1383 }
1384
1385 int32_t srte_ted_do_query_type_c(struct srte_segment_entry *entry,
1386 struct prefix *prefix_cli, uint32_t algo)
1387 {
1388 int32_t status = 0;
1389 uint32_t ted_sid = MPLS_LABEL_NONE;
1390
1391 if (!entry || !prefix_cli)
1392 return 0;
1393
1394 if (!path_ted_is_initialized())
1395 return 0;
1396
1397 ted_sid = path_ted_query_type_c(prefix_cli, algo);
1398 if (ted_sid == MPLS_LABEL_NONE) {
1399 zlog_warn(" %s: PATHD-TED: SL: ERROR query C : ted-sid (%d)",
1400 __func__, ted_sid);
1401 } else {
1402 PATH_TED_DEBUG(
1403 "%s: PATHD-TED: SL: Success query C : ted-sid (%d)",
1404 __func__, ted_sid);
1405 }
1406 if (CHECK_SID(entry->segment_list->protocol_origin, ted_sid,
1407 entry->sid_value)) {
1408 status = PATH_SID_ERROR;
1409 } else
1410 srte_segment_set_local_modification(entry->segment_list, entry,
1411 ted_sid);
1412 return status;
1413 }
1414
1415 int32_t srte_ted_do_query_type_e(struct srte_segment_entry *entry,
1416 struct prefix *prefix_cli,
1417 uint32_t local_iface)
1418 {
1419 int32_t status = 0;
1420 uint32_t ted_sid = MPLS_LABEL_NONE;
1421
1422 if (!entry || !prefix_cli)
1423 return 0;
1424
1425 if (!path_ted_is_initialized())
1426 return 0;
1427
1428 ted_sid = path_ted_query_type_e(prefix_cli, local_iface);
1429 if (ted_sid == MPLS_LABEL_NONE) {
1430 zlog_warn(" %s: PATHD-TED: SL: ERROR query E : ted-sid (%d)",
1431 __func__, ted_sid);
1432 } else {
1433 PATH_TED_DEBUG(
1434 "%s: PATHD-TED: SL: Success query E : ted-sid (%d)",
1435 __func__, ted_sid);
1436 }
1437 if (CHECK_SID(entry->segment_list->protocol_origin, ted_sid,
1438 entry->sid_value)) {
1439 status = PATH_SID_ERROR;
1440 } else
1441 srte_segment_set_local_modification(entry->segment_list, entry,
1442 ted_sid);
1443 return status;
1444 }
1445
1446 int32_t srte_ted_do_query_type_f(struct srte_segment_entry *entry,
1447 struct ipaddr *local, struct ipaddr *remote)
1448 {
1449 int32_t status = 0;
1450 uint32_t ted_sid = MPLS_LABEL_NONE;
1451
1452 if (!entry || !local || !remote)
1453 return 0;
1454
1455 if (!path_ted_is_initialized())
1456 return status;
1457
1458 ted_sid = path_ted_query_type_f(local, remote);
1459 if (ted_sid == MPLS_LABEL_NONE) {
1460 zlog_warn("%s:SL: ERROR query F : ted-sid (%d)", __func__,
1461 ted_sid);
1462 } else {
1463 PATH_TED_DEBUG("%s:SL: Success query F : ted-sid (%d)",
1464 __func__, ted_sid);
1465 }
1466 if (CHECK_SID(entry->segment_list->protocol_origin, ted_sid,
1467 entry->sid_value)) {
1468 status = PATH_SID_ERROR;
1469 } else
1470 srte_segment_set_local_modification(entry->segment_list, entry,
1471 ted_sid);
1472 return status;
1473 }