]> git.proxmox.com Git - mirror_frr.git/blame - sharpd/sharp_zebra.c
sharpd: Re-arrange route_add|delete
[mirror_frr.git] / sharpd / sharp_zebra.c
CommitLineData
8a71d93d
DS
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"
8a71d93d
DS
28#include "stream.h"
29#include "memory.h"
30#include "zclient.h"
8a71d93d 31#include "nexthop.h"
694b242f 32#include "nexthop_group.h"
8a71d93d 33
547dc642 34#include "sharp_globals.h"
86da53ab 35#include "sharp_nht.h"
8a71d93d
DS
36#include "sharp_zebra.h"
37
38/* Zebra structure to hold current status. */
39struct zclient *zclient = NULL;
40
41/* For registering threads. */
04cbc08f 42extern struct thread_master *master;
8a71d93d 43
2be4d61a 44/* Privs info */
04cbc08f 45extern struct zebra_privs_t sharp_privs;
2be4d61a
MS
46
47DEFINE_MTYPE_STATIC(SHARPD, ZC, "Test zclients");
48
49/* Struct to hold list of test zclients */
50struct sharp_zclient {
51 struct sharp_zclient *prev;
52 struct sharp_zclient *next;
53 struct zclient *client;
54};
55
56/* Head of test zclient list */
57static struct sharp_zclient *sharp_clients_head;
58
59static int sharp_opaque_handler(ZAPI_CALLBACK_ARGS);
60
61/* Utility to add a test zclient struct to the list */
62static void add_zclient(struct zclient *client)
63{
64 struct sharp_zclient *node;
65
66 node = XCALLOC(MTYPE_ZC, sizeof(struct sharp_zclient));
67
68 node->client = client;
69
70 node->next = sharp_clients_head;
71 if (sharp_clients_head)
72 sharp_clients_head->prev = node;
73 sharp_clients_head = node;
74}
75
76/* Interface addition message from zebra. */
ef7bd2a3 77static int sharp_ifp_create(struct interface *ifp)
8a71d93d 78{
8a71d93d
DS
79 return 0;
80}
81
3c3c3252 82static int sharp_ifp_destroy(struct interface *ifp)
8a71d93d 83{
8a71d93d
DS
84 return 0;
85}
86
121f9dee 87static int interface_address_add(ZAPI_CALLBACK_ARGS)
8a71d93d 88{
121f9dee 89 zebra_interface_address_read(cmd, zclient->ibuf, vrf_id);
8a71d93d
DS
90
91 return 0;
92}
93
121f9dee 94static int interface_address_delete(ZAPI_CALLBACK_ARGS)
8a71d93d
DS
95{
96 struct connected *c;
97
121f9dee 98 c = zebra_interface_address_read(cmd, zclient->ibuf, vrf_id);
8a71d93d
DS
99
100 if (!c)
101 return 0;
102
721c0857 103 connected_free(&c);
8a71d93d
DS
104 return 0;
105}
106
ddbf3e60 107static int sharp_ifp_up(struct interface *ifp)
8a71d93d 108{
8a71d93d
DS
109 return 0;
110}
111
b0b69e59 112static int sharp_ifp_down(struct interface *ifp)
8a71d93d 113{
8a71d93d
DS
114 return 0;
115}
116
faa75dfa
MS
117int sharp_install_lsps_helper(bool install_p, bool update_p,
118 const struct prefix *p, uint8_t type,
119 int instance, uint32_t in_label,
665edffd
MS
120 const struct nexthop_group *nhg,
121 const struct nexthop_group *backup_nhg)
c9e5adba
MS
122{
123 struct zapi_labels zl = {};
124 struct zapi_nexthop *znh;
125 const struct nexthop *nh;
faa75dfa 126 int i, cmd, ret;
c9e5adba
MS
127
128 zl.type = ZEBRA_LSP_SHARP;
129 zl.local_label = in_label;
130
131 if (p) {
132 SET_FLAG(zl.message, ZAPI_LABELS_FTN);
133 prefix_copy(&zl.route.prefix, p);
134 zl.route.type = type;
135 zl.route.instance = instance;
136 }
137
665edffd 138 /* List of nexthops is optional for delete */
c9e5adba 139 i = 0;
665edffd
MS
140 if (nhg) {
141 for (ALL_NEXTHOPS_PTR(nhg, nh)) {
142 znh = &zl.nexthops[i];
143
144 /* Must have labels to be useful */
145 if (nh->nh_label == NULL ||
146 nh->nh_label->num_labels == 0)
147 continue;
148
149 if (nh->type == NEXTHOP_TYPE_IFINDEX ||
150 nh->type == NEXTHOP_TYPE_BLACKHOLE)
151 /* Hmm - can't really deal with these types */
152 continue;
153
154 ret = zapi_nexthop_from_nexthop(znh, nh);
155 if (ret < 0)
156 return -1;
157
158 i++;
474aebd9
MS
159 if (i >= MULTIPATH_NUM)
160 break;
665edffd
MS
161 }
162 }
c9e5adba 163
665edffd
MS
164 /* Whoops - no nexthops isn't very useful for install */
165 if (i == 0 && install_p)
166 return -1;
c9e5adba 167
665edffd 168 zl.nexthop_num = i;
c9e5adba 169
665edffd
MS
170 /* Add optional backup nexthop info. Since these are used by index,
171 * we can't just skip over an invalid backup nexthop: we will
172 * invalidate the entire operation.
173 */
174 if (backup_nhg != NULL) {
175 i = 0;
176 for (ALL_NEXTHOPS_PTR(backup_nhg, nh)) {
177 znh = &zl.backup_nexthops[i];
c9e5adba 178
665edffd
MS
179 /* Must have labels to be useful */
180 if (nh->nh_label == NULL ||
181 nh->nh_label->num_labels == 0)
182 return -1;
c9e5adba 183
665edffd
MS
184 if (nh->type == NEXTHOP_TYPE_IFINDEX ||
185 nh->type == NEXTHOP_TYPE_BLACKHOLE)
186 /* Hmm - can't really deal with these types */
187 return -1;
c9e5adba 188
665edffd
MS
189 ret = zapi_nexthop_from_nexthop(znh, nh);
190 if (ret < 0)
191 return -1;
192
193 i++;
474aebd9
MS
194 if (i >= MULTIPATH_NUM)
195 break;
665edffd
MS
196 }
197
198 if (i > 0)
199 SET_FLAG(zl.message, ZAPI_LABELS_HAS_BACKUPS);
200
201 zl.backup_nexthop_num = i;
202 }
c9e5adba 203
faa75dfa
MS
204
205 if (install_p) {
206 if (update_p)
207 cmd = ZEBRA_MPLS_LABELS_REPLACE;
208 else
209 cmd = ZEBRA_MPLS_LABELS_ADD;
210 } else {
211 cmd = ZEBRA_MPLS_LABELS_DELETE;
212 }
213
214 ret = zebra_send_mpls_labels(zclient, cmd, &zl);
c9e5adba
MS
215
216 return ret;
217}
218
241e5df1
DS
219/*
220 * route_add - Encodes a route to zebra
221 *
222 * This function returns true when the route was buffered
223 * by the underlying stream system
224 */
225static bool route_add(const struct prefix *p, vrf_id_t vrf_id, uint8_t instance,
226 uint32_t nhgid, const struct nexthop_group *nhg,
227 const struct nexthop_group *backup_nhg)
228{
229 struct zapi_route api;
230 struct zapi_nexthop *api_nh;
231 struct nexthop *nh;
232 int i = 0;
233
234 memset(&api, 0, sizeof(api));
235 api.vrf_id = vrf_id;
236 api.type = ZEBRA_ROUTE_SHARP;
237 api.instance = instance;
238 api.safi = SAFI_UNICAST;
239 memcpy(&api.prefix, p, sizeof(*p));
240
241 SET_FLAG(api.flags, ZEBRA_FLAG_ALLOW_RECURSION);
242 SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
243
244 /* Only send via ID if nhgroup has been successfully installed */
245 if (nhgid && sharp_nhgroup_id_is_installed(nhgid)) {
246 SET_FLAG(api.message, ZAPI_MESSAGE_NHG);
247 api.nhgid = nhgid;
248 } else {
249 for (ALL_NEXTHOPS_PTR(nhg, nh)) {
250 api_nh = &api.nexthops[i];
251
252 zapi_nexthop_from_nexthop(api_nh, nh);
253
254 i++;
255 }
256 api.nexthop_num = i;
257 }
258
259 /* Include backup nexthops, if present */
260 if (backup_nhg && backup_nhg->nexthop) {
261 SET_FLAG(api.message, ZAPI_MESSAGE_BACKUP_NEXTHOPS);
262
263 i = 0;
264 for (ALL_NEXTHOPS_PTR(backup_nhg, nh)) {
265 api_nh = &api.backup_nexthops[i];
266
267 zapi_backup_nexthop_from_nexthop(api_nh, nh);
268
269 i++;
270 }
271
272 api.backup_nexthop_num = i;
273 }
274
275 if (zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api) == 1)
276 return true;
277 else
278 return false;
279}
280
281/*
282 * route_delete - Encodes a route for deletion to zebra
283 *
284 * This function returns true when the route sent was
285 * buffered by the underlying stream system.
286 */
287static bool route_delete(struct prefix *p, vrf_id_t vrf_id, uint8_t instance)
288{
289 struct zapi_route api;
290
291 memset(&api, 0, sizeof(api));
292 api.vrf_id = vrf_id;
293 api.type = ZEBRA_ROUTE_SHARP;
294 api.safi = SAFI_UNICAST;
295 api.instance = instance;
296 memcpy(&api.prefix, p, sizeof(*p));
297
298 if (zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api) == 1)
299 return true;
300 else
301 return false;
302}
303
0cf08685 304void sharp_install_routes_helper(struct prefix *p, vrf_id_t vrf_id,
569e87c0 305 uint8_t instance, uint32_t nhgid,
1df3b1dc
MS
306 const struct nexthop_group *nhg,
307 const struct nexthop_group *backup_nhg,
6b98d34f
DS
308 uint32_t routes)
309{
310 uint32_t temp, i;
dbc1bf46 311 bool v4 = false;
6b98d34f
DS
312
313 zlog_debug("Inserting %u routes", routes);
314
dbc1bf46
DS
315 if (p->family == AF_INET) {
316 v4 = true;
317 temp = ntohl(p->u.prefix4.s_addr);
318 } else
319 temp = ntohl(p->u.val32[3]);
320
1df3b1dc
MS
321 /* Only use backup route/nexthops if present */
322 if (backup_nhg && (backup_nhg->nexthop == NULL))
323 backup_nhg = NULL;
324
547dc642 325 monotime(&sg.r.t_start);
6b98d34f 326 for (i = 0; i < routes; i++) {
569e87c0 327 route_add(p, vrf_id, (uint8_t)instance, nhgid, nhg, backup_nhg);
dbc1bf46
DS
328 if (v4)
329 p->u.prefix4.s_addr = htonl(++temp);
330 else
331 p->u.val32[3] = htonl(++temp);
6b98d34f
DS
332 }
333}
334
0cf08685
DS
335void sharp_remove_routes_helper(struct prefix *p, vrf_id_t vrf_id,
336 uint8_t instance, uint32_t routes)
6b98d34f
DS
337{
338 uint32_t temp, i;
dbc1bf46 339 bool v4 = false;
6b98d34f
DS
340
341 zlog_debug("Removing %u routes", routes);
342
dbc1bf46
DS
343 if (p->family == AF_INET) {
344 v4 = true;
345 temp = ntohl(p->u.prefix4.s_addr);
346 } else
347 temp = ntohl(p->u.val32[3]);
348
547dc642 349 monotime(&sg.r.t_start);
6b98d34f 350 for (i = 0; i < routes; i++) {
0cf08685 351 route_delete(p, vrf_id, (uint8_t)instance);
dbc1bf46
DS
352 if (v4)
353 p->u.prefix4.s_addr = htonl(++temp);
354 else
355 p->u.val32[3] = htonl(++temp);
6b98d34f
DS
356 }
357}
358
b939f6ff 359static void handle_repeated(bool installed)
6b98d34f 360{
547dc642
DS
361 struct prefix p = sg.r.orig_prefix;
362 sg.r.repeat--;
6b98d34f 363
547dc642 364 if (sg.r.repeat <= 0)
6b98d34f
DS
365 return;
366
367 if (installed) {
547dc642 368 sg.r.removed_routes = 0;
0cf08685
DS
369 sharp_remove_routes_helper(&p, sg.r.vrf_id,
370 sg.r.inst, sg.r.total_routes);
6b98d34f
DS
371 }
372
f54f37c1 373 if (!installed) {
547dc642 374 sg.r.installed_routes = 0;
0cf08685 375 sharp_install_routes_helper(&p, sg.r.vrf_id, sg.r.inst,
ff9aca4f 376 sg.r.nhgid, &sg.r.nhop_group,
1df3b1dc 377 &sg.r.backup_nhop_group,
547dc642 378 sg.r.total_routes);
6b98d34f
DS
379 }
380}
381
121f9dee 382static int route_notify_owner(ZAPI_CALLBACK_ARGS)
8a71d93d 383{
25c84d86 384 struct timeval r;
8a71d93d
DS
385 struct prefix p;
386 enum zapi_route_notify_owner note;
28610f7e 387 uint32_t table;
8a71d93d 388
77b38a4a
S
389 if (!zapi_route_notify_decode(zclient->ibuf, &p, &table, &note,
390 NULL, NULL))
8a71d93d
DS
391 return -1;
392
5e54c602
DS
393 switch (note) {
394 case ZAPI_ROUTE_INSTALLED:
547dc642
DS
395 sg.r.installed_routes++;
396 if (sg.r.total_routes == sg.r.installed_routes) {
397 monotime(&sg.r.t_end);
398 timersub(&sg.r.t_end, &sg.r.t_start, &r);
051a0be4
DL
399 zlog_debug("Installed All Items %jd.%ld",
400 (intmax_t)r.tv_sec, (long)r.tv_usec);
6b98d34f
DS
401 handle_repeated(true);
402 }
5e54c602
DS
403 break;
404 case ZAPI_ROUTE_FAIL_INSTALL:
405 zlog_debug("Failed install of route");
406 break;
407 case ZAPI_ROUTE_BETTER_ADMIN_WON:
408 zlog_debug("Better Admin Distance won over us");
409 break;
410 case ZAPI_ROUTE_REMOVED:
547dc642
DS
411 sg.r.removed_routes++;
412 if (sg.r.total_routes == sg.r.removed_routes) {
413 monotime(&sg.r.t_end);
414 timersub(&sg.r.t_end, &sg.r.t_start, &r);
051a0be4
DL
415 zlog_debug("Removed all Items %jd.%ld",
416 (intmax_t)r.tv_sec, (long)r.tv_usec);
6b98d34f
DS
417 handle_repeated(false);
418 }
5e54c602
DS
419 break;
420 case ZAPI_ROUTE_REMOVE_FAIL:
421 zlog_debug("Route removal Failure");
422 break;
423 }
8a71d93d
DS
424 return 0;
425}
426
427static void zebra_connected(struct zclient *zclient)
428{
429 zclient_send_reg_requests(zclient, VRF_DEFAULT);
67a9eda9
DS
430
431 /*
432 * Do not actually turn this on yet
433 * This is just the start of the infrastructure needed here
434 * This can be fixed at a later time.
435 *
436 * zebra_redistribute_send(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP,
437 * ZEBRA_ROUTE_ALL, 0, VRF_DEFAULT);
438 */
8a71d93d
DS
439}
440
7d061b3c 441void vrf_label_add(vrf_id_t vrf_id, afi_t afi, mpls_label_t label)
ab18a495 442{
7d061b3c 443 zclient_send_vrf_label(zclient, vrf_id, afi, label, ZEBRA_LSP_SHARP);
ab18a495
DS
444}
445
21735352
SW
446void nhg_add(uint32_t id, const struct nexthop_group *nhg,
447 const struct nexthop_group *backup_nhg)
569e87c0 448{
c6ce9334 449 struct zapi_nhg api_nhg = {};
569e87c0 450 struct zapi_nexthop *api_nh;
569e87c0
DS
451 struct nexthop *nh;
452
c6ce9334 453 api_nhg.id = id;
569e87c0 454 for (ALL_NEXTHOPS_PTR(nhg, nh)) {
c6ce9334 455 if (api_nhg.nexthop_num >= MULTIPATH_NUM) {
54a701e4
SW
456 zlog_warn(
457 "%s: number of nexthops greater than max multipath size, truncating",
458 __func__);
459 break;
460 }
461
c6ce9334 462 api_nh = &api_nhg.nexthops[api_nhg.nexthop_num];
569e87c0
DS
463
464 zapi_nexthop_from_nexthop(api_nh, nh);
c6ce9334 465 api_nhg.nexthop_num++;
569e87c0
DS
466 }
467
21735352
SW
468 if (backup_nhg) {
469 for (ALL_NEXTHOPS_PTR(backup_nhg, nh)) {
470 if (api_nhg.backup_nexthop_num >= MULTIPATH_NUM) {
471 zlog_warn(
472 "%s: number of backup nexthops greater than max multipath size, truncating",
473 __func__);
474 break;
475 }
476 api_nh = &api_nhg.backup_nexthops
477 [api_nhg.backup_nexthop_num];
478
479 zapi_backup_nexthop_from_nexthop(api_nh, nh);
480 api_nhg.backup_nexthop_num++;
481 }
482 }
483
c6ce9334 484 zclient_nhg_send(zclient, ZEBRA_NHG_ADD, &api_nhg);
569e87c0
DS
485}
486
487void nhg_del(uint32_t id)
488{
c6ce9334
SW
489 struct zapi_nhg api_nhg = {};
490
491 api_nhg.id = id;
492
493 zclient_nhg_send(zclient, ZEBRA_NHG_DEL, &api_nhg);
569e87c0
DS
494}
495
91529dc8 496void sharp_zebra_nexthop_watch(struct prefix *p, vrf_id_t vrf_id, bool import,
b47dc61a 497 bool watch, bool connected)
0ae8130d 498{
b47dc61a 499 int command;
0ae8130d 500
b47dc61a
DS
501 if (!import) {
502 command = ZEBRA_NEXTHOP_REGISTER;
503
504 if (!watch)
505 command = ZEBRA_NEXTHOP_UNREGISTER;
506 } else {
507 command = ZEBRA_IMPORT_ROUTE_REGISTER;
508
509 if (!watch)
510 command = ZEBRA_IMPORT_ROUTE_UNREGISTER;
511 }
0ae8130d 512
91529dc8 513 if (zclient_send_rnh(zclient, command, p, connected, vrf_id) < 0)
15569c58 514 zlog_warn("%s: Failure to send nexthop to zebra", __func__);
0ae8130d
DS
515}
516
67a9eda9 517static int sharp_debug_nexthops(struct zapi_route *api)
0ae8130d 518{
0ae8130d 519 int i;
67a9eda9 520 char buf[PREFIX_STRLEN];
0ae8130d 521
8b85b2cb
MS
522 if (api->nexthop_num == 0) {
523 zlog_debug(
524 " Not installed");
525 return 0;
526 }
527
67a9eda9
DS
528 for (i = 0; i < api->nexthop_num; i++) {
529 struct zapi_nexthop *znh = &api->nexthops[i];
0ae8130d
DS
530
531 switch (znh->type) {
532 case NEXTHOP_TYPE_IPV4_IFINDEX:
533 case NEXTHOP_TYPE_IPV4:
534 zlog_debug(
d6951e5e 535 " Nexthop %s, type: %d, ifindex: %d, vrf: %d, label_num: %d",
0ae8130d
DS
536 inet_ntop(AF_INET, &znh->gate.ipv4.s_addr, buf,
537 sizeof(buf)),
538 znh->type, znh->ifindex, znh->vrf_id,
539 znh->label_num);
540 break;
541 case NEXTHOP_TYPE_IPV6_IFINDEX:
542 case NEXTHOP_TYPE_IPV6:
543 zlog_debug(
d6951e5e 544 " Nexthop %s, type: %d, ifindex: %d, vrf: %d, label_num: %d",
0ae8130d
DS
545 inet_ntop(AF_INET6, &znh->gate.ipv6, buf,
546 sizeof(buf)),
547 znh->type, znh->ifindex, znh->vrf_id,
548 znh->label_num);
549 break;
550 case NEXTHOP_TYPE_IFINDEX:
d6951e5e 551 zlog_debug(" Nexthop IFINDEX: %d, ifindex: %d",
0ae8130d
DS
552 znh->type, znh->ifindex);
553 break;
554 case NEXTHOP_TYPE_BLACKHOLE:
d6951e5e 555 zlog_debug(" Nexthop blackhole");
0ae8130d
DS
556 break;
557 }
558 }
67a9eda9
DS
559
560 return i;
561}
562static int sharp_nexthop_update(ZAPI_CALLBACK_ARGS)
563{
564 struct sharp_nh_tracker *nht;
565 struct zapi_route nhr;
566
567 if (!zapi_nexthop_update_decode(zclient->ibuf, &nhr)) {
6c83dded 568 zlog_err("%s: Decode of update failed", __func__);
67a9eda9
DS
569 return 0;
570 }
571
572 zlog_debug("Received update for %pFX", &nhr.prefix);
573
574 nht = sharp_nh_tracker_get(&nhr.prefix);
575 nht->nhop_num = nhr.nexthop_num;
576 nht->updates++;
577
578 sharp_debug_nexthops(&nhr);
579
580 return 0;
581}
582
583static int sharp_redistribute_route(ZAPI_CALLBACK_ARGS)
584{
585 struct zapi_route api;
586
587 if (zapi_route_decode(zclient->ibuf, &api) < 0)
15569c58 588 zlog_warn("%s: Decode of redistribute failed: %d", __func__,
67a9eda9
DS
589 ZEBRA_REDISTRIBUTE_ROUTE_ADD);
590
591 zlog_debug("%s: %pFX (%s)", zserv_command_string(cmd),
592 &api.prefix, zebra_route_string(api.type));
593
594 sharp_debug_nexthops(&api);
595
0ae8130d
DS
596 return 0;
597}
598
2be4d61a
MS
599/* Add a zclient with a specified session id, for testing. */
600int sharp_zclient_create(uint32_t session_id)
601{
602 struct zclient *client;
603 struct sharp_zclient *node;
604
605 /* Check for duplicates */
606 for (node = sharp_clients_head; node != NULL; node = node->next) {
607 if (node->client->session_id == session_id)
608 return -1;
609 }
610
611 client = zclient_new(master, &zclient_options_default);
612 client->sock = -1;
613 client->session_id = session_id;
614
615 zclient_init(client, ZEBRA_ROUTE_SHARP, 0, &sharp_privs);
616
617 /* Register handlers for messages we expect this session to see */
618 client->opaque_msg_handler = sharp_opaque_handler;
619
620 /* Enqueue on the list of test clients */
621 add_zclient(client);
622
623 return 0;
624}
625
626/* Delete one of the extra test zclients */
627int sharp_zclient_delete(uint32_t session_id)
628{
629 struct sharp_zclient *node;
630
631 /* Search for session */
632 for (node = sharp_clients_head; node != NULL; node = node->next) {
633 if (node->client->session_id == session_id) {
634 /* Dequeue from list */
635 if (node->next)
636 node->next->prev = node->prev;
637 if (node->prev)
638 node->prev->next = node->next;
639 if (node == sharp_clients_head)
640 sharp_clients_head = node->next;
641
642 /* Clean up zclient */
643 zclient_stop(node->client);
644 zclient_free(node->client);
645
646 /* Free memory */
647 XFREE(MTYPE_ZC, node);
648 break;
649 }
650 }
651
652 return 0;
653}
654
7f5ac773
MS
655/* Handler for opaque messages */
656static int sharp_opaque_handler(ZAPI_CALLBACK_ARGS)
657{
7f5ac773 658 struct stream *s;
387831ff 659 struct zapi_opaque_msg info;
7f5ac773
MS
660
661 s = zclient->ibuf;
662
387831ff
MS
663 if (zclient_opaque_decode(s, &info) != 0)
664 return -1;
7f5ac773 665
2be4d61a 666 zlog_debug("%s: [%u] received opaque type %u", __func__,
c8b27f2a 667 zclient->session_id, info.type);
7f5ac773
MS
668
669 return 0;
670}
671
2ac6c90d
MS
672/*
673 * Send OPAQUE messages, using subtype 'type'.
674 */
c8b27f2a
MS
675void sharp_opaque_send(uint32_t type, uint32_t proto, uint32_t instance,
676 uint32_t session_id, uint32_t count)
2ac6c90d 677{
7f5ac773 678 uint8_t buf[32];
2ac6c90d
MS
679 int ret;
680 uint32_t i;
681
682 /* Prepare a small payload */
683 for (i = 0; i < sizeof(buf); i++) {
684 if (type < 255)
685 buf[i] = type;
686 else
687 buf[i] = 255;
688 }
689
c8b27f2a 690 /* Send some messages - broadcast and unicast are supported */
2ac6c90d 691 for (i = 0; i < count; i++) {
c8b27f2a
MS
692 if (proto == 0)
693 ret = zclient_send_opaque(zclient, type, buf,
694 sizeof(buf));
695 else
696 ret = zclient_send_opaque_unicast(zclient, type, proto,
697 instance, session_id,
698 buf, sizeof(buf));
2ac6c90d
MS
699 if (ret < 0) {
700 zlog_debug("%s: send_opaque() failed => %d",
701 __func__, ret);
702 break;
703 }
704 }
705
706}
707
939b2339
MS
708/*
709 * Send OPAQUE registration messages, using subtype 'type'.
710 */
711void sharp_opaque_reg_send(bool is_reg, uint32_t proto, uint32_t instance,
712 uint32_t session_id, uint32_t type)
713{
714 struct stream *s;
715
716 s = zclient->obuf;
717 stream_reset(s);
718
719 if (is_reg)
720 zclient_create_header(s, ZEBRA_OPAQUE_REGISTER, VRF_DEFAULT);
721 else
722 zclient_create_header(s, ZEBRA_OPAQUE_UNREGISTER, VRF_DEFAULT);
723
724 /* Send sub-type */
725 stream_putl(s, type);
726
727 /* Add zclient info */
728 stream_putc(s, proto);
729 stream_putw(s, instance);
730 stream_putl(s, session_id);
731
732 /* Put length at the first point of the stream. */
733 stream_putw_at(s, 0, stream_get_endp(s));
734
735 (void)zclient_send_message(zclient);
736
737}
738
da187b77
JU
739void sharp_zebra_send_arp(const struct interface *ifp, const struct prefix *p)
740{
741 zclient_send_neigh_discovery_req(zclient, ifp, p);
742}
743
2053061b
SW
744static int nhg_notify_owner(ZAPI_CALLBACK_ARGS)
745{
746 enum zapi_nhg_notify_owner note;
747 uint32_t id;
748
749 if (!zapi_nhg_notify_decode(zclient->ibuf, &id, &note))
750 return -1;
751
752 switch (note) {
753 case ZAPI_NHG_INSTALLED:
754 sharp_nhgroup_id_set_installed(id, true);
755 zlog_debug("Installed nhg %u", id);
756 break;
757 case ZAPI_NHG_FAIL_INSTALL:
758 zlog_debug("Failed install of nhg %u", id);
759 break;
760 case ZAPI_NHG_REMOVED:
761 zlog_debug("Removed nhg %u", id);
762 break;
763 case ZAPI_NHG_REMOVE_FAIL:
764 zlog_debug("Failed removal of nhg %u", id);
765 break;
766 }
767
768 return 0;
769}
770
8a71d93d
DS
771void sharp_zebra_init(void)
772{
996c9314 773 struct zclient_options opt = {.receive_notify = true};
8a71d93d 774
138c5a74
DS
775 if_zapi_callbacks(sharp_ifp_create, sharp_ifp_up,
776 sharp_ifp_down, sharp_ifp_destroy);
777
26f63a1e 778 zclient = zclient_new(master, &opt);
8a71d93d
DS
779
780 zclient_init(zclient, ZEBRA_ROUTE_SHARP, 0, &sharp_privs);
781 zclient->zebra_connected = zebra_connected;
8a71d93d
DS
782 zclient->interface_address_add = interface_address_add;
783 zclient->interface_address_delete = interface_address_delete;
28b11f81 784 zclient->route_notify_owner = route_notify_owner;
0ae8130d 785 zclient->nexthop_update = sharp_nexthop_update;
b47dc61a 786 zclient->import_check_update = sharp_nexthop_update;
2053061b 787 zclient->nhg_notify_owner = nhg_notify_owner;
67a9eda9
DS
788
789 zclient->redistribute_route_add = sharp_redistribute_route;
790 zclient->redistribute_route_del = sharp_redistribute_route;
7f5ac773 791 zclient->opaque_msg_handler = sharp_opaque_handler;
8a71d93d 792}