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