]> git.proxmox.com Git - mirror_frr.git/blob - sharpd/sharp_zebra.c
*: Convert from ->interface_up to the interface callback
[mirror_frr.git] / sharpd / sharp_zebra.c
1 /*
2 * Zebra connect code.
3 * Copyright (C) Cumulus Networks, Inc.
4 * Donald Sharp
5 *
6 * This file is part of 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 "thread.h"
25 #include "command.h"
26 #include "network.h"
27 #include "prefix.h"
28 #include "routemap.h"
29 #include "table.h"
30 #include "stream.h"
31 #include "memory.h"
32 #include "zclient.h"
33 #include "filter.h"
34 #include "plist.h"
35 #include "log.h"
36 #include "nexthop.h"
37 #include "nexthop_group.h"
38
39 #include "sharp_globals.h"
40 #include "sharp_nht.h"
41 #include "sharp_zebra.h"
42
43 /* Zebra structure to hold current status. */
44 struct zclient *zclient = NULL;
45
46 /* For registering threads. */
47 extern struct thread_master *master;
48
49 /* Inteface addition message from zebra. */
50 static int sharp_ifp_create(struct interface *ifp)
51 {
52 return 0;
53 }
54
55 static int interface_delete(ZAPI_CALLBACK_ARGS)
56 {
57 struct interface *ifp;
58 struct stream *s;
59
60 s = zclient->ibuf;
61 /* zebra_interface_state_read () updates interface structure in iflist
62 */
63 ifp = zebra_interface_state_read(s, vrf_id);
64
65 if (ifp == NULL)
66 return 0;
67
68 if_set_index(ifp, IFINDEX_INTERNAL);
69
70 return 0;
71 }
72
73 static int interface_address_add(ZAPI_CALLBACK_ARGS)
74 {
75
76 zebra_interface_address_read(cmd, zclient->ibuf, vrf_id);
77
78 return 0;
79 }
80
81 static int interface_address_delete(ZAPI_CALLBACK_ARGS)
82 {
83 struct connected *c;
84
85 c = zebra_interface_address_read(cmd, zclient->ibuf, vrf_id);
86
87 if (!c)
88 return 0;
89
90 connected_free(c);
91 return 0;
92 }
93
94 static int sharp_ifp_up(struct interface *ifp)
95 {
96 return 0;
97 }
98
99 static int interface_state_down(ZAPI_CALLBACK_ARGS)
100 {
101
102 zebra_interface_state_read(zclient->ibuf, vrf_id);
103
104 return 0;
105 }
106
107 void sharp_install_routes_helper(struct prefix *p, vrf_id_t vrf_id,
108 uint8_t instance, struct nexthop_group *nhg,
109 uint32_t routes)
110 {
111 uint32_t temp, i;
112 bool v4 = false;
113
114 zlog_debug("Inserting %u routes", routes);
115
116 if (p->family == AF_INET) {
117 v4 = true;
118 temp = ntohl(p->u.prefix4.s_addr);
119 } else
120 temp = ntohl(p->u.val32[3]);
121
122 monotime(&sg.r.t_start);
123 for (i = 0; i < routes; i++) {
124 route_add(p, vrf_id, (uint8_t)instance, nhg);
125 if (v4)
126 p->u.prefix4.s_addr = htonl(++temp);
127 else
128 p->u.val32[3] = htonl(++temp);
129 }
130 }
131
132 void sharp_remove_routes_helper(struct prefix *p, vrf_id_t vrf_id,
133 uint8_t instance, uint32_t routes)
134 {
135 uint32_t temp, i;
136 bool v4 = false;
137
138 zlog_debug("Removing %u routes", routes);
139
140 if (p->family == AF_INET) {
141 v4 = true;
142 temp = ntohl(p->u.prefix4.s_addr);
143 } else
144 temp = ntohl(p->u.val32[3]);
145
146 monotime(&sg.r.t_start);
147 for (i = 0; i < routes; i++) {
148 route_delete(p, vrf_id, (uint8_t)instance);
149 if (v4)
150 p->u.prefix4.s_addr = htonl(++temp);
151 else
152 p->u.val32[3] = htonl(++temp);
153 }
154 }
155
156 static void handle_repeated(bool installed)
157 {
158 struct prefix p = sg.r.orig_prefix;
159 sg.r.repeat--;
160
161 if (sg.r.repeat <= 0)
162 return;
163
164 if (installed) {
165 sg.r.removed_routes = 0;
166 sharp_remove_routes_helper(&p, sg.r.vrf_id,
167 sg.r.inst, sg.r.total_routes);
168 }
169
170 if (!installed) {
171 sg.r.installed_routes = 0;
172 sharp_install_routes_helper(&p, sg.r.vrf_id, sg.r.inst,
173 &sg.r.nhop_group,
174 sg.r.total_routes);
175 }
176 }
177
178 static int route_notify_owner(ZAPI_CALLBACK_ARGS)
179 {
180 struct timeval r;
181 struct prefix p;
182 enum zapi_route_notify_owner note;
183 uint32_t table;
184
185 if (!zapi_route_notify_decode(zclient->ibuf, &p, &table, &note))
186 return -1;
187
188 switch (note) {
189 case ZAPI_ROUTE_INSTALLED:
190 sg.r.installed_routes++;
191 if (sg.r.total_routes == sg.r.installed_routes) {
192 monotime(&sg.r.t_end);
193 timersub(&sg.r.t_end, &sg.r.t_start, &r);
194 zlog_debug("Installed All Items %jd.%ld",
195 (intmax_t)r.tv_sec, (long)r.tv_usec);
196 handle_repeated(true);
197 }
198 break;
199 case ZAPI_ROUTE_FAIL_INSTALL:
200 zlog_debug("Failed install of route");
201 break;
202 case ZAPI_ROUTE_BETTER_ADMIN_WON:
203 zlog_debug("Better Admin Distance won over us");
204 break;
205 case ZAPI_ROUTE_REMOVED:
206 sg.r.removed_routes++;
207 if (sg.r.total_routes == sg.r.removed_routes) {
208 monotime(&sg.r.t_end);
209 timersub(&sg.r.t_end, &sg.r.t_start, &r);
210 zlog_debug("Removed all Items %jd.%ld",
211 (intmax_t)r.tv_sec, (long)r.tv_usec);
212 handle_repeated(false);
213 }
214 break;
215 case ZAPI_ROUTE_REMOVE_FAIL:
216 zlog_debug("Route removal Failure");
217 break;
218 }
219 return 0;
220 }
221
222 static void zebra_connected(struct zclient *zclient)
223 {
224 zclient_send_reg_requests(zclient, VRF_DEFAULT);
225 }
226
227 void vrf_label_add(vrf_id_t vrf_id, afi_t afi, mpls_label_t label)
228 {
229 zclient_send_vrf_label(zclient, vrf_id, afi, label, ZEBRA_LSP_SHARP);
230 }
231
232 void route_add(struct prefix *p, vrf_id_t vrf_id,
233 uint8_t instance, struct nexthop_group *nhg)
234 {
235 struct zapi_route api;
236 struct zapi_nexthop *api_nh;
237 struct nexthop *nh;
238 int i = 0;
239
240 memset(&api, 0, sizeof(api));
241 api.vrf_id = vrf_id;
242 api.type = ZEBRA_ROUTE_SHARP;
243 api.instance = instance;
244 api.safi = SAFI_UNICAST;
245 memcpy(&api.prefix, p, sizeof(*p));
246
247 SET_FLAG(api.flags, ZEBRA_FLAG_ALLOW_RECURSION);
248 SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
249
250 for (ALL_NEXTHOPS_PTR(nhg, nh)) {
251 api_nh = &api.nexthops[i];
252 api_nh->vrf_id = nh->vrf_id;
253 api_nh->type = nh->type;
254 switch (nh->type) {
255 case NEXTHOP_TYPE_IPV4:
256 api_nh->gate = nh->gate;
257 break;
258 case NEXTHOP_TYPE_IPV4_IFINDEX:
259 api_nh->gate = nh->gate;
260 api_nh->ifindex = nh->ifindex;
261 break;
262 case NEXTHOP_TYPE_IFINDEX:
263 api_nh->ifindex = nh->ifindex;
264 break;
265 case NEXTHOP_TYPE_IPV6:
266 memcpy(&api_nh->gate.ipv6, &nh->gate.ipv6, 16);
267 break;
268 case NEXTHOP_TYPE_IPV6_IFINDEX:
269 api_nh->ifindex = nh->ifindex;
270 memcpy(&api_nh->gate.ipv6, &nh->gate.ipv6, 16);
271 break;
272 case NEXTHOP_TYPE_BLACKHOLE:
273 api_nh->bh_type = nh->bh_type;
274 break;
275 }
276 i++;
277 }
278 api.nexthop_num = i;
279
280 zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api);
281 }
282
283 void route_delete(struct prefix *p, vrf_id_t vrf_id, uint8_t instance)
284 {
285 struct zapi_route api;
286
287 memset(&api, 0, sizeof(api));
288 api.vrf_id = vrf_id;
289 api.type = ZEBRA_ROUTE_SHARP;
290 api.safi = SAFI_UNICAST;
291 api.instance = instance;
292 memcpy(&api.prefix, p, sizeof(*p));
293 zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api);
294
295 return;
296 }
297
298 void sharp_zebra_nexthop_watch(struct prefix *p, vrf_id_t vrf_id, bool import,
299 bool watch, bool connected)
300 {
301 int command;
302
303 if (!import) {
304 command = ZEBRA_NEXTHOP_REGISTER;
305
306 if (!watch)
307 command = ZEBRA_NEXTHOP_UNREGISTER;
308 } else {
309 command = ZEBRA_IMPORT_ROUTE_REGISTER;
310
311 if (!watch)
312 command = ZEBRA_IMPORT_ROUTE_UNREGISTER;
313 }
314
315 if (zclient_send_rnh(zclient, command, p, connected, vrf_id) < 0)
316 zlog_warn("%s: Failure to send nexthop to zebra",
317 __PRETTY_FUNCTION__);
318 }
319
320 static int sharp_nexthop_update(ZAPI_CALLBACK_ARGS)
321 {
322 struct sharp_nh_tracker *nht;
323 struct zapi_route nhr;
324 char buf[PREFIX_STRLEN];
325 int i;
326
327 if (!zapi_nexthop_update_decode(zclient->ibuf, &nhr)) {
328 zlog_warn("%s: Decode of update failed", __PRETTY_FUNCTION__);
329
330 return 0;
331 }
332
333 zlog_debug("Received update for %s",
334 prefix2str(&nhr.prefix, buf, sizeof(buf)));
335
336 nht = sharp_nh_tracker_get(&nhr.prefix);
337 nht->nhop_num = nhr.nexthop_num;
338 nht->updates++;
339
340 for (i = 0; i < nhr.nexthop_num; i++) {
341 struct zapi_nexthop *znh = &nhr.nexthops[i];
342
343 switch (znh->type) {
344 case NEXTHOP_TYPE_IPV4_IFINDEX:
345 case NEXTHOP_TYPE_IPV4:
346 zlog_debug(
347 "\tNexthop %s, type: %d, ifindex: %d, vrf: %d, label_num: %d",
348 inet_ntop(AF_INET, &znh->gate.ipv4.s_addr, buf,
349 sizeof(buf)),
350 znh->type, znh->ifindex, znh->vrf_id,
351 znh->label_num);
352 break;
353 case NEXTHOP_TYPE_IPV6_IFINDEX:
354 case NEXTHOP_TYPE_IPV6:
355 zlog_debug(
356 "\tNexthop %s, type: %d, ifindex: %d, vrf: %d, label_num: %d",
357 inet_ntop(AF_INET6, &znh->gate.ipv6, buf,
358 sizeof(buf)),
359 znh->type, znh->ifindex, znh->vrf_id,
360 znh->label_num);
361 break;
362 case NEXTHOP_TYPE_IFINDEX:
363 zlog_debug("\tNexthop IFINDEX: %d, ifindex: %d",
364 znh->type, znh->ifindex);
365 break;
366 case NEXTHOP_TYPE_BLACKHOLE:
367 zlog_debug("\tNexthop blackhole");
368 break;
369 }
370 }
371 return 0;
372 }
373
374 static int sharp_ifp_down(struct interface *ifp)
375 {
376 return 0;
377 }
378
379 static int sharp_ifp_destroy(struct interface *ifp)
380 {
381 return 0;
382 }
383
384 extern struct zebra_privs_t sharp_privs;
385
386 void sharp_zebra_init(void)
387 {
388 struct zclient_options opt = {.receive_notify = true};
389
390 if_zapi_callbacks(sharp_ifp_create, sharp_ifp_up,
391 sharp_ifp_down, sharp_ifp_destroy);
392
393 zclient = zclient_new(master, &opt);
394
395 zclient_init(zclient, ZEBRA_ROUTE_SHARP, 0, &sharp_privs);
396 zclient->zebra_connected = zebra_connected;
397 zclient->interface_delete = interface_delete;
398 zclient->interface_down = interface_state_down;
399 zclient->interface_address_add = interface_address_add;
400 zclient->interface_address_delete = interface_address_delete;
401 zclient->route_notify_owner = route_notify_owner;
402 zclient->nexthop_update = sharp_nexthop_update;
403 zclient->import_check_update = sharp_nexthop_update;
404 }