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