]>
Commit | Line | Data |
---|---|---|
f8c06e2c OD |
1 | /* |
2 | * IS-IS Rout(e)ing protocol - isis_te.c | |
3 | * | |
68558b13 | 4 | * This is an implementation of RFC5305 & RFC 7810 |
f8c06e2c | 5 | * |
1b3f47d0 OD |
6 | * Author: Olivier Dugeon <olivier.dugeon@orange.com> |
7 | * | |
8 | * Copyright (C) 2014 - 2019 Orange Labs http://www.orange.com | |
f8c06e2c OD |
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 | * | |
896014f4 DL |
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 | |
f8c06e2c OD |
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" | |
af8ac8f9 | 45 | #include "sbuf.h" |
f8c06e2c | 46 | |
f8c06e2c OD |
47 | #include "isisd/isis_constants.h" |
48 | #include "isisd/isis_common.h" | |
49 | #include "isisd/isis_flags.h" | |
50 | #include "isisd/isis_circuit.h" | |
1b3f47d0 | 51 | #include "isisd/isis_adjacency.h" |
f8c06e2c | 52 | #include "isisd/isisd.h" |
f8c06e2c OD |
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" | |
1b3f47d0 | 61 | #include "isisd/isis_zebra.h" |
f8c06e2c | 62 | |
f8c06e2c OD |
63 | /*------------------------------------------------------------------------* |
64 | * Followings are control functions for MPLS-TE parameters management. | |
65 | *------------------------------------------------------------------------*/ | |
66 | ||
f8c06e2c OD |
67 | /* Main initialization / update function of the MPLS TE Circuit context */ |
68 | /* Call when interface TE Link parameters are modified */ | |
d62a17ae | 69 | void isis_link_params_update(struct isis_circuit *circuit, |
70 | struct interface *ifp) | |
f8c06e2c | 71 | { |
d62a17ae | 72 | int i; |
73 | struct prefix_ipv4 *addr; | |
1b3f47d0 OD |
74 | struct prefix_ipv6 *addr6; |
75 | struct isis_ext_subtlvs *ext; | |
76 | ||
77 | /* Check if TE is enable or not */ | |
78 | if (!circuit->area || !IS_MPLS_TE(circuit->area->mta)) | |
79 | return; | |
d62a17ae | 80 | |
81 | /* Sanity Check */ | |
b53c5f1a | 82 | if ((ifp == NULL) || (circuit->state != C_STATE_UP)) |
d62a17ae | 83 | return; |
84 | ||
1b3f47d0 OD |
85 | zlog_debug("TE(%s): Update circuit parameters for interface %s", |
86 | circuit->area->area_tag, ifp->name); | |
d62a17ae | 87 | |
88 | /* Check if MPLS TE Circuit context has not been already created */ | |
1b3f47d0 OD |
89 | if (circuit->ext == NULL) { |
90 | circuit->ext = isis_alloc_ext_subtlvs(); | |
91 | zlog_debug(" |- Allocated new Ext-subTLVs for interface %s", | |
92 | ifp->name); | |
93 | } | |
d62a17ae | 94 | |
1b3f47d0 | 95 | ext = circuit->ext; |
d62a17ae | 96 | |
1b3f47d0 | 97 | /* Fulfill Extended subTLVs from interface link parameters */ |
d62a17ae | 98 | if (HAS_LINK_PARAMS(ifp)) { |
d62a17ae | 99 | /* STD_TE metrics */ |
1b3f47d0 OD |
100 | if (IS_PARAM_SET(ifp->link_params, LP_ADM_GRP)) { |
101 | ext->adm_group = ifp->link_params->admin_grp; | |
102 | SET_SUBTLV(ext, EXT_ADM_GRP); | |
103 | } else | |
104 | UNSET_SUBTLV(ext, EXT_ADM_GRP); | |
105 | ||
106 | /* If known, register local IPv4 addr from ip_addr list */ | |
107 | if (circuit->ip_addrs != NULL | |
108 | && listcount(circuit->ip_addrs) != 0) { | |
109 | addr = (struct prefix_ipv4 *)listgetdata( | |
110 | (struct listnode *)listhead(circuit->ip_addrs)); | |
111 | IPV4_ADDR_COPY(&ext->local_addr, &addr->prefix); | |
112 | SET_SUBTLV(ext, EXT_LOCAL_ADDR); | |
113 | } else | |
114 | UNSET_SUBTLV(ext, EXT_LOCAL_ADDR); | |
115 | ||
116 | /* Same for Remote IPv4 address */ | |
117 | if (circuit->circ_type == CIRCUIT_T_P2P) { | |
d62a17ae | 118 | struct isis_adjacency *adj = circuit->u.p2p.neighbor; |
1b3f47d0 | 119 | |
44b89511 CF |
120 | if (adj && adj->adj_state == ISIS_ADJ_UP |
121 | && adj->ipv4_address_count) { | |
1b3f47d0 OD |
122 | IPV4_ADDR_COPY(&ext->neigh_addr, |
123 | &adj->ipv4_addresses[0]); | |
124 | SET_SUBTLV(ext, EXT_NEIGH_ADDR); | |
d62a17ae | 125 | } |
1b3f47d0 OD |
126 | } else |
127 | UNSET_SUBTLV(ext, EXT_NEIGH_ADDR); | |
128 | ||
129 | /* If known, register local IPv6 addr from ip_addr list */ | |
130 | if (circuit->ipv6_non_link != NULL | |
131 | && listcount(circuit->ipv6_non_link) != 0) { | |
132 | addr6 = (struct prefix_ipv6 *)listgetdata( | |
133 | (struct listnode *)listhead( | |
134 | circuit->ipv6_non_link)); | |
135 | IPV6_ADDR_COPY(&ext->local_addr6, &addr6->prefix); | |
136 | SET_SUBTLV(ext, EXT_LOCAL_ADDR6); | |
137 | } else | |
138 | UNSET_SUBTLV(ext, EXT_LOCAL_ADDR6); | |
139 | ||
140 | /* Same for Remote IPv6 address */ | |
141 | if (circuit->circ_type == CIRCUIT_T_P2P) { | |
142 | struct isis_adjacency *adj = circuit->u.p2p.neighbor; | |
d62a17ae | 143 | |
1b3f47d0 OD |
144 | if (adj && adj->adj_state == ISIS_ADJ_UP |
145 | && adj->ipv6_address_count) { | |
146 | IPV6_ADDR_COPY(&ext->neigh_addr6, | |
147 | &adj->ipv6_addresses[0]); | |
148 | SET_SUBTLV(ext, EXT_NEIGH_ADDR6); | |
149 | } | |
150 | } else | |
151 | UNSET_SUBTLV(ext, EXT_NEIGH_ADDR6); | |
152 | ||
153 | if (IS_PARAM_SET(ifp->link_params, LP_MAX_BW)) { | |
154 | ext->max_bw = ifp->link_params->max_bw; | |
155 | SET_SUBTLV(ext, EXT_MAX_BW); | |
156 | } else | |
157 | UNSET_SUBTLV(ext, EXT_MAX_BW); | |
158 | ||
159 | if (IS_PARAM_SET(ifp->link_params, LP_MAX_RSV_BW)) { | |
160 | ext->max_rsv_bw = ifp->link_params->max_rsv_bw; | |
161 | SET_SUBTLV(ext, EXT_MAX_RSV_BW); | |
162 | } else | |
163 | UNSET_SUBTLV(ext, EXT_MAX_RSV_BW); | |
164 | ||
165 | if (IS_PARAM_SET(ifp->link_params, LP_UNRSV_BW)) { | |
d62a17ae | 166 | for (i = 0; i < MAX_CLASS_TYPE; i++) |
1b3f47d0 OD |
167 | ext->unrsv_bw[i] = |
168 | ifp->link_params->unrsv_bw[i]; | |
169 | SET_SUBTLV(ext, EXT_UNRSV_BW); | |
170 | } else | |
171 | UNSET_SUBTLV(ext, EXT_UNRSV_BW); | |
172 | ||
173 | if (IS_PARAM_SET(ifp->link_params, LP_TE_METRIC)) { | |
174 | ext->te_metric = ifp->link_params->te_metric; | |
175 | SET_SUBTLV(ext, EXT_TE_METRIC); | |
176 | } else | |
177 | UNSET_SUBTLV(ext, EXT_TE_METRIC); | |
178 | ||
179 | /* TE metric extensions */ | |
180 | if (IS_PARAM_SET(ifp->link_params, LP_DELAY)) { | |
181 | ext->delay = ifp->link_params->av_delay; | |
182 | SET_SUBTLV(ext, EXT_DELAY); | |
183 | } else | |
184 | UNSET_SUBTLV(ext, EXT_DELAY); | |
185 | ||
186 | if (IS_PARAM_SET(ifp->link_params, LP_MM_DELAY)) { | |
187 | ext->min_delay = ifp->link_params->min_delay; | |
188 | ext->max_delay = ifp->link_params->max_delay; | |
189 | SET_SUBTLV(ext, EXT_MM_DELAY); | |
190 | } else | |
191 | UNSET_SUBTLV(ext, EXT_MM_DELAY); | |
192 | ||
193 | if (IS_PARAM_SET(ifp->link_params, LP_DELAY_VAR)) { | |
194 | ext->delay_var = ifp->link_params->delay_var; | |
195 | SET_SUBTLV(ext, EXT_DELAY_VAR); | |
196 | } else | |
197 | UNSET_SUBTLV(ext, EXT_DELAY_VAR); | |
198 | ||
199 | if (IS_PARAM_SET(ifp->link_params, LP_PKT_LOSS)) { | |
200 | ext->pkt_loss = ifp->link_params->pkt_loss; | |
201 | SET_SUBTLV(ext, EXT_PKT_LOSS); | |
202 | } else | |
203 | UNSET_SUBTLV(ext, EXT_PKT_LOSS); | |
204 | ||
205 | if (IS_PARAM_SET(ifp->link_params, LP_RES_BW)) { | |
206 | ext->res_bw = ifp->link_params->res_bw; | |
207 | SET_SUBTLV(ext, EXT_RES_BW); | |
208 | } else | |
209 | UNSET_SUBTLV(ext, EXT_RES_BW); | |
210 | ||
211 | if (IS_PARAM_SET(ifp->link_params, LP_AVA_BW)) { | |
212 | ext->ava_bw = ifp->link_params->ava_bw; | |
213 | SET_SUBTLV(ext, EXT_AVA_BW); | |
214 | } else | |
215 | UNSET_SUBTLV(ext, EXT_AVA_BW); | |
216 | ||
217 | if (IS_PARAM_SET(ifp->link_params, LP_USE_BW)) { | |
218 | ext->use_bw = ifp->link_params->use_bw; | |
219 | SET_SUBTLV(ext, EXT_USE_BW); | |
220 | } else | |
221 | UNSET_SUBTLV(ext, EXT_USE_BW); | |
d62a17ae | 222 | |
1b3f47d0 OD |
223 | /* INTER_AS */ |
224 | if (IS_PARAM_SET(ifp->link_params, LP_RMT_AS)) { | |
225 | ext->remote_as = ifp->link_params->rmt_as; | |
226 | ext->remote_ip = ifp->link_params->rmt_ip; | |
227 | SET_SUBTLV(ext, EXT_RMT_AS); | |
228 | SET_SUBTLV(ext, EXT_RMT_IP); | |
229 | } else { | |
230 | /* reset inter-as TE params */ | |
231 | UNSET_SUBTLV(ext, EXT_RMT_AS); | |
232 | UNSET_SUBTLV(ext, EXT_RMT_IP); | |
233 | } | |
234 | zlog_debug(" |- New MPLS-TE link parameters status 0x%x", | |
235 | ext->status); | |
236 | } else { | |
237 | zlog_debug(" |- Reset Extended subTLVs status 0x%x", | |
238 | ext->status); | |
239 | /* Reset TE subTLVs keeping SR one's */ | |
240 | if (IS_SUBTLV(ext, EXT_ADJ_SID)) | |
241 | ext->status = EXT_ADJ_SID; | |
242 | else if (IS_SUBTLV(ext, EXT_LAN_ADJ_SID)) | |
243 | ext->status = EXT_LAN_ADJ_SID; | |
d62a17ae | 244 | else |
1b3f47d0 OD |
245 | ext->status = 0; |
246 | } | |
d62a17ae | 247 | |
1b3f47d0 OD |
248 | return; |
249 | } | |
d62a17ae | 250 | |
1b3f47d0 OD |
251 | static int isis_link_update_adj_hook(struct isis_adjacency *adj) |
252 | { | |
d62a17ae | 253 | |
1b3f47d0 | 254 | struct isis_circuit *circuit = adj->circuit; |
d62a17ae | 255 | |
1b3f47d0 OD |
256 | /* Update MPLS TE Remote IP address parameter if possible */ |
257 | if (!IS_MPLS_TE(circuit->area->mta) || !IS_EXT_TE(circuit->ext)) | |
258 | return 0; | |
d62a17ae | 259 | |
1b3f47d0 OD |
260 | /* IPv4 first */ |
261 | if (adj->ipv4_address_count > 0) { | |
262 | IPV4_ADDR_COPY(&circuit->ext->neigh_addr, | |
263 | &adj->ipv4_addresses[0]); | |
264 | SET_SUBTLV(circuit->ext, EXT_NEIGH_ADDR); | |
265 | } | |
d62a17ae | 266 | |
1b3f47d0 OD |
267 | /* and IPv6 */ |
268 | if (adj->ipv6_address_count > 0) { | |
269 | IPV6_ADDR_COPY(&circuit->ext->neigh_addr6, | |
270 | &adj->ipv6_addresses[0]); | |
271 | SET_SUBTLV(circuit->ext, EXT_NEIGH_ADDR6); | |
272 | } | |
d62a17ae | 273 | |
1b3f47d0 | 274 | return 0; |
f8c06e2c OD |
275 | } |
276 | ||
1b3f47d0 | 277 | int isis_mpls_te_update(struct interface *ifp) |
f8c06e2c | 278 | { |
d62a17ae | 279 | struct isis_circuit *circuit; |
1b3f47d0 | 280 | uint8_t rc = 1; |
f8c06e2c | 281 | |
d62a17ae | 282 | /* Sanity Check */ |
283 | if (ifp == NULL) | |
1b3f47d0 | 284 | return rc; |
f8c06e2c | 285 | |
d62a17ae | 286 | /* Get circuit context from interface */ |
1b3f47d0 OD |
287 | circuit = circuit_scan_by_ifp(ifp); |
288 | if (circuit == NULL) | |
289 | return rc; | |
f8c06e2c | 290 | |
d62a17ae | 291 | /* Update TE TLVs ... */ |
292 | isis_link_params_update(circuit, ifp); | |
f8c06e2c | 293 | |
d62a17ae | 294 | /* ... and LSP */ |
2e2a8b91 | 295 | if (circuit->area && IS_MPLS_TE(circuit->area->mta)) |
d62a17ae | 296 | lsp_regenerate_schedule(circuit->area, circuit->is_type, 0); |
f8c06e2c | 297 | |
1b3f47d0 OD |
298 | rc = 0; |
299 | return rc; | |
f8c06e2c OD |
300 | } |
301 | ||
1b3f47d0 | 302 | /* Followings are vty command functions */ |
ef020087 CF |
303 | #ifndef FABRICD |
304 | ||
eab88f36 K |
305 | DEFUN(show_isis_mpls_te_router, |
306 | show_isis_mpls_te_router_cmd, | |
307 | "show " PROTO_NAME " [vrf <NAME|all>] mpls-te router", | |
308 | SHOW_STR | |
309 | PROTO_HELP | |
310 | VRF_CMD_HELP_STR "All VRFs\n" | |
311 | MPLS_TE_STR "Router information\n") | |
f8c06e2c | 312 | { |
d62a17ae | 313 | |
36944791 | 314 | struct listnode *anode, *inode; |
2e2a8b91 | 315 | struct isis_area *area; |
eab88f36 K |
316 | struct isis *isis = NULL; |
317 | const char *vrf_name = VRF_DEFAULT_NAME; | |
318 | bool all_vrf = false; | |
319 | int idx_vrf = 0; | |
2e2a8b91 | 320 | |
eab88f36 | 321 | if (!im) { |
2e2a8b91 OD |
322 | vty_out(vty, "IS-IS Routing Process not enabled\n"); |
323 | return CMD_SUCCESS; | |
324 | } | |
eab88f36 K |
325 | ISIS_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf); |
326 | if (vrf_name) { | |
327 | if (all_vrf) { | |
36944791 | 328 | for (ALL_LIST_ELEMENTS_RO(im->isis, inode, isis)) { |
eab88f36 K |
329 | for (ALL_LIST_ELEMENTS_RO(isis->area_list, |
330 | anode, area)) { | |
331 | if (!IS_MPLS_TE(area->mta)) | |
332 | continue; | |
333 | ||
334 | vty_out(vty, "Area %s:\n", | |
335 | area->area_tag); | |
336 | if (ntohs(area->mta->router_id.s_addr) | |
337 | != 0) | |
338 | vty_out(vty, | |
a854ea43 MS |
339 | " MPLS-TE Router-Address: %pI4\n", |
340 | &area->mta->router_id); | |
eab88f36 K |
341 | else |
342 | vty_out(vty, " N/A\n"); | |
343 | } | |
344 | } | |
345 | return 0; | |
346 | } | |
347 | isis = isis_lookup_by_vrfname(vrf_name); | |
348 | if (isis != NULL) { | |
349 | for (ALL_LIST_ELEMENTS_RO(isis->area_list, anode, | |
350 | area)) { | |
351 | ||
352 | if (!IS_MPLS_TE(area->mta)) | |
353 | continue; | |
354 | ||
355 | vty_out(vty, "Area %s:\n", area->area_tag); | |
356 | if (ntohs(area->mta->router_id.s_addr) != 0) | |
357 | vty_out(vty, | |
a854ea43 MS |
358 | " MPLS-TE Router-Address: %pI4\n", |
359 | &area->mta->router_id); | |
eab88f36 K |
360 | else |
361 | vty_out(vty, " N/A\n"); | |
362 | } | |
363 | } | |
2e2a8b91 | 364 | } |
d62a17ae | 365 | |
366 | return CMD_SUCCESS; | |
f8c06e2c OD |
367 | } |
368 | ||
1b3f47d0 OD |
369 | static void show_ext_sub(struct vty *vty, char *name, |
370 | struct isis_ext_subtlvs *ext) | |
f8c06e2c | 371 | { |
af8ac8f9 | 372 | struct sbuf buf; |
1b3f47d0 | 373 | char ibuf[PREFIX2STR_BUFFER]; |
af8ac8f9 CF |
374 | |
375 | sbuf_init(&buf, NULL, 0); | |
d62a17ae | 376 | |
1b3f47d0 | 377 | if (!ext || ext->status == EXT_DISABLE) |
2e2a8b91 | 378 | return; |
d62a17ae | 379 | |
2e2a8b91 | 380 | vty_out(vty, "-- MPLS-TE link parameters for %s --\n", name); |
d62a17ae | 381 | |
2e2a8b91 | 382 | sbuf_reset(&buf); |
231e94e3 | 383 | |
1b3f47d0 | 384 | if (IS_SUBTLV(ext, EXT_ADM_GRP)) |
6cde4b45 | 385 | sbuf_push(&buf, 4, "Administrative Group: 0x%x\n", |
1b3f47d0 OD |
386 | ext->adm_group); |
387 | if (IS_SUBTLV(ext, EXT_LLRI)) { | |
6cde4b45 | 388 | sbuf_push(&buf, 4, "Link Local ID: %u\n", |
1b3f47d0 | 389 | ext->local_llri); |
6cde4b45 | 390 | sbuf_push(&buf, 4, "Link Remote ID: %u\n", |
1b3f47d0 OD |
391 | ext->remote_llri); |
392 | } | |
393 | if (IS_SUBTLV(ext, EXT_LOCAL_ADDR)) | |
a854ea43 MS |
394 | sbuf_push(&buf, 4, "Local Interface IP Address(es): %pI4\n", |
395 | &ext->local_addr); | |
1b3f47d0 | 396 | if (IS_SUBTLV(ext, EXT_NEIGH_ADDR)) |
a854ea43 MS |
397 | sbuf_push(&buf, 4, "Remote Interface IP Address(es): %pI4\n", |
398 | &ext->neigh_addr); | |
1b3f47d0 OD |
399 | if (IS_SUBTLV(ext, EXT_LOCAL_ADDR6)) |
400 | sbuf_push(&buf, 4, "Local Interface IPv6 Address(es): %s\n", | |
401 | inet_ntop(AF_INET6, &ext->local_addr6, ibuf, | |
402 | PREFIX2STR_BUFFER)); | |
403 | if (IS_SUBTLV(ext, EXT_NEIGH_ADDR6)) | |
404 | sbuf_push(&buf, 4, "Remote Interface IPv6 Address(es): %s\n", | |
405 | inet_ntop(AF_INET6, &ext->local_addr6, ibuf, | |
406 | PREFIX2STR_BUFFER)); | |
407 | if (IS_SUBTLV(ext, EXT_MAX_BW)) | |
408 | sbuf_push(&buf, 4, "Maximum Bandwidth: %g (Bytes/sec)\n", | |
409 | ext->max_bw); | |
410 | if (IS_SUBTLV(ext, EXT_MAX_RSV_BW)) | |
411 | sbuf_push(&buf, 4, | |
412 | "Maximum Reservable Bandwidth: %g (Bytes/sec)\n", | |
413 | ext->max_rsv_bw); | |
414 | if (IS_SUBTLV(ext, EXT_UNRSV_BW)) { | |
415 | sbuf_push(&buf, 4, "Unreserved Bandwidth:\n"); | |
416 | for (int j = 0; j < MAX_CLASS_TYPE; j += 2) { | |
417 | sbuf_push(&buf, 4 + 2, | |
418 | "[%d]: %g (Bytes/sec),\t[%d]: %g (Bytes/sec)\n", | |
419 | j, ext->unrsv_bw[j], | |
420 | j + 1, ext->unrsv_bw[j + 1]); | |
421 | } | |
422 | } | |
423 | if (IS_SUBTLV(ext, EXT_TE_METRIC)) | |
424 | sbuf_push(&buf, 4, "Traffic Engineering Metric: %u\n", | |
425 | ext->te_metric); | |
426 | if (IS_SUBTLV(ext, EXT_RMT_AS)) | |
427 | sbuf_push(&buf, 4, | |
6cde4b45 | 428 | "Inter-AS TE Remote AS number: %u\n", |
1b3f47d0 OD |
429 | ext->remote_as); |
430 | if (IS_SUBTLV(ext, EXT_RMT_IP)) | |
431 | sbuf_push(&buf, 4, | |
a854ea43 MS |
432 | "Inter-AS TE Remote ASBR IP address: %pI4\n", |
433 | &ext->remote_ip); | |
1b3f47d0 OD |
434 | if (IS_SUBTLV(ext, EXT_DELAY)) |
435 | sbuf_push(&buf, 4, | |
6cde4b45 | 436 | "%s Average Link Delay: %u (micro-sec)\n", |
1b3f47d0 OD |
437 | IS_ANORMAL(ext->delay) ? "Anomalous" : "Normal", |
438 | ext->delay); | |
439 | if (IS_SUBTLV(ext, EXT_MM_DELAY)) { | |
6cde4b45 | 440 | sbuf_push(&buf, 4, "%s Min/Max Link Delay: %u / %u (micro-sec)\n", |
1b3f47d0 OD |
441 | IS_ANORMAL(ext->min_delay) ? "Anomalous" : "Normal", |
442 | ext->min_delay & TE_EXT_MASK, | |
443 | ext->max_delay & TE_EXT_MASK); | |
444 | } | |
445 | if (IS_SUBTLV(ext, EXT_DELAY_VAR)) | |
446 | sbuf_push(&buf, 4, | |
6cde4b45 | 447 | "Delay Variation: %u (micro-sec)\n", |
1b3f47d0 OD |
448 | ext->delay_var & TE_EXT_MASK); |
449 | if (IS_SUBTLV(ext, EXT_PKT_LOSS)) | |
450 | sbuf_push(&buf, 4, "%s Link Packet Loss: %g (%%)\n", | |
451 | IS_ANORMAL(ext->pkt_loss) ? "Anomalous" : "Normal", | |
452 | (float)((ext->pkt_loss & TE_EXT_MASK) | |
453 | * LOSS_PRECISION)); | |
454 | if (IS_SUBTLV(ext, EXT_RES_BW)) | |
455 | sbuf_push(&buf, 4, | |
456 | "Unidirectional Residual Bandwidth: %g (Bytes/sec)\n", | |
457 | ext->res_bw); | |
458 | if (IS_SUBTLV(ext, EXT_AVA_BW)) | |
459 | sbuf_push(&buf, 4, | |
460 | "Unidirectional Available Bandwidth: %g (Bytes/sec)\n", | |
461 | ext->ava_bw); | |
462 | if (IS_SUBTLV(ext, EXT_USE_BW)) | |
463 | sbuf_push(&buf, 4, | |
464 | "Unidirectional Utilized Bandwidth: %g (Bytes/sec)\n", | |
465 | ext->use_bw); | |
af8ac8f9 | 466 | |
2e2a8b91 OD |
467 | vty_multiline(vty, "", "%s", sbuf_buf(&buf)); |
468 | vty_out(vty, "---------------\n\n"); | |
d62a17ae | 469 | |
af8ac8f9 | 470 | sbuf_free(&buf); |
d62a17ae | 471 | return; |
f8c06e2c OD |
472 | } |
473 | ||
474 | DEFUN (show_isis_mpls_te_interface, | |
475 | show_isis_mpls_te_interface_cmd, | |
7c0cbd0e | 476 | "show " PROTO_NAME " mpls-te interface [INTERFACE]", |
f8c06e2c | 477 | SHOW_STR |
7c0cbd0e | 478 | PROTO_HELP |
f8c06e2c OD |
479 | MPLS_TE_STR |
480 | "Interface information\n" | |
481 | "Interface name\n") | |
482 | { | |
36944791 | 483 | struct listnode *anode, *cnode, *inode; |
2e2a8b91 OD |
484 | struct isis_area *area; |
485 | struct isis_circuit *circuit; | |
231e94e3 | 486 | struct interface *ifp; |
2e2a8b91 | 487 | int idx_interface = 4; |
eab88f36 | 488 | struct isis *isis = NULL; |
d62a17ae | 489 | |
eab88f36 | 490 | if (!im) { |
2e2a8b91 OD |
491 | vty_out(vty, "IS-IS Routing Process not enabled\n"); |
492 | return CMD_SUCCESS; | |
d62a17ae | 493 | } |
2e2a8b91 OD |
494 | |
495 | if (argc == idx_interface) { | |
496 | /* Show All Interfaces. */ | |
36944791 | 497 | for (ALL_LIST_ELEMENTS_RO(im->isis, inode, isis)) { |
eab88f36 K |
498 | for (ALL_LIST_ELEMENTS_RO(isis->area_list, anode, |
499 | area)) { | |
2e2a8b91 | 500 | |
eab88f36 K |
501 | if (!IS_MPLS_TE(area->mta)) |
502 | continue; | |
2e2a8b91 | 503 | |
eab88f36 | 504 | vty_out(vty, "Area %s:\n", area->area_tag); |
2e2a8b91 | 505 | |
eab88f36 K |
506 | for (ALL_LIST_ELEMENTS_RO(area->circuit_list, |
507 | cnode, circuit)) | |
508 | show_ext_sub(vty, | |
509 | circuit->interface->name, | |
510 | circuit->ext); | |
511 | } | |
2e2a8b91 OD |
512 | } |
513 | } else { | |
514 | /* Interface name is specified. */ | |
a36898e7 | 515 | ifp = if_lookup_by_name(argv[idx_interface]->arg, VRF_DEFAULT); |
2e2a8b91 | 516 | if (ifp == NULL) |
d62a17ae | 517 | vty_out(vty, "No such interface name\n"); |
2e2a8b91 OD |
518 | else { |
519 | circuit = circuit_scan_by_ifp(ifp); | |
520 | if (!circuit) | |
521 | vty_out(vty, | |
522 | "ISIS is not enabled on circuit %s\n", | |
523 | ifp->name); | |
524 | else | |
1b3f47d0 | 525 | show_ext_sub(vty, ifp->name, circuit->ext); |
2e2a8b91 | 526 | } |
d62a17ae | 527 | } |
528 | ||
529 | return CMD_SUCCESS; | |
f8c06e2c | 530 | } |
ef020087 | 531 | #endif |
f8c06e2c OD |
532 | |
533 | /* Initialize MPLS_TE */ | |
d62a17ae | 534 | void isis_mpls_te_init(void) |
f8c06e2c OD |
535 | { |
536 | ||
1b3f47d0 OD |
537 | /* Register Circuit and Adjacency hook */ |
538 | hook_register(isis_if_new_hook, isis_mpls_te_update); | |
539 | hook_register(isis_adj_state_change_hook, isis_link_update_adj_hook); | |
540 | ||
541 | ||
ef020087 | 542 | #ifndef FABRICD |
d62a17ae | 543 | /* Register new VTY commands */ |
544 | install_element(VIEW_NODE, &show_isis_mpls_te_router_cmd); | |
545 | install_element(VIEW_NODE, &show_isis_mpls_te_interface_cmd); | |
ef020087 | 546 | #endif |
f8c06e2c | 547 | |
d62a17ae | 548 | return; |
f8c06e2c | 549 | } |