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