1 // SPDX-License-Identifier: GPL-2.0-or-later
4 * Copyright (C) Cumulus Networks, Inc.
17 #include "nexthop_group.h"
18 #include "link_state.h"
21 #include "sharp_globals.h"
22 #include "sharp_nht.h"
23 #include "sharp_zebra.h"
25 /* Zebra structure to hold current status. */
26 struct zclient
*zclient
= NULL
;
28 /* For registering threads. */
29 extern struct event_loop
*master
;
32 extern struct zebra_privs_t sharp_privs
;
34 DEFINE_MTYPE_STATIC(SHARPD
, ZC
, "Test zclients");
36 /* Struct to hold list of test zclients */
37 struct sharp_zclient
{
38 struct sharp_zclient
*prev
;
39 struct sharp_zclient
*next
;
40 struct zclient
*client
;
43 /* Head of test zclient list */
44 static struct sharp_zclient
*sharp_clients_head
;
46 static int sharp_opaque_handler(ZAPI_CALLBACK_ARGS
);
48 /* Utility to add a test zclient struct to the list */
49 static void add_zclient(struct zclient
*client
)
51 struct sharp_zclient
*node
;
53 node
= XCALLOC(MTYPE_ZC
, sizeof(struct sharp_zclient
));
55 node
->client
= client
;
57 node
->next
= sharp_clients_head
;
58 if (sharp_clients_head
)
59 sharp_clients_head
->prev
= node
;
60 sharp_clients_head
= node
;
63 /* Interface addition message from zebra. */
64 static int sharp_ifp_create(struct interface
*ifp
)
69 static int sharp_ifp_destroy(struct interface
*ifp
)
74 static int interface_address_add(ZAPI_CALLBACK_ARGS
)
76 zebra_interface_address_read(cmd
, zclient
->ibuf
, vrf_id
);
81 static int interface_address_delete(ZAPI_CALLBACK_ARGS
)
85 c
= zebra_interface_address_read(cmd
, zclient
->ibuf
, vrf_id
);
94 static int sharp_ifp_up(struct interface
*ifp
)
99 static int sharp_ifp_down(struct interface
*ifp
)
104 int sharp_install_lsps_helper(bool install_p
, bool update_p
,
105 const struct prefix
*p
, uint8_t type
,
106 int instance
, uint32_t in_label
,
107 const struct nexthop_group
*nhg
,
108 const struct nexthop_group
*backup_nhg
)
110 struct zapi_labels zl
= {};
111 struct zapi_nexthop
*znh
;
112 const struct nexthop
*nh
;
115 zl
.type
= ZEBRA_LSP_SHARP
;
116 zl
.local_label
= in_label
;
119 SET_FLAG(zl
.message
, ZAPI_LABELS_FTN
);
120 prefix_copy(&zl
.route
.prefix
, p
);
121 zl
.route
.type
= type
;
122 zl
.route
.instance
= instance
;
125 /* List of nexthops is optional for delete */
128 for (ALL_NEXTHOPS_PTR(nhg
, nh
)) {
129 znh
= &zl
.nexthops
[i
];
131 /* Must have labels to be useful */
132 if (nh
->nh_label
== NULL
||
133 nh
->nh_label
->num_labels
== 0)
136 if (nh
->type
== NEXTHOP_TYPE_IFINDEX
||
137 nh
->type
== NEXTHOP_TYPE_BLACKHOLE
)
138 /* Hmm - can't really deal with these types */
141 ret
= zapi_nexthop_from_nexthop(znh
, nh
);
146 if (i
>= MULTIPATH_NUM
)
151 /* Whoops - no nexthops isn't very useful for install */
152 if (i
== 0 && install_p
)
157 /* Add optional backup nexthop info. Since these are used by index,
158 * we can't just skip over an invalid backup nexthop: we will
159 * invalidate the entire operation.
161 if (backup_nhg
!= NULL
) {
163 for (ALL_NEXTHOPS_PTR(backup_nhg
, nh
)) {
164 znh
= &zl
.backup_nexthops
[i
];
166 /* Must have labels to be useful */
167 if (nh
->nh_label
== NULL
||
168 nh
->nh_label
->num_labels
== 0)
171 if (nh
->type
== NEXTHOP_TYPE_IFINDEX
||
172 nh
->type
== NEXTHOP_TYPE_BLACKHOLE
)
173 /* Hmm - can't really deal with these types */
176 ret
= zapi_nexthop_from_nexthop(znh
, nh
);
181 if (i
>= MULTIPATH_NUM
)
186 SET_FLAG(zl
.message
, ZAPI_LABELS_HAS_BACKUPS
);
188 zl
.backup_nexthop_num
= i
;
194 cmd
= ZEBRA_MPLS_LABELS_REPLACE
;
196 cmd
= ZEBRA_MPLS_LABELS_ADD
;
198 cmd
= ZEBRA_MPLS_LABELS_DELETE
;
201 if (zebra_send_mpls_labels(zclient
, cmd
, &zl
) == ZCLIENT_SEND_FAILURE
)
207 enum where_to_restart
{
208 SHARP_INSTALL_ROUTES_RESTART
,
209 SHARP_DELETE_ROUTES_RESTART
,
212 struct buffer_delay
{
220 const struct nexthop_group
*nhg
;
221 const struct nexthop_group
*backup_nhg
;
222 enum where_to_restart restart
;
227 * route_add - Encodes a route to zebra
229 * This function returns true when the route was buffered
230 * by the underlying stream system
232 static bool route_add(const struct prefix
*p
, vrf_id_t vrf_id
, uint8_t instance
,
233 uint32_t nhgid
, const struct nexthop_group
*nhg
,
234 const struct nexthop_group
*backup_nhg
, uint32_t flags
,
237 struct zapi_route api
;
238 struct zapi_nexthop
*api_nh
;
242 memset(&api
, 0, sizeof(api
));
244 api
.type
= ZEBRA_ROUTE_SHARP
;
245 api
.instance
= instance
;
246 api
.safi
= SAFI_UNICAST
;
247 memcpy(&api
.prefix
, p
, sizeof(*p
));
250 SET_FLAG(api
.flags
, ZEBRA_FLAG_ALLOW_RECURSION
);
251 SET_FLAG(api
.message
, ZAPI_MESSAGE_NEXTHOP
);
253 /* Only send via ID if nhgroup has been successfully installed */
254 if (nhgid
&& sharp_nhgroup_id_is_installed(nhgid
)) {
255 SET_FLAG(api
.message
, ZAPI_MESSAGE_NHG
);
258 for (ALL_NEXTHOPS_PTR(nhg
, nh
)) {
259 /* Check if we set a VNI label */
261 (nh
->nh_label_type
== ZEBRA_LSP_EVPN
))
262 SET_FLAG(api
.flags
, ZEBRA_FLAG_EVPN_ROUTE
);
264 api_nh
= &api
.nexthops
[i
];
266 zapi_nexthop_from_nexthop(api_nh
, nh
);
273 /* Include backup nexthops, if present */
274 if (backup_nhg
&& backup_nhg
->nexthop
) {
275 SET_FLAG(api
.message
, ZAPI_MESSAGE_BACKUP_NEXTHOPS
);
278 for (ALL_NEXTHOPS_PTR(backup_nhg
, nh
)) {
279 api_nh
= &api
.backup_nexthops
[i
];
281 zapi_backup_nexthop_from_nexthop(api_nh
, nh
);
286 api
.backup_nexthop_num
= i
;
289 if (strlen(opaque
)) {
290 SET_FLAG(api
.message
, ZAPI_MESSAGE_OPAQUE
);
291 api
.opaque
.length
= strlen(opaque
) + 1;
292 assert(api
.opaque
.length
<= ZAPI_MESSAGE_OPAQUE_LENGTH
);
293 memcpy(api
.opaque
.data
, opaque
, api
.opaque
.length
);
296 if (zclient_route_send(ZEBRA_ROUTE_ADD
, zclient
, &api
) ==
297 ZCLIENT_SEND_BUFFERED
)
304 * route_delete - Encodes a route for deletion to zebra
306 * This function returns true when the route sent was
307 * buffered by the underlying stream system.
309 static bool route_delete(struct prefix
*p
, vrf_id_t vrf_id
, uint8_t instance
)
311 struct zapi_route api
;
313 memset(&api
, 0, sizeof(api
));
315 api
.type
= ZEBRA_ROUTE_SHARP
;
316 api
.safi
= SAFI_UNICAST
;
317 api
.instance
= instance
;
318 memcpy(&api
.prefix
, p
, sizeof(*p
));
320 if (zclient_route_send(ZEBRA_ROUTE_DELETE
, zclient
, &api
) ==
321 ZCLIENT_SEND_BUFFERED
)
327 static void sharp_install_routes_restart(struct prefix
*p
, uint32_t count
,
328 vrf_id_t vrf_id
, uint8_t instance
,
330 const struct nexthop_group
*nhg
,
331 const struct nexthop_group
*backup_nhg
,
332 uint32_t routes
, uint32_t flags
,
338 if (p
->family
== AF_INET
) {
340 temp
= ntohl(p
->u
.prefix4
.s_addr
);
342 temp
= ntohl(p
->u
.val32
[3]);
344 for (i
= count
; i
< routes
; i
++) {
345 bool buffered
= route_add(p
, vrf_id
, (uint8_t)instance
, nhgid
,
346 nhg
, backup_nhg
, flags
, opaque
);
348 p
->u
.prefix4
.s_addr
= htonl(++temp
);
350 p
->u
.val32
[3] = htonl(++temp
);
357 wb
.instance
= instance
;
361 wb
.backup_nhg
= backup_nhg
;
363 wb
.restart
= SHARP_INSTALL_ROUTES_RESTART
;
370 void sharp_install_routes_helper(struct prefix
*p
, vrf_id_t vrf_id
,
371 uint8_t instance
, uint32_t nhgid
,
372 const struct nexthop_group
*nhg
,
373 const struct nexthop_group
*backup_nhg
,
374 uint32_t routes
, uint32_t flags
, char *opaque
)
376 zlog_debug("Inserting %u routes", routes
);
378 /* Only use backup route/nexthops if present */
379 if (backup_nhg
&& (backup_nhg
->nexthop
== NULL
))
382 monotime(&sg
.r
.t_start
);
383 sharp_install_routes_restart(p
, 0, vrf_id
, instance
, nhgid
, nhg
,
384 backup_nhg
, routes
, flags
, opaque
);
387 static void sharp_remove_routes_restart(struct prefix
*p
, uint32_t count
,
388 vrf_id_t vrf_id
, uint8_t instance
,
394 if (p
->family
== AF_INET
) {
396 temp
= ntohl(p
->u
.prefix4
.s_addr
);
398 temp
= ntohl(p
->u
.val32
[3]);
400 for (i
= count
; i
< routes
; i
++) {
401 bool buffered
= route_delete(p
, vrf_id
, (uint8_t)instance
);
404 p
->u
.prefix4
.s_addr
= htonl(++temp
);
406 p
->u
.val32
[3] = htonl(++temp
);
412 wb
.instance
= instance
;
414 wb
.restart
= SHARP_DELETE_ROUTES_RESTART
;
421 void sharp_remove_routes_helper(struct prefix
*p
, vrf_id_t vrf_id
,
422 uint8_t instance
, uint32_t routes
)
424 zlog_debug("Removing %u routes", routes
);
426 monotime(&sg
.r
.t_start
);
428 sharp_remove_routes_restart(p
, 0, vrf_id
, instance
, routes
);
431 static void handle_repeated(bool installed
)
433 struct prefix p
= sg
.r
.orig_prefix
;
436 if (sg
.r
.repeat
<= 0)
440 sg
.r
.removed_routes
= 0;
441 sharp_remove_routes_helper(&p
, sg
.r
.vrf_id
, sg
.r
.inst
,
446 sg
.r
.installed_routes
= 0;
447 sharp_install_routes_helper(
448 &p
, sg
.r
.vrf_id
, sg
.r
.inst
, sg
.r
.nhgid
,
449 &sg
.r
.nhop_group
, &sg
.r
.backup_nhop_group
,
450 sg
.r
.total_routes
, sg
.r
.flags
, sg
.r
.opaque
);
454 static void sharp_zclient_buffer_ready(void)
456 switch (wb
.restart
) {
457 case SHARP_INSTALL_ROUTES_RESTART
:
458 sharp_install_routes_restart(
459 &wb
.p
, wb
.count
, wb
.vrf_id
, wb
.instance
, wb
.nhgid
,
460 wb
.nhg
, wb
.backup_nhg
, wb
.routes
, wb
.flags
, wb
.opaque
);
462 case SHARP_DELETE_ROUTES_RESTART
:
463 sharp_remove_routes_restart(&wb
.p
, wb
.count
, wb
.vrf_id
,
464 wb
.instance
, wb
.routes
);
469 static int route_notify_owner(ZAPI_CALLBACK_ARGS
)
473 enum zapi_route_notify_owner note
;
476 if (!zapi_route_notify_decode(zclient
->ibuf
, &p
, &table
, ¬e
, NULL
,
481 case ZAPI_ROUTE_INSTALLED
:
482 sg
.r
.installed_routes
++;
483 if (sg
.r
.total_routes
== sg
.r
.installed_routes
) {
484 monotime(&sg
.r
.t_end
);
485 timersub(&sg
.r
.t_end
, &sg
.r
.t_start
, &r
);
486 zlog_debug("Installed All Items %jd.%ld",
487 (intmax_t)r
.tv_sec
, (long)r
.tv_usec
);
488 handle_repeated(true);
491 case ZAPI_ROUTE_FAIL_INSTALL
:
492 zlog_debug("Failed install of route");
494 case ZAPI_ROUTE_BETTER_ADMIN_WON
:
495 zlog_debug("Better Admin Distance won over us");
497 case ZAPI_ROUTE_REMOVED
:
498 sg
.r
.removed_routes
++;
499 if (sg
.r
.total_routes
== sg
.r
.removed_routes
) {
500 monotime(&sg
.r
.t_end
);
501 timersub(&sg
.r
.t_end
, &sg
.r
.t_start
, &r
);
502 zlog_debug("Removed all Items %jd.%ld",
503 (intmax_t)r
.tv_sec
, (long)r
.tv_usec
);
504 handle_repeated(false);
507 case ZAPI_ROUTE_REMOVE_FAIL
:
508 zlog_debug("Route removal Failure");
514 static void zebra_connected(struct zclient
*zclient
)
516 zclient_send_reg_requests(zclient
, VRF_DEFAULT
);
519 * Do not actually turn this on yet
520 * This is just the start of the infrastructure needed here
521 * This can be fixed at a later time.
523 * zebra_redistribute_send(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP,
524 * ZEBRA_ROUTE_ALL, 0, VRF_DEFAULT);
528 void vrf_label_add(vrf_id_t vrf_id
, afi_t afi
, mpls_label_t label
)
530 zclient_send_vrf_label(zclient
, vrf_id
, afi
, label
, ZEBRA_LSP_SHARP
);
533 void nhg_add(uint32_t id
, const struct nexthop_group
*nhg
,
534 const struct nexthop_group
*backup_nhg
)
536 struct zapi_nhg api_nhg
= {};
537 struct zapi_nexthop
*api_nh
;
539 bool is_valid
= true;
543 api_nhg
.resilience
= nhg
->nhgr
;
545 for (ALL_NEXTHOPS_PTR(nhg
, nh
)) {
546 if (api_nhg
.nexthop_num
>= MULTIPATH_NUM
) {
548 "%s: number of nexthops greater than max multipath size, truncating",
553 /* Unresolved nexthops will lead to failure - only send
554 * nexthops that zebra will consider valid.
556 if (nh
->ifindex
== 0)
559 api_nh
= &api_nhg
.nexthops
[api_nhg
.nexthop_num
];
561 zapi_nexthop_from_nexthop(api_nh
, nh
);
562 api_nhg
.nexthop_num
++;
565 if (api_nhg
.nexthop_num
== 0) {
566 zlog_debug("%s: nhg %u not sent: no valid nexthops", __func__
,
573 for (ALL_NEXTHOPS_PTR(backup_nhg
, nh
)) {
574 if (api_nhg
.backup_nexthop_num
>= MULTIPATH_NUM
) {
576 "%s: number of backup nexthops greater than max multipath size, truncating",
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
587 if (nh
->ifindex
== 0) {
588 zlog_debug("%s: nhg %u: invalid backup nexthop",
594 api_nh
= &api_nhg
.backup_nexthops
595 [api_nhg
.backup_nexthop_num
];
597 zapi_backup_nexthop_from_nexthop(api_nh
, nh
);
598 api_nhg
.backup_nexthop_num
++;
604 zclient_nhg_send(zclient
, ZEBRA_NHG_ADD
, &api_nhg
);
607 void nhg_del(uint32_t id
)
609 struct zapi_nhg api_nhg
= {};
613 zclient_nhg_send(zclient
, ZEBRA_NHG_DEL
, &api_nhg
);
616 void sharp_zebra_nexthop_watch(struct prefix
*p
, vrf_id_t vrf_id
, bool import
,
617 bool watch
, bool connected
)
621 command
= ZEBRA_NEXTHOP_REGISTER
;
624 command
= ZEBRA_NEXTHOP_UNREGISTER
;
626 if (zclient_send_rnh(zclient
, command
, p
, SAFI_UNICAST
, connected
,
627 false, vrf_id
) == ZCLIENT_SEND_FAILURE
)
628 zlog_warn("%s: Failure to send nexthop to zebra", __func__
);
631 static int sharp_debug_nexthops(struct zapi_route
*api
)
635 if (api
->nexthop_num
== 0) {
636 zlog_debug(" Not installed");
640 for (i
= 0; i
< api
->nexthop_num
; i
++) {
641 struct zapi_nexthop
*znh
= &api
->nexthops
[i
];
644 case NEXTHOP_TYPE_IPV4_IFINDEX
:
645 case NEXTHOP_TYPE_IPV4
:
647 " Nexthop %pI4, type: %d, ifindex: %d, vrf: %d, label_num: %d",
648 &znh
->gate
.ipv4
.s_addr
, znh
->type
, znh
->ifindex
,
649 znh
->vrf_id
, znh
->label_num
);
651 case NEXTHOP_TYPE_IPV6_IFINDEX
:
652 case NEXTHOP_TYPE_IPV6
:
654 " Nexthop %pI6, type: %d, ifindex: %d, vrf: %d, label_num: %d",
655 &znh
->gate
.ipv6
, znh
->type
, znh
->ifindex
,
656 znh
->vrf_id
, znh
->label_num
);
658 case NEXTHOP_TYPE_IFINDEX
:
659 zlog_debug(" Nexthop IFINDEX: %d, ifindex: %d",
660 znh
->type
, znh
->ifindex
);
662 case NEXTHOP_TYPE_BLACKHOLE
:
663 zlog_debug(" Nexthop blackhole");
670 static int sharp_nexthop_update(ZAPI_CALLBACK_ARGS
)
672 struct sharp_nh_tracker
*nht
;
673 struct zapi_route nhr
;
674 struct prefix matched
;
676 if (!zapi_nexthop_update_decode(zclient
->ibuf
, &matched
, &nhr
)) {
677 zlog_err("%s: Decode of update failed", __func__
);
681 zlog_debug("Received update for %pFX actual match: %pFX metric: %u",
682 &matched
, &nhr
.prefix
, nhr
.metric
);
684 nht
= sharp_nh_tracker_get(&matched
);
685 nht
->nhop_num
= nhr
.nexthop_num
;
688 sharp_debug_nexthops(&nhr
);
693 static int sharp_redistribute_route(ZAPI_CALLBACK_ARGS
)
695 struct zapi_route api
;
697 if (zapi_route_decode(zclient
->ibuf
, &api
) < 0)
698 zlog_warn("%s: Decode of redistribute failed: %d", __func__
,
699 ZEBRA_REDISTRIBUTE_ROUTE_ADD
);
701 zlog_debug("%s: %pFX (%s)", zserv_command_string(cmd
), &api
.prefix
,
702 zebra_route_string(api
.type
));
704 sharp_debug_nexthops(&api
);
709 void sharp_redistribute_vrf(struct vrf
*vrf
, int type
)
711 zebra_redistribute_send(ZEBRA_REDISTRIBUTE_ADD
, zclient
, AFI_IP
, type
,
715 static zclient_handler
*const sharp_opaque_handlers
[] = {
716 [ZEBRA_OPAQUE_MESSAGE
] = sharp_opaque_handler
,
719 /* Add a zclient with a specified session id, for testing. */
720 int sharp_zclient_create(uint32_t session_id
)
722 struct zclient
*client
;
723 struct sharp_zclient
*node
;
725 /* Check for duplicates */
726 for (node
= sharp_clients_head
; node
!= NULL
; node
= node
->next
) {
727 if (node
->client
->session_id
== session_id
)
731 client
= zclient_new(master
, &zclient_options_default
,
732 sharp_opaque_handlers
,
733 array_size(sharp_opaque_handlers
));
735 client
->session_id
= session_id
;
737 zclient_init(client
, ZEBRA_ROUTE_SHARP
, 0, &sharp_privs
);
739 /* Enqueue on the list of test clients */
745 /* Delete one of the extra test zclients */
746 int sharp_zclient_delete(uint32_t session_id
)
748 struct sharp_zclient
*node
;
750 /* Search for session */
751 for (node
= sharp_clients_head
; node
!= NULL
; node
= node
->next
) {
752 if (node
->client
->session_id
== session_id
) {
753 /* Dequeue from list */
755 node
->next
->prev
= node
->prev
;
757 node
->prev
->next
= node
->next
;
758 if (node
== sharp_clients_head
)
759 sharp_clients_head
= node
->next
;
761 /* Clean up zclient */
762 zclient_stop(node
->client
);
763 zclient_free(node
->client
);
766 XFREE(MTYPE_ZC
, node
);
774 static const char *const type2txt
[] = {"Generic", "Vertex", "Edge", "Subnet"};
775 static const char *const status2txt
[] = {"Unknown", "New", "Update",
776 "Delete", "Sync", "Orphan"};
777 /* Handler for opaque messages */
778 static int sharp_opaque_handler(ZAPI_CALLBACK_ARGS
)
781 struct zapi_opaque_msg info
;
782 struct ls_element
*lse
;
786 if (zclient_opaque_decode(s
, &info
) != 0)
789 zlog_debug("%s: [%u] received opaque type %u", __func__
,
790 zclient
->session_id
, info
.type
);
792 if (info
.type
== LINK_STATE_UPDATE
) {
793 lse
= ls_stream2ted(sg
.ted
, s
, true);
795 zlog_debug(" |- Got %s %s from Link State Database",
796 status2txt
[lse
->status
],
797 type2txt
[lse
->type
]);
801 "%s: Error to convert Stream into Link State",
809 * Send OPAQUE messages, using subtype 'type'.
811 void sharp_opaque_send(uint32_t type
, uint32_t proto
, uint32_t instance
,
812 uint32_t session_id
, uint32_t count
)
818 /* Prepare a small payload */
819 for (i
= 0; i
< sizeof(buf
); i
++) {
826 /* Send some messages - broadcast and unicast are supported */
827 for (i
= 0; i
< count
; i
++) {
829 ret
= zclient_send_opaque(zclient
, type
, buf
,
832 ret
= zclient_send_opaque_unicast(zclient
, type
, proto
,
833 instance
, session_id
,
835 if (ret
== ZCLIENT_SEND_FAILURE
) {
836 zlog_debug("%s: send_opaque() failed => %d", __func__
,
844 * Send OPAQUE registration messages, using subtype 'type'.
846 void sharp_opaque_reg_send(bool is_reg
, uint32_t proto
, uint32_t instance
,
847 uint32_t session_id
, uint32_t type
)
855 zclient_create_header(s
, ZEBRA_OPAQUE_REGISTER
, VRF_DEFAULT
);
857 zclient_create_header(s
, ZEBRA_OPAQUE_UNREGISTER
, VRF_DEFAULT
);
860 stream_putl(s
, type
);
862 /* Add zclient info */
863 stream_putc(s
, proto
);
864 stream_putw(s
, instance
);
865 stream_putl(s
, session_id
);
867 /* Put length at the first point of the stream. */
868 stream_putw_at(s
, 0, stream_get_endp(s
));
870 (void)zclient_send_message(zclient
);
873 /* Link State registration */
874 void sharp_zebra_register_te(void)
876 /* First register to received Link State Update messages */
877 zclient_register_opaque(zclient
, LINK_STATE_UPDATE
);
879 /* Then, request initial TED with SYNC message */
880 ls_request_sync(zclient
);
883 void sharp_zebra_send_arp(const struct interface
*ifp
, const struct prefix
*p
)
885 zclient_send_neigh_discovery_req(zclient
, ifp
, p
);
888 static int nhg_notify_owner(ZAPI_CALLBACK_ARGS
)
890 enum zapi_nhg_notify_owner note
;
893 if (!zapi_nhg_notify_decode(zclient
->ibuf
, &id
, ¬e
))
897 case ZAPI_NHG_INSTALLED
:
898 sharp_nhgroup_id_set_installed(id
, true);
899 zlog_debug("Installed nhg %u", id
);
901 case ZAPI_NHG_FAIL_INSTALL
:
902 zlog_debug("Failed install of nhg %u", id
);
904 case ZAPI_NHG_REMOVED
:
905 zlog_debug("Removed nhg %u", id
);
907 case ZAPI_NHG_REMOVE_FAIL
:
908 zlog_debug("Failed removal of nhg %u", id
);
915 int sharp_zebra_srv6_manager_get_locator_chunk(const char *locator_name
)
917 return srv6_manager_get_locator_chunk(zclient
, locator_name
);
920 int sharp_zebra_srv6_manager_release_locator_chunk(const char *locator_name
)
922 return srv6_manager_release_locator_chunk(zclient
, locator_name
);
925 static int sharp_zebra_process_srv6_locator_chunk(ZAPI_CALLBACK_ARGS
)
927 struct stream
*s
= NULL
;
928 struct srv6_locator_chunk s6c
= {};
929 struct listnode
*node
, *nnode
;
930 struct sharp_srv6_locator
*loc
;
933 zapi_srv6_locator_chunk_decode(s
, &s6c
);
935 for (ALL_LIST_ELEMENTS(sg
.srv6_locators
, node
, nnode
, loc
)) {
936 struct prefix_ipv6
*chunk
= NULL
;
937 struct listnode
*chunk_node
;
938 struct prefix_ipv6
*c
;
940 if (strcmp(loc
->name
, s6c
.locator_name
) != 0) {
941 zlog_err("%s: Locator name unmatch %s:%s", __func__
,
942 loc
->name
, s6c
.locator_name
);
946 for (ALL_LIST_ELEMENTS_RO(loc
->chunks
, chunk_node
, c
))
947 if (!prefix_cmp(c
, &s6c
.prefix
))
950 chunk
= prefix_ipv6_new();
952 listnode_add(loc
->chunks
, chunk
);
956 zlog_err("%s: can't get locator_chunk!!", __func__
);
960 int sharp_zebra_send_interface_protodown(struct interface
*ifp
, bool down
)
962 zlog_debug("Sending zebra to set %s protodown %s", ifp
->name
,
963 down
? "on" : "off");
965 if (zclient_send_interface_protodown(zclient
, ifp
->vrf
->vrf_id
, ifp
,
966 down
) == ZCLIENT_SEND_FAILURE
)
972 int sharp_zebra_send_tc_filter_rate(struct interface
*ifp
,
973 const struct prefix
*source
,
974 const struct prefix
*destination
,
975 uint8_t ip_proto
, uint16_t src_port
,
976 uint16_t dst_port
, uint64_t rate
)
978 #define SHARPD_TC_HANDLE 0x0001
983 struct tc_qdisc q
= {.ifindex
= ifp
->ifindex
, .kind
= TC_QDISC_HTB
};
985 zapi_tc_qdisc_encode(ZEBRA_TC_QDISC_INSTALL
, s
, &q
);
986 if (zclient_send_message(zclient
) == ZCLIENT_SEND_FAILURE
)
989 struct tc_class c
= {.ifindex
= ifp
->ifindex
,
990 .handle
= SHARPD_TC_HANDLE
& 0xffff,
991 .kind
= TC_QDISC_HTB
,
995 zapi_tc_class_encode(ZEBRA_TC_CLASS_ADD
, s
, &c
);
996 if (zclient_send_message(zclient
) == ZCLIENT_SEND_FAILURE
)
999 struct tc_filter f
= {.ifindex
= ifp
->ifindex
,
1000 .handle
= SHARPD_TC_HANDLE
,
1002 .kind
= TC_FILTER_FLOWER
,
1003 .u
.flower
.filter_bm
= 0};
1006 f
.protocol
= ETH_P_IP
;
1008 f
.protocol
= 0x0800;
1011 f
.u
.flower
.filter_bm
|= TC_FLOWER_IP_PROTOCOL
;
1012 f
.u
.flower
.ip_proto
= ip_proto
;
1013 f
.u
.flower
.filter_bm
|= TC_FLOWER_SRC_IP
;
1014 prefix_copy(&f
.u
.flower
.src_ip
, source
);
1015 f
.u
.flower
.filter_bm
|= TC_FLOWER_DST_IP
;
1016 prefix_copy(&f
.u
.flower
.dst_ip
, destination
);
1017 f
.u
.flower
.filter_bm
|= TC_FLOWER_SRC_PORT
;
1018 f
.u
.flower
.src_port_min
= f
.u
.flower
.src_port_max
= src_port
;
1019 f
.u
.flower
.filter_bm
|= TC_FLOWER_DST_PORT
;
1020 f
.u
.flower
.dst_port_min
= f
.u
.flower
.dst_port_max
= dst_port
;
1021 f
.u
.flower
.classid
= SHARPD_TC_HANDLE
& 0xffff;
1023 zapi_tc_filter_encode(ZEBRA_TC_FILTER_ADD
, s
, &f
);
1024 if (zclient_send_message(zclient
) == ZCLIENT_SEND_FAILURE
)
1030 static zclient_handler
*const sharp_handlers
[] = {
1031 [ZEBRA_INTERFACE_ADDRESS_ADD
] = interface_address_add
,
1032 [ZEBRA_INTERFACE_ADDRESS_DELETE
] = interface_address_delete
,
1033 [ZEBRA_ROUTE_NOTIFY_OWNER
] = route_notify_owner
,
1034 [ZEBRA_NEXTHOP_UPDATE
] = sharp_nexthop_update
,
1035 [ZEBRA_NHG_NOTIFY_OWNER
] = nhg_notify_owner
,
1036 [ZEBRA_REDISTRIBUTE_ROUTE_ADD
] = sharp_redistribute_route
,
1037 [ZEBRA_REDISTRIBUTE_ROUTE_DEL
] = sharp_redistribute_route
,
1038 [ZEBRA_OPAQUE_MESSAGE
] = sharp_opaque_handler
,
1039 [ZEBRA_SRV6_MANAGER_GET_LOCATOR_CHUNK
] =
1040 sharp_zebra_process_srv6_locator_chunk
,
1043 void sharp_zebra_init(void)
1045 struct zclient_options opt
= {.receive_notify
= true};
1047 if_zapi_callbacks(sharp_ifp_create
, sharp_ifp_up
, sharp_ifp_down
,
1050 zclient
= zclient_new(master
, &opt
, sharp_handlers
,
1051 array_size(sharp_handlers
));
1053 zclient_init(zclient
, ZEBRA_ROUTE_SHARP
, 0, &sharp_privs
);
1054 zclient
->zebra_connected
= zebra_connected
;
1055 zclient
->zebra_buffer_write_ready
= sharp_zclient_buffer_ready
;