Line data Source code
1 : /**
2 : * bgp_bfd.c: BGP BFD handling routines
3 : *
4 : * @copyright Copyright (C) 2015 Cumulus Networks, Inc.
5 : *
6 : * This file is part of GNU Zebra.
7 : *
8 : * GNU Zebra is free software; you can redistribute it and/or modify it
9 : * under the terms of the GNU General Public License as published by the
10 : * Free Software Foundation; either version 2, or (at your option) any
11 : * later version.
12 : *
13 : * GNU Zebra is distributed in the hope that it will be useful, but
14 : * WITHOUT ANY WARRANTY; without even the implied warranty of
15 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 : * General Public License for more details.
17 : *
18 : * You should have received a copy of the GNU General Public License along
19 : * with this program; see the file COPYING; if not, write to the Free Software
20 : * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 : */
22 :
23 : #include <zebra.h>
24 :
25 : #include "command.h"
26 : #include "linklist.h"
27 : #include "memory.h"
28 : #include "prefix.h"
29 : #include "thread.h"
30 : #include "buffer.h"
31 : #include "stream.h"
32 : #include "vrf.h"
33 : #include "zclient.h"
34 : #include "bfd.h"
35 : #include "lib/json.h"
36 : #include "filter.h"
37 :
38 : #include "bgpd/bgpd.h"
39 : #include "bgp_fsm.h"
40 : #include "bgpd/bgp_bfd.h"
41 : #include "bgpd/bgp_debug.h"
42 : #include "bgpd/bgp_vty.h"
43 : #include "bgpd/bgp_packet.h"
44 :
45 144 : DEFINE_MTYPE_STATIC(BGPD, BFD_CONFIG, "BFD configuration data");
46 :
47 : extern struct zclient *zclient;
48 :
49 0 : static void bfd_session_status_update(struct bfd_session_params *bsp,
50 : const struct bfd_session_status *bss,
51 : void *arg)
52 : {
53 0 : struct peer *peer = arg;
54 :
55 0 : if (BGP_DEBUG(bfd, BFD_LIB))
56 0 : zlog_debug("%s: neighbor %s vrf %s(%u) bfd state %s -> %s",
57 : __func__, peer->conf_if ? peer->conf_if : peer->host,
58 : bfd_sess_vrf(bsp), bfd_sess_vrf_id(bsp),
59 : bfd_get_status_str(bss->previous_state),
60 : bfd_get_status_str(bss->state));
61 :
62 0 : if (bss->state == BSS_DOWN && bss->previous_state == BSS_UP) {
63 0 : if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_MODE)
64 0 : && bfd_sess_cbit(bsp) && !bss->remote_cbit) {
65 0 : if (BGP_DEBUG(bfd, BFD_LIB))
66 0 : zlog_debug(
67 : "%s BFD DOWN message ignored in the process of graceful restart when C bit is cleared",
68 : peer->host);
69 0 : return;
70 : }
71 0 : peer->last_reset = PEER_DOWN_BFD_DOWN;
72 :
73 : /* draft-ietf-idr-bfd-subcode */
74 0 : if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
75 0 : bgp_notify_send(peer, BGP_NOTIFY_CEASE,
76 : BGP_NOTIFY_CEASE_BFD_DOWN);
77 :
78 0 : BGP_EVENT_ADD(peer, BGP_Stop);
79 : }
80 :
81 0 : if (bss->state == BSS_UP && bss->previous_state != BSS_UP
82 0 : && !peer_established(peer)) {
83 0 : if (!BGP_PEER_START_SUPPRESSED(peer)) {
84 0 : bgp_fsm_nht_update(peer, true);
85 0 : BGP_EVENT_ADD(peer, BGP_Start);
86 : }
87 : }
88 : }
89 :
90 0 : void bgp_peer_config_apply(struct peer *p, struct peer_group *pg)
91 : {
92 0 : struct listnode *n;
93 0 : struct peer *pn;
94 0 : struct peer *gconfig;
95 :
96 : /* When called on a group, apply to all peers. */
97 0 : if (CHECK_FLAG(p->sflags, PEER_STATUS_GROUP)) {
98 0 : for (ALL_LIST_ELEMENTS_RO(p->group->peer, n, pn))
99 0 : bgp_peer_config_apply(pn, pg);
100 : return;
101 : }
102 :
103 : /* No group, just use current configuration. */
104 0 : if (pg == NULL || pg->conf->bfd_config == NULL) {
105 0 : bfd_sess_set_timers(p->bfd_config->session,
106 0 : p->bfd_config->detection_multiplier,
107 : p->bfd_config->min_rx,
108 0 : p->bfd_config->min_tx);
109 0 : bfd_sess_set_cbit(p->bfd_config->session, p->bfd_config->cbit);
110 0 : bfd_sess_set_profile(p->bfd_config->session,
111 0 : p->bfd_config->profile);
112 0 : bfd_sess_install(p->bfd_config->session);
113 0 : return;
114 : }
115 :
116 : /*
117 : * Check if the group configuration was overwritten or apply group
118 : * configuration.
119 : */
120 0 : gconfig = pg->conf;
121 :
122 : /*
123 : * If using default control plane independent configuration,
124 : * then prefer group's (e.g. it means it wasn't manually configured).
125 : */
126 0 : if (!p->bfd_config->cbit)
127 0 : bfd_sess_set_cbit(p->bfd_config->session,
128 0 : gconfig->bfd_config->cbit);
129 : else
130 0 : bfd_sess_set_cbit(p->bfd_config->session, p->bfd_config->cbit);
131 :
132 : /* If no profile was specified in peer, then use the group profile. */
133 0 : if (p->bfd_config->profile[0] == 0)
134 0 : bfd_sess_set_profile(p->bfd_config->session,
135 0 : gconfig->bfd_config->profile);
136 : else
137 0 : bfd_sess_set_profile(p->bfd_config->session,
138 0 : p->bfd_config->profile);
139 :
140 : /* If no specific timers were configured, then use the group timers. */
141 0 : if (p->bfd_config->detection_multiplier == BFD_DEF_DETECT_MULT
142 0 : || p->bfd_config->min_rx == BFD_DEF_MIN_RX
143 0 : || p->bfd_config->min_tx == BFD_DEF_MIN_TX)
144 0 : bfd_sess_set_timers(p->bfd_config->session,
145 0 : gconfig->bfd_config->detection_multiplier,
146 : gconfig->bfd_config->min_rx,
147 0 : gconfig->bfd_config->min_tx);
148 : else
149 0 : bfd_sess_set_timers(p->bfd_config->session,
150 : p->bfd_config->detection_multiplier,
151 : p->bfd_config->min_rx,
152 : p->bfd_config->min_tx);
153 :
154 0 : bfd_sess_install(p->bfd_config->session);
155 : }
156 :
157 0 : void bgp_peer_bfd_update_source(struct peer *p)
158 : {
159 0 : struct bfd_session_params *session = p->bfd_config->session;
160 0 : const union sockunion *source;
161 0 : bool changed = false;
162 0 : int family;
163 0 : union {
164 : struct in_addr v4;
165 : struct in6_addr v6;
166 : } src, dst;
167 :
168 : /* Nothing to do for groups. */
169 0 : if (CHECK_FLAG(p->sflags, PEER_STATUS_GROUP))
170 0 : return;
171 :
172 : /* Figure out the correct source to use. */
173 0 : if (CHECK_FLAG(p->flags, PEER_FLAG_UPDATE_SOURCE) && p->update_source)
174 : source = p->update_source;
175 : else
176 0 : source = p->su_local;
177 :
178 : /* Update peer's source/destination addresses. */
179 0 : bfd_sess_addresses(session, &family, &src.v6, &dst.v6);
180 0 : if (family == AF_INET) {
181 0 : if ((source && source->sin.sin_addr.s_addr != src.v4.s_addr)
182 0 : || p->su.sin.sin_addr.s_addr != dst.v4.s_addr) {
183 0 : if (BGP_DEBUG(bfd, BFD_LIB))
184 0 : zlog_debug(
185 : "%s: address [%pI4->%pI4] to [%pI4->%pI4]",
186 : __func__, &src.v4, &dst.v4,
187 : source ? &source->sin.sin_addr
188 : : &src.v4,
189 : &p->su.sin.sin_addr);
190 :
191 0 : bfd_sess_set_ipv4_addrs(
192 : session, source ? &source->sin.sin_addr : NULL,
193 0 : &p->su.sin.sin_addr);
194 0 : changed = true;
195 : }
196 : } else {
197 0 : if ((source && memcmp(&source->sin6, &src.v6, sizeof(src.v6)))
198 0 : || memcmp(&p->su.sin6, &dst.v6, sizeof(dst.v6))) {
199 0 : if (BGP_DEBUG(bfd, BFD_LIB))
200 0 : zlog_debug(
201 : "%s: address [%pI6->%pI6] to [%pI6->%pI6]",
202 : __func__, &src.v6, &dst.v6,
203 : source ? &source->sin6.sin6_addr
204 : : &src.v6,
205 : &p->su.sin6.sin6_addr);
206 :
207 0 : bfd_sess_set_ipv6_addrs(session,
208 : source ? &source->sin6.sin6_addr
209 : : NULL,
210 0 : &p->su.sin6.sin6_addr);
211 0 : changed = true;
212 : }
213 : }
214 :
215 : /* Update interface. */
216 0 : if (p->nexthop.ifp && bfd_sess_interface(session) == NULL) {
217 0 : if (BGP_DEBUG(bfd, BFD_LIB))
218 0 : zlog_debug("%s: interface none to %s", __func__,
219 : p->nexthop.ifp->name);
220 :
221 0 : bfd_sess_set_interface(session, p->nexthop.ifp->name);
222 0 : changed = true;
223 : }
224 :
225 : /*
226 : * Update TTL.
227 : *
228 : * Two cases:
229 : * - We detected that the peer is a hop away from us (remove multi hop).
230 : * (this happens when `p->shared_network` is set to `true`)
231 : * - eBGP multi hop / TTL security changed.
232 : */
233 0 : if (!PEER_IS_MULTIHOP(p) && bfd_sess_hop_count(session) > 1) {
234 0 : if (BGP_DEBUG(bfd, BFD_LIB))
235 0 : zlog_debug("%s: TTL %d to 1", __func__,
236 : bfd_sess_hop_count(session));
237 :
238 0 : bfd_sess_set_hop_count(session, 1);
239 0 : changed = true;
240 : }
241 0 : if (PEER_IS_MULTIHOP(p) && p->ttl != bfd_sess_hop_count(session)) {
242 0 : if (BGP_DEBUG(bfd, BFD_LIB))
243 0 : zlog_debug("%s: TTL %d to %d", __func__,
244 : bfd_sess_hop_count(session), p->ttl);
245 :
246 0 : bfd_sess_set_hop_count(session, p->ttl);
247 0 : changed = true;
248 : }
249 :
250 : /* Update VRF. */
251 0 : if (bfd_sess_vrf_id(session) != p->bgp->vrf_id) {
252 0 : if (BGP_DEBUG(bfd, BFD_LIB))
253 0 : zlog_debug(
254 : "%s: VRF %s(%d) to %s(%d)", __func__,
255 : bfd_sess_vrf(session), bfd_sess_vrf_id(session),
256 : vrf_id_to_name(p->bgp->vrf_id), p->bgp->vrf_id);
257 :
258 0 : bfd_sess_set_vrf(session, p->bgp->vrf_id);
259 0 : changed = true;
260 : }
261 :
262 0 : if (changed)
263 0 : bfd_sess_install(session);
264 : }
265 :
266 : /**
267 : * Reset BFD configuration data structure to its defaults settings.
268 : */
269 0 : static void bgp_peer_bfd_reset(struct peer *p)
270 : {
271 : /* Set defaults. */
272 0 : p->bfd_config->detection_multiplier = BFD_DEF_DETECT_MULT;
273 0 : p->bfd_config->min_rx = BFD_DEF_MIN_RX;
274 0 : p->bfd_config->min_tx = BFD_DEF_MIN_TX;
275 0 : p->bfd_config->cbit = false;
276 0 : p->bfd_config->profile[0] = 0;
277 : }
278 :
279 0 : void bgp_peer_configure_bfd(struct peer *p, bool manual)
280 : {
281 : /* Groups should not call this. */
282 0 : assert(!CHECK_FLAG(p->sflags, PEER_STATUS_GROUP));
283 :
284 : /* Already configured, skip it. */
285 0 : if (p->bfd_config) {
286 : /* If manually active update flag. */
287 0 : if (!p->bfd_config->manual)
288 0 : p->bfd_config->manual = manual;
289 :
290 0 : return;
291 : }
292 :
293 : /* Allocate memory for configuration overrides. */
294 0 : p->bfd_config = XCALLOC(MTYPE_BFD_CONFIG, sizeof(*p->bfd_config));
295 0 : p->bfd_config->manual = manual;
296 :
297 : /* Create new session and assign callback. */
298 0 : p->bfd_config->session = bfd_sess_new(bfd_session_status_update, p);
299 0 : bgp_peer_bfd_reset(p);
300 :
301 : /* Configure session with basic BGP peer data. */
302 0 : if (p->su.sa.sa_family == AF_INET)
303 0 : bfd_sess_set_ipv4_addrs(p->bfd_config->session,
304 0 : p->su_local ? &p->su_local->sin.sin_addr
305 : : NULL,
306 0 : &p->su.sin.sin_addr);
307 : else
308 0 : bfd_sess_set_ipv6_addrs(
309 : p->bfd_config->session,
310 0 : p->su_local ? &p->su_local->sin6.sin6_addr : NULL,
311 0 : &p->su.sin6.sin6_addr);
312 :
313 0 : bfd_sess_set_vrf(p->bfd_config->session, p->bgp->vrf_id);
314 0 : bfd_sess_set_hop_count(p->bfd_config->session,
315 0 : PEER_IS_MULTIHOP(p) ? p->ttl : 1);
316 :
317 0 : if (p->nexthop.ifp)
318 0 : bfd_sess_set_interface(p->bfd_config->session,
319 0 : p->nexthop.ifp->name);
320 : }
321 :
322 0 : static void bgp_peer_remove_bfd(struct peer *p)
323 : {
324 : /* Groups should not call this. */
325 0 : assert(!CHECK_FLAG(p->sflags, PEER_STATUS_GROUP));
326 :
327 : /*
328 : * Peer configuration was removed, however we must check if there
329 : * is still a group configuration to keep this running.
330 : */
331 0 : if (p->group && p->group->conf->bfd_config) {
332 0 : p->bfd_config->manual = false;
333 0 : bgp_peer_bfd_reset(p);
334 0 : bgp_peer_config_apply(p, p->group);
335 0 : return;
336 : }
337 :
338 0 : if (p->bfd_config)
339 0 : bfd_sess_free(&p->bfd_config->session);
340 :
341 0 : XFREE(MTYPE_BFD_CONFIG, p->bfd_config);
342 : }
343 :
344 0 : static void bgp_group_configure_bfd(struct peer *p)
345 : {
346 0 : struct listnode *n;
347 0 : struct peer *pn;
348 :
349 : /* Peers should not call this. */
350 0 : assert(CHECK_FLAG(p->sflags, PEER_STATUS_GROUP));
351 :
352 : /* Already allocated: do nothing. */
353 0 : if (p->bfd_config)
354 : return;
355 :
356 0 : p->bfd_config = XCALLOC(MTYPE_BFD_CONFIG, sizeof(*p->bfd_config));
357 :
358 : /* Set defaults. */
359 0 : p->bfd_config->detection_multiplier = BFD_DEF_DETECT_MULT;
360 0 : p->bfd_config->min_rx = BFD_DEF_MIN_RX;
361 0 : p->bfd_config->min_tx = BFD_DEF_MIN_TX;
362 :
363 0 : for (ALL_LIST_ELEMENTS_RO(p->group->peer, n, pn))
364 0 : bgp_peer_configure_bfd(pn, false);
365 : }
366 :
367 0 : static void bgp_group_remove_bfd(struct peer *p)
368 : {
369 0 : struct listnode *n;
370 0 : struct peer *pn;
371 :
372 : /* Peers should not call this. */
373 0 : assert(CHECK_FLAG(p->sflags, PEER_STATUS_GROUP));
374 :
375 : /* Already freed: do nothing. */
376 0 : if (p->bfd_config == NULL)
377 : return;
378 :
379 : /* Free configuration and point to `NULL`. */
380 0 : XFREE(MTYPE_BFD_CONFIG, p->bfd_config);
381 :
382 : /* Now that it is `NULL` recalculate configuration for all peers. */
383 0 : for (ALL_LIST_ELEMENTS_RO(p->group->peer, n, pn)) {
384 0 : if (pn->bfd_config->manual)
385 0 : bgp_peer_config_apply(pn, NULL);
386 : else
387 0 : bgp_peer_remove_bfd(pn);
388 : }
389 : }
390 :
391 0 : void bgp_peer_remove_bfd_config(struct peer *p)
392 : {
393 0 : if (CHECK_FLAG(p->sflags, PEER_STATUS_GROUP))
394 0 : bgp_group_remove_bfd(p);
395 : else
396 0 : bgp_peer_remove_bfd(p);
397 0 : }
398 :
399 : /*
400 : * bgp_bfd_peer_config_write - Write the peer BFD configuration.
401 : */
402 0 : void bgp_bfd_peer_config_write(struct vty *vty, const struct peer *peer,
403 : const char *addr)
404 : {
405 : /*
406 : * Always show group BFD configuration, but peer only when explicitly
407 : * configured.
408 : */
409 0 : if ((!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)
410 0 : && peer->bfd_config->manual)
411 0 : || CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
412 : #if HAVE_BFDD > 0
413 0 : vty_out(vty, " neighbor %s bfd\n", addr);
414 : #else
415 : vty_out(vty, " neighbor %s bfd %d %d %d\n", addr,
416 : peer->bfd_config->detection_multiplier,
417 : peer->bfd_config->min_rx, peer->bfd_config->min_tx);
418 : #endif /* HAVE_BFDD */
419 : }
420 :
421 0 : if (peer->bfd_config->profile[0])
422 0 : vty_out(vty, " neighbor %s bfd profile %s\n", addr,
423 0 : peer->bfd_config->profile);
424 :
425 0 : if (peer->bfd_config->cbit)
426 0 : vty_out(vty, " neighbor %s bfd check-control-plane-failure\n",
427 : addr);
428 0 : }
429 :
430 : /*
431 : * bgp_bfd_show_info - Show the peer BFD information.
432 : */
433 0 : void bgp_bfd_show_info(struct vty *vty, const struct peer *peer,
434 : json_object *json_neigh)
435 : {
436 0 : bfd_sess_show(vty, json_neigh, peer->bfd_config->session);
437 0 : }
438 :
439 0 : DEFUN (neighbor_bfd,
440 : neighbor_bfd_cmd,
441 : "neighbor <A.B.C.D|X:X::X:X|WORD> bfd",
442 : NEIGHBOR_STR
443 : NEIGHBOR_ADDR_STR2
444 : "Enables BFD support\n")
445 : {
446 0 : int idx_peer = 1;
447 0 : struct peer *peer;
448 :
449 0 : peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
450 0 : if (!peer)
451 : return CMD_WARNING_CONFIG_FAILED;
452 :
453 0 : if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
454 0 : bgp_group_configure_bfd(peer);
455 : else
456 0 : bgp_peer_configure_bfd(peer, true);
457 :
458 0 : bgp_peer_config_apply(peer, peer->group);
459 :
460 0 : return CMD_SUCCESS;
461 : }
462 :
463 : #if HAVE_BFDD > 0
464 0 : DEFUN_HIDDEN(
465 : #else
466 : DEFUN(
467 : #endif /* HAVE_BFDD */
468 : neighbor_bfd_param,
469 : neighbor_bfd_param_cmd,
470 : "neighbor <A.B.C.D|X:X::X:X|WORD> bfd (2-255) (50-60000) (50-60000)",
471 : NEIGHBOR_STR
472 : NEIGHBOR_ADDR_STR2
473 : "Enables BFD support\n"
474 : "Detect Multiplier\n"
475 : "Required min receive interval\n"
476 : "Desired min transmit interval\n")
477 : {
478 0 : int idx_peer = 1;
479 0 : int idx_number_1 = 3;
480 0 : int idx_number_2 = 4;
481 0 : int idx_number_3 = 5;
482 0 : long detection_multiplier, min_rx, min_tx;
483 0 : struct peer *peer;
484 :
485 0 : peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
486 0 : if (!peer)
487 : return CMD_WARNING_CONFIG_FAILED;
488 :
489 0 : detection_multiplier = strtol(argv[idx_number_1]->arg, NULL, 10);
490 0 : min_rx = strtol(argv[idx_number_2]->arg, NULL, 10);
491 0 : min_tx = strtol(argv[idx_number_3]->arg, NULL, 10);
492 :
493 0 : if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
494 0 : bgp_group_configure_bfd(peer);
495 : else
496 0 : bgp_peer_configure_bfd(peer, true);
497 :
498 0 : peer->bfd_config->detection_multiplier = detection_multiplier;
499 0 : peer->bfd_config->min_rx = min_rx;
500 0 : peer->bfd_config->min_tx = min_tx;
501 0 : bgp_peer_config_apply(peer, peer->group);
502 :
503 0 : return CMD_SUCCESS;
504 : }
505 :
506 0 : DEFUN (neighbor_bfd_check_controlplane_failure,
507 : neighbor_bfd_check_controlplane_failure_cmd,
508 : "[no] neighbor <A.B.C.D|X:X::X:X|WORD> bfd check-control-plane-failure",
509 : NO_STR
510 : NEIGHBOR_STR
511 : NEIGHBOR_ADDR_STR2
512 : "BFD support\n"
513 : "Link dataplane status with BGP controlplane\n")
514 : {
515 0 : const char *no = strmatch(argv[0]->text, "no") ? "no" : NULL;
516 0 : int idx_peer = 0;
517 0 : struct peer *peer;
518 :
519 0 : if (no)
520 : idx_peer = 2;
521 : else
522 : idx_peer = 1;
523 0 : peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
524 0 : if (!peer)
525 : return CMD_WARNING_CONFIG_FAILED;
526 :
527 0 : if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
528 0 : bgp_group_configure_bfd(peer);
529 : else
530 0 : bgp_peer_configure_bfd(peer, true);
531 :
532 0 : peer->bfd_config->cbit = no == NULL;
533 0 : bgp_peer_config_apply(peer, peer->group);
534 :
535 0 : return CMD_SUCCESS;
536 : }
537 :
538 0 : DEFUN (no_neighbor_bfd,
539 : no_neighbor_bfd_cmd,
540 : #if HAVE_BFDD > 0
541 : "no neighbor <A.B.C.D|X:X::X:X|WORD> bfd",
542 : #else
543 : "no neighbor <A.B.C.D|X:X::X:X|WORD> bfd [(2-255) (50-60000) (50-60000)]",
544 : #endif /* HAVE_BFDD */
545 : NO_STR
546 : NEIGHBOR_STR
547 : NEIGHBOR_ADDR_STR2
548 : "Disables BFD support\n"
549 : #if HAVE_BFDD == 0
550 : "Detect Multiplier\n"
551 : "Required min receive interval\n"
552 : "Desired min transmit interval\n"
553 : #endif /* !HAVE_BFDD */
554 : )
555 : {
556 0 : int idx_peer = 2;
557 0 : struct peer *peer;
558 :
559 0 : peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
560 0 : if (!peer)
561 : return CMD_WARNING_CONFIG_FAILED;
562 :
563 0 : if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
564 0 : bgp_group_remove_bfd(peer);
565 : else
566 0 : bgp_peer_remove_bfd(peer);
567 :
568 : return CMD_SUCCESS;
569 : }
570 :
571 : #if HAVE_BFDD > 0
572 0 : DEFUN(neighbor_bfd_profile, neighbor_bfd_profile_cmd,
573 : "neighbor <A.B.C.D|X:X::X:X|WORD> bfd profile BFDPROF",
574 : NEIGHBOR_STR
575 : NEIGHBOR_ADDR_STR2
576 : "BFD integration\n"
577 : BFD_PROFILE_STR
578 : BFD_PROFILE_NAME_STR)
579 : {
580 0 : int idx_peer = 1, idx_prof = 4;
581 0 : struct peer *peer;
582 :
583 0 : peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
584 0 : if (!peer)
585 : return CMD_WARNING_CONFIG_FAILED;
586 :
587 0 : if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
588 0 : bgp_group_configure_bfd(peer);
589 : else
590 0 : bgp_peer_configure_bfd(peer, true);
591 :
592 0 : strlcpy(peer->bfd_config->profile, argv[idx_prof]->arg,
593 : sizeof(peer->bfd_config->profile));
594 0 : bgp_peer_config_apply(peer, peer->group);
595 :
596 0 : return CMD_SUCCESS;
597 : }
598 :
599 0 : DEFUN(no_neighbor_bfd_profile, no_neighbor_bfd_profile_cmd,
600 : "no neighbor <A.B.C.D|X:X::X:X|WORD> bfd profile [BFDPROF]",
601 : NO_STR
602 : NEIGHBOR_STR
603 : NEIGHBOR_ADDR_STR2
604 : "BFD integration\n"
605 : BFD_PROFILE_STR
606 : BFD_PROFILE_NAME_STR)
607 : {
608 0 : int idx_peer = 2;
609 0 : struct peer *peer;
610 :
611 0 : peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
612 0 : if (!peer)
613 : return CMD_WARNING_CONFIG_FAILED;
614 :
615 0 : if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
616 0 : bgp_group_configure_bfd(peer);
617 : else
618 0 : bgp_peer_configure_bfd(peer, true);
619 :
620 0 : peer->bfd_config->profile[0] = 0;
621 0 : bgp_peer_config_apply(peer, peer->group);
622 :
623 0 : return CMD_SUCCESS;
624 : }
625 : #endif /* HAVE_BFDD */
626 :
627 48 : void bgp_bfd_init(struct thread_master *tm)
628 : {
629 : /* Initialize BFD client functions */
630 48 : bfd_protocol_integration_init(zclient, tm);
631 :
632 : /* "neighbor bfd" commands. */
633 48 : install_element(BGP_NODE, &neighbor_bfd_cmd);
634 48 : install_element(BGP_NODE, &neighbor_bfd_param_cmd);
635 48 : install_element(BGP_NODE, &neighbor_bfd_check_controlplane_failure_cmd);
636 48 : install_element(BGP_NODE, &no_neighbor_bfd_cmd);
637 :
638 : #if HAVE_BFDD > 0
639 48 : install_element(BGP_NODE, &neighbor_bfd_profile_cmd);
640 48 : install_element(BGP_NODE, &no_neighbor_bfd_profile_cmd);
641 : #endif /* HAVE_BFDD */
642 48 : }
|