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