]> git.proxmox.com Git - mirror_frr.git/blob - ospfd/ospf_ldp_sync.c
Merge pull request #12837 from donaldsharp/unlikely_routemap
[mirror_frr.git] / ospfd / ospf_ldp_sync.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * ospf_ldp_sync.c: OSPF LDP-IGP Sync handling routines
4 * Copyright (C) 2020 Volta Networks, Inc.
5 */
6
7 #include <zebra.h>
8 #include <string.h>
9
10 #include "monotime.h"
11 #include "memory.h"
12 #include "frrevent.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
31 extern struct zclient *zclient;
32
33 /*
34 * LDP-SYNC msg between IGP and LDP
35 */
36 int 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
52 ols_debug("%s: rcvd %s from LDP if %s", __func__,
53 state.sync_start ? "sync-start" : "sync-complete", ifp->name);
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
62 int 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
77 ols_debug("%s: rcvd announce from LDP", __func__);
78
79 /* LDP just started up:
80 * set cost to LSInfinity
81 * send request to LDP for LDP-SYNC state for each interface
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
87 return 0;
88 }
89
90 void ospf_ldp_sync_state_req_msg(struct interface *ifp)
91 {
92 struct ldp_igp_sync_if_state_req request;
93
94 ols_debug("%s: send state request to LDP for %s", __func__, ifp->name);
95
96 memset(&request, 0, sizeof(request));
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 */
108 void 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 */
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)))
121 return;
122
123 ols_debug("%s: init if %s", __func__, ifp->name);
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
130 /* specified on interface overrides global config. */
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
143 void 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) {
163 ols_debug("%s: start on if %s state: %s", __func__, ifp->name,
164 "Holding down until Sync");
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
174 void 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;
193 EVENT_OFF(ldp_sync_info->t_holddown);
194 ospf_if_recalculate_output_cost(ifp);
195 }
196 }
197
198 void 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 */
218 zlog_err("%s: LDP down", __func__);
219
220 vrf = vrf_lookup_by_id(ospf->vrf_id);
221 FOR_ALL_INTERFACES (vrf, ifp)
222 ospf_ldp_sync_ldp_fail(ifp);
223 }
224
225 void 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
236 /* LDP client close detected:
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) {
244 EVENT_OFF(ldp_sync_info->t_holddown);
245 ldp_sync_info->state = LDP_IGP_SYNC_STATE_REQUIRED_NOT_UP;
246 ospf_if_recalculate_output_cost(ifp);
247 }
248 }
249
250 void 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
264 ols_debug("%s: down on if %s", __func__, ifp->name);
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
290 void 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 */
306 ols_debug("%s: Removed from if %s", __func__, ifp->name);
307
308 EVENT_OFF(ldp_sync_info->t_holddown);
309
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) {
315 ldp_sync_info_free(&ldp_sync_info);
316 params->ldp_sync_info = NULL;
317 }
318 }
319
320 static 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 */
342 static void ospf_ldp_sync_holddown_timer(struct event *thread)
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 = EVENT_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;
358
359 ols_debug("%s: holddown timer expired for %s state: %s",
360 __func__, ifp->name, "Sync achieved");
361
362 ospf_if_recalculate_output_cost(ifp);
363 }
364 }
365
366 void 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
383 ols_debug("%s: start holddown timer for %s time %d", __func__,
384 ifp->name, ldp_sync_info->holddown);
385
386 event_add_timer(master, ospf_ldp_sync_holddown_timer, ifp,
387 ldp_sync_info->holddown, &ldp_sync_info->t_holddown);
388 }
389
390 /*
391 * LDP-SYNC exit routes.
392 */
393 void ospf_ldp_sync_gbl_exit(struct ospf *ospf, bool remove)
394 {
395 struct interface *ifp;
396 struct vrf *vrf;
397
398 /* ospf is being removed
399 * stop any holddown timers
400 */
401 if (CHECK_FLAG(ospf->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE)) {
402 /* unregister with opaque client to recv LDP-IGP Sync msgs */
403 zclient_unregister_opaque(zclient,
404 LDP_IGP_SYNC_IF_STATE_UPDATE);
405 zclient_unregister_opaque(zclient,
406 LDP_IGP_SYNC_ANNOUNCE_UPDATE);
407
408 /* disable LDP globally */
409 UNSET_FLAG(ospf->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE);
410 UNSET_FLAG(ospf->ldp_sync_cmd.flags, LDP_SYNC_FLAG_HOLDDOWN);
411 ospf->ldp_sync_cmd.holddown = LDP_IGP_SYNC_HOLDDOWN_DEFAULT;
412
413 /* turn off LDP-IGP Sync on all OSPF interfaces */
414 vrf = vrf_lookup_by_id(ospf->vrf_id);
415 FOR_ALL_INTERFACES (vrf, ifp)
416 ospf_ldp_sync_if_remove(ifp, remove);
417 }
418 }
419
420 /*
421 * LDP-SYNC routes used by set commands.
422 */
423 void ospf_if_set_ldp_sync_enable(struct ospf *ospf, struct interface *ifp)
424 {
425 struct ospf_if_params *params;
426 struct ldp_sync_info *ldp_sync_info;
427
428 /* called when setting LDP-SYNC at the global level:
429 * specified on interface overrides global config
430 * if ptop link send msg to LDP indicating ldp-sync enabled
431 */
432 if (if_is_loopback(ifp))
433 return;
434
435 params = IF_DEF_PARAMS(ifp);
436 if (params->ldp_sync_info == NULL)
437 params->ldp_sync_info = ldp_sync_info_create();
438 ldp_sync_info = params->ldp_sync_info;
439
440 /* config on interface, overrides global config. */
441 if (CHECK_FLAG(ldp_sync_info->flags, LDP_SYNC_FLAG_IF_CONFIG))
442 if (ldp_sync_info->enabled != LDP_IGP_SYNC_ENABLED)
443 return;
444
445 ldp_sync_info->enabled = LDP_IGP_SYNC_ENABLED;
446
447 ols_debug("%s: enable if %s", __func__, ifp->name);
448
449 /* send message to LDP if ptop link */
450 if (params->type == OSPF_IFTYPE_POINTOPOINT ||
451 if_is_pointopoint(ifp)) {
452 ldp_sync_info->state = LDP_IGP_SYNC_STATE_REQUIRED_NOT_UP;
453 ospf_ldp_sync_state_req_msg(ifp);
454 } else {
455 ldp_sync_info->state = LDP_IGP_SYNC_STATE_NOT_REQUIRED;
456 zlog_debug("%s: Sync only runs on P2P links %s", __func__,
457 ifp->name);
458 }
459 }
460
461 void ospf_if_set_ldp_sync_holddown(struct ospf *ospf, struct interface *ifp)
462 {
463 struct ospf_if_params *params;
464 struct ldp_sync_info *ldp_sync_info;
465
466 /* called when setting LDP-SYNC at the global level:
467 * specified on interface overrides global config.
468 */
469 if (if_is_loopback(ifp))
470 return;
471
472 params = IF_DEF_PARAMS(ifp);
473 if (params->ldp_sync_info == NULL)
474 params->ldp_sync_info = ldp_sync_info_create();
475 ldp_sync_info = params->ldp_sync_info;
476
477 /* config on interface, overrides global config. */
478 if (CHECK_FLAG(ldp_sync_info->flags, LDP_SYNC_FLAG_HOLDDOWN))
479 return;
480 if (CHECK_FLAG(ospf->ldp_sync_cmd.flags, LDP_SYNC_FLAG_HOLDDOWN))
481 ldp_sync_info->holddown = ospf->ldp_sync_cmd.holddown;
482 else
483 ldp_sync_info->holddown = LDP_IGP_SYNC_HOLDDOWN_DEFAULT;
484 }
485
486 /*
487 * LDP-SYNC routines used by show commands.
488 */
489
490 void ospf_ldp_sync_show_info(struct vty *vty, struct ospf *ospf,
491 json_object *json_vrf, bool use_json)
492 {
493
494 if (CHECK_FLAG(ospf->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE)) {
495 if (use_json) {
496 json_object_boolean_true_add(json_vrf,
497 "mplsLdpIgpSyncEnabled");
498 json_object_int_add(json_vrf, "mplsLdpIgpSyncHolddown",
499 ospf->ldp_sync_cmd.holddown);
500 } else {
501 vty_out(vty, " MPLS LDP-IGP Sync is enabled\n");
502 if (ospf->ldp_sync_cmd.holddown == 0)
503 vty_out(vty,
504 " MPLS LDP-IGP Sync holddown timer is disabled\n");
505 else
506 vty_out(vty,
507 " MPLS LDP-IGP Sync holddown timer %d sec\n",
508 ospf->ldp_sync_cmd.holddown);
509 }
510 }
511 }
512
513 static void show_ip_ospf_mpls_ldp_interface_sub(struct vty *vty,
514 struct ospf_interface *oi,
515 struct interface *ifp,
516 json_object *json_interface_sub,
517 bool use_json)
518 {
519 const char *ldp_state;
520 struct ospf_if_params *params;
521 char timebuf[OSPF_TIME_DUMP_SIZE];
522 struct ldp_sync_info *ldp_sync_info;
523
524 params = IF_DEF_PARAMS(oi->ifp);
525 if (params->ldp_sync_info == NULL)
526 return;
527
528 ldp_sync_info = params->ldp_sync_info;
529 if (use_json) {
530 if (ldp_sync_info->enabled == LDP_IGP_SYNC_ENABLED)
531 json_object_boolean_true_add(json_interface_sub,
532 "ldpIgpSyncEnabled");
533 else
534 json_object_boolean_false_add(json_interface_sub,
535 "ldpIgpSyncEnabled");
536
537 json_object_int_add(json_interface_sub, "holdDownTimeInSec",
538 ldp_sync_info->holddown);
539
540 } else {
541 vty_out(vty, "%-10s\n", ifp->name);
542 vty_out(vty, " LDP-IGP Synchronization enabled: %s\n",
543 ldp_sync_info->enabled == LDP_IGP_SYNC_ENABLED
544 ? "yes"
545 : "no");
546 vty_out(vty, " Holddown timer in seconds: %u\n",
547 ldp_sync_info->holddown);
548 }
549
550 switch (ldp_sync_info->state) {
551 case LDP_IGP_SYNC_STATE_REQUIRED_UP:
552 if (use_json)
553 json_object_string_add(json_interface_sub,
554 "ldpIgpSyncState",
555 "Sync achieved");
556 else
557 vty_out(vty, " State: Sync achieved\n");
558 break;
559 case LDP_IGP_SYNC_STATE_REQUIRED_NOT_UP:
560 if (ldp_sync_info->t_holddown != NULL) {
561 if (use_json) {
562 long time_store;
563
564 time_store = monotime_until(
565 &ldp_sync_info->t_holddown->u.sands,
566 NULL)
567 /1000LL;
568
569 json_object_int_add(json_interface_sub,
570 "ldpIgpSyncTimeRemainInMsec",
571 time_store);
572
573 json_object_string_add(json_interface_sub,
574 "ldpIgpSyncState",
575 "Holding down until Sync");
576 } else {
577 vty_out(vty,
578 " Holddown timer is running %s remaining\n",
579 ospf_timer_dump(
580 ldp_sync_info->t_holddown,
581 timebuf,
582 sizeof(timebuf)));
583
584 vty_out(vty,
585 " State: Holding down until Sync\n");
586 }
587 } else {
588 if (use_json)
589 json_object_string_add(json_interface_sub,
590 "ldpIgpSyncState",
591 "Sync not achieved");
592 else
593 vty_out(vty, " State: Sync not achieved\n");
594 }
595 break;
596 case LDP_IGP_SYNC_STATE_NOT_REQUIRED:
597 default:
598 if (IF_DEF_PARAMS(ifp)->type != OSPF_IFTYPE_POINTOPOINT &&
599 !if_is_pointopoint(ifp))
600 ldp_state = "Sync not required: non-p2p link";
601 else
602 ldp_state = "Sync not required";
603
604 if (use_json)
605 json_object_string_add(json_interface_sub,
606 "ldpIgpSyncState",
607 ldp_state);
608 else
609 vty_out(vty, " State: %s\n", ldp_state);
610 break;
611 }
612 }
613
614 static int show_ip_ospf_mpls_ldp_interface_common(struct vty *vty,
615 struct ospf *ospf,
616 char *intf_name,
617 json_object *json,
618 bool use_json)
619 {
620 struct interface *ifp;
621 struct vrf *vrf = vrf_lookup_by_id(ospf->vrf_id);
622 json_object *json_interface_sub = NULL;
623
624 if (intf_name == NULL) {
625 /* Show All Interfaces.*/
626 FOR_ALL_INTERFACES (vrf, ifp) {
627 struct route_node *rn;
628 struct ospf_interface *oi;
629
630 if (ospf_oi_count(ifp) == 0 && !use_json) {
631 if (!if_is_up(ifp))
632 vty_out(vty, "%s\n Interface down\n",
633 ifp->name);
634 continue;
635 }
636 for (rn = route_top(IF_OIFS(ifp)); rn;
637 rn = route_next(rn)) {
638 oi = rn->info;
639
640 if (use_json) {
641 json_interface_sub =
642 json_object_new_object();
643 }
644 show_ip_ospf_mpls_ldp_interface_sub(
645 vty, oi, ifp, json_interface_sub,
646 use_json);
647
648 if (use_json) {
649 json_object_object_add(
650 json, ifp->name,
651 json_interface_sub);
652 }
653 }
654 }
655 } else {
656 /* Interface name is specified. */
657 ifp = if_lookup_by_name(intf_name, ospf->vrf_id);
658 if (ifp != NULL) {
659 struct route_node *rn;
660 struct ospf_interface *oi;
661
662 if (ospf_oi_count(ifp) == 0 && !use_json) {
663 if (if_is_up(ifp))
664 vty_out(vty, "%s\n OSPF not enabled\n",
665 ifp->name);
666 else
667 vty_out(vty, "%s\n Interface down\n",
668 ifp->name);
669 return CMD_SUCCESS;
670 }
671 for (rn = route_top(IF_OIFS(ifp)); rn;
672 rn = route_next(rn)) {
673 oi = rn->info;
674
675 if (use_json)
676 json_interface_sub =
677 json_object_new_object();
678
679 show_ip_ospf_mpls_ldp_interface_sub(
680 vty, oi, ifp, json_interface_sub,
681 use_json);
682
683 if (use_json) {
684 json_object_object_add(
685 json, ifp->name,
686 json_interface_sub);
687 }
688 }
689 }
690 }
691 return CMD_SUCCESS;
692 }
693
694 /*
695 * Write the global LDP-SYNC configuration.
696 */
697 void ospf_ldp_sync_write_config(struct vty *vty, struct ospf *ospf)
698 {
699 if (CHECK_FLAG(ospf->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE))
700 vty_out(vty, " mpls ldp-sync\n");
701 if (CHECK_FLAG(ospf->ldp_sync_cmd.flags, LDP_SYNC_FLAG_HOLDDOWN))
702 vty_out(vty, " mpls ldp-sync holddown %u\n",
703 ospf->ldp_sync_cmd.holddown);
704 }
705
706 /*
707 * Write the interface LDP-SYNC configuration.
708 */
709 void ospf_ldp_sync_if_write_config(struct vty *vty,
710 struct ospf_if_params *params)
711
712 {
713 struct ldp_sync_info *ldp_sync_info;
714
715 ldp_sync_info = params->ldp_sync_info;
716 if (ldp_sync_info == NULL)
717 return;
718
719 if (CHECK_FLAG(ldp_sync_info->flags, LDP_SYNC_FLAG_IF_CONFIG)) {
720 if (ldp_sync_info->enabled == LDP_IGP_SYNC_ENABLED)
721 vty_out(vty, " ip ospf mpls ldp-sync\n");
722 else
723 vty_out(vty, " no ip ospf mpls ldp-sync\n");
724 }
725 if (CHECK_FLAG(ldp_sync_info->flags, LDP_SYNC_FLAG_HOLDDOWN))
726 vty_out(vty, " ip ospf mpls ldp-sync holddown %u\n",
727 ldp_sync_info->holddown);
728 }
729
730 /*
731 * LDP-SYNC commands.
732 */
733 #include "ospfd/ospf_ldp_sync_clippy.c"
734
735 DEFPY (ospf_mpls_ldp_sync,
736 ospf_mpls_ldp_sync_cmd,
737 "mpls ldp-sync",
738 "MPLS specific commands\n"
739 "Enable MPLS LDP-IGP Sync\n")
740 {
741 VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
742 struct vrf *vrf = vrf_lookup_by_id(ospf->vrf_id);
743 struct interface *ifp;
744
745 if (ospf->vrf_id != VRF_DEFAULT) {
746 vty_out(vty, "ldp-sync only runs on DEFAULT VRF\n");
747 return CMD_ERR_NOTHING_TODO;
748 }
749
750 /* register with opaque client to recv LDP-IGP Sync msgs */
751 zclient_register_opaque(zclient, LDP_IGP_SYNC_IF_STATE_UPDATE);
752 zclient_register_opaque(zclient, LDP_IGP_SYNC_ANNOUNCE_UPDATE);
753
754 if (!CHECK_FLAG(ospf->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE)) {
755 SET_FLAG(ospf->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE);
756 /* turn on LDP-IGP Sync on all ptop OSPF interfaces */
757 FOR_ALL_INTERFACES (vrf, ifp)
758 ospf_if_set_ldp_sync_enable(ospf, ifp);
759 }
760 return CMD_SUCCESS;
761 }
762
763 DEFPY (no_ospf_mpls_ldp_sync,
764 no_ospf_mpls_ldp_sync_cmd,
765 "no mpls ldp-sync",
766 NO_STR
767 "MPLS specific commands\n"
768 "Disable MPLS LDP-IGP Sync\n")
769 {
770 VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
771 ospf_ldp_sync_gbl_exit(ospf, false);
772 return CMD_SUCCESS;
773 }
774
775 DEFPY (ospf_mpls_ldp_sync_holddown,
776 ospf_mpls_ldp_sync_holddown_cmd,
777 "mpls ldp-sync holddown (1-10000)",
778 "MPLS specific commands\n"
779 "Enable MPLS LDP-IGP Sync\n"
780 "Set holddown timer\n"
781 "seconds\n")
782 {
783 VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
784 struct vrf *vrf = vrf_lookup_by_id(ospf->vrf_id);
785 struct interface *ifp;
786
787 if (ospf->vrf_id != VRF_DEFAULT) {
788 vty_out(vty, "ldp-sync only runs on DEFAULT VRF\n");
789 return CMD_ERR_NOTHING_TODO;
790 }
791
792 SET_FLAG(ospf->ldp_sync_cmd.flags, LDP_SYNC_FLAG_HOLDDOWN);
793 ospf->ldp_sync_cmd.holddown = holddown;
794 /* set holddown time on all OSPF interfaces */
795 FOR_ALL_INTERFACES (vrf, ifp)
796 ospf_if_set_ldp_sync_holddown(ospf, ifp);
797
798 return CMD_SUCCESS;
799 }
800
801 DEFPY (no_ospf_mpls_ldp_sync_holddown,
802 no_ospf_mpls_ldp_sync_holddown_cmd,
803 "no mpls ldp-sync holddown [<(1-10000)>]",
804 NO_STR
805 "MPLS specific commands\n"
806 "Disable MPLS LDP-IGP Sync\n"
807 "holddown timer disable\n"
808 "Time in seconds\n")
809 {
810 VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
811 struct vrf *vrf = vrf_lookup_by_id(ospf->vrf_id);
812 struct interface *ifp;
813
814 if (CHECK_FLAG(ospf->ldp_sync_cmd.flags, LDP_SYNC_FLAG_HOLDDOWN)) {
815 UNSET_FLAG(ospf->ldp_sync_cmd.flags, LDP_SYNC_FLAG_HOLDDOWN);
816 ospf->ldp_sync_cmd.holddown = LDP_IGP_SYNC_HOLDDOWN_DEFAULT;
817 /* turn off holddown timer on all OSPF interfaces */
818 FOR_ALL_INTERFACES (vrf, ifp)
819 ospf_if_set_ldp_sync_holddown(ospf, ifp);
820 }
821 return CMD_SUCCESS;
822 }
823
824
825 DEFPY (mpls_ldp_sync,
826 mpls_ldp_sync_cmd,
827 "ip ospf mpls ldp-sync",
828 IP_STR
829 "OSPF interface commands\n"
830 MPLS_STR
831 MPLS_LDP_SYNC_STR)
832 {
833 VTY_DECLVAR_CONTEXT(interface, ifp);
834 struct ospf_if_params *params;
835 struct ldp_sync_info *ldp_sync_info;
836
837 if (if_is_loopback(ifp)) {
838 vty_out(vty, "ldp-sync does not run on loopback interface\n");
839 return CMD_ERR_NOTHING_TODO;
840 }
841
842 if (ifp->vrf->vrf_id != VRF_DEFAULT) {
843 vty_out(vty, "ldp-sync only runs on DEFAULT VRF\n");
844 return CMD_ERR_NOTHING_TODO;
845 }
846
847 params = IF_DEF_PARAMS(ifp);
848 if (params->ldp_sync_info == NULL)
849 params->ldp_sync_info = ldp_sync_info_create();
850
851 ldp_sync_info = params->ldp_sync_info;
852
853 SET_FLAG(ldp_sync_info->flags, LDP_SYNC_FLAG_IF_CONFIG);
854 ldp_sync_info->enabled = LDP_IGP_SYNC_ENABLED;
855 if (params->type == OSPF_IFTYPE_POINTOPOINT || if_is_pointopoint(ifp)) {
856 ldp_sync_info->state = LDP_IGP_SYNC_STATE_REQUIRED_NOT_UP;
857 ospf_ldp_sync_state_req_msg(ifp);
858 } else {
859 zlog_debug("ldp_sync: only runs on P2P links %s", ifp->name);
860 ldp_sync_info->state = LDP_IGP_SYNC_STATE_NOT_REQUIRED;
861 }
862 return CMD_SUCCESS;
863 }
864
865 DEFPY (no_mpls_ldp_sync,
866 no_mpls_ldp_sync_cmd,
867 "no ip ospf mpls ldp-sync",
868 NO_STR
869 IP_STR
870 "OSPF interface commands\n"
871 MPLS_STR
872 NO_MPLS_LDP_SYNC_STR)
873 {
874 VTY_DECLVAR_CONTEXT(interface, ifp);
875 struct ospf_if_params *params;
876 struct ldp_sync_info *ldp_sync_info;
877
878 if (if_is_loopback(ifp)) {
879 vty_out(vty, "ldp-sync: does not run on loopback interface\n");
880 return CMD_ERR_NOTHING_TODO;
881 }
882
883 if (ifp->vrf->vrf_id != VRF_DEFAULT) {
884 vty_out(vty, "ldp-sync only runs on DEFAULT VRF\n");
885 return CMD_ERR_NOTHING_TODO;
886 }
887
888 params = IF_DEF_PARAMS(ifp);
889 if (params->ldp_sync_info == NULL)
890 params->ldp_sync_info = ldp_sync_info_create();
891
892 ldp_sync_info = params->ldp_sync_info;
893
894 /* disable LDP-SYNC on an interface
895 * stop holddown timer if running
896 * restore ospf cost
897 */
898 SET_FLAG(ldp_sync_info->flags, LDP_SYNC_FLAG_IF_CONFIG);
899 ldp_sync_info->enabled = LDP_IGP_SYNC_DEFAULT;
900 ldp_sync_info->state = LDP_IGP_SYNC_STATE_NOT_REQUIRED;
901 EVENT_OFF(ldp_sync_info->t_holddown);
902 ospf_if_recalculate_output_cost(ifp);
903
904 return CMD_SUCCESS;
905 }
906
907 DEFPY (mpls_ldp_sync_holddown,
908 mpls_ldp_sync_holddown_cmd,
909 "ip ospf mpls ldp-sync holddown (0-10000)",
910 IP_STR
911 "OSPF interface commands\n"
912 MPLS_STR
913 MPLS_LDP_SYNC_STR
914 "Time to wait for LDP-SYNC to occur before restoring interface cost\n"
915 "Time in seconds\n")
916 {
917 VTY_DECLVAR_CONTEXT(interface, ifp);
918 struct ospf_if_params *params;
919 struct ldp_sync_info *ldp_sync_info;
920
921 if (if_is_loopback(ifp)) {
922 vty_out(vty, "ldp-sync: does not run on loopback interface\n");
923 return CMD_ERR_NOTHING_TODO;
924 }
925
926 if (ifp->vrf->vrf_id != VRF_DEFAULT) {
927 vty_out(vty, "ldp-sync only runs on DEFAULT VRF\n");
928 return CMD_ERR_NOTHING_TODO;
929 }
930
931 params = IF_DEF_PARAMS(ifp);
932 if (params->ldp_sync_info == NULL)
933 params->ldp_sync_info = ldp_sync_info_create();
934
935 ldp_sync_info = params->ldp_sync_info;
936
937 SET_FLAG(ldp_sync_info->flags, LDP_SYNC_FLAG_HOLDDOWN);
938 ldp_sync_info->holddown = holddown;
939
940 return CMD_SUCCESS;
941 }
942
943 DEFPY (no_mpls_ldp_sync_holddown,
944 no_mpls_ldp_sync_holddown_cmd,
945 "no ip ospf mpls ldp-sync holddown [<(1-10000)>]",
946 NO_STR
947 IP_STR
948 "OSPF interface commands\n"
949 MPLS_STR
950 NO_MPLS_LDP_SYNC_STR
951 NO_MPLS_LDP_SYNC_HOLDDOWN_STR
952 "Time in seconds\n")
953 {
954 VTY_DECLVAR_CONTEXT(interface, ifp);
955 struct ospf_if_params *params;
956 struct ldp_sync_info *ldp_sync_info;
957 struct ospf *ospf;
958
959 if (if_is_loopback(ifp)) {
960 vty_out(vty, "ldp-sync: does not run on loopback interface\n");
961 return CMD_ERR_NOTHING_TODO;
962 }
963
964 if (ifp->vrf->vrf_id != VRF_DEFAULT) {
965 vty_out(vty, "ldp-sync only runs on DEFAULT VRF\n");
966 return CMD_ERR_NOTHING_TODO;
967 }
968
969 params = IF_DEF_PARAMS(ifp);
970 ldp_sync_info = params->ldp_sync_info;
971 if (ldp_sync_info == NULL)
972 return CMD_SUCCESS;
973
974 /* use global configured value if set */
975 if (CHECK_FLAG(ldp_sync_info->flags, LDP_SYNC_FLAG_HOLDDOWN)) {
976 UNSET_FLAG(ldp_sync_info->flags, LDP_SYNC_FLAG_HOLDDOWN);
977 ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
978 if (ospf && CHECK_FLAG(ospf->ldp_sync_cmd.flags,
979 LDP_SYNC_FLAG_HOLDDOWN))
980 ldp_sync_info->holddown = ospf->ldp_sync_cmd.holddown;
981 else
982 ldp_sync_info->holddown = LDP_IGP_SYNC_HOLDDOWN_DEFAULT;
983 }
984 return CMD_SUCCESS;
985 }
986
987 DEFPY (show_ip_ospf_mpls_ldp_interface,
988 show_ip_ospf_mpls_ldp_interface_cmd,
989 "show ip ospf mpls ldp-sync [interface <INTERFACE|all>] [json]",
990 SHOW_STR
991 IP_STR
992 "OSPF information\n"
993 MPLS_STR
994 "LDP-IGP Sync information\n"
995 "Interface information\n"
996 "Interface name\n"
997 "All interfaces\n"
998 JSON_STR)
999 {
1000 struct ospf *ospf;
1001 bool uj = use_json(argc, argv);
1002 char *intf_name = NULL;
1003 int ret = CMD_SUCCESS;
1004 int idx_intf = 0;
1005 json_object *json = NULL;
1006
1007 if (argv_find(argv, argc, "INTERFACE", &idx_intf))
1008 intf_name = argv[idx_intf]->arg;
1009
1010 if (uj)
1011 json = json_object_new_object();
1012
1013 /* Display default ospf (instance 0) info */
1014 ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
1015 if (ospf == NULL || !ospf->oi_running) {
1016 if (uj)
1017 vty_json(vty, json);
1018 else
1019 vty_out(vty, "%% OSPF instance not found\n");
1020 return CMD_SUCCESS;
1021 }
1022
1023 if (!CHECK_FLAG(ospf->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE)) {
1024 if (uj)
1025 vty_json(vty, json);
1026 else
1027 vty_out(vty, "LDP-sync is disabled\n");
1028 return CMD_SUCCESS;
1029 }
1030
1031 ret = show_ip_ospf_mpls_ldp_interface_common(vty, ospf, intf_name,
1032 json, uj);
1033 if (uj)
1034 vty_json(vty, json);
1035
1036 return ret;
1037 }
1038
1039 void ospf_ldp_sync_init(void)
1040 {
1041 /* Install global ldp-igp sync commands */
1042 install_element(OSPF_NODE, &ospf_mpls_ldp_sync_cmd);
1043 install_element(OSPF_NODE, &no_ospf_mpls_ldp_sync_cmd);
1044 install_element(OSPF_NODE, &ospf_mpls_ldp_sync_holddown_cmd);
1045 install_element(OSPF_NODE, &no_ospf_mpls_ldp_sync_holddown_cmd);
1046
1047 /* Interface lsp-igp sync commands */
1048 install_element(INTERFACE_NODE, &mpls_ldp_sync_cmd);
1049 install_element(INTERFACE_NODE, &no_mpls_ldp_sync_cmd);
1050 install_element(INTERFACE_NODE, &mpls_ldp_sync_holddown_cmd);
1051 install_element(INTERFACE_NODE, &no_mpls_ldp_sync_holddown_cmd);
1052
1053 /* "show ip ospf mpls ldp interface" commands. */
1054 install_element(VIEW_NODE, &show_ip_ospf_mpls_ldp_interface_cmd);
1055
1056 hook_register(ospf_ism_change, ospf_ldp_sync_ism_change);
1057
1058 }