]>
Commit | Line | Data |
---|---|---|
acddc0ed | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
7f342629 DS |
2 | /** |
3 | * ospf_bfd.c: OSPF BFD handling routines | |
4 | * | |
5 | * @copyright Copyright (C) 2015 Cumulus Networks, Inc. | |
7f342629 DS |
6 | */ |
7 | ||
8 | #include <zebra.h> | |
9 | ||
10 | #include "command.h" | |
659f4e40 | 11 | #include "json.h" |
7f342629 DS |
12 | #include "linklist.h" |
13 | #include "memory.h" | |
14 | #include "prefix.h" | |
24a58196 | 15 | #include "frrevent.h" |
7f342629 DS |
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 | ||
659f4e40 | 33 | DEFINE_MTYPE_STATIC(OSPFD, BFD_CONFIG, "BFD configuration data"); |
d62a17ae | 34 | |
7f342629 DS |
35 | /* |
36 | * ospf_bfd_trigger_event - Neighbor is registered/deregistered with BFD when | |
37 | * neighbor state is changed to/from 2way. | |
38 | */ | |
d62a17ae | 39 | void ospf_bfd_trigger_event(struct ospf_neighbor *nbr, int old_state, int state) |
7f342629 | 40 | { |
d62a17ae | 41 | if ((old_state < NSM_TwoWay) && (state >= NSM_TwoWay)) |
659f4e40 | 42 | bfd_sess_install(nbr->bfd_session); |
d62a17ae | 43 | else if ((old_state >= NSM_TwoWay) && (state < NSM_TwoWay)) |
659f4e40 | 44 | bfd_sess_uninstall(nbr->bfd_session); |
7f342629 DS |
45 | } |
46 | ||
659f4e40 RZ |
47 | static void ospf_bfd_session_change(struct bfd_session_params *bsp, |
48 | const struct bfd_session_status *bss, | |
49 | void *arg) | |
7f342629 | 50 | { |
659f4e40 | 51 | struct ospf_neighbor *nbr = arg; |
d62a17ae | 52 | |
659f4e40 RZ |
53 | /* BFD peer went down. */ |
54 | if (bss->state == BFD_STATUS_DOWN | |
55 | && bss->previous_state == BFD_STATUS_UP) { | |
e4505a2e RZ |
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); | |
d62a17ae | 59 | |
659f4e40 | 60 | OSPF_NSM_EVENT_SCHEDULE(nbr, NSM_InactivityTimer); |
d62a17ae | 61 | } |
62 | ||
659f4e40 RZ |
63 | /* BFD peer went up. */ |
64 | if (bss->state == BSS_UP && bss->previous_state == BSS_DOWN) | |
e4505a2e RZ |
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); | |
7f342629 DS |
68 | } |
69 | ||
659f4e40 | 70 | void ospf_neighbor_bfd_apply(struct ospf_neighbor *nbr) |
7f342629 | 71 | { |
659f4e40 RZ |
72 | struct ospf_interface *oi = nbr->oi; |
73 | struct ospf_if_params *oip = IF_DEF_PARAMS(oi->ifp); | |
d62a17ae | 74 | |
659f4e40 RZ |
75 | /* BFD configuration was removed. */ |
76 | if (oip->bfd_config == NULL) { | |
77 | bfd_sess_free(&nbr->bfd_session); | |
78 | return; | |
d62a17ae | 79 | } |
80 | ||
659f4e40 RZ |
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); | |
659f4e40 | 87 | } |
d62a17ae | 88 | |
659f4e40 RZ |
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); | |
d62a17ae | 94 | |
659f4e40 RZ |
95 | /* Don't start sessions on down OSPF sessions. */ |
96 | if (nbr->state < NSM_TwoWay) | |
97 | return; | |
d62a17ae | 98 | |
659f4e40 | 99 | bfd_sess_install(nbr->bfd_session); |
7f342629 DS |
100 | } |
101 | ||
659f4e40 | 102 | static void ospf_interface_bfd_apply(struct interface *ifp) |
7f342629 | 103 | { |
d62a17ae | 104 | struct ospf_interface *oi; |
659f4e40 RZ |
105 | struct route_table *nbrs; |
106 | struct ospf_neighbor *nbr; | |
107 | struct route_node *irn; | |
108 | struct route_node *nrn; | |
6e641a8f | 109 | |
659f4e40 RZ |
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) | |
d62a17ae | 113 | continue; |
659f4e40 | 114 | if ((nbrs = oi->nbrs) == NULL) |
d62a17ae | 115 | continue; |
659f4e40 RZ |
116 | for (nrn = route_top(nbrs); nrn; nrn = route_next(nrn)) { |
117 | if ((nbr = nrn->info) == NULL || nbr == oi->nbr_self) | |
118 | continue; | |
d62a17ae | 119 | |
659f4e40 | 120 | ospf_neighbor_bfd_apply(nbr); |
4828ea77 | 121 | } |
d62a17ae | 122 | } |
7f342629 DS |
123 | } |
124 | ||
659f4e40 | 125 | static void ospf_interface_enable_bfd(struct interface *ifp) |
68fe91d6 | 126 | { |
659f4e40 | 127 | struct ospf_if_params *oip = IF_DEF_PARAMS(ifp); |
d62a17ae | 128 | |
659f4e40 | 129 | if (oip->bfd_config) |
d62a17ae | 130 | return; |
131 | ||
659f4e40 RZ |
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 | } | |
d62a17ae | 138 | |
659f4e40 RZ |
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); | |
68fe91d6 | 144 | } |
145 | ||
7f342629 DS |
146 | /* |
147 | * ospf_bfd_write_config - Write the interface BFD configuration. | |
148 | */ | |
659f4e40 RZ |
149 | void ospf_bfd_write_config(struct vty *vty, const struct ospf_if_params *params |
150 | __attribute__((unused))) | |
7f342629 | 151 | { |
a0841732 | 152 | #if HAVE_BFDD == 0 |
69b34634 IR |
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) | |
659f4e40 RZ |
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); | |
d62a17ae | 159 | else |
a0841732 | 160 | #endif /* ! HAVE_BFDD */ |
d62a17ae | 161 | vty_out(vty, " ip ospf bfd\n"); |
96b52510 RZ |
162 | |
163 | if (params->bfd_config->profile[0]) | |
164 | vty_out(vty, " ip ospf bfd profile %s\n", | |
165 | params->bfd_config->profile); | |
7f342629 DS |
166 | } |
167 | ||
659f4e40 RZ |
168 | void ospf_interface_bfd_show(struct vty *vty, const struct interface *ifp, |
169 | struct json_object *json) | |
68fe91d6 | 170 | { |
659f4e40 RZ |
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; | |
7f342629 | 174 | |
659f4e40 RZ |
175 | if (bfd_config == NULL) |
176 | return; | |
7f342629 | 177 | |
659f4e40 RZ |
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); | |
7f342629 DS |
192 | } |
193 | ||
7f342629 DS |
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 | { | |
d62a17ae | 201 | VTY_DECLVAR_CONTEXT(interface, ifp); |
659f4e40 RZ |
202 | ospf_interface_enable_bfd(ifp); |
203 | ospf_interface_bfd_apply(ifp); | |
d62a17ae | 204 | return CMD_SUCCESS; |
7f342629 DS |
205 | } |
206 | ||
64dc4b2d RZ |
207 | #if HAVE_BFDD > 0 |
208 | DEFUN_HIDDEN( | |
209 | #else | |
210 | DEFUN( | |
211 | #endif /* HAVE_BFDD */ | |
212 | ip_ospf_bfd_param, | |
7f342629 | 213 | ip_ospf_bfd_param_cmd, |
9ccf14f7 | 214 | "ip ospf bfd (2-255) (50-60000) (50-60000)", |
7f342629 DS |
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 | { | |
d62a17ae | 222 | VTY_DECLVAR_CONTEXT(interface, ifp); |
659f4e40 | 223 | struct ospf_if_params *params; |
d62a17ae | 224 | int idx_number = 3; |
225 | int idx_number_2 = 4; | |
226 | int idx_number_3 = 5; | |
d62a17ae | 227 | |
659f4e40 | 228 | ospf_interface_enable_bfd(ifp); |
d62a17ae | 229 | |
659f4e40 RZ |
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); | |
d62a17ae | 235 | |
659f4e40 | 236 | ospf_interface_bfd_apply(ifp); |
d62a17ae | 237 | |
238 | return CMD_SUCCESS; | |
7f342629 DS |
239 | } |
240 | ||
96b52510 RZ |
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 | ||
96b52510 | 254 | params = IF_DEF_PARAMS(ifp); |
f3fd7196 DT |
255 | if (!params->bfd_config) { |
256 | vty_out(vty, "ip ospf bfd has not been set\n"); | |
257 | return CMD_WARNING; | |
258 | } | |
259 | ||
96b52510 RZ |
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 | ||
96b52510 | 280 | params = IF_DEF_PARAMS(ifp); |
f3fd7196 DT |
281 | if (!params->bfd_config) |
282 | return CMD_SUCCESS; | |
283 | ||
96b52510 RZ |
284 | params->bfd_config->profile[0] = 0; |
285 | ospf_interface_bfd_apply(ifp); | |
286 | ||
287 | return CMD_SUCCESS; | |
288 | } | |
289 | ||
7f342629 DS |
290 | DEFUN (no_ip_ospf_bfd, |
291 | no_ip_ospf_bfd_cmd, | |
64dc4b2d RZ |
292 | #if HAVE_BFDD > 0 |
293 | "no ip ospf bfd", | |
294 | #else | |
692b4c65 | 295 | "no ip ospf bfd [(2-255) (50-60000) (50-60000)]", |
64dc4b2d | 296 | #endif /* HAVE_BFDD */ |
7f342629 DS |
297 | NO_STR |
298 | "IP Information\n" | |
299 | "OSPF interface commands\n" | |
692b4c65 | 300 | "Disables BFD support\n" |
64dc4b2d | 301 | #if HAVE_BFDD == 0 |
692b4c65 QY |
302 | "Detect Multiplier\n" |
303 | "Required min receive interval\n" | |
64dc4b2d RZ |
304 | "Desired min transmit interval\n" |
305 | #endif /* !HAVE_BFDD */ | |
306 | ) | |
7f342629 | 307 | { |
d62a17ae | 308 | VTY_DECLVAR_CONTEXT(interface, ifp); |
659f4e40 | 309 | ospf_interface_disable_bfd(ifp, IF_DEF_PARAMS(ifp)); |
d62a17ae | 310 | return CMD_SUCCESS; |
7f342629 DS |
311 | } |
312 | ||
cd9d0537 | 313 | void ospf_bfd_init(struct event_loop *tm) |
7f342629 | 314 | { |
659f4e40 | 315 | bfd_protocol_integration_init(zclient, tm); |
7f342629 | 316 | |
d62a17ae | 317 | /* Install BFD command */ |
318 | install_element(INTERFACE_NODE, &ip_ospf_bfd_cmd); | |
319 | install_element(INTERFACE_NODE, &ip_ospf_bfd_param_cmd); | |
96b52510 RZ |
320 | install_element(INTERFACE_NODE, &ip_ospf_bfd_prof_cmd); |
321 | install_element(INTERFACE_NODE, &no_ip_ospf_bfd_prof_cmd); | |
d62a17ae | 322 | install_element(INTERFACE_NODE, &no_ip_ospf_bfd_cmd); |
7f342629 | 323 | } |