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
);
284 case SRTE_SEGMENT_NAI_TYPE_NONE
:
285 case SRTE_SEGMENT_NAI_TYPE_IPV6_ADJACENCY_LINK_LOCAL_ADDRESSES
:
286 segment
->nai_local_addr
.ipa_type
= IPADDR_NONE
;
287 segment
->nai_local_iface
= 0;
288 segment
->nai_remote_addr
.ipa_type
= IPADDR_NONE
;
289 segment
->nai_remote_iface
= 0;
295 * Mark segment as modified depending in protocol and sid conditions
297 * @param protocol_origin Origin of the segment list
298 * @param s_list Ptr to segment list with flags,sid to modidy
299 * @param s_entry Ptr to segment entry with sid to modidy
300 * @param ted_sid The sid from ted query
303 void srte_segment_set_local_modification(struct srte_segment_list
*s_list
,
304 struct srte_segment_entry
*s_entry
,
307 if (!s_list
|| !s_entry
)
310 if (s_list
->protocol_origin
== SRTE_ORIGIN_LOCAL
311 && s_entry
->sid_value
!= ted_sid
) {
312 s_entry
->sid_value
= ted_sid
;
313 SET_FLAG(s_list
->flags
, F_SEGMENT_LIST_MODIFIED
);
318 * Add a policy to pathd.
320 * WARNING: The color 0 is a special case as it is the no-color.
322 * @param color The color of the policy.
323 * @param endpoint The IP address of the policy endpoint
324 * @return The created policy
326 struct srte_policy
*srte_policy_add(uint32_t color
, struct ipaddr
*endpoint
,
327 enum srte_protocol_origin origin
,
328 const char *originator
)
330 struct srte_policy
*policy
;
332 policy
= XCALLOC(MTYPE_PATH_SR_POLICY
, sizeof(*policy
));
333 policy
->color
= color
;
334 policy
->endpoint
= *endpoint
;
335 policy
->binding_sid
= MPLS_LABEL_NONE
;
336 policy
->protocol_origin
= origin
;
337 if (originator
!= NULL
)
338 strlcpy(policy
->originator
, originator
,
339 sizeof(policy
->originator
));
341 RB_INIT(srte_candidate_head
, &policy
->candidate_paths
);
342 RB_INSERT(srte_policy_head
, &srte_policies
, policy
);
348 * Delete a policy from pathd.
350 * The given policy structure will be freed and should never be used again
351 * after calling this function.
353 * @param policy The policy to be removed
355 void srte_policy_del(struct srte_policy
*policy
)
357 struct srte_candidate
*candidate
;
359 path_zebra_delete_sr_policy(policy
);
361 path_zebra_release_label(policy
->binding_sid
);
363 while (!RB_EMPTY(srte_candidate_head
, &policy
->candidate_paths
)) {
365 RB_ROOT(srte_candidate_head
, &policy
->candidate_paths
);
366 trigger_pathd_candidate_removed(candidate
);
367 srte_candidate_del(candidate
);
370 RB_REMOVE(srte_policy_head
, &srte_policies
, policy
);
371 XFREE(MTYPE_PATH_SR_POLICY
, policy
);
375 * Search for a policy by color and endpoint.
377 * WARNING: The color 0 is a special case as it is the no-color.
379 * @param color The color of the policy to look for
380 * @param endpoint The endpoint of the policy to look for
381 * @return The policy if found, NULL otherwise
383 struct srte_policy
*srte_policy_find(uint32_t color
, struct ipaddr
*endpoint
)
385 struct srte_policy search
;
387 search
.color
= color
;
388 search
.endpoint
= *endpoint
;
389 return RB_FIND(srte_policy_head
, &srte_policies
, &search
);
393 * After new data from igp,local and pce the segment list :
394 * Mark as invalid for origin pce if cannot be validated
395 * Updated for origin local
397 int srte_policy_update_ted_sid(void)
400 int number_of_sid_clashed
= 0;
401 struct srte_segment_list
*s_list
;
402 struct srte_segment_entry
*s_entry
;
404 if (!path_ted_is_initialized())
406 if (RB_EMPTY(srte_segment_list_head
, &srte_segment_lists
))
409 RB_FOREACH (s_list
, srte_segment_list_head
, &srte_segment_lists
) {
410 if (CHECK_FLAG(s_list
->flags
, F_SEGMENT_LIST_DELETED
))
412 RB_FOREACH (s_entry
, srte_segment_entry_head
,
415 "%s:PATHD-TED: SL: Name: %s index:(%d) sid:(%d) prefix_len:(%d) local iface:(%d) algorithm:(%d)",
416 __func__
, s_list
->name
, s_entry
->index
,
418 s_entry
->nai_local_prefix_len
,
419 s_entry
->nai_local_iface
,
420 s_entry
->nai_algorithm
);
421 struct prefix prefix_cli
= {0};
423 switch (s_entry
->nai_type
) {
424 case SRTE_SEGMENT_NAI_TYPE_IPV6_ADJACENCY
:
425 case SRTE_SEGMENT_NAI_TYPE_IPV4_ADJACENCY
:
426 number_of_sid_clashed
+=
427 srte_ted_do_query_type_f(
429 &s_entry
->nai_local_addr
,
430 &s_entry
->nai_remote_addr
);
432 case SRTE_SEGMENT_NAI_TYPE_IPV6_LOCAL_IFACE
:
433 prefix_cli
.family
= AF_INET6
;
434 prefix_cli
.prefixlen
=
435 s_entry
->nai_local_prefix_len
;
436 prefix_cli
.u
.prefix6
=
437 s_entry
->nai_local_addr
.ip
._v6_addr
;
438 number_of_sid_clashed
+=
439 srte_ted_do_query_type_e(
440 s_entry
, &prefix_cli
,
441 s_entry
->nai_local_iface
);
443 case SRTE_SEGMENT_NAI_TYPE_IPV4_LOCAL_IFACE
:
444 prefix_cli
.family
= AF_INET
;
445 prefix_cli
.prefixlen
=
446 s_entry
->nai_local_prefix_len
;
447 prefix_cli
.u
.prefix4
=
448 s_entry
->nai_local_addr
.ip
._v4_addr
;
449 number_of_sid_clashed
+=
450 srte_ted_do_query_type_e(
451 s_entry
, &prefix_cli
,
452 s_entry
->nai_local_iface
);
454 case SRTE_SEGMENT_NAI_TYPE_IPV6_ALGORITHM
:
455 prefix_cli
.family
= AF_INET6
;
456 prefix_cli
.prefixlen
=
457 s_entry
->nai_local_prefix_len
;
458 prefix_cli
.u
.prefix6
=
459 s_entry
->nai_local_addr
.ip
._v6_addr
;
460 number_of_sid_clashed
+=
461 srte_ted_do_query_type_c(
462 s_entry
, &prefix_cli
,
463 s_entry
->nai_algorithm
);
465 case SRTE_SEGMENT_NAI_TYPE_IPV4_ALGORITHM
:
466 prefix_cli
.family
= AF_INET
;
467 prefix_cli
.prefixlen
=
468 s_entry
->nai_local_prefix_len
;
469 prefix_cli
.u
.prefix4
=
470 s_entry
->nai_local_addr
.ip
._v4_addr
;
471 number_of_sid_clashed
+=
472 srte_ted_do_query_type_c(
473 s_entry
, &prefix_cli
,
474 s_entry
->nai_algorithm
);
476 case SRTE_SEGMENT_NAI_TYPE_NONE
:
477 case SRTE_SEGMENT_NAI_TYPE_IPV4_NODE
:
478 case SRTE_SEGMENT_NAI_TYPE_IPV6_NODE
:
479 case SRTE_SEGMENT_NAI_TYPE_IPV4_UNNUMBERED_ADJACENCY
:
480 case SRTE_SEGMENT_NAI_TYPE_IPV6_ADJACENCY_LINK_LOCAL_ADDRESSES
:
484 if (number_of_sid_clashed
) {
485 SET_FLAG(s_list
->flags
, F_SEGMENT_LIST_SID_CONFLICT
);
486 number_of_sid_clashed
= 0;
488 UNSET_FLAG(s_list
->flags
, F_SEGMENT_LIST_SID_CONFLICT
);
490 srte_apply_changes();
496 * Update a policy binding SID.
498 * @param policy The policy for which the SID should be updated
499 * @param binding_sid The new binding SID for the given policy
501 void srte_policy_update_binding_sid(struct srte_policy
*policy
,
502 uint32_t binding_sid
)
504 if (policy
->binding_sid
!= MPLS_LABEL_NONE
)
505 path_zebra_release_label(policy
->binding_sid
);
507 policy
->binding_sid
= binding_sid
;
509 /* Reinstall the Binding-SID if necessary. */
510 if (policy
->best_candidate
)
511 path_zebra_add_sr_policy(
512 policy
, policy
->best_candidate
->lsp
->segment_list
);
516 * Gives the policy best candidate path.
518 * @param policy The policy we want the best candidate path from
519 * @return The best candidate path
521 static struct srte_candidate
*
522 srte_policy_best_candidate(const struct srte_policy
*policy
)
524 struct srte_candidate
*candidate
;
526 RB_FOREACH_REVERSE (candidate
, srte_candidate_head
,
527 &policy
->candidate_paths
) {
528 /* search for highest preference with existing segment list */
529 if (!CHECK_FLAG(candidate
->flags
, F_CANDIDATE_DELETED
)
530 && candidate
->lsp
->segment_list
531 && (!CHECK_FLAG(candidate
->lsp
->segment_list
->flags
,
532 F_SEGMENT_LIST_SID_CONFLICT
)))
539 void srte_clean_zebra(void)
541 struct srte_policy
*policy
, *safe_pol
;
543 RB_FOREACH_SAFE (policy
, srte_policy_head
, &srte_policies
, safe_pol
)
544 srte_policy_del(policy
);
550 * Apply changes defined by setting the policies, candidate paths
551 * and segment lists modification flags NEW, MODIFIED and DELETED.
553 * This allows the northbound code to delay all the side effects of adding
554 * modifying and deleting them to the end.
556 * Example of marking an object as modified:
557 * `SET_FLAG(obj->flags, F_XXX_MODIFIED)`
559 void srte_apply_changes(void)
561 struct srte_policy
*policy
, *safe_pol
;
562 struct srte_segment_list
*segment_list
, *safe_sl
;
564 RB_FOREACH_SAFE (policy
, srte_policy_head
, &srte_policies
, safe_pol
) {
565 if (CHECK_FLAG(policy
->flags
, F_POLICY_DELETED
)) {
566 if (policy
->status
!= SRTE_POLICY_STATUS_DOWN
) {
567 policy
->status
= SRTE_POLICY_STATUS_DOWN
;
568 srte_policy_status_log(policy
);
570 srte_policy_del(policy
);
573 srte_policy_apply_changes(policy
);
574 UNSET_FLAG(policy
->flags
, F_POLICY_NEW
);
575 UNSET_FLAG(policy
->flags
, F_POLICY_MODIFIED
);
578 RB_FOREACH_SAFE (segment_list
, srte_segment_list_head
,
579 &srte_segment_lists
, safe_sl
) {
580 if (CHECK_FLAG(segment_list
->flags
, F_SEGMENT_LIST_DELETED
)) {
581 srte_segment_list_del(segment_list
);
584 UNSET_FLAG(segment_list
->flags
, F_SEGMENT_LIST_NEW
);
585 UNSET_FLAG(segment_list
->flags
, F_SEGMENT_LIST_MODIFIED
);
590 * Apply changes defined by setting the given policy and its candidate paths
591 * modification flags NEW, MODIFIED and DELETED.
593 * In moste cases `void srte_apply_changes(void)` should be used instead,
594 * this function will not handle the changes of segment lists used by the
597 * @param policy The policy changes has to be applied to.
599 void srte_policy_apply_changes(struct srte_policy
*policy
)
601 struct srte_candidate
*candidate
, *safe
;
602 struct srte_candidate
*old_best_candidate
;
603 struct srte_candidate
*new_best_candidate
;
604 char endpoint
[ENDPOINT_STR_LENGTH
];
606 ipaddr2str(&policy
->endpoint
, endpoint
, sizeof(endpoint
));
608 /* Get old and new best candidate path. */
609 old_best_candidate
= policy
->best_candidate
;
610 new_best_candidate
= srte_policy_best_candidate(policy
);
612 if (new_best_candidate
!= old_best_candidate
) {
614 "SR-TE(%s, %u): best candidate changed from %s to %s",
615 endpoint
, policy
->color
,
616 old_best_candidate
? old_best_candidate
->name
: "none",
617 new_best_candidate
? new_best_candidate
->name
: "none");
619 if (old_best_candidate
) {
620 policy
->best_candidate
= NULL
;
621 UNSET_FLAG(old_best_candidate
->flags
, F_CANDIDATE_BEST
);
622 SET_FLAG(old_best_candidate
->flags
,
623 F_CANDIDATE_MODIFIED
);
626 * Rely on replace semantics if there's a new best
629 if (!new_best_candidate
)
630 path_zebra_delete_sr_policy(policy
);
632 if (new_best_candidate
) {
633 policy
->best_candidate
= new_best_candidate
;
634 SET_FLAG(new_best_candidate
->flags
, F_CANDIDATE_BEST
);
635 SET_FLAG(new_best_candidate
->flags
,
636 F_CANDIDATE_MODIFIED
);
638 path_zebra_add_sr_policy(
639 policy
, new_best_candidate
->lsp
->segment_list
);
641 } else if (new_best_candidate
) {
642 /* The best candidate path did not change, but some of its
643 * attributes or its segment list may have changed.
646 bool candidate_changed
= CHECK_FLAG(new_best_candidate
->flags
,
647 F_CANDIDATE_MODIFIED
);
648 bool segment_list_changed
=
649 new_best_candidate
->lsp
->segment_list
651 new_best_candidate
->lsp
->segment_list
->flags
,
652 F_SEGMENT_LIST_MODIFIED
);
654 if (candidate_changed
|| segment_list_changed
) {
656 "SR-TE(%s, %u): best candidate %s changed",
657 endpoint
, policy
->color
,
658 new_best_candidate
->name
);
660 path_zebra_add_sr_policy(
661 policy
, new_best_candidate
->lsp
->segment_list
);
665 RB_FOREACH_SAFE (candidate
, srte_candidate_head
,
666 &policy
->candidate_paths
, safe
) {
667 if (CHECK_FLAG(candidate
->flags
, F_CANDIDATE_DELETED
)) {
668 trigger_pathd_candidate_removed(candidate
);
669 srte_candidate_del(candidate
);
671 } else if (CHECK_FLAG(candidate
->flags
, F_CANDIDATE_NEW
)) {
672 trigger_pathd_candidate_created(candidate
);
673 } else if (CHECK_FLAG(candidate
->flags
, F_CANDIDATE_MODIFIED
)) {
674 trigger_pathd_candidate_updated(candidate
);
675 } else if (candidate
->lsp
->segment_list
676 && CHECK_FLAG(candidate
->lsp
->segment_list
->flags
,
677 F_SEGMENT_LIST_MODIFIED
)) {
678 trigger_pathd_candidate_updated(candidate
);
681 UNSET_FLAG(candidate
->flags
, F_CANDIDATE_NEW
);
682 UNSET_FLAG(candidate
->flags
, F_CANDIDATE_MODIFIED
);
687 * Adds a candidate path to a policy.
689 * @param policy The policy the candidate path should be added to
690 * @param preference The preference of the candidate path to be added
691 * @return The added candidate path
693 struct srte_candidate
*srte_candidate_add(struct srte_policy
*policy
,
695 enum srte_protocol_origin origin
,
696 const char *originator
)
698 struct srte_candidate
*candidate
;
699 struct srte_lsp
*lsp
;
701 candidate
= XCALLOC(MTYPE_PATH_SR_CANDIDATE
, sizeof(*candidate
));
702 lsp
= XCALLOC(MTYPE_PATH_SR_CANDIDATE
, sizeof(*lsp
));
704 candidate
->preference
= preference
;
705 candidate
->policy
= policy
;
706 candidate
->type
= SRTE_CANDIDATE_TYPE_UNDEFINED
;
707 candidate
->discriminator
= frr_weak_random();
708 candidate
->protocol_origin
= origin
;
709 if (originator
!= NULL
) {
710 strlcpy(candidate
->originator
, originator
,
711 sizeof(candidate
->originator
));
712 lsp
->protocol_origin
= origin
;
715 if (candidate
->protocol_origin
== SRTE_ORIGIN_PCEP
716 || candidate
->protocol_origin
== SRTE_ORIGIN_BGP
) {
717 candidate
->type
= SRTE_CANDIDATE_TYPE_DYNAMIC
;
719 lsp
->candidate
= candidate
;
720 candidate
->lsp
= lsp
;
722 RB_INSERT(srte_candidate_head
, &policy
->candidate_paths
, candidate
);
728 * Deletes a candidate.
730 * The corresponding LSP will be removed alongside the candidate path.
731 * The given candidate will be freed and shouldn't be used anymore after the
732 * calling this function.
734 * @param candidate The candidate path to delete
736 void srte_candidate_del(struct srte_candidate
*candidate
)
738 struct srte_policy
*srte_policy
= candidate
->policy
;
740 RB_REMOVE(srte_candidate_head
, &srte_policy
->candidate_paths
,
743 XFREE(MTYPE_PATH_SR_CANDIDATE
, candidate
->lsp
);
744 XFREE(MTYPE_PATH_SR_CANDIDATE
, candidate
);
748 * Sets the bandwidth constraint of given candidate path.
750 * The corresponding LSP will be changed too.
752 * @param candidate The candidate path of which the bandwidth should be changed
753 * @param bandwidth The Bandwidth constraint to set to the candidate path
754 * @param required If the constraint is required (true) or only desired (false)
756 void srte_candidate_set_bandwidth(struct srte_candidate
*candidate
,
757 float bandwidth
, bool required
)
759 struct srte_policy
*policy
= candidate
->policy
;
760 char endpoint
[ENDPOINT_STR_LENGTH
];
762 ipaddr2str(&policy
->endpoint
, endpoint
, sizeof(endpoint
));
764 "SR-TE(%s, %u): candidate %s %sconfig bandwidth set to %f B/s",
765 endpoint
, policy
->color
, candidate
->name
,
766 required
? "required " : "", bandwidth
);
767 SET_FLAG(candidate
->flags
, F_CANDIDATE_HAS_BANDWIDTH
);
768 COND_FLAG(candidate
->flags
, F_CANDIDATE_REQUIRED_BANDWIDTH
, required
);
769 candidate
->bandwidth
= bandwidth
;
771 srte_lsp_set_bandwidth(candidate
->lsp
, bandwidth
, required
);
775 * Sets the bandwidth constraint of the given LSP.
777 * The changes will not be shown as part of the running configuration.
779 * @param lsp The lsp of which the bandwidth should be changed
780 * @param bandwidth The Bandwidth constraint to set to the candidate path
781 * @param required If the constraint is required (true) or only desired (false)
783 void srte_lsp_set_bandwidth(struct srte_lsp
*lsp
, float bandwidth
,
786 struct srte_candidate
*candidate
= lsp
->candidate
;
787 struct srte_policy
*policy
= candidate
->policy
;
788 char endpoint
[ENDPOINT_STR_LENGTH
];
790 ipaddr2str(&policy
->endpoint
, endpoint
, sizeof(endpoint
));
792 "SR-TE(%s, %u): candidate %s %slsp bandwidth set to %f B/s",
793 endpoint
, policy
->color
, candidate
->name
,
794 required
? "required" : "", bandwidth
);
795 SET_FLAG(lsp
->flags
, F_CANDIDATE_HAS_BANDWIDTH
);
796 COND_FLAG(lsp
->flags
, F_CANDIDATE_REQUIRED_BANDWIDTH
, required
);
797 lsp
->bandwidth
= bandwidth
;
801 * Remove a candidate path bandwidth constraint.
803 * The corresponding LSP will be changed too.
805 * @param candidate The candidate path of which the bandwidth should be removed
807 void srte_candidate_unset_bandwidth(struct srte_candidate
*candidate
)
809 struct srte_policy
*policy
= candidate
->policy
;
810 char endpoint
[ENDPOINT_STR_LENGTH
];
812 ipaddr2str(&policy
->endpoint
, endpoint
, sizeof(endpoint
));
813 PATH_POLICY_DEBUG("SR-TE(%s, %u): candidate %s config bandwidth unset",
814 endpoint
, policy
->color
, candidate
->name
);
815 UNSET_FLAG(candidate
->flags
, F_CANDIDATE_HAS_BANDWIDTH
);
816 UNSET_FLAG(candidate
->flags
, F_CANDIDATE_REQUIRED_BANDWIDTH
);
817 candidate
->bandwidth
= 0;
818 SET_FLAG(candidate
->flags
, F_CANDIDATE_MODIFIED
);
819 srte_lsp_unset_bandwidth(candidate
->lsp
);
823 * Remove an LSP bandwidth constraint.
825 * The changes will not be shown as part of the running configuration.
827 * @param lsp The lsp of which the bandwidth should be changed
829 void srte_lsp_unset_bandwidth(struct srte_lsp
*lsp
)
831 struct srte_candidate
*candidate
= lsp
->candidate
;
832 struct srte_policy
*policy
= candidate
->policy
;
833 char endpoint
[ENDPOINT_STR_LENGTH
];
835 ipaddr2str(&policy
->endpoint
, endpoint
, sizeof(endpoint
));
836 PATH_POLICY_DEBUG("SR-TE(%s, %u): candidate %s lsp bandwidth unset",
837 endpoint
, policy
->color
, candidate
->name
);
838 UNSET_FLAG(lsp
->flags
, F_CANDIDATE_HAS_BANDWIDTH
);
839 UNSET_FLAG(lsp
->flags
, F_CANDIDATE_REQUIRED_BANDWIDTH
);
840 SET_FLAG(candidate
->flags
, F_CANDIDATE_MODIFIED
);
845 * Sets a candidate path metric constraint.
847 * The corresponding LSP will be changed too.
849 * @param candidate The candidate path of which the metric should be changed
850 * @param type The metric type
851 * @param value The metric value
852 * @param required If the constraint is required (true) or only desired (false)
853 * @param is_bound If the metric is an indicative value or a strict upper bound
854 * @param is_computed If the metric was computed or configured
856 void srte_candidate_set_metric(struct srte_candidate
*candidate
,
857 enum srte_candidate_metric_type type
,
858 float value
, bool required
, bool is_bound
,
861 struct srte_policy
*policy
= candidate
->policy
;
862 char endpoint
[ENDPOINT_STR_LENGTH
];
864 ipaddr2str(&policy
->endpoint
, endpoint
, sizeof(endpoint
));
866 "SR-TE(%s, %u): candidate %s %sconfig metric %s (%u) set to %f (is-bound: %s; is_computed: %s)",
867 endpoint
, policy
->color
, candidate
->name
,
868 required
? "required " : "", srte_candidate_metric_name(type
),
869 type
, value
, is_bound
? "true" : "false",
870 is_computed
? "true" : "false");
871 assert((type
> 0) && (type
<= MAX_METRIC_TYPE
));
872 srte_set_metric(&candidate
->metrics
[type
- 1], value
, required
,
873 is_bound
, is_computed
);
874 srte_lsp_set_metric(candidate
->lsp
, type
, value
, required
, is_bound
,
876 SET_FLAG(candidate
->flags
, F_CANDIDATE_MODIFIED
);
880 * Sets an LSP metric constraint.
882 * The changes will not be shown as part of the running configuration.
884 * @param lsp The LSP of which the metric should be changed
885 * @param type The metric type
886 * @param value The metric value
887 * @param required If the constraint is required (true) or only desired (false)
888 * @param is_bound If the metric is an indicative value or a strict upper bound
889 * @param is_computed If the metric was computed or configured
891 void srte_lsp_set_metric(struct srte_lsp
*lsp
,
892 enum srte_candidate_metric_type type
, float value
,
893 bool required
, bool is_bound
, bool is_computed
)
895 struct srte_candidate
*candidate
= lsp
->candidate
;
896 struct srte_policy
*policy
= candidate
->policy
;
897 char endpoint
[ENDPOINT_STR_LENGTH
];
899 ipaddr2str(&policy
->endpoint
, endpoint
, sizeof(endpoint
));
901 "SR-TE(%s, %u): candidate %s %slsp metric %s (%u) set to %f (is-bound: %s; is_computed: %s)",
902 endpoint
, policy
->color
, candidate
->name
,
903 required
? "required " : "", srte_candidate_metric_name(type
),
904 type
, value
, is_bound
? "true" : "false",
905 is_computed
? "true" : "false");
906 assert((type
> 0) && (type
<= MAX_METRIC_TYPE
));
907 srte_set_metric(&lsp
->metrics
[type
- 1], value
, required
, is_bound
,
911 void srte_set_metric(struct srte_metric
*metric
, float value
, bool required
,
912 bool is_bound
, bool is_computed
)
914 SET_FLAG(metric
->flags
, F_METRIC_IS_DEFINED
);
915 COND_FLAG(metric
->flags
, F_METRIC_IS_REQUIRED
, required
);
916 COND_FLAG(metric
->flags
, F_METRIC_IS_BOUND
, is_bound
);
917 COND_FLAG(metric
->flags
, F_METRIC_IS_COMPUTED
, is_computed
);
918 metric
->value
= value
;
922 * Removes a candidate path metric constraint.
924 * The corresponding LSP will be changed too.
926 * @param candidate The candidate path from which the metric should be removed
927 * @param type The metric type
929 void srte_candidate_unset_metric(struct srte_candidate
*candidate
,
930 enum srte_candidate_metric_type type
)
932 struct srte_policy
*policy
= candidate
->policy
;
933 char endpoint
[ENDPOINT_STR_LENGTH
];
935 ipaddr2str(&policy
->endpoint
, endpoint
, sizeof(endpoint
));
937 "SR-TE(%s, %u): candidate %s config metric %s (%u) unset",
938 endpoint
, policy
->color
, candidate
->name
,
939 srte_candidate_metric_name(type
), type
);
940 assert((type
> 0) && (type
<= MAX_METRIC_TYPE
));
941 srte_unset_metric(&candidate
->metrics
[type
- 1]);
942 srte_lsp_unset_metric(candidate
->lsp
, type
);
943 SET_FLAG(candidate
->flags
, F_CANDIDATE_MODIFIED
);
947 * Removes a candidate path metric constraint.
949 * The changes will not be shown as part of the running configuration.
951 * @param lsp The LSP from which the metric should be removed
952 * @param type The metric type
954 void srte_lsp_unset_metric(struct srte_lsp
*lsp
,
955 enum srte_candidate_metric_type type
)
957 struct srte_candidate
*candidate
= lsp
->candidate
;
958 struct srte_policy
*policy
= candidate
->policy
;
959 char endpoint
[ENDPOINT_STR_LENGTH
];
961 ipaddr2str(&policy
->endpoint
, endpoint
, sizeof(endpoint
));
963 "SR-TE(%s, %u): candidate %s lsp metric %s (%u) unset",
964 endpoint
, policy
->color
, candidate
->name
,
965 srte_candidate_metric_name(type
), type
);
966 assert((type
> 0) && (type
<= MAX_METRIC_TYPE
));
967 srte_unset_metric(&lsp
->metrics
[type
- 1]);
970 void srte_unset_metric(struct srte_metric
*metric
)
972 UNSET_FLAG(metric
->flags
, F_METRIC_IS_DEFINED
);
973 UNSET_FLAG(metric
->flags
, F_METRIC_IS_BOUND
);
974 UNSET_FLAG(metric
->flags
, F_METRIC_IS_COMPUTED
);
979 * Sets a candidate path objective function.
981 * @param candidate The candidate path of which the OF should be changed
982 * @param required If the constraint is required (true) or only desired (false)
983 * @param type The objective function type
985 void srte_candidate_set_objfun(struct srte_candidate
*candidate
, bool required
,
986 enum objfun_type type
)
988 struct srte_policy
*policy
= candidate
->policy
;
989 char endpoint
[ENDPOINT_STR_LENGTH
];
991 ipaddr2str(&policy
->endpoint
, endpoint
, sizeof(endpoint
));
993 candidate
->objfun
= type
;
994 SET_FLAG(candidate
->flags
, F_CANDIDATE_HAS_OBJFUN
);
995 COND_FLAG(candidate
->flags
, F_CANDIDATE_REQUIRED_OBJFUN
, required
);
996 SET_FLAG(candidate
->flags
, F_CANDIDATE_MODIFIED
);
998 "SR-TE(%s, %u): candidate %s %sobjective function set to %s",
999 endpoint
, policy
->color
, candidate
->name
,
1000 required
? "required " : "", objfun_type_name(type
));
1004 * Removed the objective function constraint from a candidate path.
1006 * @param candidate The candidate path from which the OF should be removed
1008 void srte_candidate_unset_objfun(struct srte_candidate
*candidate
)
1010 struct srte_policy
*policy
= candidate
->policy
;
1011 char endpoint
[ENDPOINT_STR_LENGTH
];
1013 ipaddr2str(&policy
->endpoint
, endpoint
, sizeof(endpoint
));
1015 UNSET_FLAG(candidate
->flags
, F_CANDIDATE_HAS_OBJFUN
);
1016 UNSET_FLAG(candidate
->flags
, F_CANDIDATE_REQUIRED_OBJFUN
);
1017 SET_FLAG(candidate
->flags
, F_CANDIDATE_MODIFIED
);
1018 candidate
->objfun
= OBJFUN_UNDEFINED
;
1020 "SR-TE(%s, %u): candidate %s objective functions preferences unset",
1021 endpoint
, policy
->color
, candidate
->name
);
1024 static uint32_t filter_type_to_flag(enum affinity_filter_type type
)
1027 case AFFINITY_FILTER_EXCLUDE_ANY
:
1028 return F_CANDIDATE_HAS_EXCLUDE_ANY
;
1029 case AFFINITY_FILTER_INCLUDE_ANY
:
1030 return F_CANDIDATE_HAS_INCLUDE_ANY
;
1031 case AFFINITY_FILTER_INCLUDE_ALL
:
1032 return F_CANDIDATE_HAS_INCLUDE_ALL
;
1033 case AFFINITY_FILTER_UNDEFINED
:
1037 assert(!"Reached end of function we should never hit");
1040 static const char *filter_type_name(enum affinity_filter_type type
)
1043 case AFFINITY_FILTER_EXCLUDE_ANY
:
1044 return "exclude-any";
1045 case AFFINITY_FILTER_INCLUDE_ANY
:
1046 return "include-any";
1047 case AFFINITY_FILTER_INCLUDE_ALL
:
1048 return "include-all";
1049 case AFFINITY_FILTER_UNDEFINED
:
1053 assert(!"Reached end of function we should never hit");
1057 * Sets a candidate path affinity filter constraint.
1059 * @param candidate The candidate path of which the constraint should be changed
1060 * @param type The affinity constraint type to set
1061 * @param filter The bitmask filter of the constraint
1063 void srte_candidate_set_affinity_filter(struct srte_candidate
*candidate
,
1064 enum affinity_filter_type type
,
1067 struct srte_policy
*policy
= candidate
->policy
;
1068 char endpoint
[ENDPOINT_STR_LENGTH
];
1070 ipaddr2str(&policy
->endpoint
, endpoint
, sizeof(endpoint
));
1072 assert(type
> AFFINITY_FILTER_UNDEFINED
);
1073 assert(type
<= MAX_AFFINITY_FILTER_TYPE
);
1074 SET_FLAG(candidate
->flags
, filter_type_to_flag(type
));
1075 SET_FLAG(candidate
->flags
, F_CANDIDATE_MODIFIED
);
1076 candidate
->affinity_filters
[type
- 1] = filter
;
1078 "SR-TE(%s, %u): candidate %s affinity filter %s set to 0x%08x",
1079 endpoint
, policy
->color
, candidate
->name
,
1080 filter_type_name(type
), filter
);
1084 * Removes a candidate path affinity filter constraint.
1086 * @param candidate The candidate path from which the constraint should be
1088 * @param type The affinity constraint type to remove
1090 void srte_candidate_unset_affinity_filter(struct srte_candidate
*candidate
,
1091 enum affinity_filter_type type
)
1093 struct srte_policy
*policy
= candidate
->policy
;
1094 char endpoint
[ENDPOINT_STR_LENGTH
];
1096 ipaddr2str(&policy
->endpoint
, endpoint
, sizeof(endpoint
));
1098 assert(type
> AFFINITY_FILTER_UNDEFINED
);
1099 assert(type
<= MAX_AFFINITY_FILTER_TYPE
);
1100 UNSET_FLAG(candidate
->flags
, filter_type_to_flag(type
));
1101 SET_FLAG(candidate
->flags
, F_CANDIDATE_MODIFIED
);
1102 candidate
->affinity_filters
[type
- 1] = 0;
1104 "SR-TE(%s, %u): candidate %s affinity filter %s unset",
1105 endpoint
, policy
->color
, candidate
->name
,
1106 filter_type_name(type
));
1110 * Searches for a candidate path of the given policy.
1112 * @param policy The policy to search for candidate path
1113 * @param preference The preference of the candidate path you are looking for
1114 * @return The candidate path if found, NULL otherwise
1116 struct srte_candidate
*srte_candidate_find(struct srte_policy
*policy
,
1117 uint32_t preference
)
1119 struct srte_candidate search
;
1121 search
.preference
= preference
;
1122 return RB_FIND(srte_candidate_head
, &policy
->candidate_paths
, &search
);
1126 * Searches for a an entry of a given segment list.
1128 * @param segment_list The segment list to search for the entry
1129 * @param index The index of the entry you are looking for
1130 * @return The segment list entry if found, NULL otherwise.
1132 struct srte_segment_entry
*
1133 srte_segment_entry_find(struct srte_segment_list
*segment_list
, uint32_t index
)
1135 struct srte_segment_entry search
;
1137 search
.index
= index
;
1138 return RB_FIND(srte_segment_entry_head
, &segment_list
->segments
,
1143 * Updates a candidate status.
1145 * @param candidate The candidate of which the status should be updated
1146 * @param status The new candidate path status
1148 void srte_candidate_status_update(struct srte_candidate
*candidate
, int status
)
1150 struct srte_policy
*policy
= candidate
->policy
;
1151 char endpoint
[ENDPOINT_STR_LENGTH
];
1153 ipaddr2str(&policy
->endpoint
, endpoint
, sizeof(endpoint
));
1154 PATH_POLICY_DEBUG("SR-TE(%s, %u): zebra updated status to %d", endpoint
,
1155 policy
->color
, status
);
1157 case ZEBRA_SR_POLICY_DOWN
:
1158 switch (policy
->status
) {
1159 /* If the policy is GOING_UP, and zebra faild
1160 to install it, we wait for zebra to retry */
1161 /* TODO: Add some timeout after which we would
1162 get is back to DOWN and remove the
1164 case SRTE_POLICY_STATUS_GOING_UP
:
1165 case SRTE_POLICY_STATUS_DOWN
:
1167 case SRTE_POLICY_STATUS_UNKNOWN
:
1168 case SRTE_POLICY_STATUS_UP
:
1169 case SRTE_POLICY_STATUS_GOING_DOWN
:
1170 policy
->status
= SRTE_POLICY_STATUS_DOWN
;
1171 srte_policy_status_log(policy
);
1175 case ZEBRA_SR_POLICY_UP
:
1176 switch (policy
->status
) {
1177 case SRTE_POLICY_STATUS_UP
:
1179 case SRTE_POLICY_STATUS_UNKNOWN
:
1180 case SRTE_POLICY_STATUS_DOWN
:
1181 case SRTE_POLICY_STATUS_GOING_DOWN
:
1182 case SRTE_POLICY_STATUS_GOING_UP
:
1183 policy
->status
= SRTE_POLICY_STATUS_UP
;
1184 srte_policy_status_log(policy
);
1190 trigger_pathd_candidate_updated(candidate
);
1194 * Flags the segment lists from give originator for removal.
1196 * The function srte_apply_changes must be called afterward for
1197 * the segment list to be removed.
1199 * @param originator The originator tag of the segment list to be marked
1200 * @param force If the unset should be forced regardless of the originator
1202 void srte_candidate_unset_segment_list(const char *originator
, bool force
)
1204 if (originator
== NULL
) {
1206 "Cannot unset segment list because originator is NULL");
1210 PATH_POLICY_DEBUG("Unset segment lists for originator %s", originator
);
1212 /* Iterate the policies, then iterate each policy's candidate path
1213 * to check the candidate path's segment list originator */
1214 struct srte_policy
*policy
;
1215 RB_FOREACH (policy
, srte_policy_head
, &srte_policies
) {
1216 PATH_POLICY_DEBUG("Unset segment lists checking policy %s",
1218 struct srte_candidate
*candidate
;
1219 RB_FOREACH (candidate
, srte_candidate_head
,
1220 &policy
->candidate_paths
) {
1222 "Unset segment lists checking candidate %s",
1224 if (candidate
->lsp
== NULL
) {
1228 /* The candidate->lsp->segment_list is operational data,
1229 * configured by the PCE. We dont want to modify the
1230 * candidate->segment_list,
1231 * which is configuration data. */
1232 struct srte_segment_list
*segment_list
=
1233 candidate
->lsp
->segment_list
;
1234 if (segment_list
== NULL
) {
1238 if (segment_list
->protocol_origin
1239 == SRTE_ORIGIN_LOCAL
) {
1241 "Cannot unset segment list %s because it was created locally",
1242 segment_list
->name
);
1246 /* In the case of last pce,we force the unset
1247 * because we don't have pce by prefix (TODO) is all
1249 if (strncmp(segment_list
->originator
, originator
,
1250 sizeof(segment_list
->originator
))
1253 PATH_POLICY_DEBUG("Unset segment list %s",
1254 segment_list
->name
);
1255 SET_FLAG(segment_list
->flags
,
1256 F_SEGMENT_LIST_DELETED
);
1257 SET_FLAG(candidate
->flags
,
1258 F_CANDIDATE_MODIFIED
);
1259 candidate
->lsp
->segment_list
= NULL
;
1266 * Gives a string representation of given protocol origin enum.
1268 * @param origin The enum you want a string representation of
1269 * @return The string representation of given enum
1271 const char *srte_origin2str(enum srte_protocol_origin origin
)
1274 case SRTE_ORIGIN_PCEP
:
1276 case SRTE_ORIGIN_BGP
:
1278 case SRTE_ORIGIN_LOCAL
:
1280 case SRTE_ORIGIN_UNDEFINED
:
1284 assert(!"Reached end of function we should never hit");
1287 void path_policy_show_debugging(struct vty
*vty
)
1289 if (DEBUG_FLAGS_CHECK(&path_policy_debug
, PATH_POLICY_DEBUG_BASIC
))
1290 vty_out(vty
, " Path policy debugging is on\n");
1293 void pathd_shutdown(void)
1295 path_ted_teardown();
1300 void trigger_pathd_candidate_created(struct srte_candidate
*candidate
)
1302 /* The hook is called asynchronously to let the PCEP module
1303 time to send a response to the PCE before receiving any updates from
1304 pathd. In addition, a minimum amount of time need to pass before
1305 the hook is called to prevent the hook to be called multiple times
1306 from changing the candidate by hand with the console */
1307 if (candidate
->hook_timer
!= NULL
)
1309 thread_add_timer(master
, trigger_pathd_candidate_created_timer
,
1310 (void *)candidate
, HOOK_DELAY
, &candidate
->hook_timer
);
1313 void trigger_pathd_candidate_created_timer(struct thread
*thread
)
1315 struct srte_candidate
*candidate
= THREAD_ARG(thread
);
1316 candidate
->hook_timer
= NULL
;
1317 hook_call(pathd_candidate_created
, candidate
);
1320 void trigger_pathd_candidate_updated(struct srte_candidate
*candidate
)
1322 /* The hook is called asynchronously to let the PCEP module
1323 time to send a response to the PCE before receiving any updates from
1324 pathd. In addition, a minimum amount of time need to pass before
1325 the hook is called to prevent the hook to be called multiple times
1326 from changing the candidate by hand with the console */
1327 if (candidate
->hook_timer
!= NULL
)
1329 thread_add_timer(master
, trigger_pathd_candidate_updated_timer
,
1330 (void *)candidate
, HOOK_DELAY
, &candidate
->hook_timer
);
1333 void trigger_pathd_candidate_updated_timer(struct thread
*thread
)
1335 struct srte_candidate
*candidate
= THREAD_ARG(thread
);
1336 candidate
->hook_timer
= NULL
;
1337 hook_call(pathd_candidate_updated
, candidate
);
1340 void trigger_pathd_candidate_removed(struct srte_candidate
*candidate
)
1342 /* The hook needs to be call synchronously, otherwise the candidate
1343 path will be already deleted when the handler is called */
1344 if (candidate
->hook_timer
!= NULL
) {
1345 thread_cancel(&candidate
->hook_timer
);
1346 candidate
->hook_timer
= NULL
;
1348 hook_call(pathd_candidate_removed
, candidate
);
1351 const char *srte_candidate_metric_name(enum srte_candidate_metric_type type
)
1354 case SRTE_CANDIDATE_METRIC_TYPE_IGP
:
1356 case SRTE_CANDIDATE_METRIC_TYPE_TE
:
1358 case SRTE_CANDIDATE_METRIC_TYPE_HC
:
1360 case SRTE_CANDIDATE_METRIC_TYPE_ABC
:
1362 case SRTE_CANDIDATE_METRIC_TYPE_LMLL
:
1364 case SRTE_CANDIDATE_METRIC_TYPE_CIGP
:
1366 case SRTE_CANDIDATE_METRIC_TYPE_CTE
:
1368 case SRTE_CANDIDATE_METRIC_TYPE_PIGP
:
1370 case SRTE_CANDIDATE_METRIC_TYPE_PTE
:
1372 case SRTE_CANDIDATE_METRIC_TYPE_PHC
:
1374 case SRTE_CANDIDATE_METRIC_TYPE_MSD
:
1376 case SRTE_CANDIDATE_METRIC_TYPE_PD
:
1378 case SRTE_CANDIDATE_METRIC_TYPE_PDV
:
1380 case SRTE_CANDIDATE_METRIC_TYPE_PL
:
1382 case SRTE_CANDIDATE_METRIC_TYPE_PPD
:
1384 case SRTE_CANDIDATE_METRIC_TYPE_PPDV
:
1386 case SRTE_CANDIDATE_METRIC_TYPE_PPL
:
1388 case SRTE_CANDIDATE_METRIC_TYPE_NAP
:
1390 case SRTE_CANDIDATE_METRIC_TYPE_NLP
:
1392 case SRTE_CANDIDATE_METRIC_TYPE_DC
:
1394 case SRTE_CANDIDATE_METRIC_TYPE_BNC
:
1401 int32_t srte_ted_do_query_type_c(struct srte_segment_entry
*entry
,
1402 struct prefix
*prefix_cli
, uint32_t algo
)
1405 uint32_t ted_sid
= MPLS_LABEL_NONE
;
1407 if (!entry
|| !prefix_cli
)
1410 if (!path_ted_is_initialized())
1413 ted_sid
= path_ted_query_type_c(prefix_cli
, algo
);
1414 if (ted_sid
== MPLS_LABEL_NONE
) {
1415 zlog_warn(" %s: PATHD-TED: SL: ERROR query C : ted-sid (%d)",
1419 "%s: PATHD-TED: SL: Success query C : ted-sid (%d)",
1422 if (CHECK_SID(entry
->segment_list
->protocol_origin
, ted_sid
,
1423 entry
->sid_value
)) {
1424 status
= PATH_SID_ERROR
;
1426 srte_segment_set_local_modification(entry
->segment_list
, entry
,
1431 int32_t srte_ted_do_query_type_e(struct srte_segment_entry
*entry
,
1432 struct prefix
*prefix_cli
,
1433 uint32_t local_iface
)
1436 uint32_t ted_sid
= MPLS_LABEL_NONE
;
1438 if (!entry
|| !prefix_cli
)
1441 if (!path_ted_is_initialized())
1444 ted_sid
= path_ted_query_type_e(prefix_cli
, local_iface
);
1445 if (ted_sid
== MPLS_LABEL_NONE
) {
1446 zlog_warn(" %s: PATHD-TED: SL: ERROR query E : ted-sid (%d)",
1450 "%s: PATHD-TED: SL: Success query E : ted-sid (%d)",
1453 if (CHECK_SID(entry
->segment_list
->protocol_origin
, ted_sid
,
1454 entry
->sid_value
)) {
1455 status
= PATH_SID_ERROR
;
1457 srte_segment_set_local_modification(entry
->segment_list
, entry
,
1462 int32_t srte_ted_do_query_type_f(struct srte_segment_entry
*entry
,
1463 struct ipaddr
*local
, struct ipaddr
*remote
)
1466 uint32_t ted_sid
= MPLS_LABEL_NONE
;
1468 if (!entry
|| !local
|| !remote
)
1471 if (!path_ted_is_initialized())
1474 ted_sid
= path_ted_query_type_f(local
, remote
);
1475 if (ted_sid
== MPLS_LABEL_NONE
) {
1476 zlog_warn("%s:SL: ERROR query F : ted-sid (%d)", __func__
,
1479 PATH_TED_DEBUG("%s:SL: Success query F : ted-sid (%d)",
1482 if (CHECK_SID(entry
->segment_list
->protocol_origin
, ted_sid
,
1483 entry
->sid_value
)) {
1484 status
= PATH_SID_ERROR
;
1486 srte_segment_set_local_modification(entry
->segment_list
, entry
,