]>
Commit | Line | Data |
---|---|---|
c43ed2e4 DS |
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 | * | |
896014f4 DL |
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 | |
c43ed2e4 DS |
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 "zclient.h" | |
7f342629 | 33 | #include "bfd.h" |
856ca177 | 34 | #include "lib/json.h" |
039f3a34 DS |
35 | #include "filter.h" |
36 | ||
c43ed2e4 | 37 | #include "bgpd/bgpd.h" |
7f342629 | 38 | #include "bgp_fsm.h" |
c43ed2e4 DS |
39 | #include "bgpd/bgp_bfd.h" |
40 | #include "bgpd/bgp_debug.h" | |
41 | #include "bgpd/bgp_vty.h" | |
42 | ||
43 | extern struct zclient *zclient; | |
44 | ||
c43ed2e4 | 45 | /* |
d62a17ae | 46 | * bgp_bfd_peer_group2peer_copy - Copy the BFD information from peer group |
47 | * template | |
c43ed2e4 DS |
48 | * to peer. |
49 | */ | |
d62a17ae | 50 | void bgp_bfd_peer_group2peer_copy(struct peer *conf, struct peer *peer) |
c43ed2e4 | 51 | { |
d62a17ae | 52 | struct bfd_info *bfd_info; |
53 | struct bfd_info *conf_bfd_info; | |
7f342629 | 54 | |
d62a17ae | 55 | if (!conf->bfd_info) |
56 | return; | |
7f342629 | 57 | |
d62a17ae | 58 | conf_bfd_info = (struct bfd_info *)conf->bfd_info; |
59 | if (!peer->bfd_info) | |
60 | peer->bfd_info = bfd_info_create(); | |
c43ed2e4 | 61 | |
d62a17ae | 62 | bfd_info = (struct bfd_info *)peer->bfd_info; |
c43ed2e4 | 63 | |
d62a17ae | 64 | /* Copy BFD parameter values */ |
65 | bfd_info->required_min_rx = conf_bfd_info->required_min_rx; | |
66 | bfd_info->desired_min_tx = conf_bfd_info->desired_min_tx; | |
67 | bfd_info->detect_mult = conf_bfd_info->detect_mult; | |
68 | bfd_info->type = conf_bfd_info->type; | |
c43ed2e4 DS |
69 | } |
70 | ||
71 | /* | |
d62a17ae | 72 | * bgp_bfd_is_peer_multihop - returns whether BFD peer is multi-hop or single |
73 | * hop. | |
c43ed2e4 | 74 | */ |
3dc339cd | 75 | bool bgp_bfd_is_peer_multihop(struct peer *peer) |
c43ed2e4 | 76 | { |
d62a17ae | 77 | struct bfd_info *bfd_info; |
986aa00f | 78 | |
d62a17ae | 79 | bfd_info = (struct bfd_info *)peer->bfd_info; |
986aa00f | 80 | |
d62a17ae | 81 | if (!bfd_info) |
3dc339cd | 82 | return false; |
986aa00f | 83 | |
d62a17ae | 84 | if ((bfd_info->type == BFD_TYPE_MULTIHOP) |
85 | || ((peer->sort == BGP_PEER_IBGP) && !peer->shared_network) | |
86 | || is_ebgp_multihop_configured(peer)) | |
3dc339cd | 87 | return true; |
d62a17ae | 88 | else |
3dc339cd | 89 | return false; |
c43ed2e4 DS |
90 | } |
91 | ||
92 | /* | |
7f342629 DS |
93 | * bgp_bfd_peer_sendmsg - Format and send a Peer register/Unregister |
94 | * command to Zebra to be forwarded to BFD | |
c43ed2e4 | 95 | */ |
d62a17ae | 96 | static void bgp_bfd_peer_sendmsg(struct peer *peer, int command) |
c43ed2e4 | 97 | { |
02012bef | 98 | struct bfd_session_arg arg = {}; |
d62a17ae | 99 | struct bfd_info *bfd_info; |
02012bef | 100 | int multihop; |
0945d5ed | 101 | vrf_id_t vrf_id; |
02012bef | 102 | size_t addrlen; |
d62a17ae | 103 | |
95a99382 RZ |
104 | /* |
105 | * XXX: some pointers are dangling during shutdown, so instead of | |
106 | * trying to send a message during signal handlers lets just wait BGP | |
107 | * to terminate zebra's connection and BFD will automatically find | |
108 | * out that we are no longer expecting notifications. | |
109 | * | |
110 | * The pointer that is causing a crash here is `peer->nexthop.ifp`. | |
111 | * That happens because at this point of the shutdown all interfaces are | |
112 | * already `free()`d. | |
113 | */ | |
114 | if (bm->terminating) | |
115 | return; | |
d62a17ae | 116 | |
117 | bfd_info = (struct bfd_info *)peer->bfd_info; | |
118 | ||
0945d5ed | 119 | vrf_id = peer->bgp->vrf_id; |
d62a17ae | 120 | |
121 | if (command == ZEBRA_BFD_DEST_DEREGISTER) { | |
122 | multihop = | |
123 | CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_TYPE_MULTIHOP); | |
124 | UNSET_FLAG(bfd_info->flags, BFD_FLAG_BFD_TYPE_MULTIHOP); | |
125 | } else { | |
126 | multihop = bgp_bfd_is_peer_multihop(peer); | |
127 | if ((command == ZEBRA_BFD_DEST_REGISTER) && multihop) | |
128 | SET_FLAG(bfd_info->flags, BFD_FLAG_BFD_TYPE_MULTIHOP); | |
129 | } | |
dcffea69 PG |
130 | /* while graceful restart with fwd path preserved |
131 | * and bfd controlplane check not configured is not kept | |
9beff0bd PG |
132 | * keep bfd independent controlplane bit set to 1 |
133 | */ | |
892fedb6 DA |
134 | if (!CHECK_FLAG(peer->bgp->flags, BGP_FLAG_GRACEFUL_RESTART) |
135 | && !CHECK_FLAG(peer->bgp->flags, BGP_FLAG_GR_PRESERVE_FWD) | |
dcffea69 | 136 | && !CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_CHECK_CONTROLPLANE)) |
892fedb6 | 137 | SET_FLAG(bfd_info->flags, BFD_FLAG_BFD_CBIT_ON); |
9beff0bd | 138 | |
02012bef RZ |
139 | /* Set all message arguments. */ |
140 | arg.family = peer->su.sa.sa_family; | |
141 | addrlen = arg.family == AF_INET ? sizeof(struct in_addr) | |
142 | : sizeof(struct in6_addr); | |
143 | ||
144 | if (arg.family == AF_INET) | |
145 | memcpy(&arg.dst, &peer->su.sin.sin_addr, addrlen); | |
146 | else | |
147 | memcpy(&arg.dst, &peer->su.sin6.sin6_addr, addrlen); | |
148 | ||
149 | if (peer->su_local) { | |
150 | if (arg.family == AF_INET) | |
151 | memcpy(&arg.src, &peer->su_local->sin.sin_addr, | |
152 | addrlen); | |
153 | else | |
154 | memcpy(&arg.src, &peer->su_local->sin6.sin6_addr, | |
155 | addrlen); | |
156 | } | |
157 | ||
158 | if (peer->nexthop.ifp) { | |
159 | arg.ifnamelen = strlen(peer->nexthop.ifp->name); | |
160 | strlcpy(arg.ifname, peer->nexthop.ifp->name, | |
161 | sizeof(arg.ifname)); | |
162 | } | |
163 | ||
164 | if (bfd_info->profile[0]) { | |
165 | arg.profilelen = strlen(bfd_info->profile); | |
166 | strlcpy(arg.profile, bfd_info->profile, sizeof(arg.profile)); | |
167 | } | |
168 | ||
169 | arg.set_flag = 1; | |
170 | arg.mhop = multihop; | |
171 | arg.ttl = peer->ttl; | |
172 | arg.vrf_id = vrf_id; | |
173 | arg.command = command; | |
174 | arg.bfd_info = bfd_info; | |
175 | arg.min_tx = bfd_info->desired_min_tx; | |
176 | arg.min_rx = bfd_info->required_min_rx; | |
177 | arg.detection_multiplier = bfd_info->detect_mult; | |
178 | arg.cbit = CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_CBIT_ON); | |
179 | ||
180 | /* Send message. */ | |
181 | zclient_bfd_command(zclient, &arg); | |
c43ed2e4 DS |
182 | } |
183 | ||
184 | /* | |
185 | * bgp_bfd_register_peer - register a peer with BFD through zebra | |
186 | * for monitoring the peer rechahability. | |
187 | */ | |
d62a17ae | 188 | void bgp_bfd_register_peer(struct peer *peer) |
c43ed2e4 | 189 | { |
d62a17ae | 190 | struct bfd_info *bfd_info; |
c43ed2e4 | 191 | |
d62a17ae | 192 | if (!peer->bfd_info) |
193 | return; | |
194 | bfd_info = (struct bfd_info *)peer->bfd_info; | |
c43ed2e4 | 195 | |
d62a17ae | 196 | /* Check if BFD is enabled and peer has already been registered with BFD |
197 | */ | |
198 | if (CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_REG)) | |
199 | return; | |
c43ed2e4 | 200 | |
d62a17ae | 201 | bgp_bfd_peer_sendmsg(peer, ZEBRA_BFD_DEST_REGISTER); |
c43ed2e4 DS |
202 | } |
203 | ||
204 | /** | |
205 | * bgp_bfd_deregister_peer - deregister a peer with BFD through zebra | |
206 | * for stopping the monitoring of the peer | |
207 | * rechahability. | |
208 | */ | |
d62a17ae | 209 | void bgp_bfd_deregister_peer(struct peer *peer) |
c43ed2e4 | 210 | { |
d62a17ae | 211 | struct bfd_info *bfd_info; |
c43ed2e4 | 212 | |
d62a17ae | 213 | if (!peer->bfd_info) |
214 | return; | |
215 | bfd_info = (struct bfd_info *)peer->bfd_info; | |
c43ed2e4 | 216 | |
d62a17ae | 217 | /* Check if BFD is eanbled and peer has not been registered */ |
218 | if (!CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_REG)) | |
219 | return; | |
c43ed2e4 | 220 | |
d62a17ae | 221 | bfd_info->status = BFD_STATUS_DOWN; |
222 | bfd_info->last_update = bgp_clock(); | |
5c940836 | 223 | |
d62a17ae | 224 | bgp_bfd_peer_sendmsg(peer, ZEBRA_BFD_DEST_DEREGISTER); |
c43ed2e4 DS |
225 | } |
226 | ||
227 | /* | |
228 | * bgp_bfd_update_peer - update peer with BFD with new BFD paramters | |
229 | * through zebra. | |
230 | */ | |
d62a17ae | 231 | static void bgp_bfd_update_peer(struct peer *peer) |
c43ed2e4 | 232 | { |
d62a17ae | 233 | struct bfd_info *bfd_info; |
c43ed2e4 | 234 | |
d62a17ae | 235 | if (!peer->bfd_info) |
236 | return; | |
237 | bfd_info = (struct bfd_info *)peer->bfd_info; | |
c43ed2e4 | 238 | |
d62a17ae | 239 | /* Check if the peer has been registered with BFD*/ |
240 | if (!CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_REG)) | |
241 | return; | |
c43ed2e4 | 242 | |
d62a17ae | 243 | bgp_bfd_peer_sendmsg(peer, ZEBRA_BFD_DEST_UPDATE); |
c43ed2e4 DS |
244 | } |
245 | ||
fe0c4ed7 PG |
246 | /** |
247 | * bgp_bfd_reset_peer - reinitialise bfd | |
248 | * ensures that bfd state machine is restarted | |
249 | * to be synced with remote bfd | |
250 | */ | |
251 | void bgp_bfd_reset_peer(struct peer *peer) | |
252 | { | |
fe0c4ed7 PG |
253 | if (!peer->bfd_info) |
254 | return; | |
fe0c4ed7 | 255 | |
fe0c4ed7 PG |
256 | bgp_bfd_peer_sendmsg(peer, ZEBRA_BFD_DEST_REGISTER); |
257 | } | |
258 | ||
986aa00f | 259 | /* |
260 | * bgp_bfd_update_type - update session type with BFD through zebra. | |
261 | */ | |
d62a17ae | 262 | static void bgp_bfd_update_type(struct peer *peer) |
986aa00f | 263 | { |
d62a17ae | 264 | struct bfd_info *bfd_info; |
265 | int multihop; | |
266 | ||
267 | if (!peer->bfd_info) | |
268 | return; | |
269 | bfd_info = (struct bfd_info *)peer->bfd_info; | |
270 | ||
271 | /* Check if the peer has been registered with BFD*/ | |
272 | if (!CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_REG)) | |
273 | return; | |
274 | ||
275 | if (bfd_info->type == BFD_TYPE_NOT_CONFIGURED) { | |
276 | multihop = bgp_bfd_is_peer_multihop(peer); | |
277 | if ((multihop | |
278 | && !CHECK_FLAG(bfd_info->flags, | |
279 | BFD_FLAG_BFD_TYPE_MULTIHOP)) | |
9d303b37 DL |
280 | || (!multihop && CHECK_FLAG(bfd_info->flags, |
281 | BFD_FLAG_BFD_TYPE_MULTIHOP))) { | |
d62a17ae | 282 | bgp_bfd_peer_sendmsg(peer, ZEBRA_BFD_DEST_DEREGISTER); |
283 | bgp_bfd_peer_sendmsg(peer, ZEBRA_BFD_DEST_REGISTER); | |
284 | } | |
285 | } else { | |
286 | if ((bfd_info->type == BFD_TYPE_MULTIHOP | |
287 | && !CHECK_FLAG(bfd_info->flags, | |
288 | BFD_FLAG_BFD_TYPE_MULTIHOP)) | |
289 | || (bfd_info->type == BFD_TYPE_SINGLEHOP | |
290 | && CHECK_FLAG(bfd_info->flags, | |
291 | BFD_FLAG_BFD_TYPE_MULTIHOP))) { | |
292 | bgp_bfd_peer_sendmsg(peer, ZEBRA_BFD_DEST_DEREGISTER); | |
293 | bgp_bfd_peer_sendmsg(peer, ZEBRA_BFD_DEST_REGISTER); | |
294 | } | |
295 | } | |
986aa00f | 296 | } |
297 | ||
c43ed2e4 DS |
298 | /* |
299 | * bgp_bfd_dest_replay - Replay all the peers that have BFD enabled | |
300 | * to zebra | |
301 | */ | |
121f9dee | 302 | static int bgp_bfd_dest_replay(ZAPI_CALLBACK_ARGS) |
c43ed2e4 | 303 | { |
d62a17ae | 304 | struct listnode *mnode, *node, *nnode; |
305 | struct bgp *bgp; | |
306 | struct peer *peer; | |
c43ed2e4 | 307 | |
d62a17ae | 308 | if (BGP_DEBUG(zebra, ZEBRA)) |
309 | zlog_debug("Zebra: BFD Dest replay request"); | |
c43ed2e4 | 310 | |
d62a17ae | 311 | /* Send the client registration */ |
0945d5ed | 312 | bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER, vrf_id); |
055c4dfc | 313 | |
d62a17ae | 314 | /* Replay the peer, if BFD is enabled in BGP */ |
c43ed2e4 | 315 | |
d62a17ae | 316 | for (ALL_LIST_ELEMENTS_RO(bm->bgp, mnode, bgp)) |
317 | for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { | |
318 | bgp_bfd_update_peer(peer); | |
319 | } | |
c43ed2e4 | 320 | |
d62a17ae | 321 | return 0; |
c43ed2e4 DS |
322 | } |
323 | ||
324 | /* | |
68fe91d6 | 325 | * bgp_bfd_peer_status_update - Update the BFD status if it has changed. Bring |
d62a17ae | 326 | * down the peer if the BFD session went down from |
327 | * * up. | |
68fe91d6 | 328 | */ |
9beff0bd PG |
329 | static void bgp_bfd_peer_status_update(struct peer *peer, int status, |
330 | int remote_cbit) | |
68fe91d6 | 331 | { |
d62a17ae | 332 | struct bfd_info *bfd_info; |
333 | int old_status; | |
68fe91d6 | 334 | |
d62a17ae | 335 | bfd_info = (struct bfd_info *)peer->bfd_info; |
68fe91d6 | 336 | |
d62a17ae | 337 | if (bfd_info->status == status) |
338 | return; | |
68fe91d6 | 339 | |
d62a17ae | 340 | old_status = bfd_info->status; |
7555dc61 S |
341 | BFD_SET_CLIENT_STATUS(bfd_info->status, status); |
342 | ||
d62a17ae | 343 | bfd_info->last_update = bgp_clock(); |
68fe91d6 | 344 | |
37bb7aca PG |
345 | if (status != old_status) { |
346 | if (BGP_DEBUG(neighbor_events, NEIGHBOR_EVENTS)) | |
347 | zlog_debug("[%s]: BFD %s", peer->host, | |
348 | bfd_get_status_str(status)); | |
349 | } | |
d62a17ae | 350 | if ((status == BFD_STATUS_DOWN) && (old_status == BFD_STATUS_UP)) { |
9beff0bd | 351 | if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_MODE) && |
dcffea69 | 352 | CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_CHECK_CONTROLPLANE) && |
9beff0bd | 353 | !remote_cbit) { |
3efd0893 | 354 | zlog_info("%s BFD DOWN message ignored in the process of graceful restart when C bit is cleared", |
9beff0bd PG |
355 | peer->host); |
356 | return; | |
357 | } | |
d62a17ae | 358 | peer->last_reset = PEER_DOWN_BFD_DOWN; |
359 | BGP_EVENT_ADD(peer, BGP_Stop); | |
360 | } | |
51728519 PG |
361 | if ((status == BFD_STATUS_UP) && (old_status == BFD_STATUS_DOWN) |
362 | && peer->status != Established) { | |
fc04a677 | 363 | if (!BGP_PEER_START_SUPPRESSED(peer)) { |
f8dcd38d | 364 | bgp_fsm_nht_update(peer, true); |
51728519 | 365 | BGP_EVENT_ADD(peer, BGP_Start); |
fc04a677 | 366 | } |
51728519 | 367 | } |
68fe91d6 | 368 | } |
369 | ||
370 | /* | |
371 | * bgp_bfd_dest_update - Find the peer for which the BFD status | |
372 | * has changed and bring down the peer | |
373 | * connectivity if the BFD session went down. | |
c43ed2e4 | 374 | */ |
121f9dee | 375 | static int bgp_bfd_dest_update(ZAPI_CALLBACK_ARGS) |
c43ed2e4 | 376 | { |
d62a17ae | 377 | struct interface *ifp; |
378 | struct prefix dp; | |
379 | struct prefix sp; | |
380 | int status; | |
9beff0bd | 381 | int remote_cbit; |
d62a17ae | 382 | |
9beff0bd PG |
383 | ifp = bfd_get_peer_info(zclient->ibuf, &dp, &sp, &status, |
384 | &remote_cbit, vrf_id); | |
d62a17ae | 385 | |
386 | if (BGP_DEBUG(zebra, ZEBRA)) { | |
137147c6 | 387 | struct vrf *vrf; |
d62a17ae | 388 | char buf[2][PREFIX2STR_BUFFER]; |
137147c6 DS |
389 | |
390 | vrf = vrf_lookup_by_id(vrf_id); | |
d62a17ae | 391 | prefix2str(&dp, buf[0], sizeof(buf[0])); |
392 | if (ifp) { | |
393 | zlog_debug( | |
137147c6 DS |
394 | "Zebra: vrf %s(%u) interface %s bfd destination %s %s %s", |
395 | VRF_LOGNAME(vrf), vrf_id, ifp->name, | |
396 | buf[0], bfd_get_status_str(status), | |
9beff0bd | 397 | remote_cbit ? "(cbit on)" : ""); |
d62a17ae | 398 | } else { |
399 | prefix2str(&sp, buf[1], sizeof(buf[1])); | |
400 | zlog_debug( | |
137147c6 DS |
401 | "Zebra: vrf %s(%u) source %s bfd destination %s %s %s", |
402 | VRF_LOGNAME(vrf), vrf_id, buf[1], buf[0], | |
9beff0bd PG |
403 | bfd_get_status_str(status), |
404 | remote_cbit ? "(cbit on)" : ""); | |
d62a17ae | 405 | } |
406 | } | |
407 | ||
408 | /* Bring the peer down if BFD is enabled in BGP */ | |
409 | { | |
410 | struct listnode *mnode, *node, *nnode; | |
411 | struct bgp *bgp; | |
412 | struct peer *peer; | |
413 | ||
414 | for (ALL_LIST_ELEMENTS_RO(bm->bgp, mnode, bgp)) | |
415 | for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { | |
416 | if (!peer->bfd_info) | |
417 | continue; | |
418 | ||
419 | if ((dp.family == AF_INET) | |
420 | && (peer->su.sa.sa_family == AF_INET)) { | |
421 | if (dp.u.prefix4.s_addr | |
422 | != peer->su.sin.sin_addr.s_addr) | |
423 | continue; | |
424 | } else if ((dp.family == AF_INET6) | |
425 | && (peer->su.sa.sa_family | |
426 | == AF_INET6)) { | |
427 | if (memcmp(&dp.u.prefix6, | |
428 | &peer->su.sin6.sin6_addr, | |
429 | sizeof(struct in6_addr))) | |
430 | continue; | |
431 | } else | |
432 | continue; | |
433 | ||
434 | if (ifp && (ifp == peer->nexthop.ifp)) { | |
435 | bgp_bfd_peer_status_update(peer, | |
9beff0bd PG |
436 | status, |
437 | remote_cbit); | |
d62a17ae | 438 | } else { |
439 | if (!peer->su_local) | |
440 | continue; | |
441 | ||
442 | if ((sp.family == AF_INET) | |
443 | && (peer->su_local->sa.sa_family | |
444 | == AF_INET)) { | |
445 | if (sp.u.prefix4.s_addr | |
446 | != peer->su_local->sin | |
447 | .sin_addr.s_addr) | |
448 | continue; | |
449 | } else if ((sp.family == AF_INET6) | |
450 | && (peer->su_local->sa | |
451 | .sa_family | |
452 | == AF_INET6)) { | |
453 | if (memcmp(&sp.u.prefix6, | |
454 | &peer->su_local->sin6 | |
455 | .sin6_addr, | |
456 | sizeof(struct | |
457 | in6_addr))) | |
458 | continue; | |
459 | } else | |
460 | continue; | |
461 | ||
462 | if ((vrf_id != VRF_DEFAULT) | |
463 | && (peer->bgp->vrf_id != vrf_id)) | |
464 | continue; | |
465 | ||
466 | bgp_bfd_peer_status_update(peer, | |
9beff0bd PG |
467 | status, |
468 | remote_cbit); | |
d62a17ae | 469 | } |
470 | } | |
471 | } | |
472 | ||
473 | return 0; | |
c43ed2e4 DS |
474 | } |
475 | ||
476 | /* | |
477 | * bgp_bfd_peer_param_set - Set the configured BFD paramter values for peer. | |
478 | */ | |
d7c0a89a QY |
479 | static int bgp_bfd_peer_param_set(struct peer *peer, uint32_t min_rx, |
480 | uint32_t min_tx, uint8_t detect_mult, | |
d62a17ae | 481 | int defaults) |
c43ed2e4 | 482 | { |
68286f96 | 483 | struct bfd_info *bi; |
d62a17ae | 484 | struct peer_group *group; |
485 | struct listnode *node, *nnode; | |
486 | int command = 0; | |
487 | ||
488 | bfd_set_param((struct bfd_info **)&(peer->bfd_info), min_rx, min_tx, | |
4affdba7 | 489 | detect_mult, NULL, defaults, &command); |
d62a17ae | 490 | |
68286f96 RZ |
491 | /* This command overrides profile if it was previously applied. */ |
492 | bi = peer->bfd_info; | |
493 | bi->profile[0] = 0; | |
494 | ||
d62a17ae | 495 | if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { |
496 | group = peer->group; | |
497 | for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { | |
498 | command = 0; | |
499 | bfd_set_param((struct bfd_info **)&(peer->bfd_info), | |
4affdba7 G |
500 | min_rx, min_tx, detect_mult, NULL, |
501 | defaults, &command); | |
d62a17ae | 502 | |
68286f96 RZ |
503 | /* |
504 | * This command overrides profile if it was previously | |
505 | * applied. | |
506 | */ | |
507 | bi = peer->bfd_info; | |
508 | bi->profile[0] = 0; | |
509 | ||
d62a17ae | 510 | if ((peer->status == Established) |
511 | && (command == ZEBRA_BFD_DEST_REGISTER)) | |
512 | bgp_bfd_register_peer(peer); | |
513 | else if (command == ZEBRA_BFD_DEST_UPDATE) | |
514 | bgp_bfd_update_peer(peer); | |
515 | } | |
516 | } else { | |
517 | if ((peer->status == Established) | |
518 | && (command == ZEBRA_BFD_DEST_REGISTER)) | |
519 | bgp_bfd_register_peer(peer); | |
520 | else if (command == ZEBRA_BFD_DEST_UPDATE) | |
521 | bgp_bfd_update_peer(peer); | |
522 | } | |
523 | return 0; | |
c43ed2e4 DS |
524 | } |
525 | ||
526 | /* | |
d62a17ae | 527 | * bgp_bfd_peer_param_unset - Delete the configured BFD paramter values for |
528 | * peer. | |
c43ed2e4 | 529 | */ |
d62a17ae | 530 | static int bgp_bfd_peer_param_unset(struct peer *peer) |
c43ed2e4 | 531 | { |
d62a17ae | 532 | struct peer_group *group; |
533 | struct listnode *node, *nnode; | |
534 | ||
535 | if (!peer->bfd_info) | |
536 | return 0; | |
537 | ||
538 | if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { | |
539 | bfd_info_free(&(peer->bfd_info)); | |
540 | group = peer->group; | |
541 | for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { | |
542 | bgp_bfd_deregister_peer(peer); | |
543 | bfd_info_free(&(peer->bfd_info)); | |
544 | } | |
545 | } else { | |
546 | bgp_bfd_deregister_peer(peer); | |
547 | bfd_info_free(&(peer->bfd_info)); | |
548 | } | |
549 | return 0; | |
c43ed2e4 DS |
550 | } |
551 | ||
986aa00f | 552 | /* |
d62a17ae | 553 | * bgp_bfd_peer_param_type_set - set the BFD session type (multihop or |
554 | * singlehop) | |
986aa00f | 555 | */ |
d62a17ae | 556 | static int bgp_bfd_peer_param_type_set(struct peer *peer, |
557 | enum bfd_sess_type type) | |
986aa00f | 558 | { |
d62a17ae | 559 | struct peer_group *group; |
560 | struct listnode *node, *nnode; | |
561 | int command = 0; | |
562 | struct bfd_info *bfd_info; | |
563 | ||
564 | if (!peer->bfd_info) | |
565 | bfd_set_param((struct bfd_info **)&(peer->bfd_info), | |
566 | BFD_DEF_MIN_RX, BFD_DEF_MIN_TX, | |
4affdba7 | 567 | BFD_DEF_DETECT_MULT, NULL, 1, &command); |
d62a17ae | 568 | |
569 | bfd_info = (struct bfd_info *)peer->bfd_info; | |
570 | bfd_info->type = type; | |
571 | ||
572 | if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { | |
573 | group = peer->group; | |
574 | for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { | |
575 | command = 0; | |
576 | if (!peer->bfd_info) | |
577 | bfd_set_param( | |
578 | (struct bfd_info **)&(peer->bfd_info), | |
579 | BFD_DEF_MIN_RX, BFD_DEF_MIN_TX, | |
4affdba7 | 580 | BFD_DEF_DETECT_MULT, NULL, 1, &command); |
d62a17ae | 581 | |
582 | bfd_info = (struct bfd_info *)peer->bfd_info; | |
583 | bfd_info->type = type; | |
584 | ||
585 | if (peer->status == Established) { | |
586 | if (command == ZEBRA_BFD_DEST_REGISTER) | |
587 | bgp_bfd_register_peer(peer); | |
588 | else | |
589 | bgp_bfd_update_type(peer); | |
590 | } | |
591 | } | |
592 | } else { | |
593 | if (peer->status == Established) { | |
594 | if (command == ZEBRA_BFD_DEST_REGISTER) | |
595 | bgp_bfd_register_peer(peer); | |
596 | else | |
597 | bgp_bfd_update_type(peer); | |
598 | } | |
599 | } | |
600 | ||
601 | return 0; | |
986aa00f | 602 | } |
603 | ||
02012bef RZ |
604 | /** |
605 | * Set peer BFD profile configuration. | |
606 | */ | |
607 | static int bgp_bfd_peer_set_profile(struct peer *peer, const char *profile) | |
608 | { | |
609 | struct peer_group *group; | |
610 | struct listnode *node, *nnode; | |
611 | int command = 0; | |
612 | struct bfd_info *bfd_info; | |
613 | ||
614 | bfd_set_param((struct bfd_info **)&(peer->bfd_info), BFD_DEF_MIN_RX, | |
4affdba7 | 615 | BFD_DEF_MIN_TX, BFD_DEF_DETECT_MULT, NULL, 1, &command); |
02012bef RZ |
616 | |
617 | bfd_info = (struct bfd_info *)peer->bfd_info; | |
618 | ||
619 | /* If profile was specified, then copy string. */ | |
620 | if (profile) | |
621 | strlcpy(bfd_info->profile, profile, sizeof(bfd_info->profile)); | |
622 | else /* Otherwise just initialize it empty. */ | |
623 | bfd_info->profile[0] = 0; | |
624 | ||
625 | if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { | |
626 | group = peer->group; | |
627 | for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { | |
628 | command = 0; | |
629 | bfd_set_param((struct bfd_info **)&(peer->bfd_info), | |
630 | BFD_DEF_MIN_RX, BFD_DEF_MIN_TX, | |
4affdba7 | 631 | BFD_DEF_DETECT_MULT, NULL, 1, &command); |
02012bef RZ |
632 | |
633 | bfd_info = (struct bfd_info *)peer->bfd_info; | |
634 | ||
635 | /* If profile was specified, then copy string. */ | |
636 | if (profile) | |
637 | strlcpy(bfd_info->profile, profile, | |
638 | sizeof(bfd_info->profile)); | |
639 | else /* Otherwise just initialize it empty. */ | |
640 | bfd_info->profile[0] = 0; | |
641 | ||
642 | if (peer->status == Established | |
643 | && command == ZEBRA_BFD_DEST_REGISTER) | |
644 | bgp_bfd_register_peer(peer); | |
645 | else if (command == ZEBRA_BFD_DEST_UPDATE) | |
646 | bgp_bfd_update_peer(peer); | |
647 | } | |
648 | } else { | |
649 | if (peer->status == Established | |
650 | && command == ZEBRA_BFD_DEST_REGISTER) | |
651 | bgp_bfd_register_peer(peer); | |
652 | else if (command == ZEBRA_BFD_DEST_UPDATE) | |
653 | bgp_bfd_update_peer(peer); | |
654 | } | |
655 | ||
656 | return 0; | |
657 | } | |
658 | ||
c43ed2e4 DS |
659 | /* |
660 | * bgp_bfd_peer_config_write - Write the peer BFD configuration. | |
661 | */ | |
d62a17ae | 662 | void bgp_bfd_peer_config_write(struct vty *vty, struct peer *peer, char *addr) |
c43ed2e4 | 663 | { |
d62a17ae | 664 | struct bfd_info *bfd_info; |
c43ed2e4 | 665 | |
d62a17ae | 666 | if (!peer->bfd_info) |
667 | return; | |
7f342629 | 668 | |
d62a17ae | 669 | bfd_info = (struct bfd_info *)peer->bfd_info; |
c43ed2e4 | 670 | |
d62a17ae | 671 | if (CHECK_FLAG(bfd_info->flags, BFD_FLAG_PARAM_CFG)) |
a0841732 RZ |
672 | #if HAVE_BFDD > 0 |
673 | vty_out(vty, " neighbor %s bfd\n", addr); | |
674 | #else | |
d62a17ae | 675 | vty_out(vty, " neighbor %s bfd %d %d %d\n", addr, |
676 | bfd_info->detect_mult, bfd_info->required_min_rx, | |
677 | bfd_info->desired_min_tx); | |
a0841732 | 678 | #endif /* HAVE_BFDD */ |
986aa00f | 679 | |
d62a17ae | 680 | if (bfd_info->type != BFD_TYPE_NOT_CONFIGURED) |
681 | vty_out(vty, " neighbor %s bfd %s\n", addr, | |
682 | (bfd_info->type == BFD_TYPE_MULTIHOP) ? "multihop" | |
683 | : "singlehop"); | |
986aa00f | 684 | |
d62a17ae | 685 | if (!CHECK_FLAG(bfd_info->flags, BFD_FLAG_PARAM_CFG) |
02012bef RZ |
686 | && (bfd_info->type == BFD_TYPE_NOT_CONFIGURED)) { |
687 | vty_out(vty, " neighbor %s bfd", addr); | |
688 | if (bfd_info->profile[0]) | |
689 | vty_out(vty, " profile %s", bfd_info->profile); | |
690 | vty_out(vty, "\n"); | |
691 | } | |
dcffea69 PG |
692 | |
693 | if (CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_CHECK_CONTROLPLANE)) | |
694 | vty_out(vty, " neighbor %s bfd check-control-plane-failure\n", addr); | |
c43ed2e4 DS |
695 | } |
696 | ||
697 | /* | |
698 | * bgp_bfd_show_info - Show the peer BFD information. | |
699 | */ | |
9f049418 | 700 | void bgp_bfd_show_info(struct vty *vty, struct peer *peer, bool use_json, |
d62a17ae | 701 | json_object *json_neigh) |
c43ed2e4 | 702 | { |
d62a17ae | 703 | bfd_show_info(vty, (struct bfd_info *)peer->bfd_info, |
704 | bgp_bfd_is_peer_multihop(peer), 0, use_json, json_neigh); | |
c43ed2e4 DS |
705 | } |
706 | ||
707 | DEFUN (neighbor_bfd, | |
708 | neighbor_bfd_cmd, | |
9ccf14f7 | 709 | "neighbor <A.B.C.D|X:X::X:X|WORD> bfd", |
c43ed2e4 DS |
710 | NEIGHBOR_STR |
711 | NEIGHBOR_ADDR_STR2 | |
712 | "Enables BFD support\n") | |
713 | { | |
d62a17ae | 714 | int idx_peer = 1; |
715 | struct peer *peer; | |
716 | int ret; | |
c43ed2e4 | 717 | |
d62a17ae | 718 | peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg); |
719 | if (!peer) | |
720 | return CMD_WARNING_CONFIG_FAILED; | |
c43ed2e4 | 721 | |
d62a17ae | 722 | ret = bgp_bfd_peer_param_set(peer, BFD_DEF_MIN_RX, BFD_DEF_MIN_TX, |
723 | BFD_DEF_DETECT_MULT, 1); | |
724 | if (ret != 0) | |
725 | return bgp_vty_return(vty, ret); | |
c43ed2e4 | 726 | |
d62a17ae | 727 | return CMD_SUCCESS; |
c43ed2e4 DS |
728 | } |
729 | ||
64dc4b2d RZ |
730 | #if HAVE_BFDD > 0 |
731 | DEFUN_HIDDEN( | |
732 | #else | |
733 | DEFUN( | |
734 | #endif /* HAVE_BFDD */ | |
735 | neighbor_bfd_param, | |
c43ed2e4 | 736 | neighbor_bfd_param_cmd, |
9ccf14f7 | 737 | "neighbor <A.B.C.D|X:X::X:X|WORD> bfd (2-255) (50-60000) (50-60000)", |
c43ed2e4 DS |
738 | NEIGHBOR_STR |
739 | NEIGHBOR_ADDR_STR2 | |
740 | "Enables BFD support\n" | |
741 | "Detect Multiplier\n" | |
742 | "Required min receive interval\n" | |
743 | "Desired min transmit interval\n") | |
744 | { | |
d62a17ae | 745 | int idx_peer = 1; |
746 | int idx_number_1 = 3; | |
747 | int idx_number_2 = 4; | |
748 | int idx_number_3 = 5; | |
749 | struct peer *peer; | |
d7c0a89a QY |
750 | uint32_t rx_val; |
751 | uint32_t tx_val; | |
752 | uint8_t dm_val; | |
d62a17ae | 753 | int ret; |
754 | ||
755 | peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg); | |
756 | if (!peer) | |
757 | return CMD_WARNING_CONFIG_FAILED; | |
758 | ||
759 | if ((ret = bfd_validate_param( | |
760 | vty, argv[idx_number_1]->arg, argv[idx_number_2]->arg, | |
761 | argv[idx_number_3]->arg, &dm_val, &rx_val, &tx_val)) | |
762 | != CMD_SUCCESS) | |
763 | return ret; | |
764 | ||
765 | ret = bgp_bfd_peer_param_set(peer, rx_val, tx_val, dm_val, 0); | |
766 | if (ret != 0) | |
767 | return bgp_vty_return(vty, ret); | |
768 | ||
769 | return CMD_SUCCESS; | |
c43ed2e4 DS |
770 | } |
771 | ||
986aa00f | 772 | DEFUN_HIDDEN (neighbor_bfd_type, |
773 | neighbor_bfd_type_cmd, | |
e83a9414 | 774 | "neighbor <A.B.C.D|X:X::X:X|WORD> bfd <multihop|singlehop>", |
986aa00f | 775 | NEIGHBOR_STR |
776 | NEIGHBOR_ADDR_STR2 | |
777 | "Enables BFD support\n" | |
d7fa34c1 QY |
778 | "Multihop session\n" |
779 | "Single hop session\n") | |
986aa00f | 780 | { |
d62a17ae | 781 | int idx_peer = 1; |
782 | int idx_hop = 3; | |
783 | struct peer *peer; | |
784 | enum bfd_sess_type type; | |
785 | int ret; | |
786 | ||
787 | peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg); | |
788 | if (!peer) | |
789 | return CMD_WARNING_CONFIG_FAILED; | |
790 | ||
791 | if (strmatch(argv[idx_hop]->text, "singlehop")) | |
792 | type = BFD_TYPE_SINGLEHOP; | |
793 | else if (strmatch(argv[idx_hop]->text, "multihop")) | |
794 | type = BFD_TYPE_MULTIHOP; | |
795 | else | |
796 | return CMD_WARNING_CONFIG_FAILED; | |
797 | ||
798 | ret = bgp_bfd_peer_param_type_set(peer, type); | |
799 | if (ret != 0) | |
800 | return bgp_vty_return(vty, ret); | |
801 | ||
802 | return CMD_SUCCESS; | |
986aa00f | 803 | } |
804 | ||
dcffea69 PG |
805 | static int bgp_bfd_set_check_controlplane_failure_peer(struct vty *vty, struct peer *peer, |
806 | const char *no) | |
807 | { | |
808 | struct bfd_info *bfd_info; | |
809 | ||
810 | if (!peer->bfd_info) { | |
811 | if (no) | |
812 | return CMD_SUCCESS; | |
813 | vty_out(vty, "%% Specify bfd command first\n"); | |
814 | return CMD_WARNING_CONFIG_FAILED; | |
815 | } | |
816 | bfd_info = (struct bfd_info *)peer->bfd_info; | |
817 | if (!no) { | |
818 | if (!CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_CHECK_CONTROLPLANE)) { | |
819 | SET_FLAG(bfd_info->flags, BFD_FLAG_BFD_CHECK_CONTROLPLANE); | |
820 | bgp_bfd_update_peer(peer); | |
821 | } | |
822 | } else { | |
823 | if (CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_CHECK_CONTROLPLANE)) { | |
824 | UNSET_FLAG(bfd_info->flags, BFD_FLAG_BFD_CHECK_CONTROLPLANE); | |
825 | bgp_bfd_update_peer(peer); | |
826 | } | |
827 | } | |
828 | return CMD_SUCCESS; | |
829 | } | |
830 | ||
831 | ||
832 | DEFUN (neighbor_bfd_check_controlplane_failure, | |
833 | neighbor_bfd_check_controlplane_failure_cmd, | |
834 | "[no] neighbor <A.B.C.D|X:X::X:X|WORD> bfd check-control-plane-failure", | |
835 | NO_STR | |
836 | NEIGHBOR_STR | |
837 | NEIGHBOR_ADDR_STR2 | |
838 | "BFD support\n" | |
839 | "Link dataplane status with BGP controlplane\n") | |
840 | { | |
841 | const char *no = strmatch(argv[0]->text, "no") ? "no" : NULL; | |
842 | int idx_peer = 0; | |
843 | struct peer *peer; | |
844 | struct peer_group *group; | |
845 | struct listnode *node, *nnode; | |
846 | int ret = CMD_SUCCESS; | |
847 | ||
848 | if (no) | |
849 | idx_peer = 2; | |
850 | else | |
851 | idx_peer = 1; | |
852 | peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg); | |
853 | if (!peer) { | |
854 | vty_out(vty, "%% Specify remote-as or peer-group commands first\n"); | |
855 | return CMD_WARNING_CONFIG_FAILED; | |
856 | } | |
857 | if (!peer->bfd_info) { | |
858 | if (no) | |
859 | return CMD_SUCCESS; | |
860 | vty_out(vty, "%% Specify bfd command first\n"); | |
861 | return CMD_WARNING_CONFIG_FAILED; | |
862 | } | |
863 | if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { | |
864 | group = peer->group; | |
865 | for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) | |
866 | ret = bgp_bfd_set_check_controlplane_failure_peer(vty, peer, no); | |
867 | } else | |
868 | ret = bgp_bfd_set_check_controlplane_failure_peer(vty, peer, no); | |
869 | return ret; | |
870 | } | |
871 | ||
c43ed2e4 DS |
872 | DEFUN (no_neighbor_bfd, |
873 | no_neighbor_bfd_cmd, | |
64dc4b2d RZ |
874 | #if HAVE_BFDD > 0 |
875 | "no neighbor <A.B.C.D|X:X::X:X|WORD> bfd", | |
876 | #else | |
5bf15956 | 877 | "no neighbor <A.B.C.D|X:X::X:X|WORD> bfd [(2-255) (50-60000) (50-60000)]", |
64dc4b2d | 878 | #endif /* HAVE_BFDD */ |
c43ed2e4 DS |
879 | NO_STR |
880 | NEIGHBOR_STR | |
881 | NEIGHBOR_ADDR_STR2 | |
5bf15956 | 882 | "Disables BFD support\n" |
64dc4b2d | 883 | #if HAVE_BFDD == 0 |
5bf15956 DW |
884 | "Detect Multiplier\n" |
885 | "Required min receive interval\n" | |
64dc4b2d RZ |
886 | "Desired min transmit interval\n" |
887 | #endif /* !HAVE_BFDD */ | |
888 | ) | |
c43ed2e4 | 889 | { |
d62a17ae | 890 | int idx_peer = 2; |
891 | struct peer *peer; | |
892 | int ret; | |
c43ed2e4 | 893 | |
d62a17ae | 894 | peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg); |
895 | if (!peer) | |
896 | return CMD_WARNING_CONFIG_FAILED; | |
c43ed2e4 | 897 | |
d62a17ae | 898 | ret = bgp_bfd_peer_param_unset(peer); |
899 | if (ret != 0) | |
900 | return bgp_vty_return(vty, ret); | |
c43ed2e4 | 901 | |
d62a17ae | 902 | return CMD_SUCCESS; |
c43ed2e4 DS |
903 | } |
904 | ||
813d4307 | 905 | |
986aa00f | 906 | DEFUN_HIDDEN (no_neighbor_bfd_type, |
907 | no_neighbor_bfd_type_cmd, | |
e83a9414 | 908 | "no neighbor <A.B.C.D|X:X::X:X|WORD> bfd <multihop|singlehop>", |
986aa00f | 909 | NO_STR |
910 | NEIGHBOR_STR | |
911 | NEIGHBOR_ADDR_STR2 | |
912 | "Disables BFD support\n" | |
3a2d747c QY |
913 | "Multihop session\n" |
914 | "Singlehop session\n") | |
986aa00f | 915 | { |
d62a17ae | 916 | int idx_peer = 2; |
917 | struct peer *peer; | |
918 | int ret; | |
986aa00f | 919 | |
d62a17ae | 920 | peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg); |
921 | if (!peer) | |
922 | return CMD_WARNING_CONFIG_FAILED; | |
986aa00f | 923 | |
d62a17ae | 924 | if (!peer->bfd_info) |
925 | return 0; | |
986aa00f | 926 | |
d62a17ae | 927 | ret = bgp_bfd_peer_param_type_set(peer, BFD_TYPE_NOT_CONFIGURED); |
928 | if (ret != 0) | |
929 | return bgp_vty_return(vty, ret); | |
986aa00f | 930 | |
d62a17ae | 931 | return CMD_SUCCESS; |
986aa00f | 932 | } |
933 | ||
02012bef RZ |
934 | #if HAVE_BFDD > 0 |
935 | DEFUN(neighbor_bfd_profile, neighbor_bfd_profile_cmd, | |
936 | "neighbor <A.B.C.D|X:X::X:X|WORD> bfd profile BFDPROF", | |
937 | NEIGHBOR_STR | |
938 | NEIGHBOR_ADDR_STR2 | |
939 | "BFD integration\n" | |
940 | BFD_PROFILE_STR | |
941 | BFD_PROFILE_NAME_STR) | |
942 | { | |
943 | int idx_peer = 1, idx_prof = 4; | |
944 | struct peer *peer; | |
945 | int ret; | |
946 | ||
947 | peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg); | |
948 | if (!peer) | |
949 | return CMD_WARNING_CONFIG_FAILED; | |
950 | ||
951 | ret = bgp_bfd_peer_set_profile(peer, argv[idx_prof]->arg); | |
952 | if (ret != 0) | |
953 | return bgp_vty_return(vty, ret); | |
954 | ||
955 | return CMD_SUCCESS; | |
956 | } | |
957 | ||
958 | DEFUN(no_neighbor_bfd_profile, no_neighbor_bfd_profile_cmd, | |
959 | "no neighbor <A.B.C.D|X:X::X:X|WORD> bfd profile [BFDPROF]", | |
960 | NO_STR | |
961 | NEIGHBOR_STR | |
962 | NEIGHBOR_ADDR_STR2 | |
963 | "BFD integration\n" | |
964 | BFD_PROFILE_STR | |
965 | BFD_PROFILE_NAME_STR) | |
966 | { | |
967 | int idx_peer = 2; | |
968 | struct peer *peer; | |
969 | int ret; | |
970 | ||
971 | peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg); | |
972 | if (!peer) | |
973 | return CMD_WARNING_CONFIG_FAILED; | |
974 | ||
975 | if (!peer->bfd_info) | |
976 | return 0; | |
977 | ||
978 | ret = bgp_bfd_peer_set_profile(peer, NULL); | |
979 | if (ret != 0) | |
980 | return bgp_vty_return(vty, ret); | |
981 | ||
982 | return CMD_SUCCESS; | |
983 | } | |
984 | #endif /* HAVE_BFDD */ | |
985 | ||
d62a17ae | 986 | void bgp_bfd_init(void) |
c43ed2e4 | 987 | { |
d62a17ae | 988 | bfd_gbl_init(); |
989 | ||
990 | /* Initialize BFD client functions */ | |
991 | zclient->interface_bfd_dest_update = bgp_bfd_dest_update; | |
992 | zclient->bfd_dest_replay = bgp_bfd_dest_replay; | |
993 | ||
994 | /* "neighbor bfd" commands. */ | |
995 | install_element(BGP_NODE, &neighbor_bfd_cmd); | |
996 | install_element(BGP_NODE, &neighbor_bfd_param_cmd); | |
997 | install_element(BGP_NODE, &neighbor_bfd_type_cmd); | |
dcffea69 | 998 | install_element(BGP_NODE, &neighbor_bfd_check_controlplane_failure_cmd); |
d62a17ae | 999 | install_element(BGP_NODE, &no_neighbor_bfd_cmd); |
1000 | install_element(BGP_NODE, &no_neighbor_bfd_type_cmd); | |
02012bef RZ |
1001 | |
1002 | #if HAVE_BFDD > 0 | |
1003 | install_element(BGP_NODE, &neighbor_bfd_profile_cmd); | |
1004 | install_element(BGP_NODE, &no_neighbor_bfd_profile_cmd); | |
1005 | #endif /* HAVE_BFDD */ | |
c43ed2e4 | 1006 | } |