]> git.proxmox.com Git - mirror_frr.git/blob - sharpd/sharp_zebra.c
Merge pull request #8230 from donaldsharp/flex_more
[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 "stream.h"
29 #include "memory.h"
30 #include "zclient.h"
31 #include "nexthop.h"
32 #include "nexthop_group.h"
33
34 #include "sharp_globals.h"
35 #include "sharp_nht.h"
36 #include "sharp_zebra.h"
37
38 /* Zebra structure to hold current status. */
39 struct zclient *zclient = NULL;
40
41 /* For registering threads. */
42 extern struct thread_master *master;
43
44 /* Privs info */
45 extern struct zebra_privs_t sharp_privs;
46
47 DEFINE_MTYPE_STATIC(SHARPD, ZC, "Test zclients");
48
49 /* Struct to hold list of test zclients */
50 struct sharp_zclient {
51 struct sharp_zclient *prev;
52 struct sharp_zclient *next;
53 struct zclient *client;
54 };
55
56 /* Head of test zclient list */
57 static struct sharp_zclient *sharp_clients_head;
58
59 static int sharp_opaque_handler(ZAPI_CALLBACK_ARGS);
60
61 /* Utility to add a test zclient struct to the list */
62 static 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. */
77 static int sharp_ifp_create(struct interface *ifp)
78 {
79 return 0;
80 }
81
82 static int sharp_ifp_destroy(struct interface *ifp)
83 {
84 return 0;
85 }
86
87 static int interface_address_add(ZAPI_CALLBACK_ARGS)
88 {
89 zebra_interface_address_read(cmd, zclient->ibuf, vrf_id);
90
91 return 0;
92 }
93
94 static int interface_address_delete(ZAPI_CALLBACK_ARGS)
95 {
96 struct connected *c;
97
98 c = zebra_interface_address_read(cmd, zclient->ibuf, vrf_id);
99
100 if (!c)
101 return 0;
102
103 connected_free(&c);
104 return 0;
105 }
106
107 static int sharp_ifp_up(struct interface *ifp)
108 {
109 return 0;
110 }
111
112 static int sharp_ifp_down(struct interface *ifp)
113 {
114 return 0;
115 }
116
117 int 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,
120 const struct nexthop_group *nhg,
121 const struct nexthop_group *backup_nhg)
122 {
123 struct zapi_labels zl = {};
124 struct zapi_nexthop *znh;
125 const struct nexthop *nh;
126 int i, cmd, ret;
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
138 /* List of nexthops is optional for delete */
139 i = 0;
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++;
159 if (i >= MULTIPATH_NUM)
160 break;
161 }
162 }
163
164 /* Whoops - no nexthops isn't very useful for install */
165 if (i == 0 && install_p)
166 return -1;
167
168 zl.nexthop_num = i;
169
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];
178
179 /* Must have labels to be useful */
180 if (nh->nh_label == NULL ||
181 nh->nh_label->num_labels == 0)
182 return -1;
183
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;
188
189 ret = zapi_nexthop_from_nexthop(znh, nh);
190 if (ret < 0)
191 return -1;
192
193 i++;
194 if (i >= MULTIPATH_NUM)
195 break;
196 }
197
198 if (i > 0)
199 SET_FLAG(zl.message, ZAPI_LABELS_HAS_BACKUPS);
200
201 zl.backup_nexthop_num = i;
202 }
203
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 if (zebra_send_mpls_labels(zclient, cmd, &zl) == ZCLIENT_SEND_FAILURE)
215 return -1;
216
217 return 0;
218 }
219
220 enum where_to_restart {
221 SHARP_INSTALL_ROUTES_RESTART,
222 SHARP_DELETE_ROUTES_RESTART,
223 };
224
225 struct buffer_delay {
226 struct prefix p;
227 uint32_t count;
228 uint32_t routes;
229 vrf_id_t vrf_id;
230 uint8_t instance;
231 uint32_t nhgid;
232 const struct nexthop_group *nhg;
233 const struct nexthop_group *backup_nhg;
234 enum where_to_restart restart;
235 char *opaque;
236 } wb;
237
238 /*
239 * route_add - Encodes a route to zebra
240 *
241 * This function returns true when the route was buffered
242 * by the underlying stream system
243 */
244 static bool route_add(const struct prefix *p, vrf_id_t vrf_id, uint8_t instance,
245 uint32_t nhgid, const struct nexthop_group *nhg,
246 const struct nexthop_group *backup_nhg, char *opaque)
247 {
248 struct zapi_route api;
249 struct zapi_nexthop *api_nh;
250 struct nexthop *nh;
251 int i = 0;
252
253 memset(&api, 0, sizeof(api));
254 api.vrf_id = vrf_id;
255 api.type = ZEBRA_ROUTE_SHARP;
256 api.instance = instance;
257 api.safi = SAFI_UNICAST;
258 memcpy(&api.prefix, p, sizeof(*p));
259
260 SET_FLAG(api.flags, ZEBRA_FLAG_ALLOW_RECURSION);
261 SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
262
263 /* Only send via ID if nhgroup has been successfully installed */
264 if (nhgid && sharp_nhgroup_id_is_installed(nhgid)) {
265 SET_FLAG(api.message, ZAPI_MESSAGE_NHG);
266 api.nhgid = nhgid;
267 } else {
268 for (ALL_NEXTHOPS_PTR(nhg, nh)) {
269 api_nh = &api.nexthops[i];
270
271 zapi_nexthop_from_nexthop(api_nh, nh);
272
273 i++;
274 }
275 api.nexthop_num = i;
276 }
277
278 /* Include backup nexthops, if present */
279 if (backup_nhg && backup_nhg->nexthop) {
280 SET_FLAG(api.message, ZAPI_MESSAGE_BACKUP_NEXTHOPS);
281
282 i = 0;
283 for (ALL_NEXTHOPS_PTR(backup_nhg, nh)) {
284 api_nh = &api.backup_nexthops[i];
285
286 zapi_backup_nexthop_from_nexthop(api_nh, nh);
287
288 i++;
289 }
290
291 api.backup_nexthop_num = i;
292 }
293
294 if (strlen(opaque)) {
295 SET_FLAG(api.message, ZAPI_MESSAGE_OPAQUE);
296 api.opaque.length = strlen(opaque) + 1;
297 assert(api.opaque.length <= ZAPI_MESSAGE_OPAQUE_LENGTH);
298 memcpy(api.opaque.data, opaque, api.opaque.length);
299 }
300
301 if (zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api)
302 == ZCLIENT_SEND_BUFFERED)
303 return true;
304 else
305 return false;
306 }
307
308 /*
309 * route_delete - Encodes a route for deletion to zebra
310 *
311 * This function returns true when the route sent was
312 * buffered by the underlying stream system.
313 */
314 static bool route_delete(struct prefix *p, vrf_id_t vrf_id, uint8_t instance)
315 {
316 struct zapi_route api;
317
318 memset(&api, 0, sizeof(api));
319 api.vrf_id = vrf_id;
320 api.type = ZEBRA_ROUTE_SHARP;
321 api.safi = SAFI_UNICAST;
322 api.instance = instance;
323 memcpy(&api.prefix, p, sizeof(*p));
324
325 if (zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api)
326 == ZCLIENT_SEND_BUFFERED)
327 return true;
328 else
329 return false;
330 }
331
332 static void sharp_install_routes_restart(struct prefix *p, uint32_t count,
333 vrf_id_t vrf_id, uint8_t instance,
334 uint32_t nhgid,
335 const struct nexthop_group *nhg,
336 const struct nexthop_group *backup_nhg,
337 uint32_t routes, char *opaque)
338 {
339 uint32_t temp, i;
340 bool v4 = false;
341
342 if (p->family == AF_INET) {
343 v4 = true;
344 temp = ntohl(p->u.prefix4.s_addr);
345 } else
346 temp = ntohl(p->u.val32[3]);
347
348 for (i = count; i < routes; i++) {
349 bool buffered = route_add(p, vrf_id, (uint8_t)instance, nhgid,
350 nhg, backup_nhg, opaque);
351 if (v4)
352 p->u.prefix4.s_addr = htonl(++temp);
353 else
354 p->u.val32[3] = htonl(++temp);
355
356 if (buffered) {
357 wb.p = *p;
358 wb.count = i+1;
359 wb.routes = routes;
360 wb.vrf_id = vrf_id;
361 wb.instance = instance;
362 wb.nhgid = nhgid;
363 wb.nhg = nhg;
364 wb.backup_nhg = backup_nhg;
365 wb.opaque = opaque;
366 wb.restart = SHARP_INSTALL_ROUTES_RESTART;
367
368 return;
369 }
370 }
371 }
372
373 void sharp_install_routes_helper(struct prefix *p, vrf_id_t vrf_id,
374 uint8_t instance, uint32_t nhgid,
375 const struct nexthop_group *nhg,
376 const struct nexthop_group *backup_nhg,
377 uint32_t routes, char *opaque)
378 {
379 zlog_debug("Inserting %u routes", routes);
380
381 /* Only use backup route/nexthops if present */
382 if (backup_nhg && (backup_nhg->nexthop == NULL))
383 backup_nhg = NULL;
384
385 monotime(&sg.r.t_start);
386 sharp_install_routes_restart(p, 0, vrf_id, instance, nhgid, nhg,
387 backup_nhg, routes, opaque);
388 }
389
390 static void sharp_remove_routes_restart(struct prefix *p, uint32_t count,
391 vrf_id_t vrf_id, uint8_t instance,
392 uint32_t routes)
393 {
394 uint32_t temp, i;
395 bool v4 = false;
396
397 if (p->family == AF_INET) {
398 v4 = true;
399 temp = ntohl(p->u.prefix4.s_addr);
400 } else
401 temp = ntohl(p->u.val32[3]);
402
403 for (i = count; i < routes; i++) {
404 bool buffered = route_delete(p, vrf_id, (uint8_t)instance);
405
406 if (v4)
407 p->u.prefix4.s_addr = htonl(++temp);
408 else
409 p->u.val32[3] = htonl(++temp);
410
411 if (buffered) {
412 wb.p = *p;
413 wb.count = i + 1;
414 wb.vrf_id = vrf_id;
415 wb.instance = instance;
416 wb.routes = routes;
417 wb.restart = SHARP_DELETE_ROUTES_RESTART;
418
419 return;
420 }
421 }
422 }
423
424 void sharp_remove_routes_helper(struct prefix *p, vrf_id_t vrf_id,
425 uint8_t instance, uint32_t routes)
426 {
427 zlog_debug("Removing %u routes", routes);
428
429 monotime(&sg.r.t_start);
430
431 sharp_remove_routes_restart(p, 0, vrf_id, instance, routes);
432 }
433
434 static void handle_repeated(bool installed)
435 {
436 struct prefix p = sg.r.orig_prefix;
437 sg.r.repeat--;
438
439 if (sg.r.repeat <= 0)
440 return;
441
442 if (installed) {
443 sg.r.removed_routes = 0;
444 sharp_remove_routes_helper(&p, sg.r.vrf_id,
445 sg.r.inst, sg.r.total_routes);
446 }
447
448 if (!installed) {
449 sg.r.installed_routes = 0;
450 sharp_install_routes_helper(&p, sg.r.vrf_id, sg.r.inst,
451 sg.r.nhgid, &sg.r.nhop_group,
452 &sg.r.backup_nhop_group,
453 sg.r.total_routes, sg.r.opaque);
454 }
455 }
456
457 static void sharp_zclient_buffer_ready(void)
458 {
459 switch (wb.restart) {
460 case SHARP_INSTALL_ROUTES_RESTART:
461 sharp_install_routes_restart(
462 &wb.p, wb.count, wb.vrf_id, wb.instance, wb.nhgid,
463 wb.nhg, wb.backup_nhg, wb.routes, wb.opaque);
464 return;
465 case SHARP_DELETE_ROUTES_RESTART:
466 sharp_remove_routes_restart(&wb.p, wb.count, wb.vrf_id,
467 wb.instance, wb.routes);
468 return;
469 }
470 }
471
472 static int route_notify_owner(ZAPI_CALLBACK_ARGS)
473 {
474 struct timeval r;
475 struct prefix p;
476 enum zapi_route_notify_owner note;
477 uint32_t table;
478
479 if (!zapi_route_notify_decode(zclient->ibuf, &p, &table, &note,
480 NULL, NULL))
481 return -1;
482
483 switch (note) {
484 case ZAPI_ROUTE_INSTALLED:
485 sg.r.installed_routes++;
486 if (sg.r.total_routes == sg.r.installed_routes) {
487 monotime(&sg.r.t_end);
488 timersub(&sg.r.t_end, &sg.r.t_start, &r);
489 zlog_debug("Installed All Items %jd.%ld",
490 (intmax_t)r.tv_sec, (long)r.tv_usec);
491 handle_repeated(true);
492 }
493 break;
494 case ZAPI_ROUTE_FAIL_INSTALL:
495 zlog_debug("Failed install of route");
496 break;
497 case ZAPI_ROUTE_BETTER_ADMIN_WON:
498 zlog_debug("Better Admin Distance won over us");
499 break;
500 case ZAPI_ROUTE_REMOVED:
501 sg.r.removed_routes++;
502 if (sg.r.total_routes == sg.r.removed_routes) {
503 monotime(&sg.r.t_end);
504 timersub(&sg.r.t_end, &sg.r.t_start, &r);
505 zlog_debug("Removed all Items %jd.%ld",
506 (intmax_t)r.tv_sec, (long)r.tv_usec);
507 handle_repeated(false);
508 }
509 break;
510 case ZAPI_ROUTE_REMOVE_FAIL:
511 zlog_debug("Route removal Failure");
512 break;
513 }
514 return 0;
515 }
516
517 static void zebra_connected(struct zclient *zclient)
518 {
519 zclient_send_reg_requests(zclient, VRF_DEFAULT);
520
521 /*
522 * Do not actually turn this on yet
523 * This is just the start of the infrastructure needed here
524 * This can be fixed at a later time.
525 *
526 * zebra_redistribute_send(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP,
527 * ZEBRA_ROUTE_ALL, 0, VRF_DEFAULT);
528 */
529 }
530
531 void vrf_label_add(vrf_id_t vrf_id, afi_t afi, mpls_label_t label)
532 {
533 zclient_send_vrf_label(zclient, vrf_id, afi, label, ZEBRA_LSP_SHARP);
534 }
535
536 void nhg_add(uint32_t id, const struct nexthop_group *nhg,
537 const struct nexthop_group *backup_nhg)
538 {
539 struct zapi_nhg api_nhg = {};
540 struct zapi_nexthop *api_nh;
541 struct nexthop *nh;
542 bool is_valid = true;
543
544 api_nhg.id = id;
545 for (ALL_NEXTHOPS_PTR(nhg, nh)) {
546 if (api_nhg.nexthop_num >= MULTIPATH_NUM) {
547 zlog_warn(
548 "%s: number of nexthops greater than max multipath size, truncating",
549 __func__);
550 break;
551 }
552
553 /* Unresolved nexthops will lead to failure - only send
554 * nexthops that zebra will consider valid.
555 */
556 if (nh->ifindex == 0)
557 continue;
558
559 api_nh = &api_nhg.nexthops[api_nhg.nexthop_num];
560
561 zapi_nexthop_from_nexthop(api_nh, nh);
562 api_nhg.nexthop_num++;
563 }
564
565 if (api_nhg.nexthop_num == 0) {
566 zlog_debug("%s: nhg %u not sent: no valid nexthops",
567 __func__, id);
568 is_valid = false;
569 goto done;
570 }
571
572 if (backup_nhg) {
573 for (ALL_NEXTHOPS_PTR(backup_nhg, nh)) {
574 if (api_nhg.backup_nexthop_num >= MULTIPATH_NUM) {
575 zlog_warn(
576 "%s: number of backup nexthops greater than max multipath size, truncating",
577 __func__);
578 break;
579 }
580
581 /* Unresolved nexthop: will be rejected by zebra.
582 * That causes a problem, since the primary nexthops
583 * rely on array indexing into the backup nexthops. If
584 * that array isn't valid, the backup indexes won't be
585 * valid.
586 */
587 if (nh->ifindex == 0) {
588 zlog_debug("%s: nhg %u: invalid backup nexthop",
589 __func__, id);
590 is_valid = false;
591 break;
592 }
593
594 api_nh = &api_nhg.backup_nexthops
595 [api_nhg.backup_nexthop_num];
596
597 zapi_backup_nexthop_from_nexthop(api_nh, nh);
598 api_nhg.backup_nexthop_num++;
599 }
600 }
601
602 done:
603 if (is_valid)
604 zclient_nhg_send(zclient, ZEBRA_NHG_ADD, &api_nhg);
605 }
606
607 void nhg_del(uint32_t id)
608 {
609 struct zapi_nhg api_nhg = {};
610
611 api_nhg.id = id;
612
613 zclient_nhg_send(zclient, ZEBRA_NHG_DEL, &api_nhg);
614 }
615
616 void sharp_zebra_nexthop_watch(struct prefix *p, vrf_id_t vrf_id, bool import,
617 bool watch, bool connected)
618 {
619 int command;
620
621 if (!import) {
622 command = ZEBRA_NEXTHOP_REGISTER;
623
624 if (!watch)
625 command = ZEBRA_NEXTHOP_UNREGISTER;
626 } else {
627 command = ZEBRA_IMPORT_ROUTE_REGISTER;
628
629 if (!watch)
630 command = ZEBRA_IMPORT_ROUTE_UNREGISTER;
631 }
632
633 if (zclient_send_rnh(zclient, command, p, connected, vrf_id)
634 == ZCLIENT_SEND_FAILURE)
635 zlog_warn("%s: Failure to send nexthop to zebra", __func__);
636 }
637
638 static int sharp_debug_nexthops(struct zapi_route *api)
639 {
640 int i;
641
642 if (api->nexthop_num == 0) {
643 zlog_debug(
644 " Not installed");
645 return 0;
646 }
647
648 for (i = 0; i < api->nexthop_num; i++) {
649 struct zapi_nexthop *znh = &api->nexthops[i];
650
651 switch (znh->type) {
652 case NEXTHOP_TYPE_IPV4_IFINDEX:
653 case NEXTHOP_TYPE_IPV4:
654 zlog_debug(
655 " Nexthop %pI4, type: %d, ifindex: %d, vrf: %d, label_num: %d",
656 &znh->gate.ipv4.s_addr, znh->type, znh->ifindex,
657 znh->vrf_id, znh->label_num);
658 break;
659 case NEXTHOP_TYPE_IPV6_IFINDEX:
660 case NEXTHOP_TYPE_IPV6:
661 zlog_debug(
662 " Nexthop %pI6, type: %d, ifindex: %d, vrf: %d, label_num: %d",
663 &znh->gate.ipv6, znh->type, znh->ifindex,
664 znh->vrf_id, znh->label_num);
665 break;
666 case NEXTHOP_TYPE_IFINDEX:
667 zlog_debug(" Nexthop IFINDEX: %d, ifindex: %d",
668 znh->type, znh->ifindex);
669 break;
670 case NEXTHOP_TYPE_BLACKHOLE:
671 zlog_debug(" Nexthop blackhole");
672 break;
673 }
674 }
675
676 return i;
677 }
678 static int sharp_nexthop_update(ZAPI_CALLBACK_ARGS)
679 {
680 struct sharp_nh_tracker *nht;
681 struct zapi_route nhr;
682
683 if (!zapi_nexthop_update_decode(zclient->ibuf, &nhr)) {
684 zlog_err("%s: Decode of update failed", __func__);
685 return 0;
686 }
687
688 zlog_debug("Received update for %pFX", &nhr.prefix);
689
690 nht = sharp_nh_tracker_get(&nhr.prefix);
691 nht->nhop_num = nhr.nexthop_num;
692 nht->updates++;
693
694 sharp_debug_nexthops(&nhr);
695
696 return 0;
697 }
698
699 static int sharp_redistribute_route(ZAPI_CALLBACK_ARGS)
700 {
701 struct zapi_route api;
702
703 if (zapi_route_decode(zclient->ibuf, &api) < 0)
704 zlog_warn("%s: Decode of redistribute failed: %d", __func__,
705 ZEBRA_REDISTRIBUTE_ROUTE_ADD);
706
707 zlog_debug("%s: %pFX (%s)", zserv_command_string(cmd),
708 &api.prefix, zebra_route_string(api.type));
709
710 sharp_debug_nexthops(&api);
711
712 return 0;
713 }
714
715 /* Add a zclient with a specified session id, for testing. */
716 int sharp_zclient_create(uint32_t session_id)
717 {
718 struct zclient *client;
719 struct sharp_zclient *node;
720
721 /* Check for duplicates */
722 for (node = sharp_clients_head; node != NULL; node = node->next) {
723 if (node->client->session_id == session_id)
724 return -1;
725 }
726
727 client = zclient_new(master, &zclient_options_default);
728 client->sock = -1;
729 client->session_id = session_id;
730
731 zclient_init(client, ZEBRA_ROUTE_SHARP, 0, &sharp_privs);
732
733 /* Register handlers for messages we expect this session to see */
734 client->opaque_msg_handler = sharp_opaque_handler;
735
736 /* Enqueue on the list of test clients */
737 add_zclient(client);
738
739 return 0;
740 }
741
742 /* Delete one of the extra test zclients */
743 int sharp_zclient_delete(uint32_t session_id)
744 {
745 struct sharp_zclient *node;
746
747 /* Search for session */
748 for (node = sharp_clients_head; node != NULL; node = node->next) {
749 if (node->client->session_id == session_id) {
750 /* Dequeue from list */
751 if (node->next)
752 node->next->prev = node->prev;
753 if (node->prev)
754 node->prev->next = node->next;
755 if (node == sharp_clients_head)
756 sharp_clients_head = node->next;
757
758 /* Clean up zclient */
759 zclient_stop(node->client);
760 zclient_free(node->client);
761
762 /* Free memory */
763 XFREE(MTYPE_ZC, node);
764 break;
765 }
766 }
767
768 return 0;
769 }
770
771 /* Handler for opaque messages */
772 static int sharp_opaque_handler(ZAPI_CALLBACK_ARGS)
773 {
774 struct stream *s;
775 struct zapi_opaque_msg info;
776
777 s = zclient->ibuf;
778
779 if (zclient_opaque_decode(s, &info) != 0)
780 return -1;
781
782 zlog_debug("%s: [%u] received opaque type %u", __func__,
783 zclient->session_id, info.type);
784
785 return 0;
786 }
787
788 /*
789 * Send OPAQUE messages, using subtype 'type'.
790 */
791 void sharp_opaque_send(uint32_t type, uint32_t proto, uint32_t instance,
792 uint32_t session_id, uint32_t count)
793 {
794 uint8_t buf[32];
795 int ret;
796 uint32_t i;
797
798 /* Prepare a small payload */
799 for (i = 0; i < sizeof(buf); i++) {
800 if (type < 255)
801 buf[i] = type;
802 else
803 buf[i] = 255;
804 }
805
806 /* Send some messages - broadcast and unicast are supported */
807 for (i = 0; i < count; i++) {
808 if (proto == 0)
809 ret = zclient_send_opaque(zclient, type, buf,
810 sizeof(buf));
811 else
812 ret = zclient_send_opaque_unicast(zclient, type, proto,
813 instance, session_id,
814 buf, sizeof(buf));
815 if (ret == ZCLIENT_SEND_FAILURE) {
816 zlog_debug("%s: send_opaque() failed => %d",
817 __func__, ret);
818 break;
819 }
820 }
821
822 }
823
824 /*
825 * Send OPAQUE registration messages, using subtype 'type'.
826 */
827 void sharp_opaque_reg_send(bool is_reg, uint32_t proto, uint32_t instance,
828 uint32_t session_id, uint32_t type)
829 {
830 struct stream *s;
831
832 s = zclient->obuf;
833 stream_reset(s);
834
835 if (is_reg)
836 zclient_create_header(s, ZEBRA_OPAQUE_REGISTER, VRF_DEFAULT);
837 else
838 zclient_create_header(s, ZEBRA_OPAQUE_UNREGISTER, VRF_DEFAULT);
839
840 /* Send sub-type */
841 stream_putl(s, type);
842
843 /* Add zclient info */
844 stream_putc(s, proto);
845 stream_putw(s, instance);
846 stream_putl(s, session_id);
847
848 /* Put length at the first point of the stream. */
849 stream_putw_at(s, 0, stream_get_endp(s));
850
851 (void)zclient_send_message(zclient);
852
853 }
854
855 void sharp_zebra_send_arp(const struct interface *ifp, const struct prefix *p)
856 {
857 zclient_send_neigh_discovery_req(zclient, ifp, p);
858 }
859
860 static int nhg_notify_owner(ZAPI_CALLBACK_ARGS)
861 {
862 enum zapi_nhg_notify_owner note;
863 uint32_t id;
864
865 if (!zapi_nhg_notify_decode(zclient->ibuf, &id, &note))
866 return -1;
867
868 switch (note) {
869 case ZAPI_NHG_INSTALLED:
870 sharp_nhgroup_id_set_installed(id, true);
871 zlog_debug("Installed nhg %u", id);
872 break;
873 case ZAPI_NHG_FAIL_INSTALL:
874 zlog_debug("Failed install of nhg %u", id);
875 break;
876 case ZAPI_NHG_REMOVED:
877 zlog_debug("Removed nhg %u", id);
878 break;
879 case ZAPI_NHG_REMOVE_FAIL:
880 zlog_debug("Failed removal of nhg %u", id);
881 break;
882 }
883
884 return 0;
885 }
886
887 void sharp_zebra_init(void)
888 {
889 struct zclient_options opt = {.receive_notify = true};
890
891 if_zapi_callbacks(sharp_ifp_create, sharp_ifp_up,
892 sharp_ifp_down, sharp_ifp_destroy);
893
894 zclient = zclient_new(master, &opt);
895
896 zclient_init(zclient, ZEBRA_ROUTE_SHARP, 0, &sharp_privs);
897 zclient->zebra_connected = zebra_connected;
898 zclient->interface_address_add = interface_address_add;
899 zclient->interface_address_delete = interface_address_delete;
900 zclient->route_notify_owner = route_notify_owner;
901 zclient->nexthop_update = sharp_nexthop_update;
902 zclient->import_check_update = sharp_nexthop_update;
903 zclient->nhg_notify_owner = nhg_notify_owner;
904 zclient->zebra_buffer_write_ready = sharp_zclient_buffer_ready;
905 zclient->redistribute_route_add = sharp_redistribute_route;
906 zclient->redistribute_route_del = sharp_redistribute_route;
907 zclient->opaque_msg_handler = sharp_opaque_handler;
908 }