blob: bd171c89b2eb33f4d01d5d5310bd253825a7da25 [file] [log] [blame]
Avneesh Sachdev3bccb4f2016-03-11 12:21:26 -08001/*
2 * zebra_fpm_dt.c
3 *
4 * @copyright Copyright (C) 2016 Sproute Networks, Inc.
5 *
6 * @author Avneesh Sachdev <avneesh@sproute.com>
7 *
8 * This file is part of GNU Zebra.
9 *
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
13 * later version.
14 *
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.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with GNU Zebra; see the file COPYING. If not, write to the Free
22 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
23 * 02111-1307, USA.
24 */
25
26/*
27 * Developer tests for the zebra code that interfaces with the
28 * forwarding plane manager.
29 *
30 * The functions here are built into developer builds of zebra (when
31 * DEV_BUILD is defined), and can be called via the 'invoke' cli
32 * command.
33 *
34 * For example:
35 *
36 * # invoke zebra function zfpm_dt_benchmark_protobuf_encode 100000
37 *
38 */
39
40#include <zebra.h>
41#include "log.h"
42#include "vrf.h"
43
44#include "zebra/rib.h"
45
46#include "zebra_fpm_private.h"
47
48#include "qpb/qpb_allocator.h"
49#include "qpb/linear_allocator.h"
50
51#include "qpb/qpb.h"
52#include "fpm/fpm.pb-c.h"
53
54/*
55 * Externs.
56 */
57extern int zfpm_dt_benchmark_netlink_encode (int argc, const char **argv);
58extern int zfpm_dt_benchmark_protobuf_encode (int argc, const char **argv);
59extern int zfpm_dt_benchmark_protobuf_decode (int argc, const char **argv);
60
61/*
62 * zfpm_dt_find_route
63 *
64 * Selects a suitable rib destination for fpm interface tests.
65 */
66static int
67zfpm_dt_find_route (rib_dest_t **dest_p, struct rib **rib_p)
68{
69 struct route_node *rnode;
70 route_table_iter_t iter;
71 struct route_table *table;
72 rib_dest_t *dest;
73 struct rib *rib;
74 int ret;
75
76 table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT);
77 if (!table)
78 return 0;
79
80 route_table_iter_init(&iter, table);
81 while ((rnode = route_table_iter_next(&iter)))
82 {
83 dest = rib_dest_from_rnode (rnode);
84
85 if (!dest)
86 continue;
87
88 rib = zfpm_route_for_update(dest);
89 if (!rib)
90 continue;
91
92 if (rib->nexthop_active_num <= 0)
93 continue;
94
95 *dest_p = dest;
96 *rib_p = rib;
97 ret = 1;
98 goto done;
99 }
100
101 ret = 0;
102
103 done:
104 route_table_iter_cleanup(&iter);
105 return ret;
106}
107#ifdef HAVE_NETLINK
108
109/*
110 * zfpm_dt_benchmark_netlink_encode
111 */
112int
113zfpm_dt_benchmark_netlink_encode (int argc, const char **argv)
114{
115 int times, i, len;
116 rib_dest_t *dest;
117 struct rib *rib;
118 char buf[4096];
119
120 times = 100000;
121 if (argc > 0) {
122 times = atoi(argv[0]);
123 }
124
125 if (!zfpm_dt_find_route(&dest, &rib)) {
126 return 1;
127 }
128
129 for (i = 0; i < times; i++) {
130 len = zfpm_netlink_encode_route(RTM_NEWROUTE, dest, rib, buf, sizeof(buf));
131 if (len <= 0) {
132 return 2;
133 }
134 }
135 return 0;
136}
137
138#endif /* HAVE_NETLINK */
139
140#ifdef HAVE_PROTOBUF
141
142/*
143 * zfpm_dt_benchmark_protobuf_encode
144 */
145int
146zfpm_dt_benchmark_protobuf_encode (int argc, const char **argv)
147{
148 int times, i, len;
149 rib_dest_t *dest;
150 struct rib *rib;
151 uint8_t buf[4096];
152
153 times = 100000;
154 if (argc > 0) {
155 times = atoi(argv[0]);
156 }
157
158 if (!zfpm_dt_find_route(&dest, &rib)) {
159 return 1;
160 }
161
162 for (i = 0; i < times; i++) {
163 len = zfpm_protobuf_encode_route(dest, rib, buf, sizeof(buf));
164 if (len <= 0) {
165 return 2;
166 }
167 }
168 return 0;
169}
170
171/*
172 * zfpm_dt_log_fpm_message
173 */
174static void
175zfpm_dt_log_fpm_message (Fpm__Message *msg)
176{
177 Fpm__AddRoute *add_route;
178 Fpm__Nexthop *nexthop;
179 struct prefix prefix;
180 u_char family, nh_family;
181 uint if_index;
182 char *if_name;
183 size_t i;
184 char buf[INET6_ADDRSTRLEN];
185 union g_addr nh_addr;
186
187 if (msg->type != FPM__MESSAGE__TYPE__ADD_ROUTE)
188 return;
189
190 zfpm_debug ("Add route message");
191 add_route = msg->add_route;
192
193 if (!qpb_address_family_get (add_route->address_family, &family))
194 return;
195
196 if (!qpb_l3_prefix_get (add_route->key->prefix, family, &prefix))
197 return;
198
199 zfpm_debug ("Vrf id: %d, Prefix: %s/%d, Metric: %d", add_route->vrf_id,
200 inet_ntop (family, &prefix.u.prefix, buf, sizeof (buf)),
201 prefix.prefixlen, add_route->metric);
202
203 /*
204 * Go over nexthops.
205 */
206 for (i = 0; i < add_route->n_nexthops; i++)
207 {
208 nexthop = add_route->nexthops[i];
209 if (!qpb_if_identifier_get (nexthop->if_id, &if_index, &if_name))
210 continue;
211
212 if (nexthop->address)
213 qpb_l3_address_get (nexthop->address, &nh_family, &nh_addr);
214
215 zfpm_debug ("Nexthop - if_index: %d (%s), gateway: %s, ", if_index,
216 if_name ? if_name : "name not specified",
217 nexthop->address ? inet_ntoa (nh_addr.ipv4) : "None");
218 }
219}
220
221/*
222 * zfpm_dt_benchmark_protobuf_decode
223 */
224int
225zfpm_dt_benchmark_protobuf_decode (int argc, const char **argv)
226{
227 int times, i, len;
228 rib_dest_t *dest;
229 struct rib *rib;
230 uint8_t msg_buf[4096];
231 QPB_DECLARE_STACK_ALLOCATOR (allocator, 8192);
232 Fpm__Message *fpm_msg;
233
234 QPB_INIT_STACK_ALLOCATOR (allocator);
235
236 times = 100000;
237 if (argc > 0)
238 times = atoi(argv[0]);
239
240 if (!zfpm_dt_find_route (&dest, &rib))
241 return 1;
242
243 /*
244 * Encode the route into the message buffer once only.
245 */
246 len = zfpm_protobuf_encode_route (dest, rib, msg_buf, sizeof (msg_buf));
247 if (len <= 0)
248 return 2;
249
250 // Decode once, and display the decoded message
251 fpm_msg = fpm__message__unpack(&allocator, len, msg_buf);
252
253 if (fpm_msg)
254 {
255 zfpm_dt_log_fpm_message(fpm_msg);
256 QPB_RESET_STACK_ALLOCATOR (allocator);
257 }
258
259 /*
260 * Decode encoded message the specified number of times.
261 */
262 for (i = 0; i < times; i++)
263 {
264 fpm_msg = fpm__message__unpack (&allocator, len, msg_buf);
265
266 if (!fpm_msg)
267 return 3;
268
269 // fpm__message__free_unpacked(msg, NULL);
270 QPB_RESET_STACK_ALLOCATOR (allocator);
271 }
272 return 0;
273}
274
275#endif /* HAVE_PROTOBUF */