Coverage Report

Created: 2025-10-23 06:55

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