1 /*
2  * Copyright (C) 2001,2002   Sampo Saaristo
3  *                           Tampere University of Technology
4  *                           Institute of Communications Engineering
5  * Copyright (C) 2018        Volta Networks
6  *                           Emanuele Di Pascale
7  *
8  * This program is free software; you can redistribute it and/or modify it
9  * under the terms of the GNU General Public License as published by the Free
10  * Software Foundation; either version 2 of the License, or (at your option)
11  * any later version.
12  *
13  * This program is distributed in the hope that it will be useful, but WITHOUT
14  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
16  * more details.
17  *
18  * You should have received a copy of the GNU General Public License along
19  * with this program; see the file COPYING; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22 
23 #include <zebra.h>
24 
25 #include "if.h"
26 #include "vrf.h"
27 #include "log.h"
28 #include "prefix.h"
29 #include "command.h"
30 #include "northbound_cli.h"
31 #include "libfrr.h"
32 #include "yang.h"
33 #include "lib/linklist.h"
34 #include "isisd/isisd.h"
35 #include "isisd/isis_nb.h"
36 #include "isisd/isis_misc.h"
37 #include "isisd/isis_circuit.h"
38 #include "isisd/isis_csm.h"
39 
40 #ifndef VTYSH_EXTRACT_PL
41 #include "isisd/isis_cli_clippy.c"
42 #endif
43 
44 #ifndef FABRICD
45 
46 /*
47  * XPath: /frr-isisd:isis/instance
48  */
49 DEFPY_YANG_NOSH(router_isis, router_isis_cmd,
50 		"router isis WORD$tag [vrf NAME$vrf_name]",
51 		ROUTER_STR
52 		"ISO IS-IS\n"
53 		"ISO Routing area tag\n" VRF_CMD_HELP_STR)
54 {
55 	int ret;
56 	char base_xpath[XPATH_MAXLEN];
57 
58 	if (!vrf_name)
59 		vrf_name = VRF_DEFAULT_NAME;
60 
61 	snprintf(base_xpath, XPATH_MAXLEN,
62 		 "/frr-isisd:isis/instance[area-tag='%s'][vrf='%s']", tag,
63 		 vrf_name);
64 	nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
65 	/* default value in yang for is-type is level-1, but in FRR
66 	 * the first instance is assigned is-type level-1-2. We
67 	 * need to make sure to set it in the yang model so that it
68 	 * is consistent with what FRR sees.
69 	 */
70 
71 	if (!im) {
72 		return CMD_SUCCESS;
73 	}
74 
75 	if (listcount(im->isis) == 0)
76 		nb_cli_enqueue_change(vty, "./is-type", NB_OP_MODIFY,
77 				      "level-1-2");
78 	ret = nb_cli_apply_changes(vty, base_xpath);
79 	if (ret == CMD_SUCCESS)
80 		VTY_PUSH_XPATH(ISIS_NODE, base_xpath);
81 
82 	return ret;
83 }
84 
85 DEFPY_YANG(no_router_isis, no_router_isis_cmd,
86 	   "no router isis WORD$tag [vrf NAME$vrf_name]",
87 	   NO_STR ROUTER_STR
88 	   "ISO IS-IS\n"
89 	   "ISO Routing area tag\n" VRF_CMD_HELP_STR)
90 {
91 	char temp_xpath[XPATH_MAXLEN];
92 	struct listnode *node, *nnode;
93 	struct isis_circuit *circuit = NULL;
94 	struct isis_area *area = NULL;
95 
96 	if (!vrf_name)
97 		vrf_name = VRF_DEFAULT_NAME;
98 
99 	if (!yang_dnode_exists(
100 		    vty->candidate_config->dnode,
101 		    "/frr-isisd:isis/instance[area-tag='%s'][vrf='%s']", tag,
102 		    vrf_name)) {
103 		vty_out(vty, "ISIS area %s not found.\n", tag);
104 		return CMD_ERR_NOTHING_TODO;
105 	}
106 
107 	nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
108 	area = isis_area_lookup_by_vrf(tag, vrf_name);
109 	if (area && area->circuit_list && listcount(area->circuit_list)) {
110 		for (ALL_LIST_ELEMENTS(area->circuit_list, node, nnode,
111 				       circuit)) {
112 			/* add callbacks to delete each of the circuits listed
113 			 */
114 			const char *vrf_name =
115 				vrf_lookup_by_id(circuit->interface->vrf_id)
116 					->name;
117 			snprintf(
118 				temp_xpath, XPATH_MAXLEN,
119 				"/frr-interface:lib/interface[name='%s'][vrf='%s']/frr-isisd:isis",
120 				circuit->interface->name, vrf_name);
121 			nb_cli_enqueue_change(vty, temp_xpath, NB_OP_DESTROY,
122 					      NULL);
123 		}
124 	}
125 
126 	return nb_cli_apply_changes(
127 		vty, "/frr-isisd:isis/instance[area-tag='%s'][vrf='%s']", tag,
128 		vrf_name);
129 }
130 
cli_show_router_isis(struct vty * vty,struct lyd_node * dnode,bool show_defaults)131 void cli_show_router_isis(struct vty *vty, struct lyd_node *dnode,
132 			  bool show_defaults)
133 {
134 	const char *vrf = NULL;
135 
136 	vrf = yang_dnode_get_string(dnode, "./vrf");
137 
138 	vty_out(vty, "!\n");
139 	vty_out(vty, "router isis %s ",
140 		yang_dnode_get_string(dnode, "./area-tag"));
141 	if (!strmatch(vrf, VRF_DEFAULT_NAME))
142 		vty_out(vty, "vrf %s", yang_dnode_get_string(dnode, "./vrf"));
143 	vty_out(vty, "\n");
144 }
145 
146 /*
147  * XPath: /frr-interface:lib/interface/frr-isisd:isis/
148  * XPath: /frr-interface:lib/interface/frr-isisd:isis/ipv4-routing
149  * XPath: /frr-interface:lib/interface/frr-isisd:isis/ipv6-routing
150  * XPath: /frr-isisd:isis/instance
151  */
152 DEFPY_YANG(ip_router_isis, ip_router_isis_cmd,
153 	   "ip router isis WORD$tag [vrf NAME$vrf_name]",
154 	   "Interface Internet Protocol config commands\n"
155 	   "IP router interface commands\n"
156 	   "IS-IS routing protocol\n"
157 	   "Routing process tag\n" VRF_CMD_HELP_STR)
158 {
159 	char temp_xpath[XPATH_MAXLEN];
160 	const char *circ_type;
161 	struct isis_area *area = NULL;
162 	struct interface *ifp;
163 	struct vrf *vrf;
164 
165 	/* area will be created if it is not present. make sure the yang model
166 	 * is synced with FRR and call the appropriate NB cb.
167 	 */
168 
169 	if (!im) {
170 		return CMD_SUCCESS;
171 	}
172 	ifp = nb_running_get_entry(NULL, VTY_CURR_XPATH, false);
173 	if (!vrf_name) {
174 		if (ifp) {
175 			if (ifp->vrf_id == VRF_DEFAULT)
176 				vrf_name = VRF_DEFAULT_NAME;
177 			else {
178 				vrf = vrf_lookup_by_id(ifp->vrf_id);
179 				if (vrf && !vrf_name)
180 					vrf_name = vrf->name;
181 			}
182 		} else
183 			vrf_name = VRF_DEFAULT_NAME;
184 	}
185 
186 	area = isis_area_lookup_by_vrf(tag, vrf_name);
187 	if (!area) {
188 		isis_global_instance_create(vrf_name);
189 		snprintf(temp_xpath, XPATH_MAXLEN,
190 			 "/frr-isisd:isis/instance[area-tag='%s'][vrf='%s']",
191 			 tag, vrf_name);
192 		nb_cli_enqueue_change(vty, temp_xpath, NB_OP_CREATE, tag);
193 		snprintf(
194 			temp_xpath, XPATH_MAXLEN,
195 			"/frr-isisd:isis/instance[area-tag='%s'][vrf='%s']/is-type",
196 			tag, vrf_name);
197 		nb_cli_enqueue_change(vty, temp_xpath, NB_OP_MODIFY,
198 				      listcount(im->isis) == 0 ? "level-1-2"
199 							       : NULL);
200 		nb_cli_enqueue_change(vty, "./frr-isisd:isis", NB_OP_CREATE,
201 				      NULL);
202 		nb_cli_enqueue_change(vty, "./frr-isisd:isis/area-tag",
203 				      NB_OP_MODIFY, tag);
204 
205 		nb_cli_enqueue_change(vty, "./frr-isisd:isis/vrf", NB_OP_MODIFY,
206 				      vrf_name);
207 		nb_cli_enqueue_change(vty, "./frr-isisd:isis/ipv4-routing",
208 				      NB_OP_MODIFY, "true");
209 		nb_cli_enqueue_change(
210 			vty, "./frr-isisd:isis/circuit-type", NB_OP_MODIFY,
211 			listcount(im->isis) == 0 ? "level-1-2" : "level-1");
212 	} else {
213 		/* area exists, circuit type defaults to its area's is_type */
214 		switch (area->is_type) {
215 		case IS_LEVEL_1:
216 			circ_type = "level-1";
217 			break;
218 		case IS_LEVEL_2:
219 			circ_type = "level-2";
220 			break;
221 		case IS_LEVEL_1_AND_2:
222 			circ_type = "level-1-2";
223 			break;
224 		default:
225 			/* just to silence compiler warnings */
226 			return CMD_WARNING_CONFIG_FAILED;
227 		}
228 		nb_cli_enqueue_change(vty, "./frr-isisd:isis", NB_OP_CREATE,
229 				      NULL);
230 		nb_cli_enqueue_change(vty, "./frr-isisd:isis/area-tag",
231 				      NB_OP_MODIFY, tag);
232 		nb_cli_enqueue_change(vty, "./frr-isisd:isis/vrf", NB_OP_MODIFY,
233 				      vrf_name);
234 
235 		nb_cli_enqueue_change(vty, "./frr-isisd:isis/ipv4-routing",
236 				      NB_OP_MODIFY, "true");
237 		nb_cli_enqueue_change(vty, "./frr-isisd:isis/circuit-type",
238 				      NB_OP_MODIFY, circ_type);
239 	}
240 
241 	/* check if the interface is a loopback and if so set it as passive */
242 	if (ifp && if_is_loopback(ifp))
243 		nb_cli_enqueue_change(vty, "./frr-isisd:isis/passive",
244 				      NB_OP_MODIFY, "true");
245 
246 	return nb_cli_apply_changes(vty, NULL);
247 }
248 
249 DEFPY_YANG(ip6_router_isis, ip6_router_isis_cmd,
250 	   "ipv6 router isis WORD$tag [vrf NAME$vrf_name]",
251 	   "Interface Internet Protocol config commands\n"
252 	   "IP router interface commands\n"
253 	   "IS-IS routing protocol\n"
254 	   "Routing process tag\n" VRF_CMD_HELP_STR)
255 {
256 	char temp_xpath[XPATH_MAXLEN];
257 	const char *circ_type;
258 	struct interface *ifp;
259 	struct isis_area *area;
260 	struct vrf *vrf;
261 
262 	/* area will be created if it is not present. make sure the yang model
263 	 * is synced with FRR and call the appropriate NB cb.
264 	 */
265 
266 	if (!im)
267 		return CMD_SUCCESS;
268 
269 	ifp = nb_running_get_entry(NULL, VTY_CURR_XPATH, false);
270 	if (!vrf_name) {
271 		if (ifp) {
272 			if (ifp->vrf_id == VRF_DEFAULT)
273 				vrf_name = VRF_DEFAULT_NAME;
274 			else {
275 				vrf = vrf_lookup_by_id(ifp->vrf_id);
276 				if (vrf && !vrf_name)
277 					vrf_name = vrf->name;
278 			}
279 		} else
280 			vrf_name = VRF_DEFAULT_NAME;
281 	}
282 
283 	area = isis_area_lookup_by_vrf(tag, vrf_name);
284 	if (!area) {
285 		isis_global_instance_create(vrf_name);
286 		snprintf(temp_xpath, XPATH_MAXLEN,
287 			 "/frr-isisd:isis/instance[area-tag='%s'][vrf='%s']",
288 			 tag, vrf_name);
289 		nb_cli_enqueue_change(vty, temp_xpath, NB_OP_CREATE, tag);
290 		snprintf(
291 			temp_xpath, XPATH_MAXLEN,
292 			"/frr-isisd:isis/instance[area-tag='%s'][vrf='%s']/is-type",
293 			tag, vrf_name);
294 		nb_cli_enqueue_change(vty, temp_xpath, NB_OP_MODIFY,
295 				      listcount(im->isis) == 0 ? "level-1-2"
296 							       : NULL);
297 		nb_cli_enqueue_change(vty, "./frr-isisd:isis", NB_OP_CREATE,
298 				      NULL);
299 		nb_cli_enqueue_change(vty, "./frr-isisd:isis/area-tag",
300 				      NB_OP_MODIFY, tag);
301 		nb_cli_enqueue_change(vty, "./frr-isisd:isis/vrf", NB_OP_MODIFY,
302 				      vrf_name);
303 
304 		nb_cli_enqueue_change(vty, "./frr-isisd:isis/ipv6-routing",
305 				      NB_OP_MODIFY, "true");
306 		nb_cli_enqueue_change(
307 			vty, "./frr-isisd:isis/circuit-type", NB_OP_MODIFY,
308 			listcount(im->isis) == 0 ? "level-1-2" : "level-1");
309 	} else {
310 		/* area exists, circuit type defaults to its area's is_type */
311 		switch (area->is_type) {
312 		case IS_LEVEL_1:
313 			circ_type = "level-1";
314 			break;
315 		case IS_LEVEL_2:
316 			circ_type = "level-2";
317 			break;
318 		case IS_LEVEL_1_AND_2:
319 			circ_type = "level-1-2";
320 			break;
321 		default:
322 			/* just to silence compiler warnings */
323 			return CMD_WARNING_CONFIG_FAILED;
324 		}
325 		nb_cli_enqueue_change(vty, "./frr-isisd:isis", NB_OP_CREATE,
326 				      NULL);
327 		nb_cli_enqueue_change(vty, "./frr-isisd:isis/area-tag",
328 				      NB_OP_MODIFY, tag);
329 		nb_cli_enqueue_change(vty, "./frr-isisd:isis/vrf", NB_OP_MODIFY,
330 				      vrf_name);
331 		nb_cli_enqueue_change(vty, "./frr-isisd:isis/ipv6-routing",
332 				      NB_OP_MODIFY, "true");
333 		nb_cli_enqueue_change(vty, "./frr-isisd:isis/circuit-type",
334 				      NB_OP_MODIFY, circ_type);
335 	}
336 
337 	/* check if the interface is a loopback and if so set it as passive */
338 	if (ifp && if_is_loopback(ifp))
339 		nb_cli_enqueue_change(vty, "./frr-isisd:isis/passive",
340 				      NB_OP_MODIFY, "true");
341 
342 	return nb_cli_apply_changes(vty, NULL);
343 }
344 
345 DEFPY_YANG(no_ip_router_isis, no_ip_router_isis_cmd,
346 	   "no <ip|ipv6>$ip router isis [WORD]$tag [vrf NAME$vrf_name]",
347 	   NO_STR
348 	   "Interface Internet Protocol config commands\n"
349 	   "IP router interface commands\n"
350 	   "IP router interface commands\n"
351 	   "IS-IS routing protocol\n"
352 	   "Routing process tag\n"
353            VRF_CMD_HELP_STR)
354 {
355 	const struct lyd_node *dnode;
356 
357 	dnode = yang_dnode_get(vty->candidate_config->dnode,
358 			       "%s/frr-isisd:isis", VTY_CURR_XPATH);
359 	if (!dnode)
360 		return CMD_SUCCESS;
361 
362 	/*
363 	 * If both ipv4 and ipv6 are off delete the interface isis container.
364 	 */
365 	if (strmatch(ip, "ipv6")) {
366 		if (!yang_dnode_get_bool(dnode, "./ipv4-routing"))
367 			nb_cli_enqueue_change(vty, "./frr-isisd:isis",
368 					      NB_OP_DESTROY, NULL);
369 		else
370 			nb_cli_enqueue_change(vty,
371 					      "./frr-isisd:isis/ipv6-routing",
372 					      NB_OP_MODIFY, "false");
373 	} else {
374 		if (!yang_dnode_get_bool(dnode, "./ipv6-routing"))
375 			nb_cli_enqueue_change(vty, "./frr-isisd:isis",
376 					      NB_OP_DESTROY, NULL);
377 		else
378 			nb_cli_enqueue_change(vty,
379 					      "./frr-isisd:isis/ipv4-routing",
380 					      NB_OP_MODIFY, "false");
381 	}
382 
383 	return nb_cli_apply_changes(vty, NULL);
384 }
385 
cli_show_ip_isis_ipv4(struct vty * vty,struct lyd_node * dnode,bool show_defaults)386 void cli_show_ip_isis_ipv4(struct vty *vty, struct lyd_node *dnode,
387 			   bool show_defaults)
388 {
389 	const char *vrf;
390 
391 	vrf = yang_dnode_get_string(dnode, "../vrf");
392 
393 	if (!yang_dnode_get_bool(dnode, NULL))
394 		vty_out(vty, " no");
395 	vty_out(vty, " ip router isis %s ",
396 		yang_dnode_get_string(dnode, "../area-tag"));
397 	if (!strmatch(vrf, VRF_DEFAULT_NAME))
398 		vty_out(vty, "vrf %s", vrf);
399 	vty_out(vty, "\n");
400 }
401 
cli_show_ip_isis_ipv6(struct vty * vty,struct lyd_node * dnode,bool show_defaults)402 void cli_show_ip_isis_ipv6(struct vty *vty, struct lyd_node *dnode,
403 			   bool show_defaults)
404 {
405 	const char *vrf;
406 
407 	vrf = yang_dnode_get_string(dnode, "../vrf");
408 
409 	if (!yang_dnode_get_bool(dnode, NULL))
410 		vty_out(vty, " no");
411 	vty_out(vty, " ipv6 router isis %s ",
412 		yang_dnode_get_string(dnode, "../area-tag"));
413 	if (!strmatch(vrf, VRF_DEFAULT_NAME))
414 		vty_out(vty, "vrf %s", vrf);
415 	vty_out(vty, "\n");
416 }
417 
418 /*
419  * XPath: /frr-interface:lib/interface/frr-isisd:isis/bfd-monitoring
420  */
421 DEFPY_YANG(isis_bfd,
422       isis_bfd_cmd,
423       "[no] isis bfd",
424       NO_STR PROTO_HELP
425       "Enable BFD support\n")
426 {
427 	const struct lyd_node *dnode;
428 
429 	dnode = yang_dnode_get(vty->candidate_config->dnode,
430 			       "%s/frr-isisd:isis", VTY_CURR_XPATH);
431 	if (dnode == NULL) {
432 		vty_out(vty, "ISIS is not enabled on this circuit\n");
433 		return CMD_SUCCESS;
434 	}
435 
436 	nb_cli_enqueue_change(vty, "./frr-isisd:isis/bfd-monitoring/enabled",
437 			      NB_OP_MODIFY, no ? "false" : "true");
438 
439 	return nb_cli_apply_changes(vty, NULL);
440 }
441 
442 /*
443  * XPath: /frr-interface:lib/interface/frr-isisd:isis/bfd-monitoring/profile
444  */
445 DEFPY_YANG(isis_bfd_profile,
446       isis_bfd_profile_cmd,
447       "[no] isis bfd profile WORD",
448       NO_STR PROTO_HELP
449       "Enable BFD support\n"
450       "Use a pre-configured profile\n"
451       "Profile name\n")
452 {
453 	const struct lyd_node *dnode;
454 
455 	dnode = yang_dnode_get(vty->candidate_config->dnode,
456 			       "%s/frr-isisd:isis", VTY_CURR_XPATH);
457 	if (dnode == NULL) {
458 		vty_out(vty, "ISIS is not enabled on this circuit\n");
459 		return CMD_SUCCESS;
460 	}
461 
462 	nb_cli_enqueue_change(vty, "./frr-isisd:isis/bfd-monitoring/profile",
463 			      NB_OP_MODIFY, no ? NULL : profile);
464 
465 	return nb_cli_apply_changes(vty, NULL);
466 }
467 
cli_show_ip_isis_bfd_monitoring(struct vty * vty,struct lyd_node * dnode,bool show_defaults)468 void cli_show_ip_isis_bfd_monitoring(struct vty *vty, struct lyd_node *dnode,
469 				     bool show_defaults)
470 {
471 	const char *profile;
472 
473 	if (!yang_dnode_get_bool(dnode, "./enabled"))
474 		vty_out(vty, " no");
475 
476 	vty_out(vty, " isis bfd\n");
477 
478 	if (yang_dnode_exists(dnode, "./profile")) {
479 		profile = yang_dnode_get_string(dnode, "./profile");
480 		if (profile[0] != '\0')
481 			vty_out(vty, " isis bfd profile %s\n", profile);
482 	}
483 }
484 
485 /*
486  * XPath: /frr-isisd:isis/instance/area-address
487  */
488 DEFPY_YANG(net, net_cmd, "[no] net WORD",
489       "Remove an existing Network Entity Title for this process\n"
490       "A Network Entity Title for this process (OSI only)\n"
491       "XX.XXXX. ... .XXX.XX  Network entity title (NET)\n")
492 {
493 	nb_cli_enqueue_change(vty, "./area-address",
494 			      no ? NB_OP_DESTROY : NB_OP_CREATE, net);
495 
496 	return nb_cli_apply_changes(vty, NULL);
497 }
498 
cli_show_isis_area_address(struct vty * vty,struct lyd_node * dnode,bool show_defaults)499 void cli_show_isis_area_address(struct vty *vty, struct lyd_node *dnode,
500 				bool show_defaults)
501 {
502 	vty_out(vty, " net %s\n", yang_dnode_get_string(dnode, NULL));
503 }
504 
505 /*
506  * XPath: /frr-isisd:isis/instance/is-type
507  */
508 DEFPY_YANG(is_type, is_type_cmd, "is-type <level-1|level-1-2|level-2-only>$level",
509       "IS Level for this routing process (OSI only)\n"
510       "Act as a station router only\n"
511       "Act as both a station router and an area router\n"
512       "Act as an area router only\n")
513 {
514 	nb_cli_enqueue_change(vty, "./is-type", NB_OP_MODIFY,
515 			      strmatch(level, "level-2-only") ? "level-2"
516 							      : level);
517 
518 	return nb_cli_apply_changes(vty, NULL);
519 }
520 
521 DEFPY_YANG(no_is_type, no_is_type_cmd,
522       "no is-type [<level-1|level-1-2|level-2-only>]",
523       NO_STR
524       "IS Level for this routing process (OSI only)\n"
525       "Act as a station router only\n"
526       "Act as both a station router and an area router\n"
527       "Act as an area router only\n")
528 {
529 	nb_cli_enqueue_change(vty, "./is-type", NB_OP_MODIFY, NULL);
530 
531 	return nb_cli_apply_changes(vty, NULL);
532 }
533 
cli_show_isis_is_type(struct vty * vty,struct lyd_node * dnode,bool show_defaults)534 void cli_show_isis_is_type(struct vty *vty, struct lyd_node *dnode,
535 			   bool show_defaults)
536 {
537 	int is_type = yang_dnode_get_enum(dnode, NULL);
538 
539 	switch (is_type) {
540 	case IS_LEVEL_1:
541 		vty_out(vty, " is-type level-1\n");
542 		break;
543 	case IS_LEVEL_2:
544 		vty_out(vty, " is-type level-2-only\n");
545 		break;
546 	case IS_LEVEL_1_AND_2:
547 		vty_out(vty, " is-type level-1-2\n");
548 		break;
549 	}
550 }
551 
552 /*
553  * XPath: /frr-isisd:isis/instance/dynamic-hostname
554  */
555 DEFPY_YANG(dynamic_hostname, dynamic_hostname_cmd, "[no] hostname dynamic",
556       NO_STR
557       "Dynamic hostname for IS-IS\n"
558       "Dynamic hostname\n")
559 {
560 	nb_cli_enqueue_change(vty, "./dynamic-hostname", NB_OP_MODIFY,
561 			      no ? "false" : "true");
562 
563 	return nb_cli_apply_changes(vty, NULL);
564 }
565 
cli_show_isis_dynamic_hostname(struct vty * vty,struct lyd_node * dnode,bool show_defaults)566 void cli_show_isis_dynamic_hostname(struct vty *vty, struct lyd_node *dnode,
567 				    bool show_defaults)
568 {
569 	if (!yang_dnode_get_bool(dnode, NULL))
570 		vty_out(vty, " no");
571 
572 	vty_out(vty, " hostname dynamic\n");
573 }
574 
575 /*
576  * XPath: /frr-isisd:isis/instance/overload
577  */
578 DEFPY_YANG(set_overload_bit, set_overload_bit_cmd, "[no] set-overload-bit",
579       "Reset overload bit to accept transit traffic\n"
580       "Set overload bit to avoid any transit traffic\n")
581 {
582 	nb_cli_enqueue_change(vty, "./overload", NB_OP_MODIFY,
583 			      no ? "false" : "true");
584 
585 	return nb_cli_apply_changes(vty, NULL);
586 }
587 
cli_show_isis_overload(struct vty * vty,struct lyd_node * dnode,bool show_defaults)588 void cli_show_isis_overload(struct vty *vty, struct lyd_node *dnode,
589 			    bool show_defaults)
590 {
591 	if (!yang_dnode_get_bool(dnode, NULL))
592 		vty_out(vty, " no");
593 	vty_out(vty, " set-overload-bit\n");
594 }
595 
596 /*
597  * XPath: /frr-isisd:isis/instance/attached
598  */
599 DEFPY_YANG(set_attached_bit, set_attached_bit_cmd, "[no] set-attached-bit",
600       "Reset attached bit\n"
601       "Set attached bit to identify as L1/L2 router for inter-area traffic\n")
602 {
603 	nb_cli_enqueue_change(vty, "./attached", NB_OP_MODIFY,
604 			      no ? "false" : "true");
605 
606 	return nb_cli_apply_changes(vty, NULL);
607 }
608 
cli_show_isis_attached(struct vty * vty,struct lyd_node * dnode,bool show_defaults)609 void cli_show_isis_attached(struct vty *vty, struct lyd_node *dnode,
610 			    bool show_defaults)
611 {
612 	if (!yang_dnode_get_bool(dnode, NULL))
613 		vty_out(vty, " no");
614 	vty_out(vty, " set-attached-bit\n");
615 }
616 
617 /*
618  * XPath: /frr-isisd:isis/instance/metric-style
619  */
620 DEFPY_YANG(metric_style, metric_style_cmd,
621       "metric-style <narrow|transition|wide>$style",
622       "Use old-style (ISO 10589) or new-style packet formats\n"
623       "Use old style of TLVs with narrow metric\n"
624       "Send and accept both styles of TLVs during transition\n"
625       "Use new style of TLVs to carry wider metric\n")
626 {
627 	nb_cli_enqueue_change(vty, "./metric-style", NB_OP_MODIFY, style);
628 
629 	return nb_cli_apply_changes(vty, NULL);
630 }
631 
632 DEFPY_YANG(no_metric_style, no_metric_style_cmd,
633       "no metric-style [narrow|transition|wide]",
634       NO_STR
635       "Use old-style (ISO 10589) or new-style packet formats\n"
636       "Use old style of TLVs with narrow metric\n"
637       "Send and accept both styles of TLVs during transition\n"
638       "Use new style of TLVs to carry wider metric\n")
639 {
640 	nb_cli_enqueue_change(vty, "./metric-style", NB_OP_MODIFY, NULL);
641 
642 	return nb_cli_apply_changes(vty, NULL);
643 }
644 
cli_show_isis_metric_style(struct vty * vty,struct lyd_node * dnode,bool show_defaults)645 void cli_show_isis_metric_style(struct vty *vty, struct lyd_node *dnode,
646 				bool show_defaults)
647 {
648 	int metric = yang_dnode_get_enum(dnode, NULL);
649 
650 	switch (metric) {
651 	case ISIS_NARROW_METRIC:
652 		vty_out(vty, " metric-style narrow\n");
653 		break;
654 	case ISIS_WIDE_METRIC:
655 		vty_out(vty, " metric-style wide\n");
656 		break;
657 	case ISIS_TRANSITION_METRIC:
658 		vty_out(vty, " metric-style transition\n");
659 		break;
660 	}
661 }
662 
663 /*
664  * XPath: /frr-isisd:isis/instance/area-password
665  */
666 DEFPY_YANG(area_passwd, area_passwd_cmd,
667       "area-password <clear|md5>$pwd_type WORD$pwd [authenticate snp <send-only|validate>$snp]",
668       "Configure the authentication password for an area\n"
669       "Clear-text authentication type\n"
670       "MD5 authentication type\n"
671       "Level-wide password\n"
672       "Authentication\n"
673       "SNP PDUs\n"
674       "Send but do not check PDUs on receiving\n"
675       "Send and check PDUs on receiving\n")
676 {
677 	nb_cli_enqueue_change(vty, "./area-password", NB_OP_CREATE, NULL);
678 	nb_cli_enqueue_change(vty, "./area-password/password", NB_OP_MODIFY,
679 			      pwd);
680 	nb_cli_enqueue_change(vty, "./area-password/password-type",
681 			      NB_OP_MODIFY, pwd_type);
682 	nb_cli_enqueue_change(vty, "./area-password/authenticate-snp",
683 			      NB_OP_MODIFY, snp ? snp : "none");
684 
685 	return nb_cli_apply_changes(vty, NULL);
686 }
687 
cli_show_isis_area_pwd(struct vty * vty,struct lyd_node * dnode,bool show_defaults)688 void cli_show_isis_area_pwd(struct vty *vty, struct lyd_node *dnode,
689 			    bool show_defaults)
690 {
691 	const char *snp;
692 
693 	vty_out(vty, " area-password %s %s",
694 		yang_dnode_get_string(dnode, "./password-type"),
695 		yang_dnode_get_string(dnode, "./password"));
696 	snp = yang_dnode_get_string(dnode, "./authenticate-snp");
697 	if (!strmatch("none", snp))
698 		vty_out(vty, " authenticate snp %s", snp);
699 	vty_out(vty, "\n");
700 }
701 
702 /*
703  * XPath: /frr-isisd:isis/instance/domain-password
704  */
705 DEFPY_YANG(domain_passwd, domain_passwd_cmd,
706       "domain-password <clear|md5>$pwd_type WORD$pwd [authenticate snp <send-only|validate>$snp]",
707       "Set the authentication password for a routing domain\n"
708       "Clear-text authentication type\n"
709       "MD5 authentication type\n"
710       "Level-wide password\n"
711       "Authentication\n"
712       "SNP PDUs\n"
713       "Send but do not check PDUs on receiving\n"
714       "Send and check PDUs on receiving\n")
715 {
716 	nb_cli_enqueue_change(vty, "./domain-password", NB_OP_CREATE, NULL);
717 	nb_cli_enqueue_change(vty, "./domain-password/password", NB_OP_MODIFY,
718 			      pwd);
719 	nb_cli_enqueue_change(vty, "./domain-password/password-type",
720 			      NB_OP_MODIFY, pwd_type);
721 	nb_cli_enqueue_change(vty, "./domain-password/authenticate-snp",
722 			      NB_OP_MODIFY, snp ? snp : "none");
723 
724 	return nb_cli_apply_changes(vty, NULL);
725 }
726 
727 DEFPY_YANG(no_area_passwd, no_area_passwd_cmd,
728       "no <area-password|domain-password>$cmd",
729       NO_STR
730       "Configure the authentication password for an area\n"
731       "Set the authentication password for a routing domain\n")
732 {
733 	nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
734 
735 	return nb_cli_apply_changes(vty, "./%s", cmd);
736 }
737 
cli_show_isis_domain_pwd(struct vty * vty,struct lyd_node * dnode,bool show_defaults)738 void cli_show_isis_domain_pwd(struct vty *vty, struct lyd_node *dnode,
739 			      bool show_defaults)
740 {
741 	const char *snp;
742 
743 	vty_out(vty, " domain-password %s %s",
744 		yang_dnode_get_string(dnode, "./password-type"),
745 		yang_dnode_get_string(dnode, "./password"));
746 	snp = yang_dnode_get_string(dnode, "./authenticate-snp");
747 	if (!strmatch("none", snp))
748 		vty_out(vty, " authenticate snp %s", snp);
749 	vty_out(vty, "\n");
750 }
751 
752 /*
753  * XPath: /frr-isisd:isis/instance/lsp/timers/level-1/generation-interval
754  * XPath: /frr-isisd:isis/instance/lsp/timers/level-2/generation-interval
755  */
756 DEFPY_YANG(lsp_gen_interval, lsp_gen_interval_cmd,
757       "lsp-gen-interval [level-1|level-2]$level (1-120)$val",
758       "Minimum interval between regenerating same LSP\n"
759       "Set interval for level 1 only\n"
760       "Set interval for level 2 only\n"
761       "Minimum interval in seconds\n")
762 {
763 	if (!level || strmatch(level, "level-1"))
764 		nb_cli_enqueue_change(
765 			vty, "./lsp/timers/level-1/generation-interval",
766 			NB_OP_MODIFY, val_str);
767 	if (!level || strmatch(level, "level-2"))
768 		nb_cli_enqueue_change(
769 			vty, "./lsp/timers/level-2/generation-interval",
770 			NB_OP_MODIFY, val_str);
771 
772 	return nb_cli_apply_changes(vty, NULL);
773 }
774 
775 DEFPY_YANG(no_lsp_gen_interval, no_lsp_gen_interval_cmd,
776       "no lsp-gen-interval [level-1|level-2]$level [(1-120)]",
777       NO_STR
778       "Minimum interval between regenerating same LSP\n"
779       "Set interval for level 1 only\n"
780       "Set interval for level 2 only\n"
781       "Minimum interval in seconds\n")
782 {
783 	if (!level || strmatch(level, "level-1"))
784 		nb_cli_enqueue_change(
785 			vty, "./lsp/timers/level-1/generation-interval",
786 			NB_OP_MODIFY, NULL);
787 	if (!level || strmatch(level, "level-2"))
788 		nb_cli_enqueue_change(
789 			vty, "./lsp/timers/level-2/generation-interval",
790 			NB_OP_MODIFY, NULL);
791 
792 	return nb_cli_apply_changes(vty, NULL);
793 }
794 
795 /*
796  * XPath: /frr-isisd:isis/instance/lsp/timers/level-1/refresh-interval
797  * XPath: /frr-isisd:isis/instance/lsp/timers/level-2/refresh-interval
798  */
799 DEFPY_YANG(lsp_refresh_interval, lsp_refresh_interval_cmd,
800       "lsp-refresh-interval [level-1|level-2]$level (1-65235)$val",
801       "LSP refresh interval\n"
802       "LSP refresh interval for Level 1 only\n"
803       "LSP refresh interval for Level 2 only\n"
804       "LSP refresh interval in seconds\n")
805 {
806 	if (!level || strmatch(level, "level-1"))
807 		nb_cli_enqueue_change(vty,
808 				      "./lsp/timers/level-1/refresh-interval",
809 				      NB_OP_MODIFY, val_str);
810 	if (!level || strmatch(level, "level-2"))
811 		nb_cli_enqueue_change(vty,
812 				      "./lsp/timers/level-2/refresh-interval",
813 				      NB_OP_MODIFY, val_str);
814 
815 	return nb_cli_apply_changes(vty, NULL);
816 }
817 
818 DEFPY_YANG(no_lsp_refresh_interval, no_lsp_refresh_interval_cmd,
819       "no lsp-refresh-interval [level-1|level-2]$level [(1-65235)]",
820       NO_STR
821       "LSP refresh interval\n"
822       "LSP refresh interval for Level 1 only\n"
823       "LSP refresh interval for Level 2 only\n"
824       "LSP refresh interval in seconds\n")
825 {
826 	if (!level || strmatch(level, "level-1"))
827 		nb_cli_enqueue_change(vty,
828 				      "./lsp/timers/level-1/refresh-interval",
829 				      NB_OP_MODIFY, NULL);
830 	if (!level || strmatch(level, "level-2"))
831 		nb_cli_enqueue_change(vty,
832 				      "./lsp/timers/level-2/refresh-interval",
833 				      NB_OP_MODIFY, NULL);
834 
835 	return nb_cli_apply_changes(vty, NULL);
836 }
837 
838 /*
839  * XPath: /frr-isisd:isis/instance/lsp/timers/level-1/maximum-lifetime
840  * XPath: /frr-isisd:isis/instance/lsp/timers/level-1/maximum-lifetime
841  */
842 
843 DEFPY_YANG(max_lsp_lifetime, max_lsp_lifetime_cmd,
844       "max-lsp-lifetime [level-1|level-2]$level (350-65535)$val",
845       "Maximum LSP lifetime\n"
846       "Maximum LSP lifetime for Level 1 only\n"
847       "Maximum LSP lifetime for Level 2 only\n"
848       "LSP lifetime in seconds\n")
849 {
850 	if (!level || strmatch(level, "level-1"))
851 		nb_cli_enqueue_change(vty,
852 				      "./lsp/timers/level-1/maximum-lifetime",
853 				      NB_OP_MODIFY, val_str);
854 	if (!level || strmatch(level, "level-2"))
855 		nb_cli_enqueue_change(vty,
856 				      "./lsp/timers/level-2/maximum-lifetime",
857 				      NB_OP_MODIFY, val_str);
858 
859 	return nb_cli_apply_changes(vty, NULL);
860 }
861 
862 DEFPY_YANG(no_max_lsp_lifetime, no_max_lsp_lifetime_cmd,
863       "no max-lsp-lifetime [level-1|level-2]$level [(350-65535)]",
864       NO_STR
865       "Maximum LSP lifetime\n"
866       "Maximum LSP lifetime for Level 1 only\n"
867       "Maximum LSP lifetime for Level 2 only\n"
868       "LSP lifetime in seconds\n")
869 {
870 	if (!level || strmatch(level, "level-1"))
871 		nb_cli_enqueue_change(vty,
872 				      "./lsp/timers/level-1/maximum-lifetime",
873 				      NB_OP_MODIFY, NULL);
874 	if (!level || strmatch(level, "level-2"))
875 		nb_cli_enqueue_change(vty,
876 				      "./lsp/timers/level-2/maximum-lifetime",
877 				      NB_OP_MODIFY, NULL);
878 
879 	return nb_cli_apply_changes(vty, NULL);
880 }
881 
882 /* unified LSP timers command
883  * XPath: /frr-isisd:isis/instance/lsp/timers
884  */
885 
886 DEFPY_YANG(lsp_timers, lsp_timers_cmd,
887       "lsp-timers [level-1|level-2]$level gen-interval (1-120)$gen refresh-interval (1-65235)$refresh max-lifetime (350-65535)$lifetime",
888       "LSP-related timers\n"
889       "LSP-related timers for Level 1 only\n"
890       "LSP-related timers for Level 2 only\n"
891       "Minimum interval between regenerating same LSP\n"
892       "Generation interval in seconds\n"
893       "LSP refresh interval\n"
894       "LSP refresh interval in seconds\n"
895       "Maximum LSP lifetime\n"
896       "Maximum LSP lifetime in seconds\n")
897 {
898 	if (!level || strmatch(level, "level-1")) {
899 		nb_cli_enqueue_change(
900 			vty, "./lsp/timers/level-1/generation-interval",
901 			NB_OP_MODIFY, gen_str);
902 		nb_cli_enqueue_change(vty,
903 				      "./lsp/timers/level-1/refresh-interval",
904 				      NB_OP_MODIFY, refresh_str);
905 		nb_cli_enqueue_change(vty,
906 				      "./lsp/timers/level-1/maximum-lifetime",
907 				      NB_OP_MODIFY, lifetime_str);
908 	}
909 	if (!level || strmatch(level, "level-2")) {
910 		nb_cli_enqueue_change(
911 			vty, "./lsp/timers/level-2/generation-interval",
912 			NB_OP_MODIFY, gen_str);
913 		nb_cli_enqueue_change(vty,
914 				      "./lsp/timers/level-2/refresh-interval",
915 				      NB_OP_MODIFY, refresh_str);
916 		nb_cli_enqueue_change(vty,
917 				      "./lsp/timers/level-2/maximum-lifetime",
918 				      NB_OP_MODIFY, lifetime_str);
919 	}
920 
921 	return nb_cli_apply_changes(vty, NULL);
922 }
923 
924 DEFPY_YANG(no_lsp_timers, no_lsp_timers_cmd,
925       "no lsp-timers [level-1|level-2]$level [gen-interval (1-120) refresh-interval (1-65235) max-lifetime (350-65535)]",
926       NO_STR
927       "LSP-related timers\n"
928       "LSP-related timers for Level 1 only\n"
929       "LSP-related timers for Level 2 only\n"
930       "Minimum interval between regenerating same LSP\n"
931       "Generation interval in seconds\n"
932       "LSP refresh interval\n"
933       "LSP refresh interval in seconds\n"
934       "Maximum LSP lifetime\n"
935       "Maximum LSP lifetime in seconds\n")
936 {
937 	if (!level || strmatch(level, "level-1")) {
938 		nb_cli_enqueue_change(
939 			vty, "./lsp/timers/level-1/generation-interval",
940 			NB_OP_MODIFY, NULL);
941 		nb_cli_enqueue_change(vty,
942 				      "./lsp/timers/level-1/refresh-interval",
943 				      NB_OP_MODIFY, NULL);
944 		nb_cli_enqueue_change(vty,
945 				      "./lsp/timers/level-1/maximum-lifetime",
946 				      NB_OP_MODIFY, NULL);
947 	}
948 	if (!level || strmatch(level, "level-2")) {
949 		nb_cli_enqueue_change(
950 			vty, "./lsp/timers/level-2/generation-interval",
951 			NB_OP_MODIFY, NULL);
952 		nb_cli_enqueue_change(vty,
953 				      "./lsp/timers/level-2/refresh-interval",
954 				      NB_OP_MODIFY, NULL);
955 		nb_cli_enqueue_change(vty,
956 				      "./lsp/timers/level-2/maximum-lifetime",
957 				      NB_OP_MODIFY, NULL);
958 	}
959 
960 	return nb_cli_apply_changes(vty, NULL);
961 }
962 
cli_show_isis_lsp_timers(struct vty * vty,struct lyd_node * dnode,bool show_defaults)963 void cli_show_isis_lsp_timers(struct vty *vty, struct lyd_node *dnode,
964 			      bool show_defaults)
965 {
966 	const char *l1_refresh =
967 		yang_dnode_get_string(dnode, "./level-1/refresh-interval");
968 	const char *l2_refresh =
969 		yang_dnode_get_string(dnode, "./level-2/refresh-interval");
970 	const char *l1_lifetime =
971 		yang_dnode_get_string(dnode, "./level-1/maximum-lifetime");
972 	const char *l2_lifetime =
973 		yang_dnode_get_string(dnode, "./level-2/maximum-lifetime");
974 	const char *l1_gen =
975 		yang_dnode_get_string(dnode, "./level-1/generation-interval");
976 	const char *l2_gen =
977 		yang_dnode_get_string(dnode, "./level-2/generation-interval");
978 	if (strmatch(l1_refresh, l2_refresh)
979 	    && strmatch(l1_lifetime, l2_lifetime) && strmatch(l1_gen, l2_gen))
980 		vty_out(vty,
981 			" lsp-timers gen-interval %s refresh-interval %s max-lifetime %s\n",
982 			l1_gen, l1_refresh, l1_lifetime);
983 	else {
984 		vty_out(vty,
985 			" lsp-timers level-1 gen-interval %s refresh-interval %s max-lifetime %s\n",
986 			l1_gen, l1_refresh, l1_lifetime);
987 		vty_out(vty,
988 			" lsp-timers level-2 gen-interval %s refresh-interval %s max-lifetime %s\n",
989 			l2_gen, l2_refresh, l2_lifetime);
990 	}
991 }
992 
993 /*
994  * XPath: /frr-isisd:isis/instance/lsp/mtu
995  */
996 DEFPY_YANG(area_lsp_mtu, area_lsp_mtu_cmd, "lsp-mtu (128-4352)$val",
997       "Configure the maximum size of generated LSPs\n"
998       "Maximum size of generated LSPs\n")
999 {
1000 	nb_cli_enqueue_change(vty, "./lsp/mtu", NB_OP_MODIFY, val_str);
1001 
1002 	return nb_cli_apply_changes(vty, NULL);
1003 }
1004 
1005 DEFPY_YANG(no_area_lsp_mtu, no_area_lsp_mtu_cmd, "no lsp-mtu [(128-4352)]",
1006       NO_STR
1007       "Configure the maximum size of generated LSPs\n"
1008       "Maximum size of generated LSPs\n")
1009 {
1010 	nb_cli_enqueue_change(vty, "./lsp/mtu", NB_OP_MODIFY, NULL);
1011 
1012 	return nb_cli_apply_changes(vty, NULL);
1013 }
1014 
cli_show_isis_lsp_mtu(struct vty * vty,struct lyd_node * dnode,bool show_defaults)1015 void cli_show_isis_lsp_mtu(struct vty *vty, struct lyd_node *dnode,
1016 			   bool show_defaults)
1017 {
1018 	vty_out(vty, " lsp-mtu %s\n", yang_dnode_get_string(dnode, NULL));
1019 }
1020 
1021 /*
1022  * XPath: /frr-isisd:isis/instance/spf/minimum-interval
1023  */
1024 DEFPY_YANG(spf_interval, spf_interval_cmd,
1025       "spf-interval [level-1|level-2]$level (1-120)$val",
1026       "Minimum interval between SPF calculations\n"
1027       "Set interval for level 1 only\n"
1028       "Set interval for level 2 only\n"
1029       "Minimum interval between consecutive SPFs in seconds\n")
1030 {
1031 	if (!level || strmatch(level, "level-1"))
1032 		nb_cli_enqueue_change(vty, "./spf/minimum-interval/level-1",
1033 				      NB_OP_MODIFY, val_str);
1034 	if (!level || strmatch(level, "level-2"))
1035 		nb_cli_enqueue_change(vty, "./spf/minimum-interval/level-2",
1036 				      NB_OP_MODIFY, val_str);
1037 
1038 	return nb_cli_apply_changes(vty, NULL);
1039 }
1040 
1041 DEFPY_YANG(no_spf_interval, no_spf_interval_cmd,
1042       "no spf-interval [level-1|level-2]$level [(1-120)]",
1043       NO_STR
1044       "Minimum interval between SPF calculations\n"
1045       "Set interval for level 1 only\n"
1046       "Set interval for level 2 only\n"
1047       "Minimum interval between consecutive SPFs in seconds\n")
1048 {
1049 	if (!level || strmatch(level, "level-1"))
1050 		nb_cli_enqueue_change(vty, "./spf/minimum-interval/level-1",
1051 				      NB_OP_MODIFY, NULL);
1052 	if (!level || strmatch(level, "level-2"))
1053 		nb_cli_enqueue_change(vty, "./spf/minimum-interval/level-2",
1054 				      NB_OP_MODIFY, NULL);
1055 
1056 	return nb_cli_apply_changes(vty, NULL);
1057 }
1058 
cli_show_isis_spf_min_interval(struct vty * vty,struct lyd_node * dnode,bool show_defaults)1059 void cli_show_isis_spf_min_interval(struct vty *vty, struct lyd_node *dnode,
1060 				    bool show_defaults)
1061 {
1062 	const char *l1 = yang_dnode_get_string(dnode, "./level-1");
1063 	const char *l2 = yang_dnode_get_string(dnode, "./level-2");
1064 
1065 	if (strmatch(l1, l2))
1066 		vty_out(vty, " spf-interval %s\n", l1);
1067 	else {
1068 		vty_out(vty, " spf-interval level-1 %s\n", l1);
1069 		vty_out(vty, " spf-interval level-2 %s\n", l2);
1070 	}
1071 }
1072 
1073 /*
1074  * XPath: /frr-isisd:isis/instance/spf/ietf-backoff-delay
1075  */
1076 DEFPY_YANG(spf_delay_ietf, spf_delay_ietf_cmd,
1077       "spf-delay-ietf init-delay (0-60000) short-delay (0-60000) long-delay (0-60000) holddown (0-60000) time-to-learn (0-60000)",
1078       "IETF SPF delay algorithm\n"
1079       "Delay used while in QUIET state\n"
1080       "Delay used while in QUIET state in milliseconds\n"
1081       "Delay used while in SHORT_WAIT state\n"
1082       "Delay used while in SHORT_WAIT state in milliseconds\n"
1083       "Delay used while in LONG_WAIT\n"
1084       "Delay used while in LONG_WAIT state in milliseconds\n"
1085       "Time with no received IGP events before considering IGP stable\n"
1086       "Time with no received IGP events before considering IGP stable (in milliseconds)\n"
1087       "Maximum duration needed to learn all the events related to a single failure\n"
1088       "Maximum duration needed to learn all the events related to a single failure (in milliseconds)\n")
1089 {
1090 	nb_cli_enqueue_change(vty, "./spf/ietf-backoff-delay", NB_OP_CREATE,
1091 			      NULL);
1092 	nb_cli_enqueue_change(vty, "./spf/ietf-backoff-delay/init-delay",
1093 			      NB_OP_MODIFY, init_delay_str);
1094 	nb_cli_enqueue_change(vty, "./spf/ietf-backoff-delay/short-delay",
1095 			      NB_OP_MODIFY, short_delay_str);
1096 	nb_cli_enqueue_change(vty, "./spf/ietf-backoff-delay/long-delay",
1097 			      NB_OP_MODIFY, long_delay_str);
1098 	nb_cli_enqueue_change(vty, "./spf/ietf-backoff-delay/hold-down",
1099 			      NB_OP_MODIFY, holddown_str);
1100 	nb_cli_enqueue_change(vty, "./spf/ietf-backoff-delay/time-to-learn",
1101 			      NB_OP_MODIFY, time_to_learn_str);
1102 
1103 	return nb_cli_apply_changes(vty, NULL);
1104 }
1105 
1106 DEFPY_YANG(no_spf_delay_ietf, no_spf_delay_ietf_cmd,
1107       "no spf-delay-ietf [init-delay (0-60000) short-delay (0-60000) long-delay (0-60000) holddown (0-60000) time-to-learn (0-60000)]",
1108       NO_STR
1109       "IETF SPF delay algorithm\n"
1110       "Delay used while in QUIET state\n"
1111       "Delay used while in QUIET state in milliseconds\n"
1112       "Delay used while in SHORT_WAIT state\n"
1113       "Delay used while in SHORT_WAIT state in milliseconds\n"
1114       "Delay used while in LONG_WAIT\n"
1115       "Delay used while in LONG_WAIT state in milliseconds\n"
1116       "Time with no received IGP events before considering IGP stable\n"
1117       "Time with no received IGP events before considering IGP stable (in milliseconds)\n"
1118       "Maximum duration needed to learn all the events related to a single failure\n"
1119       "Maximum duration needed to learn all the events related to a single failure (in milliseconds)\n")
1120 {
1121 	nb_cli_enqueue_change(vty, "./spf/ietf-backoff-delay", NB_OP_DESTROY,
1122 			      NULL);
1123 
1124 	return nb_cli_apply_changes(vty, NULL);
1125 }
1126 
cli_show_isis_spf_ietf_backoff(struct vty * vty,struct lyd_node * dnode,bool show_defaults)1127 void cli_show_isis_spf_ietf_backoff(struct vty *vty, struct lyd_node *dnode,
1128 				    bool show_defaults)
1129 {
1130 	vty_out(vty,
1131 		" spf-delay-ietf init-delay %s short-delay %s long-delay %s holddown %s time-to-learn %s\n",
1132 		yang_dnode_get_string(dnode, "./init-delay"),
1133 		yang_dnode_get_string(dnode, "./short-delay"),
1134 		yang_dnode_get_string(dnode, "./long-delay"),
1135 		yang_dnode_get_string(dnode, "./hold-down"),
1136 		yang_dnode_get_string(dnode, "./time-to-learn"));
1137 }
1138 
1139 /*
1140  * XPath: /frr-isisd:isis/instance/purge-originator
1141  */
1142 DEFPY_YANG(area_purge_originator, area_purge_originator_cmd, "[no] purge-originator",
1143       NO_STR "Use the RFC 6232 purge-originator\n")
1144 {
1145 	nb_cli_enqueue_change(vty, "./purge-originator", NB_OP_MODIFY,
1146 			      no ? "false" : "true");
1147 
1148 	return nb_cli_apply_changes(vty, NULL);
1149 }
1150 
cli_show_isis_purge_origin(struct vty * vty,struct lyd_node * dnode,bool show_defaults)1151 void cli_show_isis_purge_origin(struct vty *vty, struct lyd_node *dnode,
1152 				bool show_defaults)
1153 {
1154 	if (!yang_dnode_get_bool(dnode, NULL))
1155 		vty_out(vty, " no");
1156 	vty_out(vty, " purge-originator\n");
1157 }
1158 
1159 /*
1160  * XPath: /frr-isisd:isis/instance/mpls-te
1161  */
1162 DEFPY_YANG(isis_mpls_te_on, isis_mpls_te_on_cmd, "mpls-te on",
1163       MPLS_TE_STR "Enable the MPLS-TE functionality\n")
1164 {
1165 	nb_cli_enqueue_change(vty, "./mpls-te", NB_OP_CREATE,
1166 			      NULL);
1167 
1168 	return nb_cli_apply_changes(vty, NULL);
1169 }
1170 
1171 DEFPY_YANG(no_isis_mpls_te_on, no_isis_mpls_te_on_cmd, "no mpls-te [on]",
1172       NO_STR
1173       "Disable the MPLS-TE functionality\n"
1174       "Disable the MPLS-TE functionality\n")
1175 {
1176 	nb_cli_enqueue_change(vty, "./mpls-te", NB_OP_DESTROY,
1177 			      NULL);
1178 
1179 	return nb_cli_apply_changes(vty, NULL);
1180 }
1181 
cli_show_isis_mpls_te(struct vty * vty,struct lyd_node * dnode,bool show_defaults)1182 void cli_show_isis_mpls_te(struct vty *vty, struct lyd_node *dnode,
1183 			   bool show_defaults)
1184 {
1185 	vty_out(vty, "  mpls-te on\n");
1186 }
1187 
1188 /*
1189  * XPath: /frr-isisd:isis/instance/mpls-te/router-address
1190  */
1191 DEFPY_YANG(isis_mpls_te_router_addr, isis_mpls_te_router_addr_cmd,
1192       "mpls-te router-address A.B.C.D",
1193       MPLS_TE_STR
1194       "Stable IP address of the advertising router\n"
1195       "MPLS-TE router address in IPv4 address format\n")
1196 {
1197 	nb_cli_enqueue_change(vty, "./mpls-te/router-address",
1198 			      NB_OP_MODIFY, router_address_str);
1199 
1200 	return nb_cli_apply_changes(vty, NULL);
1201 }
1202 
1203 DEFPY_YANG(no_isis_mpls_te_router_addr, no_isis_mpls_te_router_addr_cmd,
1204       "no mpls-te router-address [A.B.C.D]",
1205       NO_STR MPLS_TE_STR
1206       "Delete IP address of the advertising router\n"
1207       "MPLS-TE router address in IPv4 address format\n")
1208 {
1209 	nb_cli_enqueue_change(vty, "./mpls-te/router-address",
1210 			      NB_OP_DESTROY, NULL);
1211 
1212 	return nb_cli_apply_changes(vty, NULL);
1213 }
1214 
cli_show_isis_mpls_te_router_addr(struct vty * vty,struct lyd_node * dnode,bool show_defaults)1215 void cli_show_isis_mpls_te_router_addr(struct vty *vty, struct lyd_node *dnode,
1216 				       bool show_defaults)
1217 {
1218 	vty_out(vty, "  mpls-te router-address %s\n",
1219 		yang_dnode_get_string(dnode, NULL));
1220 }
1221 
1222 DEFPY_YANG(isis_mpls_te_inter_as, isis_mpls_te_inter_as_cmd,
1223       "[no] mpls-te inter-as [level-1|level-1-2|level-2-only]",
1224       NO_STR MPLS_TE_STR
1225       "Configure MPLS-TE Inter-AS support\n"
1226       "AREA native mode self originate INTER-AS LSP with L1 only flooding scope\n"
1227       "AREA native mode self originate INTER-AS LSP with L1 and L2 flooding scope\n"
1228       "AS native mode self originate INTER-AS LSP with L2 only flooding scope\n")
1229 {
1230 	vty_out(vty, "MPLS-TE Inter-AS is not yet supported\n");
1231 	return CMD_SUCCESS;
1232 }
1233 
1234 /*
1235  * XPath: /frr-isisd:isis/instance/default-information-originate
1236  */
1237 DEFPY_YANG(isis_default_originate, isis_default_originate_cmd,
1238       "[no] default-information originate <ipv4|ipv6>$ip <level-1|level-2>$level [always]$always [{metric (0-16777215)$metric|route-map WORD$rmap}]",
1239       NO_STR
1240       "Control distribution of default information\n"
1241       "Distribute a default route\n"
1242       "Distribute default route for IPv4\n"
1243       "Distribute default route for IPv6\n"
1244       "Distribute default route into level-1\n"
1245       "Distribute default route into level-2\n"
1246       "Always advertise default route\n"
1247       "Metric for default route\n"
1248       "IS-IS default metric\n"
1249       "Route map reference\n"
1250       "Pointer to route-map entries\n")
1251 {
1252 	if (no)
1253 		nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
1254 	else {
1255 		nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
1256 		nb_cli_enqueue_change(vty, "./always", NB_OP_MODIFY,
1257 				      always ? "true" : "false");
1258 		nb_cli_enqueue_change(vty, "./route-map",
1259 				      rmap ? NB_OP_MODIFY : NB_OP_DESTROY,
1260 				      rmap ? rmap : NULL);
1261 		nb_cli_enqueue_change(vty, "./metric", NB_OP_MODIFY,
1262 				      metric_str ? metric_str : NULL);
1263 		if (strmatch(ip, "ipv6") && !always) {
1264 			vty_out(vty,
1265 				"Zebra doesn't implement default-originate for IPv6 yet\n");
1266 			vty_out(vty,
1267 				"so use with care or use default-originate always.\n");
1268 		}
1269 	}
1270 
1271 	return nb_cli_apply_changes(
1272 		vty, "./default-information-originate/%s[level='%s']", ip,
1273 		level);
1274 }
1275 
vty_print_def_origin(struct vty * vty,struct lyd_node * dnode,const char * family,const char * level,bool show_defaults)1276 static void vty_print_def_origin(struct vty *vty, struct lyd_node *dnode,
1277 				 const char *family, const char *level,
1278 				 bool show_defaults)
1279 {
1280 	vty_out(vty, " default-information originate %s %s", family, level);
1281 	if (yang_dnode_get_bool(dnode, "./always"))
1282 		vty_out(vty, " always");
1283 
1284 	if (yang_dnode_exists(dnode, "./route-map"))
1285 		vty_out(vty, " route-map %s",
1286 			yang_dnode_get_string(dnode, "./route-map"));
1287 	if (show_defaults || !yang_dnode_is_default(dnode, "./metric"))
1288 		vty_out(vty, " metric %s",
1289 			yang_dnode_get_string(dnode, "./metric"));
1290 
1291 	vty_out(vty, "\n");
1292 }
1293 
cli_show_isis_def_origin_ipv4(struct vty * vty,struct lyd_node * dnode,bool show_defaults)1294 void cli_show_isis_def_origin_ipv4(struct vty *vty, struct lyd_node *dnode,
1295 				   bool show_defaults)
1296 {
1297 	const char *level = yang_dnode_get_string(dnode, "./level");
1298 
1299 	vty_print_def_origin(vty, dnode, "ipv4", level, show_defaults);
1300 }
1301 
cli_show_isis_def_origin_ipv6(struct vty * vty,struct lyd_node * dnode,bool show_defaults)1302 void cli_show_isis_def_origin_ipv6(struct vty *vty, struct lyd_node *dnode,
1303 				   bool show_defaults)
1304 {
1305 	const char *level = yang_dnode_get_string(dnode, "./level");
1306 
1307 	vty_print_def_origin(vty, dnode, "ipv6", level, show_defaults);
1308 }
1309 
1310 /*
1311  * XPath: /frr-isisd:isis/instance/redistribute
1312  */
1313 DEFPY_YANG(isis_redistribute, isis_redistribute_cmd,
1314       "[no] redistribute <ipv4|ipv6>$ip " PROTO_REDIST_STR
1315       "$proto <level-1|level-2>$level [{metric (0-16777215)|route-map WORD}]",
1316       NO_STR REDIST_STR
1317       "Redistribute IPv4 routes\n"
1318       "Redistribute IPv6 routes\n" PROTO_REDIST_HELP
1319       "Redistribute into level-1\n"
1320       "Redistribute into level-2\n"
1321       "Metric for redistributed routes\n"
1322       "IS-IS default metric\n"
1323       "Route map reference\n"
1324       "Pointer to route-map entries\n")
1325 {
1326 	if (no)
1327 		nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
1328 	else {
1329 		nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
1330 		nb_cli_enqueue_change(vty, "./route-map",
1331 				      route_map ? NB_OP_MODIFY : NB_OP_DESTROY,
1332 				      route_map ? route_map : NULL);
1333 		nb_cli_enqueue_change(vty, "./metric", NB_OP_MODIFY,
1334 				      metric_str ? metric_str : NULL);
1335 	}
1336 
1337 	return nb_cli_apply_changes(
1338 		vty, "./redistribute/%s[protocol='%s'][level='%s']", ip, proto,
1339 		level);
1340 }
1341 
vty_print_redistribute(struct vty * vty,struct lyd_node * dnode,bool show_defaults,const char * family)1342 static void vty_print_redistribute(struct vty *vty, struct lyd_node *dnode,
1343 				   bool show_defaults, const char *family)
1344 {
1345 	const char *level = yang_dnode_get_string(dnode, "./level");
1346 	const char *protocol = yang_dnode_get_string(dnode, "./protocol");
1347 
1348 	vty_out(vty, " redistribute %s %s %s", family, protocol, level);
1349 	if (show_defaults || !yang_dnode_is_default(dnode, "./metric"))
1350 		vty_out(vty, " metric %s",
1351 			yang_dnode_get_string(dnode, "./metric"));
1352 	if (yang_dnode_exists(dnode, "./route-map"))
1353 		vty_out(vty, " route-map %s",
1354 			yang_dnode_get_string(dnode, "./route-map"));
1355 	vty_out(vty, "\n");
1356 }
1357 
cli_show_isis_redistribute_ipv4(struct vty * vty,struct lyd_node * dnode,bool show_defaults)1358 void cli_show_isis_redistribute_ipv4(struct vty *vty, struct lyd_node *dnode,
1359 				     bool show_defaults)
1360 {
1361 	vty_print_redistribute(vty, dnode, show_defaults, "ipv4");
1362 }
cli_show_isis_redistribute_ipv6(struct vty * vty,struct lyd_node * dnode,bool show_defaults)1363 void cli_show_isis_redistribute_ipv6(struct vty *vty, struct lyd_node *dnode,
1364 				     bool show_defaults)
1365 {
1366 	vty_print_redistribute(vty, dnode, show_defaults, "ipv6");
1367 }
1368 
1369 /*
1370  * XPath: /frr-isisd:isis/instance/multi-topology
1371  */
1372 DEFPY_YANG(isis_topology, isis_topology_cmd,
1373       "[no] topology <ipv4-unicast|ipv4-mgmt|ipv6-unicast|ipv4-multicast|ipv6-multicast|ipv6-mgmt|ipv6-dstsrc>$topology [overload]$overload",
1374       NO_STR
1375       "Configure IS-IS topologies\n"
1376       "IPv4 unicast topology\n"
1377       "IPv4 management topology\n"
1378       "IPv6 unicast topology\n"
1379       "IPv4 multicast topology\n"
1380       "IPv6 multicast topology\n"
1381       "IPv6 management topology\n"
1382       "IPv6 dst-src topology\n"
1383       "Set overload bit for topology\n")
1384 {
1385 	char base_xpath[XPATH_MAXLEN];
1386 
1387 	/* Since IPv4-unicast is not configurable it is not present in the
1388 	 * YANG model, so we need to validate it here
1389 	 */
1390 	if (strmatch(topology, "ipv4-unicast")) {
1391 		vty_out(vty, "Cannot configure IPv4 unicast topology\n");
1392 		return CMD_WARNING_CONFIG_FAILED;
1393 	}
1394 
1395 	if (strmatch(topology, "ipv4-mgmt"))
1396 		snprintf(base_xpath, XPATH_MAXLEN,
1397 			 "./multi-topology/ipv4-management");
1398 	else if (strmatch(topology, "ipv6-mgmt"))
1399 		snprintf(base_xpath, XPATH_MAXLEN,
1400 			 "./multi-topology/ipv6-management");
1401 	else
1402 		snprintf(base_xpath, XPATH_MAXLEN, "./multi-topology/%s",
1403 			 topology);
1404 
1405 	if (no)
1406 		nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
1407 	else {
1408 		nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
1409 		nb_cli_enqueue_change(vty, "./overload", NB_OP_MODIFY,
1410 				      overload ? "true" : "false");
1411 	}
1412 
1413 	return nb_cli_apply_changes(vty, base_xpath);
1414 }
1415 
cli_show_isis_mt_ipv4_multicast(struct vty * vty,struct lyd_node * dnode,bool show_defaults)1416 void cli_show_isis_mt_ipv4_multicast(struct vty *vty, struct lyd_node *dnode,
1417 				     bool show_defaults)
1418 {
1419 	vty_out(vty, " topology ipv4-multicast");
1420 	if (yang_dnode_get_bool(dnode, "./overload"))
1421 		vty_out(vty, " overload");
1422 	vty_out(vty, "\n");
1423 }
1424 
cli_show_isis_mt_ipv4_mgmt(struct vty * vty,struct lyd_node * dnode,bool show_defaults)1425 void cli_show_isis_mt_ipv4_mgmt(struct vty *vty, struct lyd_node *dnode,
1426 				bool show_defaults)
1427 {
1428 	vty_out(vty, " topology ipv4-mgmt");
1429 	if (yang_dnode_get_bool(dnode, "./overload"))
1430 		vty_out(vty, " overload");
1431 	vty_out(vty, "\n");
1432 }
1433 
cli_show_isis_mt_ipv6_unicast(struct vty * vty,struct lyd_node * dnode,bool show_defaults)1434 void cli_show_isis_mt_ipv6_unicast(struct vty *vty, struct lyd_node *dnode,
1435 				   bool show_defaults)
1436 {
1437 	vty_out(vty, " topology ipv6-unicast");
1438 	if (yang_dnode_get_bool(dnode, "./overload"))
1439 		vty_out(vty, " overload");
1440 	vty_out(vty, "\n");
1441 }
1442 
cli_show_isis_mt_ipv6_multicast(struct vty * vty,struct lyd_node * dnode,bool show_defaults)1443 void cli_show_isis_mt_ipv6_multicast(struct vty *vty, struct lyd_node *dnode,
1444 				     bool show_defaults)
1445 {
1446 	vty_out(vty, " topology ipv6-multicast");
1447 	if (yang_dnode_get_bool(dnode, "./overload"))
1448 		vty_out(vty, " overload");
1449 	vty_out(vty, "\n");
1450 }
1451 
cli_show_isis_mt_ipv6_mgmt(struct vty * vty,struct lyd_node * dnode,bool show_defaults)1452 void cli_show_isis_mt_ipv6_mgmt(struct vty *vty, struct lyd_node *dnode,
1453 				bool show_defaults)
1454 {
1455 	vty_out(vty, " topology ipv6-mgmt");
1456 	if (yang_dnode_get_bool(dnode, "./overload"))
1457 		vty_out(vty, " overload");
1458 	vty_out(vty, "\n");
1459 }
1460 
cli_show_isis_mt_ipv6_dstsrc(struct vty * vty,struct lyd_node * dnode,bool show_defaults)1461 void cli_show_isis_mt_ipv6_dstsrc(struct vty *vty, struct lyd_node *dnode,
1462 				  bool show_defaults)
1463 {
1464 	vty_out(vty, " topology ipv6-dstsrc");
1465 	if (yang_dnode_get_bool(dnode, "./overload"))
1466 		vty_out(vty, " overload");
1467 	vty_out(vty, "\n");
1468 }
1469 
1470 /*
1471  * XPath: /frr-isisd:isis/instance/segment-routing/enabled
1472  */
1473 DEFPY_YANG (isis_sr_enable,
1474        isis_sr_enable_cmd,
1475        "segment-routing on",
1476        SR_STR
1477        "Enable Segment Routing\n")
1478 {
1479 	nb_cli_enqueue_change(vty, "./segment-routing/enabled", NB_OP_MODIFY,
1480 			      "true");
1481 
1482 	return nb_cli_apply_changes(vty, NULL);
1483 }
1484 
1485 DEFPY_YANG (no_isis_sr_enable,
1486        no_isis_sr_enable_cmd,
1487        "no segment-routing [on]",
1488        NO_STR
1489        SR_STR
1490        "Disable Segment Routing\n")
1491 {
1492 	nb_cli_enqueue_change(vty, "./segment-routing/enabled", NB_OP_MODIFY,
1493 			      "false");
1494 
1495 	return nb_cli_apply_changes(vty, NULL);
1496 }
1497 
cli_show_isis_sr_enabled(struct vty * vty,struct lyd_node * dnode,bool show_defaults)1498 void cli_show_isis_sr_enabled(struct vty *vty, struct lyd_node *dnode,
1499 			      bool show_defaults)
1500 {
1501 	if (!yang_dnode_get_bool(dnode, NULL))
1502 		vty_out(vty, " no");
1503 
1504 	vty_out(vty, " segment-routing on\n");
1505 }
1506 
1507 /*
1508  * XPath: /frr-isisd:isis/instance/segment-routing/srgb
1509  */
1510 DEFPY_YANG (isis_sr_global_block_label_range,
1511        isis_sr_global_block_label_range_cmd,
1512        "segment-routing global-block (16-1048575)$lower_bound (16-1048575)$upper_bound",
1513        SR_STR
1514        "Segment Routing Global Block label range\n"
1515        "The lower bound of the block\n"
1516        "The upper bound of the block (block size may not exceed 65535)\n")
1517 {
1518 	nb_cli_enqueue_change(vty, "./segment-routing/srgb/lower-bound",
1519 			      NB_OP_MODIFY, lower_bound_str);
1520 	nb_cli_enqueue_change(vty, "./segment-routing/srgb/upper-bound",
1521 			      NB_OP_MODIFY, upper_bound_str);
1522 
1523 	return nb_cli_apply_changes(vty, NULL);
1524 }
1525 
1526 DEFPY_YANG (no_isis_sr_global_block_label_range,
1527        no_isis_sr_global_block_label_range_cmd,
1528        "no segment-routing global-block [(16-1048575) (16-1048575)]",
1529        NO_STR
1530        SR_STR
1531        "Segment Routing Global Block label range\n"
1532        "The lower bound of the block\n"
1533        "The upper bound of the block (block size may not exceed 65535)\n")
1534 {
1535 	nb_cli_enqueue_change(vty, "./segment-routing/srgb/lower-bound",
1536 			      NB_OP_MODIFY, NULL);
1537 	nb_cli_enqueue_change(vty, "./segment-routing/srgb/upper-bound",
1538 			      NB_OP_MODIFY, NULL);
1539 
1540 	return nb_cli_apply_changes(vty, NULL);
1541 }
1542 
cli_show_isis_srgb(struct vty * vty,struct lyd_node * dnode,bool show_defaults)1543 void cli_show_isis_srgb(struct vty *vty, struct lyd_node *dnode,
1544 			bool show_defaults)
1545 {
1546 	vty_out(vty, " segment-routing global-block %s %s\n",
1547 		yang_dnode_get_string(dnode, "./lower-bound"),
1548 		yang_dnode_get_string(dnode, "./upper-bound"));
1549 }
1550 
1551 /*
1552  * XPath: /frr-isisd:isis/instance/segment-routing/srlb
1553  */
1554 DEFPY_YANG (isis_sr_local_block_label_range,
1555        isis_sr_local_block_label_range_cmd,
1556        "segment-routing local-block (16-1048575)$lower_bound (16-1048575)$upper_bound",
1557        SR_STR
1558        "Segment Routing Local Block label range\n"
1559        "The lower bound of the block\n"
1560        "The upper bound of the block (block size may not exceed 65535)\n")
1561 {
1562 	nb_cli_enqueue_change(vty, "./segment-routing/srlb/lower-bound",
1563 			      NB_OP_MODIFY, lower_bound_str);
1564 	nb_cli_enqueue_change(vty, "./segment-routing/srlb/upper-bound",
1565 			      NB_OP_MODIFY, upper_bound_str);
1566 
1567 	return nb_cli_apply_changes(vty, NULL);
1568 }
1569 
1570 DEFPY_YANG (no_isis_sr_local_block_label_range,
1571        no_isis_sr_local_block_label_range_cmd,
1572        "no segment-routing local-block [(16-1048575) (16-1048575)]",
1573        NO_STR
1574        SR_STR
1575        "Segment Routing Local Block label range\n"
1576        "The lower bound of the block\n"
1577        "The upper bound of the block (block size may not exceed 65535)\n")
1578 {
1579 	nb_cli_enqueue_change(vty, "./segment-routing/srlb/lower-bound",
1580 			      NB_OP_MODIFY, NULL);
1581 	nb_cli_enqueue_change(vty, "./segment-routing/srlb/upper-bound",
1582 			      NB_OP_MODIFY, NULL);
1583 
1584 	return nb_cli_apply_changes(vty, NULL);
1585 }
1586 
cli_show_isis_srlb(struct vty * vty,struct lyd_node * dnode,bool show_defaults)1587 void cli_show_isis_srlb(struct vty *vty, struct lyd_node *dnode,
1588 			bool show_defaults)
1589 {
1590 	vty_out(vty, " segment-routing local-block %s %s\n",
1591 		yang_dnode_get_string(dnode, "./lower-bound"),
1592 		yang_dnode_get_string(dnode, "./upper-bound"));
1593 }
1594 
1595 /*
1596  * XPath: /frr-isisd:isis/instance/segment-routing/msd/node-msd
1597  */
1598 DEFPY_YANG (isis_sr_node_msd,
1599        isis_sr_node_msd_cmd,
1600        "segment-routing node-msd (1-16)$msd",
1601        SR_STR
1602        "Maximum Stack Depth for this router\n"
1603        "Maximum number of label that can be stack (1-16)\n")
1604 {
1605 	nb_cli_enqueue_change(vty, "./segment-routing/msd/node-msd",
1606 			      NB_OP_MODIFY, msd_str);
1607 
1608 	return nb_cli_apply_changes(vty, NULL);
1609 }
1610 
1611 DEFPY_YANG (no_isis_sr_node_msd,
1612        no_isis_sr_node_msd_cmd,
1613        "no segment-routing node-msd [(1-16)]",
1614        NO_STR
1615        SR_STR
1616        "Maximum Stack Depth for this router\n"
1617        "Maximum number of label that can be stack (1-16)\n")
1618 {
1619 	nb_cli_enqueue_change(vty, "./segment-routing/msd/node-msd",
1620 			      NB_OP_DESTROY, NULL);
1621 
1622 	return nb_cli_apply_changes(vty, NULL);
1623 }
1624 
cli_show_isis_node_msd(struct vty * vty,struct lyd_node * dnode,bool show_defaults)1625 void cli_show_isis_node_msd(struct vty *vty, struct lyd_node *dnode,
1626 			    bool show_defaults)
1627 {
1628 	vty_out(vty, " segment-routing node-msd %s\n",
1629 		yang_dnode_get_string(dnode, NULL));
1630 }
1631 
1632 /*
1633  * XPath: /frr-isisd:isis/instance/segment-routing/prefix-sid-map/prefix-sid
1634  */
1635 DEFPY_YANG (isis_sr_prefix_sid,
1636        isis_sr_prefix_sid_cmd,
1637        "segment-routing prefix\
1638           <A.B.C.D/M|X:X::X:X/M>$prefix\
1639 	  <absolute$sid_type (16-1048575)$sid_value|index$sid_type (0-65535)$sid_value>\
1640 	  [<no-php-flag|explicit-null>$lh_behavior]",
1641        SR_STR
1642        "Prefix SID\n"
1643        "IPv4 Prefix\n"
1644        "IPv6 Prefix\n"
1645        "Specify the absolute value of Prefix Segment ID\n"
1646        "The Prefix Segment ID value\n"
1647        "Specify the index of Prefix Segment ID\n"
1648        "The Prefix Segment ID index\n"
1649        "Don't request Penultimate Hop Popping (PHP)\n"
1650        "Upstream neighbor must replace prefix-sid with explicit null label\n")
1651 {
1652 	nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
1653 	nb_cli_enqueue_change(vty, "./sid-value-type", NB_OP_MODIFY, sid_type);
1654 	nb_cli_enqueue_change(vty, "./sid-value", NB_OP_MODIFY, sid_value_str);
1655 	if (lh_behavior) {
1656 		const char *value;
1657 
1658 		if (strmatch(lh_behavior, "no-php-flag"))
1659 			value = "no-php";
1660 		else
1661 			value = "explicit-null";
1662 
1663 		nb_cli_enqueue_change(vty, "./last-hop-behavior", NB_OP_MODIFY,
1664 				      value);
1665 	} else
1666 		nb_cli_enqueue_change(vty, "./last-hop-behavior", NB_OP_MODIFY,
1667 				      NULL);
1668 
1669 	return nb_cli_apply_changes(
1670 		vty, "./segment-routing/prefix-sid-map/prefix-sid[prefix='%s']",
1671 		prefix_str);
1672 }
1673 
1674 DEFPY_YANG (no_isis_sr_prefix_sid,
1675        no_isis_sr_prefix_sid_cmd,
1676        "no segment-routing prefix <A.B.C.D/M|X:X::X:X/M>$prefix\
1677          [<absolute$sid_type (16-1048575)|index (0-65535)> [<no-php-flag|explicit-null>]]",
1678        NO_STR
1679        SR_STR
1680        "Prefix SID\n"
1681        "IPv4 Prefix\n"
1682        "IPv6 Prefix\n"
1683        "Specify the absolute value of Prefix Segment ID\n"
1684        "The Prefix Segment ID value\n"
1685        "Specify the index of Prefix Segment ID\n"
1686        "The Prefix Segment ID index\n"
1687        "Don't request Penultimate Hop Popping (PHP)\n"
1688        "Upstream neighbor must replace prefix-sid with explicit null label\n")
1689 {
1690 	nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
1691 
1692 	return nb_cli_apply_changes(
1693 		vty, "./segment-routing/prefix-sid-map/prefix-sid[prefix='%s']",
1694 		prefix_str);
1695 }
1696 
cli_show_isis_prefix_sid(struct vty * vty,struct lyd_node * dnode,bool show_defaults)1697 void cli_show_isis_prefix_sid(struct vty *vty, struct lyd_node *dnode,
1698 			      bool show_defaults)
1699 {
1700 	const char *prefix;
1701 	const char *lh_behavior;
1702 	const char *sid_value_type;
1703 	const char *sid_value;
1704 
1705 	prefix = yang_dnode_get_string(dnode, "./prefix");
1706 	lh_behavior = yang_dnode_get_string(dnode, "./last-hop-behavior");
1707 	sid_value_type = yang_dnode_get_string(dnode, "./sid-value-type");
1708 	sid_value = yang_dnode_get_string(dnode, "./sid-value");
1709 
1710 	vty_out(vty, " segment-routing prefix %s", prefix);
1711 	if (strmatch(sid_value_type, "absolute"))
1712 		vty_out(vty, " absolute");
1713 	else
1714 		vty_out(vty, " index");
1715 	vty_out(vty, " %s", sid_value);
1716 	if (strmatch(lh_behavior, "no-php"))
1717 		vty_out(vty, " no-php-flag");
1718 	else if (strmatch(lh_behavior, "explicit-null"))
1719 		vty_out(vty, " explicit-null");
1720 	vty_out(vty, "\n");
1721 }
1722 
1723 /*
1724  * XPath: /frr-interface:lib/interface/frr-isisd:isis/passive
1725  */
1726 DEFPY_YANG(isis_passive, isis_passive_cmd, "[no] isis passive",
1727       NO_STR
1728       "IS-IS routing protocol\n"
1729       "Configure the passive mode for interface\n")
1730 {
1731 	nb_cli_enqueue_change(vty, "./frr-isisd:isis/passive", NB_OP_MODIFY,
1732 			      no ? "false" : "true");
1733 
1734 	return nb_cli_apply_changes(vty, NULL);
1735 }
1736 
cli_show_ip_isis_passive(struct vty * vty,struct lyd_node * dnode,bool show_defaults)1737 void cli_show_ip_isis_passive(struct vty *vty, struct lyd_node *dnode,
1738 			      bool show_defaults)
1739 {
1740 	if (!yang_dnode_get_bool(dnode, NULL))
1741 		vty_out(vty, " no");
1742 	vty_out(vty, " isis passive\n");
1743 }
1744 
1745 /*
1746  * XPath: /frr-interface:lib/interface/frr-isisd:isis/password
1747  */
1748 
1749 DEFPY_YANG(isis_passwd, isis_passwd_cmd, "isis password <md5|clear>$type WORD$pwd",
1750       "IS-IS routing protocol\n"
1751       "Configure the authentication password for a circuit\n"
1752       "HMAC-MD5 authentication\n"
1753       "Cleartext password\n"
1754       "Circuit password\n")
1755 {
1756 	nb_cli_enqueue_change(vty, "./frr-isisd:isis/password", NB_OP_CREATE,
1757 			      NULL);
1758 	nb_cli_enqueue_change(vty, "./frr-isisd:isis/password/password",
1759 			      NB_OP_MODIFY, pwd);
1760 	nb_cli_enqueue_change(vty, "./frr-isisd:isis/password/password-type",
1761 			      NB_OP_MODIFY, type);
1762 
1763 	return nb_cli_apply_changes(vty, NULL);
1764 }
1765 
1766 DEFPY_YANG(no_isis_passwd, no_isis_passwd_cmd, "no isis password [<md5|clear> WORD]",
1767       NO_STR
1768       "IS-IS routing protocol\n"
1769       "Configure the authentication password for a circuit\n"
1770       "HMAC-MD5 authentication\n"
1771       "Cleartext password\n"
1772       "Circuit password\n")
1773 {
1774 	nb_cli_enqueue_change(vty, "./frr-isisd:isis/password", NB_OP_DESTROY,
1775 			      NULL);
1776 
1777 	return nb_cli_apply_changes(vty, NULL);
1778 }
1779 
cli_show_ip_isis_password(struct vty * vty,struct lyd_node * dnode,bool show_defaults)1780 void cli_show_ip_isis_password(struct vty *vty, struct lyd_node *dnode,
1781 			       bool show_defaults)
1782 {
1783 	vty_out(vty, " isis password %s %s\n",
1784 		yang_dnode_get_string(dnode, "./password-type"),
1785 		yang_dnode_get_string(dnode, "./password"));
1786 }
1787 
1788 /*
1789  * XPath: /frr-interface:lib/interface/frr-isisd:isis/metric
1790  */
1791 DEFPY_YANG(isis_metric, isis_metric_cmd,
1792       "isis metric [level-1|level-2]$level (0-16777215)$met",
1793       "IS-IS routing protocol\n"
1794       "Set default metric for circuit\n"
1795       "Specify metric for level-1 routing\n"
1796       "Specify metric for level-2 routing\n"
1797       "Default metric value\n")
1798 {
1799 	if (!level || strmatch(level, "level-1"))
1800 		nb_cli_enqueue_change(vty, "./frr-isisd:isis/metric/level-1",
1801 				      NB_OP_MODIFY, met_str);
1802 	if (!level || strmatch(level, "level-2"))
1803 		nb_cli_enqueue_change(vty, "./frr-isisd:isis/metric/level-2",
1804 				      NB_OP_MODIFY, met_str);
1805 
1806 	return nb_cli_apply_changes(vty, NULL);
1807 }
1808 
1809 DEFPY_YANG(no_isis_metric, no_isis_metric_cmd,
1810       "no isis metric [level-1|level-2]$level [(0-16777215)]",
1811       NO_STR
1812       "IS-IS routing protocol\n"
1813       "Set default metric for circuit\n"
1814       "Specify metric for level-1 routing\n"
1815       "Specify metric for level-2 routing\n"
1816       "Default metric value\n")
1817 {
1818 	if (!level || strmatch(level, "level-1"))
1819 		nb_cli_enqueue_change(vty, "./frr-isisd:isis/metric/level-1",
1820 				      NB_OP_MODIFY, NULL);
1821 	if (!level || strmatch(level, "level-2"))
1822 		nb_cli_enqueue_change(vty, "./frr-isisd:isis/metric/level-2",
1823 				      NB_OP_MODIFY, NULL);
1824 
1825 	return nb_cli_apply_changes(vty, NULL);
1826 }
1827 
cli_show_ip_isis_metric(struct vty * vty,struct lyd_node * dnode,bool show_defaults)1828 void cli_show_ip_isis_metric(struct vty *vty, struct lyd_node *dnode,
1829 			     bool show_defaults)
1830 {
1831 	const char *l1 = yang_dnode_get_string(dnode, "./level-1");
1832 	const char *l2 = yang_dnode_get_string(dnode, "./level-2");
1833 
1834 	if (strmatch(l1, l2))
1835 		vty_out(vty, " isis metric %s\n", l1);
1836 	else {
1837 		vty_out(vty, " isis metric level-1 %s\n", l1);
1838 		vty_out(vty, " isis metric level-2 %s\n", l2);
1839 	}
1840 }
1841 
1842 /*
1843  * XPath: /frr-interface:lib/interface/frr-isisd:isis/hello/interval
1844  */
1845 DEFPY_YANG(isis_hello_interval, isis_hello_interval_cmd,
1846       "isis hello-interval [level-1|level-2]$level (1-600)$intv",
1847       "IS-IS routing protocol\n"
1848       "Set Hello interval\n"
1849       "Specify hello-interval for level-1 IIHs\n"
1850       "Specify hello-interval for level-2 IIHs\n"
1851       "Holdtime 1 seconds, interval depends on multiplier\n")
1852 {
1853 	if (!level || strmatch(level, "level-1"))
1854 		nb_cli_enqueue_change(vty,
1855 				      "./frr-isisd:isis/hello/interval/level-1",
1856 				      NB_OP_MODIFY, intv_str);
1857 	if (!level || strmatch(level, "level-2"))
1858 		nb_cli_enqueue_change(vty,
1859 				      "./frr-isisd:isis/hello/interval/level-2",
1860 				      NB_OP_MODIFY, intv_str);
1861 
1862 	return nb_cli_apply_changes(vty, NULL);
1863 }
1864 
1865 DEFPY_YANG(no_isis_hello_interval, no_isis_hello_interval_cmd,
1866       "no isis hello-interval [level-1|level-2]$level [(1-600)]",
1867       NO_STR
1868       "IS-IS routing protocol\n"
1869       "Set Hello interval\n"
1870       "Specify hello-interval for level-1 IIHs\n"
1871       "Specify hello-interval for level-2 IIHs\n"
1872       "Holdtime 1 second, interval depends on multiplier\n")
1873 {
1874 	if (!level || strmatch(level, "level-1"))
1875 		nb_cli_enqueue_change(vty,
1876 				      "./frr-isisd:isis/hello/interval/level-1",
1877 				      NB_OP_MODIFY, NULL);
1878 	if (!level || strmatch(level, "level-2"))
1879 		nb_cli_enqueue_change(vty,
1880 				      "./frr-isisd:isis/hello/interval/level-2",
1881 				      NB_OP_MODIFY, NULL);
1882 
1883 	return nb_cli_apply_changes(vty, NULL);
1884 }
1885 
cli_show_ip_isis_hello_interval(struct vty * vty,struct lyd_node * dnode,bool show_defaults)1886 void cli_show_ip_isis_hello_interval(struct vty *vty, struct lyd_node *dnode,
1887 				     bool show_defaults)
1888 {
1889 	const char *l1 = yang_dnode_get_string(dnode, "./level-1");
1890 	const char *l2 = yang_dnode_get_string(dnode, "./level-2");
1891 
1892 	if (strmatch(l1, l2))
1893 		vty_out(vty, " isis hello-interval %s\n", l1);
1894 	else {
1895 		vty_out(vty, " isis hello-interval level-1 %s\n", l1);
1896 		vty_out(vty, " isis hello-interval level-2 %s\n", l2);
1897 	}
1898 }
1899 
1900 /*
1901  * XPath: /frr-interface:lib/interface/frr-isisd:isis/hello/multiplier
1902  */
1903 DEFPY_YANG(isis_hello_multiplier, isis_hello_multiplier_cmd,
1904       "isis hello-multiplier [level-1|level-2]$level (2-100)$mult",
1905       "IS-IS routing protocol\n"
1906       "Set multiplier for Hello holding time\n"
1907       "Specify hello multiplier for level-1 IIHs\n"
1908       "Specify hello multiplier for level-2 IIHs\n"
1909       "Hello multiplier value\n")
1910 {
1911 	if (!level || strmatch(level, "level-1"))
1912 		nb_cli_enqueue_change(
1913 			vty, "./frr-isisd:isis/hello/multiplier/level-1",
1914 			NB_OP_MODIFY, mult_str);
1915 	if (!level || strmatch(level, "level-2"))
1916 		nb_cli_enqueue_change(
1917 			vty, "./frr-isisd:isis/hello/multiplier/level-2",
1918 			NB_OP_MODIFY, mult_str);
1919 
1920 	return nb_cli_apply_changes(vty, NULL);
1921 }
1922 
1923 DEFPY_YANG(no_isis_hello_multiplier, no_isis_hello_multiplier_cmd,
1924       "no isis hello-multiplier [level-1|level-2]$level [(2-100)]",
1925       NO_STR
1926       "IS-IS routing protocol\n"
1927       "Set multiplier for Hello holding time\n"
1928       "Specify hello multiplier for level-1 IIHs\n"
1929       "Specify hello multiplier for level-2 IIHs\n"
1930       "Hello multiplier value\n")
1931 {
1932 	if (!level || strmatch(level, "level-1"))
1933 		nb_cli_enqueue_change(
1934 			vty, "./frr-isisd:isis/hello/multiplier/level-1",
1935 			NB_OP_MODIFY, NULL);
1936 	if (!level || strmatch(level, "level-2"))
1937 		nb_cli_enqueue_change(
1938 			vty, "./frr-isisd:isis/hello/multiplier/level-2",
1939 			NB_OP_MODIFY, NULL);
1940 
1941 	return nb_cli_apply_changes(vty, NULL);
1942 }
1943 
cli_show_ip_isis_hello_multi(struct vty * vty,struct lyd_node * dnode,bool show_defaults)1944 void cli_show_ip_isis_hello_multi(struct vty *vty, struct lyd_node *dnode,
1945 				  bool show_defaults)
1946 {
1947 	const char *l1 = yang_dnode_get_string(dnode, "./level-1");
1948 	const char *l2 = yang_dnode_get_string(dnode, "./level-2");
1949 
1950 	if (strmatch(l1, l2))
1951 		vty_out(vty, " isis hello-multiplier %s\n", l1);
1952 	else {
1953 		vty_out(vty, " isis hello-multiplier level-1 %s\n", l1);
1954 		vty_out(vty, " isis hello-multiplier level-2 %s\n", l2);
1955 	}
1956 }
1957 
1958 /*
1959  * XPath:
1960  * /frr-interface:lib/interface/frr-isisd:isis/disable-three-way-handshake
1961  */
1962 DEFPY_YANG(isis_threeway_adj, isis_threeway_adj_cmd, "[no] isis three-way-handshake",
1963       NO_STR
1964       "IS-IS commands\n"
1965       "Enable/Disable three-way handshake\n")
1966 {
1967 	nb_cli_enqueue_change(vty,
1968 			      "./frr-isisd:isis/disable-three-way-handshake",
1969 			      NB_OP_MODIFY, no ? "true" : "false");
1970 
1971 	return nb_cli_apply_changes(vty, NULL);
1972 }
1973 
cli_show_ip_isis_threeway_shake(struct vty * vty,struct lyd_node * dnode,bool show_defaults)1974 void cli_show_ip_isis_threeway_shake(struct vty *vty, struct lyd_node *dnode,
1975 				     bool show_defaults)
1976 {
1977 	if (yang_dnode_get_bool(dnode, NULL))
1978 		vty_out(vty, " no");
1979 	vty_out(vty, " isis three-way-handshake\n");
1980 }
1981 
1982 /*
1983  * XPath: /frr-interface:lib/interface/frr-isisd:isis/hello/padding
1984  */
1985 DEFPY_YANG(isis_hello_padding, isis_hello_padding_cmd, "[no] isis hello padding",
1986       NO_STR
1987       "IS-IS routing protocol\n"
1988       "Add padding to IS-IS hello packets\n"
1989       "Pad hello packets\n")
1990 {
1991 	nb_cli_enqueue_change(vty, "./frr-isisd:isis/hello/padding",
1992 			      NB_OP_MODIFY, no ? "false" : "true");
1993 
1994 	return nb_cli_apply_changes(vty, NULL);
1995 }
1996 
cli_show_ip_isis_hello_padding(struct vty * vty,struct lyd_node * dnode,bool show_defaults)1997 void cli_show_ip_isis_hello_padding(struct vty *vty, struct lyd_node *dnode,
1998 				    bool show_defaults)
1999 {
2000 	if (!yang_dnode_get_bool(dnode, NULL))
2001 		vty_out(vty, " no");
2002 
2003 	vty_out(vty, " isis hello padding\n");
2004 }
2005 
2006 /*
2007  * XPath: /frr-interface:lib/interface/frr-isisd:isis/csnp-interval
2008  */
2009 DEFPY_YANG(csnp_interval, csnp_interval_cmd,
2010       "isis csnp-interval (1-600)$intv [level-1|level-2]$level",
2011       "IS-IS routing protocol\n"
2012       "Set CSNP interval in seconds\n"
2013       "CSNP interval value\n"
2014       "Specify interval for level-1 CSNPs\n"
2015       "Specify interval for level-2 CSNPs\n")
2016 {
2017 	if (!level || strmatch(level, "level-1"))
2018 		nb_cli_enqueue_change(vty,
2019 				      "./frr-isisd:isis/csnp-interval/level-1",
2020 				      NB_OP_MODIFY, intv_str);
2021 	if (!level || strmatch(level, "level-2"))
2022 		nb_cli_enqueue_change(vty,
2023 				      "./frr-isisd:isis/csnp-interval/level-2",
2024 				      NB_OP_MODIFY, intv_str);
2025 
2026 	return nb_cli_apply_changes(vty, NULL);
2027 }
2028 
2029 DEFPY_YANG(no_csnp_interval, no_csnp_interval_cmd,
2030       "no isis csnp-interval [(1-600)] [level-1|level-2]$level",
2031       NO_STR
2032       "IS-IS routing protocol\n"
2033       "Set CSNP interval in seconds\n"
2034       "CSNP interval value\n"
2035       "Specify interval for level-1 CSNPs\n"
2036       "Specify interval for level-2 CSNPs\n")
2037 {
2038 	if (!level || strmatch(level, "level-1"))
2039 		nb_cli_enqueue_change(vty,
2040 				      "./frr-isisd:isis/csnp-interval/level-1",
2041 				      NB_OP_MODIFY, NULL);
2042 	if (!level || strmatch(level, "level-2"))
2043 		nb_cli_enqueue_change(vty,
2044 				      "./frr-isisd:isis/csnp-interval/level-2",
2045 				      NB_OP_MODIFY, NULL);
2046 
2047 	return nb_cli_apply_changes(vty, NULL);
2048 }
2049 
cli_show_ip_isis_csnp_interval(struct vty * vty,struct lyd_node * dnode,bool show_defaults)2050 void cli_show_ip_isis_csnp_interval(struct vty *vty, struct lyd_node *dnode,
2051 				    bool show_defaults)
2052 {
2053 	const char *l1 = yang_dnode_get_string(dnode, "./level-1");
2054 	const char *l2 = yang_dnode_get_string(dnode, "./level-2");
2055 
2056 	if (strmatch(l1, l2))
2057 		vty_out(vty, " isis csnp-interval %s\n", l1);
2058 	else {
2059 		vty_out(vty, " isis csnp-interval %s level-1\n", l1);
2060 		vty_out(vty, " isis csnp-interval %s level-2\n", l2);
2061 	}
2062 }
2063 
2064 /*
2065  * XPath: /frr-interface:lib/interface/frr-isisd:isis/psnp-interval
2066  */
2067 DEFPY_YANG(psnp_interval, psnp_interval_cmd,
2068       "isis psnp-interval (1-120)$intv [level-1|level-2]$level",
2069       "IS-IS routing protocol\n"
2070       "Set PSNP interval in seconds\n"
2071       "PSNP interval value\n"
2072       "Specify interval for level-1 PSNPs\n"
2073       "Specify interval for level-2 PSNPs\n")
2074 {
2075 	if (!level || strmatch(level, "level-1"))
2076 		nb_cli_enqueue_change(vty,
2077 				      "./frr-isisd:isis/psnp-interval/level-1",
2078 				      NB_OP_MODIFY, intv_str);
2079 	if (!level || strmatch(level, "level-2"))
2080 		nb_cli_enqueue_change(vty,
2081 				      "./frr-isisd:isis/psnp-interval/level-2",
2082 				      NB_OP_MODIFY, intv_str);
2083 
2084 	return nb_cli_apply_changes(vty, NULL);
2085 }
2086 
2087 DEFPY_YANG(no_psnp_interval, no_psnp_interval_cmd,
2088       "no isis psnp-interval [(1-120)] [level-1|level-2]$level",
2089       NO_STR
2090       "IS-IS routing protocol\n"
2091       "Set PSNP interval in seconds\n"
2092       "PSNP interval value\n"
2093       "Specify interval for level-1 PSNPs\n"
2094       "Specify interval for level-2 PSNPs\n")
2095 {
2096 	if (!level || strmatch(level, "level-1"))
2097 		nb_cli_enqueue_change(vty,
2098 				      "./frr-isisd:isis/psnp-interval/level-1",
2099 				      NB_OP_MODIFY, NULL);
2100 	if (!level || strmatch(level, "level-2"))
2101 		nb_cli_enqueue_change(vty,
2102 				      "./frr-isisd:isis/psnp-interval/level-2",
2103 				      NB_OP_MODIFY, NULL);
2104 
2105 	return nb_cli_apply_changes(vty, NULL);
2106 }
2107 
cli_show_ip_isis_psnp_interval(struct vty * vty,struct lyd_node * dnode,bool show_defaults)2108 void cli_show_ip_isis_psnp_interval(struct vty *vty, struct lyd_node *dnode,
2109 				    bool show_defaults)
2110 {
2111 	const char *l1 = yang_dnode_get_string(dnode, "./level-1");
2112 	const char *l2 = yang_dnode_get_string(dnode, "./level-2");
2113 
2114 	if (strmatch(l1, l2))
2115 		vty_out(vty, " isis psnp-interval %s\n", l1);
2116 	else {
2117 		vty_out(vty, " isis psnp-interval %s level-1\n", l1);
2118 		vty_out(vty, " isis psnp-interval %s level-2\n", l2);
2119 	}
2120 }
2121 
2122 /*
2123  * XPath: /frr-interface:lib/interface/frr-isisd:isis/multi-topology
2124  */
2125 DEFPY_YANG(circuit_topology, circuit_topology_cmd,
2126       "[no] isis topology<ipv4-unicast|ipv4-mgmt|ipv6-unicast|ipv4-multicast|ipv6-multicast|ipv6-mgmt|ipv6-dstsrc>$topology",
2127       NO_STR
2128       "IS-IS routing protocol\n"
2129       "Configure interface IS-IS topologies\n"
2130       "IPv4 unicast topology\n"
2131       "IPv4 management topology\n"
2132       "IPv6 unicast topology\n"
2133       "IPv4 multicast topology\n"
2134       "IPv6 multicast topology\n"
2135       "IPv6 management topology\n"
2136       "IPv6 dst-src topology\n")
2137 {
2138 	nb_cli_enqueue_change(vty, ".", NB_OP_MODIFY, no ? "false" : "true");
2139 
2140 	if (strmatch(topology, "ipv4-mgmt"))
2141 		return nb_cli_apply_changes(
2142 			vty, "./frr-isisd:isis/multi-topology/ipv4-management");
2143 	else if (strmatch(topology, "ipv6-mgmt"))
2144 		return nb_cli_apply_changes(
2145 			vty, "./frr-isisd:isis/multi-topology/ipv6-management");
2146 	else
2147 		return nb_cli_apply_changes(
2148 			vty, "./frr-isisd:isis/multi-topology/%s", topology);
2149 }
2150 
cli_show_ip_isis_mt_ipv4_unicast(struct vty * vty,struct lyd_node * dnode,bool show_defaults)2151 void cli_show_ip_isis_mt_ipv4_unicast(struct vty *vty, struct lyd_node *dnode,
2152 				      bool show_defaults)
2153 {
2154 	if (!yang_dnode_get_bool(dnode, NULL))
2155 		vty_out(vty, " no");
2156 	vty_out(vty, " isis topology ipv4-unicast\n");
2157 }
2158 
cli_show_ip_isis_mt_ipv4_multicast(struct vty * vty,struct lyd_node * dnode,bool show_defaults)2159 void cli_show_ip_isis_mt_ipv4_multicast(struct vty *vty, struct lyd_node *dnode,
2160 					bool show_defaults)
2161 {
2162 	if (!yang_dnode_get_bool(dnode, NULL))
2163 		vty_out(vty, " no");
2164 	vty_out(vty, " isis topology ipv4-multicast\n");
2165 }
2166 
cli_show_ip_isis_mt_ipv4_mgmt(struct vty * vty,struct lyd_node * dnode,bool show_defaults)2167 void cli_show_ip_isis_mt_ipv4_mgmt(struct vty *vty, struct lyd_node *dnode,
2168 				   bool show_defaults)
2169 {
2170 	if (!yang_dnode_get_bool(dnode, NULL))
2171 		vty_out(vty, " no");
2172 	vty_out(vty, " isis topology ipv4-mgmt\n");
2173 }
2174 
cli_show_ip_isis_mt_ipv6_unicast(struct vty * vty,struct lyd_node * dnode,bool show_defaults)2175 void cli_show_ip_isis_mt_ipv6_unicast(struct vty *vty, struct lyd_node *dnode,
2176 				      bool show_defaults)
2177 {
2178 	if (!yang_dnode_get_bool(dnode, NULL))
2179 		vty_out(vty, " no");
2180 	vty_out(vty, " isis topology ipv6-unicast\n");
2181 }
2182 
cli_show_ip_isis_mt_ipv6_multicast(struct vty * vty,struct lyd_node * dnode,bool show_defaults)2183 void cli_show_ip_isis_mt_ipv6_multicast(struct vty *vty, struct lyd_node *dnode,
2184 					bool show_defaults)
2185 {
2186 	if (!yang_dnode_get_bool(dnode, NULL))
2187 		vty_out(vty, " no");
2188 	vty_out(vty, " isis topology ipv6-multicast\n");
2189 }
2190 
cli_show_ip_isis_mt_ipv6_mgmt(struct vty * vty,struct lyd_node * dnode,bool show_defaults)2191 void cli_show_ip_isis_mt_ipv6_mgmt(struct vty *vty, struct lyd_node *dnode,
2192 				   bool show_defaults)
2193 {
2194 	if (!yang_dnode_get_bool(dnode, NULL))
2195 		vty_out(vty, " no");
2196 	vty_out(vty, " isis topology ipv6-mgmt\n");
2197 }
2198 
cli_show_ip_isis_mt_ipv6_dstsrc(struct vty * vty,struct lyd_node * dnode,bool show_defaults)2199 void cli_show_ip_isis_mt_ipv6_dstsrc(struct vty *vty, struct lyd_node *dnode,
2200 				     bool show_defaults)
2201 {
2202 	if (!yang_dnode_get_bool(dnode, NULL))
2203 		vty_out(vty, " no");
2204 	vty_out(vty, " isis topology ipv6-dstsrc\n");
2205 }
2206 
2207 /*
2208  * XPath: /frr-interface:lib/interface/frr-isisd:isis/circuit-type
2209  */
2210 DEFPY_YANG(isis_circuit_type, isis_circuit_type_cmd,
2211       "isis circuit-type <level-1|level-1-2|level-2-only>$type",
2212       "IS-IS routing protocol\n"
2213       "Configure circuit type for interface\n"
2214       "Level-1 only adjacencies are formed\n"
2215       "Level-1-2 adjacencies are formed\n"
2216       "Level-2 only adjacencies are formed\n")
2217 {
2218 	nb_cli_enqueue_change(
2219 		vty, "./frr-isisd:isis/circuit-type", NB_OP_MODIFY,
2220 		strmatch(type, "level-2-only") ? "level-2" : type);
2221 
2222 	return nb_cli_apply_changes(vty, NULL);
2223 }
2224 
2225 DEFPY_YANG(no_isis_circuit_type, no_isis_circuit_type_cmd,
2226       "no isis circuit-type [level-1|level-1-2|level-2-only]",
2227       NO_STR
2228       "IS-IS routing protocol\n"
2229       "Configure circuit type for interface\n"
2230       "Level-1 only adjacencies are formed\n"
2231       "Level-1-2 adjacencies are formed\n"
2232       "Level-2 only adjacencies are formed\n")
2233 {
2234 	struct interface *ifp;
2235 	struct isis_circuit *circuit;
2236 	int is_type;
2237 	const char *circ_type;
2238 
2239 	/*
2240 	 * Default value depends on whether the circuit is part of an area,
2241 	 * and the is-type of the area if there is one. So we need to do this
2242 	 * here.
2243 	 */
2244 	ifp = nb_running_get_entry(NULL, VTY_CURR_XPATH, false);
2245 	if (!ifp)
2246 		goto def_val;
2247 
2248 	circuit = circuit_scan_by_ifp(ifp);
2249 	if (!circuit)
2250 		goto def_val;
2251 
2252 	if (circuit->state == C_STATE_UP)
2253 		is_type = circuit->area->is_type;
2254 	else
2255 		goto def_val;
2256 
2257 	switch (is_type) {
2258 	case IS_LEVEL_1:
2259 		circ_type = "level-1";
2260 		break;
2261 	case IS_LEVEL_2:
2262 		circ_type = "level-2";
2263 		break;
2264 	case IS_LEVEL_1_AND_2:
2265 		circ_type = "level-1-2";
2266 		break;
2267 	default:
2268 		return CMD_ERR_NO_MATCH;
2269 	}
2270 	nb_cli_enqueue_change(vty, "./frr-isisd:isis/circuit-type",
2271 			      NB_OP_MODIFY, circ_type);
2272 
2273 	return nb_cli_apply_changes(vty, NULL);
2274 
2275 def_val:
2276 	nb_cli_enqueue_change(vty, "./frr-isisd:isis/circuit-type",
2277 			      NB_OP_MODIFY, NULL);
2278 
2279 	return nb_cli_apply_changes(vty, NULL);
2280 }
2281 
cli_show_ip_isis_circ_type(struct vty * vty,struct lyd_node * dnode,bool show_defaults)2282 void cli_show_ip_isis_circ_type(struct vty *vty, struct lyd_node *dnode,
2283 				bool show_defaults)
2284 {
2285 	int level = yang_dnode_get_enum(dnode, NULL);
2286 
2287 	switch (level) {
2288 	case IS_LEVEL_1:
2289 		vty_out(vty, " isis circuit-type level-1\n");
2290 		break;
2291 	case IS_LEVEL_2:
2292 		vty_out(vty, " isis circuit-type level-2-only\n");
2293 		break;
2294 	case IS_LEVEL_1_AND_2:
2295 		vty_out(vty, " isis circuit-type level-1-2\n");
2296 		break;
2297 	}
2298 }
2299 
2300 /*
2301  * XPath: /frr-interface:lib/interface/frr-isisd:isis/network-type
2302  */
2303 DEFPY_YANG(isis_network, isis_network_cmd, "[no] isis network point-to-point",
2304       NO_STR
2305       "IS-IS routing protocol\n"
2306       "Set network type\n"
2307       "point-to-point network type\n")
2308 {
2309 	nb_cli_enqueue_change(vty, "./frr-isisd:isis/network-type",
2310 			      NB_OP_MODIFY,
2311 			      no ? "broadcast" : "point-to-point");
2312 
2313 	return nb_cli_apply_changes(vty, NULL);
2314 }
2315 
cli_show_ip_isis_network_type(struct vty * vty,struct lyd_node * dnode,bool show_defaults)2316 void cli_show_ip_isis_network_type(struct vty *vty, struct lyd_node *dnode,
2317 				   bool show_defaults)
2318 {
2319 	if (yang_dnode_get_enum(dnode, NULL) != CIRCUIT_T_P2P)
2320 		vty_out(vty, " no");
2321 
2322 	vty_out(vty, " isis network point-to-point\n");
2323 }
2324 
2325 /*
2326  * XPath: /frr-interface:lib/interface/frr-isisd:isis/priority
2327  */
2328 DEFPY_YANG(isis_priority, isis_priority_cmd,
2329       "isis priority (0-127)$prio [level-1|level-2]$level",
2330       "IS-IS routing protocol\n"
2331       "Set priority for Designated Router election\n"
2332       "Priority value\n"
2333       "Specify priority for level-1 routing\n"
2334       "Specify priority for level-2 routing\n")
2335 {
2336 	if (!level || strmatch(level, "level-1"))
2337 		nb_cli_enqueue_change(vty, "./frr-isisd:isis/priority/level-1",
2338 				      NB_OP_MODIFY, prio_str);
2339 	if (!level || strmatch(level, "level-2"))
2340 		nb_cli_enqueue_change(vty, "./frr-isisd:isis/priority/level-2",
2341 				      NB_OP_MODIFY, prio_str);
2342 
2343 	return nb_cli_apply_changes(vty, NULL);
2344 }
2345 
2346 DEFPY_YANG(no_isis_priority, no_isis_priority_cmd,
2347       "no isis priority [(0-127)] [level-1|level-2]$level",
2348       NO_STR
2349       "IS-IS routing protocol\n"
2350       "Set priority for Designated Router election\n"
2351       "Priority value\n"
2352       "Specify priority for level-1 routing\n"
2353       "Specify priority for level-2 routing\n")
2354 {
2355 	if (!level || strmatch(level, "level-1"))
2356 		nb_cli_enqueue_change(vty, "./frr-isisd:isis/priority/level-1",
2357 				      NB_OP_MODIFY, NULL);
2358 	if (!level || strmatch(level, "level-2"))
2359 		nb_cli_enqueue_change(vty, "./frr-isisd:isis/priority/level-2",
2360 				      NB_OP_MODIFY, NULL);
2361 
2362 	return nb_cli_apply_changes(vty, NULL);
2363 }
2364 
cli_show_ip_isis_priority(struct vty * vty,struct lyd_node * dnode,bool show_defaults)2365 void cli_show_ip_isis_priority(struct vty *vty, struct lyd_node *dnode,
2366 			       bool show_defaults)
2367 {
2368 	const char *l1 = yang_dnode_get_string(dnode, "./level-1");
2369 	const char *l2 = yang_dnode_get_string(dnode, "./level-2");
2370 
2371 	if (strmatch(l1, l2))
2372 		vty_out(vty, " isis priority %s\n", l1);
2373 	else {
2374 		vty_out(vty, " isis priority %s level-1\n", l1);
2375 		vty_out(vty, " isis priority %s level-2\n", l2);
2376 	}
2377 }
2378 
2379 /*
2380  * XPath: /frr-isisd:isis/instance/log-adjacency-changes
2381  */
2382 DEFPY_YANG(log_adj_changes, log_adj_changes_cmd, "[no] log-adjacency-changes",
2383       NO_STR "Log changes in adjacency state\n")
2384 {
2385 	nb_cli_enqueue_change(vty, "./log-adjacency-changes", NB_OP_MODIFY,
2386 			      no ? "false" : "true");
2387 
2388 	return nb_cli_apply_changes(vty, NULL);
2389 }
2390 
cli_show_isis_log_adjacency(struct vty * vty,struct lyd_node * dnode,bool show_defaults)2391 void cli_show_isis_log_adjacency(struct vty *vty, struct lyd_node *dnode,
2392 				 bool show_defaults)
2393 {
2394 	if (!yang_dnode_get_bool(dnode, NULL))
2395 		vty_out(vty, " no");
2396 	vty_out(vty, " log-adjacency-changes\n");
2397 }
2398 
isis_cli_init(void)2399 void isis_cli_init(void)
2400 {
2401 	install_element(CONFIG_NODE, &router_isis_cmd);
2402 	install_element(CONFIG_NODE, &no_router_isis_cmd);
2403 
2404 	install_element(INTERFACE_NODE, &ip_router_isis_cmd);
2405 	install_element(INTERFACE_NODE, &ip6_router_isis_cmd);
2406 	install_element(INTERFACE_NODE, &no_ip_router_isis_cmd);
2407 	install_element(INTERFACE_NODE, &isis_bfd_cmd);
2408 	install_element(INTERFACE_NODE, &isis_bfd_profile_cmd);
2409 
2410 	install_element(ISIS_NODE, &net_cmd);
2411 
2412 	install_element(ISIS_NODE, &is_type_cmd);
2413 	install_element(ISIS_NODE, &no_is_type_cmd);
2414 
2415 	install_element(ISIS_NODE, &dynamic_hostname_cmd);
2416 
2417 	install_element(ISIS_NODE, &set_overload_bit_cmd);
2418 	install_element(ISIS_NODE, &set_attached_bit_cmd);
2419 
2420 	install_element(ISIS_NODE, &metric_style_cmd);
2421 	install_element(ISIS_NODE, &no_metric_style_cmd);
2422 
2423 	install_element(ISIS_NODE, &area_passwd_cmd);
2424 	install_element(ISIS_NODE, &domain_passwd_cmd);
2425 	install_element(ISIS_NODE, &no_area_passwd_cmd);
2426 
2427 	install_element(ISIS_NODE, &lsp_gen_interval_cmd);
2428 	install_element(ISIS_NODE, &no_lsp_gen_interval_cmd);
2429 	install_element(ISIS_NODE, &lsp_refresh_interval_cmd);
2430 	install_element(ISIS_NODE, &no_lsp_refresh_interval_cmd);
2431 	install_element(ISIS_NODE, &max_lsp_lifetime_cmd);
2432 	install_element(ISIS_NODE, &no_max_lsp_lifetime_cmd);
2433 	install_element(ISIS_NODE, &lsp_timers_cmd);
2434 	install_element(ISIS_NODE, &no_lsp_timers_cmd);
2435 	install_element(ISIS_NODE, &area_lsp_mtu_cmd);
2436 	install_element(ISIS_NODE, &no_area_lsp_mtu_cmd);
2437 
2438 	install_element(ISIS_NODE, &spf_interval_cmd);
2439 	install_element(ISIS_NODE, &no_spf_interval_cmd);
2440 	install_element(ISIS_NODE, &spf_delay_ietf_cmd);
2441 	install_element(ISIS_NODE, &no_spf_delay_ietf_cmd);
2442 
2443 	install_element(ISIS_NODE, &area_purge_originator_cmd);
2444 
2445 	install_element(ISIS_NODE, &isis_mpls_te_on_cmd);
2446 	install_element(ISIS_NODE, &no_isis_mpls_te_on_cmd);
2447 	install_element(ISIS_NODE, &isis_mpls_te_router_addr_cmd);
2448 	install_element(ISIS_NODE, &no_isis_mpls_te_router_addr_cmd);
2449 	install_element(ISIS_NODE, &isis_mpls_te_inter_as_cmd);
2450 
2451 	install_element(ISIS_NODE, &isis_default_originate_cmd);
2452 	install_element(ISIS_NODE, &isis_redistribute_cmd);
2453 
2454 	install_element(ISIS_NODE, &isis_topology_cmd);
2455 
2456 	install_element(ISIS_NODE, &isis_sr_enable_cmd);
2457 	install_element(ISIS_NODE, &no_isis_sr_enable_cmd);
2458 	install_element(ISIS_NODE, &isis_sr_global_block_label_range_cmd);
2459 	install_element(ISIS_NODE, &no_isis_sr_global_block_label_range_cmd);
2460 	install_element(ISIS_NODE, &isis_sr_local_block_label_range_cmd);
2461 	install_element(ISIS_NODE, &no_isis_sr_local_block_label_range_cmd);
2462 	install_element(ISIS_NODE, &isis_sr_node_msd_cmd);
2463 	install_element(ISIS_NODE, &no_isis_sr_node_msd_cmd);
2464 	install_element(ISIS_NODE, &isis_sr_prefix_sid_cmd);
2465 	install_element(ISIS_NODE, &no_isis_sr_prefix_sid_cmd);
2466 
2467 	install_element(INTERFACE_NODE, &isis_passive_cmd);
2468 
2469 	install_element(INTERFACE_NODE, &isis_passwd_cmd);
2470 	install_element(INTERFACE_NODE, &no_isis_passwd_cmd);
2471 
2472 	install_element(INTERFACE_NODE, &isis_metric_cmd);
2473 	install_element(INTERFACE_NODE, &no_isis_metric_cmd);
2474 
2475 	install_element(INTERFACE_NODE, &isis_hello_interval_cmd);
2476 	install_element(INTERFACE_NODE, &no_isis_hello_interval_cmd);
2477 
2478 	install_element(INTERFACE_NODE, &isis_hello_multiplier_cmd);
2479 	install_element(INTERFACE_NODE, &no_isis_hello_multiplier_cmd);
2480 
2481 	install_element(INTERFACE_NODE, &isis_threeway_adj_cmd);
2482 
2483 	install_element(INTERFACE_NODE, &isis_hello_padding_cmd);
2484 
2485 	install_element(INTERFACE_NODE, &csnp_interval_cmd);
2486 	install_element(INTERFACE_NODE, &no_csnp_interval_cmd);
2487 
2488 	install_element(INTERFACE_NODE, &psnp_interval_cmd);
2489 	install_element(INTERFACE_NODE, &no_psnp_interval_cmd);
2490 
2491 	install_element(INTERFACE_NODE, &circuit_topology_cmd);
2492 
2493 	install_element(INTERFACE_NODE, &isis_circuit_type_cmd);
2494 	install_element(INTERFACE_NODE, &no_isis_circuit_type_cmd);
2495 
2496 	install_element(INTERFACE_NODE, &isis_network_cmd);
2497 
2498 	install_element(INTERFACE_NODE, &isis_priority_cmd);
2499 	install_element(INTERFACE_NODE, &no_isis_priority_cmd);
2500 
2501 	install_element(ISIS_NODE, &log_adj_changes_cmd);
2502 }
2503 
2504 #endif /* ifndef FABRICD */
2505