1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2020 NetDEF, Inc.
10 #include "lib_errors.h"
16 #include "pathd/pathd.h"
17 #include "pathd/path_zebra.h"
18 #include "pathd/path_debug.h"
19 #include "pathd/path_ted.h"
23 DEFINE_MGROUP(PATHD
, "pathd");
25 DEFINE_MTYPE_STATIC(PATHD
, PATH_SEGMENT_LIST
, "Segment List");
26 DEFINE_MTYPE_STATIC(PATHD
, PATH_SR_POLICY
, "SR Policy");
27 DEFINE_MTYPE_STATIC(PATHD
, PATH_SR_CANDIDATE
, "SR Policy candidate path");
29 DEFINE_HOOK(pathd_candidate_created
, (struct srte_candidate
* candidate
),
31 DEFINE_HOOK(pathd_candidate_updated
, (struct srte_candidate
* candidate
),
33 DEFINE_HOOK(pathd_candidate_removed
, (struct srte_candidate
* candidate
),
36 struct debug path_policy_debug
;
38 #define PATH_POLICY_DEBUG(fmt, ...) \
40 if (DEBUG_FLAGS_CHECK(&path_policy_debug, \
41 PATH_POLICY_DEBUG_BASIC)) \
42 DEBUGD(&path_policy_debug, "policy: " fmt, \
47 static void trigger_pathd_candidate_created(struct srte_candidate
*candidate
);
48 static void trigger_pathd_candidate_created_timer(struct thread
*thread
);
49 static void trigger_pathd_candidate_updated(struct srte_candidate
*candidate
);
50 static void trigger_pathd_candidate_updated_timer(struct thread
*thread
);
51 static void trigger_pathd_candidate_removed(struct srte_candidate
*candidate
);
53 srte_candidate_metric_name(enum srte_candidate_metric_type type
);
55 static void srte_set_metric(struct srte_metric
*metric
, float value
,
56 bool required
, bool is_bound
, bool is_computed
);
57 static void srte_unset_metric(struct srte_metric
*metric
);
60 /* Generate rb-tree of Segment List Segment instances. */
61 static inline int srte_segment_entry_compare(const struct srte_segment_entry
*a
,
62 const struct srte_segment_entry
*b
)
64 return a
->index
- b
->index
;
66 RB_GENERATE(srte_segment_entry_head
, srte_segment_entry
, entry
,
67 srte_segment_entry_compare
)
69 /* Generate rb-tree of Segment List instances. */
70 static inline int srte_segment_list_compare(const struct srte_segment_list
*a
,
71 const struct srte_segment_list
*b
)
73 return strcmp(a
->name
, b
->name
);
75 RB_GENERATE(srte_segment_list_head
, srte_segment_list
, entry
,
76 srte_segment_list_compare
)
78 struct srte_segment_list_head srte_segment_lists
=
79 RB_INITIALIZER(&srte_segment_lists
);
81 /* Generate rb-tree of Candidate Path instances. */
82 static inline int srte_candidate_compare(const struct srte_candidate
*a
,
83 const struct srte_candidate
*b
)
85 return a
->preference
- b
->preference
;
87 RB_GENERATE(srte_candidate_head
, srte_candidate
, entry
, srte_candidate_compare
)
89 /* Generate rb-tree of SR Policy instances. */
90 static inline int srte_policy_compare(const struct srte_policy
*a
,
91 const struct srte_policy
*b
)
93 return sr_policy_compare(&a
->endpoint
, &b
->endpoint
, a
->color
,
96 RB_GENERATE(srte_policy_head
, srte_policy
, entry
, srte_policy_compare
)
98 struct srte_policy_head srte_policies
= RB_INITIALIZER(&srte_policies
);
100 static void srte_policy_status_log(struct srte_policy
*policy
)
102 char endpoint
[ENDPOINT_STR_LENGTH
];
104 ipaddr2str(&policy
->endpoint
, endpoint
, sizeof(endpoint
));
105 if (policy
->status
== SRTE_POLICY_STATUS_DOWN
) {
106 PATH_POLICY_DEBUG("SR-TE(%s, %u): policy is DOWN", endpoint
,
108 } else if (policy
->status
== SRTE_POLICY_STATUS_UP
) {
109 PATH_POLICY_DEBUG("SR-TE(%s, %u): policy is UP", endpoint
,
115 * Adds a segment list to pathd.
117 * @param name The name of the segment list to add
118 * @return The added segment list
120 struct srte_segment_list
*srte_segment_list_add(const char *name
)
122 struct srte_segment_list
*segment_list
;
124 segment_list
= XCALLOC(MTYPE_PATH_SEGMENT_LIST
, sizeof(*segment_list
));
125 strlcpy(segment_list
->name
, name
, sizeof(segment_list
->name
));
126 RB_INIT(srte_segment_entry_head
, &segment_list
->segments
);
127 RB_INSERT(srte_segment_list_head
, &srte_segment_lists
, segment_list
);
133 * Deletes a segment list from pathd.
135 * The given segment list structure will be freed and should not be used anymore
136 * after calling this function.
138 * @param segment_list the segment list to remove from pathd.
140 void srte_segment_list_del(struct srte_segment_list
*segment_list
)
142 struct srte_segment_entry
*segment
, *safe_seg
;
143 RB_FOREACH_SAFE (segment
, srte_segment_entry_head
,
144 &segment_list
->segments
, safe_seg
) {
145 srte_segment_entry_del(segment
);
147 RB_REMOVE(srte_segment_list_head
, &srte_segment_lists
, segment_list
);
148 XFREE(MTYPE_PATH_SEGMENT_LIST
, segment_list
);
152 * Search for a segment list by name.
154 * @param name The name of the segment list to look for
155 * @return The segment list if found, NULL otherwise
157 struct srte_segment_list
*srte_segment_list_find(const char *name
)
159 struct srte_segment_list search
;
161 strlcpy(search
.name
, name
, sizeof(search
.name
));
162 return RB_FIND(srte_segment_list_head
, &srte_segment_lists
, &search
);
166 * Adds a segment to a segment list.
168 * @param segment_list The segment list the segment should be added to
169 * @param index The index of the added segment in the segment list
170 * @return The added segment
172 struct srte_segment_entry
*
173 srte_segment_entry_add(struct srte_segment_list
*segment_list
, uint32_t index
)
175 struct srte_segment_entry
*segment
;
177 segment
= XCALLOC(MTYPE_PATH_SEGMENT_LIST
, sizeof(*segment
));
178 segment
->segment_list
= segment_list
;
179 segment
->index
= index
;
180 RB_INSERT(srte_segment_entry_head
, &segment_list
->segments
, segment
);
186 * Deletes a segment from a segment list.
188 * @param segment The segment to be removed
190 void srte_segment_entry_del(struct srte_segment_entry
*segment
)
192 RB_REMOVE(srte_segment_entry_head
, &segment
->segment_list
->segments
,
194 XFREE(MTYPE_PATH_SEGMENT_LIST
, segment
);
198 * Set the node or adjacency identifier of a segment.
200 * @param segment The segment for which the NAI should be set
201 * @param type The type of the NAI
202 * @param type The address of the node or the local address of the adjacency
203 * @param type The local interface index of the unumbered adjacency
204 * @param type The remote address of the adjacency
205 * @param type The remote interface index of the unumbered adjacency
207 int srte_segment_entry_set_nai(struct srte_segment_entry
*segment
,
208 enum srte_segment_nai_type type
,
209 struct ipaddr
*local_ip
, uint32_t local_iface
,
210 struct ipaddr
*remote_ip
, uint32_t remote_iface
,
211 uint8_t algo
, uint8_t pref_len
)
215 struct prefix pre
= {0};
217 if (!segment
|| !local_ip
|| !remote_ip
)
220 segment
->nai_type
= type
;
221 memcpy(&segment
->nai_local_addr
, local_ip
, sizeof(struct ipaddr
));
224 case SRTE_SEGMENT_NAI_TYPE_IPV4_NODE
:
225 case SRTE_SEGMENT_NAI_TYPE_IPV6_NODE
:
227 case SRTE_SEGMENT_NAI_TYPE_IPV4_ADJACENCY
:
228 case SRTE_SEGMENT_NAI_TYPE_IPV6_ADJACENCY
:
229 memcpy(&segment
->nai_remote_addr
, remote_ip
,
230 sizeof(struct ipaddr
));
231 status
= srte_ted_do_query_type_f(segment
, local_ip
, remote_ip
);
233 case SRTE_SEGMENT_NAI_TYPE_IPV4_UNNUMBERED_ADJACENCY
:
234 memcpy(&segment
->nai_remote_addr
, remote_ip
,
235 sizeof(struct ipaddr
));
236 segment
->nai_local_iface
= local_iface
;
237 segment
->nai_remote_iface
= remote_iface
;
239 case SRTE_SEGMENT_NAI_TYPE_IPV6_ALGORITHM
:
240 pre
.family
= AF_INET6
;
241 pre
.prefixlen
= pref_len
;
242 pre
.u
.prefix6
= local_ip
->ip
._v6_addr
;
243 segment
->nai_local_prefix_len
= pref_len
;
244 segment
->nai_algorithm
= algo
;
245 status
= srte_ted_do_query_type_c(segment
, &pre
, algo
);
247 case SRTE_SEGMENT_NAI_TYPE_IPV4_ALGORITHM
:
248 pre
.family
= AF_INET
;
249 pre
.prefixlen
= pref_len
;
250 pre
.u
.prefix4
= local_ip
->ip
._v4_addr
;
251 segment
->nai_local_prefix_len
= pref_len
;
252 segment
->nai_algorithm
= algo
;
253 status
= srte_ted_do_query_type_c(segment
, &pre
, algo
);
255 case SRTE_SEGMENT_NAI_TYPE_IPV6_LOCAL_IFACE
:
256 pre
.family
= AF_INET6
;
257 pre
.prefixlen
= pref_len
;
258 pre
.u
.prefix6
= local_ip
->ip
._v6_addr
;
259 segment
->nai_local_prefix_len
= pref_len
;
260 segment
->nai_local_iface
= local_iface
;
261 status
= srte_ted_do_query_type_e(segment
, &pre
, local_iface
);
263 case SRTE_SEGMENT_NAI_TYPE_IPV4_LOCAL_IFACE
:
264 pre
.family
= AF_INET
;
265 pre
.prefixlen
= pref_len
;
266 pre
.u
.prefix4
= local_ip
->ip
._v4_addr
;
267 segment
->nai_local_prefix_len
= pref_len
;
268 segment
->nai_local_iface
= local_iface
;
269 status
= srte_ted_do_query_type_e(segment
, &pre
, local_iface
);
271 case SRTE_SEGMENT_NAI_TYPE_NONE
:
272 case SRTE_SEGMENT_NAI_TYPE_IPV6_ADJACENCY_LINK_LOCAL_ADDRESSES
:
273 segment
->nai_local_addr
.ipa_type
= IPADDR_NONE
;
274 segment
->nai_local_iface
= 0;
275 segment
->nai_remote_addr
.ipa_type
= IPADDR_NONE
;
276 segment
->nai_remote_iface
= 0;
282 * Mark segment as modified depending in protocol and sid conditions
284 * @param protocol_origin Origin of the segment list
285 * @param s_list Ptr to segment list with flags,sid to modidy
286 * @param s_entry Ptr to segment entry with sid to modidy
287 * @param ted_sid The sid from ted query
290 void srte_segment_set_local_modification(struct srte_segment_list
*s_list
,
291 struct srte_segment_entry
*s_entry
,
294 if (!s_list
|| !s_entry
)
297 if (s_list
->protocol_origin
== SRTE_ORIGIN_LOCAL
298 && s_entry
->sid_value
!= ted_sid
) {
299 s_entry
->sid_value
= ted_sid
;
300 SET_FLAG(s_list
->flags
, F_SEGMENT_LIST_MODIFIED
);
305 * Add a policy to pathd.
307 * WARNING: The color 0 is a special case as it is the no-color.
309 * @param color The color of the policy.
310 * @param endpoint The IP address of the policy endpoint
311 * @return The created policy
313 struct srte_policy
*srte_policy_add(uint32_t color
, struct ipaddr
*endpoint
,
314 enum srte_protocol_origin origin
,
315 const char *originator
)
317 struct srte_policy
*policy
;
319 policy
= XCALLOC(MTYPE_PATH_SR_POLICY
, sizeof(*policy
));
320 policy
->color
= color
;
321 policy
->endpoint
= *endpoint
;
322 policy
->binding_sid
= MPLS_LABEL_NONE
;
323 policy
->protocol_origin
= origin
;
324 if (originator
!= NULL
)
325 strlcpy(policy
->originator
, originator
,
326 sizeof(policy
->originator
));
328 RB_INIT(srte_candidate_head
, &policy
->candidate_paths
);
329 RB_INSERT(srte_policy_head
, &srte_policies
, policy
);
335 * Delete a policy from pathd.
337 * The given policy structure will be freed and should never be used again
338 * after calling this function.
340 * @param policy The policy to be removed
342 void srte_policy_del(struct srte_policy
*policy
)
344 struct srte_candidate
*candidate
;
346 path_zebra_delete_sr_policy(policy
);
348 path_zebra_release_label(policy
->binding_sid
);
350 while (!RB_EMPTY(srte_candidate_head
, &policy
->candidate_paths
)) {
352 RB_ROOT(srte_candidate_head
, &policy
->candidate_paths
);
353 trigger_pathd_candidate_removed(candidate
);
354 srte_candidate_del(candidate
);
357 RB_REMOVE(srte_policy_head
, &srte_policies
, policy
);
358 XFREE(MTYPE_PATH_SR_POLICY
, policy
);
362 * Search for a policy by color and endpoint.
364 * WARNING: The color 0 is a special case as it is the no-color.
366 * @param color The color of the policy to look for
367 * @param endpoint The endpoint of the policy to look for
368 * @return The policy if found, NULL otherwise
370 struct srte_policy
*srte_policy_find(uint32_t color
, struct ipaddr
*endpoint
)
372 struct srte_policy search
;
374 search
.color
= color
;
375 search
.endpoint
= *endpoint
;
376 return RB_FIND(srte_policy_head
, &srte_policies
, &search
);
380 * After new data from igp,local and pce the segment list :
381 * Mark as invalid for origin pce if cannot be validated
382 * Updated for origin local
384 int srte_policy_update_ted_sid(void)
387 int number_of_sid_clashed
= 0;
388 struct srte_segment_list
*s_list
;
389 struct srte_segment_entry
*s_entry
;
391 if (!path_ted_is_initialized())
393 if (RB_EMPTY(srte_segment_list_head
, &srte_segment_lists
))
396 RB_FOREACH (s_list
, srte_segment_list_head
, &srte_segment_lists
) {
397 if (CHECK_FLAG(s_list
->flags
, F_SEGMENT_LIST_DELETED
))
399 RB_FOREACH (s_entry
, srte_segment_entry_head
,
402 "%s:PATHD-TED: SL: Name: %s index:(%d) sid:(%d) prefix_len:(%d) local iface:(%d) algorithm:(%d)",
403 __func__
, s_list
->name
, s_entry
->index
,
405 s_entry
->nai_local_prefix_len
,
406 s_entry
->nai_local_iface
,
407 s_entry
->nai_algorithm
);
408 struct prefix prefix_cli
= {0};
410 switch (s_entry
->nai_type
) {
411 case SRTE_SEGMENT_NAI_TYPE_IPV6_ADJACENCY
:
412 case SRTE_SEGMENT_NAI_TYPE_IPV4_ADJACENCY
:
413 number_of_sid_clashed
+=
414 srte_ted_do_query_type_f(
416 &s_entry
->nai_local_addr
,
417 &s_entry
->nai_remote_addr
);
419 case SRTE_SEGMENT_NAI_TYPE_IPV6_LOCAL_IFACE
:
420 prefix_cli
.family
= AF_INET6
;
421 prefix_cli
.prefixlen
=
422 s_entry
->nai_local_prefix_len
;
423 prefix_cli
.u
.prefix6
=
424 s_entry
->nai_local_addr
.ip
._v6_addr
;
425 number_of_sid_clashed
+=
426 srte_ted_do_query_type_e(
427 s_entry
, &prefix_cli
,
428 s_entry
->nai_local_iface
);
430 case SRTE_SEGMENT_NAI_TYPE_IPV4_LOCAL_IFACE
:
431 prefix_cli
.family
= AF_INET
;
432 prefix_cli
.prefixlen
=
433 s_entry
->nai_local_prefix_len
;
434 prefix_cli
.u
.prefix4
=
435 s_entry
->nai_local_addr
.ip
._v4_addr
;
436 number_of_sid_clashed
+=
437 srte_ted_do_query_type_e(
438 s_entry
, &prefix_cli
,
439 s_entry
->nai_local_iface
);
441 case SRTE_SEGMENT_NAI_TYPE_IPV6_ALGORITHM
:
442 prefix_cli
.family
= AF_INET6
;
443 prefix_cli
.prefixlen
=
444 s_entry
->nai_local_prefix_len
;
445 prefix_cli
.u
.prefix6
=
446 s_entry
->nai_local_addr
.ip
._v6_addr
;
447 number_of_sid_clashed
+=
448 srte_ted_do_query_type_c(
449 s_entry
, &prefix_cli
,
450 s_entry
->nai_algorithm
);
452 case SRTE_SEGMENT_NAI_TYPE_IPV4_ALGORITHM
:
453 prefix_cli
.family
= AF_INET
;
454 prefix_cli
.prefixlen
=
455 s_entry
->nai_local_prefix_len
;
456 prefix_cli
.u
.prefix4
=
457 s_entry
->nai_local_addr
.ip
._v4_addr
;
458 number_of_sid_clashed
+=
459 srte_ted_do_query_type_c(
460 s_entry
, &prefix_cli
,
461 s_entry
->nai_algorithm
);
463 case SRTE_SEGMENT_NAI_TYPE_NONE
:
464 case SRTE_SEGMENT_NAI_TYPE_IPV4_NODE
:
465 case SRTE_SEGMENT_NAI_TYPE_IPV6_NODE
:
466 case SRTE_SEGMENT_NAI_TYPE_IPV4_UNNUMBERED_ADJACENCY
:
467 case SRTE_SEGMENT_NAI_TYPE_IPV6_ADJACENCY_LINK_LOCAL_ADDRESSES
:
471 if (number_of_sid_clashed
) {
472 SET_FLAG(s_list
->flags
, F_SEGMENT_LIST_SID_CONFLICT
);
473 number_of_sid_clashed
= 0;
475 UNSET_FLAG(s_list
->flags
, F_SEGMENT_LIST_SID_CONFLICT
);
477 srte_apply_changes();
483 * Update a policy binding SID.
485 * @param policy The policy for which the SID should be updated
486 * @param binding_sid The new binding SID for the given policy
488 void srte_policy_update_binding_sid(struct srte_policy
*policy
,
489 uint32_t binding_sid
)
491 if (policy
->binding_sid
!= MPLS_LABEL_NONE
)
492 path_zebra_release_label(policy
->binding_sid
);
494 policy
->binding_sid
= binding_sid
;
496 /* Reinstall the Binding-SID if necessary. */
497 if (policy
->best_candidate
)
498 path_zebra_add_sr_policy(
499 policy
, policy
->best_candidate
->lsp
->segment_list
);
503 * Gives the policy best candidate path.
505 * @param policy The policy we want the best candidate path from
506 * @return The best candidate path
508 static struct srte_candidate
*
509 srte_policy_best_candidate(const struct srte_policy
*policy
)
511 struct srte_candidate
*candidate
;
513 RB_FOREACH_REVERSE (candidate
, srte_candidate_head
,
514 &policy
->candidate_paths
) {
515 /* search for highest preference with existing segment list */
516 if (!CHECK_FLAG(candidate
->flags
, F_CANDIDATE_DELETED
)
517 && candidate
->lsp
->segment_list
518 && (!CHECK_FLAG(candidate
->lsp
->segment_list
->flags
,
519 F_SEGMENT_LIST_SID_CONFLICT
)))
526 void srte_clean_zebra(void)
528 struct srte_policy
*policy
, *safe_pol
;
530 RB_FOREACH_SAFE (policy
, srte_policy_head
, &srte_policies
, safe_pol
)
531 srte_policy_del(policy
);
537 * Apply changes defined by setting the policies, candidate paths
538 * and segment lists modification flags NEW, MODIFIED and DELETED.
540 * This allows the northbound code to delay all the side effects of adding
541 * modifying and deleting them to the end.
543 * Example of marking an object as modified:
544 * `SET_FLAG(obj->flags, F_XXX_MODIFIED)`
546 void srte_apply_changes(void)
548 struct srte_policy
*policy
, *safe_pol
;
549 struct srte_segment_list
*segment_list
, *safe_sl
;
551 RB_FOREACH_SAFE (policy
, srte_policy_head
, &srte_policies
, safe_pol
) {
552 if (CHECK_FLAG(policy
->flags
, F_POLICY_DELETED
)) {
553 if (policy
->status
!= SRTE_POLICY_STATUS_DOWN
) {
554 policy
->status
= SRTE_POLICY_STATUS_DOWN
;
555 srte_policy_status_log(policy
);
557 srte_policy_del(policy
);
560 srte_policy_apply_changes(policy
);
561 UNSET_FLAG(policy
->flags
, F_POLICY_NEW
);
562 UNSET_FLAG(policy
->flags
, F_POLICY_MODIFIED
);
565 RB_FOREACH_SAFE (segment_list
, srte_segment_list_head
,
566 &srte_segment_lists
, safe_sl
) {
567 if (CHECK_FLAG(segment_list
->flags
, F_SEGMENT_LIST_DELETED
)) {
568 srte_segment_list_del(segment_list
);
571 UNSET_FLAG(segment_list
->flags
, F_SEGMENT_LIST_NEW
);
572 UNSET_FLAG(segment_list
->flags
, F_SEGMENT_LIST_MODIFIED
);
577 * Apply changes defined by setting the given policy and its candidate paths
578 * modification flags NEW, MODIFIED and DELETED.
580 * In moste cases `void srte_apply_changes(void)` should be used instead,
581 * this function will not handle the changes of segment lists used by the
584 * @param policy The policy changes has to be applied to.
586 void srte_policy_apply_changes(struct srte_policy
*policy
)
588 struct srte_candidate
*candidate
, *safe
;
589 struct srte_candidate
*old_best_candidate
;
590 struct srte_candidate
*new_best_candidate
;
591 char endpoint
[ENDPOINT_STR_LENGTH
];
593 ipaddr2str(&policy
->endpoint
, endpoint
, sizeof(endpoint
));
595 /* Get old and new best candidate path. */
596 old_best_candidate
= policy
->best_candidate
;
597 new_best_candidate
= srte_policy_best_candidate(policy
);
599 if (new_best_candidate
!= old_best_candidate
) {
601 "SR-TE(%s, %u): best candidate changed from %s to %s",
602 endpoint
, policy
->color
,
603 old_best_candidate
? old_best_candidate
->name
: "none",
604 new_best_candidate
? new_best_candidate
->name
: "none");
606 if (old_best_candidate
) {
607 policy
->best_candidate
= NULL
;
608 UNSET_FLAG(old_best_candidate
->flags
, F_CANDIDATE_BEST
);
609 SET_FLAG(old_best_candidate
->flags
,
610 F_CANDIDATE_MODIFIED
);
613 * Rely on replace semantics if there's a new best
616 if (!new_best_candidate
)
617 path_zebra_delete_sr_policy(policy
);
619 if (new_best_candidate
) {
620 policy
->best_candidate
= new_best_candidate
;
621 SET_FLAG(new_best_candidate
->flags
, F_CANDIDATE_BEST
);
622 SET_FLAG(new_best_candidate
->flags
,
623 F_CANDIDATE_MODIFIED
);
625 path_zebra_add_sr_policy(
626 policy
, new_best_candidate
->lsp
->segment_list
);
628 } else if (new_best_candidate
) {
629 /* The best candidate path did not change, but some of its
630 * attributes or its segment list may have changed.
633 bool candidate_changed
= CHECK_FLAG(new_best_candidate
->flags
,
634 F_CANDIDATE_MODIFIED
);
635 bool segment_list_changed
=
636 new_best_candidate
->lsp
->segment_list
638 new_best_candidate
->lsp
->segment_list
->flags
,
639 F_SEGMENT_LIST_MODIFIED
);
641 if (candidate_changed
|| segment_list_changed
) {
643 "SR-TE(%s, %u): best candidate %s changed",
644 endpoint
, policy
->color
,
645 new_best_candidate
->name
);
647 path_zebra_add_sr_policy(
648 policy
, new_best_candidate
->lsp
->segment_list
);
652 RB_FOREACH_SAFE (candidate
, srte_candidate_head
,
653 &policy
->candidate_paths
, safe
) {
654 if (CHECK_FLAG(candidate
->flags
, F_CANDIDATE_DELETED
)) {
655 trigger_pathd_candidate_removed(candidate
);
656 srte_candidate_del(candidate
);
658 } else if (CHECK_FLAG(candidate
->flags
, F_CANDIDATE_NEW
)) {
659 trigger_pathd_candidate_created(candidate
);
660 } else if (CHECK_FLAG(candidate
->flags
, F_CANDIDATE_MODIFIED
)) {
661 trigger_pathd_candidate_updated(candidate
);
662 } else if (candidate
->lsp
->segment_list
663 && CHECK_FLAG(candidate
->lsp
->segment_list
->flags
,
664 F_SEGMENT_LIST_MODIFIED
)) {
665 trigger_pathd_candidate_updated(candidate
);
668 UNSET_FLAG(candidate
->flags
, F_CANDIDATE_NEW
);
669 UNSET_FLAG(candidate
->flags
, F_CANDIDATE_MODIFIED
);
674 * Adds a candidate path to a policy.
676 * @param policy The policy the candidate path should be added to
677 * @param preference The preference of the candidate path to be added
678 * @return The added candidate path
680 struct srte_candidate
*srte_candidate_add(struct srte_policy
*policy
,
682 enum srte_protocol_origin origin
,
683 const char *originator
)
685 struct srte_candidate
*candidate
;
686 struct srte_lsp
*lsp
;
688 candidate
= XCALLOC(MTYPE_PATH_SR_CANDIDATE
, sizeof(*candidate
));
689 lsp
= XCALLOC(MTYPE_PATH_SR_CANDIDATE
, sizeof(*lsp
));
691 candidate
->preference
= preference
;
692 candidate
->policy
= policy
;
693 candidate
->type
= SRTE_CANDIDATE_TYPE_UNDEFINED
;
694 candidate
->discriminator
= frr_weak_random();
695 candidate
->protocol_origin
= origin
;
696 if (originator
!= NULL
) {
697 strlcpy(candidate
->originator
, originator
,
698 sizeof(candidate
->originator
));
699 lsp
->protocol_origin
= origin
;
702 if (candidate
->protocol_origin
== SRTE_ORIGIN_PCEP
703 || candidate
->protocol_origin
== SRTE_ORIGIN_BGP
) {
704 candidate
->type
= SRTE_CANDIDATE_TYPE_DYNAMIC
;
706 lsp
->candidate
= candidate
;
707 candidate
->lsp
= lsp
;
709 RB_INSERT(srte_candidate_head
, &policy
->candidate_paths
, candidate
);
715 * Deletes a candidate.
717 * The corresponding LSP will be removed alongside the candidate path.
718 * The given candidate will be freed and shouldn't be used anymore after the
719 * calling this function.
721 * @param candidate The candidate path to delete
723 void srte_candidate_del(struct srte_candidate
*candidate
)
725 struct srte_policy
*srte_policy
= candidate
->policy
;
727 RB_REMOVE(srte_candidate_head
, &srte_policy
->candidate_paths
,
730 XFREE(MTYPE_PATH_SR_CANDIDATE
, candidate
->lsp
);
731 XFREE(MTYPE_PATH_SR_CANDIDATE
, candidate
);
735 * Sets the bandwidth constraint of given candidate path.
737 * The corresponding LSP will be changed too.
739 * @param candidate The candidate path of which the bandwidth should be changed
740 * @param bandwidth The Bandwidth constraint to set to the candidate path
741 * @param required If the constraint is required (true) or only desired (false)
743 void srte_candidate_set_bandwidth(struct srte_candidate
*candidate
,
744 float bandwidth
, bool required
)
746 struct srte_policy
*policy
= candidate
->policy
;
747 char endpoint
[ENDPOINT_STR_LENGTH
];
749 ipaddr2str(&policy
->endpoint
, endpoint
, sizeof(endpoint
));
751 "SR-TE(%s, %u): candidate %s %sconfig bandwidth set to %f B/s",
752 endpoint
, policy
->color
, candidate
->name
,
753 required
? "required " : "", bandwidth
);
754 SET_FLAG(candidate
->flags
, F_CANDIDATE_HAS_BANDWIDTH
);
755 COND_FLAG(candidate
->flags
, F_CANDIDATE_REQUIRED_BANDWIDTH
, required
);
756 candidate
->bandwidth
= bandwidth
;
758 srte_lsp_set_bandwidth(candidate
->lsp
, bandwidth
, required
);
762 * Sets the bandwidth constraint of the given LSP.
764 * The changes will not be shown as part of the running configuration.
766 * @param lsp The lsp of which the bandwidth should be changed
767 * @param bandwidth The Bandwidth constraint to set to the candidate path
768 * @param required If the constraint is required (true) or only desired (false)
770 void srte_lsp_set_bandwidth(struct srte_lsp
*lsp
, float bandwidth
,
773 struct srte_candidate
*candidate
= lsp
->candidate
;
774 struct srte_policy
*policy
= candidate
->policy
;
775 char endpoint
[ENDPOINT_STR_LENGTH
];
777 ipaddr2str(&policy
->endpoint
, endpoint
, sizeof(endpoint
));
779 "SR-TE(%s, %u): candidate %s %slsp bandwidth set to %f B/s",
780 endpoint
, policy
->color
, candidate
->name
,
781 required
? "required" : "", bandwidth
);
782 SET_FLAG(lsp
->flags
, F_CANDIDATE_HAS_BANDWIDTH
);
783 COND_FLAG(lsp
->flags
, F_CANDIDATE_REQUIRED_BANDWIDTH
, required
);
784 lsp
->bandwidth
= bandwidth
;
788 * Remove a candidate path bandwidth constraint.
790 * The corresponding LSP will be changed too.
792 * @param candidate The candidate path of which the bandwidth should be removed
794 void srte_candidate_unset_bandwidth(struct srte_candidate
*candidate
)
796 struct srte_policy
*policy
= candidate
->policy
;
797 char endpoint
[ENDPOINT_STR_LENGTH
];
799 ipaddr2str(&policy
->endpoint
, endpoint
, sizeof(endpoint
));
800 PATH_POLICY_DEBUG("SR-TE(%s, %u): candidate %s config bandwidth unset",
801 endpoint
, policy
->color
, candidate
->name
);
802 UNSET_FLAG(candidate
->flags
, F_CANDIDATE_HAS_BANDWIDTH
);
803 UNSET_FLAG(candidate
->flags
, F_CANDIDATE_REQUIRED_BANDWIDTH
);
804 candidate
->bandwidth
= 0;
805 SET_FLAG(candidate
->flags
, F_CANDIDATE_MODIFIED
);
806 srte_lsp_unset_bandwidth(candidate
->lsp
);
810 * Remove an LSP bandwidth constraint.
812 * The changes will not be shown as part of the running configuration.
814 * @param lsp The lsp of which the bandwidth should be changed
816 void srte_lsp_unset_bandwidth(struct srte_lsp
*lsp
)
818 struct srte_candidate
*candidate
= lsp
->candidate
;
819 struct srte_policy
*policy
= candidate
->policy
;
820 char endpoint
[ENDPOINT_STR_LENGTH
];
822 ipaddr2str(&policy
->endpoint
, endpoint
, sizeof(endpoint
));
823 PATH_POLICY_DEBUG("SR-TE(%s, %u): candidate %s lsp bandwidth unset",
824 endpoint
, policy
->color
, candidate
->name
);
825 UNSET_FLAG(lsp
->flags
, F_CANDIDATE_HAS_BANDWIDTH
);
826 UNSET_FLAG(lsp
->flags
, F_CANDIDATE_REQUIRED_BANDWIDTH
);
827 SET_FLAG(candidate
->flags
, F_CANDIDATE_MODIFIED
);
832 * Sets a candidate path metric constraint.
834 * The corresponding LSP will be changed too.
836 * @param candidate The candidate path of which the metric should be changed
837 * @param type The metric type
838 * @param value The metric value
839 * @param required If the constraint is required (true) or only desired (false)
840 * @param is_bound If the metric is an indicative value or a strict upper bound
841 * @param is_computed If the metric was computed or configured
843 void srte_candidate_set_metric(struct srte_candidate
*candidate
,
844 enum srte_candidate_metric_type type
,
845 float value
, bool required
, bool is_bound
,
848 struct srte_policy
*policy
= candidate
->policy
;
849 char endpoint
[ENDPOINT_STR_LENGTH
];
851 ipaddr2str(&policy
->endpoint
, endpoint
, sizeof(endpoint
));
853 "SR-TE(%s, %u): candidate %s %sconfig metric %s (%u) set to %f (is-bound: %s; is_computed: %s)",
854 endpoint
, policy
->color
, candidate
->name
,
855 required
? "required " : "", srte_candidate_metric_name(type
),
856 type
, value
, is_bound
? "true" : "false",
857 is_computed
? "true" : "false");
858 assert((type
> 0) && (type
<= MAX_METRIC_TYPE
));
859 srte_set_metric(&candidate
->metrics
[type
- 1], value
, required
,
860 is_bound
, is_computed
);
861 srte_lsp_set_metric(candidate
->lsp
, type
, value
, required
, is_bound
,
863 SET_FLAG(candidate
->flags
, F_CANDIDATE_MODIFIED
);
867 * Sets an LSP metric constraint.
869 * The changes will not be shown as part of the running configuration.
871 * @param lsp The LSP of which the metric should be changed
872 * @param type The metric type
873 * @param value The metric value
874 * @param required If the constraint is required (true) or only desired (false)
875 * @param is_bound If the metric is an indicative value or a strict upper bound
876 * @param is_computed If the metric was computed or configured
878 void srte_lsp_set_metric(struct srte_lsp
*lsp
,
879 enum srte_candidate_metric_type type
, float value
,
880 bool required
, bool is_bound
, bool is_computed
)
882 struct srte_candidate
*candidate
= lsp
->candidate
;
883 struct srte_policy
*policy
= candidate
->policy
;
884 char endpoint
[ENDPOINT_STR_LENGTH
];
886 ipaddr2str(&policy
->endpoint
, endpoint
, sizeof(endpoint
));
888 "SR-TE(%s, %u): candidate %s %slsp metric %s (%u) set to %f (is-bound: %s; is_computed: %s)",
889 endpoint
, policy
->color
, candidate
->name
,
890 required
? "required " : "", srte_candidate_metric_name(type
),
891 type
, value
, is_bound
? "true" : "false",
892 is_computed
? "true" : "false");
893 assert((type
> 0) && (type
<= MAX_METRIC_TYPE
));
894 srte_set_metric(&lsp
->metrics
[type
- 1], value
, required
, is_bound
,
898 void srte_set_metric(struct srte_metric
*metric
, float value
, bool required
,
899 bool is_bound
, bool is_computed
)
901 SET_FLAG(metric
->flags
, F_METRIC_IS_DEFINED
);
902 COND_FLAG(metric
->flags
, F_METRIC_IS_REQUIRED
, required
);
903 COND_FLAG(metric
->flags
, F_METRIC_IS_BOUND
, is_bound
);
904 COND_FLAG(metric
->flags
, F_METRIC_IS_COMPUTED
, is_computed
);
905 metric
->value
= value
;
909 * Removes a candidate path metric constraint.
911 * The corresponding LSP will be changed too.
913 * @param candidate The candidate path from which the metric should be removed
914 * @param type The metric type
916 void srte_candidate_unset_metric(struct srte_candidate
*candidate
,
917 enum srte_candidate_metric_type type
)
919 struct srte_policy
*policy
= candidate
->policy
;
920 char endpoint
[ENDPOINT_STR_LENGTH
];
922 ipaddr2str(&policy
->endpoint
, endpoint
, sizeof(endpoint
));
924 "SR-TE(%s, %u): candidate %s config metric %s (%u) unset",
925 endpoint
, policy
->color
, candidate
->name
,
926 srte_candidate_metric_name(type
), type
);
927 assert((type
> 0) && (type
<= MAX_METRIC_TYPE
));
928 srte_unset_metric(&candidate
->metrics
[type
- 1]);
929 srte_lsp_unset_metric(candidate
->lsp
, type
);
930 SET_FLAG(candidate
->flags
, F_CANDIDATE_MODIFIED
);
934 * Removes a candidate path metric constraint.
936 * The changes will not be shown as part of the running configuration.
938 * @param lsp The LSP from which the metric should be removed
939 * @param type The metric type
941 void srte_lsp_unset_metric(struct srte_lsp
*lsp
,
942 enum srte_candidate_metric_type type
)
944 struct srte_candidate
*candidate
= lsp
->candidate
;
945 struct srte_policy
*policy
= candidate
->policy
;
946 char endpoint
[ENDPOINT_STR_LENGTH
];
948 ipaddr2str(&policy
->endpoint
, endpoint
, sizeof(endpoint
));
950 "SR-TE(%s, %u): candidate %s lsp metric %s (%u) unset",
951 endpoint
, policy
->color
, candidate
->name
,
952 srte_candidate_metric_name(type
), type
);
953 assert((type
> 0) && (type
<= MAX_METRIC_TYPE
));
954 srte_unset_metric(&lsp
->metrics
[type
- 1]);
957 void srte_unset_metric(struct srte_metric
*metric
)
959 UNSET_FLAG(metric
->flags
, F_METRIC_IS_DEFINED
);
960 UNSET_FLAG(metric
->flags
, F_METRIC_IS_BOUND
);
961 UNSET_FLAG(metric
->flags
, F_METRIC_IS_COMPUTED
);
966 * Sets a candidate path objective function.
968 * @param candidate The candidate path of which the OF should be changed
969 * @param required If the constraint is required (true) or only desired (false)
970 * @param type The objective function type
972 void srte_candidate_set_objfun(struct srte_candidate
*candidate
, bool required
,
973 enum objfun_type type
)
975 struct srte_policy
*policy
= candidate
->policy
;
976 char endpoint
[ENDPOINT_STR_LENGTH
];
978 ipaddr2str(&policy
->endpoint
, endpoint
, sizeof(endpoint
));
980 candidate
->objfun
= type
;
981 SET_FLAG(candidate
->flags
, F_CANDIDATE_HAS_OBJFUN
);
982 COND_FLAG(candidate
->flags
, F_CANDIDATE_REQUIRED_OBJFUN
, required
);
983 SET_FLAG(candidate
->flags
, F_CANDIDATE_MODIFIED
);
985 "SR-TE(%s, %u): candidate %s %sobjective function set to %s",
986 endpoint
, policy
->color
, candidate
->name
,
987 required
? "required " : "", objfun_type_name(type
));
991 * Removed the objective function constraint from a candidate path.
993 * @param candidate The candidate path from which the OF should be removed
995 void srte_candidate_unset_objfun(struct srte_candidate
*candidate
)
997 struct srte_policy
*policy
= candidate
->policy
;
998 char endpoint
[ENDPOINT_STR_LENGTH
];
1000 ipaddr2str(&policy
->endpoint
, endpoint
, sizeof(endpoint
));
1002 UNSET_FLAG(candidate
->flags
, F_CANDIDATE_HAS_OBJFUN
);
1003 UNSET_FLAG(candidate
->flags
, F_CANDIDATE_REQUIRED_OBJFUN
);
1004 SET_FLAG(candidate
->flags
, F_CANDIDATE_MODIFIED
);
1005 candidate
->objfun
= OBJFUN_UNDEFINED
;
1007 "SR-TE(%s, %u): candidate %s objective functions preferences unset",
1008 endpoint
, policy
->color
, candidate
->name
);
1011 static uint32_t filter_type_to_flag(enum affinity_filter_type type
)
1014 case AFFINITY_FILTER_EXCLUDE_ANY
:
1015 return F_CANDIDATE_HAS_EXCLUDE_ANY
;
1016 case AFFINITY_FILTER_INCLUDE_ANY
:
1017 return F_CANDIDATE_HAS_INCLUDE_ANY
;
1018 case AFFINITY_FILTER_INCLUDE_ALL
:
1019 return F_CANDIDATE_HAS_INCLUDE_ALL
;
1020 case AFFINITY_FILTER_UNDEFINED
:
1024 assert(!"Reached end of function we should never hit");
1027 static const char *filter_type_name(enum affinity_filter_type type
)
1030 case AFFINITY_FILTER_EXCLUDE_ANY
:
1031 return "exclude-any";
1032 case AFFINITY_FILTER_INCLUDE_ANY
:
1033 return "include-any";
1034 case AFFINITY_FILTER_INCLUDE_ALL
:
1035 return "include-all";
1036 case AFFINITY_FILTER_UNDEFINED
:
1040 assert(!"Reached end of function we should never hit");
1044 * Sets a candidate path affinity filter constraint.
1046 * @param candidate The candidate path of which the constraint should be changed
1047 * @param type The affinity constraint type to set
1048 * @param filter The bitmask filter of the constraint
1050 void srte_candidate_set_affinity_filter(struct srte_candidate
*candidate
,
1051 enum affinity_filter_type type
,
1054 struct srte_policy
*policy
= candidate
->policy
;
1055 char endpoint
[ENDPOINT_STR_LENGTH
];
1057 ipaddr2str(&policy
->endpoint
, endpoint
, sizeof(endpoint
));
1059 assert(type
> AFFINITY_FILTER_UNDEFINED
);
1060 assert(type
<= MAX_AFFINITY_FILTER_TYPE
);
1061 SET_FLAG(candidate
->flags
, filter_type_to_flag(type
));
1062 SET_FLAG(candidate
->flags
, F_CANDIDATE_MODIFIED
);
1063 candidate
->affinity_filters
[type
- 1] = filter
;
1065 "SR-TE(%s, %u): candidate %s affinity filter %s set to 0x%08x",
1066 endpoint
, policy
->color
, candidate
->name
,
1067 filter_type_name(type
), filter
);
1071 * Removes a candidate path affinity filter constraint.
1073 * @param candidate The candidate path from which the constraint should be
1075 * @param type The affinity constraint type to remove
1077 void srte_candidate_unset_affinity_filter(struct srte_candidate
*candidate
,
1078 enum affinity_filter_type type
)
1080 struct srte_policy
*policy
= candidate
->policy
;
1081 char endpoint
[ENDPOINT_STR_LENGTH
];
1083 ipaddr2str(&policy
->endpoint
, endpoint
, sizeof(endpoint
));
1085 assert(type
> AFFINITY_FILTER_UNDEFINED
);
1086 assert(type
<= MAX_AFFINITY_FILTER_TYPE
);
1087 UNSET_FLAG(candidate
->flags
, filter_type_to_flag(type
));
1088 SET_FLAG(candidate
->flags
, F_CANDIDATE_MODIFIED
);
1089 candidate
->affinity_filters
[type
- 1] = 0;
1091 "SR-TE(%s, %u): candidate %s affinity filter %s unset",
1092 endpoint
, policy
->color
, candidate
->name
,
1093 filter_type_name(type
));
1097 * Searches for a candidate path of the given policy.
1099 * @param policy The policy to search for candidate path
1100 * @param preference The preference of the candidate path you are looking for
1101 * @return The candidate path if found, NULL otherwise
1103 struct srte_candidate
*srte_candidate_find(struct srte_policy
*policy
,
1104 uint32_t preference
)
1106 struct srte_candidate search
;
1108 search
.preference
= preference
;
1109 return RB_FIND(srte_candidate_head
, &policy
->candidate_paths
, &search
);
1113 * Searches for a an entry of a given segment list.
1115 * @param segment_list The segment list to search for the entry
1116 * @param index The index of the entry you are looking for
1117 * @return The segment list entry if found, NULL otherwise.
1119 struct srte_segment_entry
*
1120 srte_segment_entry_find(struct srte_segment_list
*segment_list
, uint32_t index
)
1122 struct srte_segment_entry search
;
1124 search
.index
= index
;
1125 return RB_FIND(srte_segment_entry_head
, &segment_list
->segments
,
1130 * Updates a candidate status.
1132 * @param candidate The candidate of which the status should be updated
1133 * @param status The new candidate path status
1135 void srte_candidate_status_update(struct srte_candidate
*candidate
, int status
)
1137 struct srte_policy
*policy
= candidate
->policy
;
1138 char endpoint
[ENDPOINT_STR_LENGTH
];
1140 ipaddr2str(&policy
->endpoint
, endpoint
, sizeof(endpoint
));
1141 PATH_POLICY_DEBUG("SR-TE(%s, %u): zebra updated status to %d", endpoint
,
1142 policy
->color
, status
);
1144 case ZEBRA_SR_POLICY_DOWN
:
1145 switch (policy
->status
) {
1146 /* If the policy is GOING_UP, and zebra faild
1147 to install it, we wait for zebra to retry */
1148 /* TODO: Add some timeout after which we would
1149 get is back to DOWN and remove the
1151 case SRTE_POLICY_STATUS_GOING_UP
:
1152 case SRTE_POLICY_STATUS_DOWN
:
1154 case SRTE_POLICY_STATUS_UNKNOWN
:
1155 case SRTE_POLICY_STATUS_UP
:
1156 case SRTE_POLICY_STATUS_GOING_DOWN
:
1157 policy
->status
= SRTE_POLICY_STATUS_DOWN
;
1158 srte_policy_status_log(policy
);
1162 case ZEBRA_SR_POLICY_UP
:
1163 switch (policy
->status
) {
1164 case SRTE_POLICY_STATUS_UP
:
1166 case SRTE_POLICY_STATUS_UNKNOWN
:
1167 case SRTE_POLICY_STATUS_DOWN
:
1168 case SRTE_POLICY_STATUS_GOING_DOWN
:
1169 case SRTE_POLICY_STATUS_GOING_UP
:
1170 policy
->status
= SRTE_POLICY_STATUS_UP
;
1171 srte_policy_status_log(policy
);
1177 trigger_pathd_candidate_updated(candidate
);
1181 * Flags the segment lists from give originator for removal.
1183 * The function srte_apply_changes must be called afterward for
1184 * the segment list to be removed.
1186 * @param originator The originator tag of the segment list to be marked
1187 * @param force If the unset should be forced regardless of the originator
1189 void srte_candidate_unset_segment_list(const char *originator
, bool force
)
1191 if (originator
== NULL
) {
1193 "Cannot unset segment list because originator is NULL");
1197 PATH_POLICY_DEBUG("Unset segment lists for originator %s", originator
);
1199 /* Iterate the policies, then iterate each policy's candidate path
1200 * to check the candidate path's segment list originator */
1201 struct srte_policy
*policy
;
1202 RB_FOREACH (policy
, srte_policy_head
, &srte_policies
) {
1203 PATH_POLICY_DEBUG("Unset segment lists checking policy %s",
1205 struct srte_candidate
*candidate
;
1206 RB_FOREACH (candidate
, srte_candidate_head
,
1207 &policy
->candidate_paths
) {
1209 "Unset segment lists checking candidate %s",
1211 if (candidate
->lsp
== NULL
) {
1215 /* The candidate->lsp->segment_list is operational data,
1216 * configured by the PCE. We dont want to modify the
1217 * candidate->segment_list,
1218 * which is configuration data. */
1219 struct srte_segment_list
*segment_list
=
1220 candidate
->lsp
->segment_list
;
1221 if (segment_list
== NULL
) {
1225 if (segment_list
->protocol_origin
1226 == SRTE_ORIGIN_LOCAL
) {
1228 "Cannot unset segment list %s because it was created locally",
1229 segment_list
->name
);
1233 /* In the case of last pce,we force the unset
1234 * because we don't have pce by prefix (TODO) is all
1236 if (strncmp(segment_list
->originator
, originator
,
1237 sizeof(segment_list
->originator
))
1240 PATH_POLICY_DEBUG("Unset segment list %s",
1241 segment_list
->name
);
1242 SET_FLAG(segment_list
->flags
,
1243 F_SEGMENT_LIST_DELETED
);
1244 SET_FLAG(candidate
->flags
,
1245 F_CANDIDATE_MODIFIED
);
1246 candidate
->lsp
->segment_list
= NULL
;
1253 * Gives a string representation of given protocol origin enum.
1255 * @param origin The enum you want a string representation of
1256 * @return The string representation of given enum
1258 const char *srte_origin2str(enum srte_protocol_origin origin
)
1261 case SRTE_ORIGIN_PCEP
:
1263 case SRTE_ORIGIN_BGP
:
1265 case SRTE_ORIGIN_LOCAL
:
1267 case SRTE_ORIGIN_UNDEFINED
:
1271 assert(!"Reached end of function we should never hit");
1274 void path_policy_show_debugging(struct vty
*vty
)
1276 if (DEBUG_FLAGS_CHECK(&path_policy_debug
, PATH_POLICY_DEBUG_BASIC
))
1277 vty_out(vty
, " Path policy debugging is on\n");
1280 void pathd_shutdown(void)
1282 path_ted_teardown();
1287 void trigger_pathd_candidate_created(struct srte_candidate
*candidate
)
1289 /* The hook is called asynchronously to let the PCEP module
1290 time to send a response to the PCE before receiving any updates from
1291 pathd. In addition, a minimum amount of time need to pass before
1292 the hook is called to prevent the hook to be called multiple times
1293 from changing the candidate by hand with the console */
1294 if (candidate
->hook_timer
!= NULL
)
1296 thread_add_timer(master
, trigger_pathd_candidate_created_timer
,
1297 (void *)candidate
, HOOK_DELAY
, &candidate
->hook_timer
);
1300 void trigger_pathd_candidate_created_timer(struct thread
*thread
)
1302 struct srte_candidate
*candidate
= THREAD_ARG(thread
);
1303 candidate
->hook_timer
= NULL
;
1304 hook_call(pathd_candidate_created
, candidate
);
1307 void trigger_pathd_candidate_updated(struct srte_candidate
*candidate
)
1309 /* The hook is called asynchronously to let the PCEP module
1310 time to send a response to the PCE before receiving any updates from
1311 pathd. In addition, a minimum amount of time need to pass before
1312 the hook is called to prevent the hook to be called multiple times
1313 from changing the candidate by hand with the console */
1314 if (candidate
->hook_timer
!= NULL
)
1316 thread_add_timer(master
, trigger_pathd_candidate_updated_timer
,
1317 (void *)candidate
, HOOK_DELAY
, &candidate
->hook_timer
);
1320 void trigger_pathd_candidate_updated_timer(struct thread
*thread
)
1322 struct srte_candidate
*candidate
= THREAD_ARG(thread
);
1323 candidate
->hook_timer
= NULL
;
1324 hook_call(pathd_candidate_updated
, candidate
);
1327 void trigger_pathd_candidate_removed(struct srte_candidate
*candidate
)
1329 /* The hook needs to be call synchronously, otherwise the candidate
1330 path will be already deleted when the handler is called */
1331 if (candidate
->hook_timer
!= NULL
) {
1332 thread_cancel(&candidate
->hook_timer
);
1333 candidate
->hook_timer
= NULL
;
1335 hook_call(pathd_candidate_removed
, candidate
);
1338 const char *srte_candidate_metric_name(enum srte_candidate_metric_type type
)
1341 case SRTE_CANDIDATE_METRIC_TYPE_IGP
:
1343 case SRTE_CANDIDATE_METRIC_TYPE_TE
:
1345 case SRTE_CANDIDATE_METRIC_TYPE_HC
:
1347 case SRTE_CANDIDATE_METRIC_TYPE_ABC
:
1349 case SRTE_CANDIDATE_METRIC_TYPE_LMLL
:
1351 case SRTE_CANDIDATE_METRIC_TYPE_CIGP
:
1353 case SRTE_CANDIDATE_METRIC_TYPE_CTE
:
1355 case SRTE_CANDIDATE_METRIC_TYPE_PIGP
:
1357 case SRTE_CANDIDATE_METRIC_TYPE_PTE
:
1359 case SRTE_CANDIDATE_METRIC_TYPE_PHC
:
1361 case SRTE_CANDIDATE_METRIC_TYPE_MSD
:
1363 case SRTE_CANDIDATE_METRIC_TYPE_PD
:
1365 case SRTE_CANDIDATE_METRIC_TYPE_PDV
:
1367 case SRTE_CANDIDATE_METRIC_TYPE_PL
:
1369 case SRTE_CANDIDATE_METRIC_TYPE_PPD
:
1371 case SRTE_CANDIDATE_METRIC_TYPE_PPDV
:
1373 case SRTE_CANDIDATE_METRIC_TYPE_PPL
:
1375 case SRTE_CANDIDATE_METRIC_TYPE_NAP
:
1377 case SRTE_CANDIDATE_METRIC_TYPE_NLP
:
1379 case SRTE_CANDIDATE_METRIC_TYPE_DC
:
1381 case SRTE_CANDIDATE_METRIC_TYPE_BNC
:
1388 int32_t srte_ted_do_query_type_c(struct srte_segment_entry
*entry
,
1389 struct prefix
*prefix_cli
, uint32_t algo
)
1392 uint32_t ted_sid
= MPLS_LABEL_NONE
;
1394 if (!entry
|| !prefix_cli
)
1397 if (!path_ted_is_initialized())
1400 ted_sid
= path_ted_query_type_c(prefix_cli
, algo
);
1401 if (ted_sid
== MPLS_LABEL_NONE
) {
1402 zlog_warn(" %s: PATHD-TED: SL: ERROR query C : ted-sid (%d)",
1406 "%s: PATHD-TED: SL: Success query C : ted-sid (%d)",
1409 if (CHECK_SID(entry
->segment_list
->protocol_origin
, ted_sid
,
1410 entry
->sid_value
)) {
1411 status
= PATH_SID_ERROR
;
1413 srte_segment_set_local_modification(entry
->segment_list
, entry
,
1418 int32_t srte_ted_do_query_type_e(struct srte_segment_entry
*entry
,
1419 struct prefix
*prefix_cli
,
1420 uint32_t local_iface
)
1423 uint32_t ted_sid
= MPLS_LABEL_NONE
;
1425 if (!entry
|| !prefix_cli
)
1428 if (!path_ted_is_initialized())
1431 ted_sid
= path_ted_query_type_e(prefix_cli
, local_iface
);
1432 if (ted_sid
== MPLS_LABEL_NONE
) {
1433 zlog_warn(" %s: PATHD-TED: SL: ERROR query E : ted-sid (%d)",
1437 "%s: PATHD-TED: SL: Success query E : ted-sid (%d)",
1440 if (CHECK_SID(entry
->segment_list
->protocol_origin
, ted_sid
,
1441 entry
->sid_value
)) {
1442 status
= PATH_SID_ERROR
;
1444 srte_segment_set_local_modification(entry
->segment_list
, entry
,
1449 int32_t srte_ted_do_query_type_f(struct srte_segment_entry
*entry
,
1450 struct ipaddr
*local
, struct ipaddr
*remote
)
1453 uint32_t ted_sid
= MPLS_LABEL_NONE
;
1455 if (!entry
|| !local
|| !remote
)
1458 if (!path_ted_is_initialized())
1461 ted_sid
= path_ted_query_type_f(local
, remote
);
1462 if (ted_sid
== MPLS_LABEL_NONE
) {
1463 zlog_warn("%s:SL: ERROR query F : ted-sid (%d)", __func__
,
1466 PATH_TED_DEBUG("%s:SL: Success query F : ted-sid (%d)",
1469 if (CHECK_SID(entry
->segment_list
->protocol_origin
, ted_sid
,
1470 entry
->sid_value
)) {
1471 status
= PATH_SID_ERROR
;
1473 srte_segment_set_local_modification(entry
->segment_list
, entry
,