]> git.proxmox.com Git - mirror_frr.git/blob - isisd/isis_nb_config.c
Merge pull request #6437 from opensourcerouting/bfd-profiles-bgp
[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 "northbound.h"
26 #include "linklist.h"
27 #include "log.h"
28 #include "bfd.h"
29 #include "spf_backoff.h"
30 #include "lib_errors.h"
31 #include "vrf.h"
32
33 #include "isisd/isisd.h"
34 #include "isisd/isis_nb.h"
35 #include "isisd/isis_common.h"
36 #include "isisd/isis_bfd.h"
37 #include "isisd/isis_circuit.h"
38 #include "isisd/isis_lsp.h"
39 #include "isisd/isis_dynhn.h"
40 #include "isisd/isis_misc.h"
41 #include "isisd/isis_csm.h"
42 #include "isisd/isis_adjacency.h"
43 #include "isisd/isis_spf.h"
44 #include "isisd/isis_te.h"
45 #include "isisd/isis_memory.h"
46 #include "isisd/isis_mt.h"
47 #include "isisd/isis_redist.h"
48
49 /*
50 * XPath: /frr-isisd:isis/instance
51 */
52 int isis_instance_create(struct nb_cb_create_args *args)
53 {
54 struct isis_area *area;
55 const char *area_tag;
56
57 if (args->event != NB_EV_APPLY)
58 return NB_OK;
59
60 area_tag = yang_dnode_get_string(args->dnode, "./area-tag");
61 area = isis_area_lookup(area_tag);
62 if (area)
63 return NB_ERR_INCONSISTENCY;
64
65 area = isis_area_create(area_tag);
66 /* save area in dnode to avoid looking it up all the time */
67 nb_running_set_entry(args->dnode, area);
68
69 return NB_OK;
70 }
71
72 int isis_instance_destroy(struct nb_cb_destroy_args *args)
73 {
74 struct isis_area *area;
75
76 if (args->event != NB_EV_APPLY)
77 return NB_OK;
78
79 area = nb_running_unset_entry(args->dnode);
80 isis_area_destroy(area->area_tag);
81
82 return NB_OK;
83 }
84
85 /*
86 * XPath: /frr-isisd:isis/instance/is-type
87 */
88 int isis_instance_is_type_modify(struct nb_cb_modify_args *args)
89 {
90 struct isis_area *area;
91 int type;
92
93 if (args->event != NB_EV_APPLY)
94 return NB_OK;
95
96 area = nb_running_get_entry(args->dnode, NULL, true);
97 type = yang_dnode_get_enum(args->dnode, NULL);
98 isis_area_is_type_set(area, type);
99
100 return NB_OK;
101 }
102
103 /*
104 * XPath: /frr-isisd:isis/instance/area-address
105 */
106 int isis_instance_area_address_create(struct nb_cb_create_args *args)
107 {
108 struct isis_area *area;
109 struct area_addr addr, *addrr = NULL, *addrp = NULL;
110 struct listnode *node;
111 uint8_t buff[255];
112 const char *net_title = yang_dnode_get_string(args->dnode, NULL);
113
114 switch (args->event) {
115 case NB_EV_VALIDATE:
116 addr.addr_len = dotformat2buff(buff, net_title);
117 memcpy(addr.area_addr, buff, addr.addr_len);
118 if (addr.area_addr[addr.addr_len - 1] != 0) {
119 snprintf(
120 args->errmsg, args->errmsg_len,
121 "nsel byte (last byte) in area address must be 0");
122 return NB_ERR_VALIDATION;
123 }
124 if (isis->sysid_set) {
125 /* Check that the SystemID portions match */
126 if (memcmp(isis->sysid, GETSYSID((&addr)),
127 ISIS_SYS_ID_LEN)) {
128 snprintf(
129 args->errmsg, args->errmsg_len,
130 "System ID must not change when defining additional area addresses");
131 return NB_ERR_VALIDATION;
132 }
133 }
134 break;
135 case NB_EV_PREPARE:
136 addrr = XMALLOC(MTYPE_ISIS_AREA_ADDR, sizeof(struct area_addr));
137 addrr->addr_len = dotformat2buff(buff, net_title);
138 memcpy(addrr->area_addr, buff, addrr->addr_len);
139 args->resource->ptr = addrr;
140 break;
141 case NB_EV_ABORT:
142 XFREE(MTYPE_ISIS_AREA_ADDR, args->resource->ptr);
143 break;
144 case NB_EV_APPLY:
145 area = nb_running_get_entry(args->dnode, NULL, true);
146 addrr = args->resource->ptr;
147
148 if (isis->sysid_set == 0) {
149 /*
150 * First area address - get the SystemID for this router
151 */
152 memcpy(isis->sysid, GETSYSID(addrr), ISIS_SYS_ID_LEN);
153 isis->sysid_set = 1;
154 } else {
155 /* check that we don't already have this address */
156 for (ALL_LIST_ELEMENTS_RO(area->area_addrs, node,
157 addrp)) {
158 if ((addrp->addr_len + ISIS_SYS_ID_LEN
159 + ISIS_NSEL_LEN)
160 != (addrr->addr_len))
161 continue;
162 if (!memcmp(addrp->area_addr, addrr->area_addr,
163 addrr->addr_len)) {
164 XFREE(MTYPE_ISIS_AREA_ADDR, addrr);
165 return NB_OK; /* silent fail */
166 }
167 }
168 }
169
170 /*Forget the systemID part of the address */
171 addrr->addr_len -= (ISIS_SYS_ID_LEN + ISIS_NSEL_LEN);
172 assert(area->area_addrs); /* to silence scan-build sillyness */
173 listnode_add(area->area_addrs, addrr);
174
175 /* only now we can safely generate our LSPs for this area */
176 if (listcount(area->area_addrs) > 0) {
177 if (area->is_type & IS_LEVEL_1)
178 lsp_generate(area, IS_LEVEL_1);
179 if (area->is_type & IS_LEVEL_2)
180 lsp_generate(area, IS_LEVEL_2);
181 }
182 break;
183 }
184
185 return NB_OK;
186 }
187
188 int isis_instance_area_address_destroy(struct nb_cb_destroy_args *args)
189 {
190 struct area_addr addr, *addrp = NULL;
191 struct listnode *node;
192 uint8_t buff[255];
193 struct isis_area *area;
194 const char *net_title;
195
196 if (args->event != NB_EV_APPLY)
197 return NB_OK;
198
199 net_title = yang_dnode_get_string(args->dnode, NULL);
200 addr.addr_len = dotformat2buff(buff, net_title);
201 memcpy(addr.area_addr, buff, (int)addr.addr_len);
202 area = nb_running_get_entry(args->dnode, NULL, true);
203 for (ALL_LIST_ELEMENTS_RO(area->area_addrs, node, addrp)) {
204 if ((addrp->addr_len + ISIS_SYS_ID_LEN + 1) == addr.addr_len
205 && !memcmp(addrp->area_addr, addr.area_addr, addr.addr_len))
206 break;
207 }
208 if (!addrp)
209 return NB_ERR_INCONSISTENCY;
210
211 listnode_delete(area->area_addrs, addrp);
212 XFREE(MTYPE_ISIS_AREA_ADDR, addrp);
213 /*
214 * Last area address - reset the SystemID for this router
215 */
216 if (listcount(area->area_addrs) == 0) {
217 memset(isis->sysid, 0, ISIS_SYS_ID_LEN);
218 isis->sysid_set = 0;
219 if (IS_DEBUG_EVENTS)
220 zlog_debug("Router has no SystemID");
221 }
222
223 return NB_OK;
224 }
225
226 /*
227 * XPath: /frr-isisd:isis/instance/dynamic-hostname
228 */
229 int isis_instance_dynamic_hostname_modify(struct nb_cb_modify_args *args)
230 {
231 struct isis_area *area;
232
233 if (args->event != NB_EV_APPLY)
234 return NB_OK;
235
236 area = nb_running_get_entry(args->dnode, NULL, true);
237 isis_area_dynhostname_set(area, yang_dnode_get_bool(args->dnode, NULL));
238
239 return NB_OK;
240 }
241
242 /*
243 * XPath: /frr-isisd:isis/instance/attached
244 */
245 int isis_instance_attached_modify(struct nb_cb_modify_args *args)
246 {
247 struct isis_area *area;
248 bool attached;
249
250 if (args->event != NB_EV_APPLY)
251 return NB_OK;
252
253 area = nb_running_get_entry(args->dnode, NULL, true);
254 attached = yang_dnode_get_bool(args->dnode, NULL);
255 isis_area_attached_bit_set(area, attached);
256
257 return NB_OK;
258 }
259
260 /*
261 * XPath: /frr-isisd:isis/instance/overload
262 */
263 int isis_instance_overload_modify(struct nb_cb_modify_args *args)
264 {
265 struct isis_area *area;
266 bool overload;
267
268 if (args->event != NB_EV_APPLY)
269 return NB_OK;
270
271 area = nb_running_get_entry(args->dnode, NULL, true);
272 overload = yang_dnode_get_bool(args->dnode, NULL);
273 isis_area_overload_bit_set(area, overload);
274
275 return NB_OK;
276 }
277
278 /*
279 * XPath: /frr-isisd:isis/instance/metric-style
280 */
281 int isis_instance_metric_style_modify(struct nb_cb_modify_args *args)
282 {
283 struct isis_area *area;
284 bool old_metric, new_metric;
285 enum isis_metric_style metric_style =
286 yang_dnode_get_enum(args->dnode, NULL);
287
288 if (args->event != NB_EV_APPLY)
289 return NB_OK;
290
291 area = nb_running_get_entry(args->dnode, NULL, true);
292 old_metric = (metric_style == ISIS_WIDE_METRIC) ? false : true;
293 new_metric = (metric_style == ISIS_NARROW_METRIC) ? false : true;
294 isis_area_metricstyle_set(area, old_metric, new_metric);
295
296 return NB_OK;
297 }
298
299 /*
300 * XPath: /frr-isisd:isis/instance/purge-originator
301 */
302 int isis_instance_purge_originator_modify(struct nb_cb_modify_args *args)
303 {
304 struct isis_area *area;
305
306 if (args->event != NB_EV_APPLY)
307 return NB_OK;
308
309 area = nb_running_get_entry(args->dnode, NULL, true);
310 area->purge_originator = yang_dnode_get_bool(args->dnode, NULL);
311
312 return NB_OK;
313 }
314
315 /*
316 * XPath: /frr-isisd:isis/instance/lsp/mtu
317 */
318 int isis_instance_lsp_mtu_modify(struct nb_cb_modify_args *args)
319 {
320 struct listnode *node;
321 struct isis_circuit *circuit;
322 uint16_t lsp_mtu = yang_dnode_get_uint16(args->dnode, NULL);
323 struct isis_area *area;
324
325 switch (args->event) {
326 case NB_EV_VALIDATE:
327 area = nb_running_get_entry(args->dnode, NULL, false);
328 if (!area)
329 break;
330 for (ALL_LIST_ELEMENTS_RO(area->circuit_list, node, circuit)) {
331 if (circuit->state != C_STATE_INIT
332 && circuit->state != C_STATE_UP)
333 continue;
334 if (lsp_mtu > isis_circuit_pdu_size(circuit)) {
335 snprintf(
336 args->errmsg, args->errmsg_len,
337 "ISIS area contains circuit %s, which has a maximum PDU size of %zu",
338 circuit->interface->name,
339 isis_circuit_pdu_size(circuit));
340 return NB_ERR_VALIDATION;
341 }
342 }
343 break;
344 case NB_EV_PREPARE:
345 case NB_EV_ABORT:
346 break;
347 case NB_EV_APPLY:
348 area = nb_running_get_entry(args->dnode, NULL, true);
349 isis_area_lsp_mtu_set(area, lsp_mtu);
350 break;
351 }
352
353 return NB_OK;
354 }
355
356 /*
357 * XPath: /frr-isisd:isis/instance/lsp/timers/level-1/refresh-interval
358 */
359 int isis_instance_lsp_refresh_interval_level_1_modify(
360 struct nb_cb_modify_args *args)
361 {
362 struct isis_area *area;
363 uint16_t refr_int;
364
365 if (args->event != NB_EV_APPLY)
366 return NB_OK;
367
368 refr_int = yang_dnode_get_uint16(args->dnode, NULL);
369 area = nb_running_get_entry(args->dnode, NULL, true);
370 isis_area_lsp_refresh_set(area, IS_LEVEL_1, refr_int);
371
372 return NB_OK;
373 }
374
375 /*
376 * XPath: /frr-isisd:isis/instance/lsp/timers/level-2/refresh-interval
377 */
378 int isis_instance_lsp_refresh_interval_level_2_modify(
379 struct nb_cb_modify_args *args)
380 {
381 struct isis_area *area;
382 uint16_t refr_int;
383
384 if (args->event != NB_EV_APPLY)
385 return NB_OK;
386
387 refr_int = yang_dnode_get_uint16(args->dnode, NULL);
388 area = nb_running_get_entry(args->dnode, NULL, true);
389 isis_area_lsp_refresh_set(area, IS_LEVEL_2, refr_int);
390
391 return NB_OK;
392 }
393
394 /*
395 * XPath: /frr-isisd:isis/instance/lsp/timers/level-1/maximum-lifetime
396 */
397 int isis_instance_lsp_maximum_lifetime_level_1_modify(
398 struct nb_cb_modify_args *args)
399 {
400 struct isis_area *area;
401 uint16_t max_lt;
402
403 if (args->event != NB_EV_APPLY)
404 return NB_OK;
405
406 max_lt = yang_dnode_get_uint16(args->dnode, NULL);
407 area = nb_running_get_entry(args->dnode, NULL, true);
408 isis_area_max_lsp_lifetime_set(area, IS_LEVEL_1, max_lt);
409
410 return NB_OK;
411 }
412
413 /*
414 * XPath: /frr-isisd:isis/instance/lsp/timers/level-2/maximum-lifetime
415 */
416 int isis_instance_lsp_maximum_lifetime_level_2_modify(
417 struct nb_cb_modify_args *args)
418 {
419 struct isis_area *area;
420 uint16_t max_lt;
421
422 if (args->event != NB_EV_APPLY)
423 return NB_OK;
424
425 max_lt = yang_dnode_get_uint16(args->dnode, NULL);
426 area = nb_running_get_entry(args->dnode, NULL, true);
427 isis_area_max_lsp_lifetime_set(area, IS_LEVEL_2, max_lt);
428
429 return NB_OK;
430 }
431
432 /*
433 * XPath: /frr-isisd:isis/instance/lsp/timers/level-1/generation-interval
434 */
435 int isis_instance_lsp_generation_interval_level_1_modify(
436 struct nb_cb_modify_args *args)
437 {
438 struct isis_area *area;
439 uint16_t gen_int;
440
441 if (args->event != NB_EV_APPLY)
442 return NB_OK;
443
444 gen_int = yang_dnode_get_uint16(args->dnode, NULL);
445 area = nb_running_get_entry(args->dnode, NULL, true);
446 area->lsp_gen_interval[0] = gen_int;
447
448 return NB_OK;
449 }
450
451 /*
452 * XPath: /frr-isisd:isis/instance/lsp/timers/level-2/generation-interval
453 */
454 int isis_instance_lsp_generation_interval_level_2_modify(
455 struct nb_cb_modify_args *args)
456 {
457 struct isis_area *area;
458 uint16_t gen_int;
459
460 if (args->event != NB_EV_APPLY)
461 return NB_OK;
462
463 gen_int = yang_dnode_get_uint16(args->dnode, NULL);
464 area = nb_running_get_entry(args->dnode, NULL, true);
465 area->lsp_gen_interval[1] = gen_int;
466
467 return NB_OK;
468 }
469
470 /*
471 * XPath: /frr-isisd:isis/instance/spf/ietf-backoff-delay
472 */
473 void ietf_backoff_delay_apply_finish(struct nb_cb_apply_finish_args *args)
474 {
475 long init_delay = yang_dnode_get_uint16(args->dnode, "./init-delay");
476 long short_delay = yang_dnode_get_uint16(args->dnode, "./short-delay");
477 long long_delay = yang_dnode_get_uint16(args->dnode, "./long-delay");
478 long holddown = yang_dnode_get_uint16(args->dnode, "./hold-down");
479 long timetolearn =
480 yang_dnode_get_uint16(args->dnode, "./time-to-learn");
481 struct isis_area *area = nb_running_get_entry(args->dnode, NULL, true);
482 size_t bufsiz = strlen(area->area_tag) + sizeof("IS-IS Lx");
483 char *buf = XCALLOC(MTYPE_TMP, bufsiz);
484
485 snprintf(buf, bufsiz, "IS-IS %s L1", area->area_tag);
486 spf_backoff_free(area->spf_delay_ietf[0]);
487 area->spf_delay_ietf[0] =
488 spf_backoff_new(master, buf, init_delay, short_delay,
489 long_delay, holddown, timetolearn);
490
491 snprintf(buf, bufsiz, "IS-IS %s L2", area->area_tag);
492 spf_backoff_free(area->spf_delay_ietf[1]);
493 area->spf_delay_ietf[1] =
494 spf_backoff_new(master, buf, init_delay, short_delay,
495 long_delay, holddown, timetolearn);
496
497 XFREE(MTYPE_TMP, buf);
498 }
499
500 int isis_instance_spf_ietf_backoff_delay_create(struct nb_cb_create_args *args)
501 {
502 /* All the work is done in the apply_finish */
503 return NB_OK;
504 }
505
506 int isis_instance_spf_ietf_backoff_delay_destroy(
507 struct nb_cb_destroy_args *args)
508 {
509 struct isis_area *area;
510
511 if (args->event != NB_EV_APPLY)
512 return NB_OK;
513
514 area = nb_running_get_entry(args->dnode, NULL, true);
515 spf_backoff_free(area->spf_delay_ietf[0]);
516 spf_backoff_free(area->spf_delay_ietf[1]);
517 area->spf_delay_ietf[0] = NULL;
518 area->spf_delay_ietf[1] = NULL;
519
520 return NB_OK;
521 }
522
523 /*
524 * XPath: /frr-isisd:isis/instance/spf/ietf-backoff-delay/init-delay
525 */
526 int isis_instance_spf_ietf_backoff_delay_init_delay_modify(
527 struct nb_cb_modify_args *args)
528 {
529 /* All the work is done in the apply_finish */
530 return NB_OK;
531 }
532
533 /*
534 * XPath: /frr-isisd:isis/instance/spf/ietf-backoff-delay/short-delay
535 */
536 int isis_instance_spf_ietf_backoff_delay_short_delay_modify(
537 struct nb_cb_modify_args *args)
538 {
539 /* All the work is done in the apply_finish */
540 return NB_OK;
541 }
542
543 /*
544 * XPath: /frr-isisd:isis/instance/spf/ietf-backoff-delay/long-delay
545 */
546 int isis_instance_spf_ietf_backoff_delay_long_delay_modify(
547 struct nb_cb_modify_args *args)
548 {
549 /* All the work is done in the apply_finish */
550 return NB_OK;
551 }
552
553 /*
554 * XPath: /frr-isisd:isis/instance/spf/ietf-backoff-delay/hold-down
555 */
556 int isis_instance_spf_ietf_backoff_delay_hold_down_modify(
557 struct nb_cb_modify_args *args)
558 {
559 /* All the work is done in the apply_finish */
560 return NB_OK;
561 }
562
563 /*
564 * XPath: /frr-isisd:isis/instance/spf/ietf-backoff-delay/time-to-learn
565 */
566 int isis_instance_spf_ietf_backoff_delay_time_to_learn_modify(
567 struct nb_cb_modify_args *args)
568 {
569 /* All the work is done in the apply_finish */
570 return NB_OK;
571 }
572
573 /*
574 * XPath: /frr-isisd:isis/instance/spf/minimum-interval/level-1
575 */
576 int isis_instance_spf_minimum_interval_level_1_modify(
577 struct nb_cb_modify_args *args)
578 {
579 struct isis_area *area;
580
581 if (args->event != NB_EV_APPLY)
582 return NB_OK;
583
584 area = nb_running_get_entry(args->dnode, NULL, true);
585 area->min_spf_interval[0] = yang_dnode_get_uint16(args->dnode, NULL);
586
587 return NB_OK;
588 }
589
590 /*
591 * XPath: /frr-isisd:isis/instance/spf/minimum-interval/level-2
592 */
593 int isis_instance_spf_minimum_interval_level_2_modify(
594 struct nb_cb_modify_args *args)
595 {
596 struct isis_area *area;
597
598 if (args->event != NB_EV_APPLY)
599 return NB_OK;
600
601 area = nb_running_get_entry(args->dnode, NULL, true);
602 area->min_spf_interval[1] = yang_dnode_get_uint16(args->dnode, NULL);
603
604 return NB_OK;
605 }
606
607 /*
608 * XPath: /frr-isisd:isis/instance/area-password
609 */
610 void area_password_apply_finish(struct nb_cb_apply_finish_args *args)
611 {
612 const char *password = yang_dnode_get_string(args->dnode, "./password");
613 struct isis_area *area = nb_running_get_entry(args->dnode, NULL, true);
614 int pass_type = yang_dnode_get_enum(args->dnode, "./password-type");
615 uint8_t snp_auth =
616 yang_dnode_get_enum(args->dnode, "./authenticate-snp");
617
618 switch (pass_type) {
619 case ISIS_PASSWD_TYPE_CLEARTXT:
620 isis_area_passwd_cleartext_set(area, IS_LEVEL_1, password,
621 snp_auth);
622 break;
623 case ISIS_PASSWD_TYPE_HMAC_MD5:
624 isis_area_passwd_hmac_md5_set(area, IS_LEVEL_1, password,
625 snp_auth);
626 break;
627 }
628 }
629
630 int isis_instance_area_password_create(struct nb_cb_create_args *args)
631 {
632 /* actual setting is done in apply_finish */
633 return NB_OK;
634 }
635
636 int isis_instance_area_password_destroy(struct nb_cb_destroy_args *args)
637 {
638 struct isis_area *area;
639
640 if (args->event != NB_EV_APPLY)
641 return NB_OK;
642
643 area = nb_running_get_entry(args->dnode, NULL, true);
644 isis_area_passwd_unset(area, IS_LEVEL_1);
645
646 return NB_OK;
647 }
648
649 /*
650 * XPath: /frr-isisd:isis/instance/area-password/password
651 */
652 int isis_instance_area_password_password_modify(struct nb_cb_modify_args *args)
653 {
654 /* actual setting is done in apply_finish */
655 return NB_OK;
656 }
657
658 /*
659 * XPath: /frr-isisd:isis/instance/area-password/password-type
660 */
661 int isis_instance_area_password_password_type_modify(
662 struct nb_cb_modify_args *args)
663 {
664 /* actual setting is done in apply_finish */
665 return NB_OK;
666 }
667
668 /*
669 * XPath: /frr-isisd:isis/instance/area-password/authenticate-snp
670 */
671 int isis_instance_area_password_authenticate_snp_modify(
672 struct nb_cb_modify_args *args)
673 {
674 /* actual setting is done in apply_finish */
675 return NB_OK;
676 }
677
678 /*
679 * XPath: /frr-isisd:isis/instance/domain-password
680 */
681 void domain_password_apply_finish(struct nb_cb_apply_finish_args *args)
682 {
683 const char *password = yang_dnode_get_string(args->dnode, "./password");
684 struct isis_area *area = nb_running_get_entry(args->dnode, NULL, true);
685 int pass_type = yang_dnode_get_enum(args->dnode, "./password-type");
686 uint8_t snp_auth =
687 yang_dnode_get_enum(args->dnode, "./authenticate-snp");
688
689 switch (pass_type) {
690 case ISIS_PASSWD_TYPE_CLEARTXT:
691 isis_area_passwd_cleartext_set(area, IS_LEVEL_2, password,
692 snp_auth);
693 break;
694 case ISIS_PASSWD_TYPE_HMAC_MD5:
695 isis_area_passwd_hmac_md5_set(area, IS_LEVEL_2, password,
696 snp_auth);
697 break;
698 }
699 }
700
701 int isis_instance_domain_password_create(struct nb_cb_create_args *args)
702 {
703 /* actual setting is done in apply_finish */
704 return NB_OK;
705 }
706
707 int isis_instance_domain_password_destroy(struct nb_cb_destroy_args *args)
708 {
709 struct isis_area *area;
710
711 if (args->event != NB_EV_APPLY)
712 return NB_OK;
713
714 area = nb_running_get_entry(args->dnode, NULL, true);
715 isis_area_passwd_unset(area, IS_LEVEL_2);
716
717 return NB_OK;
718 }
719
720 /*
721 * XPath: /frr-isisd:isis/instance/domain-password/password
722 */
723 int isis_instance_domain_password_password_modify(
724 struct nb_cb_modify_args *args)
725 {
726 /* actual setting is done in apply_finish */
727 return NB_OK;
728 }
729
730 /*
731 * XPath: /frr-isisd:isis/instance/domain-password/password-type
732 */
733 int isis_instance_domain_password_password_type_modify(
734 struct nb_cb_modify_args *args)
735 {
736 /* actual setting is done in apply_finish */
737 return NB_OK;
738 }
739
740 /*
741 * XPath: /frr-isisd:isis/instance/domain-password/authenticate-snp
742 */
743 int isis_instance_domain_password_authenticate_snp_modify(
744 struct nb_cb_modify_args *args)
745 {
746 /* actual setting is done in apply_finish */
747 return NB_OK;
748 }
749
750 /*
751 * XPath: /frr-isisd:isis/instance/default-information-originate/ipv4
752 */
753 void default_info_origin_apply_finish(const struct lyd_node *dnode, int family)
754 {
755 int originate_type = DEFAULT_ORIGINATE;
756 unsigned long metric = 0;
757 const char *routemap = NULL;
758 struct isis_area *area = nb_running_get_entry(dnode, NULL, true);
759 int level = yang_dnode_get_enum(dnode, "./level");
760
761 if (yang_dnode_get_bool(dnode, "./always")) {
762 originate_type = DEFAULT_ORIGINATE_ALWAYS;
763 } else if (family == AF_INET6) {
764 zlog_warn(
765 "%s: Zebra doesn't implement default-originate for IPv6 yet, so use with care or use default-originate always.",
766 __func__);
767 }
768
769 if (yang_dnode_exists(dnode, "./metric"))
770 metric = yang_dnode_get_uint32(dnode, "./metric");
771 if (yang_dnode_exists(dnode, "./route-map"))
772 routemap = yang_dnode_get_string(dnode, "./route-map");
773
774 isis_redist_set(area, level, family, DEFAULT_ROUTE, metric, routemap,
775 originate_type);
776 }
777
778 void default_info_origin_ipv4_apply_finish(struct nb_cb_apply_finish_args *args)
779 {
780 default_info_origin_apply_finish(args->dnode, AF_INET);
781 }
782
783 void default_info_origin_ipv6_apply_finish(struct nb_cb_apply_finish_args *args)
784 {
785 default_info_origin_apply_finish(args->dnode, AF_INET6);
786 }
787
788 int isis_instance_default_information_originate_ipv4_create(
789 struct nb_cb_create_args *args)
790 {
791 /* It's all done by default_info_origin_apply_finish */
792 return NB_OK;
793 }
794
795 int isis_instance_default_information_originate_ipv4_destroy(
796 struct nb_cb_destroy_args *args)
797 {
798 struct isis_area *area;
799 int level;
800
801 if (args->event != NB_EV_APPLY)
802 return NB_OK;
803
804 area = nb_running_get_entry(args->dnode, NULL, true);
805 level = yang_dnode_get_enum(args->dnode, "./level");
806 isis_redist_unset(area, level, AF_INET, DEFAULT_ROUTE);
807
808 return NB_OK;
809 }
810
811 /*
812 * XPath: /frr-isisd:isis/instance/default-information-originate/ipv4/always
813 */
814 int isis_instance_default_information_originate_ipv4_always_modify(
815 struct nb_cb_modify_args *args)
816 {
817 /* It's all done by default_info_origin_apply_finish */
818 return NB_OK;
819 }
820
821 /*
822 * XPath: /frr-isisd:isis/instance/default-information-originate/ipv4/route-map
823 */
824 int isis_instance_default_information_originate_ipv4_route_map_modify(
825 struct nb_cb_modify_args *args)
826 {
827 /* It's all done by default_info_origin_apply_finish */
828 return NB_OK;
829 }
830
831 int isis_instance_default_information_originate_ipv4_route_map_destroy(
832 struct nb_cb_destroy_args *args)
833 {
834 /* It's all done by default_info_origin_apply_finish */
835 return NB_OK;
836 }
837
838 /*
839 * XPath: /frr-isisd:isis/instance/default-information-originate/ipv4/metric
840 */
841 int isis_instance_default_information_originate_ipv4_metric_modify(
842 struct nb_cb_modify_args *args)
843 {
844 /* It's all done by default_info_origin_apply_finish */
845 return NB_OK;
846 }
847
848 /*
849 * XPath: /frr-isisd:isis/instance/default-information-originate/ipv6
850 */
851 int isis_instance_default_information_originate_ipv6_create(
852 struct nb_cb_create_args *args)
853 {
854 /* It's all done by default_info_origin_apply_finish */
855 return NB_OK;
856 }
857
858 int isis_instance_default_information_originate_ipv6_destroy(
859 struct nb_cb_destroy_args *args)
860 {
861 struct isis_area *area;
862 int level;
863
864 if (args->event != NB_EV_APPLY)
865 return NB_OK;
866
867 area = nb_running_get_entry(args->dnode, NULL, true);
868 level = yang_dnode_get_enum(args->dnode, "./level");
869 isis_redist_unset(area, level, AF_INET6, DEFAULT_ROUTE);
870
871 return NB_OK;
872 }
873
874 /*
875 * XPath: /frr-isisd:isis/instance/default-information-originate/ipv6/always
876 */
877 int isis_instance_default_information_originate_ipv6_always_modify(
878 struct nb_cb_modify_args *args)
879 {
880 /* It's all done by default_info_origin_apply_finish */
881 return NB_OK;
882 }
883
884 /*
885 * XPath: /frr-isisd:isis/instance/default-information-originate/ipv6/route-map
886 */
887 int isis_instance_default_information_originate_ipv6_route_map_modify(
888 struct nb_cb_modify_args *args)
889 {
890 /* It's all done by default_info_origin_apply_finish */
891 return NB_OK;
892 }
893
894 int isis_instance_default_information_originate_ipv6_route_map_destroy(
895 struct nb_cb_destroy_args *args)
896 {
897 /* It's all done by default_info_origin_apply_finish */
898 return NB_OK;
899 }
900
901 /*
902 * XPath: /frr-isisd:isis/instance/default-information-originate/ipv6/metric
903 */
904 int isis_instance_default_information_originate_ipv6_metric_modify(
905 struct nb_cb_modify_args *args)
906 {
907 /* It's all done by default_info_origin_apply_finish */
908 return NB_OK;
909 }
910
911 /*
912 * XPath: /frr-isisd:isis/instance/redistribute/ipv4
913 */
914 void redistribute_apply_finish(const struct lyd_node *dnode, int family)
915 {
916 assert(family == AF_INET || family == AF_INET6);
917 int type, level;
918 unsigned long metric = 0;
919 const char *routemap = NULL;
920 struct isis_area *area;
921
922 type = yang_dnode_get_enum(dnode, "./protocol");
923 level = yang_dnode_get_enum(dnode, "./level");
924 area = nb_running_get_entry(dnode, NULL, true);
925
926 if (yang_dnode_exists(dnode, "./metric"))
927 metric = yang_dnode_get_uint32(dnode, "./metric");
928 if (yang_dnode_exists(dnode, "./route-map"))
929 routemap = yang_dnode_get_string(dnode, "./route-map");
930
931 isis_redist_set(area, level, family, type, metric, routemap, 0);
932 }
933
934 void redistribute_ipv4_apply_finish(struct nb_cb_apply_finish_args *args)
935 {
936 redistribute_apply_finish(args->dnode, AF_INET);
937 }
938
939 void redistribute_ipv6_apply_finish(struct nb_cb_apply_finish_args *args)
940 {
941 redistribute_apply_finish(args->dnode, AF_INET6);
942 }
943
944 int isis_instance_redistribute_ipv4_create(struct nb_cb_create_args *args)
945 {
946 /* It's all done by redistribute_apply_finish */
947 return NB_OK;
948 }
949
950 int isis_instance_redistribute_ipv4_destroy(struct nb_cb_destroy_args *args)
951 {
952 struct isis_area *area;
953 int level, type;
954
955 if (args->event != NB_EV_APPLY)
956 return NB_OK;
957
958 area = nb_running_get_entry(args->dnode, NULL, true);
959 level = yang_dnode_get_enum(args->dnode, "./level");
960 type = yang_dnode_get_enum(args->dnode, "./protocol");
961 isis_redist_unset(area, level, AF_INET, type);
962
963 return NB_OK;
964 }
965
966 /*
967 * XPath: /frr-isisd:isis/instance/redistribute/ipv4/route-map
968 */
969 int isis_instance_redistribute_ipv4_route_map_modify(
970 struct nb_cb_modify_args *args)
971 {
972 /* It's all done by redistribute_apply_finish */
973 return NB_OK;
974 }
975
976 int isis_instance_redistribute_ipv4_route_map_destroy(
977 struct nb_cb_destroy_args *args)
978 {
979 /* It's all done by redistribute_apply_finish */
980 return NB_OK;
981 }
982
983 /*
984 * XPath: /frr-isisd:isis/instance/redistribute/ipv4/metric
985 */
986 int isis_instance_redistribute_ipv4_metric_modify(
987 struct nb_cb_modify_args *args)
988 {
989 /* It's all done by redistribute_apply_finish */
990 return NB_OK;
991 }
992
993 /*
994 * XPath: /frr-isisd:isis/instance/redistribute/ipv6
995 */
996 int isis_instance_redistribute_ipv6_create(struct nb_cb_create_args *args)
997 {
998 /* It's all done by redistribute_apply_finish */
999 return NB_OK;
1000 }
1001
1002 int isis_instance_redistribute_ipv6_destroy(struct nb_cb_destroy_args *args)
1003 {
1004 struct isis_area *area;
1005 int level, type;
1006
1007 if (args->event != NB_EV_APPLY)
1008 return NB_OK;
1009
1010 area = nb_running_get_entry(args->dnode, NULL, true);
1011 level = yang_dnode_get_enum(args->dnode, "./level");
1012 type = yang_dnode_get_enum(args->dnode, "./protocol");
1013 isis_redist_unset(area, level, AF_INET6, type);
1014
1015 return NB_OK;
1016 }
1017
1018 /*
1019 * XPath: /frr-isisd:isis/instance/redistribute/ipv6/route-map
1020 */
1021 int isis_instance_redistribute_ipv6_route_map_modify(
1022 struct nb_cb_modify_args *args)
1023 {
1024 /* It's all done by redistribute_apply_finish */
1025 return NB_OK;
1026 }
1027
1028 int isis_instance_redistribute_ipv6_route_map_destroy(
1029 struct nb_cb_destroy_args *args)
1030 {
1031 /* It's all done by redistribute_apply_finish */
1032 return NB_OK;
1033 }
1034
1035 /*
1036 * XPath: /frr-isisd:isis/instance/redistribute/ipv6/metric
1037 */
1038 int isis_instance_redistribute_ipv6_metric_modify(
1039 struct nb_cb_modify_args *args)
1040 {
1041 /* It's all done by redistribute_apply_finish */
1042 return NB_OK;
1043 }
1044
1045 /*
1046 * XPath: /frr-isisd:isis/instance/multi-topology/ipv4-multicast
1047 */
1048 static int isis_multi_topology_common(enum nb_event event,
1049 const struct lyd_node *dnode,
1050 char *errmsg, size_t errmsg_len,
1051 const char *topology, bool create)
1052 {
1053 struct isis_area *area;
1054 struct isis_area_mt_setting *setting;
1055 uint16_t mtid = isis_str2mtid(topology);
1056
1057 switch (event) {
1058 case NB_EV_VALIDATE:
1059 if (mtid == (uint16_t)-1) {
1060 snprintf(errmsg, errmsg_len, "Unknown topology %s",
1061 topology);
1062 return NB_ERR_VALIDATION;
1063 }
1064 break;
1065 case NB_EV_PREPARE:
1066 case NB_EV_ABORT:
1067 break;
1068 case NB_EV_APPLY:
1069 area = nb_running_get_entry(dnode, NULL, true);
1070 setting = area_get_mt_setting(area, mtid);
1071 setting->enabled = create;
1072 lsp_regenerate_schedule(area, IS_LEVEL_1 | IS_LEVEL_2, 0);
1073 break;
1074 }
1075
1076 return NB_OK;
1077 }
1078
1079 static int isis_multi_topology_overload_common(enum nb_event event,
1080 const struct lyd_node *dnode,
1081 const char *topology)
1082 {
1083 struct isis_area *area;
1084 struct isis_area_mt_setting *setting;
1085 uint16_t mtid = isis_str2mtid(topology);
1086
1087 /* validation is done in isis_multi_topology_common */
1088 if (event != NB_EV_APPLY)
1089 return NB_OK;
1090
1091 area = nb_running_get_entry(dnode, NULL, true);
1092 setting = area_get_mt_setting(area, mtid);
1093 setting->overload = yang_dnode_get_bool(dnode, NULL);
1094 if (setting->enabled)
1095 lsp_regenerate_schedule(area, IS_LEVEL_1 | IS_LEVEL_2, 0);
1096
1097 return NB_OK;
1098 }
1099
1100 int isis_instance_multi_topology_ipv4_multicast_create(
1101 struct nb_cb_create_args *args)
1102 {
1103 return isis_multi_topology_common(args->event, args->dnode,
1104 args->errmsg, args->errmsg_len,
1105 "ipv4-multicast", true);
1106 }
1107
1108 int isis_instance_multi_topology_ipv4_multicast_destroy(
1109 struct nb_cb_destroy_args *args)
1110 {
1111 return isis_multi_topology_common(args->event, args->dnode,
1112 args->errmsg, args->errmsg_len,
1113 "ipv4-multicast", false);
1114 }
1115
1116 /*
1117 * XPath: /frr-isisd:isis/instance/multi-topology/ipv4-multicast/overload
1118 */
1119 int isis_instance_multi_topology_ipv4_multicast_overload_modify(
1120 struct nb_cb_modify_args *args)
1121 {
1122 return isis_multi_topology_overload_common(args->event, args->dnode,
1123 "ipv4-multicast");
1124 }
1125
1126 /*
1127 * XPath: /frr-isisd:isis/instance/multi-topology/ipv4-management
1128 */
1129 int isis_instance_multi_topology_ipv4_management_create(
1130 struct nb_cb_create_args *args)
1131 {
1132 return isis_multi_topology_common(args->event, args->dnode,
1133 args->errmsg, args->errmsg_len,
1134 "ipv4-mgmt", true);
1135 }
1136
1137 int isis_instance_multi_topology_ipv4_management_destroy(
1138 struct nb_cb_destroy_args *args)
1139 {
1140 return isis_multi_topology_common(args->event, args->dnode,
1141 args->errmsg, args->errmsg_len,
1142 "ipv4-mgmt", false);
1143 }
1144
1145 /*
1146 * XPath: /frr-isisd:isis/instance/multi-topology/ipv4-management/overload
1147 */
1148 int isis_instance_multi_topology_ipv4_management_overload_modify(
1149 struct nb_cb_modify_args *args)
1150 {
1151 return isis_multi_topology_overload_common(args->event, args->dnode,
1152 "ipv4-mgmt");
1153 }
1154
1155 /*
1156 * XPath: /frr-isisd:isis/instance/multi-topology/ipv6-unicast
1157 */
1158 int isis_instance_multi_topology_ipv6_unicast_create(
1159 struct nb_cb_create_args *args)
1160 {
1161 return isis_multi_topology_common(args->event, args->dnode,
1162 args->errmsg, args->errmsg_len,
1163 "ipv6-unicast", true);
1164 }
1165
1166 int isis_instance_multi_topology_ipv6_unicast_destroy(
1167 struct nb_cb_destroy_args *args)
1168 {
1169 return isis_multi_topology_common(args->event, args->dnode,
1170 args->errmsg, args->errmsg_len,
1171 "ipv6-unicast", false);
1172 }
1173
1174 /*
1175 * XPath: /frr-isisd:isis/instance/multi-topology/ipv6-unicast/overload
1176 */
1177 int isis_instance_multi_topology_ipv6_unicast_overload_modify(
1178 struct nb_cb_modify_args *args)
1179 {
1180 return isis_multi_topology_overload_common(args->event, args->dnode,
1181 "ipv6-unicast");
1182 }
1183
1184 /*
1185 * XPath: /frr-isisd:isis/instance/multi-topology/ipv6-multicast
1186 */
1187 int isis_instance_multi_topology_ipv6_multicast_create(
1188 struct nb_cb_create_args *args)
1189 {
1190 return isis_multi_topology_common(args->event, args->dnode,
1191 args->errmsg, args->errmsg_len,
1192 "ipv6-multicast", true);
1193 }
1194
1195 int isis_instance_multi_topology_ipv6_multicast_destroy(
1196 struct nb_cb_destroy_args *args)
1197 {
1198 return isis_multi_topology_common(args->event, args->dnode,
1199 args->errmsg, args->errmsg_len,
1200 "ipv6-multicast", false);
1201 }
1202
1203 /*
1204 * XPath: /frr-isisd:isis/instance/multi-topology/ipv6-multicast/overload
1205 */
1206 int isis_instance_multi_topology_ipv6_multicast_overload_modify(
1207 struct nb_cb_modify_args *args)
1208 {
1209 return isis_multi_topology_overload_common(args->event, args->dnode,
1210 "ipv6-multicast");
1211 }
1212
1213 /*
1214 * XPath: /frr-isisd:isis/instance/multi-topology/ipv6-management
1215 */
1216 int isis_instance_multi_topology_ipv6_management_create(
1217 struct nb_cb_create_args *args)
1218 {
1219 return isis_multi_topology_common(args->event, args->dnode,
1220 args->errmsg, args->errmsg_len,
1221 "ipv6-mgmt", true);
1222 }
1223
1224 int isis_instance_multi_topology_ipv6_management_destroy(
1225 struct nb_cb_destroy_args *args)
1226 {
1227 return isis_multi_topology_common(args->event, args->dnode,
1228 args->errmsg, args->errmsg_len,
1229 "ipv6-mgmt", false);
1230 }
1231
1232 /*
1233 * XPath: /frr-isisd:isis/instance/multi-topology/ipv6-management/overload
1234 */
1235 int isis_instance_multi_topology_ipv6_management_overload_modify(
1236 struct nb_cb_modify_args *args)
1237 {
1238 return isis_multi_topology_overload_common(args->event, args->dnode,
1239 "ipv6-mgmt");
1240 }
1241
1242 /*
1243 * XPath: /frr-isisd:isis/instance/multi-topology/ipv6-dstsrc
1244 */
1245 int isis_instance_multi_topology_ipv6_dstsrc_create(
1246 struct nb_cb_create_args *args)
1247 {
1248 return isis_multi_topology_common(args->event, args->dnode,
1249 args->errmsg, args->errmsg_len,
1250 "ipv6-dstsrc", true);
1251 }
1252
1253 int isis_instance_multi_topology_ipv6_dstsrc_destroy(
1254 struct nb_cb_destroy_args *args)
1255 {
1256 return isis_multi_topology_common(args->event, args->dnode,
1257 args->errmsg, args->errmsg_len,
1258 "ipv6-dstsrc", false);
1259 }
1260
1261 /*
1262 * XPath: /frr-isisd:isis/instance/multi-topology/ipv6-dstsrc/overload
1263 */
1264 int isis_instance_multi_topology_ipv6_dstsrc_overload_modify(
1265 struct nb_cb_modify_args *args)
1266 {
1267 return isis_multi_topology_overload_common(args->event, args->dnode,
1268 "ipv6-dstsrc");
1269 }
1270
1271 /*
1272 * XPath: /frr-isisd:isis/instance/log-adjacency-changes
1273 */
1274 int isis_instance_log_adjacency_changes_modify(struct nb_cb_modify_args *args)
1275 {
1276 struct isis_area *area;
1277 bool log = yang_dnode_get_bool(args->dnode, NULL);
1278
1279 if (args->event != NB_EV_APPLY)
1280 return NB_OK;
1281
1282 area = nb_running_get_entry(args->dnode, NULL, true);
1283 area->log_adj_changes = log ? 1 : 0;
1284
1285 return NB_OK;
1286 }
1287
1288 /*
1289 * XPath: /frr-isisd:isis/instance/mpls-te
1290 */
1291 int isis_instance_mpls_te_create(struct nb_cb_create_args *args)
1292 {
1293 struct listnode *node;
1294 struct isis_area *area;
1295 struct isis_circuit *circuit;
1296
1297 if (args->event != NB_EV_APPLY)
1298 return NB_OK;
1299
1300 area = nb_running_get_entry(args->dnode, NULL, true);
1301 if (area->mta == NULL) {
1302
1303 struct mpls_te_area *new;
1304
1305 zlog_debug("ISIS-TE(%s): Initialize MPLS Traffic Engineering",
1306 area->area_tag);
1307
1308 new = XCALLOC(MTYPE_ISIS_MPLS_TE, sizeof(struct mpls_te_area));
1309
1310 /* Initialize MPLS_TE structure */
1311 new->status = enable;
1312 new->level = 0;
1313 new->inter_as = off;
1314 new->interas_areaid.s_addr = 0;
1315 new->router_id.s_addr = 0;
1316
1317 area->mta = new;
1318 } else {
1319 area->mta->status = enable;
1320 }
1321
1322 /* Update Extended TLVs according to Interface link parameters */
1323 for (ALL_LIST_ELEMENTS_RO(area->circuit_list, node, circuit))
1324 isis_link_params_update(circuit, circuit->interface);
1325
1326 /* Reoriginate STD_TE & GMPLS circuits */
1327 lsp_regenerate_schedule(area, area->is_type, 0);
1328
1329 return NB_OK;
1330 }
1331
1332 int isis_instance_mpls_te_destroy(struct nb_cb_destroy_args *args)
1333 {
1334 struct listnode *node;
1335 struct isis_area *area;
1336 struct isis_circuit *circuit;
1337
1338 if (args->event != NB_EV_APPLY)
1339 return NB_OK;
1340
1341 area = nb_running_get_entry(args->dnode, NULL, true);
1342 if (IS_MPLS_TE(area->mta))
1343 area->mta->status = disable;
1344 else
1345 return NB_OK;
1346
1347 /* Flush LSP if circuit engage */
1348 for (ALL_LIST_ELEMENTS_RO(area->circuit_list, node, circuit)) {
1349 if (!IS_EXT_TE(circuit->ext))
1350 continue;
1351
1352 /* disable MPLS_TE Circuit keeping SR one's */
1353 if (IS_SUBTLV(circuit->ext, EXT_ADJ_SID))
1354 circuit->ext->status = EXT_ADJ_SID;
1355 else if (IS_SUBTLV(circuit->ext, EXT_LAN_ADJ_SID))
1356 circuit->ext->status = EXT_LAN_ADJ_SID;
1357 else
1358 circuit->ext->status = 0;
1359 }
1360
1361 /* Reoriginate STD_TE & GMPLS circuits */
1362 lsp_regenerate_schedule(area, area->is_type, 0);
1363
1364 zlog_debug("ISIS-TE(%s): Disabled MPLS Traffic Engineering",
1365 area->area_tag);
1366
1367 return NB_OK;
1368 }
1369
1370 /*
1371 * XPath: /frr-isisd:isis/instance/mpls-te/router-address
1372 */
1373 int isis_instance_mpls_te_router_address_modify(struct nb_cb_modify_args *args)
1374 {
1375 struct in_addr value;
1376 struct isis_area *area;
1377
1378 if (args->event != NB_EV_APPLY)
1379 return NB_OK;
1380
1381 area = nb_running_get_entry(args->dnode, NULL, true);
1382 /* only proceed if MPLS-TE is enabled */
1383 if (!IS_MPLS_TE(area->mta))
1384 return NB_OK;
1385
1386 /* Update Area Router ID */
1387 yang_dnode_get_ipv4(&value, args->dnode, NULL);
1388 area->mta->router_id.s_addr = value.s_addr;
1389
1390 /* And re-schedule LSP update */
1391 lsp_regenerate_schedule(area, area->is_type, 0);
1392
1393 return NB_OK;
1394 }
1395
1396 int isis_instance_mpls_te_router_address_destroy(
1397 struct nb_cb_destroy_args *args)
1398 {
1399 struct isis_area *area;
1400
1401 if (args->event != NB_EV_APPLY)
1402 return NB_OK;
1403
1404 area = nb_running_get_entry(args->dnode, NULL, true);
1405 /* only proceed if MPLS-TE is enabled */
1406 if (!IS_MPLS_TE(area->mta))
1407 return NB_OK;
1408
1409 /* Reset Area Router ID */
1410 area->mta->router_id.s_addr = INADDR_ANY;
1411
1412 /* And re-schedule LSP update */
1413 lsp_regenerate_schedule(area, area->is_type, 0);
1414
1415 return NB_OK;
1416 }
1417
1418 /*
1419 * XPath: /frr-isisd:isis/instance/segment-routing/enabled
1420 */
1421 int isis_instance_segment_routing_enabled_modify(
1422 struct nb_cb_modify_args *args)
1423 {
1424 struct isis_area *area;
1425
1426 if (args->event != NB_EV_APPLY)
1427 return NB_OK;
1428
1429 area = nb_running_get_entry(args->dnode, NULL, true);
1430 area->srdb.config.enabled = yang_dnode_get_bool(args->dnode, NULL);
1431
1432 if (area->srdb.config.enabled) {
1433 if (IS_DEBUG_EVENTS)
1434 zlog_debug("SR: Segment Routing: OFF -> ON");
1435
1436 isis_sr_start(area);
1437 } else {
1438 if (IS_DEBUG_EVENTS)
1439 zlog_debug("SR: Segment Routing: ON -> OFF");
1440
1441 isis_sr_stop(area);
1442 }
1443
1444 return NB_OK;
1445 }
1446
1447 /*
1448 * XPath: /frr-isisd:isis/instance/segment-routing/srgb
1449 */
1450 int isis_instance_segment_routing_srgb_pre_validate(
1451 struct nb_cb_pre_validate_args *args)
1452 {
1453 uint32_t srgb_lbound;
1454 uint32_t srgb_ubound;
1455 uint32_t srlb_lbound;
1456 uint32_t srlb_ubound;
1457
1458 srgb_lbound = yang_dnode_get_uint32(args->dnode, "./lower-bound");
1459 srgb_ubound = yang_dnode_get_uint32(args->dnode, "./upper-bound");
1460 srlb_lbound = yang_dnode_get_uint32(args->dnode, "../srlb/lower-bound");
1461 srlb_ubound = yang_dnode_get_uint32(args->dnode, "../srlb/upper-bound");
1462
1463 /* Check that the block size does not exceed 65535 */
1464 if ((srgb_ubound - srgb_lbound + 1) > 65535) {
1465 zlog_warn(
1466 "New SR Global Block (%u/%u) exceed the limit of 65535",
1467 srgb_lbound, srgb_ubound);
1468 return NB_ERR_VALIDATION;
1469 }
1470
1471 /* Validate SRGB against SRLB */
1472 if (!((srgb_ubound < srlb_lbound) || (srgb_lbound > srlb_ubound))) {
1473 zlog_warn(
1474 "New SR Global Block (%u/%u) conflict with Local Block (%u/%u)",
1475 srgb_lbound, srgb_ubound, srlb_lbound, srlb_ubound);
1476 return NB_ERR_VALIDATION;
1477 }
1478
1479 return NB_OK;
1480 }
1481
1482 void isis_instance_segment_routing_srgb_apply_finish(
1483 struct nb_cb_apply_finish_args *args)
1484 {
1485 struct isis_area *area;
1486 uint32_t lower_bound, upper_bound;
1487
1488 area = nb_running_get_entry(args->dnode, NULL, true);
1489 lower_bound = yang_dnode_get_uint32(args->dnode, "./lower-bound");
1490 upper_bound = yang_dnode_get_uint32(args->dnode, "./upper-bound");
1491
1492 isis_sr_cfg_srgb_update(area, lower_bound, upper_bound);
1493 }
1494
1495 /*
1496 * XPath: /frr-isisd:isis/instance/segment-routing/srgb/lower-bound
1497 */
1498 int isis_instance_segment_routing_srgb_lower_bound_modify(
1499 struct nb_cb_modify_args *args)
1500 {
1501 uint32_t lower_bound = yang_dnode_get_uint32(args->dnode, NULL);
1502
1503 switch (args->event) {
1504 case NB_EV_VALIDATE:
1505 if (!IS_MPLS_UNRESERVED_LABEL(lower_bound)) {
1506 zlog_warn("Invalid SRGB lower bound: %" PRIu32,
1507 lower_bound);
1508 return NB_ERR_VALIDATION;
1509 }
1510 break;
1511 case NB_EV_PREPARE:
1512 case NB_EV_ABORT:
1513 case NB_EV_APPLY:
1514 break;
1515 }
1516
1517 return NB_OK;
1518 }
1519
1520 /*
1521 * XPath: /frr-isisd:isis/instance/segment-routing/srgb/upper-bound
1522 */
1523 int isis_instance_segment_routing_srgb_upper_bound_modify(
1524 struct nb_cb_modify_args *args)
1525 {
1526 uint32_t upper_bound = yang_dnode_get_uint32(args->dnode, NULL);
1527
1528 switch (args->event) {
1529 case NB_EV_VALIDATE:
1530 if (!IS_MPLS_UNRESERVED_LABEL(upper_bound)) {
1531 zlog_warn("Invalid SRGB upper bound: %" PRIu32,
1532 upper_bound);
1533 return NB_ERR_VALIDATION;
1534 }
1535 break;
1536 case NB_EV_PREPARE:
1537 case NB_EV_ABORT:
1538 case NB_EV_APPLY:
1539 break;
1540 }
1541
1542 return NB_OK;
1543 }
1544
1545 /*
1546 * XPath: /frr-isisd:isis/instance/segment-routing/srlb
1547 */
1548 int isis_instance_segment_routing_srlb_pre_validate(
1549 struct nb_cb_pre_validate_args *args)
1550 {
1551 uint32_t srgb_lbound;
1552 uint32_t srgb_ubound;
1553 uint32_t srlb_lbound;
1554 uint32_t srlb_ubound;
1555
1556 srgb_lbound = yang_dnode_get_uint32(args->dnode, "../srgb/lower-bound");
1557 srgb_ubound = yang_dnode_get_uint32(args->dnode, "../srgb/upper-bound");
1558 srlb_lbound = yang_dnode_get_uint32(args->dnode, "./lower-bound");
1559 srlb_ubound = yang_dnode_get_uint32(args->dnode, "./upper-bound");
1560
1561 /* Check that the block size does not exceed 65535 */
1562 if ((srlb_ubound - srlb_lbound + 1) > 65535) {
1563 zlog_warn(
1564 "New SR Local Block (%u/%u) exceed the limit of 65535",
1565 srlb_lbound, srlb_ubound);
1566 return NB_ERR_VALIDATION;
1567 }
1568
1569 /* Validate SRLB against SRGB */
1570 if (!((srlb_ubound < srgb_lbound) || (srlb_lbound > srgb_ubound))) {
1571 zlog_warn(
1572 "New SR Local Block (%u/%u) conflict with Global Block (%u/%u)",
1573 srlb_lbound, srlb_ubound, srgb_lbound, srgb_ubound);
1574 return NB_ERR_VALIDATION;
1575 }
1576
1577 return NB_OK;
1578 }
1579
1580 void isis_instance_segment_routing_srlb_apply_finish(
1581 struct nb_cb_apply_finish_args *args)
1582 {
1583 struct isis_area *area;
1584 uint32_t lower_bound, upper_bound;
1585
1586 area = nb_running_get_entry(args->dnode, NULL, true);
1587 lower_bound = yang_dnode_get_uint32(args->dnode, "./lower-bound");
1588 upper_bound = yang_dnode_get_uint32(args->dnode, "./upper-bound");
1589
1590 isis_sr_cfg_srlb_update(area, lower_bound, upper_bound);
1591 }
1592
1593 /*
1594 * XPath: /frr-isisd:isis/instance/segment-routing/srlb/lower-bound
1595 */
1596 int isis_instance_segment_routing_srlb_lower_bound_modify(
1597 struct nb_cb_modify_args *args)
1598 {
1599 uint32_t lower_bound = yang_dnode_get_uint32(args->dnode, NULL);
1600
1601 switch (args->event) {
1602 case NB_EV_VALIDATE:
1603 if (!IS_MPLS_UNRESERVED_LABEL(lower_bound)) {
1604 zlog_warn("Invalid SRLB lower bound: %" PRIu32,
1605 lower_bound);
1606 return NB_ERR_VALIDATION;
1607 }
1608 break;
1609 case NB_EV_PREPARE:
1610 case NB_EV_ABORT:
1611 case NB_EV_APPLY:
1612 break;
1613 }
1614
1615 return NB_OK;
1616 }
1617
1618 /*
1619 * XPath: /frr-isisd:isis/instance/segment-routing/srlb/upper-bound
1620 */
1621 int isis_instance_segment_routing_srlb_upper_bound_modify(
1622 struct nb_cb_modify_args *args)
1623 {
1624 uint32_t upper_bound = yang_dnode_get_uint32(args->dnode, NULL);
1625
1626 switch (args->event) {
1627 case NB_EV_VALIDATE:
1628 if (!IS_MPLS_UNRESERVED_LABEL(upper_bound)) {
1629 zlog_warn("Invalid SRLB upper bound: %" PRIu32,
1630 upper_bound);
1631 return NB_ERR_VALIDATION;
1632 }
1633 break;
1634 case NB_EV_PREPARE:
1635 case NB_EV_ABORT:
1636 case NB_EV_APPLY:
1637 break;
1638 }
1639
1640 return NB_OK;
1641 }
1642
1643 /*
1644 * XPath: /frr-isisd:isis/instance/segment-routing/msd/node-msd
1645 */
1646 int isis_instance_segment_routing_msd_node_msd_modify(
1647 struct nb_cb_modify_args *args)
1648 {
1649 struct isis_area *area;
1650
1651 if (args->event != NB_EV_APPLY)
1652 return NB_OK;
1653
1654 area = nb_running_get_entry(args->dnode, NULL, true);
1655 area->srdb.config.msd = yang_dnode_get_uint8(args->dnode, NULL);
1656
1657 /* Update and regenerate LSP */
1658 lsp_regenerate_schedule(area, area->is_type, 0);
1659
1660 return NB_OK;
1661 }
1662
1663 int isis_instance_segment_routing_msd_node_msd_destroy(
1664 struct nb_cb_destroy_args *args)
1665 {
1666 struct isis_area *area;
1667
1668 if (args->event != NB_EV_APPLY)
1669 return NB_OK;
1670
1671 area = nb_running_get_entry(args->dnode, NULL, true);
1672 area->srdb.config.msd = 0;
1673
1674 /* Update and regenerate LSP */
1675 lsp_regenerate_schedule(area, area->is_type, 0);
1676
1677 return NB_OK;
1678 }
1679
1680 /*
1681 * XPath: /frr-isisd:isis/instance/segment-routing/prefix-sid-map/prefix-sid
1682 */
1683 int isis_instance_segment_routing_prefix_sid_map_prefix_sid_create(
1684 struct nb_cb_create_args *args)
1685 {
1686 struct isis_area *area;
1687 struct prefix prefix;
1688 struct sr_prefix_cfg *pcfg;
1689
1690 if (args->event != NB_EV_APPLY)
1691 return NB_OK;
1692
1693 area = nb_running_get_entry(args->dnode, NULL, true);
1694 yang_dnode_get_prefix(&prefix, args->dnode, "./prefix");
1695
1696 pcfg = isis_sr_cfg_prefix_add(area, &prefix);
1697 nb_running_set_entry(args->dnode, pcfg);
1698
1699 return NB_OK;
1700 }
1701
1702 int isis_instance_segment_routing_prefix_sid_map_prefix_sid_destroy(
1703 struct nb_cb_destroy_args *args)
1704 {
1705 struct sr_prefix_cfg *pcfg;
1706 struct isis_area *area;
1707
1708 if (args->event != NB_EV_APPLY)
1709 return NB_OK;
1710
1711 pcfg = nb_running_unset_entry(args->dnode);
1712 area = pcfg->area;
1713 isis_sr_cfg_prefix_del(pcfg);
1714 lsp_regenerate_schedule(area, area->is_type, 0);
1715
1716 return NB_OK;
1717 }
1718
1719 int isis_instance_segment_routing_prefix_sid_map_prefix_sid_pre_validate(
1720 struct nb_cb_pre_validate_args *args)
1721 {
1722 uint32_t srgb_lbound;
1723 uint32_t srgb_ubound;
1724 uint32_t srgb_range;
1725 uint32_t sid;
1726 enum sr_sid_value_type sid_type;
1727
1728 srgb_lbound = yang_dnode_get_uint32(args->dnode,
1729 "../../srgb/lower-bound");
1730 srgb_ubound = yang_dnode_get_uint32(args->dnode,
1731 "../../srgb/upper-bound");
1732 sid = yang_dnode_get_uint32(args->dnode, "./sid-value");
1733 sid_type = yang_dnode_get_enum(args->dnode, "./sid-value-type");
1734
1735 srgb_range = srgb_ubound - srgb_lbound + 1;
1736 switch (sid_type) {
1737 case SR_SID_VALUE_TYPE_INDEX:
1738 if (sid >= srgb_range) {
1739 zlog_warn("SID index %u falls outside local SRGB range",
1740 sid);
1741 return NB_ERR_VALIDATION;
1742 }
1743 break;
1744 case SR_SID_VALUE_TYPE_ABSOLUTE:
1745 if (!IS_MPLS_UNRESERVED_LABEL(sid)) {
1746 zlog_warn("Invalid absolute SID %u", sid);
1747 return NB_ERR_VALIDATION;
1748 }
1749 break;
1750 }
1751
1752 return NB_OK;
1753 }
1754
1755 void isis_instance_segment_routing_prefix_sid_map_prefix_sid_apply_finish(
1756 struct nb_cb_apply_finish_args *args)
1757 {
1758 struct sr_prefix_cfg *pcfg;
1759 struct isis_area *area;
1760
1761 pcfg = nb_running_get_entry(args->dnode, NULL, true);
1762 area = pcfg->area;
1763 lsp_regenerate_schedule(area, area->is_type, 0);
1764 }
1765
1766 /*
1767 * XPath:
1768 * /frr-isisd:isis/instance/segment-routing/prefix-sid-map/prefix-sid/sid-value-type
1769 */
1770 int isis_instance_segment_routing_prefix_sid_map_prefix_sid_sid_value_type_modify(
1771 struct nb_cb_modify_args *args)
1772 {
1773 struct sr_prefix_cfg *pcfg;
1774
1775 if (args->event != NB_EV_APPLY)
1776 return NB_OK;
1777
1778 pcfg = nb_running_get_entry(args->dnode, NULL, true);
1779 pcfg->sid_type = yang_dnode_get_enum(args->dnode, NULL);
1780
1781 return NB_OK;
1782 }
1783
1784 /*
1785 * XPath:
1786 * /frr-isisd:isis/instance/segment-routing/prefix-sid-map/prefix-sid/sid-value
1787 */
1788 int isis_instance_segment_routing_prefix_sid_map_prefix_sid_sid_value_modify(
1789 struct nb_cb_modify_args *args)
1790 {
1791 struct sr_prefix_cfg *pcfg;
1792
1793 if (args->event != NB_EV_APPLY)
1794 return NB_OK;
1795
1796 pcfg = nb_running_get_entry(args->dnode, NULL, true);
1797 pcfg->sid = yang_dnode_get_uint32(args->dnode, NULL);
1798
1799 return NB_OK;
1800 }
1801
1802 /*
1803 * XPath:
1804 * /frr-isisd:isis/instance/segment-routing/prefix-sid-map/prefix-sid/last-hop-behavior
1805 */
1806 int isis_instance_segment_routing_prefix_sid_map_prefix_sid_last_hop_behavior_modify(
1807 struct nb_cb_modify_args *args)
1808 {
1809 struct sr_prefix_cfg *pcfg;
1810
1811 if (args->event != NB_EV_APPLY)
1812 return NB_OK;
1813
1814 pcfg = nb_running_get_entry(args->dnode, NULL, true);
1815 pcfg->last_hop_behavior = yang_dnode_get_enum(args->dnode, NULL);
1816
1817 return NB_OK;
1818 }
1819
1820 /*
1821 * XPath: /frr-interface:lib/interface/frr-isisd:isis
1822 */
1823 int lib_interface_isis_create(struct nb_cb_create_args *args)
1824 {
1825 struct isis_area *area;
1826 struct interface *ifp;
1827 struct isis_circuit *circuit;
1828 const char *area_tag = yang_dnode_get_string(args->dnode, "./area-tag");
1829 uint32_t min_mtu, actual_mtu;
1830
1831 switch (args->event) {
1832 case NB_EV_PREPARE:
1833 case NB_EV_ABORT:
1834 break;
1835 case NB_EV_VALIDATE:
1836 /* check if interface mtu is sufficient. If the area has not
1837 * been created yet, assume default MTU for the area
1838 */
1839 ifp = nb_running_get_entry(args->dnode, NULL, false);
1840 /* zebra might not know yet about the MTU - nothing we can do */
1841 if (!ifp || ifp->mtu == 0)
1842 break;
1843 actual_mtu =
1844 if_is_broadcast(ifp) ? ifp->mtu - LLC_LEN : ifp->mtu;
1845 area = isis_area_lookup(area_tag);
1846 if (area)
1847 min_mtu = area->lsp_mtu;
1848 else
1849 #ifndef FABRICD
1850 min_mtu = yang_get_default_uint16(
1851 "/frr-isisd:isis/instance/lsp/mtu");
1852 #else
1853 min_mtu = DEFAULT_LSP_MTU;
1854 #endif /* ifndef FABRICD */
1855 if (actual_mtu < min_mtu) {
1856 snprintf(args->errmsg, args->errmsg_len,
1857 "Interface %s has MTU %" PRIu32
1858 ", minimum MTU for the area is %" PRIu32 "",
1859 ifp->name, actual_mtu, min_mtu);
1860 return NB_ERR_VALIDATION;
1861 }
1862 break;
1863 case NB_EV_APPLY:
1864 area = isis_area_lookup(area_tag);
1865 /* The area should have already be created. We are
1866 * setting the priority of the global isis area creation
1867 * slightly lower, so it should be executed first, but I
1868 * cannot rely on that so here I have to check.
1869 */
1870 if (!area) {
1871 flog_err(
1872 EC_LIB_NB_CB_CONFIG_APPLY,
1873 "%s: attempt to create circuit for area %s before the area has been created",
1874 __func__, area_tag);
1875 abort();
1876 }
1877
1878 ifp = nb_running_get_entry(args->dnode, NULL, true);
1879 circuit = isis_circuit_create(area, ifp);
1880 assert(circuit
1881 && (circuit->state == C_STATE_CONF
1882 || circuit->state == C_STATE_UP));
1883 nb_running_set_entry(args->dnode, circuit);
1884 break;
1885 }
1886
1887 return NB_OK;
1888 }
1889
1890 int lib_interface_isis_destroy(struct nb_cb_destroy_args *args)
1891 {
1892 struct isis_circuit *circuit;
1893
1894 if (args->event != NB_EV_APPLY)
1895 return NB_OK;
1896
1897 circuit = nb_running_unset_entry(args->dnode);
1898 if (!circuit)
1899 return NB_ERR_INCONSISTENCY;
1900
1901 /* disable both AFs for this circuit. this will also update the
1902 * CSM state by sending an ISIS_DISABLED signal. If there is no
1903 * area associated to the circuit there is nothing to do
1904 */
1905 if (circuit->area)
1906 isis_circuit_af_set(circuit, false, false);
1907 return NB_OK;
1908 }
1909
1910 /*
1911 * XPath: /frr-interface:lib/interface/frr-isisd:isis/area-tag
1912 */
1913 int lib_interface_isis_area_tag_modify(struct nb_cb_modify_args *args)
1914 {
1915 struct isis_circuit *circuit;
1916 struct interface *ifp;
1917 struct vrf *vrf;
1918 const char *area_tag, *ifname, *vrfname;
1919
1920 if (args->event == NB_EV_VALIDATE) {
1921 /* libyang doesn't like relative paths across module boundaries
1922 */
1923 ifname = yang_dnode_get_string(args->dnode->parent->parent,
1924 "./name");
1925 vrfname = yang_dnode_get_string(args->dnode->parent->parent,
1926 "./vrf");
1927 vrf = vrf_lookup_by_name(vrfname);
1928 assert(vrf);
1929 ifp = if_lookup_by_name(ifname, vrf->vrf_id);
1930 if (!ifp)
1931 return NB_OK;
1932 circuit = circuit_lookup_by_ifp(ifp, isis->init_circ_list);
1933 area_tag = yang_dnode_get_string(args->dnode, NULL);
1934 if (circuit && circuit->area && circuit->area->area_tag
1935 && strcmp(circuit->area->area_tag, area_tag)) {
1936 snprintf(args->errmsg, args->errmsg_len,
1937 "ISIS circuit is already defined on %s",
1938 circuit->area->area_tag);
1939 return NB_ERR_VALIDATION;
1940 }
1941 }
1942
1943 return NB_OK;
1944 }
1945
1946 /*
1947 * XPath: /frr-interface:lib/interface/frr-isisd:isis/circuit-type
1948 */
1949 int lib_interface_isis_circuit_type_modify(struct nb_cb_modify_args *args)
1950 {
1951 int circ_type = yang_dnode_get_enum(args->dnode, NULL);
1952 struct isis_circuit *circuit;
1953 struct interface *ifp;
1954 struct vrf *vrf;
1955 const char *ifname, *vrfname;
1956
1957 switch (args->event) {
1958 case NB_EV_VALIDATE:
1959 /* libyang doesn't like relative paths across module boundaries
1960 */
1961 ifname = yang_dnode_get_string(args->dnode->parent->parent,
1962 "./name");
1963 vrfname = yang_dnode_get_string(args->dnode->parent->parent,
1964 "./vrf");
1965 vrf = vrf_lookup_by_name(vrfname);
1966 assert(vrf);
1967 ifp = if_lookup_by_name(ifname, vrf->vrf_id);
1968 if (!ifp)
1969 break;
1970 circuit = circuit_lookup_by_ifp(ifp, isis->init_circ_list);
1971 if (circuit && circuit->state == C_STATE_UP
1972 && circuit->area->is_type != IS_LEVEL_1_AND_2
1973 && circuit->area->is_type != circ_type) {
1974 snprintf(args->errmsg, args->errmsg_len,
1975 "Invalid circuit level for area %s",
1976 circuit->area->area_tag);
1977 return NB_ERR_VALIDATION;
1978 }
1979 break;
1980 case NB_EV_PREPARE:
1981 case NB_EV_ABORT:
1982 break;
1983 case NB_EV_APPLY:
1984 circuit = nb_running_get_entry(args->dnode, NULL, true);
1985 isis_circuit_is_type_set(circuit, circ_type);
1986 break;
1987 }
1988
1989 return NB_OK;
1990 }
1991
1992 /*
1993 * XPath: /frr-interface:lib/interface/frr-isisd:isis/ipv4-routing
1994 */
1995 int lib_interface_isis_ipv4_routing_modify(struct nb_cb_modify_args *args)
1996 {
1997 bool ipv4, ipv6;
1998 struct isis_circuit *circuit;
1999
2000 if (args->event != NB_EV_APPLY)
2001 return NB_OK;
2002
2003 circuit = nb_running_get_entry(args->dnode, NULL, true);
2004 ipv4 = yang_dnode_get_bool(args->dnode, NULL);
2005 ipv6 = yang_dnode_get_bool(args->dnode, "../ipv6-routing");
2006 isis_circuit_af_set(circuit, ipv4, ipv6);
2007
2008 return NB_OK;
2009 }
2010
2011 /*
2012 * XPath: /frr-interface:lib/interface/frr-isisd:isis/ipv6-routing
2013 */
2014 int lib_interface_isis_ipv6_routing_modify(struct nb_cb_modify_args *args)
2015 {
2016 bool ipv4, ipv6;
2017 struct isis_circuit *circuit;
2018
2019 if (args->event != NB_EV_APPLY)
2020 return NB_OK;
2021
2022 circuit = nb_running_get_entry(args->dnode, NULL, true);
2023 ipv4 = yang_dnode_exists(args->dnode, "../ipv4-routing");
2024 ipv6 = yang_dnode_get_bool(args->dnode, NULL);
2025 isis_circuit_af_set(circuit, ipv4, ipv6);
2026
2027 return NB_OK;
2028 }
2029
2030 /*
2031 * XPath: /frr-interface:lib/interface/frr-isisd:isis/bfd-monitoring
2032 */
2033 int lib_interface_isis_bfd_monitoring_modify(struct nb_cb_modify_args *args)
2034 {
2035 struct isis_circuit *circuit;
2036 bool bfd_monitoring;
2037
2038 if (args->event != NB_EV_APPLY)
2039 return NB_OK;
2040
2041 circuit = nb_running_get_entry(args->dnode, NULL, true);
2042 bfd_monitoring = yang_dnode_get_bool(args->dnode, NULL);
2043
2044 if (bfd_monitoring) {
2045 isis_bfd_circuit_param_set(circuit, BFD_DEF_MIN_RX,
2046 BFD_DEF_MIN_TX, BFD_DEF_DETECT_MULT,
2047 true);
2048 } else {
2049 isis_bfd_circuit_cmd(circuit, ZEBRA_BFD_DEST_DEREGISTER);
2050 bfd_info_free(&circuit->bfd_info);
2051 }
2052
2053 return NB_OK;
2054 }
2055
2056 /*
2057 * XPath: /frr-interface:lib/interface/frr-isisd:isis/csnp-interval/level-1
2058 */
2059 int lib_interface_isis_csnp_interval_level_1_modify(
2060 struct nb_cb_modify_args *args)
2061 {
2062 struct isis_circuit *circuit;
2063
2064 if (args->event != NB_EV_APPLY)
2065 return NB_OK;
2066
2067 circuit = nb_running_get_entry(args->dnode, NULL, true);
2068 circuit->csnp_interval[0] = yang_dnode_get_uint16(args->dnode, NULL);
2069
2070 return NB_OK;
2071 }
2072
2073 /*
2074 * XPath: /frr-interface:lib/interface/frr-isisd:isis/csnp-interval/level-2
2075 */
2076 int lib_interface_isis_csnp_interval_level_2_modify(
2077 struct nb_cb_modify_args *args)
2078 {
2079 struct isis_circuit *circuit;
2080
2081 if (args->event != NB_EV_APPLY)
2082 return NB_OK;
2083
2084 circuit = nb_running_get_entry(args->dnode, NULL, true);
2085 circuit->csnp_interval[1] = yang_dnode_get_uint16(args->dnode, NULL);
2086
2087 return NB_OK;
2088 }
2089
2090 /*
2091 * XPath: /frr-interface:lib/interface/frr-isisd:isis/psnp-interval/level-1
2092 */
2093 int lib_interface_isis_psnp_interval_level_1_modify(
2094 struct nb_cb_modify_args *args)
2095 {
2096 struct isis_circuit *circuit;
2097
2098 if (args->event != NB_EV_APPLY)
2099 return NB_OK;
2100
2101 circuit = nb_running_get_entry(args->dnode, NULL, true);
2102 circuit->psnp_interval[0] = yang_dnode_get_uint16(args->dnode, NULL);
2103
2104 return NB_OK;
2105 }
2106
2107 /*
2108 * XPath: /frr-interface:lib/interface/frr-isisd:isis/psnp-interval/level-2
2109 */
2110 int lib_interface_isis_psnp_interval_level_2_modify(
2111 struct nb_cb_modify_args *args)
2112 {
2113 struct isis_circuit *circuit;
2114
2115 if (args->event != NB_EV_APPLY)
2116 return NB_OK;
2117
2118 circuit = nb_running_get_entry(args->dnode, NULL, true);
2119 circuit->psnp_interval[1] = yang_dnode_get_uint16(args->dnode, NULL);
2120
2121 return NB_OK;
2122 }
2123
2124 /*
2125 * XPath: /frr-interface:lib/interface/frr-isisd:isis/hello/padding
2126 */
2127 int lib_interface_isis_hello_padding_modify(struct nb_cb_modify_args *args)
2128 {
2129 struct isis_circuit *circuit;
2130
2131 if (args->event != NB_EV_APPLY)
2132 return NB_OK;
2133
2134 circuit = nb_running_get_entry(args->dnode, NULL, true);
2135 circuit->pad_hellos = yang_dnode_get_bool(args->dnode, NULL);
2136
2137 return NB_OK;
2138 }
2139
2140 /*
2141 * XPath: /frr-interface:lib/interface/frr-isisd:isis/hello/interval/level-1
2142 */
2143 int lib_interface_isis_hello_interval_level_1_modify(
2144 struct nb_cb_modify_args *args)
2145 {
2146 struct isis_circuit *circuit;
2147 uint32_t interval;
2148
2149 if (args->event != NB_EV_APPLY)
2150 return NB_OK;
2151
2152 circuit = nb_running_get_entry(args->dnode, NULL, true);
2153 interval = yang_dnode_get_uint32(args->dnode, NULL);
2154 circuit->hello_interval[0] = interval;
2155
2156 return NB_OK;
2157 }
2158
2159 /*
2160 * XPath: /frr-interface:lib/interface/frr-isisd:isis/hello/interval/level-2
2161 */
2162 int lib_interface_isis_hello_interval_level_2_modify(
2163 struct nb_cb_modify_args *args)
2164 {
2165 struct isis_circuit *circuit;
2166 uint32_t interval;
2167
2168 if (args->event != NB_EV_APPLY)
2169 return NB_OK;
2170
2171 circuit = nb_running_get_entry(args->dnode, NULL, true);
2172 interval = yang_dnode_get_uint32(args->dnode, NULL);
2173 circuit->hello_interval[1] = interval;
2174
2175 return NB_OK;
2176 }
2177
2178 /*
2179 * XPath: /frr-interface:lib/interface/frr-isisd:isis/hello/multiplier/level-1
2180 */
2181 int lib_interface_isis_hello_multiplier_level_1_modify(
2182 struct nb_cb_modify_args *args)
2183 {
2184 struct isis_circuit *circuit;
2185 uint16_t multi;
2186
2187 if (args->event != NB_EV_APPLY)
2188 return NB_OK;
2189
2190 circuit = nb_running_get_entry(args->dnode, NULL, true);
2191 multi = yang_dnode_get_uint16(args->dnode, NULL);
2192 circuit->hello_multiplier[0] = multi;
2193
2194 return NB_OK;
2195 }
2196
2197 /*
2198 * XPath: /frr-interface:lib/interface/frr-isisd:isis/hello/multiplier/level-2
2199 */
2200 int lib_interface_isis_hello_multiplier_level_2_modify(
2201 struct nb_cb_modify_args *args)
2202 {
2203 struct isis_circuit *circuit;
2204 uint16_t multi;
2205
2206 if (args->event != NB_EV_APPLY)
2207 return NB_OK;
2208
2209 circuit = nb_running_get_entry(args->dnode, NULL, true);
2210 multi = yang_dnode_get_uint16(args->dnode, NULL);
2211 circuit->hello_multiplier[1] = multi;
2212
2213 return NB_OK;
2214 }
2215
2216 /*
2217 * XPath: /frr-interface:lib/interface/frr-isisd:isis/metric/level-1
2218 */
2219 int lib_interface_isis_metric_level_1_modify(struct nb_cb_modify_args *args)
2220 {
2221 struct isis_circuit *circuit;
2222 unsigned int met;
2223
2224 if (args->event != NB_EV_APPLY)
2225 return NB_OK;
2226
2227 circuit = nb_running_get_entry(args->dnode, NULL, true);
2228 met = yang_dnode_get_uint32(args->dnode, NULL);
2229 isis_circuit_metric_set(circuit, IS_LEVEL_1, met);
2230
2231 return NB_OK;
2232 }
2233
2234 /*
2235 * XPath: /frr-interface:lib/interface/frr-isisd:isis/metric/level-2
2236 */
2237 int lib_interface_isis_metric_level_2_modify(struct nb_cb_modify_args *args)
2238 {
2239 struct isis_circuit *circuit;
2240 unsigned int met;
2241
2242 if (args->event != NB_EV_APPLY)
2243 return NB_OK;
2244
2245 circuit = nb_running_get_entry(args->dnode, NULL, true);
2246 met = yang_dnode_get_uint32(args->dnode, NULL);
2247 isis_circuit_metric_set(circuit, IS_LEVEL_2, met);
2248
2249 return NB_OK;
2250 }
2251
2252 /*
2253 * XPath: /frr-interface:lib/interface/frr-isisd:isis/priority/level-1
2254 */
2255 int lib_interface_isis_priority_level_1_modify(struct nb_cb_modify_args *args)
2256 {
2257 struct isis_circuit *circuit;
2258
2259 if (args->event != NB_EV_APPLY)
2260 return NB_OK;
2261
2262 circuit = nb_running_get_entry(args->dnode, NULL, true);
2263 circuit->priority[0] = yang_dnode_get_uint8(args->dnode, NULL);
2264
2265 return NB_OK;
2266 }
2267
2268 /*
2269 * XPath: /frr-interface:lib/interface/frr-isisd:isis/priority/level-2
2270 */
2271 int lib_interface_isis_priority_level_2_modify(struct nb_cb_modify_args *args)
2272 {
2273 struct isis_circuit *circuit;
2274
2275 if (args->event != NB_EV_APPLY)
2276 return NB_OK;
2277
2278 circuit = nb_running_get_entry(args->dnode, NULL, true);
2279 circuit->priority[1] = yang_dnode_get_uint8(args->dnode, NULL);
2280
2281 return NB_OK;
2282 }
2283
2284 /*
2285 * XPath: /frr-interface:lib/interface/frr-isisd:isis/network-type
2286 */
2287 int lib_interface_isis_network_type_modify(struct nb_cb_modify_args *args)
2288 {
2289 struct isis_circuit *circuit;
2290 int net_type = yang_dnode_get_enum(args->dnode, NULL);
2291
2292 switch (args->event) {
2293 case NB_EV_VALIDATE:
2294 circuit = nb_running_get_entry(args->dnode, NULL, false);
2295 if (!circuit)
2296 break;
2297 if (circuit->circ_type == CIRCUIT_T_LOOPBACK) {
2298 snprintf(
2299 args->errmsg, args->errmsg_len,
2300 "Cannot change network type on loopback interface");
2301 return NB_ERR_VALIDATION;
2302 }
2303 if (net_type == CIRCUIT_T_BROADCAST
2304 && circuit->state == C_STATE_UP
2305 && !if_is_broadcast(circuit->interface)) {
2306 snprintf(
2307 args->errmsg, args->errmsg_len,
2308 "Cannot configure non-broadcast interface for broadcast operation");
2309 return NB_ERR_VALIDATION;
2310 }
2311 break;
2312 case NB_EV_PREPARE:
2313 case NB_EV_ABORT:
2314 break;
2315 case NB_EV_APPLY:
2316 circuit = nb_running_get_entry(args->dnode, NULL, true);
2317 isis_circuit_circ_type_set(circuit, net_type);
2318 break;
2319 }
2320
2321 return NB_OK;
2322 }
2323
2324 /*
2325 * XPath: /frr-interface:lib/interface/frr-isisd:isis/passive
2326 */
2327 int lib_interface_isis_passive_modify(struct nb_cb_modify_args *args)
2328 {
2329 struct isis_circuit *circuit;
2330 struct isis_area *area;
2331 struct interface *ifp;
2332 bool passive = yang_dnode_get_bool(args->dnode, NULL);
2333
2334 /* validation only applies if we are setting passive to false */
2335 if (!passive && args->event == NB_EV_VALIDATE) {
2336 circuit = nb_running_get_entry(args->dnode, NULL, false);
2337 if (!circuit)
2338 return NB_OK;
2339 ifp = circuit->interface;
2340 if (!ifp)
2341 return NB_OK;
2342 if (if_is_loopback(ifp)) {
2343 snprintf(args->errmsg, args->errmsg_len,
2344 "Loopback is always passive");
2345 return NB_ERR_VALIDATION;
2346 }
2347 }
2348
2349 if (args->event != NB_EV_APPLY)
2350 return NB_OK;
2351
2352 circuit = nb_running_get_entry(args->dnode, NULL, true);
2353 if (circuit->state != C_STATE_UP) {
2354 circuit->is_passive = passive;
2355 } else {
2356 area = circuit->area;
2357 isis_csm_state_change(ISIS_DISABLE, circuit, area);
2358 circuit->is_passive = passive;
2359 isis_csm_state_change(ISIS_ENABLE, circuit, area);
2360 }
2361
2362 return NB_OK;
2363 }
2364
2365 /*
2366 * XPath: /frr-interface:lib/interface/frr-isisd:isis/password
2367 */
2368 int lib_interface_isis_password_create(struct nb_cb_create_args *args)
2369 {
2370 return NB_OK;
2371 }
2372
2373 int lib_interface_isis_password_destroy(struct nb_cb_destroy_args *args)
2374 {
2375 struct isis_circuit *circuit;
2376
2377 if (args->event != NB_EV_APPLY)
2378 return NB_OK;
2379
2380 circuit = nb_running_get_entry(args->dnode, NULL, true);
2381 isis_circuit_passwd_unset(circuit);
2382
2383 return NB_OK;
2384 }
2385
2386 /*
2387 * XPath: /frr-interface:lib/interface/frr-isisd:isis/password/password
2388 */
2389 int lib_interface_isis_password_password_modify(struct nb_cb_modify_args *args)
2390 {
2391 struct isis_circuit *circuit;
2392 const char *password;
2393
2394 if (args->event != NB_EV_APPLY)
2395 return NB_OK;
2396
2397 password = yang_dnode_get_string(args->dnode, NULL);
2398 circuit = nb_running_get_entry(args->dnode, NULL, true);
2399
2400 isis_circuit_passwd_set(circuit, circuit->passwd.type, password);
2401
2402 return NB_OK;
2403 }
2404
2405 /*
2406 * XPath: /frr-interface:lib/interface/frr-isisd:isis/password/password-type
2407 */
2408 int lib_interface_isis_password_password_type_modify(
2409 struct nb_cb_modify_args *args)
2410 {
2411 struct isis_circuit *circuit;
2412 uint8_t pass_type;
2413
2414 if (args->event != NB_EV_APPLY)
2415 return NB_OK;
2416
2417 pass_type = yang_dnode_get_enum(args->dnode, NULL);
2418 circuit = nb_running_get_entry(args->dnode, NULL, true);
2419 circuit->passwd.type = pass_type;
2420
2421 return NB_OK;
2422 }
2423
2424 /*
2425 * XPath:
2426 * /frr-interface:lib/interface/frr-isisd:isis/disable-three-way-handshake
2427 */
2428 int lib_interface_isis_disable_three_way_handshake_modify(
2429 struct nb_cb_modify_args *args)
2430 {
2431 struct isis_circuit *circuit;
2432
2433 if (args->event != NB_EV_APPLY)
2434 return NB_OK;
2435
2436 circuit = nb_running_get_entry(args->dnode, NULL, true);
2437 circuit->disable_threeway_adj = yang_dnode_get_bool(args->dnode, NULL);
2438
2439 return NB_OK;
2440 }
2441
2442 /*
2443 * XPath:
2444 * /frr-interface:lib/interface/frr-isisd:isis/multi-topology/ipv4-unicast
2445 */
2446 static int lib_interface_isis_multi_topology_common(
2447 enum nb_event event, const struct lyd_node *dnode, char *errmsg,
2448 size_t errmsg_len, uint16_t mtid)
2449 {
2450 struct isis_circuit *circuit;
2451 bool value;
2452
2453 switch (event) {
2454 case NB_EV_VALIDATE:
2455 circuit = nb_running_get_entry(dnode, NULL, false);
2456 if (circuit && circuit->area && circuit->area->oldmetric) {
2457 snprintf(
2458 errmsg, errmsg_len,
2459 "Multi topology IS-IS can only be used with wide metrics");
2460 return NB_ERR_VALIDATION;
2461 }
2462 break;
2463 case NB_EV_PREPARE:
2464 case NB_EV_ABORT:
2465 break;
2466 case NB_EV_APPLY:
2467 circuit = nb_running_get_entry(dnode, NULL, true);
2468 value = yang_dnode_get_bool(dnode, NULL);
2469 isis_circuit_mt_enabled_set(circuit, mtid, value);
2470 break;
2471 }
2472
2473 return NB_OK;
2474 }
2475
2476 int lib_interface_isis_multi_topology_ipv4_unicast_modify(
2477 struct nb_cb_modify_args *args)
2478 {
2479 return lib_interface_isis_multi_topology_common(
2480 args->event, args->dnode, args->errmsg, args->errmsg_len,
2481 ISIS_MT_IPV4_UNICAST);
2482 }
2483
2484 /*
2485 * XPath:
2486 * /frr-interface:lib/interface/frr-isisd:isis/multi-topology/ipv4-multicast
2487 */
2488 int lib_interface_isis_multi_topology_ipv4_multicast_modify(
2489 struct nb_cb_modify_args *args)
2490 {
2491 return lib_interface_isis_multi_topology_common(
2492 args->event, args->dnode, args->errmsg, args->errmsg_len,
2493 ISIS_MT_IPV4_MULTICAST);
2494 }
2495
2496 /*
2497 * XPath:
2498 * /frr-interface:lib/interface/frr-isisd:isis/multi-topology/ipv4-management
2499 */
2500 int lib_interface_isis_multi_topology_ipv4_management_modify(
2501 struct nb_cb_modify_args *args)
2502 {
2503 return lib_interface_isis_multi_topology_common(
2504 args->event, args->dnode, args->errmsg, args->errmsg_len,
2505 ISIS_MT_IPV4_MGMT);
2506 }
2507
2508 /*
2509 * XPath:
2510 * /frr-interface:lib/interface/frr-isisd:isis/multi-topology/ipv6-unicast
2511 */
2512 int lib_interface_isis_multi_topology_ipv6_unicast_modify(
2513 struct nb_cb_modify_args *args)
2514 {
2515 return lib_interface_isis_multi_topology_common(
2516 args->event, args->dnode, args->errmsg, args->errmsg_len,
2517 ISIS_MT_IPV6_UNICAST);
2518 }
2519
2520 /*
2521 * XPath:
2522 * /frr-interface:lib/interface/frr-isisd:isis/multi-topology/ipv6-multicast
2523 */
2524 int lib_interface_isis_multi_topology_ipv6_multicast_modify(
2525 struct nb_cb_modify_args *args)
2526 {
2527 return lib_interface_isis_multi_topology_common(
2528 args->event, args->dnode, args->errmsg, args->errmsg_len,
2529 ISIS_MT_IPV6_MULTICAST);
2530 }
2531
2532 /*
2533 * XPath:
2534 * /frr-interface:lib/interface/frr-isisd:isis/multi-topology/ipv6-management
2535 */
2536 int lib_interface_isis_multi_topology_ipv6_management_modify(
2537 struct nb_cb_modify_args *args)
2538 {
2539 return lib_interface_isis_multi_topology_common(
2540 args->event, args->dnode, args->errmsg, args->errmsg_len,
2541 ISIS_MT_IPV6_MGMT);
2542 }
2543
2544 /*
2545 * XPath: /frr-interface:lib/interface/frr-isisd:isis/multi-topology/ipv6-dstsrc
2546 */
2547 int lib_interface_isis_multi_topology_ipv6_dstsrc_modify(
2548 struct nb_cb_modify_args *args)
2549 {
2550 return lib_interface_isis_multi_topology_common(
2551 args->event, args->dnode, args->errmsg, args->errmsg_len,
2552 ISIS_MT_IPV6_DSTSRC);
2553 }