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