]> git.proxmox.com Git - mirror_frr.git/blame - lib/bfd.c
This patch changes ospfd from only listening mode for BFD status updates to interacti...
[mirror_frr.git] / lib / bfd.c
CommitLineData
7f342629
DS
1/**
2 * bfd.c: 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
19 * along with GNU Zebra; see the file COPYING. If not, write to the Free
20 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
21 * 02111-1307, USA.
22 */
23
24#include <zebra.h>
25
26#include "command.h"
27#include "memory.h"
28#include "prefix.h"
29#include "thread.h"
30#include "stream.h"
31#include "zclient.h"
32#include "table.h"
33#include "vty.h"
34#include "bfd.h"
35
36/*
37 * bfd_info_create - Allocate the BFD information
38 */
39struct bfd_info *
40bfd_info_create(void)
41{
42 struct bfd_info *bfd_info;
43
44 bfd_info = XCALLOC (MTYPE_BFD_INFO, sizeof (struct bfd_info));
45 assert(bfd_info);
46
47 return bfd_info;
48}
49
50/*
51 * bfd_info_free - Free the BFD information.
52 */
53void
54bfd_info_free(void **bfd_info)
55{
56 if (*bfd_info)
57 {
58 XFREE (MTYPE_BFD_INFO, *bfd_info);
59 *bfd_info = NULL;
60 }
61}
62
63/*
64 * bfd_validate_param - Validate the BFD paramter information.
65 */
66int
67bfd_validate_param(struct vty *vty, const char *dm_str, const char *rx_str,
68 const char *tx_str, u_int8_t *dm_val, u_int32_t *rx_val,
69 u_int32_t *tx_val)
70{
71 VTY_GET_INTEGER_RANGE ("detect-mul", *dm_val, dm_str,
72 BFD_MIN_DETECT_MULT, BFD_MAX_DETECT_MULT);
73 VTY_GET_INTEGER_RANGE ("min-rx", *rx_val, rx_str,
74 BFD_MIN_MIN_RX, BFD_MAX_MIN_RX);
75 VTY_GET_INTEGER_RANGE ("min-tx", *tx_val, tx_str,
76 BFD_MIN_MIN_TX, BFD_MAX_MIN_TX);
77 return CMD_SUCCESS;
78}
79
80/*
81 * bfd_set_param - Set the configured BFD paramter values
82 */
83void
84bfd_set_param (struct bfd_info **bfd_info, u_int32_t min_rx, u_int32_t min_tx,
85 u_int8_t detect_mult, int defaults, int *command)
86{
87 if (!*bfd_info)
88 {
89 *bfd_info = bfd_info_create();
90 *command = ZEBRA_BFD_DEST_REGISTER;
91 }
92 else
93 {
94 if (((*bfd_info)->required_min_rx != min_rx) ||
95 ((*bfd_info)->desired_min_tx != min_tx) ||
96 ((*bfd_info)->detect_mult != detect_mult))
97 *command = ZEBRA_BFD_DEST_UPDATE;
98 }
99
100 if (*command)
101 {
102 (*bfd_info)->required_min_rx = min_rx;
103 (*bfd_info)->desired_min_tx = min_tx;
104 (*bfd_info)->detect_mult = detect_mult;
105 }
106
107 if (!defaults)
108 SET_FLAG ((*bfd_info)->flags, BFD_FLAG_PARAM_CFG);
109 else
110 UNSET_FLAG ((*bfd_info)->flags, BFD_FLAG_PARAM_CFG);
111}
112
113/*
114 * bfd_peer_sendmsg - Format and send a peer register/Unregister
115 * command to Zebra to be forwarded to BFD
116 */
117void
118bfd_peer_sendmsg (struct zclient *zclient, struct bfd_info *bfd_info,
119 int family, void *dst_ip, void *src_ip, char *if_name,
120 int ttl, int multihop, int command, int set_flag)
121{
122 struct stream *s;
123 int ret;
124 int len;
125
126 /* Check socket. */
127 if (!zclient || zclient->sock < 0)
128 {
129 zlog_debug("%s: Can't send BFD peer register, Zebra client not "
130 "established", __FUNCTION__);
131 return;
132 }
133
134 s = zclient->obuf;
135 stream_reset (s);
136 zclient_create_header (s, command);
137
138 stream_putw(s, family);
139 switch (family)
140 {
141 case AF_INET:
142 stream_put_in_addr (s, (struct in_addr *)dst_ip);
143 break;
144#ifdef HAVE_IPV6
145 case AF_INET6:
146 stream_put(s, dst_ip, 16);
147 break;
148#endif
149 default:
150 break;
151 }
152
153 if (command != ZEBRA_BFD_DEST_DEREGISTER)
154 {
155 stream_putl(s, bfd_info->required_min_rx);
156 stream_putl(s, bfd_info->desired_min_tx);
157 stream_putc(s, bfd_info->detect_mult);
158 }
159
160 if (multihop)
161 {
162 stream_putc(s, 1);
163 /* Multi-hop destination send the source IP address to BFD */
164 if (src_ip)
165 {
166 stream_putw(s, family);
167 switch (family)
168 {
169 case AF_INET:
170 stream_put_in_addr (s, (struct in_addr *) src_ip);
171 break;
172 #ifdef HAVE_IPV6
173 case AF_INET6:
174 stream_put(s, src_ip, 16);
175 break;
176 #endif
177 default:
178 break;
179 }
180 }
181 stream_putc(s, ttl);
182 }
183 else
184 {
185 stream_putc(s, 0);
186#ifdef HAVE_IPV6
187 if ((family == AF_INET6) && (src_ip))
188 {
189 stream_putw(s, family);
190 stream_put(s, src_ip, 16);
191 }
192#endif
193 if (if_name)
194 {
195 len = strlen(if_name);
196 stream_putc(s, len);
197 stream_put(s, if_name, len);
198 }
199 else
200 {
201 stream_putc(s, 0);
202 }
203 }
204
205 stream_putw_at (s, 0, stream_get_endp (s));
206
207 ret = zclient_send_message(zclient);
208
209 if (ret < 0)
210 {
211 zlog_warn("bfd_peer_sendmsg: zclient_send_message() failed");
212 return;
213 }
214
215 if (set_flag)
216 {
217 if (command == ZEBRA_BFD_DEST_REGISTER)
218 SET_FLAG(bfd_info->flags, BFD_FLAG_BFD_REG);
219 else if (command == ZEBRA_BFD_DEST_DEREGISTER)
220 UNSET_FLAG(bfd_info->flags, BFD_FLAG_BFD_REG);
221 }
222
223 return;
224}
225
226/*
227 * bfd_get_command_dbg_str - Convert command to a debug string.
228 */
229const char *
230bfd_get_command_dbg_str(int command)
231{
232 switch (command)
233 {
234 case ZEBRA_BFD_DEST_REGISTER:
235 return "Register";
236 case ZEBRA_BFD_DEST_DEREGISTER:
237 return "Deregister";
238 case ZEBRA_BFD_DEST_UPDATE:
239 return "Update";
240 default:
241 return "Unknown";
242 }
243}
244
245/*
246 * bfd_get_peer_info - Extract the Peer information for which the BFD session
247 * went down from the message sent from Zebra to clients.
248 */
249struct interface *
250bfd_get_peer_info (struct stream *s, struct prefix *dp, struct prefix *sp)
251{
252 unsigned int ifindex;
253 struct interface *ifp = NULL;
254 int plen;
255
256 /* Get interface index. */
257 ifindex = stream_getl (s);
258
259 /* Lookup index. */
260 if (ifindex != 0)
261 {
262 ifp = if_lookup_by_index (ifindex);
263 if (ifp == NULL)
264 {
265 zlog_warn ("zebra_interface_bfd_read: "
266 "Can't find interface by ifindex: %d ", ifindex);
267 return NULL;
268 }
269 }
270
271 /* Fetch destination address. */
272 dp->family = stream_getc (s);
273
274 plen = prefix_blen (dp);
275 stream_get (&dp->u.prefix, s, plen);
276 dp->prefixlen = stream_getc (s);
277
278 if (sp)
279 {
280 sp->family = stream_getc (s);
281
282 plen = prefix_blen (sp);
283 stream_get (&sp->u.prefix, s, plen);
284 sp->prefixlen = stream_getc (s);
285 }
286 return ifp;
287}