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