2 * pim_bfd.c: PIM BFD handling routines
4 * Copyright (C) 2017 Cumulus Networks, Inc.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; see the file COPYING; if not, write to the
19 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
32 #include "pim_iface.h"
36 #include "pim_zebra.h"
39 * pim_bfd_write_config - Write the interface BFD configuration.
42 pim_bfd_write_config (struct vty
*vty
, struct interface
*ifp
)
44 struct pim_interface
*pim_ifp
= ifp
->info
;
45 struct bfd_info
*bfd_info
= NULL
;
50 bfd_info
= (struct bfd_info
*) pim_ifp
->bfd_info
;
54 if (CHECK_FLAG (bfd_info
->flags
, BFD_FLAG_PARAM_CFG
))
55 vty_out (vty
, " ip pim bfd %d %d %d%s",
56 bfd_info
->detect_mult
, bfd_info
->required_min_rx
,
57 bfd_info
->desired_min_tx
, VTY_NEWLINE
);
59 vty_out (vty
, " ip pim bfd%s", VTY_NEWLINE
);
63 * pim_bfd_show_info - Show BFD info structure
66 pim_bfd_show_info (struct vty
*vty
, void *bfd_info
, json_object
* json_obj
,
67 u_char use_json
, int param_only
)
70 bfd_show_param (vty
, (struct bfd_info
*) bfd_info
, 1, 0, use_json
,
73 bfd_show_info (vty
, (struct bfd_info
*) bfd_info
, 0, 1, use_json
,
78 * pim_bfd_info_nbr_create - Create/update BFD information for a neighbor.
81 pim_bfd_info_nbr_create (struct pim_interface
*pim_ifp
,
82 struct pim_neighbor
*neigh
)
84 struct bfd_info
*nbr_bfd_info
= NULL
;
86 /* Check if Pim Interface BFD is enabled */
87 if (!pim_ifp
|| !pim_ifp
->bfd_info
)
91 neigh
->bfd_info
= bfd_info_create ();
96 nbr_bfd_info
= (struct bfd_info
*) neigh
->bfd_info
;
97 nbr_bfd_info
->detect_mult
= pim_ifp
->bfd_info
->detect_mult
;
98 nbr_bfd_info
->desired_min_tx
= pim_ifp
->bfd_info
->desired_min_tx
;
99 nbr_bfd_info
->required_min_rx
= pim_ifp
->bfd_info
->required_min_rx
;
103 * pim_bfd_info_free - Free BFD info structure
106 pim_bfd_info_free (void **bfd_info
)
108 bfd_info_free ((struct bfd_info
**) bfd_info
);
112 pim_bfd_reg_dereg_nbr (struct pim_neighbor
*nbr
, int command
)
114 struct pim_interface
*pim_ifp
= NULL
;
115 struct bfd_info
*bfd_info
= NULL
;
116 struct zclient
*zclient
= NULL
;
118 zclient
= pim_zebra_zclient_get ();
122 pim_ifp
= nbr
->interface
->info
;
123 bfd_info
= (struct bfd_info
*) pim_ifp
->bfd_info
;
126 if (PIM_DEBUG_PIM_TRACE
)
128 char str
[INET_ADDRSTRLEN
];
129 pim_inet4_dump ("<bfd_nbr?>", nbr
->source_addr
, str
, sizeof (str
));
130 zlog_debug ("%s Nbr %s %s with BFD", __PRETTY_FUNCTION__
, str
,
131 bfd_get_command_dbg_str (command
));
133 bfd_peer_sendmsg (zclient
, bfd_info
, AF_INET
,
134 &nbr
->source_addr
, NULL
, nbr
->interface
->name
,
135 0, 0, command
, 0, VRF_DEFAULT
);
139 * pim_bfd_reg_dereg_all_nbr - Register/Deregister all neighbors associated
140 * with a interface with BFD through
141 * zebra for starting/stopping the monitoring of
142 * the neighbor rechahability.
145 pim_bfd_reg_dereg_all_nbr (struct interface
*ifp
, int command
)
147 struct pim_interface
*pim_ifp
= NULL
;
148 struct listnode
*node
= NULL
;
149 struct pim_neighbor
*neigh
= NULL
;
154 if (!pim_ifp
->bfd_info
)
157 for (ALL_LIST_ELEMENTS_RO (pim_ifp
->pim_neighbor_list
, node
, neigh
))
159 if (command
!= ZEBRA_BFD_DEST_DEREGISTER
)
160 pim_bfd_info_nbr_create (pim_ifp
, neigh
);
162 bfd_info_free ((struct bfd_info
**) &neigh
->bfd_info
);
164 pim_bfd_reg_dereg_nbr (neigh
, command
);
171 * pim_bfd_trigger_event - Neighbor is registered/deregistered with BFD when
172 * neighbor state is changed to/from 2way.
175 pim_bfd_trigger_event (struct pim_interface
*pim_ifp
, struct pim_neighbor
*nbr
, uint8_t nbr_up
)
179 pim_bfd_info_nbr_create (pim_ifp
, nbr
);
180 pim_bfd_reg_dereg_nbr (nbr
, ZEBRA_BFD_DEST_REGISTER
);
184 pim_bfd_info_free ((void *)&nbr
->bfd_info
);
185 pim_bfd_reg_dereg_nbr (nbr
, ZEBRA_BFD_DEST_DEREGISTER
);
190 * pim_bfd_if_param_set - Set the configured BFD paramter values for
194 pim_bfd_if_param_set (struct interface
*ifp
, u_int32_t min_rx
,
195 u_int32_t min_tx
, u_int8_t detect_mult
, int defaults
)
197 struct pim_interface
*pim_ifp
= ifp
->info
;
202 bfd_set_param ((struct bfd_info
**) &(pim_ifp
->bfd_info
), min_rx
, min_tx
,
203 detect_mult
, defaults
, &command
);
205 if (pim_ifp
->bfd_info
)
207 if (PIM_DEBUG_PIM_TRACE
)
208 zlog_debug ("%s: interface %s has bfd_info", __PRETTY_FUNCTION__
,
212 pim_bfd_reg_dereg_all_nbr (ifp
, command
);
217 * pim_bfd_interface_dest_update - Find the neighbor for which the BFD status
218 * has changed and bring down the neighbor
219 * connectivity if the BFD status changed to
223 pim_bfd_interface_dest_update (int command
, struct zclient
*zclient
,
224 zebra_size_t length
, vrf_id_t vrf_id
)
226 struct interface
*ifp
= NULL
;
227 struct pim_interface
*pim_ifp
= NULL
;
232 struct bfd_info
*bfd_info
= NULL
;
234 struct listnode
*neigh_node
= NULL
;
235 struct listnode
*neigh_nextnode
= NULL
;
236 struct pim_neighbor
*neigh
= NULL
;
238 ifp
= bfd_get_peer_info (zclient
->ibuf
, &p
, NULL
, &status
, vrf_id
);
240 if ((ifp
== NULL
) || (p
.family
!= AF_INET
))
247 if (!pim_ifp
->bfd_info
)
249 if (PIM_DEBUG_PIM_TRACE
)
250 zlog_debug ("%s: pim interface %s BFD is disabled ", __PRETTY_FUNCTION__
,
255 if (PIM_DEBUG_PIM_TRACE
)
257 char buf
[PREFIX2STR_BUFFER
];
258 prefix2str (&p
, buf
, sizeof (buf
));
259 zlog_debug ("%s: interface %s bfd destination %s %s",
260 __PRETTY_FUNCTION__
, ifp
->name
, buf
,
261 bfd_get_status_str (status
));
264 for (ALL_LIST_ELEMENTS (pim_ifp
->pim_neighbor_list
, neigh_node
,
265 neigh_nextnode
, neigh
))
267 /* Check neigh address matches with BFD address */
268 if (neigh
->source_addr
.s_addr
!= p
.u
.prefix4
.s_addr
)
271 bfd_info
= (struct bfd_info
*) neigh
->bfd_info
;
272 if (bfd_info
->status
== status
)
274 if (PIM_DEBUG_PIM_TRACE
)
276 char str
[INET_ADDRSTRLEN
];
277 pim_inet4_dump ("<nht_nbr?>", neigh
->source_addr
, str
,
279 zlog_debug ("%s: bfd status is same for nbr %s",
280 __PRETTY_FUNCTION__
, str
);
284 old_status
= bfd_info
->status
;
285 bfd_info
->status
= status
;
287 bfd_info
->last_update
= tv
.tv_sec
;
289 if (PIM_DEBUG_PIM_TRACE
)
291 zlog_debug ("%s: status %s old_status %s", __PRETTY_FUNCTION__
,
292 bfd_get_status_str (status
),
293 bfd_get_status_str (old_status
));
295 if ((status
== BFD_STATUS_DOWN
) && (old_status
== BFD_STATUS_UP
))
297 snprintf (msg
, sizeof (msg
), "BFD Session Expired");
298 pim_neighbor_delete (ifp
, neigh
, msg
);
305 * pim_bfd_nbr_replay - Replay all the neighbors that have BFD enabled
309 pim_bfd_nbr_replay (int command
, struct zclient
*zclient
, zebra_size_t length
,
312 struct interface
*ifp
= NULL
;
313 struct pim_interface
*pim_ifp
= NULL
;
314 struct pim_neighbor
*neigh
= NULL
;
315 struct listnode
*node
;
316 struct listnode
*neigh_node
;
317 struct listnode
*neigh_nextnode
;
319 /* Send the client registration */
320 bfd_client_sendmsg (zclient
, ZEBRA_BFD_CLIENT_REGISTER
);
322 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT
), node
, ifp
))
329 if (pim_ifp
->pim_sock_fd
< 0)
332 for (ALL_LIST_ELEMENTS (pim_ifp
->pim_neighbor_list
, neigh_node
,
333 neigh_nextnode
, neigh
))
335 if (!neigh
->bfd_info
)
337 if (PIM_DEBUG_PIM_TRACE
)
339 char str
[INET_ADDRSTRLEN
];
340 pim_inet4_dump ("<bfd_nbr?>", neigh
->source_addr
, str
,
342 zlog_debug ("%s: Replaying Pim Neigh %s to BFD",
343 __PRETTY_FUNCTION__
, str
);
345 pim_bfd_reg_dereg_nbr (neigh
, ZEBRA_BFD_DEST_UPDATE
);
355 struct zclient
*zclient
= NULL
;
357 zclient
= pim_zebra_zclient_get ();
361 zclient
->interface_bfd_dest_update
= pim_bfd_interface_dest_update
;
362 zclient
->bfd_dest_replay
= pim_bfd_nbr_replay
;