1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2020 NetDEF, Inc.
7 #include <lib_errors.h>
9 #include "northbound.h"
12 #include "pathd/path_zebra.h"
13 #include "pathd/path_nb.h"
16 * XPath: /frr-pathd:pathd
18 void pathd_apply_finish(struct nb_cb_apply_finish_args
*args
)
24 * XPath: /frr-pathd:pathd/srte/segment-list
26 int pathd_srte_segment_list_create(struct nb_cb_create_args
*args
)
28 struct srte_segment_list
*segment_list
;
31 if (args
->event
!= NB_EV_APPLY
)
34 name
= yang_dnode_get_string(args
->dnode
, "./name");
35 segment_list
= srte_segment_list_add(name
);
36 nb_running_set_entry(args
->dnode
, segment_list
);
37 SET_FLAG(segment_list
->flags
, F_SEGMENT_LIST_NEW
);
42 int pathd_srte_segment_list_destroy(struct nb_cb_destroy_args
*args
)
44 struct srte_segment_list
*segment_list
;
46 if (args
->event
!= NB_EV_APPLY
)
49 segment_list
= nb_running_unset_entry(args
->dnode
);
50 SET_FLAG(segment_list
->flags
, F_SEGMENT_LIST_DELETED
);
56 * XPath: /frr-pathd:pathd/srte/segment-list/protocol-origin
58 int pathd_srte_segment_list_protocol_origin_modify(
59 struct nb_cb_modify_args
*args
)
61 struct srte_segment_list
*segment_list
;
63 if (args
->event
!= NB_EV_APPLY
)
66 segment_list
= nb_running_get_entry(args
->dnode
, NULL
, true);
67 segment_list
->protocol_origin
= yang_dnode_get_enum(args
->dnode
, NULL
);
68 SET_FLAG(segment_list
->flags
, F_SEGMENT_LIST_MODIFIED
);
74 * XPath: /frr-pathd:pathd/srte/segment-list/originator
76 int pathd_srte_segment_list_originator_modify(struct nb_cb_modify_args
*args
)
78 struct srte_segment_list
*segment_list
;
79 const char *originator
;
81 if (args
->event
!= NB_EV_APPLY
)
84 segment_list
= nb_running_get_entry(args
->dnode
, NULL
, true);
85 originator
= yang_dnode_get_string(args
->dnode
, NULL
);
86 strlcpy(segment_list
->originator
, originator
,
87 sizeof(segment_list
->originator
));
88 SET_FLAG(segment_list
->flags
, F_SEGMENT_LIST_MODIFIED
);
95 * XPath: /frr-pathd:pathd/srte/segment-list/segment
97 int pathd_srte_segment_list_segment_create(struct nb_cb_create_args
*args
)
99 struct srte_segment_list
*segment_list
;
100 struct srte_segment_entry
*segment
;
103 if (args
->event
!= NB_EV_APPLY
)
106 segment_list
= nb_running_get_entry(args
->dnode
, NULL
, true);
107 index
= yang_dnode_get_uint32(args
->dnode
, "./index");
108 segment
= srte_segment_entry_add(segment_list
, index
);
109 nb_running_set_entry(args
->dnode
, segment
);
110 SET_FLAG(segment_list
->flags
, F_SEGMENT_LIST_MODIFIED
);
115 int pathd_srte_segment_list_segment_destroy(struct nb_cb_destroy_args
*args
)
117 struct srte_segment_entry
*segment
;
119 if (args
->event
!= NB_EV_APPLY
)
122 segment
= nb_running_unset_entry(args
->dnode
);
123 SET_FLAG(segment
->segment_list
->flags
, F_SEGMENT_LIST_MODIFIED
);
125 srte_segment_entry_del(segment
);
131 * XPath: /frr-pathd:pathd/srte/segment-list/segment/sid-value
133 int pathd_srte_segment_list_segment_sid_value_modify(
134 struct nb_cb_modify_args
*args
)
136 mpls_label_t sid_value
;
137 struct srte_segment_entry
*segment
;
139 if (args
->event
!= NB_EV_APPLY
)
142 segment
= nb_running_get_entry(args
->dnode
, NULL
, true);
143 sid_value
= yang_dnode_get_uint32(args
->dnode
, NULL
);
144 segment
->sid_value
= sid_value
;
145 SET_FLAG(segment
->segment_list
->flags
, F_SEGMENT_LIST_MODIFIED
);
150 int pathd_srte_segment_list_segment_sid_value_destroy(
151 struct nb_cb_destroy_args
*args
)
153 struct srte_segment_entry
*segment
;
155 if (args
->event
!= NB_EV_APPLY
)
158 segment
= nb_running_get_entry(args
->dnode
, NULL
, true);
159 segment
->sid_value
= MPLS_LABEL_NONE
;
160 SET_FLAG(segment
->segment_list
->flags
, F_SEGMENT_LIST_MODIFIED
);
166 int pathd_srte_segment_list_segment_nai_destroy(struct nb_cb_destroy_args
*args
)
168 struct srte_segment_entry
*segment
;
170 if (args
->event
!= NB_EV_APPLY
)
173 segment
= nb_running_get_entry(args
->dnode
, NULL
, true);
174 segment
->nai_type
= SRTE_SEGMENT_NAI_TYPE_NONE
;
175 segment
->nai_local_addr
.ipa_type
= IPADDR_NONE
;
176 segment
->nai_local_iface
= 0;
177 segment
->nai_remote_addr
.ipa_type
= IPADDR_NONE
;
178 segment
->nai_remote_iface
= 0;
183 void pathd_srte_segment_list_segment_nai_apply_finish(
184 struct nb_cb_apply_finish_args
*args
)
186 struct srte_segment_entry
*segment
;
187 enum srte_segment_nai_type type
;
188 struct ipaddr local_addr
, remote_addr
;
189 uint32_t local_iface
= 0, remote_iface
= 0;
190 uint8_t algo
= 0, local_prefix_len
= 0;
191 const char *algo_buf
, *local_prefix_len_buf
;
193 segment
= nb_running_get_entry(args
->dnode
, NULL
, true);
194 type
= yang_dnode_get_enum(args
->dnode
, "./type");
196 yang_dnode_get_ip(&local_addr
, args
->dnode
, "./local-address");
199 case SRTE_SEGMENT_NAI_TYPE_IPV4_NODE
:
200 case SRTE_SEGMENT_NAI_TYPE_IPV6_NODE
:
202 case SRTE_SEGMENT_NAI_TYPE_IPV4_ADJACENCY
:
203 case SRTE_SEGMENT_NAI_TYPE_IPV6_ADJACENCY
:
204 yang_dnode_get_ip(&remote_addr
, args
->dnode
,
207 case SRTE_SEGMENT_NAI_TYPE_IPV4_UNNUMBERED_ADJACENCY
:
208 yang_dnode_get_ip(&remote_addr
, args
->dnode
,
211 yang_dnode_get_uint32(args
->dnode
, "./local-interface");
212 remote_iface
= yang_dnode_get_uint32(args
->dnode
,
213 "./remote-interface");
215 case SRTE_SEGMENT_NAI_TYPE_IPV4_ALGORITHM
:
216 algo_buf
= yang_dnode_get_string(args
->dnode
, "./algorithm");
217 algo
= atoi(algo_buf
);
218 local_prefix_len_buf
= yang_dnode_get_string(
219 args
->dnode
, "./local-prefix-len");
220 local_prefix_len
= atoi(local_prefix_len_buf
);
222 case SRTE_SEGMENT_NAI_TYPE_IPV4_LOCAL_IFACE
:
224 yang_dnode_get_uint32(args
->dnode
, "./local-interface");
225 local_prefix_len_buf
= yang_dnode_get_string(
226 args
->dnode
, "./local-prefix-len");
227 local_prefix_len
= atoi(local_prefix_len_buf
);
229 case SRTE_SEGMENT_NAI_TYPE_NONE
:
230 case SRTE_SEGMENT_NAI_TYPE_IPV6_ADJACENCY_LINK_LOCAL_ADDRESSES
:
231 case SRTE_SEGMENT_NAI_TYPE_IPV6_LOCAL_IFACE
:
232 case SRTE_SEGMENT_NAI_TYPE_IPV6_ALGORITHM
:
236 zlog_debug(" Segment list name (%d) index (%s) ", segment
->index
,
237 segment
->segment_list
->name
);
238 if (srte_segment_entry_set_nai(segment
, type
, &local_addr
, local_iface
,
239 &remote_addr
, remote_iface
, algo
,
241 SET_FLAG(segment
->segment_list
->flags
,
242 F_SEGMENT_LIST_SID_CONFLICT
);
246 * XPath: /frr-pathd:pathd/srte/policy
248 int pathd_srte_policy_create(struct nb_cb_create_args
*args
)
250 struct srte_policy
*policy
;
252 struct ipaddr endpoint
;
254 if (args
->event
!= NB_EV_APPLY
)
257 color
= yang_dnode_get_uint32(args
->dnode
, "./color");
258 yang_dnode_get_ip(&endpoint
, args
->dnode
, "./endpoint");
259 policy
= srte_policy_add(color
, &endpoint
, SRTE_ORIGIN_LOCAL
, NULL
);
261 nb_running_set_entry(args
->dnode
, policy
);
262 SET_FLAG(policy
->flags
, F_POLICY_NEW
);
267 int pathd_srte_policy_destroy(struct nb_cb_destroy_args
*args
)
269 struct srte_policy
*policy
;
271 if (args
->event
!= NB_EV_APPLY
)
274 policy
= nb_running_unset_entry(args
->dnode
);
275 SET_FLAG(policy
->flags
, F_POLICY_DELETED
);
281 * XPath: /frr-pathd:pathd/srte/policy/name
283 int pathd_srte_policy_name_modify(struct nb_cb_modify_args
*args
)
285 struct srte_policy
*policy
;
288 if (args
->event
!= NB_EV_APPLY
&& args
->event
!= NB_EV_VALIDATE
)
291 policy
= nb_running_get_entry(args
->dnode
, NULL
, true);
293 if (args
->event
== NB_EV_VALIDATE
) {
294 /* the policy name is fixed after setting it once */
295 if (strlen(policy
->name
) > 0) {
296 flog_warn(EC_LIB_NB_CB_CONFIG_VALIDATE
,
297 "The SR Policy name is fixed!");
298 return NB_ERR_RESOURCE
;
303 name
= yang_dnode_get_string(args
->dnode
, NULL
);
304 strlcpy(policy
->name
, name
, sizeof(policy
->name
));
305 SET_FLAG(policy
->flags
, F_POLICY_MODIFIED
);
310 int pathd_srte_policy_name_destroy(struct nb_cb_destroy_args
*args
)
312 struct srte_policy
*policy
;
314 if (args
->event
!= NB_EV_APPLY
)
317 policy
= nb_running_get_entry(args
->dnode
, NULL
, true);
318 policy
->name
[0] = '\0';
319 SET_FLAG(policy
->flags
, F_POLICY_MODIFIED
);
325 * XPath: /frr-pathd:pathd/srte/policy/binding-sid
327 int pathd_srte_policy_binding_sid_modify(struct nb_cb_modify_args
*args
)
329 struct srte_policy
*policy
;
330 mpls_label_t binding_sid
;
332 binding_sid
= yang_dnode_get_uint32(args
->dnode
, NULL
);
334 switch (args
->event
) {
338 if (path_zebra_request_label(binding_sid
) < 0)
339 return NB_ERR_RESOURCE
;
344 policy
= nb_running_get_entry(args
->dnode
, NULL
, true);
345 srte_policy_update_binding_sid(policy
, binding_sid
);
346 SET_FLAG(policy
->flags
, F_POLICY_MODIFIED
);
353 int pathd_srte_policy_binding_sid_destroy(struct nb_cb_destroy_args
*args
)
355 struct srte_policy
*policy
;
357 if (args
->event
!= NB_EV_APPLY
)
360 policy
= nb_running_get_entry(args
->dnode
, NULL
, true);
361 srte_policy_update_binding_sid(policy
, MPLS_LABEL_NONE
);
362 SET_FLAG(policy
->flags
, F_POLICY_MODIFIED
);
368 * XPath: /frr-pathd:pathd/srte/policy/candidate-path
370 int pathd_srte_policy_candidate_path_create(struct nb_cb_create_args
*args
)
372 struct srte_policy
*policy
;
373 struct srte_candidate
*candidate
;
376 if (args
->event
!= NB_EV_APPLY
)
379 policy
= nb_running_get_entry(args
->dnode
, NULL
, true);
380 preference
= yang_dnode_get_uint32(args
->dnode
, "./preference");
382 srte_candidate_add(policy
, preference
, SRTE_ORIGIN_LOCAL
, NULL
);
383 nb_running_set_entry(args
->dnode
, candidate
);
384 SET_FLAG(candidate
->flags
, F_CANDIDATE_NEW
);
389 int pathd_srte_policy_candidate_path_destroy(struct nb_cb_destroy_args
*args
)
391 struct srte_candidate
*candidate
;
393 if (args
->event
!= NB_EV_APPLY
)
396 candidate
= nb_running_unset_entry(args
->dnode
);
397 SET_FLAG(candidate
->flags
, F_CANDIDATE_DELETED
);
403 * XPath: /frr-pathd:pathd/srte/policy/candidate-path/name
405 int pathd_srte_policy_candidate_path_name_modify(struct nb_cb_modify_args
*args
)
407 struct srte_candidate
*candidate
;
409 char xpath
[XPATH_MAXLEN
];
410 char xpath_buf
[XPATH_MAXLEN
- 3];
412 if (args
->event
!= NB_EV_APPLY
&& args
->event
!= NB_EV_VALIDATE
)
415 /* the candidate name is fixed after setting it once, this is checked
417 if (args
->event
== NB_EV_VALIDATE
) {
418 /* first get the precise path to the candidate path */
419 yang_dnode_get_path(args
->dnode
, xpath_buf
, sizeof(xpath_buf
));
420 snprintf(xpath
, sizeof(xpath
), "%s%s", xpath_buf
, "/..");
422 candidate
= nb_running_get_entry_non_rec(NULL
, xpath
, false);
424 /* then check if it exists and if the name was provided */
425 if (candidate
&& strlen(candidate
->name
) > 0) {
426 flog_warn(EC_LIB_NB_CB_CONFIG_VALIDATE
,
427 "The candidate name is fixed!");
428 return NB_ERR_RESOURCE
;
433 candidate
= nb_running_get_entry(args
->dnode
, NULL
, true);
435 name
= yang_dnode_get_string(args
->dnode
, NULL
);
436 strlcpy(candidate
->name
, name
, sizeof(candidate
->name
));
437 SET_FLAG(candidate
->flags
, F_CANDIDATE_MODIFIED
);
443 static int affinity_filter_modify(struct nb_cb_modify_args
*args
,
444 enum affinity_filter_type type
)
447 struct srte_candidate
*candidate
;
449 if (args
->event
!= NB_EV_APPLY
)
452 assert(args
->context
!= NULL
);
453 candidate
= nb_running_get_entry(args
->dnode
, NULL
, true);
454 filter
= yang_dnode_get_uint32(args
->dnode
, NULL
);
455 srte_candidate_set_affinity_filter(candidate
, type
, filter
);
460 static int affinity_filter_destroy(struct nb_cb_destroy_args
*args
,
461 enum affinity_filter_type type
)
463 struct srte_candidate
*candidate
;
465 if (args
->event
!= NB_EV_APPLY
)
468 assert(args
->context
!= NULL
);
469 candidate
= nb_running_get_entry(args
->dnode
, NULL
, true);
470 srte_candidate_unset_affinity_filter(candidate
, type
);
477 * /frr-pathd:pathd/srte/policy/candidate-path/constraints/affinity/exclude-any
480 int pathd_srte_policy_candidate_path_exclude_any_modify(
481 struct nb_cb_modify_args
*args
)
483 return affinity_filter_modify(args
, AFFINITY_FILTER_EXCLUDE_ANY
);
486 int pathd_srte_policy_candidate_path_exclude_any_destroy(
487 struct nb_cb_destroy_args
*args
)
489 return affinity_filter_destroy(args
, AFFINITY_FILTER_EXCLUDE_ANY
);
495 * /frr-pathd:pathd/srte/policy/candidate-path/constraints/affinity/include-any
497 int pathd_srte_policy_candidate_path_include_any_modify(
498 struct nb_cb_modify_args
*args
)
500 return affinity_filter_modify(args
, AFFINITY_FILTER_INCLUDE_ANY
);
503 int pathd_srte_policy_candidate_path_include_any_destroy(
504 struct nb_cb_destroy_args
*args
)
506 return affinity_filter_destroy(args
, AFFINITY_FILTER_INCLUDE_ANY
);
512 * /frr-pathd:pathd/srte/policy/candidate-path/constraints/affinity/include-all
514 int pathd_srte_policy_candidate_path_include_all_modify(
515 struct nb_cb_modify_args
*args
)
517 return affinity_filter_modify(args
, AFFINITY_FILTER_INCLUDE_ALL
);
520 int pathd_srte_policy_candidate_path_include_all_destroy(
521 struct nb_cb_destroy_args
*args
)
523 return affinity_filter_destroy(args
, AFFINITY_FILTER_INCLUDE_ALL
);
528 * XPath: /frr-pathd:pathd/srte/policy/candidate-path/constraints/metrics
530 int pathd_srte_policy_candidate_path_metrics_destroy(
531 struct nb_cb_destroy_args
*args
)
533 struct srte_candidate
*candidate
;
534 enum srte_candidate_metric_type type
;
536 if (args
->event
!= NB_EV_APPLY
)
539 assert(args
->context
!= NULL
);
540 candidate
= nb_running_get_entry(args
->dnode
, NULL
, true);
542 type
= yang_dnode_get_enum(args
->dnode
, "./type");
543 srte_candidate_unset_metric(candidate
, type
);
548 void pathd_srte_policy_candidate_path_metrics_apply_finish(
549 struct nb_cb_apply_finish_args
*args
)
551 struct srte_candidate
*candidate
;
552 enum srte_candidate_metric_type type
;
554 bool required
, is_bound
= false, is_computed
= false;
556 assert(args
->context
!= NULL
);
558 candidate
= nb_running_get_entry(args
->dnode
, NULL
, true);
560 type
= yang_dnode_get_enum(args
->dnode
, "./type");
561 value
= (float)yang_dnode_get_dec64(args
->dnode
, "./value");
562 required
= yang_dnode_get_bool(args
->dnode
, "./required");
563 if (yang_dnode_exists(args
->dnode
, "./is-bound"))
564 is_bound
= yang_dnode_get_bool(args
->dnode
, "./is-bound");
565 if (yang_dnode_exists(args
->dnode
, "./is-computed"))
566 is_computed
= yang_dnode_get_bool(args
->dnode
, "./is-computed");
568 srte_candidate_set_metric(candidate
, type
, value
, required
, is_bound
,
574 * /frr-pathd:pathd/srte/policy/candidate-path/constraints/objective-function
576 int pathd_srte_policy_candidate_path_objfun_destroy(
577 struct nb_cb_destroy_args
*args
)
579 struct srte_candidate
*candidate
;
581 if (args
->event
!= NB_EV_APPLY
)
584 assert(args
->context
!= NULL
);
586 candidate
= nb_running_get_entry(args
->dnode
, NULL
, true);
587 srte_candidate_unset_objfun(candidate
);
592 void pathd_srte_policy_candidate_path_objfun_apply_finish(
593 struct nb_cb_apply_finish_args
*args
)
595 struct srte_candidate
*candidate
;
596 enum objfun_type type
;
599 candidate
= nb_running_get_entry(args
->dnode
, NULL
, true);
600 required
= yang_dnode_get_bool(args
->dnode
, "./required");
601 type
= yang_dnode_get_enum(args
->dnode
, "./type");
602 srte_candidate_set_objfun(candidate
, required
, type
);
606 * XPath: /frr-pathd:pathd/srte/policy/candidate-path/protocol-origin
608 int pathd_srte_policy_candidate_path_protocol_origin_modify(
609 struct nb_cb_modify_args
*args
)
611 struct srte_candidate
*candidate
;
612 enum srte_protocol_origin protocol_origin
;
614 if (args
->event
!= NB_EV_APPLY
)
617 candidate
= nb_running_get_entry(args
->dnode
, NULL
, true);
618 protocol_origin
= yang_dnode_get_enum(args
->dnode
, NULL
);
619 candidate
->protocol_origin
= protocol_origin
;
620 candidate
->lsp
->protocol_origin
= protocol_origin
;
621 SET_FLAG(candidate
->flags
, F_CANDIDATE_MODIFIED
);
627 * XPath: /frr-pathd:pathd/srte/policy/candidate-path/originator
629 int pathd_srte_policy_candidate_path_originator_modify(
630 struct nb_cb_modify_args
*args
)
632 struct srte_candidate
*candidate
;
633 const char *originator
;
635 if (args
->event
!= NB_EV_APPLY
)
638 candidate
= nb_running_get_entry(args
->dnode
, NULL
, true);
639 originator
= yang_dnode_get_string(args
->dnode
, NULL
);
640 strlcpy(candidate
->originator
, originator
,
641 sizeof(candidate
->originator
));
642 strlcpy(candidate
->lsp
->originator
, originator
,
643 sizeof(candidate
->lsp
->originator
));
644 SET_FLAG(candidate
->flags
, F_CANDIDATE_MODIFIED
);
650 * XPath: /frr-pathd:pathd/srte/policy/candidate-path/type
652 int pathd_srte_policy_candidate_path_type_modify(struct nb_cb_modify_args
*args
)
654 struct srte_candidate
*candidate
;
655 enum srte_candidate_type type
;
656 char xpath
[XPATH_MAXLEN
];
657 char xpath_buf
[XPATH_MAXLEN
- 3];
659 if (args
->event
!= NB_EV_APPLY
&& args
->event
!= NB_EV_VALIDATE
)
662 /* the candidate type is fixed after setting it once, this is checked
664 if (args
->event
== NB_EV_VALIDATE
) {
665 /* first get the precise path to the candidate path */
666 yang_dnode_get_path(args
->dnode
, xpath_buf
, sizeof(xpath_buf
));
667 snprintf(xpath
, sizeof(xpath
), "%s%s", xpath_buf
, "/..");
669 candidate
= nb_running_get_entry_non_rec(NULL
, xpath
, false);
671 /* then check if it exists and if the type was provided */
673 && candidate
->type
!= SRTE_CANDIDATE_TYPE_UNDEFINED
) {
674 flog_warn(EC_LIB_NB_CB_CONFIG_VALIDATE
,
675 "The candidate type is fixed!");
676 return NB_ERR_RESOURCE
;
681 candidate
= nb_running_get_entry(args
->dnode
, NULL
, true);
683 type
= yang_dnode_get_enum(args
->dnode
, NULL
);
684 candidate
->type
= type
;
685 SET_FLAG(candidate
->flags
, F_CANDIDATE_MODIFIED
);
691 * XPath: /frr-pathd:pathd/srte/policy/candidate-path/segment-list-name
693 int pathd_srte_policy_candidate_path_segment_list_name_modify(
694 struct nb_cb_modify_args
*args
)
696 struct srte_candidate
*candidate
;
697 const char *segment_list_name
;
699 if (args
->event
!= NB_EV_APPLY
)
702 candidate
= nb_running_get_entry(args
->dnode
, NULL
, true);
703 segment_list_name
= yang_dnode_get_string(args
->dnode
, NULL
);
705 candidate
->segment_list
= srte_segment_list_find(segment_list_name
);
706 candidate
->lsp
->segment_list
= candidate
->segment_list
;
707 assert(candidate
->segment_list
);
708 SET_FLAG(candidate
->flags
, F_CANDIDATE_MODIFIED
);
713 int pathd_srte_policy_candidate_path_segment_list_name_destroy(
714 struct nb_cb_destroy_args
*args
)
716 struct srte_candidate
*candidate
;
718 if (args
->event
!= NB_EV_APPLY
)
721 candidate
= nb_running_get_entry(args
->dnode
, NULL
, true);
722 candidate
->segment_list
= NULL
;
723 candidate
->lsp
->segment_list
= NULL
;
724 SET_FLAG(candidate
->flags
, F_CANDIDATE_MODIFIED
);
730 * XPath: /frr-pathd:pathd/srte/policy/candidate-path/constraints/bandwidth
732 void pathd_srte_policy_candidate_path_bandwidth_apply_finish(
733 struct nb_cb_apply_finish_args
*args
)
735 struct srte_candidate
*candidate
;
739 assert(args
->context
!= NULL
);
741 candidate
= nb_running_get_entry(args
->dnode
, NULL
, true);
742 value
= (float)yang_dnode_get_dec64(args
->dnode
, "./value");
743 required
= yang_dnode_get_bool(args
->dnode
, "./required");
744 srte_candidate_set_bandwidth(candidate
, value
, required
);
747 int pathd_srte_policy_candidate_path_bandwidth_destroy(
748 struct nb_cb_destroy_args
*args
)
750 struct srte_candidate
*candidate
;
752 if (args
->event
!= NB_EV_APPLY
)
755 assert(args
->context
!= NULL
);
756 candidate
= nb_running_get_entry(args
->dnode
, NULL
, true);
757 srte_candidate_unset_bandwidth(candidate
);