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