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