]> git.proxmox.com Git - mirror_frr.git/blob - vrrpd/vrrp_zebra.c
vrrpd: interface tracking
[mirror_frr.git] / vrrpd / vrrp_zebra.c
1 /*
2 * VRRP Zebra interfacing.
3 * Copyright (C) 2018-2019 Cumulus Networks, Inc.
4 * Quentin Young
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the Free
8 * Software Foundation; either version 2 of the License, or (at your option)
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20 #include <zebra.h>
21
22 #include "lib/if.h"
23 #include "lib/linklist.h"
24 #include "lib/log.h"
25 #include "lib/prefix.h"
26 #include "lib/vty.h"
27 #include "lib/zclient.h"
28
29 #include "vrrp.h"
30 #include "vrrp_zebra.h"
31
32 static struct zclient *zclient = NULL;
33
34 static void vrrp_zebra_connected(struct zclient *zclient)
35 {
36 fprintf(stderr, "Zclient connected\n");
37 zclient_send_reg_requests(zclient, VRF_DEFAULT);
38 }
39
40 /* Router-id update message from zebra. */
41 static int vrrp_router_id_update_zebra(int command, struct zclient *zclient,
42 zebra_size_t length, vrf_id_t vrf_id)
43 {
44 struct prefix router_id;
45
46 zebra_router_id_update_read(zclient->ibuf, &router_id);
47
48 return 0;
49 }
50
51 static int vrrp_zebra_if_add(int command, struct zclient *zclient,
52 zebra_size_t length, vrf_id_t vrf_id)
53 {
54 struct interface *ifp;
55
56 /*
57 * zebra api adds/dels interfaces using the same call
58 * interface_add_read below, see comments in lib/zclient.c
59 */
60 ifp = zebra_interface_add_read(zclient->ibuf, vrf_id);
61 if (!ifp)
62 return 0;
63
64 vrrp_if_add(ifp);
65
66 return 0;
67 }
68
69 static int vrrp_zebra_if_del(int command, struct zclient *zclient,
70 zebra_size_t length, vrf_id_t vrf_id)
71 {
72 struct interface *ifp;
73
74 ifp = zebra_interface_state_read(zclient->ibuf, vrf_id);
75 if (!ifp)
76 return 0;
77
78 vrrp_if_del(ifp);
79
80 #if 0
81 if (VRRP_DEBUG_ZEBRA) {
82 zlog_debug(
83 "%s: %s index %d(%u) flags %ld metric %d mtu %d operative %d",
84 __PRETTY_FUNCTION__, ifp->name, ifp->ifindex, vrf_id,
85 (long)ifp->flags, ifp->metric, ifp->mtu,
86 if_is_operative(ifp));
87 }
88 #endif
89
90 return 0;
91 }
92
93 static int vrrp_zebra_if_state_up(int command, struct zclient *zclient,
94 zebra_size_t length, vrf_id_t vrf_id)
95 {
96 struct interface *ifp;
97
98 /*
99 * zebra api notifies interface up/down events by using the same call
100 * zebra_interface_state_read below, see comments in lib/zclient.c ifp =
101 * zebra_interface_state_read(zclient->ibuf, vrf_id);
102 */
103 ifp = zebra_interface_state_read(zclient->ibuf, vrf_id);
104 if (!ifp)
105 return 0;
106
107 vrrp_if_up(ifp);
108
109 #if 0
110 if (VRRP_DEBUG_ZEBRA) {
111 zlog_debug(
112 "%s: %s index %d(%u) flags %ld metric %d mtu %d operative %d",
113 __PRETTY_FUNCTION__, ifp->name, ifp->ifindex, vrf_id,
114 (long)ifp->flags, ifp->metric, ifp->mtu,
115 if_is_operative(ifp));
116 }
117 #endif
118
119 return 0;
120 }
121
122 static int vrrp_zebra_if_state_down(int command, struct zclient *zclient,
123 zebra_size_t length, vrf_id_t vrf_id)
124 {
125 struct interface *ifp;
126
127 /*
128 * zebra api notifies interface up/down events by using the same call
129 * zebra_interface_state_read below, see comments in lib/zclient.c
130 */
131 ifp = zebra_interface_state_read(zclient->ibuf, vrf_id);
132 if (!ifp)
133 return 0;
134
135 vrrp_if_down(ifp);
136
137 #if 0
138 if (VRRP_DEBUG_ZEBRA) {
139 zlog_debug(
140 "%s: %s index %d(%u) flags %ld metric %d mtu %d operative %d",
141 __PRETTY_FUNCTION__, ifp->name, ifp->ifindex, vrf_id,
142 (long)ifp->flags, ifp->metric, ifp->mtu,
143 if_is_operative(ifp));
144 }
145 #endif
146
147 return 0;
148 }
149
150 #ifdef VRRP_DEBUG_IFADDR_DUMP
151 static void dump_if_address(struct interface *ifp)
152 {
153 struct connected *ifc;
154 struct listnode *node;
155
156 zlog_debug("%s %s: interface %s addresses:", __FILE__,
157 __PRETTY_FUNCTION__, ifp->name);
158
159 for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) {
160 struct prefix *p = ifc->address;
161
162 if (p->family != AF_INET)
163 continue;
164
165 zlog_debug("%s %s: interface %s address %s %s", __FILE__,
166 __PRETTY_FUNCTION__, ifp->name,
167 inet_ntoa(p->u.prefix4),
168 CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY)
169 ? "secondary"
170 : "primary");
171 }
172 }
173 #endif
174
175 static int vrrp_zebra_if_address_add(int command, struct zclient *zclient,
176 zebra_size_t length, vrf_id_t vrf_id)
177 {
178 struct connected *c;
179
180 /*
181 * zebra api notifies address adds/dels events by using the same call
182 * interface_add_read below, see comments in lib/zclient.c
183 *
184 * zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_ADD, ...)
185 * will add address to interface list by calling
186 * connected_add_by_prefix()
187 */
188 c = zebra_interface_address_read(command, zclient->ibuf, vrf_id);
189 if (!c)
190 return 0;
191
192 vrrp_if_address_add(c->ifp);
193
194 #if 0
195 if (VRRP_DEBUG_ZEBRA) {
196 char buf[BUFSIZ];
197 prefix2str(p, buf, BUFSIZ);
198 zlog_debug("%s: %s(%u) connected IP address %s flags %u %s",
199 __PRETTY_FUNCTION__, c->ifp->name, vrf_id, buf,
200 c->flags,
201 CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY)
202 ? "secondary"
203 : "primary");
204
205 }
206 #endif
207
208 return 0;
209 }
210
211 static int vrrp_zebra_if_address_del(int command, struct zclient *client,
212 zebra_size_t length, vrf_id_t vrf_id)
213 {
214 struct connected *c;
215
216 /*
217 * zebra api notifies address adds/dels events by using the same call
218 * interface_add_read below, see comments in lib/zclient.c
219 *
220 * zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_DELETE, ...)
221 * will remove address from interface list by calling
222 * connected_delete_by_prefix()
223 */
224 c = zebra_interface_address_read(command, client->ibuf, vrf_id);
225 if (!c)
226 return 0;
227
228 vrrp_if_address_del(c->ifp);
229
230 return 0;
231 }
232
233 void vrrp_zebra_radv_set(struct vrrp_router *r, bool enable)
234 {
235 zclient_send_interface_radv_req(zclient, VRF_DEFAULT, r->mvl_ifp,
236 enable, VRRP_RADV_INT);
237 }
238
239 int vrrp_zclient_send_interface_protodown(struct interface *ifp, bool down)
240 {
241 return zclient_send_interface_protodown(zclient, VRF_DEFAULT, ifp,
242 down);
243 }
244
245 void vrrp_zebra_init(void)
246 {
247 /* Socket for receiving updates from Zebra daemon */
248 zclient = zclient_new(master, &zclient_options_default);
249
250 zclient->zebra_connected = vrrp_zebra_connected;
251 zclient->router_id_update = vrrp_router_id_update_zebra;
252 zclient->interface_add = vrrp_zebra_if_add;
253 zclient->interface_delete = vrrp_zebra_if_del;
254 zclient->interface_up = vrrp_zebra_if_state_up;
255 zclient->interface_down = vrrp_zebra_if_state_down;
256 zclient->interface_address_add = vrrp_zebra_if_address_add;
257 zclient->interface_address_delete = vrrp_zebra_if_address_del;
258
259 zclient_init(zclient, 0, 0, &vrrp_privs);
260
261 zlog_notice("%s: zclient socket initialized", __PRETTY_FUNCTION__);
262 }