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