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