]> git.proxmox.com Git - mirror_frr.git/blame - isisd/isis_cli.c
isisd: retrofit the 'is-type' command
[mirror_frr.git] / isisd / isis_cli.c
CommitLineData
20bd27e2
EDP
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_cli.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
aaf2fd21
EDP
46/*
47 * XPath: /frr-isisd:isis/instance
48 */
49DEFPY_NOSH(router_isis, router_isis_cmd, "router isis WORD$tag",
50 ROUTER_STR
51 "ISO IS-IS\n"
52 "ISO Routing area tag\n")
53{
54 int ret;
55 char base_xpath[XPATH_MAXLEN];
56
57 snprintf(base_xpath, XPATH_MAXLEN,
58 "/frr-isisd:isis/instance[area-tag='%s']", tag);
59 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
60 /* default value in yang for is-type is level-1, but in FRR
61 * the first instance is assigned is-type level-1-2. We
62 * need to make sure to set it in the yang model so that it
63 * is consistent with what FRR sees.
64 */
65 if (listcount(isis->area_list) == 0)
66 nb_cli_enqueue_change(vty, "./is-type", NB_OP_MODIFY,
67 "level-1-2");
68 ret = nb_cli_apply_changes(vty, base_xpath);
69 if (ret == CMD_SUCCESS)
70 VTY_PUSH_XPATH(ISIS_NODE, base_xpath);
71
72 return ret;
73}
74
75DEFPY(no_router_isis, no_router_isis_cmd, "no router isis WORD$tag",
76 NO_STR ROUTER_STR
77 "ISO IS-IS\n"
78 "ISO Routing area tag\n")
79{
80 char temp_xpath[XPATH_MAXLEN];
81 struct listnode *node, *nnode;
82 struct isis_circuit *circuit = NULL;
83 struct isis_area *area = NULL;
84
85 area = isis_area_lookup(tag);
86 if (!area) {
87 vty_out(vty, "ISIS area %s not found.\n", tag);
88 return CMD_ERR_NOTHING_TODO;
89 }
90
91 nb_cli_enqueue_change(vty, ".", NB_OP_DELETE, NULL);
92 if (area->circuit_list && listcount(area->circuit_list)) {
93 for (ALL_LIST_ELEMENTS(area->circuit_list, node, nnode,
94 circuit)) {
95 /* add callbacks to delete each of the circuits listed
96 */
97 const char *vrf_name =
98 vrf_lookup_by_id(circuit->interface->vrf_id)
99 ->name;
100 snprintf(
101 temp_xpath, XPATH_MAXLEN,
102 "/frr-interface:lib/interface[name='%s'][vrf='%s']/frr-isisd:isis",
103 circuit->interface->name, vrf_name);
104 nb_cli_enqueue_change(vty, temp_xpath, NB_OP_DELETE,
105 NULL);
106 }
107 }
108
109 return nb_cli_apply_changes(
110 vty, "/frr-isisd:isis/instance[area-tag='%s']", tag);
111}
112
113void cli_show_router_isis(struct vty *vty, struct lyd_node *dnode,
114 bool show_defaults)
115{
116 vty_out(vty, "!\n");
117 vty_out(vty, "router isis %s\n",
118 yang_dnode_get_string(dnode, "./area-tag"));
119}
120
121/*
122 * XPath: /frr-interface:lib/interface/frr-isisd:isis/
123 * XPath: /frr-interface:lib/interface/frr-isisd:isis/ipv4-routing
124 * XPath: /frr-interface:lib/interface/frr-isisd:isis/ipv6-routing
125 * XPath: /frr-isisd:isis/instance
126 */
127DEFPY(ip_router_isis, ip_router_isis_cmd, "ip router isis WORD$tag",
128 "Interface Internet Protocol config commands\n"
129 "IP router interface commands\n"
130 "IS-IS routing protocol\n"
131 "Routing process tag\n")
132{
133 char temp_xpath[XPATH_MAXLEN];
134 const char *circ_type;
135 struct isis_area *area;
136
137 /* area will be created if it is not present. make sure the yang model
138 * is synced with FRR and call the appropriate NB cb.
139 */
140 area = isis_area_lookup(tag);
141 if (!area) {
142 snprintf(temp_xpath, XPATH_MAXLEN,
143 "/frr-isisd:isis/instance[area-tag='%s']", tag);
144 nb_cli_enqueue_change(vty, temp_xpath, NB_OP_CREATE, tag);
145 snprintf(temp_xpath, XPATH_MAXLEN,
146 "/frr-isisd:isis/instance[area-tag='%s']/is-type",
147 tag);
148 nb_cli_enqueue_change(
149 vty, temp_xpath, NB_OP_MODIFY,
150 listcount(isis->area_list) == 0 ? "level-1-2" : NULL);
151 nb_cli_enqueue_change(vty, "./frr-isisd:isis", NB_OP_CREATE,
152 NULL);
153 nb_cli_enqueue_change(vty, "./frr-isisd:isis/area-tag",
154 NB_OP_MODIFY, tag);
155 nb_cli_enqueue_change(vty, "./frr-isisd:isis/ipv4-routing",
156 NB_OP_CREATE, NULL);
157 nb_cli_enqueue_change(
158 vty, "./frr-isisd:isis/circuit-type", NB_OP_MODIFY,
159 listcount(isis->area_list) == 0 ? "level-1-2"
160 : "level-1");
161 } else {
162 /* area exists, circuit type defaults to its area's is_type */
163 switch (area->is_type) {
164 case IS_LEVEL_1:
165 circ_type = "level-1";
166 break;
167 case IS_LEVEL_2:
168 circ_type = "level-2";
169 break;
170 case IS_LEVEL_1_AND_2:
171 circ_type = "level-1-2";
172 break;
173 }
174 nb_cli_enqueue_change(vty, "./frr-isisd:isis", NB_OP_CREATE,
175 NULL);
176 nb_cli_enqueue_change(vty, "./frr-isisd:isis/area-tag",
177 NB_OP_MODIFY, tag);
178 nb_cli_enqueue_change(vty, "./frr-isisd:isis/ipv4-routing",
179 NB_OP_CREATE, NULL);
180 nb_cli_enqueue_change(vty, "./frr-isisd:isis/circuit-type",
181 NB_OP_MODIFY, circ_type);
182 }
183
184 return nb_cli_apply_changes(vty, NULL);
185}
186
187DEFPY(ip6_router_isis, ip6_router_isis_cmd, "ipv6 router isis WORD$tag",
188 "Interface Internet Protocol config commands\n"
189 "IP router interface commands\n"
190 "IS-IS routing protocol\n"
191 "Routing process tag\n")
192{
193 char temp_xpath[XPATH_MAXLEN];
194 const char *circ_type;
195 struct isis_area *area;
196
197 /* area will be created if it is not present. make sure the yang model
198 * is synced with FRR and call the appropriate NB cb.
199 */
200 area = isis_area_lookup(tag);
201 if (!area) {
202 snprintf(temp_xpath, XPATH_MAXLEN,
203 "/frr-isisd:isis/instance[area-tag='%s']", tag);
204 nb_cli_enqueue_change(vty, temp_xpath, NB_OP_CREATE, tag);
205 snprintf(temp_xpath, XPATH_MAXLEN,
206 "/frr-isisd:isis/instance[area-tag='%s']/is-type",
207 tag);
208 nb_cli_enqueue_change(
209 vty, temp_xpath, NB_OP_MODIFY,
210 listcount(isis->area_list) == 0 ? "level-1-2" : NULL);
211 nb_cli_enqueue_change(vty, "./frr-isisd:isis", NB_OP_CREATE,
212 NULL);
213 nb_cli_enqueue_change(vty, "./frr-isisd:isis/area-tag",
214 NB_OP_MODIFY, tag);
215 nb_cli_enqueue_change(vty, "./frr-isisd:isis/ipv6-routing",
216 NB_OP_CREATE, NULL);
217 nb_cli_enqueue_change(
218 vty, "./frr-isisd:isis/circuit-type", NB_OP_MODIFY,
219 listcount(isis->area_list) == 0 ? "level-1-2"
220 : "level-1");
221 } else {
222 /* area exists, circuit type defaults to its area's is_type */
223 switch (area->is_type) {
224 case IS_LEVEL_1:
225 circ_type = "level-1";
226 break;
227 case IS_LEVEL_2:
228 circ_type = "level-2";
229 break;
230 case IS_LEVEL_1_AND_2:
231 circ_type = "level-1-2";
232 break;
233 }
234 nb_cli_enqueue_change(vty, "./frr-isisd:isis", NB_OP_CREATE,
235 NULL);
236 nb_cli_enqueue_change(vty, "./frr-isisd:isis/area-tag",
237 NB_OP_MODIFY, tag);
238 nb_cli_enqueue_change(vty, "./frr-isisd:isis/ipv6-routing",
239 NB_OP_CREATE, NULL);
240 nb_cli_enqueue_change(vty, "./frr-isisd:isis/circuit-type",
241 NB_OP_MODIFY, circ_type);
242 }
243
244 return nb_cli_apply_changes(vty, NULL);
245}
246
247DEFPY(no_ip_router_isis, no_ip_router_isis_cmd,
248 "no <ip|ipv6>$ip router isis [WORD]$tag",
249 NO_STR
250 "Interface Internet Protocol config commands\n"
251 "IP router interface commands\n"
252 "IP router interface commands\n"
253 "IS-IS routing protocol\n"
254 "Routing process tag\n")
255{
256 const struct lyd_node *dnode =
257 yang_dnode_get(running_config->dnode, VTY_CURR_XPATH);
258 struct interface *ifp;
259 struct isis_circuit *circuit = NULL;
260
261 /* check for the existance of a circuit */
262 if (dnode) {
263 ifp = yang_dnode_get_entry(dnode, false);
264 if (ifp)
265 circuit = circuit_scan_by_ifp(ifp);
266 }
267
268 /* if both ipv4 and ipv6 are off delete the interface isis container too
269 */
270 if (!strncmp(ip, "ipv6", strlen("ipv6"))) {
271 if (circuit && !circuit->ip_router)
272 nb_cli_enqueue_change(vty, "./frr-isisd:isis",
273 NB_OP_DELETE, NULL);
274 else
275 nb_cli_enqueue_change(vty,
276 "./frr-isisd:isis/ipv6-routing",
277 NB_OP_DELETE, NULL);
278 } else { /* no ipv4 */
279 if (circuit && !circuit->ipv6_router)
280 nb_cli_enqueue_change(vty, "./frr-isisd:isis",
281 NB_OP_DELETE, NULL);
282 else
283 nb_cli_enqueue_change(vty,
284 "./frr-isisd:isis/ipv4-routing",
285 NB_OP_DELETE, NULL);
286 }
287
288 return nb_cli_apply_changes(vty, NULL);
289}
290
291void cli_show_ip_isis_ipv4(struct vty *vty, struct lyd_node *dnode,
292 bool show_defaults)
293{
294 vty_out(vty, " ip router isis %s\n",
295 yang_dnode_get_string(dnode, "../area-tag"));
296}
297
298void cli_show_ip_isis_ipv6(struct vty *vty, struct lyd_node *dnode,
299 bool show_defaults)
300{
301 vty_out(vty, " ipv6 router isis %s\n",
302 yang_dnode_get_string(dnode, "../area-tag"));
303}
304
f084ea55
EDP
305/*
306 * XPath: /frr-isisd:isis/instance/area-address
307 */
308DEFPY(net, net_cmd, "[no] net WORD",
309 "Remove an existing Network Entity Title for this process\n"
310 "A Network Entity Title for this process (OSI only)\n"
311 "XX.XXXX. ... .XXX.XX Network entity title (NET)\n")
312{
313 nb_cli_enqueue_change(vty, "./area-address",
314 no ? NB_OP_DELETE : NB_OP_CREATE, net);
315
316 return nb_cli_apply_changes(vty, NULL);
317}
318
319void cli_show_isis_area_address(struct vty *vty, struct lyd_node *dnode,
320 bool show_defaults)
321{
322 vty_out(vty, " net %s\n", yang_dnode_get_string(dnode, NULL));
323}
324
e6bdae69
EDP
325/*
326 * XPath: /frr-isisd:isis/instance/is-type
327 */
328DEFPY(is_type, is_type_cmd, "is-type <level-1|level-1-2|level-2-only>$level",
329 "IS Level for this routing process (OSI only)\n"
330 "Act as a station router only\n"
331 "Act as both a station router and an area router\n"
332 "Act as an area router only\n")
333{
334 nb_cli_enqueue_change(vty, "./is-type", NB_OP_MODIFY,
335 strmatch(level, "level-2-only") ? "level-2"
336 : level);
337
338 return nb_cli_apply_changes(vty, NULL);
339}
340
341DEFPY(no_is_type, no_is_type_cmd,
342 "no is-type [<level-1|level-1-2|level-2-only>]",
343 NO_STR
344 "IS Level for this routing process (OSI only)\n"
345 "Act as a station router only\n"
346 "Act as both a station router and an area router\n"
347 "Act as an area router only\n")
348{
349 const char *value = NULL;
350 const struct lyd_node *dnode =
351 yang_dnode_get(running_config->dnode, VTY_CURR_XPATH);
352 struct isis_area *area = yang_dnode_get_entry(dnode, false);
353
354 /*
355 * Put the is-type back to defaults:
356 * - level-1-2 on first area
357 * - level-1 for the rest
358 */
359 if (area && listgetdata(listhead(isis->area_list)) == area)
360 value = "level-1-2";
361 else
362 value = NULL;
363 nb_cli_enqueue_change(vty, "./is-type", NB_OP_MODIFY, value);
364
365 return nb_cli_apply_changes(vty, NULL);
366}
367
368void cli_show_isis_is_type(struct vty *vty, struct lyd_node *dnode,
369 bool show_defaults)
370{
371 int is_type = yang_dnode_get_enum(dnode, NULL);
372
373 switch (is_type) {
374 case IS_LEVEL_1:
375 vty_out(vty, " is-type level-1\n");
376 break;
377 case IS_LEVEL_2:
378 vty_out(vty, " is-type level-2-only\n");
379 break;
380 case IS_LEVEL_1_AND_2:
381 vty_out(vty, " is-type level-1-2\n");
382 break;
383 }
384}
385
20bd27e2
EDP
386void isis_cli_init(void)
387{
aaf2fd21
EDP
388 install_element(CONFIG_NODE, &router_isis_cmd);
389 install_element(CONFIG_NODE, &no_router_isis_cmd);
390
391 install_element(INTERFACE_NODE, &ip_router_isis_cmd);
392 install_element(INTERFACE_NODE, &ip6_router_isis_cmd);
393 install_element(INTERFACE_NODE, &no_ip_router_isis_cmd);
f084ea55
EDP
394
395 install_element(ISIS_NODE, &net_cmd);
e6bdae69
EDP
396
397 install_element(ISIS_NODE, &is_type_cmd);
398 install_element(ISIS_NODE, &no_is_type_cmd);
20bd27e2
EDP
399}
400
401#endif /* ifndef FABRICD */