]>
Commit | Line | Data |
---|---|---|
7f342629 DS |
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 | * | |
896014f4 DL |
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 | |
7f342629 DS |
21 | */ |
22 | ||
23 | #include <zebra.h> | |
24 | ||
25 | #include "command.h" | |
659f4e40 | 26 | #include "json.h" |
7f342629 DS |
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 | ||
659f4e40 | 48 | DEFINE_MTYPE_STATIC(OSPFD, BFD_CONFIG, "BFD configuration data"); |
d62a17ae | 49 | |
7f342629 DS |
50 | /* |
51 | * ospf_bfd_trigger_event - Neighbor is registered/deregistered with BFD when | |
52 | * neighbor state is changed to/from 2way. | |
53 | */ | |
d62a17ae | 54 | void ospf_bfd_trigger_event(struct ospf_neighbor *nbr, int old_state, int state) |
7f342629 | 55 | { |
d62a17ae | 56 | if ((old_state < NSM_TwoWay) && (state >= NSM_TwoWay)) |
659f4e40 | 57 | bfd_sess_install(nbr->bfd_session); |
d62a17ae | 58 | else if ((old_state >= NSM_TwoWay) && (state < NSM_TwoWay)) |
659f4e40 | 59 | bfd_sess_uninstall(nbr->bfd_session); |
7f342629 DS |
60 | } |
61 | ||
659f4e40 RZ |
62 | static void ospf_bfd_session_change(struct bfd_session_params *bsp, |
63 | const struct bfd_session_status *bss, | |
64 | void *arg) | |
7f342629 | 65 | { |
659f4e40 | 66 | struct ospf_neighbor *nbr = arg; |
d62a17ae | 67 | |
659f4e40 RZ |
68 | /* BFD peer went down. */ |
69 | if (bss->state == BFD_STATUS_DOWN | |
70 | && bss->previous_state == BFD_STATUS_UP) { | |
e4505a2e RZ |
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); | |
d62a17ae | 74 | |
659f4e40 | 75 | OSPF_NSM_EVENT_SCHEDULE(nbr, NSM_InactivityTimer); |
d62a17ae | 76 | } |
77 | ||
659f4e40 RZ |
78 | /* BFD peer went up. */ |
79 | if (bss->state == BSS_UP && bss->previous_state == BSS_DOWN) | |
e4505a2e RZ |
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); | |
7f342629 DS |
83 | } |
84 | ||
659f4e40 | 85 | void ospf_neighbor_bfd_apply(struct ospf_neighbor *nbr) |
7f342629 | 86 | { |
659f4e40 RZ |
87 | struct ospf_interface *oi = nbr->oi; |
88 | struct ospf_if_params *oip = IF_DEF_PARAMS(oi->ifp); | |
d62a17ae | 89 | |
659f4e40 RZ |
90 | /* BFD configuration was removed. */ |
91 | if (oip->bfd_config == NULL) { | |
92 | bfd_sess_free(&nbr->bfd_session); | |
93 | return; | |
d62a17ae | 94 | } |
95 | ||
659f4e40 RZ |
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); | |
659f4e40 | 102 | } |
d62a17ae | 103 | |
659f4e40 RZ |
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); | |
d62a17ae | 109 | |
659f4e40 RZ |
110 | /* Don't start sessions on down OSPF sessions. */ |
111 | if (nbr->state < NSM_TwoWay) | |
112 | return; | |
d62a17ae | 113 | |
659f4e40 | 114 | bfd_sess_install(nbr->bfd_session); |
7f342629 DS |
115 | } |
116 | ||
659f4e40 | 117 | static void ospf_interface_bfd_apply(struct interface *ifp) |
7f342629 | 118 | { |
d62a17ae | 119 | struct ospf_interface *oi; |
659f4e40 RZ |
120 | struct route_table *nbrs; |
121 | struct ospf_neighbor *nbr; | |
122 | struct route_node *irn; | |
123 | struct route_node *nrn; | |
6e641a8f | 124 | |
659f4e40 RZ |
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) | |
d62a17ae | 128 | continue; |
659f4e40 | 129 | if ((nbrs = oi->nbrs) == NULL) |
d62a17ae | 130 | continue; |
659f4e40 RZ |
131 | for (nrn = route_top(nbrs); nrn; nrn = route_next(nrn)) { |
132 | if ((nbr = nrn->info) == NULL || nbr == oi->nbr_self) | |
133 | continue; | |
d62a17ae | 134 | |
659f4e40 | 135 | ospf_neighbor_bfd_apply(nbr); |
4828ea77 | 136 | } |
d62a17ae | 137 | } |
7f342629 DS |
138 | } |
139 | ||
659f4e40 | 140 | static void ospf_interface_enable_bfd(struct interface *ifp) |
68fe91d6 | 141 | { |
659f4e40 | 142 | struct ospf_if_params *oip = IF_DEF_PARAMS(ifp); |
d62a17ae | 143 | |
659f4e40 | 144 | if (oip->bfd_config) |
d62a17ae | 145 | return; |
146 | ||
659f4e40 RZ |
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 | } | |
d62a17ae | 153 | |
659f4e40 RZ |
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); | |
68fe91d6 | 159 | } |
160 | ||
7f342629 DS |
161 | /* |
162 | * ospf_bfd_write_config - Write the interface BFD configuration. | |
163 | */ | |
659f4e40 RZ |
164 | void ospf_bfd_write_config(struct vty *vty, const struct ospf_if_params *params |
165 | __attribute__((unused))) | |
7f342629 | 166 | { |
a0841732 | 167 | #if HAVE_BFDD == 0 |
69b34634 IR |
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) | |
659f4e40 RZ |
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); | |
d62a17ae | 174 | else |
a0841732 | 175 | #endif /* ! HAVE_BFDD */ |
d62a17ae | 176 | vty_out(vty, " ip ospf bfd\n"); |
96b52510 RZ |
177 | |
178 | if (params->bfd_config->profile[0]) | |
179 | vty_out(vty, " ip ospf bfd profile %s\n", | |
180 | params->bfd_config->profile); | |
7f342629 DS |
181 | } |
182 | ||
659f4e40 RZ |
183 | void ospf_interface_bfd_show(struct vty *vty, const struct interface *ifp, |
184 | struct json_object *json) | |
68fe91d6 | 185 | { |
659f4e40 RZ |
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; | |
7f342629 | 189 | |
659f4e40 RZ |
190 | if (bfd_config == NULL) |
191 | return; | |
7f342629 | 192 | |
659f4e40 RZ |
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); | |
7f342629 DS |
207 | } |
208 | ||
7f342629 DS |
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 | { | |
d62a17ae | 216 | VTY_DECLVAR_CONTEXT(interface, ifp); |
659f4e40 RZ |
217 | ospf_interface_enable_bfd(ifp); |
218 | ospf_interface_bfd_apply(ifp); | |
d62a17ae | 219 | return CMD_SUCCESS; |
7f342629 DS |
220 | } |
221 | ||
64dc4b2d RZ |
222 | #if HAVE_BFDD > 0 |
223 | DEFUN_HIDDEN( | |
224 | #else | |
225 | DEFUN( | |
226 | #endif /* HAVE_BFDD */ | |
227 | ip_ospf_bfd_param, | |
7f342629 | 228 | ip_ospf_bfd_param_cmd, |
9ccf14f7 | 229 | "ip ospf bfd (2-255) (50-60000) (50-60000)", |
7f342629 DS |
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 | { | |
d62a17ae | 237 | VTY_DECLVAR_CONTEXT(interface, ifp); |
659f4e40 | 238 | struct ospf_if_params *params; |
d62a17ae | 239 | int idx_number = 3; |
240 | int idx_number_2 = 4; | |
241 | int idx_number_3 = 5; | |
d62a17ae | 242 | |
659f4e40 | 243 | ospf_interface_enable_bfd(ifp); |
d62a17ae | 244 | |
659f4e40 RZ |
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); | |
d62a17ae | 250 | |
659f4e40 | 251 | ospf_interface_bfd_apply(ifp); |
d62a17ae | 252 | |
253 | return CMD_SUCCESS; | |
7f342629 DS |
254 | } |
255 | ||
96b52510 RZ |
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 | ||
96b52510 | 269 | params = IF_DEF_PARAMS(ifp); |
f3fd7196 DT |
270 | if (!params->bfd_config) { |
271 | vty_out(vty, "ip ospf bfd has not been set\n"); | |
272 | return CMD_WARNING; | |
273 | } | |
274 | ||
96b52510 RZ |
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 | ||
96b52510 | 295 | params = IF_DEF_PARAMS(ifp); |
f3fd7196 DT |
296 | if (!params->bfd_config) |
297 | return CMD_SUCCESS; | |
298 | ||
96b52510 RZ |
299 | params->bfd_config->profile[0] = 0; |
300 | ospf_interface_bfd_apply(ifp); | |
301 | ||
302 | return CMD_SUCCESS; | |
303 | } | |
304 | ||
7f342629 DS |
305 | DEFUN (no_ip_ospf_bfd, |
306 | no_ip_ospf_bfd_cmd, | |
64dc4b2d RZ |
307 | #if HAVE_BFDD > 0 |
308 | "no ip ospf bfd", | |
309 | #else | |
692b4c65 | 310 | "no ip ospf bfd [(2-255) (50-60000) (50-60000)]", |
64dc4b2d | 311 | #endif /* HAVE_BFDD */ |
7f342629 DS |
312 | NO_STR |
313 | "IP Information\n" | |
314 | "OSPF interface commands\n" | |
692b4c65 | 315 | "Disables BFD support\n" |
64dc4b2d | 316 | #if HAVE_BFDD == 0 |
692b4c65 QY |
317 | "Detect Multiplier\n" |
318 | "Required min receive interval\n" | |
64dc4b2d RZ |
319 | "Desired min transmit interval\n" |
320 | #endif /* !HAVE_BFDD */ | |
321 | ) | |
7f342629 | 322 | { |
d62a17ae | 323 | VTY_DECLVAR_CONTEXT(interface, ifp); |
659f4e40 | 324 | ospf_interface_disable_bfd(ifp, IF_DEF_PARAMS(ifp)); |
d62a17ae | 325 | return CMD_SUCCESS; |
7f342629 DS |
326 | } |
327 | ||
659f4e40 | 328 | void ospf_bfd_init(struct thread_master *tm) |
7f342629 | 329 | { |
659f4e40 | 330 | bfd_protocol_integration_init(zclient, tm); |
7f342629 | 331 | |
d62a17ae | 332 | /* Install BFD command */ |
333 | install_element(INTERFACE_NODE, &ip_ospf_bfd_cmd); | |
334 | install_element(INTERFACE_NODE, &ip_ospf_bfd_param_cmd); | |
96b52510 RZ |
335 | install_element(INTERFACE_NODE, &ip_ospf_bfd_prof_cmd); |
336 | install_element(INTERFACE_NODE, &no_ip_ospf_bfd_prof_cmd); | |
d62a17ae | 337 | install_element(INTERFACE_NODE, &no_ip_ospf_bfd_cmd); |
7f342629 | 338 | } |