4 * @copyright Copyright (C) 2016 Sproute Networks, Inc.
6 * @author Avneesh Sachdev <avneesh@sproute.com>
8 * This file is part of GNU Zebra.
10 * GNU Zebra is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation; either version 2, or (at your option) any
15 * GNU Zebra is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
20 * You should have received a copy of the GNU General Public License along
21 * with this program; see the file COPYING; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
26 * Developer tests for the zebra code that interfaces with the
27 * forwarding plane manager.
29 * The functions here are built into developer builds of zebra (when
30 * DEV_BUILD is defined), and can be called via the 'invoke' cli
35 * # invoke zebra function zfpm_dt_benchmark_protobuf_encode 100000
43 #include "zebra/rib.h"
44 #include "zebra/zserv.h"
45 #include "zebra/zebra_vrf.h"
47 #include "zebra_fpm_private.h"
49 #include "qpb/qpb_allocator.h"
50 #include "qpb/linear_allocator.h"
54 #include "fpm/fpm.pb-c.h"
60 extern int zfpm_dt_benchmark_netlink_encode(int argc
, const char **argv
);
61 extern int zfpm_dt_benchmark_protobuf_encode(int argc
, const char **argv
);
62 extern int zfpm_dt_benchmark_protobuf_decode(int argc
, const char **argv
);
67 * Selects a suitable rib destination for fpm interface tests.
69 static int zfpm_dt_find_route(rib_dest_t
**dest_p
, struct route_entry
**re_p
)
71 struct route_node
*rnode
;
72 route_table_iter_t iter
;
73 struct route_table
*table
;
75 struct route_entry
*re
;
78 table
= zebra_vrf_table(AFI_IP
, SAFI_UNICAST
, VRF_DEFAULT
);
82 route_table_iter_init(&iter
, table
);
83 while ((rnode
= route_table_iter_next(&iter
))) {
84 dest
= rib_dest_from_rnode(rnode
);
89 re
= zfpm_route_for_update(dest
);
93 if (re
->nexthop_active_num
<= 0)
105 route_table_iter_cleanup(&iter
);
111 * zfpm_dt_benchmark_netlink_encode
113 int zfpm_dt_benchmark_netlink_encode(int argc
, const char **argv
)
117 struct route_entry
*re
;
122 times
= atoi(argv
[0]);
125 if (!zfpm_dt_find_route(&dest
, &re
)) {
129 for (i
= 0; i
< times
; i
++) {
130 len
= zfpm_netlink_encode_route(RTM_NEWROUTE
, dest
, re
, buf
,
139 #endif /* HAVE_NETLINK */
144 * zfpm_dt_benchmark_protobuf_encode
146 int zfpm_dt_benchmark_protobuf_encode(int argc
, const char **argv
)
150 struct route_entry
*re
;
155 times
= atoi(argv
[0]);
158 if (!zfpm_dt_find_route(&dest
, &re
)) {
162 for (i
= 0; i
< times
; i
++) {
163 len
= zfpm_protobuf_encode_route(dest
, re
, buf
, sizeof(buf
));
172 * zfpm_dt_log_fpm_message
174 static void zfpm_dt_log_fpm_message(Fpm__Message
*msg
)
176 Fpm__AddRoute
*add_route
;
177 Fpm__Nexthop
*nexthop
;
178 struct prefix prefix
;
179 uint8_t family
, nh_family
;
183 char buf
[INET6_ADDRSTRLEN
];
184 union g_addr nh_addr
;
186 if (msg
->type
!= FPM__MESSAGE__TYPE__ADD_ROUTE
)
189 zfpm_debug("Add route message");
190 add_route
= msg
->add_route
;
192 if (!qpb_address_family_get(add_route
->address_family
, &family
))
195 if (!qpb_l3_prefix_get(add_route
->key
->prefix
, family
, &prefix
))
198 zfpm_debug("Vrf id: %d, Prefix: %s/%d, Metric: %d", add_route
->vrf_id
,
199 inet_ntop(family
, &prefix
.u
.prefix
, buf
, sizeof(buf
)),
200 prefix
.prefixlen
, add_route
->metric
);
205 for (i
= 0; i
< add_route
->n_nexthops
; i
++) {
206 nexthop
= add_route
->nexthops
[i
];
207 if (!qpb_if_identifier_get(nexthop
->if_id
, &if_index
, &if_name
))
210 if (nexthop
->address
)
211 qpb_l3_address_get(nexthop
->address
, &nh_family
,
214 zfpm_debug("Nexthop - if_index: %d (%s), gateway: %s, ",
215 if_index
, if_name
? if_name
: "name not specified",
216 nexthop
->address
? inet_ntoa(nh_addr
.ipv4
) : "None");
221 * zfpm_dt_benchmark_protobuf_decode
223 int zfpm_dt_benchmark_protobuf_decode(int argc
, const char **argv
)
227 struct route_entry
*re
;
228 uint8_t msg_buf
[4096];
229 QPB_DECLARE_STACK_ALLOCATOR(allocator
, 8192);
230 Fpm__Message
*fpm_msg
;
232 QPB_INIT_STACK_ALLOCATOR(allocator
);
236 times
= atoi(argv
[0]);
238 if (!zfpm_dt_find_route(&dest
, &re
))
242 * Encode the route into the message buffer once only.
244 len
= zfpm_protobuf_encode_route(dest
, re
, msg_buf
, sizeof(msg_buf
));
248 // Decode once, and display the decoded message
249 fpm_msg
= fpm__message__unpack(&allocator
, len
, msg_buf
);
252 zfpm_dt_log_fpm_message(fpm_msg
);
253 QPB_RESET_STACK_ALLOCATOR(allocator
);
257 * Decode encoded message the specified number of times.
259 for (i
= 0; i
< times
; i
++) {
260 fpm_msg
= fpm__message__unpack(&allocator
, len
, msg_buf
);
265 // fpm__message__free_unpacked(msg, NULL);
266 QPB_RESET_STACK_ALLOCATOR(allocator
);
271 #endif /* HAVE_PROTOBUF */