]>
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 | * | |
18 | * You should have received a copy of the GNU General Public License | |
19 | * along with GNU Zebra; see the file COPYING. If not, write to the Free | |
20 | * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | |
21 | * 02111-1307, USA. | |
22 | */ | |
23 | ||
24 | #include <zebra.h> | |
25 | ||
26 | #include "command.h" | |
27 | #include "linklist.h" | |
28 | #include "memory.h" | |
29 | #include "prefix.h" | |
30 | #include "thread.h" | |
31 | #include "buffer.h" | |
32 | #include "stream.h" | |
33 | #include "zclient.h" | |
34 | #include "vty.h" | |
7f342629 | 35 | #include "bfd.h" |
856ca177 | 36 | #include "lib/json.h" |
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 DS |
45 | /* |
46 | * bgp_bfd_peer_group2peer_copy - Copy the BFD information from peer group template | |
47 | * to peer. | |
48 | */ | |
49 | void | |
50 | bgp_bfd_peer_group2peer_copy(struct peer *conf, struct peer *peer) | |
51 | { | |
7f342629 DS |
52 | struct bfd_info *bfd_info; |
53 | struct bfd_info *conf_bfd_info; | |
54 | ||
55 | if (!conf->bfd_info) | |
56 | return; | |
57 | ||
58 | conf_bfd_info = (struct bfd_info *)conf->bfd_info; | |
59 | if (!peer->bfd_info) | |
60 | peer->bfd_info = bfd_info_create(); | |
c43ed2e4 | 61 | |
7f342629 | 62 | bfd_info = (struct bfd_info *)peer->bfd_info; |
c43ed2e4 DS |
63 | |
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 | } | |
69 | ||
70 | /* | |
71 | * bgp_bfd_is_peer_multihop - returns whether BFD peer is multi-hop or single hop. | |
72 | */ | |
73 | static int | |
74 | bgp_bfd_is_peer_multihop(struct peer *peer) | |
75 | { | |
76 | if((peer->sort == BGP_PEER_IBGP) || is_ebgp_multihop_configured(peer)) | |
77 | return 1; | |
78 | else | |
79 | return 0; | |
80 | } | |
81 | ||
82 | /* | |
7f342629 DS |
83 | * bgp_bfd_peer_sendmsg - Format and send a Peer register/Unregister |
84 | * command to Zebra to be forwarded to BFD | |
c43ed2e4 DS |
85 | */ |
86 | static void | |
7f342629 | 87 | bgp_bfd_peer_sendmsg (struct peer *peer, int command) |
c43ed2e4 | 88 | { |
7f342629 DS |
89 | struct bfd_info *bfd_info; |
90 | ||
91 | bfd_info = (struct bfd_info *)peer->bfd_info; | |
92 | ||
93 | if (peer->su.sa.sa_family == AF_INET) | |
94 | bfd_peer_sendmsg (zclient, bfd_info, AF_INET, | |
95 | &peer->su.sin.sin_addr, | |
96 | (peer->su_local) ? &peer->su_local->sin.sin_addr : NULL, | |
97 | (peer->nexthop.ifp) ? peer->nexthop.ifp->name : NULL, | |
98 | peer->ttl, bgp_bfd_is_peer_multihop(peer), command, 1); | |
99 | else if (peer->su.sa.sa_family == AF_INET6) | |
100 | bfd_peer_sendmsg (zclient, bfd_info, AF_INET6, | |
101 | &peer->su.sin6.sin6_addr, | |
102 | (peer->su_local) ? &peer->su_local->sin6.sin6_addr : NULL, | |
103 | (peer->nexthop.ifp) ? peer->nexthop.ifp->name : NULL, | |
104 | peer->ttl, bgp_bfd_is_peer_multihop(peer), command, 1); | |
c43ed2e4 DS |
105 | } |
106 | ||
107 | /* | |
108 | * bgp_bfd_register_peer - register a peer with BFD through zebra | |
109 | * for monitoring the peer rechahability. | |
110 | */ | |
111 | void | |
112 | bgp_bfd_register_peer (struct peer *peer) | |
113 | { | |
7f342629 | 114 | struct bfd_info *bfd_info; |
c43ed2e4 | 115 | |
7f342629 DS |
116 | if (!peer->bfd_info) |
117 | return; | |
118 | bfd_info = (struct bfd_info *)peer->bfd_info; | |
c43ed2e4 DS |
119 | |
120 | /* Check if BFD is enabled and peer has already been registered with BFD */ | |
7f342629 | 121 | if (CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_REG)) |
c43ed2e4 DS |
122 | return; |
123 | ||
7f342629 | 124 | bgp_bfd_peer_sendmsg(peer, ZEBRA_BFD_DEST_REGISTER); |
c43ed2e4 DS |
125 | } |
126 | ||
127 | /** | |
128 | * bgp_bfd_deregister_peer - deregister a peer with BFD through zebra | |
129 | * for stopping the monitoring of the peer | |
130 | * rechahability. | |
131 | */ | |
132 | void | |
133 | bgp_bfd_deregister_peer (struct peer *peer) | |
134 | { | |
7f342629 | 135 | struct bfd_info *bfd_info; |
c43ed2e4 | 136 | |
7f342629 DS |
137 | if (!peer->bfd_info) |
138 | return; | |
139 | bfd_info = (struct bfd_info *)peer->bfd_info; | |
c43ed2e4 DS |
140 | |
141 | /* Check if BFD is eanbled and peer has not been registered */ | |
7f342629 | 142 | if (!CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_REG)) |
c43ed2e4 DS |
143 | return; |
144 | ||
7f342629 | 145 | bgp_bfd_peer_sendmsg(peer, ZEBRA_BFD_DEST_DEREGISTER); |
c43ed2e4 DS |
146 | } |
147 | ||
148 | /* | |
149 | * bgp_bfd_update_peer - update peer with BFD with new BFD paramters | |
150 | * through zebra. | |
151 | */ | |
7f342629 | 152 | static void |
c43ed2e4 DS |
153 | bgp_bfd_update_peer (struct peer *peer) |
154 | { | |
7f342629 | 155 | struct bfd_info *bfd_info; |
c43ed2e4 | 156 | |
7f342629 DS |
157 | if (!peer->bfd_info) |
158 | return; | |
159 | bfd_info = (struct bfd_info *)peer->bfd_info; | |
c43ed2e4 DS |
160 | |
161 | /* Check if the peer has been registered with BFD*/ | |
7f342629 | 162 | if (!CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_REG)) |
c43ed2e4 DS |
163 | return; |
164 | ||
7f342629 | 165 | bgp_bfd_peer_sendmsg(peer, ZEBRA_BFD_DEST_UPDATE); |
c43ed2e4 DS |
166 | } |
167 | ||
168 | /* | |
169 | * bgp_bfd_dest_replay - Replay all the peers that have BFD enabled | |
170 | * to zebra | |
171 | */ | |
7f342629 | 172 | static int |
c43ed2e4 DS |
173 | bgp_bfd_dest_replay (int command, struct zclient *client, zebra_size_t length) |
174 | { | |
175 | struct listnode *mnode, *node, *nnode; | |
176 | struct bgp *bgp; | |
177 | struct peer *peer; | |
178 | ||
179 | if (BGP_DEBUG (zebra, ZEBRA)) | |
180 | zlog_debug("Zebra: BFD Dest replay request"); | |
181 | ||
182 | /* Replay the peer, if BFD is enabled in BGP */ | |
183 | ||
184 | for (ALL_LIST_ELEMENTS_RO (bm->bgp, mnode, bgp)) | |
185 | for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) | |
186 | { | |
c43ed2e4 DS |
187 | bgp_bfd_update_peer(peer); |
188 | } | |
189 | ||
190 | return 0; | |
191 | } | |
192 | ||
193 | /* | |
194 | * bgp_interface_bfd_dest_down - Find the peer for which the BFD status | |
195 | * has changed and bring down the peer | |
196 | * connectivity. | |
197 | */ | |
7f342629 | 198 | static int |
c43ed2e4 DS |
199 | bgp_interface_bfd_dest_down (int command, struct zclient *zclient, |
200 | zebra_size_t length) | |
201 | { | |
202 | struct interface *ifp; | |
203 | struct prefix dp; | |
204 | struct prefix sp; | |
205 | ||
7f342629 | 206 | ifp = bfd_get_peer_info (zclient->ibuf, &dp, &sp); |
c43ed2e4 DS |
207 | |
208 | if (BGP_DEBUG (zebra, ZEBRA)) | |
209 | { | |
210 | char buf[2][128]; | |
211 | prefix2str(&dp, buf[0], sizeof(buf[0])); | |
212 | if (ifp) | |
213 | { | |
214 | zlog_debug("Zebra: interface %s bfd destination %s down", | |
215 | ifp->name, buf[0]); | |
216 | } | |
217 | else | |
218 | { | |
219 | prefix2str(&sp, buf[1], sizeof(buf[1])); | |
220 | zlog_debug("Zebra: source %s bfd destination %s down", | |
221 | buf[1], buf[0]); | |
222 | } | |
223 | } | |
224 | ||
225 | /* Bring the peer down if BFD is enabled in BGP */ | |
226 | { | |
227 | struct listnode *mnode, *node, *nnode; | |
228 | struct bgp *bgp; | |
229 | struct peer *peer; | |
230 | ||
231 | for (ALL_LIST_ELEMENTS_RO (bm->bgp, mnode, bgp)) | |
232 | for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) | |
233 | { | |
7f342629 | 234 | if (!peer->bfd_info) |
c43ed2e4 DS |
235 | continue; |
236 | ||
7bbc6864 DS |
237 | if ((dp.family == AF_INET) && (peer->su.sa.sa_family == AF_INET)) |
238 | { | |
239 | if (dp.u.prefix4.s_addr != peer->su.sin.sin_addr.s_addr) | |
240 | continue; | |
241 | } | |
c43ed2e4 | 242 | #ifdef HAVE_IPV6 |
7bbc6864 DS |
243 | else if ((dp.family == AF_INET6) && |
244 | (peer->su.sa.sa_family == AF_INET6)) | |
245 | { | |
246 | if (memcmp(&dp.u.prefix6, &peer->su.sin6.sin6_addr, | |
247 | sizeof (struct in6_addr))) | |
248 | continue; | |
249 | } | |
c43ed2e4 DS |
250 | #endif |
251 | else | |
252 | continue; | |
253 | ||
254 | if (ifp && (ifp == peer->nexthop.ifp)) | |
7bbc6864 DS |
255 | { |
256 | peer->last_reset = PEER_DOWN_BFD_DOWN; | |
c43ed2e4 | 257 | BGP_EVENT_ADD (peer, BGP_Stop); |
7bbc6864 | 258 | } |
c43ed2e4 DS |
259 | else |
260 | { | |
261 | if (!peer->su_local) | |
262 | continue; | |
263 | ||
7bbc6864 DS |
264 | if ((sp.family == AF_INET) && |
265 | (peer->su_local->sa.sa_family == AF_INET)) | |
266 | { | |
267 | if (sp.u.prefix4.s_addr != peer->su_local->sin.sin_addr.s_addr) | |
268 | continue; | |
269 | } | |
c43ed2e4 | 270 | #ifdef HAVE_IPV6 |
7bbc6864 DS |
271 | else if ((sp.family == AF_INET6) && |
272 | (peer->su_local->sa.sa_family == AF_INET6)) | |
273 | { | |
274 | if (memcmp(&sp.u.prefix6, &peer->su_local->sin6.sin6_addr, | |
275 | sizeof (struct in6_addr))) | |
276 | continue; | |
277 | } | |
c43ed2e4 DS |
278 | #endif |
279 | else | |
280 | continue; | |
7bbc6864 DS |
281 | |
282 | peer->last_reset = PEER_DOWN_BFD_DOWN; | |
c43ed2e4 DS |
283 | BGP_EVENT_ADD (peer, BGP_Stop); |
284 | } | |
285 | } | |
286 | } | |
287 | ||
288 | return 0; | |
289 | } | |
290 | ||
291 | /* | |
292 | * bgp_bfd_peer_param_set - Set the configured BFD paramter values for peer. | |
293 | */ | |
7f342629 | 294 | static int |
c43ed2e4 | 295 | bgp_bfd_peer_param_set (struct peer *peer, u_int32_t min_rx, u_int32_t min_tx, |
7f342629 | 296 | u_int8_t detect_mult, int defaults) |
c43ed2e4 DS |
297 | { |
298 | struct peer_group *group; | |
299 | struct listnode *node, *nnode; | |
7f342629 | 300 | int command = 0; |
c43ed2e4 | 301 | |
7f342629 DS |
302 | bfd_set_param(&(peer->bfd_info), min_rx, min_tx, detect_mult, |
303 | defaults, &command); | |
c43ed2e4 DS |
304 | |
305 | if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) | |
306 | { | |
307 | group = peer->group; | |
308 | for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) | |
309 | { | |
7f342629 DS |
310 | command = 0; |
311 | bfd_set_param(&(peer->bfd_info), min_rx, min_tx, detect_mult, | |
312 | defaults, &command); | |
c43ed2e4 | 313 | |
7f342629 DS |
314 | if ((peer->status == Established) && |
315 | (command == ZEBRA_BFD_DEST_REGISTER)) | |
c43ed2e4 | 316 | bgp_bfd_register_peer(peer); |
7f342629 | 317 | else if (command == ZEBRA_BFD_DEST_UPDATE) |
c43ed2e4 DS |
318 | bgp_bfd_update_peer(peer); |
319 | } | |
320 | } | |
7f342629 | 321 | else |
c43ed2e4 | 322 | { |
7f342629 DS |
323 | if ((peer->status == Established) && |
324 | (command == ZEBRA_BFD_DEST_REGISTER)) | |
c43ed2e4 | 325 | bgp_bfd_register_peer(peer); |
7f342629 | 326 | else if (command == ZEBRA_BFD_DEST_UPDATE) |
c43ed2e4 DS |
327 | bgp_bfd_update_peer(peer); |
328 | } | |
329 | return 0; | |
330 | } | |
331 | ||
332 | /* | |
333 | * bgp_bfd_peer_param_unset - Unset the configured BFD paramter values for peer. | |
334 | */ | |
7f342629 | 335 | static int |
c43ed2e4 DS |
336 | bgp_bfd_peer_param_unset (struct peer *peer) |
337 | { | |
338 | struct peer_group *group; | |
339 | struct listnode *node, *nnode; | |
c43ed2e4 | 340 | |
7f342629 DS |
341 | if (!peer->bfd_info) |
342 | return 0; | |
c43ed2e4 DS |
343 | |
344 | if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) | |
345 | { | |
7f342629 | 346 | bfd_info_free(&(peer->bfd_info)); |
c43ed2e4 DS |
347 | group = peer->group; |
348 | for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) | |
349 | { | |
c43ed2e4 | 350 | bgp_bfd_deregister_peer(peer); |
7f342629 | 351 | bfd_info_free(&(peer->bfd_info)); |
c43ed2e4 DS |
352 | } |
353 | } | |
354 | else | |
7f342629 DS |
355 | { |
356 | bgp_bfd_deregister_peer(peer); | |
357 | bfd_info_free(&(peer->bfd_info)); | |
358 | } | |
c43ed2e4 DS |
359 | return 0; |
360 | } | |
361 | ||
362 | /* | |
363 | * bgp_bfd_peer_config_write - Write the peer BFD configuration. | |
364 | */ | |
365 | void | |
366 | bgp_bfd_peer_config_write(struct vty *vty, struct peer *peer, char *addr) | |
367 | { | |
7f342629 | 368 | struct bfd_info *bfd_info; |
c43ed2e4 | 369 | |
7f342629 DS |
370 | if (!peer->bfd_info) |
371 | return; | |
372 | ||
373 | bfd_info = (struct bfd_info *)peer->bfd_info; | |
c43ed2e4 | 374 | |
7f342629 | 375 | if (CHECK_FLAG (bfd_info->flags, BFD_FLAG_PARAM_CFG)) |
c43ed2e4 DS |
376 | vty_out (vty, " neighbor %s bfd %d %d %d%s", addr, |
377 | bfd_info->detect_mult, bfd_info->required_min_rx, | |
378 | bfd_info->desired_min_tx, VTY_NEWLINE); | |
379 | else | |
380 | vty_out (vty, " neighbor %s bfd%s", addr, VTY_NEWLINE); | |
381 | } | |
382 | ||
383 | /* | |
384 | * bgp_bfd_show_info - Show the peer BFD information. | |
385 | */ | |
386 | void | |
856ca177 | 387 | bgp_bfd_show_info(struct vty *vty, struct peer *peer, u_char use_json, json_object *json_neigh) |
c43ed2e4 | 388 | { |
7f342629 | 389 | struct bfd_info *bfd_info; |
856ca177 | 390 | json_object *json_bfd = NULL; |
7f342629 DS |
391 | |
392 | if (!peer->bfd_info) | |
393 | return; | |
c43ed2e4 | 394 | |
856ca177 MS |
395 | if (use_json) |
396 | json_bfd = json_object_new_object(); | |
397 | ||
7f342629 | 398 | bfd_info = (struct bfd_info *)peer->bfd_info; |
c43ed2e4 | 399 | |
856ca177 MS |
400 | if (use_json) |
401 | { | |
402 | if (bgp_bfd_is_peer_multihop(peer)) | |
403 | json_object_string_add(json_bfd, "bfdMultiHop", "yes"); | |
404 | else | |
405 | json_object_string_add(json_bfd, "bfdMultiHop", "no"); | |
406 | json_object_int_add(json_bfd, "detectMultiplier", bfd_info->detect_mult); | |
407 | json_object_int_add(json_bfd, "rxMinInterval", bfd_info->required_min_rx); | |
408 | json_object_int_add(json_bfd, "txMinInterval", bfd_info->desired_min_tx); | |
409 | json_object_object_add(json_neigh, "peerBfdInfo", json_bfd); | |
410 | } | |
411 | else | |
412 | { | |
413 | vty_out (vty, " BFD: Multi-hop: %s%s", | |
414 | (bgp_bfd_is_peer_multihop(peer)) ? "yes" : "no", VTY_NEWLINE); | |
415 | vty_out (vty, " Detect Mul: %d, Min Rx interval: %d," | |
416 | " Min Tx interval: %d%s", | |
417 | bfd_info->detect_mult, bfd_info->required_min_rx, | |
418 | bfd_info->desired_min_tx, VTY_NEWLINE); | |
419 | vty_out (vty, "%s", VTY_NEWLINE); | |
420 | } | |
c43ed2e4 DS |
421 | } |
422 | ||
423 | DEFUN (neighbor_bfd, | |
424 | neighbor_bfd_cmd, | |
425 | NEIGHBOR_CMD2 "bfd", | |
426 | NEIGHBOR_STR | |
427 | NEIGHBOR_ADDR_STR2 | |
428 | "Enables BFD support\n") | |
429 | { | |
430 | struct peer *peer; | |
431 | int ret; | |
c43ed2e4 DS |
432 | |
433 | peer = peer_and_group_lookup_vty (vty, argv[0]); | |
434 | if (! peer) | |
435 | return CMD_WARNING; | |
436 | ||
7f342629 DS |
437 | ret = bgp_bfd_peer_param_set (peer, BFD_DEF_MIN_RX, BFD_DEF_MIN_TX, |
438 | BFD_DEF_DETECT_MULT, 1); | |
c43ed2e4 DS |
439 | if (ret != 0) |
440 | return bgp_vty_return (vty, ret); | |
441 | ||
442 | return CMD_SUCCESS; | |
443 | ||
444 | } | |
445 | ||
446 | DEFUN (neighbor_bfd_param, | |
447 | neighbor_bfd_param_cmd, | |
7f342629 | 448 | NEIGHBOR_CMD2 "bfd " BFD_CMD_DETECT_MULT_RANGE BFD_CMD_MIN_RX_RANGE BFD_CMD_MIN_TX_RANGE, |
c43ed2e4 DS |
449 | NEIGHBOR_STR |
450 | NEIGHBOR_ADDR_STR2 | |
451 | "Enables BFD support\n" | |
452 | "Detect Multiplier\n" | |
453 | "Required min receive interval\n" | |
454 | "Desired min transmit interval\n") | |
455 | { | |
456 | struct peer *peer; | |
457 | u_int32_t rx_val; | |
458 | u_int32_t tx_val; | |
459 | u_int8_t dm_val; | |
460 | int ret; | |
c43ed2e4 DS |
461 | |
462 | peer = peer_and_group_lookup_vty (vty, argv[0]); | |
463 | if (!peer) | |
464 | return CMD_WARNING; | |
465 | ||
7f342629 DS |
466 | if ((ret = bfd_validate_param (vty, argv[1], argv[2], argv[3], &dm_val, |
467 | &rx_val, &tx_val)) != CMD_SUCCESS) | |
468 | return ret; | |
c43ed2e4 | 469 | |
7f342629 | 470 | ret = bgp_bfd_peer_param_set (peer, rx_val, tx_val, dm_val, 0); |
c43ed2e4 DS |
471 | if (ret != 0) |
472 | return bgp_vty_return (vty, ret); | |
473 | ||
474 | return CMD_SUCCESS; | |
475 | ||
476 | } | |
477 | ||
478 | DEFUN (no_neighbor_bfd, | |
479 | no_neighbor_bfd_cmd, | |
480 | NO_NEIGHBOR_CMD2 "bfd", | |
481 | NO_STR | |
482 | NEIGHBOR_STR | |
483 | NEIGHBOR_ADDR_STR2 | |
484 | "Disables BFD support\n") | |
485 | { | |
486 | struct peer *peer; | |
487 | int ret; | |
488 | ||
489 | peer = peer_and_group_lookup_vty (vty, argv[0]); | |
490 | if (! peer) | |
491 | return CMD_WARNING; | |
492 | ||
c43ed2e4 DS |
493 | ret = bgp_bfd_peer_param_unset(peer); |
494 | if (ret != 0) | |
495 | return bgp_vty_return (vty, ret); | |
496 | ||
c43ed2e4 DS |
497 | return CMD_SUCCESS; |
498 | } | |
499 | ||
500 | void | |
501 | bgp_bfd_init(void) | |
502 | { | |
503 | /* Initialize BFD client functions */ | |
504 | zclient->interface_bfd_dest_down = bgp_interface_bfd_dest_down; | |
505 | zclient->bfd_dest_replay = bgp_bfd_dest_replay; | |
506 | ||
507 | /* "neighbor bfd" commands. */ | |
508 | install_element (BGP_NODE, &neighbor_bfd_cmd); | |
509 | install_element (BGP_NODE, &neighbor_bfd_param_cmd); | |
510 | install_element (BGP_NODE, &no_neighbor_bfd_cmd); | |
511 | } |