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:
7 * http://www.apache.org/licenses/LICENSE-2.0
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.
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>
21 #include <vnet/ethernet/ethernet.h>
22 #include <dpdk/device/dpdk.h>
23 #include <vlib/unix/physmem.h>
24 #include <vlib/pci/pci.h>
30 #include <sys/mount.h>
34 #include <dpdk/device/dpdk_priv.h>
36 #include <vlibapi/api.h>
37 #include <vlibmemory/api.h>
39 /* define message IDs */
40 #include <dpdk/api/dpdk_msg_enum.h>
42 #define vl_typedefs /* define message structures */
43 #include <dpdk/api/dpdk_all_api_h.h>
46 #define vl_endianfun /* define message structures */
47 #include <dpdk/api/dpdk_all_api_h.h>
50 #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
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>
57 /* Macro to finish up custom dump fns */
60 vl_print (handle, (char *)s); \
64 #include <vlibapi/api_helper_macros.h>
67 vl_api_sw_interface_set_dpdk_hqos_pipe_t_handler
68 (vl_api_sw_interface_set_dpdk_hqos_pipe_t * mp)
70 vl_api_sw_interface_set_dpdk_hqos_pipe_reply_t *rmp;
73 dpdk_main_t *dm = &dpdk_main;
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;
82 VALIDATE_SW_IF_INDEX (mp);
84 /* hw_if & dpdk device */
85 hw = vnet_get_sup_hw_interface (dm->vnet_main, sw_if_index);
87 xd = vec_elt_at_index (dm->devices, hw->dev_instance);
89 rv = rte_sched_pipe_config (xd->hqos_ht->hqos, subport, pipe, profile);
91 BAD_SW_IF_INDEX_LABEL;
93 REPLY_MACRO (VL_API_SW_INTERFACE_SET_DPDK_HQOS_PIPE_REPLY);
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)
101 s = format (0, "SCRIPT: sw_interface_set_dpdk_hqos_pipe ");
103 s = format (s, "sw_if_index %u ", ntohl (mp->sw_if_index));
105 s = format (s, "subport %u pipe %u profile %u ",
106 ntohl (mp->subport), ntohl (mp->pipe), ntohl (mp->profile));
112 vl_api_sw_interface_set_dpdk_hqos_subport_t_handler
113 (vl_api_sw_interface_set_dpdk_hqos_subport_t * mp)
115 vl_api_sw_interface_set_dpdk_hqos_subport_reply_t *rmp;
118 dpdk_main_t *dm = &dpdk_main;
120 struct rte_sched_subport_params p;
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);
132 vnet_hw_interface_t *hw;
134 VALIDATE_SW_IF_INDEX (mp);
136 /* hw_if & dpdk device */
137 hw = vnet_get_sup_hw_interface (dm->vnet_main, sw_if_index);
139 xd = vec_elt_at_index (dm->devices, hw->dev_instance);
141 rv = rte_sched_subport_config (xd->hqos_ht->hqos, subport, &p);
143 BAD_SW_IF_INDEX_LABEL;
145 REPLY_MACRO (VL_API_SW_INTERFACE_SET_DPDK_HQOS_SUBPORT_REPLY);
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)
153 s = format (0, "SCRIPT: sw_interface_set_dpdk_hqos_subport ");
155 s = format (s, "sw_if_index %u ", ntohl (mp->sw_if_index));
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));
169 vl_api_sw_interface_set_dpdk_hqos_tctbl_t_handler
170 (vl_api_sw_interface_set_dpdk_hqos_tctbl_t * mp)
172 vl_api_sw_interface_set_dpdk_hqos_tctbl_reply_t *rmp;
175 dpdk_main_t *dm = &dpdk_main;
176 vlib_thread_main_t *tm = vlib_get_thread_main ();
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);
185 vnet_hw_interface_t *hw;
187 VALIDATE_SW_IF_INDEX (mp);
189 /* hw_if & dpdk device */
190 hw = vnet_get_sup_hw_interface (dm->vnet_main, sw_if_index);
192 xd = vec_elt_at_index (dm->devices, hw->dev_instance);
194 if (tc >= RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE)
196 clib_warning ("invalid traffic class !!");
197 rv = VNET_API_ERROR_INVALID_VALUE;
200 if (queue >= RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS)
202 clib_warning ("invalid queue !!");
203 rv = VNET_API_ERROR_INVALID_VALUE;
207 /* Detect the set of worker threads */
208 uword *p = hash_get_mem (tm->thread_registrations_by_name, "workers");
212 clib_warning ("worker thread registration AWOL !!");
213 rv = VNET_API_ERROR_INVALID_VALUE_2;
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;
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;
225 BAD_SW_IF_INDEX_LABEL;
228 REPLY_MACRO (VL_API_SW_INTERFACE_SET_DPDK_HQOS_TCTBL_REPLY);
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)
236 s = format (0, "SCRIPT: sw_interface_set_dpdk_hqos_tctbl ");
238 s = format (s, "sw_if_index %u ", ntohl (mp->sw_if_index));
240 s = format (s, "entry %u tc %u queue %u",
241 ntohl (mp->entry), ntohl (mp->tc), ntohl (mp->queue));
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)
251 /* Set up the API message handling tables */
252 static clib_error_t *
253 dpdk_plugin_api_hookup (vlib_main_t * vm)
255 dpdk_main_t *dm __attribute__ ((unused)) = &dpdk_main;
257 vl_msg_api_set_handlers((VL_API_##N + dm->msg_id_base), \
259 vl_api_##n##_t_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;
269 #define vl_msg_name_crc_list
270 #include <dpdk/api/dpdk_all_api_h.h>
271 #undef vl_msg_name_crc_list
274 setup_message_id_table (dpdk_main_t * dm, api_main_t * am)
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;
284 static void plugin_custom_dump_configure (dpdk_main_t * dm)
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;
293 /* force linker to link functions used by vlib and declared weak */
295 static clib_error_t *
296 dpdk_api_init (vlib_main_t * vm)
298 dpdk_main_t *dm = &dpdk_main;
299 clib_error_t *error = 0;
302 if ((error = vlib_call_init_function (vm, dpdk_init)))
306 name = format (0, "dpdk_%08x%c", api_version, 0);
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);
313 error = dpdk_plugin_api_hookup (vm);
315 /* Add our API messages to the global name_crc hash table */
316 setup_message_id_table (dm, &api_main);
319 // plugin_custom_dump_configure (dm);
324 VLIB_INIT_FUNCTION (dpdk_api_init);
328 * fd.io coding-style-patch-verification: ON
331 * eval: (c-set-style "gnu")