]> git.proxmox.com Git - mirror_frr.git/blob - ospfd/ospf_bfd.c
f4470ad833b19f816ee98a05e017ed17d3a9bbda
[mirror_frr.git] / ospfd / ospf_bfd.c
1 /**
2 * ospf_bfd.c: OSPF 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 "json.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"
35 #include "table.h"
36 #include "bfd.h"
37 #include "ospfd.h"
38 #include "ospf_asbr.h"
39 #include "ospf_lsa.h"
40 #include "ospf_lsdb.h"
41 #include "ospf_neighbor.h"
42 #include "ospf_interface.h"
43 #include "ospf_nsm.h"
44 #include "ospf_bfd.h"
45 #include "ospf_dump.h"
46 #include "ospf_vty.h"
47
48 DEFINE_MTYPE_STATIC(OSPFD, BFD_CONFIG, "BFD configuration data");
49
50 extern struct zclient *zclient;
51
52 /*
53 * ospf_bfd_trigger_event - Neighbor is registered/deregistered with BFD when
54 * neighbor state is changed to/from 2way.
55 */
56 void ospf_bfd_trigger_event(struct ospf_neighbor *nbr, int old_state, int state)
57 {
58 if ((old_state < NSM_TwoWay) && (state >= NSM_TwoWay))
59 bfd_sess_install(nbr->bfd_session);
60 else if ((old_state >= NSM_TwoWay) && (state < NSM_TwoWay))
61 bfd_sess_uninstall(nbr->bfd_session);
62 }
63
64 static void ospf_bfd_session_change(struct bfd_session_params *bsp,
65 const struct bfd_session_status *bss,
66 void *arg)
67 {
68 struct ospf_neighbor *nbr = arg;
69
70 /* BFD peer went down. */
71 if (bss->state == BFD_STATUS_DOWN
72 && bss->previous_state == BFD_STATUS_UP) {
73 if (IS_DEBUG_OSPF(nsm, NSM_EVENTS))
74 zlog_debug("NSM[%s:%pI4]: BFD Down", IF_NAME(nbr->oi),
75 &nbr->address.u.prefix4);
76
77 OSPF_NSM_EVENT_SCHEDULE(nbr, NSM_InactivityTimer);
78 }
79
80 /* BFD peer went up. */
81 if (bss->state == BSS_UP && bss->previous_state == BSS_DOWN)
82 if (IS_DEBUG_OSPF(nsm, NSM_EVENTS))
83 zlog_debug("NSM[%s:%pI4]: BFD Up", IF_NAME(nbr->oi),
84 &nbr->address.u.prefix4);
85 }
86
87 void ospf_neighbor_bfd_apply(struct ospf_neighbor *nbr)
88 {
89 struct ospf_interface *oi = nbr->oi;
90 struct ospf_if_params *oip = IF_DEF_PARAMS(oi->ifp);
91
92 /* BFD configuration was removed. */
93 if (oip->bfd_config == NULL) {
94 bfd_sess_free(&nbr->bfd_session);
95 return;
96 }
97
98 /* New BFD session. */
99 if (nbr->bfd_session == NULL) {
100 nbr->bfd_session = bfd_sess_new(ospf_bfd_session_change, nbr);
101 bfd_sess_set_ipv4_addrs(nbr->bfd_session, NULL, &nbr->src);
102 bfd_sess_set_interface(nbr->bfd_session, oi->ifp->name);
103 bfd_sess_set_vrf(nbr->bfd_session, oi->ospf->vrf_id);
104 bfd_sess_enable(nbr->bfd_session, true);
105 }
106
107 /* Set new configuration. */
108 bfd_sess_set_timers(nbr->bfd_session,
109 oip->bfd_config->detection_multiplier,
110 oip->bfd_config->min_rx, oip->bfd_config->min_tx);
111 bfd_sess_set_profile(nbr->bfd_session, oip->bfd_config->profile);
112
113 /* Don't start sessions on down OSPF sessions. */
114 if (nbr->state < NSM_TwoWay)
115 return;
116
117 bfd_sess_install(nbr->bfd_session);
118 }
119
120 static void ospf_interface_bfd_apply(struct interface *ifp)
121 {
122 struct ospf_interface *oi;
123 struct route_table *nbrs;
124 struct ospf_neighbor *nbr;
125 struct route_node *irn;
126 struct route_node *nrn;
127
128 /* Iterate over all interfaces and set neighbors BFD session. */
129 for (irn = route_top(IF_OIFS(ifp)); irn; irn = route_next(irn)) {
130 if ((oi = irn->info) == NULL)
131 continue;
132 if ((nbrs = oi->nbrs) == NULL)
133 continue;
134 for (nrn = route_top(nbrs); nrn; nrn = route_next(nrn)) {
135 if ((nbr = nrn->info) == NULL || nbr == oi->nbr_self)
136 continue;
137
138 ospf_neighbor_bfd_apply(nbr);
139 }
140 }
141 }
142
143 static void ospf_interface_enable_bfd(struct interface *ifp)
144 {
145 struct ospf_if_params *oip = IF_DEF_PARAMS(ifp);
146
147 if (oip->bfd_config)
148 return;
149
150 /* Allocate memory for configurations and set defaults. */
151 oip->bfd_config = XCALLOC(MTYPE_BFD_CONFIG, sizeof(*oip->bfd_config));
152 oip->bfd_config->detection_multiplier = BFD_DEF_DETECT_MULT;
153 oip->bfd_config->min_rx = BFD_DEF_MIN_RX;
154 oip->bfd_config->min_tx = BFD_DEF_MIN_TX;
155 }
156
157 void ospf_interface_disable_bfd(struct interface *ifp,
158 struct ospf_if_params *oip)
159 {
160 XFREE(MTYPE_BFD_CONFIG, oip->bfd_config);
161 ospf_interface_bfd_apply(ifp);
162 }
163
164 /*
165 * ospf_bfd_write_config - Write the interface BFD configuration.
166 */
167 void ospf_bfd_write_config(struct vty *vty, const struct ospf_if_params *params
168 __attribute__((unused)))
169 {
170 #if HAVE_BFDD == 0
171 if (CHECK_FLAG(bfd_info->flags, BFD_FLAG_PARAM_CFG))
172 vty_out(vty, " ip ospf bfd %d %d %d\n",
173 params->bfd_config->detection_multiplier,
174 params->bfd_config->min_rx, params->bfd_config->min_tx);
175 else
176 #endif /* ! HAVE_BFDD */
177 vty_out(vty, " ip ospf bfd\n");
178
179 if (params->bfd_config->profile[0])
180 vty_out(vty, " ip ospf bfd profile %s\n",
181 params->bfd_config->profile);
182 }
183
184 void ospf_interface_bfd_show(struct vty *vty, const struct interface *ifp,
185 struct json_object *json)
186 {
187 struct ospf_if_params *params = IF_DEF_PARAMS(ifp);
188 struct bfd_configuration *bfd_config = params->bfd_config;
189 struct json_object *json_bfd;
190
191 if (bfd_config == NULL)
192 return;
193
194 if (json) {
195 json_bfd = json_object_new_object();
196 json_object_int_add(json_bfd, "detectionMultiplier",
197 bfd_config->detection_multiplier);
198 json_object_int_add(json_bfd, "rxMinInterval",
199 bfd_config->min_rx);
200 json_object_int_add(json_bfd, "txMinInterval",
201 bfd_config->min_tx);
202 json_object_object_add(json, "peerBfdInfo", json_bfd);
203 } else
204 vty_out(vty,
205 " BFD: Detect Multiplier: %d, Min Rx interval: %d, Min Tx interval: %d\n",
206 bfd_config->detection_multiplier, bfd_config->min_rx,
207 bfd_config->min_tx);
208 }
209
210 DEFUN (ip_ospf_bfd,
211 ip_ospf_bfd_cmd,
212 "ip ospf bfd",
213 "IP Information\n"
214 "OSPF interface commands\n"
215 "Enables BFD support\n")
216 {
217 VTY_DECLVAR_CONTEXT(interface, ifp);
218 ospf_interface_enable_bfd(ifp);
219 ospf_interface_bfd_apply(ifp);
220 return CMD_SUCCESS;
221 }
222
223 #if HAVE_BFDD > 0
224 DEFUN_HIDDEN(
225 #else
226 DEFUN(
227 #endif /* HAVE_BFDD */
228 ip_ospf_bfd_param,
229 ip_ospf_bfd_param_cmd,
230 "ip ospf bfd (2-255) (50-60000) (50-60000)",
231 "IP Information\n"
232 "OSPF interface commands\n"
233 "Enables BFD support\n"
234 "Detect Multiplier\n"
235 "Required min receive interval\n"
236 "Desired min transmit interval\n")
237 {
238 VTY_DECLVAR_CONTEXT(interface, ifp);
239 struct ospf_if_params *params;
240 int idx_number = 3;
241 int idx_number_2 = 4;
242 int idx_number_3 = 5;
243
244 ospf_interface_enable_bfd(ifp);
245
246 params = IF_DEF_PARAMS(ifp);
247 params->bfd_config->detection_multiplier =
248 strtol(argv[idx_number]->arg, NULL, 10);
249 params->bfd_config->min_rx = strtol(argv[idx_number_2]->arg, NULL, 10);
250 params->bfd_config->min_tx = strtol(argv[idx_number_3]->arg, NULL, 10);
251
252 ospf_interface_bfd_apply(ifp);
253
254 return CMD_SUCCESS;
255 }
256
257 DEFUN (ip_ospf_bfd_prof,
258 ip_ospf_bfd_prof_cmd,
259 "ip ospf bfd profile BFDPROF",
260 "IP Information\n"
261 "OSPF interface commands\n"
262 "Enables BFD support\n"
263 BFD_PROFILE_STR
264 BFD_PROFILE_NAME_STR)
265 {
266 VTY_DECLVAR_CONTEXT(interface, ifp);
267 struct ospf_if_params *params;
268 int idx_prof = 4;
269
270 ospf_interface_enable_bfd(ifp);
271 params = IF_DEF_PARAMS(ifp);
272 strlcpy(params->bfd_config->profile, argv[idx_prof]->arg,
273 sizeof(params->bfd_config->profile));
274 ospf_interface_bfd_apply(ifp);
275
276 return CMD_SUCCESS;
277 }
278
279 DEFUN (no_ip_ospf_bfd_prof,
280 no_ip_ospf_bfd_prof_cmd,
281 "no ip ospf bfd profile [BFDPROF]",
282 NO_STR
283 "IP Information\n"
284 "OSPF interface commands\n"
285 "Enables BFD support\n"
286 BFD_PROFILE_STR
287 BFD_PROFILE_NAME_STR)
288 {
289 VTY_DECLVAR_CONTEXT(interface, ifp);
290 struct ospf_if_params *params;
291
292 ospf_interface_enable_bfd(ifp);
293 params = IF_DEF_PARAMS(ifp);
294 params->bfd_config->profile[0] = 0;
295 ospf_interface_bfd_apply(ifp);
296
297 return CMD_SUCCESS;
298 }
299
300 DEFUN (no_ip_ospf_bfd,
301 no_ip_ospf_bfd_cmd,
302 #if HAVE_BFDD > 0
303 "no ip ospf bfd",
304 #else
305 "no ip ospf bfd [(2-255) (50-60000) (50-60000)]",
306 #endif /* HAVE_BFDD */
307 NO_STR
308 "IP Information\n"
309 "OSPF interface commands\n"
310 "Disables BFD support\n"
311 #if HAVE_BFDD == 0
312 "Detect Multiplier\n"
313 "Required min receive interval\n"
314 "Desired min transmit interval\n"
315 #endif /* !HAVE_BFDD */
316 )
317 {
318 VTY_DECLVAR_CONTEXT(interface, ifp);
319 ospf_interface_disable_bfd(ifp, IF_DEF_PARAMS(ifp));
320 return CMD_SUCCESS;
321 }
322
323 void ospf_bfd_init(struct thread_master *tm)
324 {
325 bfd_protocol_integration_init(zclient, tm);
326
327 /* Install BFD command */
328 install_element(INTERFACE_NODE, &ip_ospf_bfd_cmd);
329 install_element(INTERFACE_NODE, &ip_ospf_bfd_param_cmd);
330 install_element(INTERFACE_NODE, &ip_ospf_bfd_prof_cmd);
331 install_element(INTERFACE_NODE, &no_ip_ospf_bfd_prof_cmd);
332 install_element(INTERFACE_NODE, &no_ip_ospf_bfd_cmd);
333 }