]> git.proxmox.com Git - mirror_frr.git/blame - isisd/isis_bfd.c
isisd: Register/deregister BFD peers for adjacencies
[mirror_frr.git] / isisd / isis_bfd.c
CommitLineData
52df8228
CF
1/*
2 * IS-IS Rout(e)ing protocol - BFD support
3 *
4 * Copyright (C) 2018 Christian Franke
5 *
6 * This file is part of FreeRangeRouting (FRR)
7 *
8 * FRR 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 * FRR 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#include <zebra.h>
23
24#include "zclient.h"
25#include "bfd.h"
26
27#include "isisd/isis_bfd.h"
28#include "isisd/isis_zebra.h"
215eccb0
CF
29#include "isisd/isis_common.h"
30#include "isisd/isis_constants.h"
31#include "isisd/isis_adjacency.h"
32#include "isisd/isis_circuit.h"
3015e3d1 33#include "isisd/isisd.h"
215eccb0 34#include "isisd/fabricd.h"
52df8228 35
20a42f01
CF
36DEFINE_MTYPE_STATIC(ISISD, BFD_SESSION, "ISIS BFD Session")
37
38struct bfd_session {
39 struct in_addr dst_ip;
40 struct in_addr src_ip;
41};
42
43static struct bfd_session *bfd_session_new(struct in_addr *dst_ip,
44 struct in_addr *src_ip)
45{
46 struct bfd_session *rv;
47
48 rv = XMALLOC(MTYPE_BFD_SESSION, sizeof(*rv));
49 rv->dst_ip = *dst_ip;
50 rv->src_ip = *src_ip;
51 return rv;
52}
53
54static void bfd_session_free(struct bfd_session **session)
55{
56 if (!*session)
57 return;
58
59 XFREE(MTYPE_BFD_SESSION, *session);
60 *session = NULL;
61}
62
52df8228
CF
63static int isis_bfd_interface_dest_update(int command, struct zclient *zclient,
64 zebra_size_t length, vrf_id_t vrf_id)
65{
66 return 0;
67}
68
69static int isis_bfd_nbr_replay(int command, struct zclient *zclient,
70 zebra_size_t length, vrf_id_t vrf_id)
71{
72 bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER);
73 return 0;
74}
75
76static void (*orig_zebra_connected)(struct zclient *);
77static void isis_bfd_zebra_connected(struct zclient *zclient)
78{
79 if (orig_zebra_connected)
80 orig_zebra_connected(zclient);
81
82 bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER);
83}
84
20a42f01
CF
85static void bfd_handle_adj_down(struct isis_adjacency *adj)
86{
87 if (!adj->bfd_session)
88 return;
89
90 bfd_peer_sendmsg(zclient, NULL, AF_INET,
91 &adj->bfd_session->dst_ip,
92 &adj->bfd_session->src_ip,
93 adj->circuit->interface->name,
94 0, /* ttl */
95 0, /* multihop */
96 ZEBRA_BFD_DEST_DEREGISTER,
97 0, /* set_flag */
98 VRF_DEFAULT);
99 bfd_session_free(&adj->bfd_session);
100}
101
102static void bfd_handle_adj_up(struct isis_adjacency *adj, int command)
215eccb0 103{
20a42f01
CF
104 struct isis_circuit *circuit = adj->circuit;
105
106 if (!circuit->bfd_info
107 || !circuit->ip_router
108 || !adj->ipv4_address_count)
109 goto out;
110
111 struct list *local_ips = fabricd_ip_addrs(adj->circuit);
112 if (!local_ips)
113 goto out;
114
115 struct in_addr *dst_ip = &adj->ipv4_addresses[0];
116 struct prefix_ipv4 *local_ip = listgetdata(listhead(local_ips));
117 struct in_addr *src_ip = &local_ip->prefix;
118
119 if (adj->bfd_session) {
120 if (adj->bfd_session->dst_ip.s_addr != dst_ip->s_addr
121 || adj->bfd_session->src_ip.s_addr != src_ip->s_addr)
122 bfd_handle_adj_down(adj);
123 }
124
125 if (!adj->bfd_session)
126 adj->bfd_session = bfd_session_new(dst_ip, src_ip);
127
128 bfd_peer_sendmsg(zclient, circuit->bfd_info, AF_INET,
129 &adj->bfd_session->dst_ip,
130 &adj->bfd_session->src_ip,
131 circuit->interface->name,
132 0, /* ttl */
133 0, /* multihop */
134 command,
135 0, /* set flag */
136 VRF_DEFAULT);
215eccb0 137 return;
20a42f01
CF
138out:
139 bfd_handle_adj_down(adj);
140}
141
142static int bfd_handle_adj_state_change(struct isis_adjacency *adj)
143{
144 if (adj->adj_state == ISIS_ADJ_UP)
145 bfd_handle_adj_up(adj, ZEBRA_BFD_DEST_REGISTER);
146 else
147 bfd_handle_adj_down(adj);
148 return 0;
149}
150
151static void bfd_adj_cmd(struct isis_adjacency *adj, int command)
152{
153 if (adj->adj_state == ISIS_ADJ_UP
154 && command != ZEBRA_BFD_DEST_DEREGISTER) {
155 bfd_handle_adj_up(adj, command);
156 } else {
157 bfd_handle_adj_down(adj);
158 }
159}
160
161void isis_bfd_circuit_cmd(struct isis_circuit *circuit, int command)
162{
163 switch (circuit->circ_type) {
164 case CIRCUIT_T_BROADCAST:
165 for (int level = ISIS_LEVEL1; level <= ISIS_LEVEL2; level++) {
166 struct list *adjdb = circuit->u.bc.adjdb[level - 1];
167
168 struct listnode *node;
169 struct isis_adjacency *adj;
170 for (ALL_LIST_ELEMENTS_RO(adjdb, node, adj))
171 bfd_adj_cmd(adj, command);
172 }
173 break;
174 case CIRCUIT_T_P2P:
175 if (circuit->u.p2p.neighbor)
176 bfd_adj_cmd(circuit->u.p2p.neighbor, command);
177 break;
178 default:
179 break;
180 }
215eccb0
CF
181}
182
183void isis_bfd_circuit_param_set(struct isis_circuit *circuit,
184 uint32_t min_rx, uint32_t min_tx,
185 uint32_t detect_mult, int defaults)
186{
187 int command = 0;
188
189 bfd_set_param(&circuit->bfd_info, min_rx,
190 min_tx, detect_mult, defaults, &command);
191
192 if (command)
193 isis_bfd_circuit_cmd(circuit, command);
194}
195
3015e3d1
CF
196static int bfd_circuit_write_settings(struct isis_circuit *circuit,
197 struct vty *vty)
198{
199 struct bfd_info *bfd_info = circuit->bfd_info;
200
201 if (!bfd_info)
202 return 0;
203
204#if HAVE_BFDD == 0
205 if (CHECK_FLAG(bfd_info->flags, BFD_FLAG_PARAM_CFG)) {
206 vty_out(vty, " %s bfd %" PRIu8 " %" PRIu32 " %" PRIu32 "\n",
207 PROTO_NAME, bfd_info->detect_mult,
208 bfd_info->required_min_rx, bfd_info->desired_min_tx);
209 } else
210#endif
211 vty_out(vty, " %s bfd\n", PROTO_NAME);
212 return 1;
213}
214
52df8228
CF
215void isis_bfd_init(void)
216{
217 bfd_gbl_init();
218
219 orig_zebra_connected = zclient->zebra_connected;
220 zclient->zebra_connected = isis_bfd_zebra_connected;
221 zclient->interface_bfd_dest_update = isis_bfd_interface_dest_update;
222 zclient->bfd_dest_replay = isis_bfd_nbr_replay;
20a42f01
CF
223 hook_register(isis_adj_state_change_hook,
224 bfd_handle_adj_state_change);
3015e3d1
CF
225 hook_register(isis_circuit_config_write,
226 bfd_circuit_write_settings);
52df8228 227}