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