]>
Commit | Line | Data |
---|---|---|
5435a2bf | 1 | /* |
63d4bd12 QY |
2 | * VRRP Zebra interfacing. |
3 | * Copyright (C) 2018-2019 Cumulus Networks, Inc. | |
4 | * Quentin Young | |
5435a2bf QY |
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 | ||
b6029d6a | 22 | #include "lib/if.h" |
63d4bd12 | 23 | #include "lib/linklist.h" |
b6029d6a QY |
24 | #include "lib/log.h" |
25 | #include "lib/prefix.h" | |
b6029d6a | 26 | #include "lib/vty.h" |
63d4bd12 | 27 | #include "lib/zclient.h" |
5435a2bf | 28 | |
b6029d6a | 29 | #include "vrrp.h" |
5435a2bf QY |
30 | #include "vrrp_zebra.h" |
31 | ||
b6029d6a QY |
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 | ||
27fd8827 | 64 | vrrp_autoconfig_if_add(ifp); |
b6029d6a QY |
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 | ||
27fd8827 QY |
78 | vrrp_autoconfig_if_del(ifp); |
79 | ||
b6029d6a QY |
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 | ||
27fd8827 QY |
107 | vrrp_autoconfig_if_up(ifp); |
108 | ||
b6029d6a QY |
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 | ||
27fd8827 QY |
135 | vrrp_autoconfig_if_down(ifp); |
136 | ||
b6029d6a QY |
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 | ||
27fd8827 QY |
192 | vrrp_autoconfig_if_address_add(c->ifp); |
193 | ||
b6029d6a QY |
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 | ||
27fd8827 QY |
228 | vrrp_autoconfig_if_address_del(c->ifp); |
229 | ||
b6029d6a QY |
230 | return 0; |
231 | } | |
5435a2bf | 232 | |
f3fe0047 QY |
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 | ||
c3bd894e QY |
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 | ||
5435a2bf QY |
245 | void vrrp_zebra_init(void) |
246 | { | |
b6029d6a QY |
247 | /* Socket for receiving updates from Zebra daemon */ |
248 | zclient = zclient_new(master, &zclient_options_default); | |
5435a2bf | 249 | |
b6029d6a QY |
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; | |
5435a2bf QY |
258 | |
259 | zclient_init(zclient, 0, 0, &vrrp_privs); | |
5435a2bf | 260 | |
b6029d6a QY |
261 | zlog_notice("%s: zclient socket initialized", __PRETTY_FUNCTION__); |
262 | } |