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