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/pci/pci.h>
29 #include <sys/mount.h>
33 #include <dpdk/device/dpdk_priv.h>
35 #include <vlibapi/api.h>
36 #include <vlibmemory/api.h>
38 /* define message IDs */
39 #include <dpdk/api/dpdk_msg_enum.h>
41 #define vl_typedefs /* define message structures */
42 #include <dpdk/api/dpdk_all_api_h.h>
45 #define vl_endianfun /* define message structures */
46 #include <dpdk/api/dpdk_all_api_h.h>
49 #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
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>
56 /* Macro to finish up custom dump fns */
59 vl_print (handle, (char *)s); \
63 #include <vlibapi/api_helper_macros.h>
66 vl_api_sw_interface_set_dpdk_hqos_pipe_t_handler
67 (vl_api_sw_interface_set_dpdk_hqos_pipe_t * mp)
69 vl_api_sw_interface_set_dpdk_hqos_pipe_reply_t *rmp;
72 dpdk_main_t *dm = &dpdk_main;
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;
81 VALIDATE_SW_IF_INDEX (mp);
83 /* hw_if & dpdk device */
84 hw = vnet_get_sup_hw_interface (dm->vnet_main, sw_if_index);
86 xd = vec_elt_at_index (dm->devices, hw->dev_instance);
88 rv = rte_sched_pipe_config (xd->hqos_ht->hqos, subport, pipe, profile);
90 BAD_SW_IF_INDEX_LABEL;
92 REPLY_MACRO (VL_API_SW_INTERFACE_SET_DPDK_HQOS_PIPE_REPLY);
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)
100 s = format (0, "SCRIPT: sw_interface_set_dpdk_hqos_pipe ");
102 s = format (s, "sw_if_index %u ", ntohl (mp->sw_if_index));
104 s = format (s, "subport %u pipe %u profile %u ",
105 ntohl (mp->subport), ntohl (mp->pipe), ntohl (mp->profile));
111 vl_api_sw_interface_set_dpdk_hqos_subport_t_handler
112 (vl_api_sw_interface_set_dpdk_hqos_subport_t * mp)
114 vl_api_sw_interface_set_dpdk_hqos_subport_reply_t *rmp;
117 dpdk_main_t *dm = &dpdk_main;
119 struct rte_sched_subport_params p;
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);
131 vnet_hw_interface_t *hw;
133 VALIDATE_SW_IF_INDEX (mp);
135 /* hw_if & dpdk device */
136 hw = vnet_get_sup_hw_interface (dm->vnet_main, sw_if_index);
138 xd = vec_elt_at_index (dm->devices, hw->dev_instance);
140 rv = rte_sched_subport_config (xd->hqos_ht->hqos, subport, &p);
142 BAD_SW_IF_INDEX_LABEL;
144 REPLY_MACRO (VL_API_SW_INTERFACE_SET_DPDK_HQOS_SUBPORT_REPLY);
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)
152 s = format (0, "SCRIPT: sw_interface_set_dpdk_hqos_subport ");
154 s = format (s, "sw_if_index %u ", ntohl (mp->sw_if_index));
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));
168 vl_api_sw_interface_set_dpdk_hqos_tctbl_t_handler
169 (vl_api_sw_interface_set_dpdk_hqos_tctbl_t * mp)
171 vl_api_sw_interface_set_dpdk_hqos_tctbl_reply_t *rmp;
174 dpdk_main_t *dm = &dpdk_main;
175 vlib_thread_main_t *tm = vlib_get_thread_main ();
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);
184 vnet_hw_interface_t *hw;
186 VALIDATE_SW_IF_INDEX (mp);
188 /* hw_if & dpdk device */
189 hw = vnet_get_sup_hw_interface (dm->vnet_main, sw_if_index);
191 xd = vec_elt_at_index (dm->devices, hw->dev_instance);
193 if (tc >= RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE)
195 clib_warning ("invalid traffic class !!");
196 rv = VNET_API_ERROR_INVALID_VALUE;
199 if (queue >= RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS)
201 clib_warning ("invalid queue !!");
202 rv = VNET_API_ERROR_INVALID_VALUE;
206 /* Detect the set of worker threads */
207 uword *p = hash_get_mem (tm->thread_registrations_by_name, "workers");
211 clib_warning ("worker thread registration AWOL !!");
212 rv = VNET_API_ERROR_INVALID_VALUE_2;
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;
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;
224 BAD_SW_IF_INDEX_LABEL;
227 REPLY_MACRO (VL_API_SW_INTERFACE_SET_DPDK_HQOS_TCTBL_REPLY);
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)
235 s = format (0, "SCRIPT: sw_interface_set_dpdk_hqos_tctbl ");
237 s = format (s, "sw_if_index %u ", ntohl (mp->sw_if_index));
239 s = format (s, "entry %u tc %u queue %u",
240 ntohl (mp->entry), ntohl (mp->tc), ntohl (mp->queue));
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)
250 /* Set up the API message handling tables */
251 static clib_error_t *
252 dpdk_plugin_api_hookup (vlib_main_t * vm)
254 dpdk_main_t *dm __attribute__ ((unused)) = &dpdk_main;
256 vl_msg_api_set_handlers((VL_API_##N + dm->msg_id_base), \
258 vl_api_##n##_t_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;
268 #define vl_msg_name_crc_list
269 #include <dpdk/api/dpdk_all_api_h.h>
270 #undef vl_msg_name_crc_list
273 setup_message_id_table (dpdk_main_t * dm, api_main_t * am)
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;
283 static void plugin_custom_dump_configure (dpdk_main_t * dm)
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;
292 /* force linker to link functions used by vlib and declared weak */
294 static clib_error_t *
295 dpdk_api_init (vlib_main_t * vm)
297 dpdk_main_t *dm = &dpdk_main;
298 clib_error_t *error = 0;
301 if ((error = vlib_call_init_function (vm, dpdk_init)))
305 name = format (0, "dpdk_%08x%c", api_version, 0);
307 /* Ask for a correctly-sized block of API message decode slots */
308 dm->msg_id_base = vl_msg_api_get_msg_ids
309 ((char *) name, VL_MSG_FIRST_AVAILABLE);
312 error = dpdk_plugin_api_hookup (vm);
314 /* Add our API messages to the global name_crc hash table */
315 setup_message_id_table (dm, &api_main);
318 // plugin_custom_dump_configure (dm);
323 VLIB_INIT_FUNCTION (dpdk_api_init);
327 * fd.io coding-style-patch-verification: ON
330 * eval: (c-set-style "gnu")