]> git.proxmox.com Git - mirror_frr.git/blame_incremental - isisd/isis_nb_config.c
Merge pull request #7833 from donaldsharp/gr_tests
[mirror_frr.git] / isisd / isis_nb_config.c
... / ...
CommitLineData
1/*
2 * Copyright (C) 2001,2002 Sampo Saaristo
3 * Tampere University of Technology
4 * Institute of Communications Engineering
5 * Copyright (C) 2018 Volta Networks
6 * Emanuele Di Pascale
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the Free
10 * Software Foundation; either version 2 of the License, or (at your option)
11 * any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 * more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; see the file COPYING; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23#include <zebra.h>
24
25#include "printfrr.h"
26#include "northbound.h"
27#include "linklist.h"
28#include "log.h"
29#include "bfd.h"
30#include "filter.h"
31#include "spf_backoff.h"
32#include "lib_errors.h"
33#include "vrf.h"
34#include "zclient.h"
35#include "ldp_sync.h"
36
37#include "isisd/isisd.h"
38#include "isisd/isis_nb.h"
39#include "isisd/isis_common.h"
40#include "isisd/isis_bfd.h"
41#include "isisd/isis_circuit.h"
42#include "isisd/isis_lsp.h"
43#include "isisd/isis_dynhn.h"
44#include "isisd/isis_misc.h"
45#include "isisd/isis_csm.h"
46#include "isisd/isis_adjacency.h"
47#include "isisd/isis_spf.h"
48#include "isisd/isis_spf_private.h"
49#include "isisd/isis_te.h"
50#include "isisd/isis_memory.h"
51#include "isisd/isis_mt.h"
52#include "isisd/isis_redist.h"
53#include "isisd/isis_ldp_sync.h"
54
55extern struct zclient *zclient;
56
57/*
58 * XPath: /frr-isisd:isis/instance
59 */
60int isis_instance_create(struct nb_cb_create_args *args)
61{
62 struct isis_area *area;
63 const char *area_tag;
64 const char *vrf_name;
65
66 if (args->event != NB_EV_APPLY)
67 return NB_OK;
68 vrf_name = yang_dnode_get_string(args->dnode, "./vrf");
69 area_tag = yang_dnode_get_string(args->dnode, "./area-tag");
70 isis_global_instance_create(vrf_name);
71 area = isis_area_lookup_by_vrf(area_tag, vrf_name);
72 if (area)
73 return NB_ERR_INCONSISTENCY;
74
75 area = isis_area_create(area_tag, vrf_name);
76
77 /* save area in dnode to avoid looking it up all the time */
78 nb_running_set_entry(args->dnode, area);
79
80 return NB_OK;
81}
82
83int isis_instance_destroy(struct nb_cb_destroy_args *args)
84{
85 struct isis_area *area;
86 vrf_id_t vrf_id;
87
88 if (args->event != NB_EV_APPLY)
89 return NB_OK;
90 area = nb_running_unset_entry(args->dnode);
91 vrf_id = area->isis->vrf_id;
92
93 /* remove ldp-sync config */
94 if (vrf_id == VRF_DEFAULT)
95 isis_ldp_sync_gbl_exit(true);
96
97 isis_area_destroy(area);
98 return NB_OK;
99}
100
101/*
102 * XPath: /frr-isisd:isis/instance/is-type
103 */
104int isis_instance_is_type_modify(struct nb_cb_modify_args *args)
105{
106 struct isis_area *area;
107 int type;
108
109 if (args->event != NB_EV_APPLY)
110 return NB_OK;
111
112 area = nb_running_get_entry(args->dnode, NULL, true);
113 type = yang_dnode_get_enum(args->dnode, NULL);
114 isis_area_is_type_set(area, type);
115
116 return NB_OK;
117}
118
119/*
120 * XPath: /frr-isisd:isis/instance/area-address
121 */
122int isis_instance_area_address_create(struct nb_cb_create_args *args)
123{
124 struct isis_area *area;
125 struct area_addr addr, *addrr = NULL, *addrp = NULL;
126 struct listnode *node;
127 uint8_t buff[255];
128 const char *net_title = yang_dnode_get_string(args->dnode, NULL);
129
130 switch (args->event) {
131 case NB_EV_VALIDATE:
132 area = nb_running_get_entry(args->dnode, NULL, true);
133 if (area == NULL)
134 return NB_ERR_VALIDATION;
135 addr.addr_len = dotformat2buff(buff, net_title);
136 memcpy(addr.area_addr, buff, addr.addr_len);
137 if (addr.area_addr[addr.addr_len - 1] != 0) {
138 snprintf(
139 args->errmsg, args->errmsg_len,
140 "nsel byte (last byte) in area address must be 0");
141 return NB_ERR_VALIDATION;
142 }
143 if (area->isis->sysid_set) {
144 /* Check that the SystemID portions match */
145 if (memcmp(area->isis->sysid, GETSYSID((&addr)),
146 ISIS_SYS_ID_LEN)) {
147 snprintf(
148 args->errmsg, args->errmsg_len,
149 "System ID must not change when defining additional area addresses");
150 return NB_ERR_VALIDATION;
151 }
152 }
153 break;
154 case NB_EV_PREPARE:
155 addrr = XMALLOC(MTYPE_ISIS_AREA_ADDR, sizeof(struct area_addr));
156 addrr->addr_len = dotformat2buff(buff, net_title);
157 memcpy(addrr->area_addr, buff, addrr->addr_len);
158 args->resource->ptr = addrr;
159 break;
160 case NB_EV_ABORT:
161 XFREE(MTYPE_ISIS_AREA_ADDR, args->resource->ptr);
162 break;
163 case NB_EV_APPLY:
164 area = nb_running_get_entry(args->dnode, NULL, true);
165 addrr = args->resource->ptr;
166 assert(area);
167
168 if (area->isis->sysid_set == 0) {
169 /*
170 * First area address - get the SystemID for this router
171 */
172 memcpy(area->isis->sysid, GETSYSID(addrr),
173 ISIS_SYS_ID_LEN);
174 area->isis->sysid_set = 1;
175 } else {
176 /* check that we don't already have this address */
177 for (ALL_LIST_ELEMENTS_RO(area->area_addrs, node,
178 addrp)) {
179 if ((addrp->addr_len + ISIS_SYS_ID_LEN
180 + ISIS_NSEL_LEN)
181 != (addrr->addr_len))
182 continue;
183 if (!memcmp(addrp->area_addr, addrr->area_addr,
184 addrr->addr_len)) {
185 XFREE(MTYPE_ISIS_AREA_ADDR, addrr);
186 return NB_OK; /* silent fail */
187 }
188 }
189 }
190
191 /*Forget the systemID part of the address */
192 addrr->addr_len -= (ISIS_SYS_ID_LEN + ISIS_NSEL_LEN);
193 assert(area->area_addrs); /* to silence scan-build sillyness */
194 listnode_add(area->area_addrs, addrr);
195
196 /* only now we can safely generate our LSPs for this area */
197 if (listcount(area->area_addrs) > 0) {
198 if (area->is_type & IS_LEVEL_1)
199 lsp_generate(area, IS_LEVEL_1);
200 if (area->is_type & IS_LEVEL_2)
201 lsp_generate(area, IS_LEVEL_2);
202 }
203 break;
204 }
205
206 return NB_OK;
207}
208
209int isis_instance_area_address_destroy(struct nb_cb_destroy_args *args)
210{
211 struct area_addr addr, *addrp = NULL;
212 struct listnode *node;
213 uint8_t buff[255];
214 struct isis_area *area;
215 const char *net_title;
216
217 if (args->event != NB_EV_APPLY)
218 return NB_OK;
219
220 net_title = yang_dnode_get_string(args->dnode, NULL);
221 addr.addr_len = dotformat2buff(buff, net_title);
222 memcpy(addr.area_addr, buff, (int)addr.addr_len);
223 area = nb_running_get_entry(args->dnode, NULL, true);
224
225 for (ALL_LIST_ELEMENTS_RO(area->area_addrs, node, addrp)) {
226 if ((addrp->addr_len + ISIS_SYS_ID_LEN + 1) == addr.addr_len
227 && !memcmp(addrp->area_addr, addr.area_addr, addr.addr_len))
228 break;
229 }
230 if (!addrp)
231 return NB_ERR_INCONSISTENCY;
232
233 listnode_delete(area->area_addrs, addrp);
234 XFREE(MTYPE_ISIS_AREA_ADDR, addrp);
235 /*
236 * Last area address - reset the SystemID for this router
237 */
238 if (listcount(area->area_addrs) == 0) {
239 memset(area->isis->sysid, 0, ISIS_SYS_ID_LEN);
240 area->isis->sysid_set = 0;
241 if (IS_DEBUG_EVENTS)
242 zlog_debug("Router has no SystemID");
243 }
244
245 return NB_OK;
246}
247
248/*
249 * XPath: /frr-isisd:isis/instance/dynamic-hostname
250 */
251int isis_instance_dynamic_hostname_modify(struct nb_cb_modify_args *args)
252{
253 struct isis_area *area;
254
255 if (args->event != NB_EV_APPLY)
256 return NB_OK;
257
258 area = nb_running_get_entry(args->dnode, NULL, true);
259 isis_area_dynhostname_set(area, yang_dnode_get_bool(args->dnode, NULL));
260
261 return NB_OK;
262}
263
264/*
265 * XPath: /frr-isisd:isis/instance/attached
266 */
267int isis_instance_attached_modify(struct nb_cb_modify_args *args)
268{
269 struct isis_area *area;
270 bool attached;
271
272 if (args->event != NB_EV_APPLY)
273 return NB_OK;
274
275 area = nb_running_get_entry(args->dnode, NULL, true);
276 attached = yang_dnode_get_bool(args->dnode, NULL);
277 isis_area_attached_bit_set(area, attached);
278
279 return NB_OK;
280}
281
282/*
283 * XPath: /frr-isisd:isis/instance/overload
284 */
285int isis_instance_overload_modify(struct nb_cb_modify_args *args)
286{
287 struct isis_area *area;
288 bool overload;
289
290 if (args->event != NB_EV_APPLY)
291 return NB_OK;
292
293 area = nb_running_get_entry(args->dnode, NULL, true);
294 overload = yang_dnode_get_bool(args->dnode, NULL);
295 isis_area_overload_bit_set(area, overload);
296
297 return NB_OK;
298}
299
300/*
301 * XPath: /frr-isisd:isis/instance/metric-style
302 */
303int isis_instance_metric_style_modify(struct nb_cb_modify_args *args)
304{
305 struct isis_area *area;
306 bool old_metric, new_metric;
307 enum isis_metric_style metric_style =
308 yang_dnode_get_enum(args->dnode, NULL);
309
310 if (args->event != NB_EV_APPLY)
311 return NB_OK;
312
313 area = nb_running_get_entry(args->dnode, NULL, true);
314 old_metric = (metric_style == ISIS_WIDE_METRIC) ? false : true;
315 new_metric = (metric_style == ISIS_NARROW_METRIC) ? false : true;
316 isis_area_metricstyle_set(area, old_metric, new_metric);
317
318 return NB_OK;
319}
320
321/*
322 * XPath: /frr-isisd:isis/instance/purge-originator
323 */
324int isis_instance_purge_originator_modify(struct nb_cb_modify_args *args)
325{
326 struct isis_area *area;
327
328 if (args->event != NB_EV_APPLY)
329 return NB_OK;
330
331 area = nb_running_get_entry(args->dnode, NULL, true);
332 area->purge_originator = yang_dnode_get_bool(args->dnode, NULL);
333
334 return NB_OK;
335}
336
337/*
338 * XPath: /frr-isisd:isis/instance/lsp/mtu
339 */
340int isis_instance_lsp_mtu_modify(struct nb_cb_modify_args *args)
341{
342 struct listnode *node;
343 struct isis_circuit *circuit;
344 uint16_t lsp_mtu = yang_dnode_get_uint16(args->dnode, NULL);
345 struct isis_area *area;
346
347 switch (args->event) {
348 case NB_EV_VALIDATE:
349 area = nb_running_get_entry(args->dnode, NULL, false);
350 if (!area)
351 break;
352 for (ALL_LIST_ELEMENTS_RO(area->circuit_list, node, circuit)) {
353 if (circuit->state != C_STATE_INIT
354 && circuit->state != C_STATE_UP)
355 continue;
356 if (lsp_mtu > isis_circuit_pdu_size(circuit)) {
357 snprintf(
358 args->errmsg, args->errmsg_len,
359 "ISIS area contains circuit %s, which has a maximum PDU size of %zu",
360 circuit->interface->name,
361 isis_circuit_pdu_size(circuit));
362 return NB_ERR_VALIDATION;
363 }
364 }
365 break;
366 case NB_EV_PREPARE:
367 case NB_EV_ABORT:
368 break;
369 case NB_EV_APPLY:
370 area = nb_running_get_entry(args->dnode, NULL, true);
371 isis_area_lsp_mtu_set(area, lsp_mtu);
372 break;
373 }
374
375 return NB_OK;
376}
377
378/*
379 * XPath: /frr-isisd:isis/instance/lsp/timers/level-1/refresh-interval
380 */
381int isis_instance_lsp_refresh_interval_level_1_modify(
382 struct nb_cb_modify_args *args)
383{
384 struct isis_area *area;
385 uint16_t refr_int;
386
387 if (args->event != NB_EV_APPLY)
388 return NB_OK;
389
390 refr_int = yang_dnode_get_uint16(args->dnode, NULL);
391 area = nb_running_get_entry(args->dnode, NULL, true);
392 isis_area_lsp_refresh_set(area, IS_LEVEL_1, refr_int);
393
394 return NB_OK;
395}
396
397/*
398 * XPath: /frr-isisd:isis/instance/lsp/timers/level-2/refresh-interval
399 */
400int isis_instance_lsp_refresh_interval_level_2_modify(
401 struct nb_cb_modify_args *args)
402{
403 struct isis_area *area;
404 uint16_t refr_int;
405
406 if (args->event != NB_EV_APPLY)
407 return NB_OK;
408
409 refr_int = yang_dnode_get_uint16(args->dnode, NULL);
410 area = nb_running_get_entry(args->dnode, NULL, true);
411 isis_area_lsp_refresh_set(area, IS_LEVEL_2, refr_int);
412
413 return NB_OK;
414}
415
416/*
417 * XPath: /frr-isisd:isis/instance/lsp/timers/level-1/maximum-lifetime
418 */
419int isis_instance_lsp_maximum_lifetime_level_1_modify(
420 struct nb_cb_modify_args *args)
421{
422 struct isis_area *area;
423 uint16_t max_lt;
424
425 if (args->event != NB_EV_APPLY)
426 return NB_OK;
427
428 max_lt = yang_dnode_get_uint16(args->dnode, NULL);
429 area = nb_running_get_entry(args->dnode, NULL, true);
430 isis_area_max_lsp_lifetime_set(area, IS_LEVEL_1, max_lt);
431
432 return NB_OK;
433}
434
435/*
436 * XPath: /frr-isisd:isis/instance/lsp/timers/level-2/maximum-lifetime
437 */
438int isis_instance_lsp_maximum_lifetime_level_2_modify(
439 struct nb_cb_modify_args *args)
440{
441 struct isis_area *area;
442 uint16_t max_lt;
443
444 if (args->event != NB_EV_APPLY)
445 return NB_OK;
446
447 max_lt = yang_dnode_get_uint16(args->dnode, NULL);
448 area = nb_running_get_entry(args->dnode, NULL, true);
449 isis_area_max_lsp_lifetime_set(area, IS_LEVEL_2, max_lt);
450
451 return NB_OK;
452}
453
454/*
455 * XPath: /frr-isisd:isis/instance/lsp/timers/level-1/generation-interval
456 */
457int isis_instance_lsp_generation_interval_level_1_modify(
458 struct nb_cb_modify_args *args)
459{
460 struct isis_area *area;
461 uint16_t gen_int;
462
463 if (args->event != NB_EV_APPLY)
464 return NB_OK;
465
466 gen_int = yang_dnode_get_uint16(args->dnode, NULL);
467 area = nb_running_get_entry(args->dnode, NULL, true);
468 area->lsp_gen_interval[0] = gen_int;
469
470 return NB_OK;
471}
472
473/*
474 * XPath: /frr-isisd:isis/instance/lsp/timers/level-2/generation-interval
475 */
476int isis_instance_lsp_generation_interval_level_2_modify(
477 struct nb_cb_modify_args *args)
478{
479 struct isis_area *area;
480 uint16_t gen_int;
481
482 if (args->event != NB_EV_APPLY)
483 return NB_OK;
484
485 gen_int = yang_dnode_get_uint16(args->dnode, NULL);
486 area = nb_running_get_entry(args->dnode, NULL, true);
487 area->lsp_gen_interval[1] = gen_int;
488
489 return NB_OK;
490}
491
492/*
493 * XPath: /frr-isisd:isis/instance/spf/ietf-backoff-delay
494 */
495void ietf_backoff_delay_apply_finish(struct nb_cb_apply_finish_args *args)
496{
497 long init_delay = yang_dnode_get_uint16(args->dnode, "./init-delay");
498 long short_delay = yang_dnode_get_uint16(args->dnode, "./short-delay");
499 long long_delay = yang_dnode_get_uint16(args->dnode, "./long-delay");
500 long holddown = yang_dnode_get_uint16(args->dnode, "./hold-down");
501 long timetolearn =
502 yang_dnode_get_uint16(args->dnode, "./time-to-learn");
503 struct isis_area *area = nb_running_get_entry(args->dnode, NULL, true);
504 size_t bufsiz = strlen(area->area_tag) + sizeof("IS-IS Lx");
505 char *buf = XCALLOC(MTYPE_TMP, bufsiz);
506
507 snprintf(buf, bufsiz, "IS-IS %s L1", area->area_tag);
508 spf_backoff_free(area->spf_delay_ietf[0]);
509 area->spf_delay_ietf[0] =
510 spf_backoff_new(master, buf, init_delay, short_delay,
511 long_delay, holddown, timetolearn);
512
513 snprintf(buf, bufsiz, "IS-IS %s L2", area->area_tag);
514 spf_backoff_free(area->spf_delay_ietf[1]);
515 area->spf_delay_ietf[1] =
516 spf_backoff_new(master, buf, init_delay, short_delay,
517 long_delay, holddown, timetolearn);
518
519 XFREE(MTYPE_TMP, buf);
520}
521
522int isis_instance_spf_ietf_backoff_delay_create(struct nb_cb_create_args *args)
523{
524 /* All the work is done in the apply_finish */
525 return NB_OK;
526}
527
528int isis_instance_spf_ietf_backoff_delay_destroy(
529 struct nb_cb_destroy_args *args)
530{
531 struct isis_area *area;
532
533 if (args->event != NB_EV_APPLY)
534 return NB_OK;
535
536 area = nb_running_get_entry(args->dnode, NULL, true);
537 spf_backoff_free(area->spf_delay_ietf[0]);
538 spf_backoff_free(area->spf_delay_ietf[1]);
539 area->spf_delay_ietf[0] = NULL;
540 area->spf_delay_ietf[1] = NULL;
541
542 return NB_OK;
543}
544
545/*
546 * XPath: /frr-isisd:isis/instance/spf/ietf-backoff-delay/init-delay
547 */
548int isis_instance_spf_ietf_backoff_delay_init_delay_modify(
549 struct nb_cb_modify_args *args)
550{
551 /* All the work is done in the apply_finish */
552 return NB_OK;
553}
554
555/*
556 * XPath: /frr-isisd:isis/instance/spf/ietf-backoff-delay/short-delay
557 */
558int isis_instance_spf_ietf_backoff_delay_short_delay_modify(
559 struct nb_cb_modify_args *args)
560{
561 /* All the work is done in the apply_finish */
562 return NB_OK;
563}
564
565/*
566 * XPath: /frr-isisd:isis/instance/spf/ietf-backoff-delay/long-delay
567 */
568int isis_instance_spf_ietf_backoff_delay_long_delay_modify(
569 struct nb_cb_modify_args *args)
570{
571 /* All the work is done in the apply_finish */
572 return NB_OK;
573}
574
575/*
576 * XPath: /frr-isisd:isis/instance/spf/ietf-backoff-delay/hold-down
577 */
578int isis_instance_spf_ietf_backoff_delay_hold_down_modify(
579 struct nb_cb_modify_args *args)
580{
581 /* All the work is done in the apply_finish */
582 return NB_OK;
583}
584
585/*
586 * XPath: /frr-isisd:isis/instance/spf/ietf-backoff-delay/time-to-learn
587 */
588int isis_instance_spf_ietf_backoff_delay_time_to_learn_modify(
589 struct nb_cb_modify_args *args)
590{
591 /* All the work is done in the apply_finish */
592 return NB_OK;
593}
594
595/*
596 * XPath: /frr-isisd:isis/instance/spf/minimum-interval/level-1
597 */
598int isis_instance_spf_minimum_interval_level_1_modify(
599 struct nb_cb_modify_args *args)
600{
601 struct isis_area *area;
602
603 if (args->event != NB_EV_APPLY)
604 return NB_OK;
605
606 area = nb_running_get_entry(args->dnode, NULL, true);
607 area->min_spf_interval[0] = yang_dnode_get_uint16(args->dnode, NULL);
608
609 return NB_OK;
610}
611
612/*
613 * XPath: /frr-isisd:isis/instance/spf/minimum-interval/level-2
614 */
615int isis_instance_spf_minimum_interval_level_2_modify(
616 struct nb_cb_modify_args *args)
617{
618 struct isis_area *area;
619
620 if (args->event != NB_EV_APPLY)
621 return NB_OK;
622
623 area = nb_running_get_entry(args->dnode, NULL, true);
624 area->min_spf_interval[1] = yang_dnode_get_uint16(args->dnode, NULL);
625
626 return NB_OK;
627}
628
629/*
630 * XPath:
631 * /frr-isisd:isis/instance/spf/prefix-priorities/critical/access-list-name
632 */
633int isis_instance_spf_prefix_priorities_critical_access_list_name_modify(
634 struct nb_cb_modify_args *args)
635{
636 struct isis_area *area;
637 const char *acl_name;
638 struct spf_prefix_priority_acl *ppa;
639
640 if (args->event != NB_EV_APPLY)
641 return NB_OK;
642
643 area = nb_running_get_entry(args->dnode, NULL, true);
644 acl_name = yang_dnode_get_string(args->dnode, NULL);
645
646 ppa = &area->spf_prefix_priorities[SPF_PREFIX_PRIO_CRITICAL];
647 XFREE(MTYPE_ISIS_ACL_NAME, ppa->name);
648 ppa->name = XSTRDUP(MTYPE_ISIS_ACL_NAME, acl_name);
649 ppa->list_v4 = access_list_lookup(AFI_IP, acl_name);
650 ppa->list_v6 = access_list_lookup(AFI_IP6, acl_name);
651 lsp_regenerate_schedule(area, area->is_type, 0);
652
653 return NB_OK;
654}
655
656int isis_instance_spf_prefix_priorities_critical_access_list_name_destroy(
657 struct nb_cb_destroy_args *args)
658{
659 struct isis_area *area;
660 struct spf_prefix_priority_acl *ppa;
661
662 if (args->event != NB_EV_APPLY)
663 return NB_OK;
664
665 area = nb_running_get_entry(args->dnode, NULL, true);
666
667 ppa = &area->spf_prefix_priorities[SPF_PREFIX_PRIO_CRITICAL];
668 XFREE(MTYPE_ISIS_ACL_NAME, ppa->name);
669 ppa->list_v4 = NULL;
670 ppa->list_v6 = NULL;
671 lsp_regenerate_schedule(area, area->is_type, 0);
672
673 return NB_OK;
674}
675
676/*
677 * XPath: /frr-isisd:isis/instance/spf/prefix-priorities/high/access-list-name
678 */
679int isis_instance_spf_prefix_priorities_high_access_list_name_modify(
680 struct nb_cb_modify_args *args)
681{
682 struct isis_area *area;
683 const char *acl_name;
684 struct spf_prefix_priority_acl *ppa;
685
686 if (args->event != NB_EV_APPLY)
687 return NB_OK;
688
689 area = nb_running_get_entry(args->dnode, NULL, true);
690 acl_name = yang_dnode_get_string(args->dnode, NULL);
691
692 ppa = &area->spf_prefix_priorities[SPF_PREFIX_PRIO_HIGH];
693 XFREE(MTYPE_ISIS_ACL_NAME, ppa->name);
694 ppa->name = XSTRDUP(MTYPE_ISIS_ACL_NAME, acl_name);
695 ppa->list_v4 = access_list_lookup(AFI_IP, acl_name);
696 ppa->list_v6 = access_list_lookup(AFI_IP6, acl_name);
697 lsp_regenerate_schedule(area, area->is_type, 0);
698
699 return NB_OK;
700}
701
702int isis_instance_spf_prefix_priorities_high_access_list_name_destroy(
703 struct nb_cb_destroy_args *args)
704{
705 struct isis_area *area;
706 struct spf_prefix_priority_acl *ppa;
707
708 if (args->event != NB_EV_APPLY)
709 return NB_OK;
710
711 area = nb_running_get_entry(args->dnode, NULL, true);
712
713 ppa = &area->spf_prefix_priorities[SPF_PREFIX_PRIO_HIGH];
714 XFREE(MTYPE_ISIS_ACL_NAME, ppa->name);
715 ppa->list_v4 = NULL;
716 ppa->list_v6 = NULL;
717 lsp_regenerate_schedule(area, area->is_type, 0);
718
719 return NB_OK;
720}
721
722/*
723 * XPath: /frr-isisd:isis/instance/spf/prefix-priorities/medium/access-list-name
724 */
725int isis_instance_spf_prefix_priorities_medium_access_list_name_modify(
726 struct nb_cb_modify_args *args)
727{
728 struct isis_area *area;
729 const char *acl_name;
730 struct spf_prefix_priority_acl *ppa;
731
732 if (args->event != NB_EV_APPLY)
733 return NB_OK;
734
735 area = nb_running_get_entry(args->dnode, NULL, true);
736 acl_name = yang_dnode_get_string(args->dnode, NULL);
737
738 ppa = &area->spf_prefix_priorities[SPF_PREFIX_PRIO_MEDIUM];
739 XFREE(MTYPE_ISIS_ACL_NAME, ppa->name);
740 ppa->name = XSTRDUP(MTYPE_ISIS_ACL_NAME, acl_name);
741 ppa->list_v4 = access_list_lookup(AFI_IP, acl_name);
742 ppa->list_v6 = access_list_lookup(AFI_IP6, acl_name);
743 lsp_regenerate_schedule(area, area->is_type, 0);
744
745 return NB_OK;
746}
747
748int isis_instance_spf_prefix_priorities_medium_access_list_name_destroy(
749 struct nb_cb_destroy_args *args)
750{
751 struct isis_area *area;
752 struct spf_prefix_priority_acl *ppa;
753
754 if (args->event != NB_EV_APPLY)
755 return NB_OK;
756
757 area = nb_running_get_entry(args->dnode, NULL, true);
758
759 ppa = &area->spf_prefix_priorities[SPF_PREFIX_PRIO_MEDIUM];
760 XFREE(MTYPE_ISIS_ACL_NAME, ppa->name);
761 ppa->list_v4 = NULL;
762 ppa->list_v6 = NULL;
763 lsp_regenerate_schedule(area, area->is_type, 0);
764
765 return NB_OK;
766}
767
768/*
769 * XPath: /frr-isisd:isis/instance/area-password
770 */
771void area_password_apply_finish(struct nb_cb_apply_finish_args *args)
772{
773 const char *password = yang_dnode_get_string(args->dnode, "./password");
774 struct isis_area *area = nb_running_get_entry(args->dnode, NULL, true);
775 int pass_type = yang_dnode_get_enum(args->dnode, "./password-type");
776 uint8_t snp_auth =
777 yang_dnode_get_enum(args->dnode, "./authenticate-snp");
778
779 switch (pass_type) {
780 case ISIS_PASSWD_TYPE_CLEARTXT:
781 isis_area_passwd_cleartext_set(area, IS_LEVEL_1, password,
782 snp_auth);
783 break;
784 case ISIS_PASSWD_TYPE_HMAC_MD5:
785 isis_area_passwd_hmac_md5_set(area, IS_LEVEL_1, password,
786 snp_auth);
787 break;
788 }
789}
790
791int isis_instance_area_password_create(struct nb_cb_create_args *args)
792{
793 /* actual setting is done in apply_finish */
794 return NB_OK;
795}
796
797int isis_instance_area_password_destroy(struct nb_cb_destroy_args *args)
798{
799 struct isis_area *area;
800
801 if (args->event != NB_EV_APPLY)
802 return NB_OK;
803
804 area = nb_running_get_entry(args->dnode, NULL, true);
805 isis_area_passwd_unset(area, IS_LEVEL_1);
806
807 return NB_OK;
808}
809
810/*
811 * XPath: /frr-isisd:isis/instance/area-password/password
812 */
813int isis_instance_area_password_password_modify(struct nb_cb_modify_args *args)
814{
815 /* actual setting is done in apply_finish */
816 return NB_OK;
817}
818
819/*
820 * XPath: /frr-isisd:isis/instance/area-password/password-type
821 */
822int isis_instance_area_password_password_type_modify(
823 struct nb_cb_modify_args *args)
824{
825 /* actual setting is done in apply_finish */
826 return NB_OK;
827}
828
829/*
830 * XPath: /frr-isisd:isis/instance/area-password/authenticate-snp
831 */
832int isis_instance_area_password_authenticate_snp_modify(
833 struct nb_cb_modify_args *args)
834{
835 /* actual setting is done in apply_finish */
836 return NB_OK;
837}
838
839/*
840 * XPath: /frr-isisd:isis/instance/domain-password
841 */
842void domain_password_apply_finish(struct nb_cb_apply_finish_args *args)
843{
844 const char *password = yang_dnode_get_string(args->dnode, "./password");
845 struct isis_area *area = nb_running_get_entry(args->dnode, NULL, true);
846 int pass_type = yang_dnode_get_enum(args->dnode, "./password-type");
847 uint8_t snp_auth =
848 yang_dnode_get_enum(args->dnode, "./authenticate-snp");
849
850 switch (pass_type) {
851 case ISIS_PASSWD_TYPE_CLEARTXT:
852 isis_area_passwd_cleartext_set(area, IS_LEVEL_2, password,
853 snp_auth);
854 break;
855 case ISIS_PASSWD_TYPE_HMAC_MD5:
856 isis_area_passwd_hmac_md5_set(area, IS_LEVEL_2, password,
857 snp_auth);
858 break;
859 }
860}
861
862int isis_instance_domain_password_create(struct nb_cb_create_args *args)
863{
864 /* actual setting is done in apply_finish */
865 return NB_OK;
866}
867
868int isis_instance_domain_password_destroy(struct nb_cb_destroy_args *args)
869{
870 struct isis_area *area;
871
872 if (args->event != NB_EV_APPLY)
873 return NB_OK;
874
875 area = nb_running_get_entry(args->dnode, NULL, true);
876 isis_area_passwd_unset(area, IS_LEVEL_2);
877
878 return NB_OK;
879}
880
881/*
882 * XPath: /frr-isisd:isis/instance/domain-password/password
883 */
884int isis_instance_domain_password_password_modify(
885 struct nb_cb_modify_args *args)
886{
887 /* actual setting is done in apply_finish */
888 return NB_OK;
889}
890
891/*
892 * XPath: /frr-isisd:isis/instance/domain-password/password-type
893 */
894int isis_instance_domain_password_password_type_modify(
895 struct nb_cb_modify_args *args)
896{
897 /* actual setting is done in apply_finish */
898 return NB_OK;
899}
900
901/*
902 * XPath: /frr-isisd:isis/instance/domain-password/authenticate-snp
903 */
904int isis_instance_domain_password_authenticate_snp_modify(
905 struct nb_cb_modify_args *args)
906{
907 /* actual setting is done in apply_finish */
908 return NB_OK;
909}
910
911/*
912 * XPath: /frr-isisd:isis/instance/default-information-originate/ipv4
913 */
914void default_info_origin_apply_finish(const struct lyd_node *dnode, int family)
915{
916 int originate_type = DEFAULT_ORIGINATE;
917 unsigned long metric = 0;
918 const char *routemap = NULL;
919 struct isis_area *area = nb_running_get_entry(dnode, NULL, true);
920 int level = yang_dnode_get_enum(dnode, "./level");
921
922 if (yang_dnode_get_bool(dnode, "./always")) {
923 originate_type = DEFAULT_ORIGINATE_ALWAYS;
924 } else if (family == AF_INET6) {
925 zlog_warn(
926 "%s: Zebra doesn't implement default-originate for IPv6 yet, so use with care or use default-originate always.",
927 __func__);
928 }
929
930 if (yang_dnode_exists(dnode, "./metric"))
931 metric = yang_dnode_get_uint32(dnode, "./metric");
932 if (yang_dnode_exists(dnode, "./route-map"))
933 routemap = yang_dnode_get_string(dnode, "./route-map");
934
935 isis_redist_set(area, level, family, DEFAULT_ROUTE, metric, routemap,
936 originate_type);
937}
938
939void default_info_origin_ipv4_apply_finish(struct nb_cb_apply_finish_args *args)
940{
941 default_info_origin_apply_finish(args->dnode, AF_INET);
942}
943
944void default_info_origin_ipv6_apply_finish(struct nb_cb_apply_finish_args *args)
945{
946 default_info_origin_apply_finish(args->dnode, AF_INET6);
947}
948
949int isis_instance_default_information_originate_ipv4_create(
950 struct nb_cb_create_args *args)
951{
952 /* It's all done by default_info_origin_apply_finish */
953 return NB_OK;
954}
955
956int isis_instance_default_information_originate_ipv4_destroy(
957 struct nb_cb_destroy_args *args)
958{
959 struct isis_area *area;
960 int level;
961
962 if (args->event != NB_EV_APPLY)
963 return NB_OK;
964
965 area = nb_running_get_entry(args->dnode, NULL, true);
966 level = yang_dnode_get_enum(args->dnode, "./level");
967 isis_redist_unset(area, level, AF_INET, DEFAULT_ROUTE);
968
969 return NB_OK;
970}
971
972/*
973 * XPath: /frr-isisd:isis/instance/default-information-originate/ipv4/always
974 */
975int isis_instance_default_information_originate_ipv4_always_modify(
976 struct nb_cb_modify_args *args)
977{
978 /* It's all done by default_info_origin_apply_finish */
979 return NB_OK;
980}
981
982/*
983 * XPath: /frr-isisd:isis/instance/default-information-originate/ipv4/route-map
984 */
985int isis_instance_default_information_originate_ipv4_route_map_modify(
986 struct nb_cb_modify_args *args)
987{
988 /* It's all done by default_info_origin_apply_finish */
989 return NB_OK;
990}
991
992int isis_instance_default_information_originate_ipv4_route_map_destroy(
993 struct nb_cb_destroy_args *args)
994{
995 /* It's all done by default_info_origin_apply_finish */
996 return NB_OK;
997}
998
999/*
1000 * XPath: /frr-isisd:isis/instance/default-information-originate/ipv4/metric
1001 */
1002int isis_instance_default_information_originate_ipv4_metric_modify(
1003 struct nb_cb_modify_args *args)
1004{
1005 /* It's all done by default_info_origin_apply_finish */
1006 return NB_OK;
1007}
1008
1009/*
1010 * XPath: /frr-isisd:isis/instance/default-information-originate/ipv6
1011 */
1012int isis_instance_default_information_originate_ipv6_create(
1013 struct nb_cb_create_args *args)
1014{
1015 /* It's all done by default_info_origin_apply_finish */
1016 return NB_OK;
1017}
1018
1019int isis_instance_default_information_originate_ipv6_destroy(
1020 struct nb_cb_destroy_args *args)
1021{
1022 struct isis_area *area;
1023 int level;
1024
1025 if (args->event != NB_EV_APPLY)
1026 return NB_OK;
1027
1028 area = nb_running_get_entry(args->dnode, NULL, true);
1029 level = yang_dnode_get_enum(args->dnode, "./level");
1030 isis_redist_unset(area, level, AF_INET6, DEFAULT_ROUTE);
1031
1032 return NB_OK;
1033}
1034
1035/*
1036 * XPath: /frr-isisd:isis/instance/default-information-originate/ipv6/always
1037 */
1038int isis_instance_default_information_originate_ipv6_always_modify(
1039 struct nb_cb_modify_args *args)
1040{
1041 /* It's all done by default_info_origin_apply_finish */
1042 return NB_OK;
1043}
1044
1045/*
1046 * XPath: /frr-isisd:isis/instance/default-information-originate/ipv6/route-map
1047 */
1048int isis_instance_default_information_originate_ipv6_route_map_modify(
1049 struct nb_cb_modify_args *args)
1050{
1051 /* It's all done by default_info_origin_apply_finish */
1052 return NB_OK;
1053}
1054
1055int isis_instance_default_information_originate_ipv6_route_map_destroy(
1056 struct nb_cb_destroy_args *args)
1057{
1058 /* It's all done by default_info_origin_apply_finish */
1059 return NB_OK;
1060}
1061
1062/*
1063 * XPath: /frr-isisd:isis/instance/default-information-originate/ipv6/metric
1064 */
1065int isis_instance_default_information_originate_ipv6_metric_modify(
1066 struct nb_cb_modify_args *args)
1067{
1068 /* It's all done by default_info_origin_apply_finish */
1069 return NB_OK;
1070}
1071
1072/*
1073 * XPath: /frr-isisd:isis/instance/redistribute/ipv4
1074 */
1075void redistribute_apply_finish(const struct lyd_node *dnode, int family)
1076{
1077 assert(family == AF_INET || family == AF_INET6);
1078 int type, level;
1079 unsigned long metric = 0;
1080 const char *routemap = NULL;
1081 struct isis_area *area;
1082
1083 type = yang_dnode_get_enum(dnode, "./protocol");
1084 level = yang_dnode_get_enum(dnode, "./level");
1085 area = nb_running_get_entry(dnode, NULL, true);
1086
1087 if (yang_dnode_exists(dnode, "./metric"))
1088 metric = yang_dnode_get_uint32(dnode, "./metric");
1089 if (yang_dnode_exists(dnode, "./route-map"))
1090 routemap = yang_dnode_get_string(dnode, "./route-map");
1091
1092 isis_redist_set(area, level, family, type, metric, routemap, 0);
1093}
1094
1095void redistribute_ipv4_apply_finish(struct nb_cb_apply_finish_args *args)
1096{
1097 redistribute_apply_finish(args->dnode, AF_INET);
1098}
1099
1100void redistribute_ipv6_apply_finish(struct nb_cb_apply_finish_args *args)
1101{
1102 redistribute_apply_finish(args->dnode, AF_INET6);
1103}
1104
1105int isis_instance_redistribute_ipv4_create(struct nb_cb_create_args *args)
1106{
1107 /* It's all done by redistribute_apply_finish */
1108 return NB_OK;
1109}
1110
1111int isis_instance_redistribute_ipv4_destroy(struct nb_cb_destroy_args *args)
1112{
1113 struct isis_area *area;
1114 int level, type;
1115
1116 if (args->event != NB_EV_APPLY)
1117 return NB_OK;
1118
1119 area = nb_running_get_entry(args->dnode, NULL, true);
1120 level = yang_dnode_get_enum(args->dnode, "./level");
1121 type = yang_dnode_get_enum(args->dnode, "./protocol");
1122 isis_redist_unset(area, level, AF_INET, type);
1123
1124 return NB_OK;
1125}
1126
1127/*
1128 * XPath: /frr-isisd:isis/instance/redistribute/ipv4/route-map
1129 */
1130int isis_instance_redistribute_ipv4_route_map_modify(
1131 struct nb_cb_modify_args *args)
1132{
1133 /* It's all done by redistribute_apply_finish */
1134 return NB_OK;
1135}
1136
1137int isis_instance_redistribute_ipv4_route_map_destroy(
1138 struct nb_cb_destroy_args *args)
1139{
1140 /* It's all done by redistribute_apply_finish */
1141 return NB_OK;
1142}
1143
1144/*
1145 * XPath: /frr-isisd:isis/instance/redistribute/ipv4/metric
1146 */
1147int isis_instance_redistribute_ipv4_metric_modify(
1148 struct nb_cb_modify_args *args)
1149{
1150 /* It's all done by redistribute_apply_finish */
1151 return NB_OK;
1152}
1153
1154/*
1155 * XPath: /frr-isisd:isis/instance/redistribute/ipv6
1156 */
1157int isis_instance_redistribute_ipv6_create(struct nb_cb_create_args *args)
1158{
1159 /* It's all done by redistribute_apply_finish */
1160 return NB_OK;
1161}
1162
1163int isis_instance_redistribute_ipv6_destroy(struct nb_cb_destroy_args *args)
1164{
1165 struct isis_area *area;
1166 int level, type;
1167
1168 if (args->event != NB_EV_APPLY)
1169 return NB_OK;
1170
1171 area = nb_running_get_entry(args->dnode, NULL, true);
1172 level = yang_dnode_get_enum(args->dnode, "./level");
1173 type = yang_dnode_get_enum(args->dnode, "./protocol");
1174 isis_redist_unset(area, level, AF_INET6, type);
1175
1176 return NB_OK;
1177}
1178
1179/*
1180 * XPath: /frr-isisd:isis/instance/redistribute/ipv6/route-map
1181 */
1182int isis_instance_redistribute_ipv6_route_map_modify(
1183 struct nb_cb_modify_args *args)
1184{
1185 /* It's all done by redistribute_apply_finish */
1186 return NB_OK;
1187}
1188
1189int isis_instance_redistribute_ipv6_route_map_destroy(
1190 struct nb_cb_destroy_args *args)
1191{
1192 /* It's all done by redistribute_apply_finish */
1193 return NB_OK;
1194}
1195
1196/*
1197 * XPath: /frr-isisd:isis/instance/redistribute/ipv6/metric
1198 */
1199int isis_instance_redistribute_ipv6_metric_modify(
1200 struct nb_cb_modify_args *args)
1201{
1202 /* It's all done by redistribute_apply_finish */
1203 return NB_OK;
1204}
1205
1206/*
1207 * XPath: /frr-isisd:isis/instance/multi-topology/ipv4-multicast
1208 */
1209static int isis_multi_topology_common(enum nb_event event,
1210 const struct lyd_node *dnode,
1211 char *errmsg, size_t errmsg_len,
1212 const char *topology, bool create)
1213{
1214 struct isis_area *area;
1215 struct isis_area_mt_setting *setting;
1216 uint16_t mtid = isis_str2mtid(topology);
1217
1218 switch (event) {
1219 case NB_EV_VALIDATE:
1220 if (mtid == (uint16_t)-1) {
1221 snprintf(errmsg, errmsg_len, "Unknown topology %s",
1222 topology);
1223 return NB_ERR_VALIDATION;
1224 }
1225 break;
1226 case NB_EV_PREPARE:
1227 case NB_EV_ABORT:
1228 break;
1229 case NB_EV_APPLY:
1230 area = nb_running_get_entry(dnode, NULL, true);
1231 setting = area_get_mt_setting(area, mtid);
1232 setting->enabled = create;
1233 lsp_regenerate_schedule(area, IS_LEVEL_1 | IS_LEVEL_2, 0);
1234 break;
1235 }
1236
1237 return NB_OK;
1238}
1239
1240static int isis_multi_topology_overload_common(enum nb_event event,
1241 const struct lyd_node *dnode,
1242 const char *topology)
1243{
1244 struct isis_area *area;
1245 struct isis_area_mt_setting *setting;
1246 uint16_t mtid = isis_str2mtid(topology);
1247
1248 /* validation is done in isis_multi_topology_common */
1249 if (event != NB_EV_APPLY)
1250 return NB_OK;
1251
1252 area = nb_running_get_entry(dnode, NULL, true);
1253 setting = area_get_mt_setting(area, mtid);
1254 setting->overload = yang_dnode_get_bool(dnode, NULL);
1255 if (setting->enabled)
1256 lsp_regenerate_schedule(area, IS_LEVEL_1 | IS_LEVEL_2, 0);
1257
1258 return NB_OK;
1259}
1260
1261int isis_instance_multi_topology_ipv4_multicast_create(
1262 struct nb_cb_create_args *args)
1263{
1264 return isis_multi_topology_common(args->event, args->dnode,
1265 args->errmsg, args->errmsg_len,
1266 "ipv4-multicast", true);
1267}
1268
1269int isis_instance_multi_topology_ipv4_multicast_destroy(
1270 struct nb_cb_destroy_args *args)
1271{
1272 return isis_multi_topology_common(args->event, args->dnode,
1273 args->errmsg, args->errmsg_len,
1274 "ipv4-multicast", false);
1275}
1276
1277/*
1278 * XPath: /frr-isisd:isis/instance/multi-topology/ipv4-multicast/overload
1279 */
1280int isis_instance_multi_topology_ipv4_multicast_overload_modify(
1281 struct nb_cb_modify_args *args)
1282{
1283 return isis_multi_topology_overload_common(args->event, args->dnode,
1284 "ipv4-multicast");
1285}
1286
1287/*
1288 * XPath: /frr-isisd:isis/instance/multi-topology/ipv4-management
1289 */
1290int isis_instance_multi_topology_ipv4_management_create(
1291 struct nb_cb_create_args *args)
1292{
1293 return isis_multi_topology_common(args->event, args->dnode,
1294 args->errmsg, args->errmsg_len,
1295 "ipv4-mgmt", true);
1296}
1297
1298int isis_instance_multi_topology_ipv4_management_destroy(
1299 struct nb_cb_destroy_args *args)
1300{
1301 return isis_multi_topology_common(args->event, args->dnode,
1302 args->errmsg, args->errmsg_len,
1303 "ipv4-mgmt", false);
1304}
1305
1306/*
1307 * XPath: /frr-isisd:isis/instance/multi-topology/ipv4-management/overload
1308 */
1309int isis_instance_multi_topology_ipv4_management_overload_modify(
1310 struct nb_cb_modify_args *args)
1311{
1312 return isis_multi_topology_overload_common(args->event, args->dnode,
1313 "ipv4-mgmt");
1314}
1315
1316/*
1317 * XPath: /frr-isisd:isis/instance/multi-topology/ipv6-unicast
1318 */
1319int isis_instance_multi_topology_ipv6_unicast_create(
1320 struct nb_cb_create_args *args)
1321{
1322 return isis_multi_topology_common(args->event, args->dnode,
1323 args->errmsg, args->errmsg_len,
1324 "ipv6-unicast", true);
1325}
1326
1327int isis_instance_multi_topology_ipv6_unicast_destroy(
1328 struct nb_cb_destroy_args *args)
1329{
1330 return isis_multi_topology_common(args->event, args->dnode,
1331 args->errmsg, args->errmsg_len,
1332 "ipv6-unicast", false);
1333}
1334
1335/*
1336 * XPath: /frr-isisd:isis/instance/multi-topology/ipv6-unicast/overload
1337 */
1338int isis_instance_multi_topology_ipv6_unicast_overload_modify(
1339 struct nb_cb_modify_args *args)
1340{
1341 return isis_multi_topology_overload_common(args->event, args->dnode,
1342 "ipv6-unicast");
1343}
1344
1345/*
1346 * XPath: /frr-isisd:isis/instance/multi-topology/ipv6-multicast
1347 */
1348int isis_instance_multi_topology_ipv6_multicast_create(
1349 struct nb_cb_create_args *args)
1350{
1351 return isis_multi_topology_common(args->event, args->dnode,
1352 args->errmsg, args->errmsg_len,
1353 "ipv6-multicast", true);
1354}
1355
1356int isis_instance_multi_topology_ipv6_multicast_destroy(
1357 struct nb_cb_destroy_args *args)
1358{
1359 return isis_multi_topology_common(args->event, args->dnode,
1360 args->errmsg, args->errmsg_len,
1361 "ipv6-multicast", false);
1362}
1363
1364/*
1365 * XPath: /frr-isisd:isis/instance/multi-topology/ipv6-multicast/overload
1366 */
1367int isis_instance_multi_topology_ipv6_multicast_overload_modify(
1368 struct nb_cb_modify_args *args)
1369{
1370 return isis_multi_topology_overload_common(args->event, args->dnode,
1371 "ipv6-multicast");
1372}
1373
1374/*
1375 * XPath: /frr-isisd:isis/instance/multi-topology/ipv6-management
1376 */
1377int isis_instance_multi_topology_ipv6_management_create(
1378 struct nb_cb_create_args *args)
1379{
1380 return isis_multi_topology_common(args->event, args->dnode,
1381 args->errmsg, args->errmsg_len,
1382 "ipv6-mgmt", true);
1383}
1384
1385int isis_instance_multi_topology_ipv6_management_destroy(
1386 struct nb_cb_destroy_args *args)
1387{
1388 return isis_multi_topology_common(args->event, args->dnode,
1389 args->errmsg, args->errmsg_len,
1390 "ipv6-mgmt", false);
1391}
1392
1393/*
1394 * XPath: /frr-isisd:isis/instance/multi-topology/ipv6-management/overload
1395 */
1396int isis_instance_multi_topology_ipv6_management_overload_modify(
1397 struct nb_cb_modify_args *args)
1398{
1399 return isis_multi_topology_overload_common(args->event, args->dnode,
1400 "ipv6-mgmt");
1401}
1402
1403/*
1404 * XPath: /frr-isisd:isis/instance/multi-topology/ipv6-dstsrc
1405 */
1406int isis_instance_multi_topology_ipv6_dstsrc_create(
1407 struct nb_cb_create_args *args)
1408{
1409 return isis_multi_topology_common(args->event, args->dnode,
1410 args->errmsg, args->errmsg_len,
1411 "ipv6-dstsrc", true);
1412}
1413
1414int isis_instance_multi_topology_ipv6_dstsrc_destroy(
1415 struct nb_cb_destroy_args *args)
1416{
1417 return isis_multi_topology_common(args->event, args->dnode,
1418 args->errmsg, args->errmsg_len,
1419 "ipv6-dstsrc", false);
1420}
1421
1422/*
1423 * XPath: /frr-isisd:isis/instance/multi-topology/ipv6-dstsrc/overload
1424 */
1425int isis_instance_multi_topology_ipv6_dstsrc_overload_modify(
1426 struct nb_cb_modify_args *args)
1427{
1428 return isis_multi_topology_overload_common(args->event, args->dnode,
1429 "ipv6-dstsrc");
1430}
1431
1432/*
1433 * XPath: /frr-isisd:isis/instance/fast-reroute/level-1/lfa/load-sharing
1434 */
1435int isis_instance_fast_reroute_level_1_lfa_load_sharing_modify(
1436 struct nb_cb_modify_args *args)
1437{
1438 struct isis_area *area;
1439
1440 if (args->event != NB_EV_APPLY)
1441 return NB_OK;
1442
1443 area = nb_running_get_entry(args->dnode, NULL, true);
1444 area->lfa_load_sharing[0] = yang_dnode_get_bool(args->dnode, NULL);
1445 lsp_regenerate_schedule(area, area->is_type, 0);
1446
1447 return NB_OK;
1448}
1449
1450/*
1451 * XPath: /frr-isisd:isis/instance/fast-reroute/level-1/lfa/priority-limit
1452 */
1453int isis_instance_fast_reroute_level_1_lfa_priority_limit_modify(
1454 struct nb_cb_modify_args *args)
1455{
1456 struct isis_area *area;
1457
1458 if (args->event != NB_EV_APPLY)
1459 return NB_OK;
1460
1461 area = nb_running_get_entry(args->dnode, NULL, true);
1462 area->lfa_priority_limit[0] = yang_dnode_get_enum(args->dnode, NULL);
1463 lsp_regenerate_schedule(area, area->is_type, 0);
1464
1465 return NB_OK;
1466}
1467
1468int isis_instance_fast_reroute_level_1_lfa_priority_limit_destroy(
1469 struct nb_cb_destroy_args *args)
1470{
1471 struct isis_area *area;
1472
1473 if (args->event != NB_EV_APPLY)
1474 return NB_OK;
1475
1476 area = nb_running_get_entry(args->dnode, NULL, true);
1477 area->lfa_priority_limit[0] = SPF_PREFIX_PRIO_LOW;
1478 lsp_regenerate_schedule(area, area->is_type, 0);
1479
1480 return NB_OK;
1481}
1482
1483/*
1484 * XPath: /frr-isisd:isis/instance/fast-reroute/level-1/lfa/tiebreaker
1485 */
1486int isis_instance_fast_reroute_level_1_lfa_tiebreaker_create(
1487 struct nb_cb_create_args *args)
1488{
1489 struct isis_area *area;
1490 uint8_t index;
1491 enum lfa_tiebreaker_type type;
1492 struct lfa_tiebreaker *tie_b;
1493
1494 if (args->event != NB_EV_APPLY)
1495 return NB_OK;
1496
1497 area = nb_running_get_entry(args->dnode, NULL, true);
1498 index = yang_dnode_get_uint8(args->dnode, "./index");
1499 type = yang_dnode_get_enum(args->dnode, "./type");
1500
1501 tie_b = isis_lfa_tiebreaker_add(area, ISIS_LEVEL1, index, type);
1502 nb_running_set_entry(args->dnode, tie_b);
1503 lsp_regenerate_schedule(area, area->is_type, 0);
1504
1505 return NB_OK;
1506}
1507
1508int isis_instance_fast_reroute_level_1_lfa_tiebreaker_destroy(
1509 struct nb_cb_destroy_args *args)
1510{
1511 struct lfa_tiebreaker *tie_b;
1512 struct isis_area *area;
1513
1514 if (args->event != NB_EV_APPLY)
1515 return NB_OK;
1516
1517 tie_b = nb_running_unset_entry(args->dnode);
1518 area = tie_b->area;
1519 isis_lfa_tiebreaker_delete(area, ISIS_LEVEL1, tie_b);
1520 lsp_regenerate_schedule(area, area->is_type, 0);
1521
1522 return NB_OK;
1523}
1524
1525/*
1526 * XPath: /frr-isisd:isis/instance/fast-reroute/level-1/lfa/tiebreaker/type
1527 */
1528int isis_instance_fast_reroute_level_1_lfa_tiebreaker_type_modify(
1529 struct nb_cb_modify_args *args)
1530{
1531 struct lfa_tiebreaker *tie_b;
1532 struct isis_area *area;
1533
1534 if (args->event != NB_EV_APPLY)
1535 return NB_OK;
1536
1537 tie_b = nb_running_get_entry(args->dnode, NULL, true);
1538 area = tie_b->area;
1539 tie_b->type = yang_dnode_get_enum(args->dnode, NULL);
1540 lsp_regenerate_schedule(area, area->is_type, 0);
1541
1542 return NB_OK;
1543}
1544
1545/*
1546 * XPath: /frr-isisd:isis/instance/fast-reroute/level-2/lfa/load-sharing
1547 */
1548int isis_instance_fast_reroute_level_2_lfa_load_sharing_modify(
1549 struct nb_cb_modify_args *args)
1550{
1551 struct isis_area *area;
1552
1553 if (args->event != NB_EV_APPLY)
1554 return NB_OK;
1555
1556 area = nb_running_get_entry(args->dnode, NULL, true);
1557 area->lfa_load_sharing[1] = yang_dnode_get_bool(args->dnode, NULL);
1558
1559 return NB_OK;
1560}
1561
1562/*
1563 * XPath: /frr-isisd:isis/instance/fast-reroute/level-2/lfa/priority-limit
1564 */
1565int isis_instance_fast_reroute_level_2_lfa_priority_limit_modify(
1566 struct nb_cb_modify_args *args)
1567{
1568 struct isis_area *area;
1569
1570 if (args->event != NB_EV_APPLY)
1571 return NB_OK;
1572
1573 area = nb_running_get_entry(args->dnode, NULL, true);
1574 area->lfa_priority_limit[1] = yang_dnode_get_enum(args->dnode, NULL);
1575
1576 return NB_OK;
1577}
1578
1579int isis_instance_fast_reroute_level_2_lfa_priority_limit_destroy(
1580 struct nb_cb_destroy_args *args)
1581{
1582 struct isis_area *area;
1583
1584 if (args->event != NB_EV_APPLY)
1585 return NB_OK;
1586
1587 area = nb_running_get_entry(args->dnode, NULL, true);
1588 area->lfa_priority_limit[1] = SPF_PREFIX_PRIO_LOW;
1589
1590 return NB_OK;
1591}
1592
1593/*
1594 * XPath: /frr-isisd:isis/instance/fast-reroute/level-2/lfa/tiebreaker
1595 */
1596int isis_instance_fast_reroute_level_2_lfa_tiebreaker_create(
1597 struct nb_cb_create_args *args)
1598{
1599 struct isis_area *area;
1600 uint8_t index;
1601 enum lfa_tiebreaker_type type;
1602 struct lfa_tiebreaker *tie_b;
1603
1604 if (args->event != NB_EV_APPLY)
1605 return NB_OK;
1606
1607 area = nb_running_get_entry(args->dnode, NULL, true);
1608 index = yang_dnode_get_uint8(args->dnode, "./index");
1609 type = yang_dnode_get_enum(args->dnode, "./type");
1610
1611 tie_b = isis_lfa_tiebreaker_add(area, ISIS_LEVEL2, index, type);
1612 nb_running_set_entry(args->dnode, tie_b);
1613 lsp_regenerate_schedule(area, area->is_type, 0);
1614
1615 return NB_OK;
1616}
1617
1618int isis_instance_fast_reroute_level_2_lfa_tiebreaker_destroy(
1619 struct nb_cb_destroy_args *args)
1620{
1621 struct lfa_tiebreaker *tie_b;
1622 struct isis_area *area;
1623
1624 if (args->event != NB_EV_APPLY)
1625 return NB_OK;
1626
1627 tie_b = nb_running_unset_entry(args->dnode);
1628 area = tie_b->area;
1629 isis_lfa_tiebreaker_delete(area, ISIS_LEVEL2, tie_b);
1630 lsp_regenerate_schedule(area, area->is_type, 0);
1631
1632 return NB_OK;
1633}
1634
1635/*
1636 * XPath: /frr-isisd:isis/instance/fast-reroute/level-2/lfa/tiebreaker/type
1637 */
1638int isis_instance_fast_reroute_level_2_lfa_tiebreaker_type_modify(
1639 struct nb_cb_modify_args *args)
1640{
1641 struct lfa_tiebreaker *tie_b;
1642 struct isis_area *area;
1643
1644 if (args->event != NB_EV_APPLY)
1645 return NB_OK;
1646
1647 tie_b = nb_running_get_entry(args->dnode, NULL, true);
1648 area = tie_b->area;
1649 tie_b->type = yang_dnode_get_enum(args->dnode, NULL);
1650 lsp_regenerate_schedule(area, area->is_type, 0);
1651
1652 return NB_OK;
1653}
1654
1655/*
1656 * XPath: /frr-isisd:isis/instance/log-adjacency-changes
1657 */
1658int isis_instance_log_adjacency_changes_modify(struct nb_cb_modify_args *args)
1659{
1660 struct isis_area *area;
1661 bool log = yang_dnode_get_bool(args->dnode, NULL);
1662
1663 if (args->event != NB_EV_APPLY)
1664 return NB_OK;
1665
1666 area = nb_running_get_entry(args->dnode, NULL, true);
1667 area->log_adj_changes = log ? 1 : 0;
1668
1669 return NB_OK;
1670}
1671
1672/*
1673 * XPath: /frr-isisd:isis/instance/mpls-te
1674 */
1675int isis_instance_mpls_te_create(struct nb_cb_create_args *args)
1676{
1677 struct listnode *node;
1678 struct isis_area *area;
1679 struct isis_circuit *circuit;
1680
1681 if (args->event != NB_EV_APPLY)
1682 return NB_OK;
1683
1684 area = nb_running_get_entry(args->dnode, NULL, true);
1685 if (area->mta == NULL) {
1686
1687 struct mpls_te_area *new;
1688
1689 zlog_debug("ISIS-TE(%s): Initialize MPLS Traffic Engineering",
1690 area->area_tag);
1691
1692 new = XCALLOC(MTYPE_ISIS_MPLS_TE, sizeof(struct mpls_te_area));
1693
1694 /* Initialize MPLS_TE structure */
1695 new->status = enable;
1696 new->level = 0;
1697 new->inter_as = off;
1698 new->interas_areaid.s_addr = 0;
1699 new->router_id.s_addr = 0;
1700
1701 area->mta = new;
1702 } else {
1703 area->mta->status = enable;
1704 }
1705
1706 /* Update Extended TLVs according to Interface link parameters */
1707 for (ALL_LIST_ELEMENTS_RO(area->circuit_list, node, circuit))
1708 isis_link_params_update(circuit, circuit->interface);
1709
1710 /* Reoriginate STD_TE & GMPLS circuits */
1711 lsp_regenerate_schedule(area, area->is_type, 0);
1712
1713 return NB_OK;
1714}
1715
1716int isis_instance_mpls_te_destroy(struct nb_cb_destroy_args *args)
1717{
1718 struct listnode *node;
1719 struct isis_area *area;
1720 struct isis_circuit *circuit;
1721
1722 if (args->event != NB_EV_APPLY)
1723 return NB_OK;
1724
1725 area = nb_running_get_entry(args->dnode, NULL, true);
1726 if (IS_MPLS_TE(area->mta))
1727 area->mta->status = disable;
1728 else
1729 return NB_OK;
1730
1731 /* Flush LSP if circuit engage */
1732 for (ALL_LIST_ELEMENTS_RO(area->circuit_list, node, circuit)) {
1733 if (!IS_EXT_TE(circuit->ext))
1734 continue;
1735
1736 /* disable MPLS_TE Circuit keeping SR one's */
1737 if (IS_SUBTLV(circuit->ext, EXT_ADJ_SID))
1738 circuit->ext->status = EXT_ADJ_SID;
1739 else if (IS_SUBTLV(circuit->ext, EXT_LAN_ADJ_SID))
1740 circuit->ext->status = EXT_LAN_ADJ_SID;
1741 else
1742 circuit->ext->status = 0;
1743 }
1744
1745 /* Reoriginate STD_TE & GMPLS circuits */
1746 lsp_regenerate_schedule(area, area->is_type, 0);
1747
1748 zlog_debug("ISIS-TE(%s): Disabled MPLS Traffic Engineering",
1749 area->area_tag);
1750
1751 return NB_OK;
1752}
1753
1754/*
1755 * XPath: /frr-isisd:isis/instance/mpls-te/router-address
1756 */
1757int isis_instance_mpls_te_router_address_modify(struct nb_cb_modify_args *args)
1758{
1759 struct in_addr value;
1760 struct isis_area *area;
1761
1762 if (args->event != NB_EV_APPLY)
1763 return NB_OK;
1764
1765 area = nb_running_get_entry(args->dnode, NULL, true);
1766 /* only proceed if MPLS-TE is enabled */
1767 if (!IS_MPLS_TE(area->mta))
1768 return NB_OK;
1769
1770 /* Update Area Router ID */
1771 yang_dnode_get_ipv4(&value, args->dnode, NULL);
1772 area->mta->router_id.s_addr = value.s_addr;
1773
1774 /* And re-schedule LSP update */
1775 lsp_regenerate_schedule(area, area->is_type, 0);
1776
1777 return NB_OK;
1778}
1779
1780int isis_instance_mpls_te_router_address_destroy(
1781 struct nb_cb_destroy_args *args)
1782{
1783 struct isis_area *area;
1784
1785 if (args->event != NB_EV_APPLY)
1786 return NB_OK;
1787
1788 area = nb_running_get_entry(args->dnode, NULL, true);
1789 /* only proceed if MPLS-TE is enabled */
1790 if (!IS_MPLS_TE(area->mta))
1791 return NB_OK;
1792
1793 /* Reset Area Router ID */
1794 area->mta->router_id.s_addr = INADDR_ANY;
1795
1796 /* And re-schedule LSP update */
1797 lsp_regenerate_schedule(area, area->is_type, 0);
1798
1799 return NB_OK;
1800}
1801
1802/*
1803 * XPath: /frr-isisd:isis/instance/segment-routing/enabled
1804 */
1805int isis_instance_segment_routing_enabled_modify(
1806 struct nb_cb_modify_args *args)
1807{
1808 struct isis_area *area;
1809
1810 if (args->event != NB_EV_APPLY)
1811 return NB_OK;
1812
1813 area = nb_running_get_entry(args->dnode, NULL, true);
1814 area->srdb.config.enabled = yang_dnode_get_bool(args->dnode, NULL);
1815
1816 if (area->srdb.config.enabled) {
1817 if (IS_DEBUG_EVENTS)
1818 zlog_debug("SR: Segment Routing: OFF -> ON");
1819
1820 isis_sr_start(area);
1821 } else {
1822 if (IS_DEBUG_EVENTS)
1823 zlog_debug("SR: Segment Routing: ON -> OFF");
1824
1825 isis_sr_stop(area);
1826 }
1827
1828 return NB_OK;
1829}
1830
1831/*
1832 * XPath: /frr-isisd:isis/instance/segment-routing/srgb
1833 */
1834int isis_instance_segment_routing_srgb_pre_validate(
1835 struct nb_cb_pre_validate_args *args)
1836{
1837 uint32_t srgb_lbound;
1838 uint32_t srgb_ubound;
1839 uint32_t srlb_lbound;
1840 uint32_t srlb_ubound;
1841
1842 srgb_lbound = yang_dnode_get_uint32(args->dnode, "./lower-bound");
1843 srgb_ubound = yang_dnode_get_uint32(args->dnode, "./upper-bound");
1844 srlb_lbound = yang_dnode_get_uint32(args->dnode, "../srlb/lower-bound");
1845 srlb_ubound = yang_dnode_get_uint32(args->dnode, "../srlb/upper-bound");
1846
1847 /* Check that the block size does not exceed 65535 */
1848 if ((srgb_ubound - srgb_lbound + 1) > 65535) {
1849 snprintf(
1850 args->errmsg, args->errmsg_len,
1851 "New SR Global Block (%u/%u) exceed the limit of 65535",
1852 srgb_lbound, srgb_ubound);
1853 return NB_ERR_VALIDATION;
1854 }
1855
1856 /* Validate SRGB against SRLB */
1857 if (!((srgb_ubound < srlb_lbound) || (srgb_lbound > srlb_ubound))) {
1858 snprintf(
1859 args->errmsg, args->errmsg_len,
1860 "New SR Global Block (%u/%u) conflict with Local Block (%u/%u)",
1861 srgb_lbound, srgb_ubound, srlb_lbound, srlb_ubound);
1862 return NB_ERR_VALIDATION;
1863 }
1864
1865 return NB_OK;
1866}
1867
1868void isis_instance_segment_routing_srgb_apply_finish(
1869 struct nb_cb_apply_finish_args *args)
1870{
1871 struct isis_area *area;
1872 uint32_t lower_bound, upper_bound;
1873
1874 area = nb_running_get_entry(args->dnode, NULL, true);
1875 lower_bound = yang_dnode_get_uint32(args->dnode, "./lower-bound");
1876 upper_bound = yang_dnode_get_uint32(args->dnode, "./upper-bound");
1877
1878 isis_sr_cfg_srgb_update(area, lower_bound, upper_bound);
1879}
1880
1881/*
1882 * XPath: /frr-isisd:isis/instance/segment-routing/srgb/lower-bound
1883 */
1884int isis_instance_segment_routing_srgb_lower_bound_modify(
1885 struct nb_cb_modify_args *args)
1886{
1887 uint32_t lower_bound = yang_dnode_get_uint32(args->dnode, NULL);
1888
1889 switch (args->event) {
1890 case NB_EV_VALIDATE:
1891 if (!IS_MPLS_UNRESERVED_LABEL(lower_bound)) {
1892 snprintf(args->errmsg, args->errmsg_len,
1893 "Invalid SRGB lower bound: %u", lower_bound);
1894 return NB_ERR_VALIDATION;
1895 }
1896 break;
1897 case NB_EV_PREPARE:
1898 case NB_EV_ABORT:
1899 case NB_EV_APPLY:
1900 break;
1901 }
1902
1903 return NB_OK;
1904}
1905
1906/*
1907 * XPath: /frr-isisd:isis/instance/segment-routing/srgb/upper-bound
1908 */
1909int isis_instance_segment_routing_srgb_upper_bound_modify(
1910 struct nb_cb_modify_args *args)
1911{
1912 uint32_t upper_bound = yang_dnode_get_uint32(args->dnode, NULL);
1913
1914 switch (args->event) {
1915 case NB_EV_VALIDATE:
1916 if (!IS_MPLS_UNRESERVED_LABEL(upper_bound)) {
1917 snprintf(args->errmsg, args->errmsg_len,
1918 "Invalid SRGB upper bound: %u", upper_bound);
1919 return NB_ERR_VALIDATION;
1920 }
1921 break;
1922 case NB_EV_PREPARE:
1923 case NB_EV_ABORT:
1924 case NB_EV_APPLY:
1925 break;
1926 }
1927
1928 return NB_OK;
1929}
1930
1931/*
1932 * XPath: /frr-isisd:isis/instance/segment-routing/srlb
1933 */
1934int isis_instance_segment_routing_srlb_pre_validate(
1935 struct nb_cb_pre_validate_args *args)
1936{
1937 uint32_t srgb_lbound;
1938 uint32_t srgb_ubound;
1939 uint32_t srlb_lbound;
1940 uint32_t srlb_ubound;
1941
1942 srgb_lbound = yang_dnode_get_uint32(args->dnode, "../srgb/lower-bound");
1943 srgb_ubound = yang_dnode_get_uint32(args->dnode, "../srgb/upper-bound");
1944 srlb_lbound = yang_dnode_get_uint32(args->dnode, "./lower-bound");
1945 srlb_ubound = yang_dnode_get_uint32(args->dnode, "./upper-bound");
1946
1947 /* Check that the block size does not exceed 65535 */
1948 if ((srlb_ubound - srlb_lbound + 1) > 65535) {
1949 snprintf(args->errmsg, args->errmsg_len,
1950 "New SR Local Block (%u/%u) exceed the limit of 65535",
1951 srlb_lbound, srlb_ubound);
1952 return NB_ERR_VALIDATION;
1953 }
1954
1955 /* Validate SRLB against SRGB */
1956 if (!((srlb_ubound < srgb_lbound) || (srlb_lbound > srgb_ubound))) {
1957 snprintf(
1958 args->errmsg, args->errmsg_len,
1959 "New SR Local Block (%u/%u) conflict with Global Block (%u/%u)",
1960 srlb_lbound, srlb_ubound, srgb_lbound, srgb_ubound);
1961 return NB_ERR_VALIDATION;
1962 }
1963
1964 return NB_OK;
1965}
1966
1967void isis_instance_segment_routing_srlb_apply_finish(
1968 struct nb_cb_apply_finish_args *args)
1969{
1970 struct isis_area *area;
1971 uint32_t lower_bound, upper_bound;
1972
1973 area = nb_running_get_entry(args->dnode, NULL, true);
1974 lower_bound = yang_dnode_get_uint32(args->dnode, "./lower-bound");
1975 upper_bound = yang_dnode_get_uint32(args->dnode, "./upper-bound");
1976
1977 isis_sr_cfg_srlb_update(area, lower_bound, upper_bound);
1978}
1979
1980/*
1981 * XPath: /frr-isisd:isis/instance/segment-routing/srlb/lower-bound
1982 */
1983int isis_instance_segment_routing_srlb_lower_bound_modify(
1984 struct nb_cb_modify_args *args)
1985{
1986 uint32_t lower_bound = yang_dnode_get_uint32(args->dnode, NULL);
1987
1988 switch (args->event) {
1989 case NB_EV_VALIDATE:
1990 if (!IS_MPLS_UNRESERVED_LABEL(lower_bound)) {
1991 snprintf(args->errmsg, args->errmsg_len,
1992 "Invalid SRLB lower bound: %u", lower_bound);
1993 return NB_ERR_VALIDATION;
1994 }
1995 break;
1996 case NB_EV_PREPARE:
1997 case NB_EV_ABORT:
1998 case NB_EV_APPLY:
1999 break;
2000 }
2001
2002 return NB_OK;
2003}
2004
2005/*
2006 * XPath: /frr-isisd:isis/instance/segment-routing/srlb/upper-bound
2007 */
2008int isis_instance_segment_routing_srlb_upper_bound_modify(
2009 struct nb_cb_modify_args *args)
2010{
2011 uint32_t upper_bound = yang_dnode_get_uint32(args->dnode, NULL);
2012
2013 switch (args->event) {
2014 case NB_EV_VALIDATE:
2015 if (!IS_MPLS_UNRESERVED_LABEL(upper_bound)) {
2016 snprintf(args->errmsg, args->errmsg_len,
2017 "Invalid SRLB upper bound: %u", upper_bound);
2018 return NB_ERR_VALIDATION;
2019 }
2020 break;
2021 case NB_EV_PREPARE:
2022 case NB_EV_ABORT:
2023 case NB_EV_APPLY:
2024 break;
2025 }
2026
2027 return NB_OK;
2028}
2029
2030/*
2031 * XPath: /frr-isisd:isis/instance/segment-routing/msd/node-msd
2032 */
2033int isis_instance_segment_routing_msd_node_msd_modify(
2034 struct nb_cb_modify_args *args)
2035{
2036 struct isis_area *area;
2037
2038 if (args->event != NB_EV_APPLY)
2039 return NB_OK;
2040
2041 area = nb_running_get_entry(args->dnode, NULL, true);
2042 area->srdb.config.msd = yang_dnode_get_uint8(args->dnode, NULL);
2043
2044 /* Update and regenerate LSP */
2045 lsp_regenerate_schedule(area, area->is_type, 0);
2046
2047 return NB_OK;
2048}
2049
2050int isis_instance_segment_routing_msd_node_msd_destroy(
2051 struct nb_cb_destroy_args *args)
2052{
2053 struct isis_area *area;
2054
2055 if (args->event != NB_EV_APPLY)
2056 return NB_OK;
2057
2058 area = nb_running_get_entry(args->dnode, NULL, true);
2059 area->srdb.config.msd = 0;
2060
2061 /* Update and regenerate LSP */
2062 lsp_regenerate_schedule(area, area->is_type, 0);
2063
2064 return NB_OK;
2065}
2066
2067/*
2068 * XPath: /frr-isisd:isis/instance/segment-routing/prefix-sid-map/prefix-sid
2069 */
2070int isis_instance_segment_routing_prefix_sid_map_prefix_sid_create(
2071 struct nb_cb_create_args *args)
2072{
2073 struct isis_area *area;
2074 struct prefix prefix;
2075 struct sr_prefix_cfg *pcfg;
2076
2077 if (args->event != NB_EV_APPLY)
2078 return NB_OK;
2079
2080 area = nb_running_get_entry(args->dnode, NULL, true);
2081 yang_dnode_get_prefix(&prefix, args->dnode, "./prefix");
2082
2083 pcfg = isis_sr_cfg_prefix_add(area, &prefix);
2084 nb_running_set_entry(args->dnode, pcfg);
2085
2086 return NB_OK;
2087}
2088
2089int isis_instance_segment_routing_prefix_sid_map_prefix_sid_destroy(
2090 struct nb_cb_destroy_args *args)
2091{
2092 struct sr_prefix_cfg *pcfg;
2093 struct isis_area *area;
2094
2095 if (args->event != NB_EV_APPLY)
2096 return NB_OK;
2097
2098 pcfg = nb_running_unset_entry(args->dnode);
2099 area = pcfg->area;
2100 isis_sr_cfg_prefix_del(pcfg);
2101 lsp_regenerate_schedule(area, area->is_type, 0);
2102
2103 return NB_OK;
2104}
2105
2106int isis_instance_segment_routing_prefix_sid_map_prefix_sid_pre_validate(
2107 struct nb_cb_pre_validate_args *args)
2108{
2109 const struct lyd_node *area_dnode;
2110 struct isis_area *area;
2111 struct prefix prefix;
2112 uint32_t srgb_lbound;
2113 uint32_t srgb_ubound;
2114 uint32_t srgb_range;
2115 uint32_t sid;
2116 enum sr_sid_value_type sid_type;
2117 struct isis_prefix_sid psid = {};
2118
2119 yang_dnode_get_prefix(&prefix, args->dnode, "./prefix");
2120 srgb_lbound = yang_dnode_get_uint32(args->dnode,
2121 "../../srgb/lower-bound");
2122 srgb_ubound = yang_dnode_get_uint32(args->dnode,
2123 "../../srgb/upper-bound");
2124 sid = yang_dnode_get_uint32(args->dnode, "./sid-value");
2125 sid_type = yang_dnode_get_enum(args->dnode, "./sid-value-type");
2126
2127 /* Check for invalid indexes/labels. */
2128 srgb_range = srgb_ubound - srgb_lbound + 1;
2129 psid.value = sid;
2130 switch (sid_type) {
2131 case SR_SID_VALUE_TYPE_INDEX:
2132 if (sid >= srgb_range) {
2133 snprintf(args->errmsg, args->errmsg_len,
2134 "SID index %u falls outside local SRGB range",
2135 sid);
2136 return NB_ERR_VALIDATION;
2137 }
2138 break;
2139 case SR_SID_VALUE_TYPE_ABSOLUTE:
2140 if (!IS_MPLS_UNRESERVED_LABEL(sid)) {
2141 snprintf(args->errmsg, args->errmsg_len,
2142 "Invalid absolute SID %u", sid);
2143 return NB_ERR_VALIDATION;
2144 }
2145 SET_FLAG(psid.flags, ISIS_PREFIX_SID_VALUE);
2146 SET_FLAG(psid.flags, ISIS_PREFIX_SID_LOCAL);
2147 break;
2148 }
2149
2150 /* Check for Prefix-SID collisions. */
2151 area_dnode = yang_dnode_get_parent(args->dnode, "instance");
2152 area = nb_running_get_entry(area_dnode, NULL, false);
2153 if (area) {
2154 for (int tree = SPFTREE_IPV4; tree < SPFTREE_COUNT; tree++) {
2155 for (int level = ISIS_LEVEL1; level <= ISIS_LEVEL2;
2156 level++) {
2157 struct isis_spftree *spftree;
2158 struct isis_vertex *vertex_psid;
2159
2160 if (!(area->is_type & level))
2161 continue;
2162 spftree = area->spftree[tree][level - 1];
2163 if (!spftree)
2164 continue;
2165
2166 vertex_psid = isis_spf_prefix_sid_lookup(
2167 spftree, &psid);
2168 if (vertex_psid
2169 && !prefix_same(&vertex_psid->N.ip.p.dest,
2170 &prefix)) {
2171 snprintfrr(
2172 args->errmsg, args->errmsg_len,
2173 "Prefix-SID collision detected, SID %s %u is already in use by prefix %pFX (L%u)",
2174 CHECK_FLAG(
2175 psid.flags,
2176 ISIS_PREFIX_SID_VALUE)
2177 ? "label"
2178 : "index",
2179 psid.value,
2180 &vertex_psid->N.ip.p.dest,
2181 level);
2182 return NB_ERR_VALIDATION;
2183 }
2184 }
2185 }
2186 }
2187
2188 return NB_OK;
2189}
2190
2191void isis_instance_segment_routing_prefix_sid_map_prefix_sid_apply_finish(
2192 struct nb_cb_apply_finish_args *args)
2193{
2194 struct sr_prefix_cfg *pcfg;
2195 struct isis_area *area;
2196
2197 pcfg = nb_running_get_entry(args->dnode, NULL, true);
2198 area = pcfg->area;
2199 lsp_regenerate_schedule(area, area->is_type, 0);
2200}
2201
2202/*
2203 * XPath:
2204 * /frr-isisd:isis/instance/segment-routing/prefix-sid-map/prefix-sid/sid-value-type
2205 */
2206int isis_instance_segment_routing_prefix_sid_map_prefix_sid_sid_value_type_modify(
2207 struct nb_cb_modify_args *args)
2208{
2209 struct sr_prefix_cfg *pcfg;
2210
2211 if (args->event != NB_EV_APPLY)
2212 return NB_OK;
2213
2214 pcfg = nb_running_get_entry(args->dnode, NULL, true);
2215 pcfg->sid_type = yang_dnode_get_enum(args->dnode, NULL);
2216
2217 return NB_OK;
2218}
2219
2220/*
2221 * XPath:
2222 * /frr-isisd:isis/instance/segment-routing/prefix-sid-map/prefix-sid/sid-value
2223 */
2224int isis_instance_segment_routing_prefix_sid_map_prefix_sid_sid_value_modify(
2225 struct nb_cb_modify_args *args)
2226{
2227 struct sr_prefix_cfg *pcfg;
2228
2229 if (args->event != NB_EV_APPLY)
2230 return NB_OK;
2231
2232 pcfg = nb_running_get_entry(args->dnode, NULL, true);
2233 pcfg->sid = yang_dnode_get_uint32(args->dnode, NULL);
2234
2235 return NB_OK;
2236}
2237
2238/*
2239 * XPath:
2240 * /frr-isisd:isis/instance/segment-routing/prefix-sid-map/prefix-sid/last-hop-behavior
2241 */
2242int isis_instance_segment_routing_prefix_sid_map_prefix_sid_last_hop_behavior_modify(
2243 struct nb_cb_modify_args *args)
2244{
2245 struct sr_prefix_cfg *pcfg;
2246
2247 if (args->event != NB_EV_APPLY)
2248 return NB_OK;
2249
2250 pcfg = nb_running_get_entry(args->dnode, NULL, true);
2251 pcfg->last_hop_behavior = yang_dnode_get_enum(args->dnode, NULL);
2252
2253 return NB_OK;
2254}
2255
2256/*
2257 * XPath: /frr-isisd:isis/instance/segment-routing/prefix-sid-map/prefix-sid/n-flag-clear
2258 */
2259int isis_instance_segment_routing_prefix_sid_map_prefix_sid_n_flag_clear_modify(
2260 struct nb_cb_modify_args *args)
2261{
2262 struct sr_prefix_cfg *pcfg;
2263
2264 if (args->event != NB_EV_APPLY)
2265 return NB_OK;
2266
2267 pcfg = nb_running_get_entry(args->dnode, NULL, true);
2268 pcfg->n_flag_clear = yang_dnode_get_bool(args->dnode, NULL);
2269
2270 return NB_OK;
2271}
2272
2273/*
2274 * XPath: /frr-isisd:isis/instance/mpls/ldp-sync
2275 */
2276int isis_instance_mpls_ldp_sync_create(struct nb_cb_create_args *args)
2277{
2278 struct isis_area *area;
2279 struct listnode *node;
2280 struct isis_circuit *circuit;
2281 struct interface *ifp;
2282 struct vrf *vrf;
2283 struct isis *isis;
2284
2285 switch (args->event) {
2286 case NB_EV_VALIDATE:
2287 area = nb_running_get_entry(args->dnode, NULL, false);
2288 if (area == NULL || area->isis == NULL)
2289 return NB_ERR_VALIDATION;
2290
2291 if (area->isis->vrf_id != VRF_DEFAULT) {
2292 snprintf(args->errmsg, args->errmsg_len,
2293 "LDP-Sync only runs on Default VRF");
2294 return NB_ERR_VALIDATION;
2295 }
2296 break;
2297 case NB_EV_PREPARE:
2298 case NB_EV_ABORT:
2299 break;
2300 case NB_EV_APPLY:
2301 area = nb_running_get_entry(args->dnode, NULL, true);
2302 isis = area->isis;
2303 vrf = vrf_lookup_by_id(isis->vrf_id);
2304
2305 /* register with opaque client to recv LDP-IGP Sync msgs */
2306 zclient_register_opaque(zclient, LDP_IGP_SYNC_IF_STATE_UPDATE);
2307 zclient_register_opaque(zclient, LDP_IGP_SYNC_ANNOUNCE_UPDATE);
2308
2309 if (!CHECK_FLAG(isis->ldp_sync_cmd.flags,
2310 LDP_SYNC_FLAG_ENABLE)) {
2311 SET_FLAG(isis->ldp_sync_cmd.flags,
2312 LDP_SYNC_FLAG_ENABLE);
2313
2314 /* turn on LDP-IGP Sync on all ptop ISIS interfaces */
2315 FOR_ALL_INTERFACES (vrf, ifp) {
2316 for (ALL_LIST_ELEMENTS_RO(isis->area_list, node,
2317 area)) {
2318 circuit = circuit_lookup_by_ifp(
2319 ifp, area->circuit_list);
2320 if (circuit == NULL)
2321 continue;
2322 isis_if_set_ldp_sync_enable(circuit);
2323 }
2324 }
2325 }
2326 break;
2327 }
2328 return NB_OK;
2329}
2330
2331int isis_instance_mpls_ldp_sync_destroy(struct nb_cb_destroy_args *args)
2332{
2333 if (args->event != NB_EV_APPLY)
2334 return NB_OK;
2335
2336 /* remove ldp-sync config */
2337 isis_ldp_sync_gbl_exit(false);
2338
2339 return NB_OK;
2340}
2341
2342/*
2343 * XPath: /frr-isisd:isis/instance/mpls/ldp-sync/holddown
2344 */
2345int isis_instance_mpls_ldp_sync_holddown_modify(struct nb_cb_modify_args *args)
2346{
2347 struct isis_area *area;
2348 struct listnode *node;
2349 struct isis_circuit *circuit;
2350 struct interface *ifp;
2351 struct vrf *vrf;
2352 uint16_t holddown = LDP_IGP_SYNC_HOLDDOWN_DEFAULT;
2353 struct isis *isis;
2354
2355 switch (args->event) {
2356 case NB_EV_VALIDATE:
2357 area = nb_running_get_entry(args->dnode, NULL, false);
2358 if (area == NULL || area->isis == NULL)
2359 return NB_ERR_VALIDATION;
2360
2361 if (area->isis->vrf_id != VRF_DEFAULT) {
2362 snprintf(args->errmsg, args->errmsg_len,
2363 "LDP-Sync only runs on Default VRF");
2364 return NB_ERR_VALIDATION;
2365 }
2366 break;
2367 case NB_EV_PREPARE:
2368 case NB_EV_ABORT:
2369 break;
2370 case NB_EV_APPLY:
2371 area = nb_running_get_entry(args->dnode, NULL, true);
2372 isis = area->isis;
2373 vrf = vrf_lookup_by_id(isis->vrf_id);
2374 holddown = yang_dnode_get_uint16(args->dnode, NULL);
2375
2376 if (holddown == LDP_IGP_SYNC_HOLDDOWN_DEFAULT)
2377 UNSET_FLAG(isis->ldp_sync_cmd.flags,
2378 LDP_SYNC_FLAG_HOLDDOWN);
2379 else
2380 SET_FLAG(isis->ldp_sync_cmd.flags,
2381 LDP_SYNC_FLAG_HOLDDOWN);
2382 isis->ldp_sync_cmd.holddown = holddown;
2383
2384 /* set holddown time on all ISIS interfaces */
2385 FOR_ALL_INTERFACES (vrf, ifp) {
2386 for (ALL_LIST_ELEMENTS_RO(isis->area_list, node,
2387 area)) {
2388 circuit = circuit_lookup_by_ifp(ifp,
2389 area->circuit_list);
2390 if (circuit == NULL)
2391 continue;
2392 isis_if_set_ldp_sync_holddown(circuit);
2393 }
2394 }
2395 break;
2396 }
2397 return NB_OK;
2398}
2399
2400/*
2401 * XPath: /frr-interface:lib/interface/frr-isisd:isis
2402 */
2403int lib_interface_isis_create(struct nb_cb_create_args *args)
2404{
2405 struct isis_area *area = NULL;
2406 struct interface *ifp;
2407 struct isis_circuit *circuit = NULL;
2408 struct vrf *vrf;
2409 const char *area_tag = yang_dnode_get_string(args->dnode, "./area-tag");
2410 const char *vrf_name = yang_dnode_get_string(args->dnode, "./vrf");
2411 uint32_t min_mtu, actual_mtu;
2412
2413 switch (args->event) {
2414 case NB_EV_PREPARE:
2415 case NB_EV_ABORT:
2416 break;
2417 case NB_EV_VALIDATE:
2418 /* check if interface mtu is sufficient. If the area has not
2419 * been created yet, assume default MTU for the area
2420 */
2421 ifp = nb_running_get_entry(args->dnode, NULL, false);
2422 /* zebra might not know yet about the MTU - nothing we can do */
2423 if (!ifp || ifp->mtu == 0)
2424 break;
2425 vrf = vrf_lookup_by_id(ifp->vrf_id);
2426 if (ifp->vrf_id != VRF_DEFAULT && vrf
2427 && strcmp(vrf->name, vrf_name) != 0) {
2428 snprintf(args->errmsg, args->errmsg_len,
2429 "interface %s not in vrf %s\n", ifp->name,
2430 vrf_name);
2431 return NB_ERR_VALIDATION;
2432 }
2433 actual_mtu =
2434 if_is_broadcast(ifp) ? ifp->mtu - LLC_LEN : ifp->mtu;
2435
2436 area = isis_area_lookup(area_tag, ifp->vrf_id);
2437 if (area)
2438 min_mtu = area->lsp_mtu;
2439 else
2440#ifndef FABRICD
2441 min_mtu = yang_get_default_uint16(
2442 "/frr-isisd:isis/instance/lsp/mtu");
2443#else
2444 min_mtu = DEFAULT_LSP_MTU;
2445#endif /* ifndef FABRICD */
2446 if (actual_mtu < min_mtu) {
2447 snprintf(args->errmsg, args->errmsg_len,
2448 "Interface %s has MTU %u, minimum MTU for the area is %u",
2449 ifp->name, actual_mtu, min_mtu);
2450 return NB_ERR_VALIDATION;
2451 }
2452 break;
2453 case NB_EV_APPLY:
2454 area = isis_area_lookup_by_vrf(area_tag, vrf_name);
2455 /* The area should have already be created. We are
2456 * setting the priority of the global isis area creation
2457 * slightly lower, so it should be executed first, but I
2458 * cannot rely on that so here I have to check.
2459 */
2460 if (!area) {
2461 flog_err(
2462 EC_LIB_NB_CB_CONFIG_APPLY,
2463 "%s: attempt to create circuit for area %s before the area has been created",
2464 __func__, area_tag);
2465 abort();
2466 }
2467 ifp = nb_running_get_entry(args->dnode, NULL, true);
2468 circuit = isis_circuit_create(area, ifp);
2469 assert(circuit
2470 && (circuit->state == C_STATE_CONF
2471 || circuit->state == C_STATE_UP));
2472 nb_running_set_entry(args->dnode, circuit);
2473 break;
2474 }
2475
2476 return NB_OK;
2477}
2478
2479int lib_interface_isis_destroy(struct nb_cb_destroy_args *args)
2480{
2481 struct isis_circuit *circuit;
2482
2483 if (args->event != NB_EV_APPLY)
2484 return NB_OK;
2485
2486 circuit = nb_running_unset_entry(args->dnode);
2487 if (!circuit)
2488 return NB_ERR_INCONSISTENCY;
2489
2490 /* remove ldp-sync config */
2491 isis_ldp_sync_if_remove(circuit, true);
2492
2493 /* disable both AFs for this circuit. this will also update the
2494 * CSM state by sending an ISIS_DISABLED signal. If there is no
2495 * area associated to the circuit there is nothing to do
2496 */
2497 if (circuit->area)
2498 isis_circuit_af_set(circuit, false, false);
2499 return NB_OK;
2500}
2501
2502/*
2503 * XPath: /frr-interface:lib/interface/frr-isisd:isis/area-tag
2504 */
2505int lib_interface_isis_area_tag_modify(struct nb_cb_modify_args *args)
2506{
2507 struct isis_circuit *circuit;
2508 struct interface *ifp;
2509 struct vrf *vrf;
2510 const char *area_tag, *ifname, *vrfname;
2511
2512 if (args->event == NB_EV_VALIDATE) {
2513 /* libyang doesn't like relative paths across module boundaries
2514 */
2515 ifname = yang_dnode_get_string(args->dnode->parent->parent,
2516 "./name");
2517 vrfname = yang_dnode_get_string(args->dnode->parent->parent,
2518 "./vrf");
2519 vrf = vrf_lookup_by_name(vrfname);
2520 assert(vrf);
2521 ifp = if_lookup_by_name(ifname, vrf->vrf_id);
2522
2523 if (!ifp)
2524 return NB_OK;
2525
2526 circuit = circuit_scan_by_ifp(ifp);
2527 area_tag = yang_dnode_get_string(args->dnode, NULL);
2528 if (circuit && circuit->area && circuit->area->area_tag
2529 && strcmp(circuit->area->area_tag, area_tag)) {
2530 snprintf(args->errmsg, args->errmsg_len,
2531 "ISIS circuit is already defined on %s",
2532 circuit->area->area_tag);
2533 return NB_ERR_VALIDATION;
2534 }
2535 }
2536
2537 return NB_OK;
2538}
2539
2540/*
2541 * XPath: /frr-interface:lib/interface/frr-isisd:isis/vrf
2542 */
2543int lib_interface_isis_vrf_modify(struct nb_cb_modify_args *args)
2544{
2545 struct interface *ifp;
2546 struct vrf *vrf;
2547 const char *ifname, *vrfname, *vrf_name;
2548 struct isis_circuit *circuit;
2549
2550 if (args->event == NB_EV_VALIDATE) {
2551 /* libyang doesn't like relative paths across module boundaries
2552 */
2553 ifname = yang_dnode_get_string(args->dnode->parent->parent,
2554 "./name");
2555 vrfname = yang_dnode_get_string(args->dnode->parent->parent,
2556 "./vrf");
2557 vrf = vrf_lookup_by_name(vrfname);
2558 assert(vrf);
2559 ifp = if_lookup_by_name(ifname, vrf->vrf_id);
2560
2561 if (!ifp)
2562 return NB_OK;
2563
2564 vrf_name = yang_dnode_get_string(args->dnode, NULL);
2565 circuit = circuit_scan_by_ifp(ifp);
2566 if (circuit && circuit->area && circuit->isis
2567 && strcmp(circuit->isis->name, vrf_name)) {
2568 snprintf(args->errmsg, args->errmsg_len,
2569 "ISIS circuit is already defined on vrf %s",
2570 circuit->isis->name);
2571 return NB_ERR_VALIDATION;
2572 }
2573 }
2574
2575 return NB_OK;
2576}
2577
2578/*
2579 * XPath: /frr-interface:lib/interface/frr-isisd:isis/circuit-type
2580 */
2581int lib_interface_isis_circuit_type_modify(struct nb_cb_modify_args *args)
2582{
2583 int circ_type = yang_dnode_get_enum(args->dnode, NULL);
2584 struct isis_circuit *circuit;
2585 struct interface *ifp;
2586 struct vrf *vrf;
2587 const char *ifname, *vrfname;
2588 struct isis *isis = NULL;
2589
2590 switch (args->event) {
2591 case NB_EV_VALIDATE:
2592 /* libyang doesn't like relative paths across module boundaries
2593 */
2594 ifname = yang_dnode_get_string(args->dnode->parent->parent,
2595 "./name");
2596 vrfname = yang_dnode_get_string(args->dnode->parent->parent,
2597 "./vrf");
2598 vrf = vrf_lookup_by_name(vrfname);
2599 assert(vrf);
2600 ifp = if_lookup_by_name(ifname, vrf->vrf_id);
2601 if (!ifp)
2602 break;
2603
2604 isis = isis_lookup_by_vrfid(ifp->vrf_id);
2605 if (isis == NULL)
2606 return NB_ERR_VALIDATION;
2607
2608 circuit = circuit_lookup_by_ifp(ifp, isis->init_circ_list);
2609 if (circuit && circuit->state == C_STATE_UP
2610 && circuit->area->is_type != IS_LEVEL_1_AND_2
2611 && circuit->area->is_type != circ_type) {
2612 snprintf(args->errmsg, args->errmsg_len,
2613 "Invalid circuit level for area %s",
2614 circuit->area->area_tag);
2615 return NB_ERR_VALIDATION;
2616 }
2617 break;
2618 case NB_EV_PREPARE:
2619 case NB_EV_ABORT:
2620 break;
2621 case NB_EV_APPLY:
2622 circuit = nb_running_get_entry(args->dnode, NULL, true);
2623 isis_circuit_is_type_set(circuit, circ_type);
2624 break;
2625 }
2626
2627 return NB_OK;
2628}
2629
2630/*
2631 * XPath: /frr-interface:lib/interface/frr-isisd:isis/ipv4-routing
2632 */
2633int lib_interface_isis_ipv4_routing_modify(struct nb_cb_modify_args *args)
2634{
2635 bool ipv4, ipv6;
2636 struct isis_circuit *circuit;
2637
2638 if (args->event != NB_EV_APPLY)
2639 return NB_OK;
2640
2641 circuit = nb_running_get_entry(args->dnode, NULL, true);
2642 ipv4 = yang_dnode_get_bool(args->dnode, NULL);
2643 ipv6 = yang_dnode_get_bool(args->dnode, "../ipv6-routing");
2644 isis_circuit_af_set(circuit, ipv4, ipv6);
2645
2646 return NB_OK;
2647}
2648
2649/*
2650 * XPath: /frr-interface:lib/interface/frr-isisd:isis/ipv6-routing
2651 */
2652int lib_interface_isis_ipv6_routing_modify(struct nb_cb_modify_args *args)
2653{
2654 bool ipv4, ipv6;
2655 struct isis_circuit *circuit;
2656
2657 if (args->event != NB_EV_APPLY)
2658 return NB_OK;
2659
2660 circuit = nb_running_get_entry(args->dnode, NULL, true);
2661 ipv4 = yang_dnode_get_bool(args->dnode, "../ipv4-routing");
2662 ipv6 = yang_dnode_get_bool(args->dnode, NULL);
2663 isis_circuit_af_set(circuit, ipv4, ipv6);
2664
2665 return NB_OK;
2666}
2667
2668/*
2669 * XPath: /frr-interface:lib/interface/frr-isisd:isis/bfd-monitoring
2670 */
2671void lib_interface_isis_bfd_monitoring_apply_finish(
2672 struct nb_cb_apply_finish_args *args)
2673{
2674 struct isis_circuit *circuit;
2675 bool enabled;
2676 const char *profile = NULL;
2677
2678 circuit = nb_running_get_entry(args->dnode, NULL, true);
2679 enabled = yang_dnode_get_bool(args->dnode, "./enabled");
2680
2681 if (yang_dnode_exists(args->dnode, "./profile"))
2682 profile = yang_dnode_get_string(args->dnode, "./profile");
2683
2684 if (enabled) {
2685 isis_bfd_circuit_param_set(circuit, BFD_DEF_MIN_RX,
2686 BFD_DEF_MIN_TX, BFD_DEF_DETECT_MULT,
2687 profile, true);
2688 } else {
2689 isis_bfd_circuit_cmd(circuit, ZEBRA_BFD_DEST_DEREGISTER);
2690 bfd_info_free(&circuit->bfd_info);
2691 }
2692}
2693
2694/*
2695 * XPath: /frr-interface:lib/interface/frr-isisd:isis/bfd-monitoring/enabled
2696 */
2697int lib_interface_isis_bfd_monitoring_enabled_modify(
2698 struct nb_cb_modify_args *args)
2699{
2700 /* Everything done in apply_finish */
2701 return NB_OK;
2702}
2703
2704/*
2705 * XPath: /frr-interface:lib/interface/frr-isisd:isis/bfd-monitoring/profile
2706 */
2707int lib_interface_isis_bfd_monitoring_profile_modify(
2708 struct nb_cb_modify_args *args)
2709{
2710 /* Everything done in apply_finish */
2711 return NB_OK;
2712}
2713
2714int lib_interface_isis_bfd_monitoring_profile_destroy(
2715 struct nb_cb_destroy_args *args)
2716{
2717 /* Everything done in apply_finish */
2718 return NB_OK;
2719}
2720
2721/*
2722 * XPath: /frr-interface:lib/interface/frr-isisd:isis/csnp-interval/level-1
2723 */
2724int lib_interface_isis_csnp_interval_level_1_modify(
2725 struct nb_cb_modify_args *args)
2726{
2727 struct isis_circuit *circuit;
2728
2729 if (args->event != NB_EV_APPLY)
2730 return NB_OK;
2731
2732 circuit = nb_running_get_entry(args->dnode, NULL, true);
2733 circuit->csnp_interval[0] = yang_dnode_get_uint16(args->dnode, NULL);
2734
2735 return NB_OK;
2736}
2737
2738/*
2739 * XPath: /frr-interface:lib/interface/frr-isisd:isis/csnp-interval/level-2
2740 */
2741int lib_interface_isis_csnp_interval_level_2_modify(
2742 struct nb_cb_modify_args *args)
2743{
2744 struct isis_circuit *circuit;
2745
2746 if (args->event != NB_EV_APPLY)
2747 return NB_OK;
2748
2749 circuit = nb_running_get_entry(args->dnode, NULL, true);
2750 circuit->csnp_interval[1] = yang_dnode_get_uint16(args->dnode, NULL);
2751
2752 return NB_OK;
2753}
2754
2755/*
2756 * XPath: /frr-interface:lib/interface/frr-isisd:isis/psnp-interval/level-1
2757 */
2758int lib_interface_isis_psnp_interval_level_1_modify(
2759 struct nb_cb_modify_args *args)
2760{
2761 struct isis_circuit *circuit;
2762
2763 if (args->event != NB_EV_APPLY)
2764 return NB_OK;
2765
2766 circuit = nb_running_get_entry(args->dnode, NULL, true);
2767 circuit->psnp_interval[0] = yang_dnode_get_uint16(args->dnode, NULL);
2768
2769 return NB_OK;
2770}
2771
2772/*
2773 * XPath: /frr-interface:lib/interface/frr-isisd:isis/psnp-interval/level-2
2774 */
2775int lib_interface_isis_psnp_interval_level_2_modify(
2776 struct nb_cb_modify_args *args)
2777{
2778 struct isis_circuit *circuit;
2779
2780 if (args->event != NB_EV_APPLY)
2781 return NB_OK;
2782
2783 circuit = nb_running_get_entry(args->dnode, NULL, true);
2784 circuit->psnp_interval[1] = yang_dnode_get_uint16(args->dnode, NULL);
2785
2786 return NB_OK;
2787}
2788
2789/*
2790 * XPath: /frr-interface:lib/interface/frr-isisd:isis/hello/padding
2791 */
2792int lib_interface_isis_hello_padding_modify(struct nb_cb_modify_args *args)
2793{
2794 struct isis_circuit *circuit;
2795
2796 if (args->event != NB_EV_APPLY)
2797 return NB_OK;
2798
2799 circuit = nb_running_get_entry(args->dnode, NULL, true);
2800 circuit->pad_hellos = yang_dnode_get_bool(args->dnode, NULL);
2801
2802 return NB_OK;
2803}
2804
2805/*
2806 * XPath: /frr-interface:lib/interface/frr-isisd:isis/hello/interval/level-1
2807 */
2808int lib_interface_isis_hello_interval_level_1_modify(
2809 struct nb_cb_modify_args *args)
2810{
2811 struct isis_circuit *circuit;
2812 uint32_t interval;
2813
2814 if (args->event != NB_EV_APPLY)
2815 return NB_OK;
2816
2817 circuit = nb_running_get_entry(args->dnode, NULL, true);
2818 interval = yang_dnode_get_uint32(args->dnode, NULL);
2819 circuit->hello_interval[0] = interval;
2820
2821 return NB_OK;
2822}
2823
2824/*
2825 * XPath: /frr-interface:lib/interface/frr-isisd:isis/hello/interval/level-2
2826 */
2827int lib_interface_isis_hello_interval_level_2_modify(
2828 struct nb_cb_modify_args *args)
2829{
2830 struct isis_circuit *circuit;
2831 uint32_t interval;
2832
2833 if (args->event != NB_EV_APPLY)
2834 return NB_OK;
2835
2836 circuit = nb_running_get_entry(args->dnode, NULL, true);
2837 interval = yang_dnode_get_uint32(args->dnode, NULL);
2838 circuit->hello_interval[1] = interval;
2839
2840 return NB_OK;
2841}
2842
2843/*
2844 * XPath: /frr-interface:lib/interface/frr-isisd:isis/hello/multiplier/level-1
2845 */
2846int lib_interface_isis_hello_multiplier_level_1_modify(
2847 struct nb_cb_modify_args *args)
2848{
2849 struct isis_circuit *circuit;
2850 uint16_t multi;
2851
2852 if (args->event != NB_EV_APPLY)
2853 return NB_OK;
2854
2855 circuit = nb_running_get_entry(args->dnode, NULL, true);
2856 multi = yang_dnode_get_uint16(args->dnode, NULL);
2857 circuit->hello_multiplier[0] = multi;
2858
2859 return NB_OK;
2860}
2861
2862/*
2863 * XPath: /frr-interface:lib/interface/frr-isisd:isis/hello/multiplier/level-2
2864 */
2865int lib_interface_isis_hello_multiplier_level_2_modify(
2866 struct nb_cb_modify_args *args)
2867{
2868 struct isis_circuit *circuit;
2869 uint16_t multi;
2870
2871 if (args->event != NB_EV_APPLY)
2872 return NB_OK;
2873
2874 circuit = nb_running_get_entry(args->dnode, NULL, true);
2875 multi = yang_dnode_get_uint16(args->dnode, NULL);
2876 circuit->hello_multiplier[1] = multi;
2877
2878 return NB_OK;
2879}
2880
2881/*
2882 * XPath: /frr-interface:lib/interface/frr-isisd:isis/metric/level-1
2883 */
2884int lib_interface_isis_metric_level_1_modify(struct nb_cb_modify_args *args)
2885{
2886 struct isis_circuit *circuit;
2887 unsigned int met;
2888
2889 if (args->event != NB_EV_APPLY)
2890 return NB_OK;
2891
2892 circuit = nb_running_get_entry(args->dnode, NULL, true);
2893 met = yang_dnode_get_uint32(args->dnode, NULL);
2894 isis_circuit_metric_set(circuit, IS_LEVEL_1, met);
2895
2896 return NB_OK;
2897}
2898
2899/*
2900 * XPath: /frr-interface:lib/interface/frr-isisd:isis/metric/level-2
2901 */
2902int lib_interface_isis_metric_level_2_modify(struct nb_cb_modify_args *args)
2903{
2904 struct isis_circuit *circuit;
2905 unsigned int met;
2906
2907 if (args->event != NB_EV_APPLY)
2908 return NB_OK;
2909
2910 circuit = nb_running_get_entry(args->dnode, NULL, true);
2911 met = yang_dnode_get_uint32(args->dnode, NULL);
2912 isis_circuit_metric_set(circuit, IS_LEVEL_2, met);
2913
2914 return NB_OK;
2915}
2916
2917/*
2918 * XPath: /frr-interface:lib/interface/frr-isisd:isis/priority/level-1
2919 */
2920int lib_interface_isis_priority_level_1_modify(struct nb_cb_modify_args *args)
2921{
2922 struct isis_circuit *circuit;
2923
2924 if (args->event != NB_EV_APPLY)
2925 return NB_OK;
2926
2927 circuit = nb_running_get_entry(args->dnode, NULL, true);
2928 circuit->priority[0] = yang_dnode_get_uint8(args->dnode, NULL);
2929
2930 return NB_OK;
2931}
2932
2933/*
2934 * XPath: /frr-interface:lib/interface/frr-isisd:isis/priority/level-2
2935 */
2936int lib_interface_isis_priority_level_2_modify(struct nb_cb_modify_args *args)
2937{
2938 struct isis_circuit *circuit;
2939
2940 if (args->event != NB_EV_APPLY)
2941 return NB_OK;
2942
2943 circuit = nb_running_get_entry(args->dnode, NULL, true);
2944 circuit->priority[1] = yang_dnode_get_uint8(args->dnode, NULL);
2945
2946 return NB_OK;
2947}
2948
2949/*
2950 * XPath: /frr-interface:lib/interface/frr-isisd:isis/network-type
2951 */
2952int lib_interface_isis_network_type_modify(struct nb_cb_modify_args *args)
2953{
2954 struct isis_circuit *circuit;
2955 int net_type = yang_dnode_get_enum(args->dnode, NULL);
2956
2957 switch (args->event) {
2958 case NB_EV_VALIDATE:
2959 circuit = nb_running_get_entry(args->dnode, NULL, false);
2960 if (!circuit)
2961 break;
2962 if (circuit->circ_type == CIRCUIT_T_LOOPBACK) {
2963 snprintf(
2964 args->errmsg, args->errmsg_len,
2965 "Cannot change network type on loopback interface");
2966 return NB_ERR_VALIDATION;
2967 }
2968 if (net_type == CIRCUIT_T_BROADCAST
2969 && circuit->state == C_STATE_UP
2970 && !if_is_broadcast(circuit->interface)) {
2971 snprintf(
2972 args->errmsg, args->errmsg_len,
2973 "Cannot configure non-broadcast interface for broadcast operation");
2974 return NB_ERR_VALIDATION;
2975 }
2976 break;
2977 case NB_EV_PREPARE:
2978 case NB_EV_ABORT:
2979 break;
2980 case NB_EV_APPLY:
2981 circuit = nb_running_get_entry(args->dnode, NULL, true);
2982 isis_circuit_circ_type_set(circuit, net_type);
2983 break;
2984 }
2985
2986 return NB_OK;
2987}
2988
2989/*
2990 * XPath: /frr-interface:lib/interface/frr-isisd:isis/passive
2991 */
2992int lib_interface_isis_passive_modify(struct nb_cb_modify_args *args)
2993{
2994 struct isis_circuit *circuit;
2995 struct isis_area *area;
2996 struct interface *ifp;
2997 bool passive = yang_dnode_get_bool(args->dnode, NULL);
2998
2999 /* validation only applies if we are setting passive to false */
3000 if (!passive && args->event == NB_EV_VALIDATE) {
3001 circuit = nb_running_get_entry(args->dnode, NULL, false);
3002 if (!circuit)
3003 return NB_OK;
3004 ifp = circuit->interface;
3005 if (!ifp)
3006 return NB_OK;
3007 if (if_is_loopback(ifp)) {
3008 snprintf(args->errmsg, args->errmsg_len,
3009 "Loopback is always passive");
3010 return NB_ERR_VALIDATION;
3011 }
3012 }
3013
3014 if (args->event != NB_EV_APPLY)
3015 return NB_OK;
3016
3017 circuit = nb_running_get_entry(args->dnode, NULL, true);
3018 if (circuit->state != C_STATE_UP) {
3019 circuit->is_passive = passive;
3020 } else {
3021 area = circuit->area;
3022 isis_csm_state_change(ISIS_DISABLE, circuit, area);
3023 circuit->is_passive = passive;
3024 isis_csm_state_change(ISIS_ENABLE, circuit, area);
3025 }
3026
3027 return NB_OK;
3028}
3029
3030/*
3031 * XPath: /frr-interface:lib/interface/frr-isisd:isis/password
3032 */
3033int lib_interface_isis_password_create(struct nb_cb_create_args *args)
3034{
3035 return NB_OK;
3036}
3037
3038int lib_interface_isis_password_destroy(struct nb_cb_destroy_args *args)
3039{
3040 struct isis_circuit *circuit;
3041
3042 if (args->event != NB_EV_APPLY)
3043 return NB_OK;
3044
3045 circuit = nb_running_get_entry(args->dnode, NULL, true);
3046 isis_circuit_passwd_unset(circuit);
3047
3048 return NB_OK;
3049}
3050
3051/*
3052 * XPath: /frr-interface:lib/interface/frr-isisd:isis/password/password
3053 */
3054int lib_interface_isis_password_password_modify(struct nb_cb_modify_args *args)
3055{
3056 struct isis_circuit *circuit;
3057 const char *password;
3058
3059 if (args->event != NB_EV_APPLY)
3060 return NB_OK;
3061
3062 password = yang_dnode_get_string(args->dnode, NULL);
3063 circuit = nb_running_get_entry(args->dnode, NULL, true);
3064
3065 isis_circuit_passwd_set(circuit, circuit->passwd.type, password);
3066
3067 return NB_OK;
3068}
3069
3070/*
3071 * XPath: /frr-interface:lib/interface/frr-isisd:isis/password/password-type
3072 */
3073int lib_interface_isis_password_password_type_modify(
3074 struct nb_cb_modify_args *args)
3075{
3076 struct isis_circuit *circuit;
3077 uint8_t pass_type;
3078
3079 if (args->event != NB_EV_APPLY)
3080 return NB_OK;
3081
3082 pass_type = yang_dnode_get_enum(args->dnode, NULL);
3083 circuit = nb_running_get_entry(args->dnode, NULL, true);
3084 circuit->passwd.type = pass_type;
3085
3086 return NB_OK;
3087}
3088
3089/*
3090 * XPath:
3091 * /frr-interface:lib/interface/frr-isisd:isis/disable-three-way-handshake
3092 */
3093int lib_interface_isis_disable_three_way_handshake_modify(
3094 struct nb_cb_modify_args *args)
3095{
3096 struct isis_circuit *circuit;
3097
3098 if (args->event != NB_EV_APPLY)
3099 return NB_OK;
3100
3101 circuit = nb_running_get_entry(args->dnode, NULL, true);
3102 circuit->disable_threeway_adj = yang_dnode_get_bool(args->dnode, NULL);
3103
3104 return NB_OK;
3105}
3106
3107/*
3108 * XPath:
3109 * /frr-interface:lib/interface/frr-isisd:isis/multi-topology/ipv4-unicast
3110 */
3111static int lib_interface_isis_multi_topology_common(
3112 enum nb_event event, const struct lyd_node *dnode, char *errmsg,
3113 size_t errmsg_len, uint16_t mtid)
3114{
3115 struct isis_circuit *circuit;
3116 bool value;
3117
3118 switch (event) {
3119 case NB_EV_VALIDATE:
3120 circuit = nb_running_get_entry(dnode, NULL, false);
3121 if (circuit && circuit->area && circuit->area->oldmetric) {
3122 snprintf(
3123 errmsg, errmsg_len,
3124 "Multi topology IS-IS can only be used with wide metrics");
3125 return NB_ERR_VALIDATION;
3126 }
3127 break;
3128 case NB_EV_PREPARE:
3129 case NB_EV_ABORT:
3130 break;
3131 case NB_EV_APPLY:
3132 circuit = nb_running_get_entry(dnode, NULL, true);
3133 value = yang_dnode_get_bool(dnode, NULL);
3134 isis_circuit_mt_enabled_set(circuit, mtid, value);
3135 break;
3136 }
3137
3138 return NB_OK;
3139}
3140
3141int lib_interface_isis_multi_topology_ipv4_unicast_modify(
3142 struct nb_cb_modify_args *args)
3143{
3144 return lib_interface_isis_multi_topology_common(
3145 args->event, args->dnode, args->errmsg, args->errmsg_len,
3146 ISIS_MT_IPV4_UNICAST);
3147}
3148
3149/*
3150 * XPath:
3151 * /frr-interface:lib/interface/frr-isisd:isis/multi-topology/ipv4-multicast
3152 */
3153int lib_interface_isis_multi_topology_ipv4_multicast_modify(
3154 struct nb_cb_modify_args *args)
3155{
3156 return lib_interface_isis_multi_topology_common(
3157 args->event, args->dnode, args->errmsg, args->errmsg_len,
3158 ISIS_MT_IPV4_MULTICAST);
3159}
3160
3161/*
3162 * XPath:
3163 * /frr-interface:lib/interface/frr-isisd:isis/multi-topology/ipv4-management
3164 */
3165int lib_interface_isis_multi_topology_ipv4_management_modify(
3166 struct nb_cb_modify_args *args)
3167{
3168 return lib_interface_isis_multi_topology_common(
3169 args->event, args->dnode, args->errmsg, args->errmsg_len,
3170 ISIS_MT_IPV4_MGMT);
3171}
3172
3173/*
3174 * XPath:
3175 * /frr-interface:lib/interface/frr-isisd:isis/multi-topology/ipv6-unicast
3176 */
3177int lib_interface_isis_multi_topology_ipv6_unicast_modify(
3178 struct nb_cb_modify_args *args)
3179{
3180 return lib_interface_isis_multi_topology_common(
3181 args->event, args->dnode, args->errmsg, args->errmsg_len,
3182 ISIS_MT_IPV6_UNICAST);
3183}
3184
3185/*
3186 * XPath:
3187 * /frr-interface:lib/interface/frr-isisd:isis/multi-topology/ipv6-multicast
3188 */
3189int lib_interface_isis_multi_topology_ipv6_multicast_modify(
3190 struct nb_cb_modify_args *args)
3191{
3192 return lib_interface_isis_multi_topology_common(
3193 args->event, args->dnode, args->errmsg, args->errmsg_len,
3194 ISIS_MT_IPV6_MULTICAST);
3195}
3196
3197/*
3198 * XPath:
3199 * /frr-interface:lib/interface/frr-isisd:isis/multi-topology/ipv6-management
3200 */
3201int lib_interface_isis_multi_topology_ipv6_management_modify(
3202 struct nb_cb_modify_args *args)
3203{
3204 return lib_interface_isis_multi_topology_common(
3205 args->event, args->dnode, args->errmsg, args->errmsg_len,
3206 ISIS_MT_IPV6_MGMT);
3207}
3208
3209/*
3210 * XPath: /frr-interface:lib/interface/frr-isisd:isis/multi-topology/ipv6-dstsrc
3211 */
3212int lib_interface_isis_multi_topology_ipv6_dstsrc_modify(
3213 struct nb_cb_modify_args *args)
3214{
3215 return lib_interface_isis_multi_topology_common(
3216 args->event, args->dnode, args->errmsg, args->errmsg_len,
3217 ISIS_MT_IPV6_DSTSRC);
3218}
3219
3220/*
3221 * XPath: /frr-interface:lib/interface/frr-isisd:isis/mpls/ldp-sync
3222 */
3223int lib_interface_isis_mpls_ldp_sync_modify(struct nb_cb_modify_args *args)
3224{
3225 struct isis_circuit *circuit;
3226 struct ldp_sync_info *ldp_sync_info;
3227 bool ldp_sync_enable;
3228 struct isis *isis;
3229
3230 switch (args->event) {
3231 case NB_EV_VALIDATE:
3232 circuit = nb_running_get_entry(args->dnode, NULL, false);
3233 if (circuit == NULL || circuit->area == NULL)
3234 return NB_ERR_VALIDATION;
3235
3236 if (circuit->isis->vrf_id != VRF_DEFAULT) {
3237 snprintf(args->errmsg, args->errmsg_len,
3238 "LDP-Sync only runs on Default VRF");
3239 return NB_ERR_VALIDATION;
3240 }
3241 break;
3242 case NB_EV_PREPARE:
3243 case NB_EV_ABORT:
3244 break;
3245 case NB_EV_APPLY:
3246 circuit = nb_running_get_entry(args->dnode, NULL, true);
3247 ldp_sync_enable = yang_dnode_get_bool(args->dnode, NULL);
3248 isis = circuit->isis;
3249
3250 if (circuit->ldp_sync_info == NULL)
3251 isis_ldp_sync_if_init(circuit, isis);
3252 assert(circuit->ldp_sync_info != NULL);
3253 ldp_sync_info = circuit->ldp_sync_info;
3254
3255 if (ldp_sync_enable) {
3256 /* enable LDP-SYNC on an interface
3257 * if ptop interface send message to LDP to get state
3258 */
3259 SET_FLAG(ldp_sync_info->flags, LDP_SYNC_FLAG_IF_CONFIG);
3260 ldp_sync_info->enabled = LDP_IGP_SYNC_ENABLED;
3261 if (circuit->circ_type == CIRCUIT_T_P2P) {
3262 ldp_sync_info->state =
3263 LDP_IGP_SYNC_STATE_REQUIRED_NOT_UP;
3264 isis_ldp_sync_state_req_msg(circuit);
3265 } else {
3266 zlog_debug("ldp_sync: only runs on P2P links %s",
3267 circuit->interface->name);
3268 ldp_sync_info->state =
3269 LDP_IGP_SYNC_STATE_NOT_REQUIRED;
3270 }
3271 } else {
3272 /* disable LDP-SYNC on an interface
3273 * stop holddown timer if running
3274 * restore isis metric
3275 */
3276 SET_FLAG(ldp_sync_info->flags, LDP_SYNC_FLAG_IF_CONFIG);
3277 ldp_sync_info->enabled = LDP_IGP_SYNC_DEFAULT;
3278 ldp_sync_info->state = LDP_IGP_SYNC_STATE_NOT_REQUIRED;
3279 THREAD_OFF(ldp_sync_info->t_holddown);
3280 isis_ldp_sync_set_if_metric(circuit, true);
3281 }
3282 break;
3283 }
3284 return NB_OK;
3285}
3286
3287/*
3288 * XPath: /frr-interface:lib/interface/frr-isisd:isis/mpls/holddown
3289 */
3290int lib_interface_isis_mpls_holddown_modify(struct nb_cb_modify_args *args)
3291{
3292 struct isis_circuit *circuit;
3293 struct ldp_sync_info *ldp_sync_info;
3294 uint16_t holddown;
3295 struct isis *isis;
3296
3297 switch (args->event) {
3298 case NB_EV_VALIDATE:
3299 circuit = nb_running_get_entry(args->dnode, NULL, false);
3300 if (circuit == NULL || circuit->area == NULL)
3301 return NB_ERR_VALIDATION;
3302
3303 if (circuit->isis->vrf_id != VRF_DEFAULT) {
3304 snprintf(args->errmsg, args->errmsg_len,
3305 "LDP-Sync only runs on Default VRF");
3306 return NB_ERR_VALIDATION;
3307 }
3308 break;
3309 case NB_EV_PREPARE:
3310 case NB_EV_ABORT:
3311 break;
3312 case NB_EV_APPLY:
3313 circuit = nb_running_get_entry(args->dnode, NULL, true);
3314 holddown = yang_dnode_get_uint16(args->dnode, NULL);
3315 isis = circuit->isis;
3316
3317 if (circuit->ldp_sync_info == NULL)
3318 isis_ldp_sync_if_init(circuit, isis);
3319 assert(circuit->ldp_sync_info != NULL);
3320 ldp_sync_info = circuit->ldp_sync_info;
3321
3322 SET_FLAG(ldp_sync_info->flags, LDP_SYNC_FLAG_HOLDDOWN);
3323 ldp_sync_info->holddown = holddown;
3324 break;
3325 }
3326 return NB_OK;
3327}
3328
3329int lib_interface_isis_mpls_holddown_destroy(struct nb_cb_destroy_args *args)
3330{
3331 struct isis_circuit *circuit;
3332 struct ldp_sync_info *ldp_sync_info;
3333 struct isis *isis;
3334
3335 switch (args->event) {
3336 case NB_EV_VALIDATE:
3337 circuit = nb_running_get_entry(args->dnode, NULL, false);
3338 if (circuit == NULL || circuit->ldp_sync_info == NULL
3339 || circuit->area == NULL)
3340 return NB_ERR_VALIDATION;
3341
3342 if (circuit->isis->vrf_id != VRF_DEFAULT) {
3343 snprintf(args->errmsg, args->errmsg_len,
3344 "LDP-Sync only runs on Default VRF");
3345 return NB_ERR_VALIDATION;
3346 }
3347 break;
3348 case NB_EV_PREPARE:
3349 case NB_EV_ABORT:
3350 break;
3351 case NB_EV_APPLY:
3352 circuit = nb_running_get_entry(args->dnode, NULL, true);
3353 isis = circuit->isis;
3354 ldp_sync_info = circuit->ldp_sync_info;
3355 UNSET_FLAG(ldp_sync_info->flags, LDP_SYNC_FLAG_HOLDDOWN);
3356
3357 if (CHECK_FLAG(isis->ldp_sync_cmd.flags,
3358 LDP_SYNC_FLAG_HOLDDOWN))
3359 ldp_sync_info->holddown = isis->ldp_sync_cmd.holddown;
3360 else
3361 ldp_sync_info->holddown = LDP_IGP_SYNC_HOLDDOWN_DEFAULT;
3362 break;
3363 }
3364
3365 return NB_OK;
3366}
3367
3368/*
3369 * XPath:
3370 * /frr-interface:lib/interface/frr-isisd:isis/fast-reroute/level-1/lfa/enable
3371 */
3372int lib_interface_isis_fast_reroute_level_1_lfa_enable_modify(
3373 struct nb_cb_modify_args *args)
3374{
3375 struct isis_area *area;
3376 struct isis_circuit *circuit;
3377
3378 if (args->event != NB_EV_APPLY)
3379 return NB_OK;
3380
3381 circuit = nb_running_get_entry(args->dnode, NULL, true);
3382 circuit->lfa_protection[0] = yang_dnode_get_bool(args->dnode, NULL);
3383 if (circuit->lfa_protection[0])
3384 circuit->area->lfa_protected_links[0]++;
3385 else {
3386 assert(circuit->area->lfa_protected_links[0] > 0);
3387 circuit->area->lfa_protected_links[0]--;
3388 }
3389
3390 area = circuit->area;
3391 lsp_regenerate_schedule(area, area->is_type, 0);
3392
3393 return NB_OK;
3394}
3395
3396/*
3397 * XPath:
3398 * /frr-interface:lib/interface/frr-isisd:isis/fast-reroute/level-1/lfa/exclude-interface
3399 */
3400int lib_interface_isis_fast_reroute_level_1_lfa_exclude_interface_create(
3401 struct nb_cb_create_args *args)
3402{
3403 struct isis_area *area;
3404 struct isis_circuit *circuit;
3405 const char *exclude_ifname;
3406
3407 if (args->event != NB_EV_APPLY)
3408 return NB_OK;
3409
3410 circuit = nb_running_get_entry(args->dnode, NULL, true);
3411 exclude_ifname = yang_dnode_get_string(args->dnode, NULL);
3412
3413 isis_lfa_excluded_iface_add(circuit, ISIS_LEVEL1, exclude_ifname);
3414 area = circuit->area;
3415 lsp_regenerate_schedule(area, area->is_type, 0);
3416
3417 return NB_OK;
3418}
3419
3420int lib_interface_isis_fast_reroute_level_1_lfa_exclude_interface_destroy(
3421 struct nb_cb_destroy_args *args)
3422{
3423 struct isis_area *area;
3424 struct isis_circuit *circuit;
3425 const char *exclude_ifname;
3426
3427 if (args->event != NB_EV_APPLY)
3428 return NB_OK;
3429
3430 circuit = nb_running_get_entry(args->dnode, NULL, true);
3431 exclude_ifname = yang_dnode_get_string(args->dnode, NULL);
3432
3433 isis_lfa_excluded_iface_delete(circuit, ISIS_LEVEL1, exclude_ifname);
3434 area = circuit->area;
3435 lsp_regenerate_schedule(area, area->is_type, 0);
3436
3437 return NB_OK;
3438}
3439
3440/*
3441 * XPath:
3442 * /frr-interface:lib/interface/frr-isisd:isis/fast-reroute/level-1/ti-lfa/enable
3443 */
3444int lib_interface_isis_fast_reroute_level_1_ti_lfa_enable_modify(
3445 struct nb_cb_modify_args *args)
3446{
3447 struct isis_area *area;
3448 struct isis_circuit *circuit;
3449
3450 if (args->event != NB_EV_APPLY)
3451 return NB_OK;
3452
3453 circuit = nb_running_get_entry(args->dnode, NULL, true);
3454 circuit->tilfa_protection[0] = yang_dnode_get_bool(args->dnode, NULL);
3455 if (circuit->tilfa_protection[0])
3456 circuit->area->tilfa_protected_links[0]++;
3457 else {
3458 assert(circuit->area->tilfa_protected_links[0] > 0);
3459 circuit->area->tilfa_protected_links[0]--;
3460 }
3461
3462 area = circuit->area;
3463 lsp_regenerate_schedule(area, area->is_type, 0);
3464
3465 return NB_OK;
3466}
3467
3468/*
3469 * XPath:
3470 * /frr-interface:lib/interface/frr-isisd:isis/fast-reroute/level-1/ti-lfa/node-protection
3471 */
3472int lib_interface_isis_fast_reroute_level_1_ti_lfa_node_protection_modify(
3473 struct nb_cb_modify_args *args)
3474{
3475 struct isis_area *area;
3476 struct isis_circuit *circuit;
3477
3478 if (args->event != NB_EV_APPLY)
3479 return NB_OK;
3480
3481 circuit = nb_running_get_entry(args->dnode, NULL, true);
3482 circuit->tilfa_node_protection[0] =
3483 yang_dnode_get_bool(args->dnode, NULL);
3484
3485 area = circuit->area;
3486 lsp_regenerate_schedule(area, area->is_type, 0);
3487
3488 return NB_OK;
3489}
3490
3491/*
3492 * XPath:
3493 * /frr-interface:lib/interface/frr-isisd:isis/fast-reroute/level-2/lfa/enable
3494 */
3495int lib_interface_isis_fast_reroute_level_2_lfa_enable_modify(
3496 struct nb_cb_modify_args *args)
3497{
3498 struct isis_area *area;
3499 struct isis_circuit *circuit;
3500
3501 if (args->event != NB_EV_APPLY)
3502 return NB_OK;
3503
3504 circuit = nb_running_get_entry(args->dnode, NULL, true);
3505 circuit->lfa_protection[1] = yang_dnode_get_bool(args->dnode, NULL);
3506 if (circuit->lfa_protection[1])
3507 circuit->area->lfa_protected_links[1]++;
3508 else {
3509 assert(circuit->area->lfa_protected_links[1] > 0);
3510 circuit->area->lfa_protected_links[1]--;
3511 }
3512
3513 area = circuit->area;
3514 lsp_regenerate_schedule(area, area->is_type, 0);
3515
3516 return NB_OK;
3517}
3518
3519/*
3520 * XPath:
3521 * /frr-interface:lib/interface/frr-isisd:isis/fast-reroute/level-2/lfa/exclude-interface
3522 */
3523int lib_interface_isis_fast_reroute_level_2_lfa_exclude_interface_create(
3524 struct nb_cb_create_args *args)
3525{
3526 struct isis_area *area;
3527 struct isis_circuit *circuit;
3528 const char *exclude_ifname;
3529
3530 if (args->event != NB_EV_APPLY)
3531 return NB_OK;
3532
3533 circuit = nb_running_get_entry(args->dnode, NULL, true);
3534 exclude_ifname = yang_dnode_get_string(args->dnode, NULL);
3535
3536 isis_lfa_excluded_iface_add(circuit, ISIS_LEVEL2, exclude_ifname);
3537 area = circuit->area;
3538 lsp_regenerate_schedule(area, area->is_type, 0);
3539
3540 return NB_OK;
3541}
3542
3543int lib_interface_isis_fast_reroute_level_2_lfa_exclude_interface_destroy(
3544 struct nb_cb_destroy_args *args)
3545{
3546 struct isis_area *area;
3547 struct isis_circuit *circuit;
3548 const char *exclude_ifname;
3549
3550 if (args->event != NB_EV_APPLY)
3551 return NB_OK;
3552
3553 circuit = nb_running_get_entry(args->dnode, NULL, true);
3554 exclude_ifname = yang_dnode_get_string(args->dnode, NULL);
3555
3556 isis_lfa_excluded_iface_delete(circuit, ISIS_LEVEL2, exclude_ifname);
3557 area = circuit->area;
3558 lsp_regenerate_schedule(area, area->is_type, 0);
3559
3560 return NB_OK;
3561}
3562
3563/*
3564 * XPath:
3565 * /frr-interface:lib/interface/frr-isisd:isis/fast-reroute/level-2/ti-lfa/enable
3566 */
3567int lib_interface_isis_fast_reroute_level_2_ti_lfa_enable_modify(
3568 struct nb_cb_modify_args *args)
3569{
3570 struct isis_area *area;
3571 struct isis_circuit *circuit;
3572
3573 if (args->event != NB_EV_APPLY)
3574 return NB_OK;
3575
3576 circuit = nb_running_get_entry(args->dnode, NULL, true);
3577 circuit->tilfa_protection[1] = yang_dnode_get_bool(args->dnode, NULL);
3578 if (circuit->tilfa_protection[1])
3579 circuit->area->tilfa_protected_links[1]++;
3580 else {
3581 assert(circuit->area->tilfa_protected_links[1] > 0);
3582 circuit->area->tilfa_protected_links[1]--;
3583 }
3584
3585 area = circuit->area;
3586 lsp_regenerate_schedule(area, area->is_type, 0);
3587
3588 return NB_OK;
3589}
3590
3591/*
3592 * XPath:
3593 * /frr-interface:lib/interface/frr-isisd:isis/fast-reroute/level-2/ti-lfa/node-protection
3594 */
3595int lib_interface_isis_fast_reroute_level_2_ti_lfa_node_protection_modify(
3596 struct nb_cb_modify_args *args)
3597{
3598 struct isis_area *area;
3599 struct isis_circuit *circuit;
3600
3601 if (args->event != NB_EV_APPLY)
3602 return NB_OK;
3603
3604 circuit = nb_running_get_entry(args->dnode, NULL, true);
3605 circuit->tilfa_node_protection[1] =
3606 yang_dnode_get_bool(args->dnode, NULL);
3607
3608 area = circuit->area;
3609 lsp_regenerate_schedule(area, area->is_type, 0);
3610
3611 return NB_OK;
3612}