]> git.proxmox.com Git - mirror_frr.git/blame - isisd/isis_ldp_sync.c
pimd: When doing json output do not output non-json strings
[mirror_frr.git] / isisd / isis_ldp_sync.c
CommitLineData
acddc0ed 1// SPDX-License-Identifier: GPL-2.0-or-later
1cbf96a8 2/**
3 * isis_ldp_sync.c: ISIS LDP-IGP Sync handling routines
4 * Copyright (C) 2020 Volta Networks, Inc.
1cbf96a8 5 */
6
7#include <zebra.h>
8#include <string.h>
9
10#include "monotime.h"
11#include "memory.h"
24a58196 12#include "frrevent.h"
1cbf96a8 13#include "prefix.h"
14#include "table.h"
15#include "vty.h"
16#include "command.h"
17#include "plist.h"
18#include "log.h"
19#include "zclient.h"
20#include <lib/json.h>
21#include "defaults.h"
22#include "ldp_sync.h"
23
24#include "isisd/isis_constants.h"
25#include "isisd/isis_common.h"
26#include "isisd/isis_flags.h"
27#include "isisd/isis_circuit.h"
28#include "isisd/isis_lsp.h"
29#include "isisd/isis_pdu.h"
30#include "isisd/isis_network.h"
31#include "isisd/isis_misc.h"
32#include "isisd/isis_constants.h"
33#include "isisd/isis_adjacency.h"
34#include "isisd/isis_dr.h"
35#include "isisd/isisd.h"
36#include "isisd/isis_csm.h"
37#include "isisd/isis_events.h"
38#include "isisd/isis_te.h"
39#include "isisd/isis_mt.h"
40#include "isisd/isis_errors.h"
41#include "isisd/isis_tx_queue.h"
42#include "isisd/isis_nb.h"
43#include "isisd/isis_ldp_sync.h"
44
45extern struct zclient *zclient;
46
47/*
48 * LDP-SYNC msg between IGP and LDP
49 */
50int isis_ldp_sync_state_update(struct ldp_igp_sync_if_state state)
51{
52 struct interface *ifp;
53 struct isis_circuit *circuit = NULL;
54 struct isis_area *area;
1cbf96a8 55
56 /* lookup circuit */
57 ifp = if_lookup_by_index(state.ifindex, VRF_DEFAULT);
58 if (ifp == NULL)
59 return 0;
60
ec62fbaa
IR
61 circuit = ifp->info;
62 if (circuit == NULL)
63 return 0;
1cbf96a8 64
65 /* if isis is not enabled or LDP-SYNC is not configured ignore */
ec62fbaa
IR
66 area = circuit->area;
67 if (area == NULL
68 || !CHECK_FLAG(area->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE))
1cbf96a8 69 return 0;
70
71 /* received ldp-sync interface state from LDP */
11106e28 72 ils_debug("%s: rcvd %s from LDP if %s", __func__,
1cbf96a8 73 state.sync_start ? "sync-start" : "sync-complete", ifp->name);
74 if (state.sync_start)
75 isis_ldp_sync_if_start(circuit, false);
76 else
77 isis_ldp_sync_if_complete(circuit);
78
79 return 0;
80}
81
82int isis_ldp_sync_announce_update(struct ldp_igp_sync_announce announce)
83{
84 struct isis_area *area;
ec62fbaa 85 struct listnode *anode, *cnode;
1cbf96a8 86 struct isis_circuit *circuit;
87 struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT);
88
ec62fbaa
IR
89 /* if isis is not enabled ignore */
90 if (!isis)
1cbf96a8 91 return 0;
92
93 if (announce.proto != ZEBRA_ROUTE_LDP)
94 return 0;
95
11106e28 96 ils_debug("%s: rcvd announce from LDP", __func__);
1cbf96a8 97
98 /* LDP just started up:
99 * set cost to LSInfinity
100 * send request to LDP for LDP-SYNC state for each interface
1cbf96a8 101 */
ec62fbaa
IR
102 for (ALL_LIST_ELEMENTS_RO(isis->area_list, anode, area)) {
103 if (!CHECK_FLAG(area->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE))
104 continue;
105
106 for (ALL_LIST_ELEMENTS_RO(area->circuit_list, cnode, circuit))
1cbf96a8 107 isis_ldp_sync_if_start(circuit, true);
1cbf96a8 108 }
109
1cbf96a8 110 return 0;
111}
112
113void isis_ldp_sync_state_req_msg(struct isis_circuit *circuit)
114{
115 struct ldp_igp_sync_if_state_req request;
116 struct interface *ifp = circuit->interface;
117
11106e28 118 ils_debug("%s: send state request to LDP for %s", __func__, ifp->name);
1cbf96a8 119
f735c2e8 120 memset(&request, 0, sizeof(request));
1cbf96a8 121 strlcpy(request.name, ifp->name, sizeof(ifp->name));
122 request.proto = LDP_IGP_SYNC_IF_STATE_REQUEST;
123 request.ifindex = ifp->ifindex;
124
125 zclient_send_opaque(zclient, LDP_IGP_SYNC_IF_STATE_REQUEST,
126 (uint8_t *)&request, sizeof(request));
127}
128
129/*
130 * LDP-SYNC general interface routines
131 */
1cbf96a8 132void isis_ldp_sync_if_start(struct isis_circuit *circuit,
133 bool send_state_req)
134{
135 struct ldp_sync_info *ldp_sync_info;
136
137 ldp_sync_info = circuit->ldp_sync_info;
138
139 /* Start LDP-SYNC on this interface:
140 * set cost of interface to LSInfinity so traffic will use different
141 * interface until LDP has learned all labels from peer
142 * start holddown timer if configured
143 * send msg to LDP to get LDP-SYNC state
144 */
145 if (ldp_sync_info &&
146 ldp_sync_info->enabled == LDP_IGP_SYNC_ENABLED &&
147 ldp_sync_info->state != LDP_IGP_SYNC_STATE_NOT_REQUIRED) {
11106e28 148 ils_debug("%s: start on if %s state: %s", __func__,
1cbf96a8 149 circuit->interface->name, "Holding down until Sync");
150 ldp_sync_info->state = LDP_IGP_SYNC_STATE_REQUIRED_NOT_UP;
151 isis_ldp_sync_set_if_metric(circuit, true);
152 isis_ldp_sync_holddown_timer_add(circuit);
153
154 if (send_state_req)
155 isis_ldp_sync_state_req_msg(circuit);
156 }
157}
158
159void isis_ldp_sync_if_complete(struct isis_circuit *circuit)
160{
161 struct ldp_sync_info *ldp_sync_info;
162
163 ldp_sync_info = circuit->ldp_sync_info;
164
165 /* received sync-complete from LDP:
166 * set state to up
167 * stop timer
168 * restore interface cost to original value
169 */
170 if (ldp_sync_info && ldp_sync_info->enabled == LDP_IGP_SYNC_ENABLED) {
171 if (ldp_sync_info->state == LDP_IGP_SYNC_STATE_REQUIRED_NOT_UP)
172 ldp_sync_info->state = LDP_IGP_SYNC_STATE_REQUIRED_UP;
50478845 173
e16d030c 174 EVENT_OFF(ldp_sync_info->t_holddown);
50478845 175
1cbf96a8 176 isis_ldp_sync_set_if_metric(circuit, true);
177 }
178}
179
180void isis_ldp_sync_ldp_fail(struct isis_circuit *circuit)
181{
182 struct ldp_sync_info *ldp_sync_info;
183
184 ldp_sync_info = circuit->ldp_sync_info;
185
cb135cc9 186 /* LDP client close detected:
1cbf96a8 187 * stop holddown timer
188 * set cost of interface to LSInfinity so traffic will use different
189 * interface until LDP restarts and has learned all labels from peer
190 */
191 if (ldp_sync_info &&
192 ldp_sync_info->enabled == LDP_IGP_SYNC_ENABLED &&
193 ldp_sync_info->state != LDP_IGP_SYNC_STATE_NOT_REQUIRED) {
e16d030c 194 EVENT_OFF(ldp_sync_info->t_holddown);
1cbf96a8 195 ldp_sync_info->state = LDP_IGP_SYNC_STATE_REQUIRED_NOT_UP;
196 isis_ldp_sync_set_if_metric(circuit, true);
197 }
198}
199
1cbf96a8 200static int isis_ldp_sync_adj_state_change(struct isis_adjacency *adj)
201{
202 struct isis_circuit *circuit = adj->circuit;
ec62fbaa
IR
203 struct ldp_sync_info *ldp_sync_info = circuit->ldp_sync_info;
204 struct isis_area *area = circuit->area;
1cbf96a8 205
ec62fbaa 206 if (!CHECK_FLAG(area->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE)
096f7609 207 || circuit->interface->vrf->vrf_id != VRF_DEFAULT
ec62fbaa 208 || if_is_loopback(circuit->interface))
1cbf96a8 209 return 0;
210
1cbf96a8 211 if (ldp_sync_info->enabled != LDP_IGP_SYNC_ENABLED)
212 return 0;
213
214 if (adj->adj_state == ISIS_ADJ_UP) {
215 if (circuit->circ_type == CIRCUIT_T_P2P ||
216 if_is_pointopoint(circuit->interface)) {
217 /* If LDP-SYNC is configure on interface then start */
218 ldp_sync_info->state =
219 LDP_IGP_SYNC_STATE_REQUIRED_NOT_UP;
220 isis_ldp_sync_if_start(circuit, true);
221 } else {
222 /* non ptop link so don't run ldp-sync */
223 ldp_sync_info->state = LDP_IGP_SYNC_STATE_NOT_REQUIRED;
224 isis_ldp_sync_set_if_metric(circuit, true);
225 }
226 } else {
227 /* If LDP-SYNC is configure on this interface then stop it */
228 if (circuit->circ_type == CIRCUIT_T_P2P ||
229 if_is_pointopoint(circuit->interface))
230 ldp_sync_info->state =
231 LDP_IGP_SYNC_STATE_REQUIRED_NOT_UP;
232 else
233 ldp_sync_info->state = LDP_IGP_SYNC_STATE_NOT_REQUIRED;
234
11106e28 235 ils_debug("%s: down on if %s", __func__,
236 circuit->interface->name);
1cbf96a8 237 ldp_sync_if_down(circuit->ldp_sync_info);
238 }
239
240 return 0;
241}
242
243bool isis_ldp_sync_if_metric_config(struct isis_circuit *circuit, int level,
244 int metric)
245{
246 struct ldp_sync_info *ldp_sync_info = circuit->ldp_sync_info;
ec62fbaa 247 struct isis_area *area = circuit->area;
1cbf96a8 248
249 /* configured interface metric has been changed:
250 * if LDP-IGP Sync is running and metric has been set to LSInfinity
251 * change saved value so when ldp-sync completes proper metric is
252 * restored
253 */
ec62fbaa
IR
254 if (area && CHECK_FLAG(area->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE)
255 && ldp_sync_info != NULL) {
1cbf96a8 256
257 if (CHECK_FLAG(ldp_sync_info->flags,
258 LDP_SYNC_FLAG_SET_METRIC)) {
259 ldp_sync_info->metric[level-1] = metric;
260 ldp_sync_info->metric[level-1] = metric;
261 return false;
262 }
263 }
264 return true;
265}
266
267void isis_ldp_sync_set_if_metric(struct isis_circuit *circuit, bool run_regen)
268{
269 struct ldp_sync_info *ldp_sync_info;
270
271 /* set interface metric:
272 * if LDP-IGP Sync is starting set metric so interface
273 * is used only as last resort
274 * else restore metric to original value
275 */
276 if (circuit->ldp_sync_info == NULL || circuit->area == NULL)
277 return;
278
279 ldp_sync_info = circuit->ldp_sync_info;
280 if (ldp_sync_if_is_enabled(ldp_sync_info)) {
281 /* if metric already set to LSInfinity just return */
282 if (CHECK_FLAG(ldp_sync_info->flags, LDP_SYNC_FLAG_SET_METRIC))
283 return;
284
285 SET_FLAG(ldp_sync_info->flags, LDP_SYNC_FLAG_SET_METRIC);
286 if (circuit->is_type & IS_LEVEL_1) {
287 if (circuit->area->newmetric) {
288 ldp_sync_info->metric[0] =
289 circuit->te_metric[0];
35f70ed3
RW
290 circuit->te_metric[0] =
291 ISIS_WIDE_METRIC_INFINITY;
1cbf96a8 292 } else {
293 ldp_sync_info->metric[0] = circuit->metric[0];
35f70ed3
RW
294 circuit->metric[0] =
295 ISIS_NARROW_METRIC_INFINITY;
1cbf96a8 296 }
297 }
298 if (circuit->is_type & IS_LEVEL_2) {
299 if (circuit->area->newmetric) {
300 ldp_sync_info->metric[1] =
301 circuit->te_metric[1];
35f70ed3
RW
302 circuit->te_metric[1] =
303 ISIS_WIDE_METRIC_INFINITY;
1cbf96a8 304 } else {
305 ldp_sync_info->metric[1] = circuit->metric[1];
35f70ed3
RW
306 circuit->metric[1] =
307 ISIS_NARROW_METRIC_INFINITY;
1cbf96a8 308 }
309 }
310 } else {
311 /* if metric already restored just return */
312 if (!CHECK_FLAG(ldp_sync_info->flags, LDP_SYNC_FLAG_SET_METRIC))
313 return;
314
315 UNSET_FLAG(ldp_sync_info->flags, LDP_SYNC_FLAG_SET_METRIC);
316 if (circuit->is_type & IS_LEVEL_1) {
317 circuit->te_metric[0] = ldp_sync_info->metric[0];
318 circuit->metric[0] = ldp_sync_info->metric[0];
319 }
320 if (circuit->is_type & IS_LEVEL_2) {
321 circuit->te_metric[1] = ldp_sync_info->metric[1];
322 circuit->metric[1] = ldp_sync_info->metric[1];
323 }
324 }
325
326 if (run_regen)
327 lsp_regenerate_schedule(circuit->area, circuit->is_type, 0);
328}
329
330
331/*
332 * LDP-SYNC holddown timer routines
333 */
e6685141 334static void isis_ldp_sync_holddown_timer(struct event *thread)
1cbf96a8 335{
336 struct isis_circuit *circuit;
337 struct ldp_sync_info *ldp_sync_info;
338
339 /* holddown timer expired:
340 * didn't receive msg from LDP indicating sync-complete
341 * restore interface cost to original value
342 */
e16d030c 343 circuit = EVENT_ARG(thread);
1cbf96a8 344 if (circuit->ldp_sync_info == NULL)
cc9f21da 345 return;
1cbf96a8 346
347 ldp_sync_info = circuit->ldp_sync_info;
348
349 ldp_sync_info->state = LDP_IGP_SYNC_STATE_REQUIRED_UP;
350 ldp_sync_info->t_holddown = NULL;
351
11106e28 352 ils_debug("%s: holddown timer expired for %s state:sync achieved",
353 __func__, circuit->interface->name);
1cbf96a8 354
355 isis_ldp_sync_set_if_metric(circuit, true);
1cbf96a8 356}
357
358void isis_ldp_sync_holddown_timer_add(struct isis_circuit *circuit)
359{
360 struct ldp_sync_info *ldp_sync_info;
361
362 ldp_sync_info = circuit->ldp_sync_info;
363
364 /* Start holddown timer:
365 * this timer is used to keep interface cost at LSInfinity
366 * once expires returns cost to original value
367 * if timer is already running or holddown time is off just return
368 */
369 if (ldp_sync_info->t_holddown ||
370 ldp_sync_info->holddown == LDP_IGP_SYNC_HOLDDOWN_DEFAULT)
371 return;
372
11106e28 373 ils_debug("%s: start holddown timer for %s time %d", __func__,
1cbf96a8 374 circuit->interface->name, ldp_sync_info->holddown);
375
907a2395
DS
376 event_add_timer(master, isis_ldp_sync_holddown_timer, circuit,
377 ldp_sync_info->holddown, &ldp_sync_info->t_holddown);
1cbf96a8 378}
379
cb135cc9
KS
380/*
381 * LDP-SYNC handle client close routine
382 */
383void isis_ldp_sync_handle_client_close(struct zapi_client_close_info *info)
384{
385 struct isis_area *area;
ec62fbaa 386 struct listnode *anode, *cnode;
cb135cc9 387 struct isis_circuit *circuit;
cb135cc9
KS
388 struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT);
389
ec62fbaa
IR
390 /* if isis is not enabled ignore */
391 if (!isis)
cb135cc9
KS
392 return;
393
394 /* Check if the LDP main client session closed */
395 if (info->proto != ZEBRA_ROUTE_LDP || info->session_id == 0)
396 return;
397
398 /* Handle the zebra notification that the LDP client session closed.
399 * set cost to LSInfinity
400 * send request to LDP for LDP-SYNC state for each interface
401 */
11106e28 402 zlog_err("%s: LDP down", __func__);
cb135cc9 403
ec62fbaa
IR
404 for (ALL_LIST_ELEMENTS_RO(isis->area_list, anode, area)) {
405 if (!CHECK_FLAG(area->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE))
406 continue;
407
408 for (ALL_LIST_ELEMENTS_RO(area->circuit_list, cnode, circuit))
c3783ac0 409 isis_ldp_sync_ldp_fail(circuit);
cb135cc9
KS
410 }
411}
412
1cbf96a8 413/*
414 * LDP-SYNC routes used by set commands.
415 */
416
ec62fbaa 417void isis_area_ldp_sync_enable(struct isis_area *area)
1cbf96a8 418{
ec62fbaa
IR
419 struct isis_circuit *circuit;
420 struct listnode *node;
421
422 if (!CHECK_FLAG(area->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE)) {
423 SET_FLAG(area->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE);
424
425 for (ALL_LIST_ELEMENTS_RO(area->circuit_list, node, circuit))
426 isis_if_ldp_sync_enable(circuit);
427 }
428}
429
430void isis_area_ldp_sync_disable(struct isis_area *area)
431{
432 struct isis_circuit *circuit;
433 struct listnode *node;
434
435 if (CHECK_FLAG(area->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE)) {
436 for (ALL_LIST_ELEMENTS_RO(area->circuit_list, node, circuit))
437 isis_if_ldp_sync_disable(circuit);
438
439 UNSET_FLAG(area->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE);
440
441 UNSET_FLAG(area->ldp_sync_cmd.flags, LDP_SYNC_FLAG_HOLDDOWN);
442 area->ldp_sync_cmd.holddown = LDP_IGP_SYNC_HOLDDOWN_DEFAULT;
443 }
444}
445
446void isis_area_ldp_sync_set_holddown(struct isis_area *area, uint16_t holddown)
447{
448 struct isis_circuit *circuit;
449 struct listnode *node;
450
451 if (holddown == LDP_IGP_SYNC_HOLDDOWN_DEFAULT)
452 UNSET_FLAG(area->ldp_sync_cmd.flags, LDP_SYNC_FLAG_HOLDDOWN);
453 else
454 SET_FLAG(area->ldp_sync_cmd.flags, LDP_SYNC_FLAG_HOLDDOWN);
455
456 area->ldp_sync_cmd.holddown = holddown;
457
458 for (ALL_LIST_ELEMENTS_RO(area->circuit_list, node, circuit))
459 isis_if_set_ldp_sync_holddown(circuit);
460}
461
462void isis_if_ldp_sync_enable(struct isis_circuit *circuit)
463{
464 struct ldp_sync_info *ldp_sync_info = circuit->ldp_sync_info;
465 struct isis_area *area = circuit->area;
1cbf96a8 466
467 /* called when setting LDP-SYNC at the global level:
bd4f51b1 468 * specified on interface overrides global config
1cbf96a8 469 * if ptop link send msg to LDP indicating ldp-sync enabled
bd4f51b1 470 */
ec62fbaa 471 if (if_is_loopback(circuit->interface))
1cbf96a8 472 return;
473
b11f166c
IR
474 if (circuit->interface->vrf->vrf_id != VRF_DEFAULT)
475 return;
476
11106e28 477 ils_debug("%s: enable if %s", __func__, circuit->interface->name);
1cbf96a8 478
ec62fbaa
IR
479 if (!CHECK_FLAG(area->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE))
480 return;
1cbf96a8 481
ec62fbaa
IR
482 /* config on interface, overrides global config. */
483 if (CHECK_FLAG(ldp_sync_info->flags, LDP_SYNC_FLAG_IF_CONFIG))
484 if (ldp_sync_info->enabled != LDP_IGP_SYNC_ENABLED)
485 return;
1cbf96a8 486
ec62fbaa
IR
487 if (!CHECK_FLAG(ldp_sync_info->flags, LDP_SYNC_FLAG_HOLDDOWN))
488 ldp_sync_info->holddown = area->ldp_sync_cmd.holddown;
489
490 if (circuit->circ_type == CIRCUIT_T_P2P
491 || if_is_pointopoint(circuit->interface)) {
492 ldp_sync_info->state = LDP_IGP_SYNC_STATE_REQUIRED_NOT_UP;
493 isis_ldp_sync_state_req_msg(circuit);
494 } else {
495 ldp_sync_info->state = LDP_IGP_SYNC_STATE_NOT_REQUIRED;
11106e28 496 ils_debug("%s: Sync only runs on P2P links %s", __func__,
ec62fbaa
IR
497 circuit->interface->name);
498 }
499}
500
501void isis_if_ldp_sync_disable(struct isis_circuit *circuit)
502{
503 struct ldp_sync_info *ldp_sync_info = circuit->ldp_sync_info;
504 struct isis_area *area = circuit->area;
505
506 /* Stop LDP-SYNC on this interface:
507 * if holddown timer is running stop it
508 * delete ldp instance on interface
509 * restore metric
510 */
511 if (if_is_loopback(circuit->interface))
512 return;
513
11106e28 514 ils_debug("%s: remove if %s", __func__, circuit->interface->name);
ec62fbaa
IR
515
516 if (!CHECK_FLAG(area->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE))
517 return;
518
e16d030c 519 EVENT_OFF(ldp_sync_info->t_holddown);
ec62fbaa
IR
520 ldp_sync_info->state = LDP_IGP_SYNC_STATE_NOT_REQUIRED;
521 isis_ldp_sync_set_if_metric(circuit, true);
1cbf96a8 522}
523
524void isis_if_set_ldp_sync_holddown(struct isis_circuit *circuit)
525{
ec62fbaa
IR
526 struct ldp_sync_info *ldp_sync_info = circuit->ldp_sync_info;
527 struct isis_area *area = circuit->area;
1cbf96a8 528
529 /* called when setting LDP-SYNC at the global level:
bd4f51b1 530 * specified on interface overrides global config.
1cbf96a8 531 */
ec62fbaa 532 if (if_is_loopback(circuit->interface))
1cbf96a8 533 return;
534
1cbf96a8 535 /* config on interface, overrides global config. */
536 if (CHECK_FLAG(ldp_sync_info->flags, LDP_SYNC_FLAG_HOLDDOWN))
537 return;
ec62fbaa
IR
538 if (CHECK_FLAG(area->ldp_sync_cmd.flags, LDP_SYNC_FLAG_HOLDDOWN))
539 ldp_sync_info->holddown = area->ldp_sync_cmd.holddown;
1cbf96a8 540 else
541 ldp_sync_info->holddown = LDP_IGP_SYNC_HOLDDOWN_DEFAULT;
542}
543
1cbf96a8 544/*
545 * LDP-SYNC routines used by show commands.
546 */
547
548static void isis_circuit_ldp_sync_print_vty(struct isis_circuit *circuit,
549 struct vty *vty)
550{
551 struct ldp_sync_info *ldp_sync_info;
552 const char *ldp_state;
553
554 if (circuit->ldp_sync_info == NULL ||
555 if_is_loopback(circuit->interface))
556 return;
557
558 ldp_sync_info = circuit->ldp_sync_info;
eb47c1be 559 vty_out(vty, "%-16s\n", circuit->interface->name);
560 if (circuit->state == C_STATE_CONF) {
561 vty_out(vty, " Interface down\n");
562 return;
563 }
564
1cbf96a8 565 vty_out(vty, " LDP-IGP Synchronization enabled: %s\n",
566 ldp_sync_info->enabled == LDP_IGP_SYNC_ENABLED
567 ? "yes"
568 : "no");
569 vty_out(vty, " holddown timer in seconds: %u\n",
570 ldp_sync_info->holddown);
571
572 switch (ldp_sync_info->state) {
573 case LDP_IGP_SYNC_STATE_REQUIRED_UP:
574 vty_out(vty, " State: Sync achieved\n");
575 break;
576 case LDP_IGP_SYNC_STATE_REQUIRED_NOT_UP:
577 if (ldp_sync_info->t_holddown != NULL) {
4f830a07
DS
578 struct timeval remain =
579 event_timer_remain(ldp_sync_info->t_holddown);
1cbf96a8 580 vty_out(vty,
581 " Holddown timer is running %lld.%03lld remaining\n",
582 (long long)remain.tv_sec,
583 (long long)remain.tv_usec/1000);
584
585 vty_out(vty, " State: Holding down until Sync\n");
586 } else
587 vty_out(vty, " State: Sync not achieved\n");
588 break;
589 case LDP_IGP_SYNC_STATE_NOT_REQUIRED:
590 default:
591 if ((circuit->circ_type != CIRCUIT_T_P2P &&
592 !if_is_pointopoint(circuit->interface)) &&
593 circuit->circ_type != CIRCUIT_T_UNKNOWN)
594 ldp_state = "Sync not required: non-p2p link";
595 else
596 ldp_state = "Sync not required";
597 vty_out(vty, " State: %s\n", ldp_state);
598 break;
599 }
600}
601
602DEFUN (show_isis_mpls_ldp_interface,
603 show_isis_mpls_ldp_interface_cmd,
604 "show " PROTO_NAME " mpls ldp-sync [interface <INTERFACE|all>]",
605 SHOW_STR
606 PROTO_HELP
607 MPLS_STR
608 "LDP-IGP Sync information\n"
31011d9c
IR
609 "Interface information\n"
610 "Interface name\n"
611 "All interfaces\n")
1cbf96a8 612{
613 char *ifname = NULL;
614 int idx_intf = 0;
615 struct listnode *anode, *cnode;
616 struct isis_area *area;
617 struct isis_circuit *circuit;
618 struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT);
eb47c1be 619 bool found = false;
1cbf96a8 620
621 if (!isis) {
622 vty_out(vty, "IS-IS Routing Process not enabled\n");
623 return CMD_SUCCESS;
624 }
625
1cbf96a8 626 if (argv_find(argv, argc, "INTERFACE", &idx_intf))
627 ifname = argv[idx_intf]->arg;
628
629 for (ALL_LIST_ELEMENTS_RO(isis->area_list, anode, area)) {
630 for (ALL_LIST_ELEMENTS_RO(area->circuit_list, cnode, circuit))
631 if (!ifname)
632 isis_circuit_ldp_sync_print_vty(circuit, vty);
eb47c1be 633 else if (strcmp(circuit->interface->name, ifname)
634 == 0) {
1cbf96a8 635 isis_circuit_ldp_sync_print_vty(circuit, vty);
eb47c1be 636 found = true;
637 }
1cbf96a8 638 }
639
eb47c1be 640 if (found == false && ifname)
641 vty_out(vty, "%-16s\n ISIS not enabled\n", ifname);
642
1cbf96a8 643 return CMD_SUCCESS;
644}
645
646void isis_ldp_sync_init(void)
647{
648
649 /* "show ip isis mpls ldp interface" commands. */
650 install_element(VIEW_NODE, &show_isis_mpls_ldp_interface_cmd);
651
652 /* register for adjacency state changes */
653 hook_register(isis_adj_state_change_hook,
654 isis_ldp_sync_adj_state_change);
655}