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