1 // SPDX-License-Identifier: GPL-2.0-or-later
5 * @copyright Copyright (C) 2016 Sproute Networks, Inc.
7 * @author Avneesh Sachdev <avneesh@sproute.com>
11 * Developer tests for the zebra code that interfaces with the
12 * forwarding plane manager.
14 * The functions here are built into developer builds of zebra (when
15 * DEV_BUILD is defined), and can be called via the 'invoke' cli
20 * # invoke zebra function zfpm_dt_benchmark_protobuf_encode 100000
28 #include "zebra/rib.h"
29 #include "zebra/zserv.h"
30 #include "zebra/zebra_vrf.h"
32 #include "zebra_fpm_private.h"
34 #include "qpb/qpb_allocator.h"
35 #include "qpb/linear_allocator.h"
39 #include "fpm/fpm.pb-c.h"
45 extern int zfpm_dt_benchmark_netlink_encode(int argc
, const char **argv
);
46 extern int zfpm_dt_benchmark_protobuf_encode(int argc
, const char **argv
);
47 extern int zfpm_dt_benchmark_protobuf_decode(int argc
, const char **argv
);
52 * Selects a suitable rib destination for fpm interface tests.
54 static int zfpm_dt_find_route(rib_dest_t
**dest_p
, struct route_entry
**re_p
)
56 struct route_node
*rnode
;
57 route_table_iter_t iter
;
58 struct route_table
*table
;
60 struct route_entry
*re
;
63 table
= zebra_vrf_table(AFI_IP
, SAFI_UNICAST
, VRF_DEFAULT
);
67 route_table_iter_init(&iter
, table
);
68 while ((rnode
= route_table_iter_next(&iter
))) {
69 dest
= rib_dest_from_rnode(rnode
);
74 re
= zfpm_route_for_update(dest
);
78 if (nexthop_group_active_nexthop_num(&(re
->nhe
->nhg
)) == 0)
90 route_table_iter_cleanup(&iter
);
96 * zfpm_dt_benchmark_netlink_encode
98 int zfpm_dt_benchmark_netlink_encode(int argc
, const char **argv
)
102 struct route_entry
*re
;
107 times
= atoi(argv
[0]);
110 if (!zfpm_dt_find_route(&dest
, &re
)) {
114 for (i
= 0; i
< times
; i
++) {
115 len
= zfpm_netlink_encode_route(RTM_NEWROUTE
, dest
, re
, buf
,
124 #endif /* HAVE_NETLINK */
129 * zfpm_dt_benchmark_protobuf_encode
131 int zfpm_dt_benchmark_protobuf_encode(int argc
, const char **argv
)
135 struct route_entry
*re
;
140 times
= atoi(argv
[0]);
143 if (!zfpm_dt_find_route(&dest
, &re
)) {
147 for (i
= 0; i
< times
; i
++) {
148 len
= zfpm_protobuf_encode_route(dest
, re
, buf
, sizeof(buf
));
157 * zfpm_dt_log_fpm_message
159 static void zfpm_dt_log_fpm_message(Fpm__Message
*msg
)
161 Fpm__AddRoute
*add_route
;
162 Fpm__Nexthop
*nexthop
;
163 struct prefix prefix
;
164 uint8_t family
, nh_family
;
168 char buf
[INET6_ADDRSTRLEN
];
169 char addr_buf
[PREFIX_STRLEN
];
170 union g_addr nh_addr
;
172 if (msg
->type
!= FPM__MESSAGE__TYPE__ADD_ROUTE
)
175 zfpm_debug("Add route message");
176 add_route
= msg
->add_route
;
178 if (!qpb_address_family_get(add_route
->address_family
, &family
))
181 if (!qpb_l3_prefix_get(add_route
->key
->prefix
, family
, &prefix
))
184 zfpm_debug("Vrf id: %d, Prefix: %s/%d, Metric: %d", add_route
->vrf_id
,
185 inet_ntop(family
, &prefix
.u
.prefix
, buf
, sizeof(buf
)),
186 prefix
.prefixlen
, add_route
->metric
);
191 for (i
= 0; i
< add_route
->n_nexthops
; i
++) {
192 nexthop
= add_route
->nexthops
[i
];
193 if (!qpb_if_identifier_get(nexthop
->if_id
, &if_index
, &if_name
))
196 if (nexthop
->address
)
197 qpb_l3_address_get(nexthop
->address
, &nh_family
,
200 zfpm_debug("Nexthop - if_index: %d (%s), gateway: %s, ",
201 if_index
, if_name
? if_name
: "name not specified",
203 inet_ntop(AF_INET
, &nh_addr
.ipv4
,
204 addr_buf
, sizeof(addr_buf
)) : "None");
209 * zfpm_dt_benchmark_protobuf_decode
211 int zfpm_dt_benchmark_protobuf_decode(int argc
, const char **argv
)
215 struct route_entry
*re
;
216 uint8_t msg_buf
[4096];
217 QPB_DECLARE_STACK_ALLOCATOR(allocator
, 8192);
218 Fpm__Message
*fpm_msg
;
220 QPB_INIT_STACK_ALLOCATOR(allocator
);
224 times
= atoi(argv
[0]);
226 if (!zfpm_dt_find_route(&dest
, &re
))
230 * Encode the route into the message buffer once only.
232 len
= zfpm_protobuf_encode_route(dest
, re
, msg_buf
, sizeof(msg_buf
));
236 // Decode once, and display the decoded message
237 fpm_msg
= fpm__message__unpack(&allocator
, len
, msg_buf
);
240 zfpm_dt_log_fpm_message(fpm_msg
);
241 QPB_RESET_STACK_ALLOCATOR(allocator
);
245 * Decode encoded message the specified number of times.
247 for (i
= 0; i
< times
; i
++) {
248 fpm_msg
= fpm__message__unpack(&allocator
, len
, msg_buf
);
253 // fpm__message__free_unpacked(msg, NULL);
254 QPB_RESET_STACK_ALLOCATOR(allocator
);
259 #endif /* HAVE_PROTOBUF */