]> git.proxmox.com Git - mirror_frr.git/blob - isisd/isis_cli.c
isisd: retrofit 'router isis' and 'ip router isis' cmds
[mirror_frr.git] / isisd / isis_cli.c
1 /*
2 * Copyright (C) 2001,2002 Sampo Saaristo
3 * Tampere University of Technology
4 * Institute of Communications Engineering
5 * Copyright (C) 2018 Volta Networks
6 * Emanuele Di Pascale
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the Free
10 * Software Foundation; either version 2 of the License, or (at your option)
11 * any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 * more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; see the file COPYING; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23 #include <zebra.h>
24
25 #include "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
46 /*
47 * XPath: /frr-isisd:isis/instance
48 */
49 DEFPY_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
75 DEFPY(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
113 void 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 */
127 DEFPY(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
187 DEFPY(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
247 DEFPY(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
291 void 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
298 void 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
305 void isis_cli_init(void)
306 {
307 install_element(CONFIG_NODE, &router_isis_cmd);
308 install_element(CONFIG_NODE, &no_router_isis_cmd);
309
310 install_element(INTERFACE_NODE, &ip_router_isis_cmd);
311 install_element(INTERFACE_NODE, &ip6_router_isis_cmd);
312 install_element(INTERFACE_NODE, &no_ip_router_isis_cmd);
313 }
314
315 #endif /* ifndef FABRICD */