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