]> git.proxmox.com Git - mirror_frr.git/blame - ospfd/ospf_ldp_sync.c
*: auto-convert to SPDX License IDs
[mirror_frr.git] / ospfd / ospf_ldp_sync.c
CommitLineData
acddc0ed 1// SPDX-License-Identifier: GPL-2.0-or-later
132a782e 2/*
3 * ospf_ldp_sync.c: OSPF LDP-IGP Sync handling routines
4 * Copyright (C) 2020 Volta Networks, Inc.
132a782e 5 */
6
7#include <zebra.h>
8#include <string.h>
9
10#include "monotime.h"
11#include "memory.h"
12#include "thread.h"
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 "ospfd.h"
25#include "ospf_interface.h"
26#include "ospf_vty.h"
27#include "ospf_ldp_sync.h"
28#include "ospf_dump.h"
29#include "ospf_ism.h"
30
31extern struct zclient *zclient;
32
33/*
34 * LDP-SYNC msg between IGP and LDP
35 */
36int ospf_ldp_sync_state_update(struct ldp_igp_sync_if_state state)
37{
38 struct ospf *ospf;
39 struct interface *ifp;
40
41 /* if ospf is not enabled or LDP-SYNC is not configured ignore */
42 ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
43 if (ospf == NULL ||
44 !CHECK_FLAG(ospf->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE))
45 return 0;
46
47 /* received ldp-sync interface state from LDP */
48 ifp = if_lookup_by_index(state.ifindex, VRF_DEFAULT);
49 if (ifp == NULL || if_is_loopback(ifp))
50 return 0;
51
f96ec6a6 52 ols_debug("%s: rcvd %s from LDP if %s", __func__,
53 state.sync_start ? "sync-start" : "sync-complete", ifp->name);
132a782e 54 if (state.sync_start)
55 ospf_ldp_sync_if_start(ifp, false);
56 else
57 ospf_ldp_sync_if_complete(ifp);
58
59 return 0;
60}
61
62int ospf_ldp_sync_announce_update(struct ldp_igp_sync_announce announce)
63{
64 struct ospf *ospf;
65 struct vrf *vrf;
66 struct interface *ifp;
67
68 /* if ospf is not enabled or LDP-SYNC is not configured ignore */
69 ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
70 if (ospf == NULL ||
71 !CHECK_FLAG(ospf->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE))
72 return 0;
73
74 if (announce.proto != ZEBRA_ROUTE_LDP)
75 return 0;
76
f96ec6a6 77 ols_debug("%s: rcvd announce from LDP", __func__);
132a782e 78
79 /* LDP just started up:
80 * set cost to LSInfinity
81 * send request to LDP for LDP-SYNC state for each interface
132a782e 82 */
83 vrf = vrf_lookup_by_id(ospf->vrf_id);
84 FOR_ALL_INTERFACES (vrf, ifp)
85 ospf_ldp_sync_if_start(ifp, true);
86
132a782e 87 return 0;
88}
89
90void ospf_ldp_sync_state_req_msg(struct interface *ifp)
91{
92 struct ldp_igp_sync_if_state_req request;
93
f96ec6a6 94 ols_debug("%s: send state request to LDP for %s", __func__, ifp->name);
132a782e 95
dd53fd08 96 memset(&request, 0, sizeof(request));
132a782e 97 strlcpy(request.name, ifp->name, sizeof(ifp->name));
98 request.proto = LDP_IGP_SYNC_IF_STATE_REQUEST;
99 request.ifindex = ifp->ifindex;
100
101 zclient_send_opaque(zclient, LDP_IGP_SYNC_IF_STATE_REQUEST,
102 (uint8_t *)&request, sizeof(request));
103}
104
105/*
106 * LDP-SYNC general interface routines
107 */
108void ospf_ldp_sync_if_init(struct ospf_interface *oi)
109{
110 struct ospf_if_params *params;
111 struct ldp_sync_info *ldp_sync_info;
112 struct interface *ifp = oi->ifp;
113
114 /* called when OSPF is configured on an interface:
115 * if LDP-IGP Sync is configured globally set state
116 * if ptop interface inform LDP LDP-SYNC is enabled
117 */
096f7609
IR
118 if (if_is_loopback(ifp) || (ifp->vrf->vrf_id != VRF_DEFAULT)
119 || !(CHECK_FLAG(oi->ospf->ldp_sync_cmd.flags,
120 LDP_SYNC_FLAG_ENABLE)))
132a782e 121 return;
122
f96ec6a6 123 ols_debug("%s: init if %s", __func__, ifp->name);
132a782e 124 params = IF_DEF_PARAMS(ifp);
125 if (params->ldp_sync_info == NULL)
126 params->ldp_sync_info = ldp_sync_info_create();
127
128 ldp_sync_info = params->ldp_sync_info;
129
bd4f51b1 130 /* specified on interface overrides global config. */
132a782e 131 if (!CHECK_FLAG(ldp_sync_info->flags, LDP_SYNC_FLAG_HOLDDOWN))
132 ldp_sync_info->holddown = oi->ospf->ldp_sync_cmd.holddown;
133
134 if (!CHECK_FLAG(ldp_sync_info->flags, LDP_SYNC_FLAG_IF_CONFIG))
135 ldp_sync_info->enabled = LDP_IGP_SYNC_ENABLED;
136
137 if ((params->type == OSPF_IFTYPE_POINTOPOINT ||
138 if_is_pointopoint(ifp)) &&
139 ldp_sync_info->enabled == LDP_IGP_SYNC_ENABLED)
140 ldp_sync_info->state = LDP_IGP_SYNC_STATE_REQUIRED_NOT_UP;
141}
142
143void ospf_ldp_sync_if_start(struct interface *ifp, bool send_state_req)
144{
145 struct ospf_if_params *params;
146 struct ldp_sync_info *ldp_sync_info;
147
148 if (if_is_loopback(ifp))
149 return;
150
151 params = IF_DEF_PARAMS(ifp);
152 ldp_sync_info = params->ldp_sync_info;
153
154 /* Start LDP-SYNC on this interface:
155 * set cost of interface to LSInfinity so traffic will use different
156 * interface until LDP has learned all labels from peer
157 * start holddown timer if configured
158 * send msg to LDP to get LDP-SYNC state
159 */
160 if (ldp_sync_info &&
161 ldp_sync_info->enabled == LDP_IGP_SYNC_ENABLED &&
162 ldp_sync_info->state != LDP_IGP_SYNC_STATE_NOT_REQUIRED) {
f96ec6a6 163 ols_debug("%s: start on if %s state: %s", __func__, ifp->name,
164 "Holding down until Sync");
132a782e 165 ldp_sync_info->state = LDP_IGP_SYNC_STATE_REQUIRED_NOT_UP;
166 ospf_if_recalculate_output_cost(ifp);
167 ospf_ldp_sync_holddown_timer_add(ifp);
168
169 if (send_state_req)
170 ospf_ldp_sync_state_req_msg(ifp);
171 }
172}
173
174void ospf_ldp_sync_if_complete(struct interface *ifp)
175{
176 struct ospf_if_params *params;
177 struct ldp_sync_info *ldp_sync_info;
178
179 if (if_is_loopback(ifp))
180 return;
181
182 params = IF_DEF_PARAMS(ifp);
183 ldp_sync_info = params->ldp_sync_info;
184
185 /* received sync-complete from LDP:
186 * set state to up
187 * stop timer
188 * restore interface cost to original value
189 */
190 if (ldp_sync_info && ldp_sync_info->enabled == LDP_IGP_SYNC_ENABLED) {
191 if (ldp_sync_info->state == LDP_IGP_SYNC_STATE_REQUIRED_NOT_UP)
192 ldp_sync_info->state = LDP_IGP_SYNC_STATE_REQUIRED_UP;
50478845 193 THREAD_OFF(ldp_sync_info->t_holddown);
132a782e 194 ospf_if_recalculate_output_cost(ifp);
195 }
196}
197
cb135cc9
KS
198void ospf_ldp_sync_handle_client_close(struct zapi_client_close_info *info)
199{
200 struct ospf *ospf;
201 struct vrf *vrf;
202 struct interface *ifp;
203
204 /* if ospf is not enabled or LDP-SYNC is not configured ignore */
205 ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
206 if (ospf == NULL
207 || !CHECK_FLAG(ospf->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE))
208 return;
209
210 /* Check if the LDP main client session closed */
211 if (info->proto != ZEBRA_ROUTE_LDP || info->session_id == 0)
212 return;
213
214 /* Handle the zebra notification that the LDP client session closed.
215 * set cost to LSInfinity
216 * send request to LDP for LDP-SYNC state for each interface
217 */
f96ec6a6 218 zlog_err("%s: LDP down", __func__);
cb135cc9
KS
219
220 vrf = vrf_lookup_by_id(ospf->vrf_id);
221 FOR_ALL_INTERFACES (vrf, ifp)
c3783ac0 222 ospf_ldp_sync_ldp_fail(ifp);
cb135cc9
KS
223}
224
132a782e 225void ospf_ldp_sync_ldp_fail(struct interface *ifp)
226{
227 struct ospf_if_params *params;
228 struct ldp_sync_info *ldp_sync_info;
229
230 if (if_is_loopback(ifp))
231 return;
232
233 params = IF_DEF_PARAMS(ifp);
234 ldp_sync_info = params->ldp_sync_info;
235
cb135cc9 236 /* LDP client close detected:
132a782e 237 * stop holddown timer
238 * set cost of interface to LSInfinity so traffic will use different
239 * interface until LDP has learned all labels from peer
240 */
241 if (ldp_sync_info &&
242 ldp_sync_info->enabled == LDP_IGP_SYNC_ENABLED &&
243 ldp_sync_info->state != LDP_IGP_SYNC_STATE_NOT_REQUIRED) {
50478845 244 THREAD_OFF(ldp_sync_info->t_holddown);
132a782e 245 ldp_sync_info->state = LDP_IGP_SYNC_STATE_REQUIRED_NOT_UP;
246 ospf_if_recalculate_output_cost(ifp);
247 }
248}
249
250void ospf_ldp_sync_if_down(struct interface *ifp)
251{
252 struct ospf_if_params *params;
253 struct ldp_sync_info *ldp_sync_info;
254
255 if (if_is_loopback(ifp))
256 return;
257
258 params = IF_DEF_PARAMS(ifp);
259 ldp_sync_info = params->ldp_sync_info;
260
261 if (ldp_sync_if_down(ldp_sync_info) == false)
262 return;
263
f96ec6a6 264 ols_debug("%s: down on if %s", __func__, ifp->name);
132a782e 265
266 /* Interface down:
267 * can occur from a link down or changing config
268 * ospf network type change interface is brought down/up
269 */
270 switch (ldp_sync_info->state) {
271 case LDP_IGP_SYNC_STATE_REQUIRED_NOT_UP:
272 case LDP_IGP_SYNC_STATE_REQUIRED_UP:
273 if (params->type != OSPF_IFTYPE_POINTOPOINT &&
274 !if_is_pointopoint(ifp))
275 /* LDP-SYNC not able to run on non-ptop interface */
276 ldp_sync_info->state = LDP_IGP_SYNC_STATE_NOT_REQUIRED;
277 break;
278 case LDP_IGP_SYNC_STATE_NOT_REQUIRED:
279 if (params->type == OSPF_IFTYPE_POINTOPOINT ||
280 if_is_pointopoint(ifp))
281 /* LDP-SYNC is able to run on ptop interface */
282 ldp_sync_info->state =
283 LDP_IGP_SYNC_STATE_REQUIRED_NOT_UP;
284 break;
285 default:
286 break;
287 }
288}
289
290void ospf_ldp_sync_if_remove(struct interface *ifp, bool remove)
291{
292 struct ospf_if_params *params;
293 struct ldp_sync_info *ldp_sync_info;
294
295 params = IF_DEF_PARAMS(ifp);
296 if (params->ldp_sync_info == NULL)
297 return;
298
299 ldp_sync_info = params->ldp_sync_info;
300
301 /* Stop LDP-SYNC on this interface:
302 * if holddown timer is running stop it
303 * delete ldp instance on interface
304 * restore cost
305 */
f96ec6a6 306 ols_debug("%s: Removed from if %s", __func__, ifp->name);
50478845
MS
307
308 THREAD_OFF(ldp_sync_info->t_holddown);
309
132a782e 310 ldp_sync_info->state = LDP_IGP_SYNC_STATE_NOT_REQUIRED;
311 ospf_if_recalculate_output_cost(ifp);
312 if (!CHECK_FLAG(ldp_sync_info->flags, LDP_SYNC_FLAG_IF_CONFIG))
313 ldp_sync_info->enabled = LDP_IGP_SYNC_DEFAULT;
314 if (remove) {
8998807f 315 ldp_sync_info_free(&ldp_sync_info);
132a782e 316 params->ldp_sync_info = NULL;
317 }
318}
319
320static int ospf_ldp_sync_ism_change(struct ospf_interface *oi, int state,
321 int old_state)
322{
323 /* Terminal state or regression */
324 switch (state) {
325 case ISM_PointToPoint:
326 /* If LDP-SYNC is configure on interface then start */
327 ospf_ldp_sync_if_start(oi->ifp, true);
328 break;
329 case ISM_Down:
330 /* If LDP-SYNC is configure on this interface then stop it */
331 ospf_ldp_sync_if_down(oi->ifp);
332 break;
333 default:
334 break;
335 }
336 return 0;
337}
338
339/*
340 * LDP-SYNC holddown timer routines
341 */
cc9f21da 342static void ospf_ldp_sync_holddown_timer(struct thread *thread)
132a782e 343{
344 struct interface *ifp;
345 struct ospf_if_params *params;
346 struct ldp_sync_info *ldp_sync_info;
347
348 /* holddown timer expired:
349 * didn't receive msg from LDP indicating sync-complete
350 * restore interface cost to original value
351 */
352 ifp = THREAD_ARG(thread);
353 params = IF_DEF_PARAMS(ifp);
354 if (params->ldp_sync_info) {
355 ldp_sync_info = params->ldp_sync_info;
356
357 ldp_sync_info->state = LDP_IGP_SYNC_STATE_REQUIRED_UP;
132a782e 358
f96ec6a6 359 ols_debug("%s: holddown timer expired for %s state: %s",
360 __func__, ifp->name, "Sync achieved");
132a782e 361
362 ospf_if_recalculate_output_cost(ifp);
363 }
132a782e 364}
365
366void ospf_ldp_sync_holddown_timer_add(struct interface *ifp)
367{
368 struct ospf_if_params *params;
369 struct ldp_sync_info *ldp_sync_info;
370
371 params = IF_DEF_PARAMS(ifp);
372 ldp_sync_info = params->ldp_sync_info;
373
374 /* Start holddown timer:
375 * this timer is used to keep interface cost at LSInfinity
376 * once expires returns cost to original value
377 * if timer is already running or holddown time is off just return
378 */
379 if (ldp_sync_info->t_holddown ||
380 ldp_sync_info->holddown == LDP_IGP_SYNC_HOLDDOWN_DEFAULT)
381 return;
382
f96ec6a6 383 ols_debug("%s: start holddown timer for %s time %d", __func__,
132a782e 384 ifp->name, ldp_sync_info->holddown);
385
386 thread_add_timer(master, ospf_ldp_sync_holddown_timer,
387 ifp, ldp_sync_info->holddown,
388 &ldp_sync_info->t_holddown);
389}
390
132a782e 391/*
392 * LDP-SYNC exit routes.
393 */
394void ospf_ldp_sync_gbl_exit(struct ospf *ospf, bool remove)
395{
396 struct interface *ifp;
397 struct vrf *vrf;
398
399 /* ospf is being removed
132a782e 400 * stop any holddown timers
401 */
402 if (CHECK_FLAG(ospf->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE)) {
403 /* unregister with opaque client to recv LDP-IGP Sync msgs */
404 zclient_unregister_opaque(zclient,
405 LDP_IGP_SYNC_IF_STATE_UPDATE);
406 zclient_unregister_opaque(zclient,
407 LDP_IGP_SYNC_ANNOUNCE_UPDATE);
132a782e 408
409 /* disable LDP globally */
410 UNSET_FLAG(ospf->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE);
411 UNSET_FLAG(ospf->ldp_sync_cmd.flags, LDP_SYNC_FLAG_HOLDDOWN);
412 ospf->ldp_sync_cmd.holddown = LDP_IGP_SYNC_HOLDDOWN_DEFAULT;
50478845 413
132a782e 414 /* turn off LDP-IGP Sync on all OSPF interfaces */
415 vrf = vrf_lookup_by_id(ospf->vrf_id);
416 FOR_ALL_INTERFACES (vrf, ifp)
417 ospf_ldp_sync_if_remove(ifp, remove);
418 }
419}
420
421/*
422 * LDP-SYNC routes used by set commands.
423 */
424void ospf_if_set_ldp_sync_enable(struct ospf *ospf, struct interface *ifp)
425{
426 struct ospf_if_params *params;
427 struct ldp_sync_info *ldp_sync_info;
428
429 /* called when setting LDP-SYNC at the global level:
bd4f51b1 430 * specified on interface overrides global config
132a782e 431 * if ptop link send msg to LDP indicating ldp-sync enabled
432 */
433 if (if_is_loopback(ifp))
434 return;
435
436 params = IF_DEF_PARAMS(ifp);
437 if (params->ldp_sync_info == NULL)
438 params->ldp_sync_info = ldp_sync_info_create();
439 ldp_sync_info = params->ldp_sync_info;
440
441 /* config on interface, overrides global config. */
442 if (CHECK_FLAG(ldp_sync_info->flags, LDP_SYNC_FLAG_IF_CONFIG))
443 if (ldp_sync_info->enabled != LDP_IGP_SYNC_ENABLED)
444 return;
445
446 ldp_sync_info->enabled = LDP_IGP_SYNC_ENABLED;
447
f96ec6a6 448 ols_debug("%s: enable if %s", __func__, ifp->name);
132a782e 449
450 /* send message to LDP if ptop link */
451 if (params->type == OSPF_IFTYPE_POINTOPOINT ||
452 if_is_pointopoint(ifp)) {
453 ldp_sync_info->state = LDP_IGP_SYNC_STATE_REQUIRED_NOT_UP;
454 ospf_ldp_sync_state_req_msg(ifp);
455 } else {
456 ldp_sync_info->state = LDP_IGP_SYNC_STATE_NOT_REQUIRED;
f96ec6a6 457 zlog_debug("%s: Sync only runs on P2P links %s", __func__,
132a782e 458 ifp->name);
459 }
460}
461
462void ospf_if_set_ldp_sync_holddown(struct ospf *ospf, struct interface *ifp)
463{
464 struct ospf_if_params *params;
465 struct ldp_sync_info *ldp_sync_info;
466
467 /* called when setting LDP-SYNC at the global level:
bd4f51b1 468 * specified on interface overrides global config.
132a782e 469 */
470 if (if_is_loopback(ifp))
471 return;
472
473 params = IF_DEF_PARAMS(ifp);
474 if (params->ldp_sync_info == NULL)
475 params->ldp_sync_info = ldp_sync_info_create();
476 ldp_sync_info = params->ldp_sync_info;
477
478 /* config on interface, overrides global config. */
479 if (CHECK_FLAG(ldp_sync_info->flags, LDP_SYNC_FLAG_HOLDDOWN))
480 return;
481 if (CHECK_FLAG(ospf->ldp_sync_cmd.flags, LDP_SYNC_FLAG_HOLDDOWN))
482 ldp_sync_info->holddown = ospf->ldp_sync_cmd.holddown;
483 else
484 ldp_sync_info->holddown = LDP_IGP_SYNC_HOLDDOWN_DEFAULT;
485}
486
487/*
488 * LDP-SYNC routines used by show commands.
489 */
490
491void ospf_ldp_sync_show_info(struct vty *vty, struct ospf *ospf,
492 json_object *json_vrf, bool use_json)
493{
494
495 if (CHECK_FLAG(ospf->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE)) {
496 if (use_json) {
77a2f8e5
DA
497 json_object_boolean_true_add(json_vrf,
498 "mplsLdpIgpSyncEnabled");
77a2f8e5
DA
499 json_object_int_add(json_vrf, "mplsLdpIgpSyncHolddown",
500 ospf->ldp_sync_cmd.holddown);
132a782e 501 } else {
502 vty_out(vty, " MPLS LDP-IGP Sync is enabled\n");
503 if (ospf->ldp_sync_cmd.holddown == 0)
504 vty_out(vty,
505 " MPLS LDP-IGP Sync holddown timer is disabled\n");
506 else
507 vty_out(vty,
508 " MPLS LDP-IGP Sync holddown timer %d sec\n",
509 ospf->ldp_sync_cmd.holddown);
510 }
511 }
512}
513
514static void show_ip_ospf_mpls_ldp_interface_sub(struct vty *vty,
515 struct ospf_interface *oi,
516 struct interface *ifp,
517 json_object *json_interface_sub,
518 bool use_json)
519{
520 const char *ldp_state;
521 struct ospf_if_params *params;
522 char timebuf[OSPF_TIME_DUMP_SIZE];
523 struct ldp_sync_info *ldp_sync_info;
524
525 params = IF_DEF_PARAMS(oi->ifp);
526 if (params->ldp_sync_info == NULL)
527 return;
528
529 ldp_sync_info = params->ldp_sync_info;
530 if (use_json) {
531 if (ldp_sync_info->enabled == LDP_IGP_SYNC_ENABLED)
532 json_object_boolean_true_add(json_interface_sub,
533 "ldpIgpSyncEnabled");
534 else
535 json_object_boolean_false_add(json_interface_sub,
536 "ldpIgpSyncEnabled");
537
538 json_object_int_add(json_interface_sub, "holdDownTimeInSec",
539 ldp_sync_info->holddown);
540
541 } else {
542 vty_out(vty, "%-10s\n", ifp->name);
543 vty_out(vty, " LDP-IGP Synchronization enabled: %s\n",
544 ldp_sync_info->enabled == LDP_IGP_SYNC_ENABLED
545 ? "yes"
546 : "no");
547 vty_out(vty, " Holddown timer in seconds: %u\n",
548 ldp_sync_info->holddown);
549 }
550
551 switch (ldp_sync_info->state) {
552 case LDP_IGP_SYNC_STATE_REQUIRED_UP:
553 if (use_json)
554 json_object_string_add(json_interface_sub,
555 "ldpIgpSyncState",
556 "Sync achieved");
557 else
558 vty_out(vty, " State: Sync achieved\n");
559 break;
560 case LDP_IGP_SYNC_STATE_REQUIRED_NOT_UP:
561 if (ldp_sync_info->t_holddown != NULL) {
562 if (use_json) {
563 long time_store;
564
565 time_store = monotime_until(
566 &ldp_sync_info->t_holddown->u.sands,
567 NULL)
568 /1000LL;
569
570 json_object_int_add(json_interface_sub,
571 "ldpIgpSyncTimeRemainInMsec",
572 time_store);
573
574 json_object_string_add(json_interface_sub,
575 "ldpIgpSyncState",
576 "Holding down until Sync");
577 } else {
578 vty_out(vty,
579 " Holddown timer is running %s remaining\n",
580 ospf_timer_dump(
581 ldp_sync_info->t_holddown,
582 timebuf,
583 sizeof(timebuf)));
584
585 vty_out(vty,
586 " State: Holding down until Sync\n");
587 }
588 } else {
589 if (use_json)
590 json_object_string_add(json_interface_sub,
591 "ldpIgpSyncState",
592 "Sync not achieved");
593 else
594 vty_out(vty, " State: Sync not achieved\n");
595 }
596 break;
597 case LDP_IGP_SYNC_STATE_NOT_REQUIRED:
598 default:
599 if (IF_DEF_PARAMS(ifp)->type != OSPF_IFTYPE_POINTOPOINT &&
600 !if_is_pointopoint(ifp))
601 ldp_state = "Sync not required: non-p2p link";
602 else
603 ldp_state = "Sync not required";
604
605 if (use_json)
606 json_object_string_add(json_interface_sub,
607 "ldpIgpSyncState",
608 ldp_state);
609 else
610 vty_out(vty, " State: %s\n", ldp_state);
611 break;
612 }
613}
614
615static int show_ip_ospf_mpls_ldp_interface_common(struct vty *vty,
616 struct ospf *ospf,
617 char *intf_name,
618 json_object *json,
619 bool use_json)
620{
621 struct interface *ifp;
622 struct vrf *vrf = vrf_lookup_by_id(ospf->vrf_id);
623 json_object *json_interface_sub = NULL;
624
625 if (intf_name == NULL) {
626 /* Show All Interfaces.*/
627 FOR_ALL_INTERFACES (vrf, ifp) {
628 struct route_node *rn;
629 struct ospf_interface *oi;
630
9919bec7 631 if (ospf_oi_count(ifp) == 0 && !use_json) {
632 if (!if_is_up(ifp))
633 vty_out(vty, "%s\n Interface down\n",
634 ifp->name);
132a782e 635 continue;
9919bec7 636 }
132a782e 637 for (rn = route_top(IF_OIFS(ifp)); rn;
638 rn = route_next(rn)) {
639 oi = rn->info;
640
641 if (use_json) {
642 json_interface_sub =
643 json_object_new_object();
644 }
645 show_ip_ospf_mpls_ldp_interface_sub(
646 vty, oi, ifp, json_interface_sub,
647 use_json);
648
649 if (use_json) {
650 json_object_object_add(
651 json, ifp->name,
652 json_interface_sub);
653 }
654 }
655 }
656 } else {
657 /* Interface name is specified. */
658 ifp = if_lookup_by_name(intf_name, ospf->vrf_id);
659 if (ifp != NULL) {
660 struct route_node *rn;
661 struct ospf_interface *oi;
662
663 if (ospf_oi_count(ifp) == 0 && !use_json) {
9919bec7 664 if (if_is_up(ifp))
665 vty_out(vty, "%s\n OSPF not enabled\n",
666 ifp->name);
667 else
668 vty_out(vty, "%s\n Interface down\n",
669 ifp->name);
132a782e 670 return CMD_SUCCESS;
671 }
672 for (rn = route_top(IF_OIFS(ifp)); rn;
673 rn = route_next(rn)) {
674 oi = rn->info;
675
676 if (use_json)
677 json_interface_sub =
678 json_object_new_object();
679
680 show_ip_ospf_mpls_ldp_interface_sub(
681 vty, oi, ifp, json_interface_sub,
682 use_json);
683
684 if (use_json) {
685 json_object_object_add(
686 json, ifp->name,
687 json_interface_sub);
688 }
689 }
690 }
691 }
692 return CMD_SUCCESS;
693}
694
695/*
696 * Write the global LDP-SYNC configuration.
697 */
698void ospf_ldp_sync_write_config(struct vty *vty, struct ospf *ospf)
699{
700 if (CHECK_FLAG(ospf->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE))
701 vty_out(vty, " mpls ldp-sync\n");
702 if (CHECK_FLAG(ospf->ldp_sync_cmd.flags, LDP_SYNC_FLAG_HOLDDOWN))
703 vty_out(vty, " mpls ldp-sync holddown %u\n",
704 ospf->ldp_sync_cmd.holddown);
705}
706
707/*
708 * Write the interface LDP-SYNC configuration.
709 */
710void ospf_ldp_sync_if_write_config(struct vty *vty,
711 struct ospf_if_params *params)
712
713{
714 struct ldp_sync_info *ldp_sync_info;
715
716 ldp_sync_info = params->ldp_sync_info;
717 if (ldp_sync_info == NULL)
718 return;
719
720 if (CHECK_FLAG(ldp_sync_info->flags, LDP_SYNC_FLAG_IF_CONFIG)) {
721 if (ldp_sync_info->enabled == LDP_IGP_SYNC_ENABLED)
722 vty_out(vty, " ip ospf mpls ldp-sync\n");
723 else
724 vty_out(vty, " no ip ospf mpls ldp-sync\n");
725 }
726 if (CHECK_FLAG(ldp_sync_info->flags, LDP_SYNC_FLAG_HOLDDOWN))
727 vty_out(vty, " ip ospf mpls ldp-sync holddown %u\n",
728 ldp_sync_info->holddown);
729}
730
731/*
732 * LDP-SYNC commands.
733 */
132a782e 734#include "ospfd/ospf_ldp_sync_clippy.c"
132a782e 735
736DEFPY (ospf_mpls_ldp_sync,
737 ospf_mpls_ldp_sync_cmd,
738 "mpls ldp-sync",
739 "MPLS specific commands\n"
740 "Enable MPLS LDP-IGP Sync\n")
741{
742 VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
743 struct vrf *vrf = vrf_lookup_by_id(ospf->vrf_id);
744 struct interface *ifp;
745
746 if (ospf->vrf_id != VRF_DEFAULT) {
747 vty_out(vty, "ldp-sync only runs on DEFAULT VRF\n");
748 return CMD_ERR_NOTHING_TODO;
749 }
750
751 /* register with opaque client to recv LDP-IGP Sync msgs */
752 zclient_register_opaque(zclient, LDP_IGP_SYNC_IF_STATE_UPDATE);
753 zclient_register_opaque(zclient, LDP_IGP_SYNC_ANNOUNCE_UPDATE);
132a782e 754
755 if (!CHECK_FLAG(ospf->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE)) {
756 SET_FLAG(ospf->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE);
757 /* turn on LDP-IGP Sync on all ptop OSPF interfaces */
758 FOR_ALL_INTERFACES (vrf, ifp)
759 ospf_if_set_ldp_sync_enable(ospf, ifp);
760 }
761 return CMD_SUCCESS;
762}
763
764DEFPY (no_ospf_mpls_ldp_sync,
765 no_ospf_mpls_ldp_sync_cmd,
766 "no mpls ldp-sync",
767 NO_STR
768 "MPLS specific commands\n"
769 "Disable MPLS LDP-IGP Sync\n")
770{
771 VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
772 ospf_ldp_sync_gbl_exit(ospf, false);
773 return CMD_SUCCESS;
774}
775
776DEFPY (ospf_mpls_ldp_sync_holddown,
777 ospf_mpls_ldp_sync_holddown_cmd,
778 "mpls ldp-sync holddown (1-10000)",
779 "MPLS specific commands\n"
780 "Enable MPLS LDP-IGP Sync\n"
781 "Set holddown timer\n"
782 "seconds\n")
783{
784 VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
785 struct vrf *vrf = vrf_lookup_by_id(ospf->vrf_id);
786 struct interface *ifp;
787
788 if (ospf->vrf_id != VRF_DEFAULT) {
789 vty_out(vty, "ldp-sync only runs on DEFAULT VRF\n");
790 return CMD_ERR_NOTHING_TODO;
791 }
792
793 SET_FLAG(ospf->ldp_sync_cmd.flags, LDP_SYNC_FLAG_HOLDDOWN);
794 ospf->ldp_sync_cmd.holddown = holddown;
795 /* set holddown time on all OSPF interfaces */
796 FOR_ALL_INTERFACES (vrf, ifp)
797 ospf_if_set_ldp_sync_holddown(ospf, ifp);
798
799 return CMD_SUCCESS;
800}
801
802DEFPY (no_ospf_mpls_ldp_sync_holddown,
803 no_ospf_mpls_ldp_sync_holddown_cmd,
804 "no mpls ldp-sync holddown [<(1-10000)>]",
805 NO_STR
806 "MPLS specific commands\n"
807 "Disable MPLS LDP-IGP Sync\n"
31011d9c
IR
808 "holddown timer disable\n"
809 "Time in seconds\n")
132a782e 810{
811 VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
812 struct vrf *vrf = vrf_lookup_by_id(ospf->vrf_id);
813 struct interface *ifp;
814
815 if (CHECK_FLAG(ospf->ldp_sync_cmd.flags, LDP_SYNC_FLAG_HOLDDOWN)) {
816 UNSET_FLAG(ospf->ldp_sync_cmd.flags, LDP_SYNC_FLAG_HOLDDOWN);
817 ospf->ldp_sync_cmd.holddown = LDP_IGP_SYNC_HOLDDOWN_DEFAULT;
818 /* turn off holddown timer on all OSPF interfaces */
819 FOR_ALL_INTERFACES (vrf, ifp)
820 ospf_if_set_ldp_sync_holddown(ospf, ifp);
821 }
822 return CMD_SUCCESS;
823}
824
825
826DEFPY (mpls_ldp_sync,
827 mpls_ldp_sync_cmd,
828 "ip ospf mpls ldp-sync",
829 IP_STR
830 "OSPF interface commands\n"
831 MPLS_STR
132a782e 832 MPLS_LDP_SYNC_STR)
833{
834 VTY_DECLVAR_CONTEXT(interface, ifp);
835 struct ospf_if_params *params;
836 struct ldp_sync_info *ldp_sync_info;
837
838 if (if_is_loopback(ifp)) {
839 vty_out(vty, "ldp-sync does not run on loopback interface\n");
840 return CMD_ERR_NOTHING_TODO;
841 }
842
096f7609 843 if (ifp->vrf->vrf_id != VRF_DEFAULT) {
132a782e 844 vty_out(vty, "ldp-sync only runs on DEFAULT VRF\n");
845 return CMD_ERR_NOTHING_TODO;
846 }
847
848 params = IF_DEF_PARAMS(ifp);
849 if (params->ldp_sync_info == NULL)
850 params->ldp_sync_info = ldp_sync_info_create();
851
852 ldp_sync_info = params->ldp_sync_info;
853
854 SET_FLAG(ldp_sync_info->flags, LDP_SYNC_FLAG_IF_CONFIG);
855 ldp_sync_info->enabled = LDP_IGP_SYNC_ENABLED;
856 if (params->type == OSPF_IFTYPE_POINTOPOINT || if_is_pointopoint(ifp)) {
857 ldp_sync_info->state = LDP_IGP_SYNC_STATE_REQUIRED_NOT_UP;
858 ospf_ldp_sync_state_req_msg(ifp);
859 } else {
860 zlog_debug("ldp_sync: only runs on P2P links %s", ifp->name);
861 ldp_sync_info->state = LDP_IGP_SYNC_STATE_NOT_REQUIRED;
862 }
863 return CMD_SUCCESS;
864}
865
866DEFPY (no_mpls_ldp_sync,
867 no_mpls_ldp_sync_cmd,
868 "no ip ospf mpls ldp-sync",
869 NO_STR
870 IP_STR
871 "OSPF interface commands\n"
872 MPLS_STR
873 NO_MPLS_LDP_SYNC_STR)
874{
875 VTY_DECLVAR_CONTEXT(interface, ifp);
876 struct ospf_if_params *params;
877 struct ldp_sync_info *ldp_sync_info;
878
879 if (if_is_loopback(ifp)) {
880 vty_out(vty, "ldp-sync: does not run on loopback interface\n");
881 return CMD_ERR_NOTHING_TODO;
882 }
883
096f7609 884 if (ifp->vrf->vrf_id != VRF_DEFAULT) {
132a782e 885 vty_out(vty, "ldp-sync only runs on DEFAULT VRF\n");
886 return CMD_ERR_NOTHING_TODO;
887 }
888
889 params = IF_DEF_PARAMS(ifp);
890 if (params->ldp_sync_info == NULL)
891 params->ldp_sync_info = ldp_sync_info_create();
892
893 ldp_sync_info = params->ldp_sync_info;
894
895 /* disable LDP-SYNC on an interface
896 * stop holddown timer if running
897 * restore ospf cost
898 */
899 SET_FLAG(ldp_sync_info->flags, LDP_SYNC_FLAG_IF_CONFIG);
900 ldp_sync_info->enabled = LDP_IGP_SYNC_DEFAULT;
901 ldp_sync_info->state = LDP_IGP_SYNC_STATE_NOT_REQUIRED;
50478845 902 THREAD_OFF(ldp_sync_info->t_holddown);
132a782e 903 ospf_if_recalculate_output_cost(ifp);
904
905 return CMD_SUCCESS;
906}
907
908DEFPY (mpls_ldp_sync_holddown,
909 mpls_ldp_sync_holddown_cmd,
910 "ip ospf mpls ldp-sync holddown (0-10000)",
911 IP_STR
912 "OSPF interface commands\n"
913 MPLS_STR
914 MPLS_LDP_SYNC_STR
915 "Time to wait for LDP-SYNC to occur before restoring interface cost\n"
916 "Time in seconds\n")
917{
918 VTY_DECLVAR_CONTEXT(interface, ifp);
919 struct ospf_if_params *params;
920 struct ldp_sync_info *ldp_sync_info;
921
922 if (if_is_loopback(ifp)) {
923 vty_out(vty, "ldp-sync: does not run on loopback interface\n");
924 return CMD_ERR_NOTHING_TODO;
925 }
926
096f7609 927 if (ifp->vrf->vrf_id != VRF_DEFAULT) {
132a782e 928 vty_out(vty, "ldp-sync only runs on DEFAULT VRF\n");
929 return CMD_ERR_NOTHING_TODO;
930 }
931
932 params = IF_DEF_PARAMS(ifp);
933 if (params->ldp_sync_info == NULL)
934 params->ldp_sync_info = ldp_sync_info_create();
935
936 ldp_sync_info = params->ldp_sync_info;
937
938 SET_FLAG(ldp_sync_info->flags, LDP_SYNC_FLAG_HOLDDOWN);
939 ldp_sync_info->holddown = holddown;
940
941 return CMD_SUCCESS;
942}
943
944DEFPY (no_mpls_ldp_sync_holddown,
945 no_mpls_ldp_sync_holddown_cmd,
946 "no ip ospf mpls ldp-sync holddown [<(1-10000)>]",
947 NO_STR
948 IP_STR
949 "OSPF interface commands\n"
950 MPLS_STR
951 NO_MPLS_LDP_SYNC_STR
31011d9c
IR
952 NO_MPLS_LDP_SYNC_HOLDDOWN_STR
953 "Time in seconds\n")
132a782e 954{
955 VTY_DECLVAR_CONTEXT(interface, ifp);
956 struct ospf_if_params *params;
957 struct ldp_sync_info *ldp_sync_info;
958 struct ospf *ospf;
959
960 if (if_is_loopback(ifp)) {
961 vty_out(vty, "ldp-sync: does not run on loopback interface\n");
962 return CMD_ERR_NOTHING_TODO;
963 }
964
096f7609 965 if (ifp->vrf->vrf_id != VRF_DEFAULT) {
132a782e 966 vty_out(vty, "ldp-sync only runs on DEFAULT VRF\n");
967 return CMD_ERR_NOTHING_TODO;
968 }
969
970 params = IF_DEF_PARAMS(ifp);
971 ldp_sync_info = params->ldp_sync_info;
972 if (ldp_sync_info == NULL)
973 return CMD_SUCCESS;
974
975 /* use global configured value if set */
976 if (CHECK_FLAG(ldp_sync_info->flags, LDP_SYNC_FLAG_HOLDDOWN)) {
977 UNSET_FLAG(ldp_sync_info->flags, LDP_SYNC_FLAG_HOLDDOWN);
978 ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
979 if (ospf && CHECK_FLAG(ospf->ldp_sync_cmd.flags,
980 LDP_SYNC_FLAG_HOLDDOWN))
981 ldp_sync_info->holddown = ospf->ldp_sync_cmd.holddown;
982 else
983 ldp_sync_info->holddown = LDP_IGP_SYNC_HOLDDOWN_DEFAULT;
984 }
985 return CMD_SUCCESS;
986}
987
988DEFPY (show_ip_ospf_mpls_ldp_interface,
989 show_ip_ospf_mpls_ldp_interface_cmd,
990 "show ip ospf mpls ldp-sync [interface <INTERFACE|all>] [json]",
991 SHOW_STR
992 IP_STR
993 "OSPF information\n"
994 MPLS_STR
995 "LDP-IGP Sync information\n"
31011d9c 996 "Interface information\n"
132a782e 997 "Interface name\n"
31011d9c 998 "All interfaces\n"
132a782e 999 JSON_STR)
1000{
1001 struct ospf *ospf;
1002 bool uj = use_json(argc, argv);
1003 char *intf_name = NULL;
1004 int ret = CMD_SUCCESS;
1005 int idx_intf = 0;
1006 json_object *json = NULL;
1007
1008 if (argv_find(argv, argc, "INTERFACE", &idx_intf))
1009 intf_name = argv[idx_intf]->arg;
1010
1011 if (uj)
1012 json = json_object_new_object();
1013
1014 /* Display default ospf (instance 0) info */
1015 ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
1016 if (ospf == NULL || !ospf->oi_running) {
c48349e3 1017 if (uj)
92ef0078 1018 vty_json(vty, json);
c48349e3 1019 else
132a782e 1020 vty_out(vty, "%% OSPF instance not found\n");
1021 return CMD_SUCCESS;
1022 }
1023
1024 if (!CHECK_FLAG(ospf->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE)) {
c48349e3 1025 if (uj)
92ef0078 1026 vty_json(vty, json);
c48349e3 1027 else
132a782e 1028 vty_out(vty, "LDP-sync is disabled\n");
1029 return CMD_SUCCESS;
1030 }
1031
1032 ret = show_ip_ospf_mpls_ldp_interface_common(vty, ospf, intf_name,
1033 json, uj);
c48349e3 1034 if (uj)
92ef0078 1035 vty_json(vty, json);
132a782e 1036
1037 return ret;
1038}
1039
1040void ospf_ldp_sync_init(void)
1041{
1042 /* Install global ldp-igp sync commands */
1043 install_element(OSPF_NODE, &ospf_mpls_ldp_sync_cmd);
1044 install_element(OSPF_NODE, &no_ospf_mpls_ldp_sync_cmd);
1045 install_element(OSPF_NODE, &ospf_mpls_ldp_sync_holddown_cmd);
1046 install_element(OSPF_NODE, &no_ospf_mpls_ldp_sync_holddown_cmd);
1047
1048 /* Interface lsp-igp sync commands */
1049 install_element(INTERFACE_NODE, &mpls_ldp_sync_cmd);
1050 install_element(INTERFACE_NODE, &no_mpls_ldp_sync_cmd);
1051 install_element(INTERFACE_NODE, &mpls_ldp_sync_holddown_cmd);
1052 install_element(INTERFACE_NODE, &no_mpls_ldp_sync_holddown_cmd);
1053
1054 /* "show ip ospf mpls ldp interface" commands. */
1055 install_element(VIEW_NODE, &show_ip_ospf_mpls_ldp_interface_cmd);
1056
1057 hook_register(ospf_ism_change, ospf_ldp_sync_ism_change);
1058
1059}