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