]>
Commit | Line | Data |
---|---|---|
1 | /* | |
2 | * IS-IS Rout(e)ing protocol - isis_te.c | |
3 | * | |
4 | * This is an implementation of RFC5305 & RFC 7810 | |
5 | * | |
6 | * Author: Olivier Dugeon <olivier.dugeon@orange.com> | |
7 | * | |
8 | * Copyright (C) 2014 - 2019 Orange Labs http://www.orange.com | |
9 | * | |
10 | * This file is part of GNU Zebra. | |
11 | * | |
12 | * GNU Zebra is free software; you can redistribute it and/or modify it | |
13 | * under the terms of the GNU General Public License as published by the | |
14 | * Free Software Foundation; either version 2, or (at your option) any | |
15 | * later version. | |
16 | * | |
17 | * GNU Zebra is distributed in the hope that it will be useful, but | |
18 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
20 | * General Public License for more details. | |
21 | * | |
22 | * You should have received a copy of the GNU General Public License along | |
23 | * with this program; see the file COPYING; if not, write to the Free Software | |
24 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
25 | */ | |
26 | ||
27 | #include <zebra.h> | |
28 | #include <math.h> | |
29 | ||
30 | #include "linklist.h" | |
31 | #include "thread.h" | |
32 | #include "vty.h" | |
33 | #include "stream.h" | |
34 | #include "memory.h" | |
35 | #include "log.h" | |
36 | #include "prefix.h" | |
37 | #include "command.h" | |
38 | #include "hash.h" | |
39 | #include "if.h" | |
40 | #include "vrf.h" | |
41 | #include "checksum.h" | |
42 | #include "md5.h" | |
43 | #include "sockunion.h" | |
44 | #include "network.h" | |
45 | #include "sbuf.h" | |
46 | ||
47 | #include "isisd/isis_constants.h" | |
48 | #include "isisd/isis_common.h" | |
49 | #include "isisd/isis_flags.h" | |
50 | #include "isisd/isis_circuit.h" | |
51 | #include "isisd/isis_adjacency.h" | |
52 | #include "isisd/isisd.h" | |
53 | #include "isisd/isis_lsp.h" | |
54 | #include "isisd/isis_pdu.h" | |
55 | #include "isisd/isis_dynhn.h" | |
56 | #include "isisd/isis_misc.h" | |
57 | #include "isisd/isis_csm.h" | |
58 | #include "isisd/isis_adjacency.h" | |
59 | #include "isisd/isis_spf.h" | |
60 | #include "isisd/isis_te.h" | |
61 | #include "isisd/isis_zebra.h" | |
62 | ||
63 | const char *mode2text[] = {"Disable", "Area", "AS", "Emulate"}; | |
64 | ||
65 | /*------------------------------------------------------------------------* | |
66 | * Followings are control functions for MPLS-TE parameters management. | |
67 | *------------------------------------------------------------------------*/ | |
68 | ||
69 | /* Main initialization / update function of the MPLS TE Circuit context */ | |
70 | /* Call when interface TE Link parameters are modified */ | |
71 | void isis_link_params_update(struct isis_circuit *circuit, | |
72 | struct interface *ifp) | |
73 | { | |
74 | int i; | |
75 | struct prefix_ipv4 *addr; | |
76 | struct prefix_ipv6 *addr6; | |
77 | struct isis_ext_subtlvs *ext; | |
78 | ||
79 | /* Check if TE is enable or not */ | |
80 | if (!circuit->area || !IS_MPLS_TE(circuit->area->mta)) | |
81 | return; | |
82 | ||
83 | /* Sanity Check */ | |
84 | if ((ifp == NULL) || (circuit->state != C_STATE_UP)) | |
85 | return; | |
86 | ||
87 | zlog_debug("TE(%s): Update circuit parameters for interface %s", | |
88 | circuit->area->area_tag, ifp->name); | |
89 | ||
90 | /* Check if MPLS TE Circuit context has not been already created */ | |
91 | if (circuit->ext == NULL) { | |
92 | circuit->ext = isis_alloc_ext_subtlvs(); | |
93 | zlog_debug(" |- Allocated new Ext-subTLVs for interface %s", | |
94 | ifp->name); | |
95 | } | |
96 | ||
97 | ext = circuit->ext; | |
98 | ||
99 | /* Fulfill Extended subTLVs from interface link parameters */ | |
100 | if (HAS_LINK_PARAMS(ifp)) { | |
101 | /* STD_TE metrics */ | |
102 | if (IS_PARAM_SET(ifp->link_params, LP_ADM_GRP)) { | |
103 | ext->adm_group = ifp->link_params->admin_grp; | |
104 | SET_SUBTLV(ext, EXT_ADM_GRP); | |
105 | } else | |
106 | UNSET_SUBTLV(ext, EXT_ADM_GRP); | |
107 | ||
108 | /* If known, register local IPv4 addr from ip_addr list */ | |
109 | if (circuit->ip_addrs != NULL | |
110 | && listcount(circuit->ip_addrs) != 0) { | |
111 | addr = (struct prefix_ipv4 *)listgetdata( | |
112 | (struct listnode *)listhead(circuit->ip_addrs)); | |
113 | IPV4_ADDR_COPY(&ext->local_addr, &addr->prefix); | |
114 | SET_SUBTLV(ext, EXT_LOCAL_ADDR); | |
115 | } else | |
116 | UNSET_SUBTLV(ext, EXT_LOCAL_ADDR); | |
117 | ||
118 | /* Same for Remote IPv4 address */ | |
119 | if (circuit->circ_type == CIRCUIT_T_P2P) { | |
120 | struct isis_adjacency *adj = circuit->u.p2p.neighbor; | |
121 | ||
122 | if (adj && adj->adj_state == ISIS_ADJ_UP | |
123 | && adj->ipv4_address_count) { | |
124 | IPV4_ADDR_COPY(&ext->neigh_addr, | |
125 | &adj->ipv4_addresses[0]); | |
126 | SET_SUBTLV(ext, EXT_NEIGH_ADDR); | |
127 | } | |
128 | } else | |
129 | UNSET_SUBTLV(ext, EXT_NEIGH_ADDR); | |
130 | ||
131 | /* If known, register local IPv6 addr from ip_addr list */ | |
132 | if (circuit->ipv6_non_link != NULL | |
133 | && listcount(circuit->ipv6_non_link) != 0) { | |
134 | addr6 = (struct prefix_ipv6 *)listgetdata( | |
135 | (struct listnode *)listhead( | |
136 | circuit->ipv6_non_link)); | |
137 | IPV6_ADDR_COPY(&ext->local_addr6, &addr6->prefix); | |
138 | SET_SUBTLV(ext, EXT_LOCAL_ADDR6); | |
139 | } else | |
140 | UNSET_SUBTLV(ext, EXT_LOCAL_ADDR6); | |
141 | ||
142 | /* Same for Remote IPv6 address */ | |
143 | if (circuit->circ_type == CIRCUIT_T_P2P) { | |
144 | struct isis_adjacency *adj = circuit->u.p2p.neighbor; | |
145 | ||
146 | if (adj && adj->adj_state == ISIS_ADJ_UP | |
147 | && adj->ipv6_address_count) { | |
148 | IPV6_ADDR_COPY(&ext->neigh_addr6, | |
149 | &adj->ipv6_addresses[0]); | |
150 | SET_SUBTLV(ext, EXT_NEIGH_ADDR6); | |
151 | } | |
152 | } else | |
153 | UNSET_SUBTLV(ext, EXT_NEIGH_ADDR6); | |
154 | ||
155 | if (IS_PARAM_SET(ifp->link_params, LP_MAX_BW)) { | |
156 | ext->max_bw = ifp->link_params->max_bw; | |
157 | SET_SUBTLV(ext, EXT_MAX_BW); | |
158 | } else | |
159 | UNSET_SUBTLV(ext, EXT_MAX_BW); | |
160 | ||
161 | if (IS_PARAM_SET(ifp->link_params, LP_MAX_RSV_BW)) { | |
162 | ext->max_rsv_bw = ifp->link_params->max_rsv_bw; | |
163 | SET_SUBTLV(ext, EXT_MAX_RSV_BW); | |
164 | } else | |
165 | UNSET_SUBTLV(ext, EXT_MAX_RSV_BW); | |
166 | ||
167 | if (IS_PARAM_SET(ifp->link_params, LP_UNRSV_BW)) { | |
168 | for (i = 0; i < MAX_CLASS_TYPE; i++) | |
169 | ext->unrsv_bw[i] = | |
170 | ifp->link_params->unrsv_bw[i]; | |
171 | SET_SUBTLV(ext, EXT_UNRSV_BW); | |
172 | } else | |
173 | UNSET_SUBTLV(ext, EXT_UNRSV_BW); | |
174 | ||
175 | if (IS_PARAM_SET(ifp->link_params, LP_TE_METRIC)) { | |
176 | ext->te_metric = ifp->link_params->te_metric; | |
177 | SET_SUBTLV(ext, EXT_TE_METRIC); | |
178 | } else | |
179 | UNSET_SUBTLV(ext, EXT_TE_METRIC); | |
180 | ||
181 | /* TE metric extensions */ | |
182 | if (IS_PARAM_SET(ifp->link_params, LP_DELAY)) { | |
183 | ext->delay = ifp->link_params->av_delay; | |
184 | SET_SUBTLV(ext, EXT_DELAY); | |
185 | } else | |
186 | UNSET_SUBTLV(ext, EXT_DELAY); | |
187 | ||
188 | if (IS_PARAM_SET(ifp->link_params, LP_MM_DELAY)) { | |
189 | ext->min_delay = ifp->link_params->min_delay; | |
190 | ext->max_delay = ifp->link_params->max_delay; | |
191 | SET_SUBTLV(ext, EXT_MM_DELAY); | |
192 | } else | |
193 | UNSET_SUBTLV(ext, EXT_MM_DELAY); | |
194 | ||
195 | if (IS_PARAM_SET(ifp->link_params, LP_DELAY_VAR)) { | |
196 | ext->delay_var = ifp->link_params->delay_var; | |
197 | SET_SUBTLV(ext, EXT_DELAY_VAR); | |
198 | } else | |
199 | UNSET_SUBTLV(ext, EXT_DELAY_VAR); | |
200 | ||
201 | if (IS_PARAM_SET(ifp->link_params, LP_PKT_LOSS)) { | |
202 | ext->pkt_loss = ifp->link_params->pkt_loss; | |
203 | SET_SUBTLV(ext, EXT_PKT_LOSS); | |
204 | } else | |
205 | UNSET_SUBTLV(ext, EXT_PKT_LOSS); | |
206 | ||
207 | if (IS_PARAM_SET(ifp->link_params, LP_RES_BW)) { | |
208 | ext->res_bw = ifp->link_params->res_bw; | |
209 | SET_SUBTLV(ext, EXT_RES_BW); | |
210 | } else | |
211 | UNSET_SUBTLV(ext, EXT_RES_BW); | |
212 | ||
213 | if (IS_PARAM_SET(ifp->link_params, LP_AVA_BW)) { | |
214 | ext->ava_bw = ifp->link_params->ava_bw; | |
215 | SET_SUBTLV(ext, EXT_AVA_BW); | |
216 | } else | |
217 | UNSET_SUBTLV(ext, EXT_AVA_BW); | |
218 | ||
219 | if (IS_PARAM_SET(ifp->link_params, LP_USE_BW)) { | |
220 | ext->use_bw = ifp->link_params->use_bw; | |
221 | SET_SUBTLV(ext, EXT_USE_BW); | |
222 | } else | |
223 | UNSET_SUBTLV(ext, EXT_USE_BW); | |
224 | ||
225 | /* INTER_AS */ | |
226 | if (IS_PARAM_SET(ifp->link_params, LP_RMT_AS)) { | |
227 | ext->remote_as = ifp->link_params->rmt_as; | |
228 | ext->remote_ip = ifp->link_params->rmt_ip; | |
229 | SET_SUBTLV(ext, EXT_RMT_AS); | |
230 | SET_SUBTLV(ext, EXT_RMT_IP); | |
231 | } else { | |
232 | /* reset inter-as TE params */ | |
233 | UNSET_SUBTLV(ext, EXT_RMT_AS); | |
234 | UNSET_SUBTLV(ext, EXT_RMT_IP); | |
235 | } | |
236 | zlog_debug(" |- New MPLS-TE link parameters status 0x%x", | |
237 | ext->status); | |
238 | } else { | |
239 | zlog_debug(" |- Reset Extended subTLVs status 0x%x", | |
240 | ext->status); | |
241 | /* Reset TE subTLVs keeping SR one's */ | |
242 | if (IS_SUBTLV(ext, EXT_ADJ_SID)) | |
243 | ext->status = EXT_ADJ_SID; | |
244 | else if (IS_SUBTLV(ext, EXT_LAN_ADJ_SID)) | |
245 | ext->status = EXT_LAN_ADJ_SID; | |
246 | else | |
247 | ext->status = 0; | |
248 | } | |
249 | ||
250 | return; | |
251 | } | |
252 | ||
253 | static int isis_link_update_adj_hook(struct isis_adjacency *adj) | |
254 | { | |
255 | ||
256 | struct isis_circuit *circuit = adj->circuit; | |
257 | ||
258 | /* Update MPLS TE Remote IP address parameter if possible */ | |
259 | if (!IS_MPLS_TE(circuit->area->mta) || !IS_EXT_TE(circuit->ext)) | |
260 | return 0; | |
261 | ||
262 | /* IPv4 first */ | |
263 | if (adj->ipv4_address_count > 0) { | |
264 | IPV4_ADDR_COPY(&circuit->ext->neigh_addr, | |
265 | &adj->ipv4_addresses[0]); | |
266 | SET_SUBTLV(circuit->ext, EXT_NEIGH_ADDR); | |
267 | } | |
268 | ||
269 | /* and IPv6 */ | |
270 | if (adj->ipv6_address_count > 0) { | |
271 | IPV6_ADDR_COPY(&circuit->ext->neigh_addr6, | |
272 | &adj->ipv6_addresses[0]); | |
273 | SET_SUBTLV(circuit->ext, EXT_NEIGH_ADDR6); | |
274 | } | |
275 | ||
276 | return 0; | |
277 | } | |
278 | ||
279 | int isis_mpls_te_update(struct interface *ifp) | |
280 | { | |
281 | struct isis_circuit *circuit; | |
282 | uint8_t rc = 1; | |
283 | ||
284 | /* Sanity Check */ | |
285 | if (ifp == NULL) | |
286 | return rc; | |
287 | ||
288 | /* Get circuit context from interface */ | |
289 | circuit = circuit_scan_by_ifp(ifp); | |
290 | if (circuit == NULL) | |
291 | return rc; | |
292 | ||
293 | /* Update TE TLVs ... */ | |
294 | isis_link_params_update(circuit, ifp); | |
295 | ||
296 | /* ... and LSP */ | |
297 | if (circuit->area && IS_MPLS_TE(circuit->area->mta)) | |
298 | lsp_regenerate_schedule(circuit->area, circuit->is_type, 0); | |
299 | ||
300 | rc = 0; | |
301 | return rc; | |
302 | } | |
303 | ||
304 | /* Followings are vty command functions */ | |
305 | #ifndef FABRICD | |
306 | ||
307 | DEFUN (show_isis_mpls_te_router, | |
308 | show_isis_mpls_te_router_cmd, | |
309 | "show " PROTO_NAME " mpls-te router", | |
310 | SHOW_STR | |
311 | PROTO_HELP | |
312 | MPLS_TE_STR | |
313 | "Router information\n") | |
314 | { | |
315 | ||
316 | struct listnode *anode; | |
317 | struct isis_area *area; | |
318 | ||
319 | if (!isis) { | |
320 | vty_out(vty, "IS-IS Routing Process not enabled\n"); | |
321 | return CMD_SUCCESS; | |
322 | } | |
323 | ||
324 | for (ALL_LIST_ELEMENTS_RO(isis->area_list, anode, area)) { | |
325 | ||
326 | if (!IS_MPLS_TE(area->mta)) | |
327 | continue; | |
328 | ||
329 | vty_out(vty, "Area %s:\n", area->area_tag); | |
330 | if (ntohs(area->mta->router_id.s_addr) != 0) | |
331 | vty_out(vty, " MPLS-TE Router-Address: %s\n", | |
332 | inet_ntoa(area->mta->router_id)); | |
333 | else | |
334 | vty_out(vty, " N/A\n"); | |
335 | } | |
336 | ||
337 | return CMD_SUCCESS; | |
338 | } | |
339 | ||
340 | static void show_ext_sub(struct vty *vty, char *name, | |
341 | struct isis_ext_subtlvs *ext) | |
342 | { | |
343 | struct sbuf buf; | |
344 | char ibuf[PREFIX2STR_BUFFER]; | |
345 | ||
346 | sbuf_init(&buf, NULL, 0); | |
347 | ||
348 | if (!ext || ext->status == EXT_DISABLE) | |
349 | return; | |
350 | ||
351 | vty_out(vty, "-- MPLS-TE link parameters for %s --\n", name); | |
352 | ||
353 | sbuf_reset(&buf); | |
354 | ||
355 | if (IS_SUBTLV(ext, EXT_ADM_GRP)) | |
356 | sbuf_push(&buf, 4, "Administrative Group: 0x%" PRIx32 "\n", | |
357 | ext->adm_group); | |
358 | if (IS_SUBTLV(ext, EXT_LLRI)) { | |
359 | sbuf_push(&buf, 4, "Link Local ID: %" PRIu32 "\n", | |
360 | ext->local_llri); | |
361 | sbuf_push(&buf, 4, "Link Remote ID: %" PRIu32 "\n", | |
362 | ext->remote_llri); | |
363 | } | |
364 | if (IS_SUBTLV(ext, EXT_LOCAL_ADDR)) | |
365 | sbuf_push(&buf, 4, "Local Interface IP Address(es): %s\n", | |
366 | inet_ntoa(ext->local_addr)); | |
367 | if (IS_SUBTLV(ext, EXT_NEIGH_ADDR)) | |
368 | sbuf_push(&buf, 4, "Remote Interface IP Address(es): %s\n", | |
369 | inet_ntoa(ext->neigh_addr)); | |
370 | if (IS_SUBTLV(ext, EXT_LOCAL_ADDR6)) | |
371 | sbuf_push(&buf, 4, "Local Interface IPv6 Address(es): %s\n", | |
372 | inet_ntop(AF_INET6, &ext->local_addr6, ibuf, | |
373 | PREFIX2STR_BUFFER)); | |
374 | if (IS_SUBTLV(ext, EXT_NEIGH_ADDR6)) | |
375 | sbuf_push(&buf, 4, "Remote Interface IPv6 Address(es): %s\n", | |
376 | inet_ntop(AF_INET6, &ext->local_addr6, ibuf, | |
377 | PREFIX2STR_BUFFER)); | |
378 | if (IS_SUBTLV(ext, EXT_MAX_BW)) | |
379 | sbuf_push(&buf, 4, "Maximum Bandwidth: %g (Bytes/sec)\n", | |
380 | ext->max_bw); | |
381 | if (IS_SUBTLV(ext, EXT_MAX_RSV_BW)) | |
382 | sbuf_push(&buf, 4, | |
383 | "Maximum Reservable Bandwidth: %g (Bytes/sec)\n", | |
384 | ext->max_rsv_bw); | |
385 | if (IS_SUBTLV(ext, EXT_UNRSV_BW)) { | |
386 | sbuf_push(&buf, 4, "Unreserved Bandwidth:\n"); | |
387 | for (int j = 0; j < MAX_CLASS_TYPE; j += 2) { | |
388 | sbuf_push(&buf, 4 + 2, | |
389 | "[%d]: %g (Bytes/sec),\t[%d]: %g (Bytes/sec)\n", | |
390 | j, ext->unrsv_bw[j], | |
391 | j + 1, ext->unrsv_bw[j + 1]); | |
392 | } | |
393 | } | |
394 | if (IS_SUBTLV(ext, EXT_TE_METRIC)) | |
395 | sbuf_push(&buf, 4, "Traffic Engineering Metric: %u\n", | |
396 | ext->te_metric); | |
397 | if (IS_SUBTLV(ext, EXT_RMT_AS)) | |
398 | sbuf_push(&buf, 4, | |
399 | "Inter-AS TE Remote AS number: %" PRIu32 "\n", | |
400 | ext->remote_as); | |
401 | if (IS_SUBTLV(ext, EXT_RMT_IP)) | |
402 | sbuf_push(&buf, 4, | |
403 | "Inter-AS TE Remote ASBR IP address: %s\n", | |
404 | inet_ntoa(ext->remote_ip)); | |
405 | if (IS_SUBTLV(ext, EXT_DELAY)) | |
406 | sbuf_push(&buf, 4, | |
407 | "%s Average Link Delay: %" PRIu32 " (micro-sec)\n", | |
408 | IS_ANORMAL(ext->delay) ? "Anomalous" : "Normal", | |
409 | ext->delay); | |
410 | if (IS_SUBTLV(ext, EXT_MM_DELAY)) { | |
411 | sbuf_push(&buf, 4, "%s Min/Max Link Delay: %" PRIu32 " / %" | |
412 | PRIu32 " (micro-sec)\n", | |
413 | IS_ANORMAL(ext->min_delay) ? "Anomalous" : "Normal", | |
414 | ext->min_delay & TE_EXT_MASK, | |
415 | ext->max_delay & TE_EXT_MASK); | |
416 | } | |
417 | if (IS_SUBTLV(ext, EXT_DELAY_VAR)) | |
418 | sbuf_push(&buf, 4, | |
419 | "Delay Variation: %" PRIu32 " (micro-sec)\n", | |
420 | ext->delay_var & TE_EXT_MASK); | |
421 | if (IS_SUBTLV(ext, EXT_PKT_LOSS)) | |
422 | sbuf_push(&buf, 4, "%s Link Packet Loss: %g (%%)\n", | |
423 | IS_ANORMAL(ext->pkt_loss) ? "Anomalous" : "Normal", | |
424 | (float)((ext->pkt_loss & TE_EXT_MASK) | |
425 | * LOSS_PRECISION)); | |
426 | if (IS_SUBTLV(ext, EXT_RES_BW)) | |
427 | sbuf_push(&buf, 4, | |
428 | "Unidirectional Residual Bandwidth: %g (Bytes/sec)\n", | |
429 | ext->res_bw); | |
430 | if (IS_SUBTLV(ext, EXT_AVA_BW)) | |
431 | sbuf_push(&buf, 4, | |
432 | "Unidirectional Available Bandwidth: %g (Bytes/sec)\n", | |
433 | ext->ava_bw); | |
434 | if (IS_SUBTLV(ext, EXT_USE_BW)) | |
435 | sbuf_push(&buf, 4, | |
436 | "Unidirectional Utilized Bandwidth: %g (Bytes/sec)\n", | |
437 | ext->use_bw); | |
438 | ||
439 | vty_multiline(vty, "", "%s", sbuf_buf(&buf)); | |
440 | vty_out(vty, "---------------\n\n"); | |
441 | ||
442 | sbuf_free(&buf); | |
443 | return; | |
444 | } | |
445 | ||
446 | DEFUN (show_isis_mpls_te_interface, | |
447 | show_isis_mpls_te_interface_cmd, | |
448 | "show " PROTO_NAME " mpls-te interface [INTERFACE]", | |
449 | SHOW_STR | |
450 | PROTO_HELP | |
451 | MPLS_TE_STR | |
452 | "Interface information\n" | |
453 | "Interface name\n") | |
454 | { | |
455 | struct listnode *anode, *cnode; | |
456 | struct isis_area *area; | |
457 | struct isis_circuit *circuit; | |
458 | struct interface *ifp; | |
459 | int idx_interface = 4; | |
460 | ||
461 | if (!isis) { | |
462 | vty_out(vty, "IS-IS Routing Process not enabled\n"); | |
463 | return CMD_SUCCESS; | |
464 | } | |
465 | ||
466 | if (argc == idx_interface) { | |
467 | /* Show All Interfaces. */ | |
468 | for (ALL_LIST_ELEMENTS_RO(isis->area_list, anode, area)) { | |
469 | ||
470 | if (!IS_MPLS_TE(area->mta)) | |
471 | continue; | |
472 | ||
473 | vty_out(vty, "Area %s:\n", area->area_tag); | |
474 | ||
475 | for (ALL_LIST_ELEMENTS_RO(area->circuit_list, cnode, | |
476 | circuit)) | |
477 | show_ext_sub(vty, circuit->interface->name, | |
478 | circuit->ext); | |
479 | } | |
480 | } else { | |
481 | /* Interface name is specified. */ | |
482 | ifp = if_lookup_by_name(argv[idx_interface]->arg, VRF_DEFAULT); | |
483 | if (ifp == NULL) | |
484 | vty_out(vty, "No such interface name\n"); | |
485 | else { | |
486 | circuit = circuit_scan_by_ifp(ifp); | |
487 | if (!circuit) | |
488 | vty_out(vty, | |
489 | "ISIS is not enabled on circuit %s\n", | |
490 | ifp->name); | |
491 | else | |
492 | show_ext_sub(vty, ifp->name, circuit->ext); | |
493 | } | |
494 | } | |
495 | ||
496 | return CMD_SUCCESS; | |
497 | } | |
498 | #endif | |
499 | ||
500 | /* Initialize MPLS_TE */ | |
501 | void isis_mpls_te_init(void) | |
502 | { | |
503 | ||
504 | /* Register Circuit and Adjacency hook */ | |
505 | hook_register(isis_if_new_hook, isis_mpls_te_update); | |
506 | hook_register(isis_adj_state_change_hook, isis_link_update_adj_hook); | |
507 | ||
508 | ||
509 | #ifndef FABRICD | |
510 | /* Register new VTY commands */ | |
511 | install_element(VIEW_NODE, &show_isis_mpls_te_router_cmd); | |
512 | install_element(VIEW_NODE, &show_isis_mpls_te_interface_cmd); | |
513 | #endif | |
514 | ||
515 | return; | |
516 | } |