dpdk: cleanup, move APIs to separate .c file
[vpp.git] / src / plugins / dpdk / api / dpdk_api.c
1 /*
2  * Copyright (c) 2017 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include <vnet/vnet.h>
16 #include <vppinfra/vec.h>
17 #include <vppinfra/error.h>
18 #include <vppinfra/format.h>
19 #include <vppinfra/bitmap.h>
20
21 #include <vnet/ethernet/ethernet.h>
22 #include <dpdk/device/dpdk.h>
23 #include <vlib/unix/physmem.h>
24 #include <vlib/pci/pci.h>
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <unistd.h>
29 #include <sys/stat.h>
30 #include <sys/mount.h>
31 #include <string.h>
32 #include <fcntl.h>
33
34 #include <dpdk/device/dpdk_priv.h>
35
36 #include <vlibapi/api.h>
37 #include <vlibmemory/api.h>
38
39 /* define message IDs */
40 #include <dpdk/api/dpdk_msg_enum.h>
41
42 #define vl_typedefs             /* define message structures */
43 #include <dpdk/api/dpdk_all_api_h.h>
44 #undef vl_typedefs
45
46 #define vl_endianfun            /* define message structures */
47 #include <dpdk/api/dpdk_all_api_h.h>
48 #undef vl_endianfun
49
50 #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
51
52 /* Get the API version number. */
53 #define vl_api_version(n,v) static u32 api_version=(v);
54 #include <dpdk/api/dpdk_all_api_h.h>
55 #undef vl_api_version
56
57 /* Macro to finish up custom dump fns */
58 #define FINISH                                  \
59     vec_add1 (s, 0);                            \
60     vl_print (handle, (char *)s);               \
61     vec_free (s);                               \
62     return handle;
63
64 #include <vlibapi/api_helper_macros.h>
65
66 static void
67   vl_api_sw_interface_set_dpdk_hqos_pipe_t_handler
68   (vl_api_sw_interface_set_dpdk_hqos_pipe_t * mp)
69 {
70   vl_api_sw_interface_set_dpdk_hqos_pipe_reply_t *rmp;
71   int rv = 0;
72
73   dpdk_main_t *dm = &dpdk_main;
74   dpdk_device_t *xd;
75
76   u32 sw_if_index = ntohl (mp->sw_if_index);
77   u32 subport = ntohl (mp->subport);
78   u32 pipe = ntohl (mp->pipe);
79   u32 profile = ntohl (mp->profile);
80   vnet_hw_interface_t *hw;
81
82   VALIDATE_SW_IF_INDEX (mp);
83
84   /* hw_if & dpdk device */
85   hw = vnet_get_sup_hw_interface (dm->vnet_main, sw_if_index);
86
87   xd = vec_elt_at_index (dm->devices, hw->dev_instance);
88
89   rv = rte_sched_pipe_config (xd->hqos_ht->hqos, subport, pipe, profile);
90
91   BAD_SW_IF_INDEX_LABEL;
92
93   REPLY_MACRO (VL_API_SW_INTERFACE_SET_DPDK_HQOS_PIPE_REPLY);
94 }
95
96 static void *vl_api_sw_interface_set_dpdk_hqos_pipe_t_print
97   (vl_api_sw_interface_set_dpdk_hqos_pipe_t * mp, void *handle)
98 {
99   u8 *s;
100
101   s = format (0, "SCRIPT: sw_interface_set_dpdk_hqos_pipe ");
102
103   s = format (s, "sw_if_index %u ", ntohl (mp->sw_if_index));
104
105   s = format (s, "subport %u  pipe %u  profile %u ",
106               ntohl (mp->subport), ntohl (mp->pipe), ntohl (mp->profile));
107
108   FINISH;
109 }
110
111 static void
112   vl_api_sw_interface_set_dpdk_hqos_subport_t_handler
113   (vl_api_sw_interface_set_dpdk_hqos_subport_t * mp)
114 {
115   vl_api_sw_interface_set_dpdk_hqos_subport_reply_t *rmp;
116   int rv = 0;
117
118   dpdk_main_t *dm = &dpdk_main;
119   dpdk_device_t *xd;
120   struct rte_sched_subport_params p;
121
122   u32 sw_if_index = ntohl (mp->sw_if_index);
123   u32 subport = ntohl (mp->subport);
124   p.tb_rate = ntohl (mp->tb_rate);
125   p.tb_size = ntohl (mp->tb_size);
126   p.tc_rate[0] = ntohl (mp->tc_rate[0]);
127   p.tc_rate[1] = ntohl (mp->tc_rate[1]);
128   p.tc_rate[2] = ntohl (mp->tc_rate[2]);
129   p.tc_rate[3] = ntohl (mp->tc_rate[3]);
130   p.tc_period = ntohl (mp->tc_period);
131
132   vnet_hw_interface_t *hw;
133
134   VALIDATE_SW_IF_INDEX (mp);
135
136   /* hw_if & dpdk device */
137   hw = vnet_get_sup_hw_interface (dm->vnet_main, sw_if_index);
138
139   xd = vec_elt_at_index (dm->devices, hw->dev_instance);
140
141   rv = rte_sched_subport_config (xd->hqos_ht->hqos, subport, &p);
142
143   BAD_SW_IF_INDEX_LABEL;
144
145   REPLY_MACRO (VL_API_SW_INTERFACE_SET_DPDK_HQOS_SUBPORT_REPLY);
146 }
147
148 static void *vl_api_sw_interface_set_dpdk_hqos_subport_t_print
149   (vl_api_sw_interface_set_dpdk_hqos_subport_t * mp, void *handle)
150 {
151   u8 *s;
152
153   s = format (0, "SCRIPT: sw_interface_set_dpdk_hqos_subport ");
154
155   s = format (s, "sw_if_index %u ", ntohl (mp->sw_if_index));
156
157   s =
158     format (s,
159             "subport %u  rate %u  bkt_size %u  tc0 %u tc1 %u tc2 %u tc3 %u period %u",
160             ntohl (mp->subport), ntohl (mp->tb_rate), ntohl (mp->tb_size),
161             ntohl (mp->tc_rate[0]), ntohl (mp->tc_rate[1]),
162             ntohl (mp->tc_rate[2]), ntohl (mp->tc_rate[3]),
163             ntohl (mp->tc_period));
164
165   FINISH;
166 }
167
168 static void
169   vl_api_sw_interface_set_dpdk_hqos_tctbl_t_handler
170   (vl_api_sw_interface_set_dpdk_hqos_tctbl_t * mp)
171 {
172   vl_api_sw_interface_set_dpdk_hqos_tctbl_reply_t *rmp;
173   int rv = 0;
174
175   dpdk_main_t *dm = &dpdk_main;
176   vlib_thread_main_t *tm = vlib_get_thread_main ();
177   dpdk_device_t *xd;
178
179   u32 sw_if_index = ntohl (mp->sw_if_index);
180   u32 entry = ntohl (mp->entry);
181   u32 tc = ntohl (mp->tc);
182   u32 queue = ntohl (mp->queue);
183   u32 val, i;
184
185   vnet_hw_interface_t *hw;
186
187   VALIDATE_SW_IF_INDEX (mp);
188
189   /* hw_if & dpdk device */
190   hw = vnet_get_sup_hw_interface (dm->vnet_main, sw_if_index);
191
192   xd = vec_elt_at_index (dm->devices, hw->dev_instance);
193
194   if (tc >= RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE)
195     {
196       clib_warning ("invalid traffic class !!");
197       rv = VNET_API_ERROR_INVALID_VALUE;
198       goto done;
199     }
200   if (queue >= RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS)
201     {
202       clib_warning ("invalid queue !!");
203       rv = VNET_API_ERROR_INVALID_VALUE;
204       goto done;
205     }
206
207   /* Detect the set of worker threads */
208   uword *p = hash_get_mem (tm->thread_registrations_by_name, "workers");
209
210   if (p == 0)
211     {
212       clib_warning ("worker thread registration AWOL !!");
213       rv = VNET_API_ERROR_INVALID_VALUE_2;
214       goto done;
215     }
216
217   vlib_thread_registration_t *tr = (vlib_thread_registration_t *) p[0];
218   int worker_thread_first = tr->first_index;
219   int worker_thread_count = tr->count;
220
221   val = tc * RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS + queue;
222   for (i = 0; i < worker_thread_count; i++)
223     xd->hqos_wt[worker_thread_first + i].hqos_tc_table[entry] = val;
224
225   BAD_SW_IF_INDEX_LABEL;
226 done:
227
228   REPLY_MACRO (VL_API_SW_INTERFACE_SET_DPDK_HQOS_TCTBL_REPLY);
229 }
230
231 static void *vl_api_sw_interface_set_dpdk_hqos_tctbl_t_print
232   (vl_api_sw_interface_set_dpdk_hqos_tctbl_t * mp, void *handle)
233 {
234   u8 *s;
235
236   s = format (0, "SCRIPT: sw_interface_set_dpdk_hqos_tctbl ");
237
238   s = format (s, "sw_if_index %u ", ntohl (mp->sw_if_index));
239
240   s = format (s, "entry %u  tc %u  queue %u",
241               ntohl (mp->entry), ntohl (mp->tc), ntohl (mp->queue));
242
243   FINISH;
244 }
245
246 #define foreach_dpdk_plugin_api_msg                                       \
247 _(SW_INTERFACE_SET_DPDK_HQOS_PIPE, sw_interface_set_dpdk_hqos_pipe)       \
248 _(SW_INTERFACE_SET_DPDK_HQOS_SUBPORT, sw_interface_set_dpdk_hqos_subport) \
249 _(SW_INTERFACE_SET_DPDK_HQOS_TCTBL, sw_interface_set_dpdk_hqos_tctbl)
250
251 /* Set up the API message handling tables */
252 static clib_error_t *
253 dpdk_plugin_api_hookup (vlib_main_t * vm)
254 {
255   dpdk_main_t *dm __attribute__ ((unused)) = &dpdk_main;
256 #define _(N,n)                                                  \
257     vl_msg_api_set_handlers((VL_API_##N + dm->msg_id_base),     \
258                            #n,          \
259                            vl_api_##n##_t_handler,              \
260                            vl_noop_handler,                     \
261                            vl_api_##n##_t_endian,               \
262                            vl_api_##n##_t_print,                \
263                            sizeof(vl_api_##n##_t), 1);
264   foreach_dpdk_plugin_api_msg;
265 #undef _
266   return 0;
267 }
268
269 #define vl_msg_name_crc_list
270 #include <dpdk/api/dpdk_all_api_h.h>
271 #undef vl_msg_name_crc_list
272
273 static void
274 setup_message_id_table (dpdk_main_t * dm, api_main_t * am)
275 {
276 #define _(id,n,crc) \
277   vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id + dm->msg_id_base);
278   foreach_vl_msg_name_crc_dpdk;
279 #undef _
280 }
281
282 //  TODO
283 /*
284 static void plugin_custom_dump_configure (dpdk_main_t * dm)
285 {
286 #define _(n,f) dm->api_main->msg_print_handlers \
287   [VL_API_##n + dm->msg_id_base]                \
288     = (void *) vl_api_##f##_t_print;
289   foreach_dpdk_plugin_api_msg;
290 #undef _
291 }
292 */
293 /* force linker to link functions used by vlib and declared weak */
294
295 static clib_error_t *
296 dpdk_api_init (vlib_main_t * vm)
297 {
298   dpdk_main_t *dm = &dpdk_main;
299   clib_error_t *error = 0;
300
301   /* init CLI */
302   if ((error = vlib_call_init_function (vm, dpdk_init)))
303     return error;
304
305   u8 *name;
306   name = format (0, "dpdk_%08x%c", api_version, 0);
307
308   /* Ask for a correctly-sized block of API message decode slots */
309   dm->msg_id_base = vl_msg_api_get_msg_ids
310     ((char *) name, VL_MSG_FIRST_AVAILABLE);
311   vec_free (name);
312
313   error = dpdk_plugin_api_hookup (vm);
314
315   /* Add our API messages to the global name_crc hash table */
316   setup_message_id_table (dm, &api_main);
317
318 //  TODO
319 //  plugin_custom_dump_configure (dm);
320
321   return error;
322 }
323
324 VLIB_INIT_FUNCTION (dpdk_api_init);
325
326
327 /*
328  * fd.io coding-style-patch-verification: ON
329  *
330  * Local Variables:
331  * eval: (c-set-style "gnu")
332  * End:
333  */