ea17e5d0e7a8ad8f535f0524cde4a89dd9640e35
[vpp.git] / src / plugins / dpdk / api / dpdk_test.c
1
2 /*
3  * dpdk_test.c - skeleton vpp-api-test plug-in
4  *
5  * Copyright (c) <current-year> <your-organization>
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at:
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 #include <vat/vat.h>
19 #include <vlibapi/api.h>
20 #include <vlibmemory/api.h>
21 #include <vlibsocket/api.h>
22 #include <vppinfra/error.h>
23 #include <vnet/ip/ip.h>
24
25 uword unformat_sw_if_index (unformat_input_t * input, va_list * args);
26
27 /* Declare message IDs */
28 #include <dpdk/api/dpdk_msg_enum.h>
29
30 /* define message structures */
31 #define vl_typedefs
32 #include <dpdk/api/dpdk.api.h>
33 #undef vl_typedefs
34
35 /* declare message handlers for each api */
36
37 #define vl_endianfun             /* define message structures */
38 #include <dpdk/api/dpdk.api.h>
39 #undef vl_endianfun
40
41 /* instantiate all the print functions we know about */
42 #define vl_print(handle, ...)
43 #define vl_printfun
44 #include <dpdk/api/dpdk.api.h>
45 #undef vl_printfun
46
47 /* Get the API version number. */
48 #define vl_api_version(n,v) static u32 api_version=(v);
49 #include <dpdk/api/dpdk.api.h>
50 #undef vl_api_version
51
52 typedef struct {
53     /* API message ID base */
54     u16 msg_id_base;
55     vat_main_t *vat_main;
56 } dpdk_test_main_t;
57
58 dpdk_test_main_t dpdk_test_main;
59
60 #define foreach_standard_reply_retval_handler         \
61 _(sw_interface_set_dpdk_hqos_pipe_reply)              \
62 _(sw_interface_set_dpdk_hqos_subport_reply)           \
63 _(sw_interface_set_dpdk_hqos_tctbl_reply)
64
65 #define _(n)                                          \
66     static void vl_api_##n##_t_handler                \
67     (vl_api_##n##_t * mp)                             \
68     {                                                 \
69         vat_main_t * vam = dpdk_test_main.vat_main;  \
70         i32 retval = ntohl(mp->retval);               \
71         if (vam->async_mode) {                        \
72             vam->async_errors += (retval < 0);        \
73         } else {                                      \
74             vam->retval = retval;                     \
75             vam->result_ready = 1;                    \
76         }                                             \
77     }
78 foreach_standard_reply_retval_handler;
79 #undef _
80
81 /* 
82  * Table of message reply handlers, must include boilerplate handlers
83  * we just generated
84  */
85 #define foreach_vpe_api_reply_msg                               \
86 _(SW_INTERFACE_SET_DPDK_HQOS_PIPE_REPLY,                        \
87   sw_interface_set_dpdk_hqos_pipe_reply)                        \
88 _(SW_INTERFACE_SET_DPDK_HQOS_SUBPORT_REPLY,                     \
89   sw_interface_set_dpdk_hqos_subport_reply)                     \
90 _(SW_INTERFACE_SET_DPDK_HQOS_TCTBL_REPLY,                       \
91   sw_interface_set_dpdk_hqos_tctbl_reply)
92
93 /* M: construct, but don't yet send a message */
94 #define M(T,t)                                                  \
95 do {                                                            \
96     vam->result_ready = 0;                                      \
97     mp = vl_msg_api_alloc(sizeof(*mp));                         \
98     memset (mp, 0, sizeof (*mp));                               \
99     mp->_vl_msg_id = ntohs (VL_API_##T + dm->msg_id_base);      \
100     mp->client_index = vam->my_client_index;                    \
101 } while(0);
102
103 #define M2(T,t,n)                                               \
104 do {                                                            \
105     vam->result_ready = 0;                                      \
106     mp = vl_msg_api_alloc(sizeof(*mp)+(n));                     \
107     memset (mp, 0, sizeof (*mp));                               \
108     mp->_vl_msg_id = ntohs (VL_API_##T + dm->msg_id_base);      \
109     mp->client_index = vam->my_client_index;                    \
110 } while(0);
111
112 /* S: send a message */
113 #define S (vl_msg_api_send_shmem (vam->vl_input_queue, (u8 *)&mp))
114
115 /* W: wait for results, with timeout */
116 #define W                                       \
117 do {                                            \
118     timeout = vat_time_now (vam) + 1.0;         \
119                                                 \
120     while (vat_time_now (vam) < timeout) {      \
121         if (vam->result_ready == 1) {           \
122             return (vam->retval);               \
123         }                                       \
124     }                                           \
125     return -99;                                 \
126 } while(0);
127
128 static int
129 api_sw_interface_set_dpdk_hqos_pipe (vat_main_t * vam)
130 {
131   dpdk_test_main_t * dm = &dpdk_test_main;
132   unformat_input_t *i = vam->input;
133   vl_api_sw_interface_set_dpdk_hqos_pipe_t *mp;
134   f64 timeout;
135   u32 sw_if_index;
136   u8 sw_if_index_set = 0;
137   u32 subport;
138   u8 subport_set = 0;
139   u32 pipe;
140   u8 pipe_set = 0;
141   u32 profile;
142   u8 profile_set = 0;
143
144   /* Parse args required to build the message */
145   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
146     {
147         if (unformat (i, "rx sw_if_index %u", &sw_if_index))
148   sw_if_index_set = 1;
149       else if (unformat (i, "subport %u", &subport))
150   subport_set = 1;
151       else if (unformat (i, "pipe %u", &pipe))
152   pipe_set = 1;
153       else if (unformat (i, "profile %u", &profile))
154   profile_set = 1;
155       else
156   break;
157     }
158
159   if (sw_if_index_set == 0)
160     {
161       errmsg ("missing interface name or sw_if_index");
162       return -99;
163     }
164
165   if (subport_set == 0)
166     {
167       errmsg ("missing subport ");
168       return -99;
169     }
170
171   if (pipe_set == 0)
172     {
173       errmsg ("missing pipe");
174       return -99;
175     }
176
177   if (profile_set == 0)
178     {
179       errmsg ("missing profile");
180       return -99;
181     }
182
183   M (SW_INTERFACE_SET_DPDK_HQOS_PIPE, sw_interface_set_dpdk_hqos_pipe);
184
185   mp->sw_if_index = ntohl (sw_if_index);
186   mp->subport = ntohl (subport);
187   mp->pipe = ntohl (pipe);
188   mp->profile = ntohl (profile);
189
190
191   S;
192   W;
193   /* NOTREACHED */
194   return 0;
195 }
196
197 static int
198 api_sw_interface_set_dpdk_hqos_subport (vat_main_t * vam)
199 {
200   dpdk_test_main_t * dm = &dpdk_test_main;
201   unformat_input_t *i = vam->input;
202   vl_api_sw_interface_set_dpdk_hqos_subport_t *mp;
203   f64 timeout;
204   u32 sw_if_index;
205   u8 sw_if_index_set = 0;
206   u32 subport;
207   u8 subport_set = 0;
208   u32 tb_rate = 1250000000; /* 10GbE */
209   u32 tb_size = 1000000;
210   u32 tc_rate[] = { 1250000000, 1250000000, 1250000000, 1250000000 };
211   u32 tc_period = 10;
212
213   /* Parse args required to build the message */
214   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
215     {
216       if (unformat (i, "rx sw_if_index %u", &sw_if_index))
217   sw_if_index_set = 1;
218       else if (unformat (i, "subport %u", &subport))
219   subport_set = 1;
220       else if (unformat (i, "rate %u", &tb_rate))
221   {
222     u32 tc_id;
223
224     for (tc_id = 0; tc_id < (sizeof (tc_rate) / sizeof (tc_rate[0]));
225          tc_id++)
226       tc_rate[tc_id] = tb_rate;
227   }
228       else if (unformat (i, "bktsize %u", &tb_size))
229   ;
230       else if (unformat (i, "tc0 %u", &tc_rate[0]))
231   ;
232       else if (unformat (i, "tc1 %u", &tc_rate[1]))
233   ;
234       else if (unformat (i, "tc2 %u", &tc_rate[2]))
235   ;
236       else if (unformat (i, "tc3 %u", &tc_rate[3]))
237   ;
238       else if (unformat (i, "period %u", &tc_period))
239   ;
240       else
241   break;
242     }
243
244   if (sw_if_index_set == 0)
245     {
246       errmsg ("missing interface name or sw_if_index");
247       return -99;
248     }
249
250   if (subport_set == 0)
251     {
252       errmsg ("missing subport ");
253       return -99;
254     }
255
256   M (SW_INTERFACE_SET_DPDK_HQOS_SUBPORT, sw_interface_set_dpdk_hqos_subport);
257
258   mp->sw_if_index = ntohl (sw_if_index);
259   mp->subport = ntohl (subport);
260   mp->tb_rate = ntohl (tb_rate);
261   mp->tb_size = ntohl (tb_size);
262   mp->tc_rate[0] = ntohl (tc_rate[0]);
263   mp->tc_rate[1] = ntohl (tc_rate[1]);
264   mp->tc_rate[2] = ntohl (tc_rate[2]);
265   mp->tc_rate[3] = ntohl (tc_rate[3]);
266   mp->tc_period = ntohl (tc_period);
267
268   S;
269   W;
270   /* NOTREACHED */
271   return 0;
272 }
273
274 static int
275 api_sw_interface_set_dpdk_hqos_tctbl (vat_main_t * vam)
276 {
277   dpdk_test_main_t * dm = &dpdk_test_main;
278   unformat_input_t *i = vam->input;
279   vl_api_sw_interface_set_dpdk_hqos_tctbl_t *mp;
280   f64 timeout;
281   u32 sw_if_index;
282   u8 sw_if_index_set = 0;
283   u8 entry_set = 0;
284   u8 tc_set = 0;
285   u8 queue_set = 0;
286   u32 entry, tc, queue;
287
288   /* Parse args required to build the message */
289   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
290     {
291       if (unformat (i, "rx sw_if_index %u", &sw_if_index))
292   sw_if_index_set = 1;
293       else if (unformat (i, "entry %d", &entry))
294   entry_set = 1;
295       else if (unformat (i, "tc %d", &tc))
296   tc_set = 1;
297       else if (unformat (i, "queue %d", &queue))
298   queue_set = 1;
299       else
300   break;
301     }
302
303   if (sw_if_index_set == 0)
304     {
305       errmsg ("missing interface name or sw_if_index");
306       return -99;
307     }
308
309   if (entry_set == 0)
310     {
311       errmsg ("missing entry ");
312       return -99;
313     }
314
315   if (tc_set == 0)
316     {
317       errmsg ("missing traffic class ");
318       return -99;
319     }
320
321   if (queue_set == 0)
322     {
323       errmsg ("missing queue ");
324       return -99;
325     }
326
327   M (SW_INTERFACE_SET_DPDK_HQOS_TCTBL, sw_interface_set_dpdk_hqos_tctbl);
328
329   mp->sw_if_index = ntohl (sw_if_index);
330   mp->entry = ntohl (entry);
331   mp->tc = ntohl (tc);
332   mp->queue = ntohl (queue);
333
334   S;
335   W;
336   /* NOTREACHED */
337   return 0;
338 }
339
340 /* 
341  * List of messages that the api test plugin sends,
342  * and that the data plane plugin processes
343  */
344 #define foreach_vpe_api_msg                                               \
345 _(sw_interface_set_dpdk_hqos_pipe,                                        \
346   "rx sw_if_index <id> subport <subport-id> pipe <pipe-id>\n"   \
347   "profile <profile-id>\n")                                               \
348 _(sw_interface_set_dpdk_hqos_subport,                                     \
349   "rx sw_if_index <id> subport <subport-id> [rate <n>]\n"       \
350   "[bktsize <n>] [tc0 <n>] [tc1 <n>] [tc2 <n>] [tc3 <n>] [period <n>]\n") \
351 _(sw_interface_set_dpdk_hqos_tctbl,                                       \
352   "rx sw_if_index <id> entry <n> tc <n> queue <n>\n")
353
354 static void dpdk_api_hookup (vat_main_t *vam)
355 {
356   dpdk_test_main_t * dm __attribute__((unused)) = &dpdk_test_main;
357   /* Hook up handlers for replies from the data plane plug-in */
358 #define _(N,n)                                                  \
359   vl_msg_api_set_handlers((VL_API_##N + dm->msg_id_base),       \
360                           #n,                                   \
361                           vl_api_##n##_t_handler,               \
362                           vl_noop_handler,                      \
363                           vl_api_##n##_t_endian,                \
364                           vl_api_##n##_t_print,                 \
365                           sizeof(vl_api_##n##_t), 1); 
366   foreach_vpe_api_reply_msg;
367 #undef _
368
369   /* API messages we can send */
370 #define _(n,h) hash_set_mem (vam->function_by_name, #n, api_##n);
371   foreach_vpe_api_msg;
372 #undef _    
373     
374   /* Help strings */
375 #define _(n,h) hash_set_mem (vam->help_by_name, #n, h);
376   foreach_vpe_api_msg;
377 #undef _
378 }
379
380 clib_error_t * vat_plugin_register (vat_main_t *vam)
381 {
382   dpdk_test_main_t * dm = &dpdk_test_main;
383   u8 * name;
384
385   dm->vat_main = vam;
386
387   /* Ask the vpp engine for the first assigned message-id */
388   name = format (0, "dpdk_%08x%c", api_version, 0);
389   dm->msg_id_base = vl_client_get_first_plugin_msg_id ((char *) name);
390
391   if (dm->msg_id_base != (u16) ~0)
392     dpdk_api_hookup (vam);
393   
394   vec_free(name);
395   
396   return 0;
397 }