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