2 * Copyright (C) 2020 NetDEF, Inc.
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)
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
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
23 #include "lib_errors.h"
29 #include "pathd/pathd.h"
30 #include "pathd/path_zebra.h"
31 #include "pathd/path_debug.h"
32 #include "pathd/path_ted.h"
36 DEFINE_MGROUP(PATHD
, "pathd");
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");
42 DEFINE_HOOK(pathd_candidate_created
, (struct srte_candidate
* candidate
),
44 DEFINE_HOOK(pathd_candidate_updated
, (struct srte_candidate
* candidate
),
46 DEFINE_HOOK(pathd_candidate_removed
, (struct srte_candidate
* candidate
),
49 struct debug path_policy_debug
;
51 #define PATH_POLICY_DEBUG(fmt, ...) \
53 if (DEBUG_FLAGS_CHECK(&path_policy_debug, \
54 PATH_POLICY_DEBUG_BASIC)) \
55 DEBUGD(&path_policy_debug, "policy: " fmt, \
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
);
66 srte_candidate_metric_name(enum srte_candidate_metric_type type
);
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
);
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
)
77 return a
->index
- b
->index
;
79 RB_GENERATE(srte_segment_entry_head
, srte_segment_entry
, entry
,
80 srte_segment_entry_compare
)
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
)
86 return strcmp(a
->name
, b
->name
);
88 RB_GENERATE(srte_segment_list_head
, srte_segment_list
, entry
,
89 srte_segment_list_compare
)
91 struct srte_segment_list_head srte_segment_lists
=
92 RB_INITIALIZER(&srte_segment_lists
);
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
)
98 return a
->preference
- b
->preference
;
100 RB_GENERATE(srte_candidate_head
, srte_candidate
, entry
, srte_candidate_compare
)
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
)
106 return sr_policy_compare(&a
->endpoint
, &b
->endpoint
, a
->color
,
109 RB_GENERATE(srte_policy_head
, srte_policy
, entry
, srte_policy_compare
)
111 struct srte_policy_head srte_policies
= RB_INITIALIZER(&srte_policies
);
113 static void srte_policy_status_log(struct srte_policy
*policy
)
115 char endpoint
[ENDPOINT_STR_LENGTH
];
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
,
121 } else if (policy
->status
== SRTE_POLICY_STATUS_UP
) {
122 PATH_POLICY_DEBUG("SR-TE(%s, %u): policy is UP", endpoint
,
128 * Adds a segment list to pathd.
130 * @param name The name of the segment list to add
131 * @return The added segment list
133 struct srte_segment_list
*srte_segment_list_add(const char *name
)
135 struct srte_segment_list
*segment_list
;
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
);
146 * Deletes a segment list from pathd.
148 * The given segment list structure will be freed and should not be used anymore
149 * after calling this function.
151 * @param segment_list the segment list to remove from pathd.
153 void srte_segment_list_del(struct srte_segment_list
*segment_list
)
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
);
160 RB_REMOVE(srte_segment_list_head
, &srte_segment_lists
, segment_list
);
161 XFREE(MTYPE_PATH_SEGMENT_LIST
, segment_list
);
165 * Search for a segment list by name.
167 * @param name The name of the segment list to look for
168 * @return The segment list if found, NULL otherwise
170 struct srte_segment_list
*srte_segment_list_find(const char *name
)
172 struct srte_segment_list search
;
174 strlcpy(search
.name
, name
, sizeof(search
.name
));
175 return RB_FIND(srte_segment_list_head
, &srte_segment_lists
, &search
);
179 * Adds a segment to a segment list.
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
185 struct srte_segment_entry
*
186 srte_segment_entry_add(struct srte_segment_list
*segment_list
, uint32_t index
)
188 struct srte_segment_entry
*segment
;
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
);
199 * Deletes a segment from a segment list.
201 * @param segment The segment to be removed
203 void srte_segment_entry_del(struct srte_segment_entry
*segment
)
205 RB_REMOVE(srte_segment_entry_head
, &segment
->segment_list
->segments
,
207 XFREE(MTYPE_PATH_SEGMENT_LIST
, segment
);
211 * Set the node or adjacency identifier of a segment.
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
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
)
228 struct prefix pre
= {0};
230 if (!segment
|| !local_ip
|| !remote_ip
)
233 segment
->nai_type
= type
;
234 memcpy(&segment
->nai_local_addr
, local_ip
, sizeof(struct ipaddr
));
237 case SRTE_SEGMENT_NAI_TYPE_IPV4_NODE
:
238 case SRTE_SEGMENT_NAI_TYPE_IPV6_NODE
:
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
);
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
;
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
);
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
);
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
);
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
);
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;
294 * Mark segment as modified depending in protocol and sid conditions
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
302 void srte_segment_set_local_modification(struct srte_segment_list
*s_list
,
303 struct srte_segment_entry
*s_entry
,
306 if (!s_list
|| !s_entry
)
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
);
317 * Add a policy to pathd.
319 * WARNING: The color 0 is a special case as it is the no-color.
321 * @param color The color of the policy.
322 * @param endpoint The IP address of the policy endpoint
323 * @return The created policy
325 struct srte_policy
*srte_policy_add(uint32_t color
, struct ipaddr
*endpoint
,
326 enum srte_protocol_origin origin
,
327 const char *originator
)
329 struct srte_policy
*policy
;
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
));
340 RB_INIT(srte_candidate_head
, &policy
->candidate_paths
);
341 RB_INSERT(srte_policy_head
, &srte_policies
, policy
);
347 * Delete a policy from pathd.
349 * The given policy structure will be freed and should never be used again
350 * after calling this function.
352 * @param policy The policy to be removed
354 void srte_policy_del(struct srte_policy
*policy
)
356 struct srte_candidate
*candidate
;
358 path_zebra_delete_sr_policy(policy
);
360 path_zebra_release_label(policy
->binding_sid
);
362 while (!RB_EMPTY(srte_candidate_head
, &policy
->candidate_paths
)) {
364 RB_ROOT(srte_candidate_head
, &policy
->candidate_paths
);
365 trigger_pathd_candidate_removed(candidate
);
366 srte_candidate_del(candidate
);
369 RB_REMOVE(srte_policy_head
, &srte_policies
, policy
);
370 XFREE(MTYPE_PATH_SR_POLICY
, policy
);
374 * Search for a policy by color and endpoint.
376 * WARNING: The color 0 is a special case as it is the no-color.
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
382 struct srte_policy
*srte_policy_find(uint32_t color
, struct ipaddr
*endpoint
)
384 struct srte_policy search
;
386 search
.color
= color
;
387 search
.endpoint
= *endpoint
;
388 return RB_FIND(srte_policy_head
, &srte_policies
, &search
);
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
396 int srte_policy_update_ted_sid(void)
399 int number_of_sid_clashed
= 0;
400 struct srte_segment_list
*s_list
;
401 struct srte_segment_entry
*s_entry
;
403 if (!path_ted_is_initialized())
405 if (RB_EMPTY(srte_segment_list_head
, &srte_segment_lists
))
408 RB_FOREACH (s_list
, srte_segment_list_head
, &srte_segment_lists
) {
409 if (CHECK_FLAG(s_list
->flags
, F_SEGMENT_LIST_DELETED
))
411 RB_FOREACH (s_entry
, srte_segment_entry_head
,
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
,
417 s_entry
->nai_local_prefix_len
,
418 s_entry
->nai_local_iface
,
419 s_entry
->nai_algorithm
);
420 struct prefix prefix_cli
= {0};
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(
428 &s_entry
->nai_local_addr
,
429 &s_entry
->nai_remote_addr
);
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
);
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
);
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
);
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
);
479 if (number_of_sid_clashed
) {
480 SET_FLAG(s_list
->flags
, F_SEGMENT_LIST_SID_CONFLICT
);
481 number_of_sid_clashed
= 0;
483 UNSET_FLAG(s_list
->flags
, F_SEGMENT_LIST_SID_CONFLICT
);
485 srte_apply_changes();
491 * Update a policy binding SID.
493 * @param policy The policy for which the SID should be updated
494 * @param binding_sid The new binding SID for the given policy
496 void srte_policy_update_binding_sid(struct srte_policy
*policy
,
497 uint32_t binding_sid
)
499 if (policy
->binding_sid
!= MPLS_LABEL_NONE
)
500 path_zebra_release_label(policy
->binding_sid
);
502 policy
->binding_sid
= binding_sid
;
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
);
511 * Gives the policy best candidate path.
513 * @param policy The policy we want the best candidate path from
514 * @return The best candidate path
516 static struct srte_candidate
*
517 srte_policy_best_candidate(const struct srte_policy
*policy
)
519 struct srte_candidate
*candidate
;
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
)))
534 void srte_clean_zebra(void)
536 struct srte_policy
*policy
, *safe_pol
;
538 RB_FOREACH_SAFE (policy
, srte_policy_head
, &srte_policies
, safe_pol
)
539 srte_policy_del(policy
);
545 * Apply changes defined by setting the policies, candidate paths
546 * and segment lists modification flags NEW, MODIFIED and DELETED.
548 * This allows the northbound code to delay all the side effects of adding
549 * modifying and deleting them to the end.
551 * Example of marking an object as modified:
552 * `SET_FLAG(obj->flags, F_XXX_MODIFIED)`
554 void srte_apply_changes(void)
556 struct srte_policy
*policy
, *safe_pol
;
557 struct srte_segment_list
*segment_list
, *safe_sl
;
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
);
565 srte_policy_del(policy
);
568 srte_policy_apply_changes(policy
);
569 UNSET_FLAG(policy
->flags
, F_POLICY_NEW
);
570 UNSET_FLAG(policy
->flags
, F_POLICY_MODIFIED
);
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
);
579 UNSET_FLAG(segment_list
->flags
, F_SEGMENT_LIST_NEW
);
580 UNSET_FLAG(segment_list
->flags
, F_SEGMENT_LIST_MODIFIED
);
585 * Apply changes defined by setting the given policy and its candidate paths
586 * modification flags NEW, MODIFIED and DELETED.
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
592 * @param policy The policy changes has to be applied to.
594 void srte_policy_apply_changes(struct srte_policy
*policy
)
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
];
601 ipaddr2str(&policy
->endpoint
, endpoint
, sizeof(endpoint
));
603 /* Get old and new best candidate path. */
604 old_best_candidate
= policy
->best_candidate
;
605 new_best_candidate
= srte_policy_best_candidate(policy
);
607 if (new_best_candidate
!= old_best_candidate
) {
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");
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
);
621 * Rely on replace semantics if there's a new best
624 if (!new_best_candidate
)
625 path_zebra_delete_sr_policy(policy
);
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
);
633 path_zebra_add_sr_policy(
634 policy
, new_best_candidate
->lsp
->segment_list
);
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.
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
646 new_best_candidate
->lsp
->segment_list
->flags
,
647 F_SEGMENT_LIST_MODIFIED
);
649 if (candidate_changed
|| segment_list_changed
) {
651 "SR-TE(%s, %u): best candidate %s changed",
652 endpoint
, policy
->color
,
653 new_best_candidate
->name
);
655 path_zebra_add_sr_policy(
656 policy
, new_best_candidate
->lsp
->segment_list
);
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
);
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
);
676 UNSET_FLAG(candidate
->flags
, F_CANDIDATE_NEW
);
677 UNSET_FLAG(candidate
->flags
, F_CANDIDATE_MODIFIED
);
682 * Adds a candidate path to a policy.
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
688 struct srte_candidate
*srte_candidate_add(struct srte_policy
*policy
,
690 enum srte_protocol_origin origin
,
691 const char *originator
)
693 struct srte_candidate
*candidate
;
694 struct srte_lsp
*lsp
;
696 candidate
= XCALLOC(MTYPE_PATH_SR_CANDIDATE
, sizeof(*candidate
));
697 lsp
= XCALLOC(MTYPE_PATH_SR_CANDIDATE
, sizeof(*lsp
));
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
;
710 if (candidate
->protocol_origin
== SRTE_ORIGIN_PCEP
711 || candidate
->protocol_origin
== SRTE_ORIGIN_BGP
) {
712 candidate
->type
= SRTE_CANDIDATE_TYPE_DYNAMIC
;
714 lsp
->candidate
= candidate
;
715 candidate
->lsp
= lsp
;
717 RB_INSERT(srte_candidate_head
, &policy
->candidate_paths
, candidate
);
723 * Deletes a candidate.
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.
729 * @param candidate The candidate path to delete
731 void srte_candidate_del(struct srte_candidate
*candidate
)
733 struct srte_policy
*srte_policy
= candidate
->policy
;
735 RB_REMOVE(srte_candidate_head
, &srte_policy
->candidate_paths
,
738 XFREE(MTYPE_PATH_SR_CANDIDATE
, candidate
->lsp
);
739 XFREE(MTYPE_PATH_SR_CANDIDATE
, candidate
);
743 * Sets the bandwidth constraint of given candidate path.
745 * The corresponding LSP will be changed too.
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)
751 void srte_candidate_set_bandwidth(struct srte_candidate
*candidate
,
752 float bandwidth
, bool required
)
754 struct srte_policy
*policy
= candidate
->policy
;
755 char endpoint
[ENDPOINT_STR_LENGTH
];
757 ipaddr2str(&policy
->endpoint
, endpoint
, sizeof(endpoint
));
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
;
766 srte_lsp_set_bandwidth(candidate
->lsp
, bandwidth
, required
);
770 * Sets the bandwidth constraint of the given LSP.
772 * The changes will not be shown as part of the running configuration.
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)
778 void srte_lsp_set_bandwidth(struct srte_lsp
*lsp
, float bandwidth
,
781 struct srte_candidate
*candidate
= lsp
->candidate
;
782 struct srte_policy
*policy
= candidate
->policy
;
783 char endpoint
[ENDPOINT_STR_LENGTH
];
785 ipaddr2str(&policy
->endpoint
, endpoint
, sizeof(endpoint
));
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
;
796 * Remove a candidate path bandwidth constraint.
798 * The corresponding LSP will be changed too.
800 * @param candidate The candidate path of which the bandwidth should be removed
802 void srte_candidate_unset_bandwidth(struct srte_candidate
*candidate
)
804 struct srte_policy
*policy
= candidate
->policy
;
805 char endpoint
[ENDPOINT_STR_LENGTH
];
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
);
818 * Remove an LSP bandwidth constraint.
820 * The changes will not be shown as part of the running configuration.
822 * @param lsp The lsp of which the bandwidth should be changed
824 void srte_lsp_unset_bandwidth(struct srte_lsp
*lsp
)
826 struct srte_candidate
*candidate
= lsp
->candidate
;
827 struct srte_policy
*policy
= candidate
->policy
;
828 char endpoint
[ENDPOINT_STR_LENGTH
];
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
);
840 * Sets a candidate path metric constraint.
842 * The corresponding LSP will be changed too.
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
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
,
856 struct srte_policy
*policy
= candidate
->policy
;
857 char endpoint
[ENDPOINT_STR_LENGTH
];
859 ipaddr2str(&policy
->endpoint
, endpoint
, sizeof(endpoint
));
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
,
871 SET_FLAG(candidate
->flags
, F_CANDIDATE_MODIFIED
);
875 * Sets an LSP metric constraint.
877 * The changes will not be shown as part of the running configuration.
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
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
)
890 struct srte_candidate
*candidate
= lsp
->candidate
;
891 struct srte_policy
*policy
= candidate
->policy
;
892 char endpoint
[ENDPOINT_STR_LENGTH
];
894 ipaddr2str(&policy
->endpoint
, endpoint
, sizeof(endpoint
));
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
,
906 void srte_set_metric(struct srte_metric
*metric
, float value
, bool required
,
907 bool is_bound
, bool is_computed
)
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
;
917 * Removes a candidate path metric constraint.
919 * The corresponding LSP will be changed too.
921 * @param candidate The candidate path from which the metric should be removed
922 * @param type The metric type
924 void srte_candidate_unset_metric(struct srte_candidate
*candidate
,
925 enum srte_candidate_metric_type type
)
927 struct srte_policy
*policy
= candidate
->policy
;
928 char endpoint
[ENDPOINT_STR_LENGTH
];
930 ipaddr2str(&policy
->endpoint
, endpoint
, sizeof(endpoint
));
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
);
942 * Removes a candidate path metric constraint.
944 * The changes will not be shown as part of the running configuration.
946 * @param lsp The LSP from which the metric should be removed
947 * @param type The metric type
949 void srte_lsp_unset_metric(struct srte_lsp
*lsp
,
950 enum srte_candidate_metric_type type
)
952 struct srte_candidate
*candidate
= lsp
->candidate
;
953 struct srte_policy
*policy
= candidate
->policy
;
954 char endpoint
[ENDPOINT_STR_LENGTH
];
956 ipaddr2str(&policy
->endpoint
, endpoint
, sizeof(endpoint
));
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]);
965 void srte_unset_metric(struct srte_metric
*metric
)
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
);
974 * Sets a candidate path objective function.
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
980 void srte_candidate_set_objfun(struct srte_candidate
*candidate
, bool required
,
981 enum objfun_type type
)
983 struct srte_policy
*policy
= candidate
->policy
;
984 char endpoint
[ENDPOINT_STR_LENGTH
];
986 ipaddr2str(&policy
->endpoint
, endpoint
, sizeof(endpoint
));
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
);
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
));
999 * Removed the objective function constraint from a candidate path.
1001 * @param candidate The candidate path from which the OF should be removed
1003 void srte_candidate_unset_objfun(struct srte_candidate
*candidate
)
1005 struct srte_policy
*policy
= candidate
->policy
;
1006 char endpoint
[ENDPOINT_STR_LENGTH
];
1008 ipaddr2str(&policy
->endpoint
, endpoint
, sizeof(endpoint
));
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
;
1015 "SR-TE(%s, %u): candidate %s objective functions preferences unset",
1016 endpoint
, policy
->color
, candidate
->name
);
1019 static uint32_t filter_type_to_flag(enum affinity_filter_type 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
;
1033 static const char *filter_type_name(enum affinity_filter_type 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";
1048 * Sets a candidate path affinity filter constraint.
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
1054 void srte_candidate_set_affinity_filter(struct srte_candidate
*candidate
,
1055 enum affinity_filter_type type
,
1058 struct srte_policy
*policy
= candidate
->policy
;
1059 char endpoint
[ENDPOINT_STR_LENGTH
];
1061 ipaddr2str(&policy
->endpoint
, endpoint
, sizeof(endpoint
));
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
;
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
);
1075 * Removes a candidate path affinity filter constraint.
1077 * @param candidate The candidate path from which the constraint should be
1079 * @param type The affinity constraint type to remove
1081 void srte_candidate_unset_affinity_filter(struct srte_candidate
*candidate
,
1082 enum affinity_filter_type type
)
1084 struct srte_policy
*policy
= candidate
->policy
;
1085 char endpoint
[ENDPOINT_STR_LENGTH
];
1087 ipaddr2str(&policy
->endpoint
, endpoint
, sizeof(endpoint
));
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;
1095 "SR-TE(%s, %u): candidate %s affinity filter %s unset",
1096 endpoint
, policy
->color
, candidate
->name
,
1097 filter_type_name(type
));
1101 * Searches for a candidate path of the given policy.
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
1107 struct srte_candidate
*srte_candidate_find(struct srte_policy
*policy
,
1108 uint32_t preference
)
1110 struct srte_candidate search
;
1112 search
.preference
= preference
;
1113 return RB_FIND(srte_candidate_head
, &policy
->candidate_paths
, &search
);
1117 * Searches for a an entry of a given segment list.
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.
1123 struct srte_segment_entry
*
1124 srte_segment_entry_find(struct srte_segment_list
*segment_list
, uint32_t index
)
1126 struct srte_segment_entry search
;
1128 search
.index
= index
;
1129 return RB_FIND(srte_segment_entry_head
, &segment_list
->segments
,
1134 * Updates a candidate status.
1136 * @param candidate The candidate of which the status should be updated
1137 * @param status The new candidate path status
1139 void srte_candidate_status_update(struct srte_candidate
*candidate
, int status
)
1141 struct srte_policy
*policy
= candidate
->policy
;
1142 char endpoint
[ENDPOINT_STR_LENGTH
];
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
);
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
1155 case SRTE_POLICY_STATUS_GOING_UP
:
1156 case SRTE_POLICY_STATUS_DOWN
:
1159 policy
->status
= SRTE_POLICY_STATUS_DOWN
;
1160 srte_policy_status_log(policy
);
1164 case ZEBRA_SR_POLICY_UP
:
1165 switch (policy
->status
) {
1166 case SRTE_POLICY_STATUS_UP
:
1169 policy
->status
= SRTE_POLICY_STATUS_UP
;
1170 srte_policy_status_log(policy
);
1176 trigger_pathd_candidate_updated(candidate
);
1180 * Flags the segment lists from give originator for removal.
1182 * The function srte_apply_changes must be called afterward for
1183 * the segment list to be removed.
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
1188 void srte_candidate_unset_segment_list(const char *originator
, bool force
)
1190 if (originator
== NULL
) {
1192 "Cannot unset segment list because originator is NULL");
1196 PATH_POLICY_DEBUG("Unset segment lists for originator %s", originator
);
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",
1204 struct srte_candidate
*candidate
;
1205 RB_FOREACH (candidate
, srte_candidate_head
,
1206 &policy
->candidate_paths
) {
1208 "Unset segment lists checking candidate %s",
1210 if (candidate
->lsp
== NULL
) {
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
) {
1224 if (segment_list
->protocol_origin
1225 == SRTE_ORIGIN_LOCAL
) {
1227 "Cannot unset segment list %s because it was created locally",
1228 segment_list
->name
);
1232 /* In the case of last pce,we force the unset
1233 * because we don't have pce by prefix (TODO) is all
1235 if (strncmp(segment_list
->originator
, originator
,
1236 sizeof(segment_list
->originator
))
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
;
1252 * Gives a string representation of given protocol origin enum.
1254 * @param origin The enum you want a string representation of
1255 * @return The string representation of given enum
1257 const char *srte_origin2str(enum srte_protocol_origin origin
)
1260 case SRTE_ORIGIN_PCEP
:
1262 case SRTE_ORIGIN_BGP
:
1264 case SRTE_ORIGIN_LOCAL
:
1271 void path_policy_show_debugging(struct vty
*vty
)
1273 if (DEBUG_FLAGS_CHECK(&path_policy_debug
, PATH_POLICY_DEBUG_BASIC
))
1274 vty_out(vty
, " Path policy debugging is on\n");
1277 void pathd_shutdown(void)
1279 path_ted_teardown();
1284 void trigger_pathd_candidate_created(struct srte_candidate
*candidate
)
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
)
1293 thread_add_timer(master
, trigger_pathd_candidate_created_timer
,
1294 (void *)candidate
, HOOK_DELAY
, &candidate
->hook_timer
);
1297 void trigger_pathd_candidate_created_timer(struct thread
*thread
)
1299 struct srte_candidate
*candidate
= THREAD_ARG(thread
);
1300 candidate
->hook_timer
= NULL
;
1301 hook_call(pathd_candidate_created
, candidate
);
1304 void trigger_pathd_candidate_updated(struct srte_candidate
*candidate
)
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
)
1313 thread_add_timer(master
, trigger_pathd_candidate_updated_timer
,
1314 (void *)candidate
, HOOK_DELAY
, &candidate
->hook_timer
);
1317 void trigger_pathd_candidate_updated_timer(struct thread
*thread
)
1319 struct srte_candidate
*candidate
= THREAD_ARG(thread
);
1320 candidate
->hook_timer
= NULL
;
1321 hook_call(pathd_candidate_updated
, candidate
);
1324 void trigger_pathd_candidate_removed(struct srte_candidate
*candidate
)
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
;
1332 hook_call(pathd_candidate_removed
, candidate
);
1335 const char *srte_candidate_metric_name(enum srte_candidate_metric_type type
)
1338 case SRTE_CANDIDATE_METRIC_TYPE_IGP
:
1340 case SRTE_CANDIDATE_METRIC_TYPE_TE
:
1342 case SRTE_CANDIDATE_METRIC_TYPE_HC
:
1344 case SRTE_CANDIDATE_METRIC_TYPE_ABC
:
1346 case SRTE_CANDIDATE_METRIC_TYPE_LMLL
:
1348 case SRTE_CANDIDATE_METRIC_TYPE_CIGP
:
1350 case SRTE_CANDIDATE_METRIC_TYPE_CTE
:
1352 case SRTE_CANDIDATE_METRIC_TYPE_PIGP
:
1354 case SRTE_CANDIDATE_METRIC_TYPE_PTE
:
1356 case SRTE_CANDIDATE_METRIC_TYPE_PHC
:
1358 case SRTE_CANDIDATE_METRIC_TYPE_MSD
:
1360 case SRTE_CANDIDATE_METRIC_TYPE_PD
:
1362 case SRTE_CANDIDATE_METRIC_TYPE_PDV
:
1364 case SRTE_CANDIDATE_METRIC_TYPE_PL
:
1366 case SRTE_CANDIDATE_METRIC_TYPE_PPD
:
1368 case SRTE_CANDIDATE_METRIC_TYPE_PPDV
:
1370 case SRTE_CANDIDATE_METRIC_TYPE_PPL
:
1372 case SRTE_CANDIDATE_METRIC_TYPE_NAP
:
1374 case SRTE_CANDIDATE_METRIC_TYPE_NLP
:
1376 case SRTE_CANDIDATE_METRIC_TYPE_DC
:
1378 case SRTE_CANDIDATE_METRIC_TYPE_BNC
:
1385 int32_t srte_ted_do_query_type_c(struct srte_segment_entry
*entry
,
1386 struct prefix
*prefix_cli
, uint32_t algo
)
1389 uint32_t ted_sid
= MPLS_LABEL_NONE
;
1391 if (!entry
|| !prefix_cli
)
1394 if (!path_ted_is_initialized())
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)",
1403 "%s: PATHD-TED: SL: Success query C : ted-sid (%d)",
1406 if (CHECK_SID(entry
->segment_list
->protocol_origin
, ted_sid
,
1407 entry
->sid_value
)) {
1408 status
= PATH_SID_ERROR
;
1410 srte_segment_set_local_modification(entry
->segment_list
, entry
,
1415 int32_t srte_ted_do_query_type_e(struct srte_segment_entry
*entry
,
1416 struct prefix
*prefix_cli
,
1417 uint32_t local_iface
)
1420 uint32_t ted_sid
= MPLS_LABEL_NONE
;
1422 if (!entry
|| !prefix_cli
)
1425 if (!path_ted_is_initialized())
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)",
1434 "%s: PATHD-TED: SL: Success query E : ted-sid (%d)",
1437 if (CHECK_SID(entry
->segment_list
->protocol_origin
, ted_sid
,
1438 entry
->sid_value
)) {
1439 status
= PATH_SID_ERROR
;
1441 srte_segment_set_local_modification(entry
->segment_list
, entry
,
1446 int32_t srte_ted_do_query_type_f(struct srte_segment_entry
*entry
,
1447 struct ipaddr
*local
, struct ipaddr
*remote
)
1450 uint32_t ted_sid
= MPLS_LABEL_NONE
;
1452 if (!entry
|| !local
|| !remote
)
1455 if (!path_ted_is_initialized())
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__
,
1463 PATH_TED_DEBUG("%s:SL: Success query F : ted-sid (%d)",
1466 if (CHECK_SID(entry
->segment_list
->protocol_origin
, ted_sid
,
1467 entry
->sid_value
)) {
1468 status
= PATH_SID_ERROR
;
1470 srte_segment_set_local_modification(entry
->segment_list
, entry
,