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