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
20 #include <lib_errors.h>
22 #include "northbound.h"
25 #include "pathd/path_zebra.h"
26 #include "pathd/path_nb.h"
29 * XPath: /frr-pathd:pathd
31 void pathd_apply_finish(struct nb_cb_apply_finish_args
*args
)
37 * XPath: /frr-pathd:pathd/srte/segment-list
39 int pathd_srte_segment_list_create(struct nb_cb_create_args
*args
)
41 struct srte_segment_list
*segment_list
;
44 if (args
->event
!= NB_EV_APPLY
)
47 name
= yang_dnode_get_string(args
->dnode
, "./name");
48 segment_list
= srte_segment_list_add(name
);
49 nb_running_set_entry(args
->dnode
, segment_list
);
50 SET_FLAG(segment_list
->flags
, F_SEGMENT_LIST_NEW
);
55 int pathd_srte_segment_list_destroy(struct nb_cb_destroy_args
*args
)
57 struct srte_segment_list
*segment_list
;
59 if (args
->event
!= NB_EV_APPLY
)
62 segment_list
= nb_running_unset_entry(args
->dnode
);
63 SET_FLAG(segment_list
->flags
, F_SEGMENT_LIST_DELETED
);
69 * XPath: /frr-pathd:pathd/srte/segment-list/protocol-origin
71 int pathd_srte_segment_list_protocol_origin_modify(
72 struct nb_cb_modify_args
*args
)
74 struct srte_segment_list
*segment_list
;
76 if (args
->event
!= NB_EV_APPLY
)
79 segment_list
= nb_running_get_entry(args
->dnode
, NULL
, true);
80 segment_list
->protocol_origin
= yang_dnode_get_enum(args
->dnode
, NULL
);
81 SET_FLAG(segment_list
->flags
, F_SEGMENT_LIST_MODIFIED
);
87 * XPath: /frr-pathd:pathd/srte/segment-list/originator
89 int pathd_srte_segment_list_originator_modify(struct nb_cb_modify_args
*args
)
91 struct srte_segment_list
*segment_list
;
92 const char *originator
;
94 if (args
->event
!= NB_EV_APPLY
)
97 segment_list
= nb_running_get_entry(args
->dnode
, NULL
, true);
98 originator
= yang_dnode_get_string(args
->dnode
, NULL
);
99 strlcpy(segment_list
->originator
, originator
,
100 sizeof(segment_list
->originator
));
101 SET_FLAG(segment_list
->flags
, F_SEGMENT_LIST_MODIFIED
);
108 * XPath: /frr-pathd:pathd/srte/segment-list/segment
110 int pathd_srte_segment_list_segment_create(struct nb_cb_create_args
*args
)
112 struct srte_segment_list
*segment_list
;
113 struct srte_segment_entry
*segment
;
116 if (args
->event
!= NB_EV_APPLY
)
119 segment_list
= nb_running_get_entry(args
->dnode
, NULL
, true);
120 index
= yang_dnode_get_uint32(args
->dnode
, "./index");
121 segment
= srte_segment_entry_add(segment_list
, index
);
122 nb_running_set_entry(args
->dnode
, segment
);
123 SET_FLAG(segment_list
->flags
, F_SEGMENT_LIST_MODIFIED
);
128 int pathd_srte_segment_list_segment_destroy(struct nb_cb_destroy_args
*args
)
130 struct srte_segment_entry
*segment
;
132 if (args
->event
!= NB_EV_APPLY
)
135 segment
= nb_running_unset_entry(args
->dnode
);
136 SET_FLAG(segment
->segment_list
->flags
, F_SEGMENT_LIST_MODIFIED
);
138 srte_segment_entry_del(segment
);
144 * XPath: /frr-pathd:pathd/srte/segment-list/segment/sid-value
146 int pathd_srte_segment_list_segment_sid_value_modify(
147 struct nb_cb_modify_args
*args
)
149 mpls_label_t sid_value
;
150 struct srte_segment_entry
*segment
;
152 if (args
->event
!= NB_EV_APPLY
)
155 segment
= nb_running_get_entry(args
->dnode
, NULL
, true);
156 sid_value
= yang_dnode_get_uint32(args
->dnode
, NULL
);
157 segment
->sid_value
= sid_value
;
158 SET_FLAG(segment
->segment_list
->flags
, F_SEGMENT_LIST_MODIFIED
);
163 int pathd_srte_segment_list_segment_sid_value_destroy(
164 struct nb_cb_destroy_args
*args
)
166 struct srte_segment_entry
*segment
;
168 if (args
->event
!= NB_EV_APPLY
)
171 segment
= nb_running_get_entry(args
->dnode
, NULL
, true);
172 segment
->sid_value
= MPLS_LABEL_NONE
;
173 SET_FLAG(segment
->segment_list
->flags
, F_SEGMENT_LIST_MODIFIED
);
179 int pathd_srte_segment_list_segment_nai_destroy(struct nb_cb_destroy_args
*args
)
181 struct srte_segment_entry
*segment
;
183 if (args
->event
!= NB_EV_APPLY
)
186 segment
= nb_running_get_entry(args
->dnode
, NULL
, true);
187 segment
->nai_type
= SRTE_SEGMENT_NAI_TYPE_NONE
;
188 segment
->nai_local_addr
.ipa_type
= IPADDR_NONE
;
189 segment
->nai_local_iface
= 0;
190 segment
->nai_remote_addr
.ipa_type
= IPADDR_NONE
;
191 segment
->nai_remote_iface
= 0;
196 void pathd_srte_segment_list_segment_nai_apply_finish(
197 struct nb_cb_apply_finish_args
*args
)
199 struct srte_segment_entry
*segment
;
200 enum srte_segment_nai_type type
;
201 struct ipaddr local_addr
, remote_addr
;
202 uint32_t local_iface
= 0, remote_iface
= 0;
203 uint8_t algo
= 0, local_prefix_len
= 0;
204 const char *algo_buf
, *local_prefix_len_buf
;
206 segment
= nb_running_get_entry(args
->dnode
, NULL
, true);
207 type
= yang_dnode_get_enum(args
->dnode
, "./type");
209 yang_dnode_get_ip(&local_addr
, args
->dnode
, "./local-address");
212 case SRTE_SEGMENT_NAI_TYPE_IPV4_NODE
:
213 case SRTE_SEGMENT_NAI_TYPE_IPV6_NODE
:
215 case SRTE_SEGMENT_NAI_TYPE_IPV4_ADJACENCY
:
216 case SRTE_SEGMENT_NAI_TYPE_IPV6_ADJACENCY
:
217 yang_dnode_get_ip(&remote_addr
, args
->dnode
,
220 case SRTE_SEGMENT_NAI_TYPE_IPV4_UNNUMBERED_ADJACENCY
:
221 yang_dnode_get_ip(&remote_addr
, args
->dnode
,
224 yang_dnode_get_uint32(args
->dnode
, "./local-interface");
225 remote_iface
= yang_dnode_get_uint32(args
->dnode
,
226 "./remote-interface");
228 case SRTE_SEGMENT_NAI_TYPE_IPV4_ALGORITHM
:
229 algo_buf
= yang_dnode_get_string(args
->dnode
, "./algorithm");
230 algo
= atoi(algo_buf
);
231 local_prefix_len_buf
= yang_dnode_get_string(
232 args
->dnode
, "./local-prefix-len");
233 local_prefix_len
= atoi(local_prefix_len_buf
);
235 case SRTE_SEGMENT_NAI_TYPE_IPV4_LOCAL_IFACE
:
237 yang_dnode_get_uint32(args
->dnode
, "./local-interface");
238 local_prefix_len_buf
= yang_dnode_get_string(
239 args
->dnode
, "./local-prefix-len");
240 local_prefix_len
= atoi(local_prefix_len_buf
);
246 zlog_debug(" Segment list name (%d) index (%s) ", segment
->index
,
247 segment
->segment_list
->name
);
248 if (srte_segment_entry_set_nai(segment
, type
, &local_addr
, local_iface
,
249 &remote_addr
, remote_iface
, algo
,
251 SET_FLAG(segment
->segment_list
->flags
,
252 F_SEGMENT_LIST_SID_CONFLICT
);
256 * XPath: /frr-pathd:pathd/srte/policy
258 int pathd_srte_policy_create(struct nb_cb_create_args
*args
)
260 struct srte_policy
*policy
;
262 struct ipaddr endpoint
;
264 if (args
->event
!= NB_EV_APPLY
)
267 color
= yang_dnode_get_uint32(args
->dnode
, "./color");
268 yang_dnode_get_ip(&endpoint
, args
->dnode
, "./endpoint");
269 policy
= srte_policy_add(color
, &endpoint
);
271 nb_running_set_entry(args
->dnode
, policy
);
272 SET_FLAG(policy
->flags
, F_POLICY_NEW
);
277 int pathd_srte_policy_destroy(struct nb_cb_destroy_args
*args
)
279 struct srte_policy
*policy
;
281 if (args
->event
!= NB_EV_APPLY
)
284 policy
= nb_running_unset_entry(args
->dnode
);
285 SET_FLAG(policy
->flags
, F_POLICY_DELETED
);
291 * XPath: /frr-pathd:pathd/srte/policy/name
293 int pathd_srte_policy_name_modify(struct nb_cb_modify_args
*args
)
295 struct srte_policy
*policy
;
298 if (args
->event
!= NB_EV_APPLY
&& args
->event
!= NB_EV_VALIDATE
)
301 policy
= nb_running_get_entry(args
->dnode
, NULL
, true);
303 if (args
->event
== NB_EV_VALIDATE
) {
304 /* the policy name is fixed after setting it once */
305 if (strlen(policy
->name
) > 0) {
306 flog_warn(EC_LIB_NB_CB_CONFIG_VALIDATE
,
307 "The SR Policy name is fixed!");
308 return NB_ERR_RESOURCE
;
313 name
= yang_dnode_get_string(args
->dnode
, NULL
);
314 strlcpy(policy
->name
, name
, sizeof(policy
->name
));
315 SET_FLAG(policy
->flags
, F_POLICY_MODIFIED
);
320 int pathd_srte_policy_name_destroy(struct nb_cb_destroy_args
*args
)
322 struct srte_policy
*policy
;
324 if (args
->event
!= NB_EV_APPLY
)
327 policy
= nb_running_get_entry(args
->dnode
, NULL
, true);
328 policy
->name
[0] = '\0';
329 SET_FLAG(policy
->flags
, F_POLICY_MODIFIED
);
335 * XPath: /frr-pathd:pathd/srte/policy/binding-sid
337 int pathd_srte_policy_binding_sid_modify(struct nb_cb_modify_args
*args
)
339 struct srte_policy
*policy
;
340 mpls_label_t binding_sid
;
342 binding_sid
= yang_dnode_get_uint32(args
->dnode
, NULL
);
344 switch (args
->event
) {
348 if (path_zebra_request_label(binding_sid
) < 0)
349 return NB_ERR_RESOURCE
;
354 policy
= nb_running_get_entry(args
->dnode
, NULL
, true);
355 srte_policy_update_binding_sid(policy
, binding_sid
);
356 SET_FLAG(policy
->flags
, F_POLICY_MODIFIED
);
363 int pathd_srte_policy_binding_sid_destroy(struct nb_cb_destroy_args
*args
)
365 struct srte_policy
*policy
;
367 if (args
->event
!= NB_EV_APPLY
)
370 policy
= nb_running_get_entry(args
->dnode
, NULL
, true);
371 srte_policy_update_binding_sid(policy
, MPLS_LABEL_NONE
);
372 SET_FLAG(policy
->flags
, F_POLICY_MODIFIED
);
378 * XPath: /frr-pathd:pathd/srte/policy/candidate-path
380 int pathd_srte_policy_candidate_path_create(struct nb_cb_create_args
*args
)
382 struct srte_policy
*policy
;
383 struct srte_candidate
*candidate
;
386 if (args
->event
!= NB_EV_APPLY
)
389 policy
= nb_running_get_entry(args
->dnode
, NULL
, true);
390 preference
= yang_dnode_get_uint32(args
->dnode
, "./preference");
391 candidate
= srte_candidate_add(policy
, preference
);
392 nb_running_set_entry(args
->dnode
, candidate
);
393 SET_FLAG(candidate
->flags
, F_CANDIDATE_NEW
);
398 int pathd_srte_policy_candidate_path_destroy(struct nb_cb_destroy_args
*args
)
400 struct srte_candidate
*candidate
;
402 if (args
->event
!= NB_EV_APPLY
)
405 candidate
= nb_running_unset_entry(args
->dnode
);
406 SET_FLAG(candidate
->flags
, F_CANDIDATE_DELETED
);
412 * XPath: /frr-pathd:pathd/srte/policy/candidate-path/name
414 int pathd_srte_policy_candidate_path_name_modify(struct nb_cb_modify_args
*args
)
416 struct srte_candidate
*candidate
;
418 char xpath
[XPATH_MAXLEN
];
419 char xpath_buf
[XPATH_MAXLEN
- 3];
421 if (args
->event
!= NB_EV_APPLY
&& args
->event
!= NB_EV_VALIDATE
)
424 /* the candidate name is fixed after setting it once, this is checked
426 if (args
->event
== NB_EV_VALIDATE
) {
427 /* first get the precise path to the candidate path */
428 yang_dnode_get_path(args
->dnode
, xpath_buf
, sizeof(xpath_buf
));
429 snprintf(xpath
, sizeof(xpath
), "%s%s", xpath_buf
, "/..");
431 candidate
= nb_running_get_entry_non_rec(NULL
, xpath
, false);
433 /* then check if it exists and if the name was provided */
434 if (candidate
&& strlen(candidate
->name
) > 0) {
435 flog_warn(EC_LIB_NB_CB_CONFIG_VALIDATE
,
436 "The candidate name is fixed!");
437 return NB_ERR_RESOURCE
;
442 candidate
= nb_running_get_entry(args
->dnode
, NULL
, true);
444 name
= yang_dnode_get_string(args
->dnode
, NULL
);
445 strlcpy(candidate
->name
, name
, sizeof(candidate
->name
));
446 SET_FLAG(candidate
->flags
, F_CANDIDATE_MODIFIED
);
452 static int affinity_filter_modify(struct nb_cb_modify_args
*args
,
453 enum affinity_filter_type type
)
456 struct srte_candidate
*candidate
;
458 if (args
->event
!= NB_EV_APPLY
)
461 assert(args
->context
!= NULL
);
462 candidate
= nb_running_get_entry(args
->dnode
, NULL
, true);
463 filter
= yang_dnode_get_uint32(args
->dnode
, NULL
);
464 srte_candidate_set_affinity_filter(candidate
, type
, filter
);
469 static int affinity_filter_destroy(struct nb_cb_destroy_args
*args
,
470 enum affinity_filter_type type
)
472 struct srte_candidate
*candidate
;
474 if (args
->event
!= NB_EV_APPLY
)
477 assert(args
->context
!= NULL
);
478 candidate
= nb_running_get_entry(args
->dnode
, NULL
, true);
479 srte_candidate_unset_affinity_filter(candidate
, type
);
486 * /frr-pathd:pathd/srte/policy/candidate-path/constraints/affinity/exclude-any
489 int pathd_srte_policy_candidate_path_exclude_any_modify(
490 struct nb_cb_modify_args
*args
)
492 return affinity_filter_modify(args
, AFFINITY_FILTER_EXCLUDE_ANY
);
495 int pathd_srte_policy_candidate_path_exclude_any_destroy(
496 struct nb_cb_destroy_args
*args
)
498 return affinity_filter_destroy(args
, AFFINITY_FILTER_EXCLUDE_ANY
);
504 * /frr-pathd:pathd/srte/policy/candidate-path/constraints/affinity/include-any
506 int pathd_srte_policy_candidate_path_include_any_modify(
507 struct nb_cb_modify_args
*args
)
509 return affinity_filter_modify(args
, AFFINITY_FILTER_INCLUDE_ANY
);
512 int pathd_srte_policy_candidate_path_include_any_destroy(
513 struct nb_cb_destroy_args
*args
)
515 return affinity_filter_destroy(args
, AFFINITY_FILTER_INCLUDE_ANY
);
521 * /frr-pathd:pathd/srte/policy/candidate-path/constraints/affinity/include-all
523 int pathd_srte_policy_candidate_path_include_all_modify(
524 struct nb_cb_modify_args
*args
)
526 return affinity_filter_modify(args
, AFFINITY_FILTER_INCLUDE_ALL
);
529 int pathd_srte_policy_candidate_path_include_all_destroy(
530 struct nb_cb_destroy_args
*args
)
532 return affinity_filter_destroy(args
, AFFINITY_FILTER_INCLUDE_ALL
);
537 * XPath: /frr-pathd:pathd/srte/policy/candidate-path/constraints/metrics
539 int pathd_srte_policy_candidate_path_metrics_destroy(
540 struct nb_cb_destroy_args
*args
)
542 struct srte_candidate
*candidate
;
543 enum srte_candidate_metric_type type
;
545 if (args
->event
!= NB_EV_APPLY
)
548 assert(args
->context
!= NULL
);
549 candidate
= nb_running_get_entry(args
->dnode
, NULL
, true);
551 type
= yang_dnode_get_enum(args
->dnode
, "./type");
552 srte_candidate_unset_metric(candidate
, type
);
557 void pathd_srte_policy_candidate_path_metrics_apply_finish(
558 struct nb_cb_apply_finish_args
*args
)
560 struct srte_candidate
*candidate
;
561 enum srte_candidate_metric_type type
;
563 bool required
, is_bound
= false, is_computed
= false;
565 assert(args
->context
!= NULL
);
567 candidate
= nb_running_get_entry(args
->dnode
, NULL
, true);
569 type
= yang_dnode_get_enum(args
->dnode
, "./type");
570 value
= (float)yang_dnode_get_dec64(args
->dnode
, "./value");
571 required
= yang_dnode_get_bool(args
->dnode
, "./required");
572 if (yang_dnode_exists(args
->dnode
, "./is-bound"))
573 is_bound
= yang_dnode_get_bool(args
->dnode
, "./is-bound");
574 if (yang_dnode_exists(args
->dnode
, "./is-computed"))
575 is_computed
= yang_dnode_get_bool(args
->dnode
, "./is-computed");
577 srte_candidate_set_metric(candidate
, type
, value
, required
, is_bound
,
583 * /frr-pathd:pathd/srte/policy/candidate-path/constraints/objective-function
585 int pathd_srte_policy_candidate_path_objfun_destroy(
586 struct nb_cb_destroy_args
*args
)
588 struct srte_candidate
*candidate
;
590 if (args
->event
!= NB_EV_APPLY
)
593 assert(args
->context
!= NULL
);
595 candidate
= nb_running_get_entry(args
->dnode
, NULL
, true);
596 srte_candidate_unset_objfun(candidate
);
601 void pathd_srte_policy_candidate_path_objfun_apply_finish(
602 struct nb_cb_apply_finish_args
*args
)
604 struct srte_candidate
*candidate
;
605 enum objfun_type type
;
608 candidate
= nb_running_get_entry(args
->dnode
, NULL
, true);
609 required
= yang_dnode_get_bool(args
->dnode
, "./required");
610 type
= yang_dnode_get_enum(args
->dnode
, "./type");
611 srte_candidate_set_objfun(candidate
, required
, type
);
615 * XPath: /frr-pathd:pathd/srte/policy/candidate-path/protocol-origin
617 int pathd_srte_policy_candidate_path_protocol_origin_modify(
618 struct nb_cb_modify_args
*args
)
620 struct srte_candidate
*candidate
;
621 enum srte_protocol_origin protocol_origin
;
623 if (args
->event
!= NB_EV_APPLY
)
626 candidate
= nb_running_get_entry(args
->dnode
, NULL
, true);
627 protocol_origin
= yang_dnode_get_enum(args
->dnode
, NULL
);
628 candidate
->protocol_origin
= protocol_origin
;
629 candidate
->lsp
->protocol_origin
= protocol_origin
;
630 SET_FLAG(candidate
->flags
, F_CANDIDATE_MODIFIED
);
636 * XPath: /frr-pathd:pathd/srte/policy/candidate-path/originator
638 int pathd_srte_policy_candidate_path_originator_modify(
639 struct nb_cb_modify_args
*args
)
641 struct srte_candidate
*candidate
;
642 const char *originator
;
644 if (args
->event
!= NB_EV_APPLY
)
647 candidate
= nb_running_get_entry(args
->dnode
, NULL
, true);
648 originator
= yang_dnode_get_string(args
->dnode
, NULL
);
649 strlcpy(candidate
->originator
, originator
,
650 sizeof(candidate
->originator
));
651 strlcpy(candidate
->lsp
->originator
, originator
,
652 sizeof(candidate
->lsp
->originator
));
653 SET_FLAG(candidate
->flags
, F_CANDIDATE_MODIFIED
);
659 * XPath: /frr-pathd:pathd/srte/policy/candidate-path/type
661 int pathd_srte_policy_candidate_path_type_modify(struct nb_cb_modify_args
*args
)
663 struct srte_candidate
*candidate
;
664 enum srte_candidate_type type
;
665 char xpath
[XPATH_MAXLEN
];
666 char xpath_buf
[XPATH_MAXLEN
- 3];
668 if (args
->event
!= NB_EV_APPLY
&& args
->event
!= NB_EV_VALIDATE
)
671 /* the candidate type is fixed after setting it once, this is checked
673 if (args
->event
== NB_EV_VALIDATE
) {
674 /* first get the precise path to the candidate path */
675 yang_dnode_get_path(args
->dnode
, xpath_buf
, sizeof(xpath_buf
));
676 snprintf(xpath
, sizeof(xpath
), "%s%s", xpath_buf
, "/..");
678 candidate
= nb_running_get_entry_non_rec(NULL
, xpath
, false);
680 /* then check if it exists and if the type was provided */
682 && candidate
->type
!= SRTE_CANDIDATE_TYPE_UNDEFINED
) {
683 flog_warn(EC_LIB_NB_CB_CONFIG_VALIDATE
,
684 "The candidate type is fixed!");
685 return NB_ERR_RESOURCE
;
690 candidate
= nb_running_get_entry(args
->dnode
, NULL
, true);
692 type
= yang_dnode_get_enum(args
->dnode
, NULL
);
693 candidate
->type
= type
;
694 SET_FLAG(candidate
->flags
, F_CANDIDATE_MODIFIED
);
700 * XPath: /frr-pathd:pathd/srte/policy/candidate-path/segment-list-name
702 int pathd_srte_policy_candidate_path_segment_list_name_modify(
703 struct nb_cb_modify_args
*args
)
705 struct srte_candidate
*candidate
;
706 const char *segment_list_name
;
708 if (args
->event
!= NB_EV_APPLY
)
711 candidate
= nb_running_get_entry(args
->dnode
, NULL
, true);
712 segment_list_name
= yang_dnode_get_string(args
->dnode
, NULL
);
714 candidate
->segment_list
= srte_segment_list_find(segment_list_name
);
715 candidate
->lsp
->segment_list
= candidate
->segment_list
;
716 assert(candidate
->segment_list
);
717 SET_FLAG(candidate
->flags
, F_CANDIDATE_MODIFIED
);
722 int pathd_srte_policy_candidate_path_segment_list_name_destroy(
723 struct nb_cb_destroy_args
*args
)
725 struct srte_candidate
*candidate
;
727 if (args
->event
!= NB_EV_APPLY
)
730 candidate
= nb_running_get_entry(args
->dnode
, NULL
, true);
731 candidate
->segment_list
= NULL
;
732 candidate
->lsp
->segment_list
= NULL
;
733 SET_FLAG(candidate
->flags
, F_CANDIDATE_MODIFIED
);
739 * XPath: /frr-pathd:pathd/srte/policy/candidate-path/constraints/bandwidth
741 void pathd_srte_policy_candidate_path_bandwidth_apply_finish(
742 struct nb_cb_apply_finish_args
*args
)
744 struct srte_candidate
*candidate
;
748 assert(args
->context
!= NULL
);
750 candidate
= nb_running_get_entry(args
->dnode
, NULL
, true);
751 value
= (float)yang_dnode_get_dec64(args
->dnode
, "./value");
752 required
= yang_dnode_get_bool(args
->dnode
, "./required");
753 srte_candidate_set_bandwidth(candidate
, value
, required
);
756 int pathd_srte_policy_candidate_path_bandwidth_destroy(
757 struct nb_cb_destroy_args
*args
)
759 struct srte_candidate
*candidate
;
761 if (args
->event
!= NB_EV_APPLY
)
764 assert(args
->context
!= NULL
);
765 candidate
= nb_running_get_entry(args
->dnode
, NULL
, true);
766 srte_candidate_unset_bandwidth(candidate
);