Line data Source code
1 : /*
2 : *------------------------------------------------------------------
3 : * Copyright (c) 2018 Cisco and/or its affiliates.
4 : * Licensed under the Apache License, Version 2.0 (the "License");
5 : * you may not use this file except in compliance with the License.
6 : * You may obtain a copy of the License at:
7 : *
8 : * http://www.apache.org/licenses/LICENSE-2.0
9 : *
10 : * Unless required by applicable law or agreed to in writing, software
11 : * distributed under the License is distributed on an "AS IS" BASIS,
12 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 : * See the License for the specific language governing permissions and
14 : * limitations under the License.
15 : *------------------------------------------------------------------
16 : */
17 :
18 : #include <vlib/vlib.h>
19 : #include <vlib/unix/unix.h>
20 : #include <vlib/pci/pci.h>
21 : #include <vnet/ethernet/ethernet.h>
22 : #include <vnet/format_fns.h>
23 :
24 : #include <vat/vat.h>
25 : #include <vlibapi/api.h>
26 : #include <vlibmemory/api.h>
27 :
28 : #include <vppinfra/error.h>
29 : #include <vmxnet3/vmxnet3.h>
30 :
31 : #define __plugin_msg_base vmxnet3_test_main.msg_id_base
32 : #include <vlibapi/vat_helper_macros.h>
33 :
34 : /* declare message IDs */
35 : #include <vmxnet3/vmxnet3.api_enum.h>
36 : #include <vmxnet3/vmxnet3.api_types.h>
37 : #include <vlibmemory/vlib.api_types.h>
38 :
39 : typedef struct
40 : {
41 : /* API message ID base */
42 : u16 msg_id_base;
43 : u32 ping_id;
44 : vat_main_t *vat_main;
45 : } vmxnet3_test_main_t;
46 :
47 : vmxnet3_test_main_t vmxnet3_test_main;
48 :
49 : /* vmxnet3 create API */
50 : static int
51 0 : api_vmxnet3_create (vat_main_t * vam)
52 : {
53 0 : unformat_input_t *i = vam->input;
54 : vl_api_vmxnet3_create_t *mp;
55 : vmxnet3_create_if_args_t args;
56 : int ret;
57 : u32 size;
58 :
59 0 : clib_memset (&args, 0, sizeof (vmxnet3_create_if_args_t));
60 :
61 0 : while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
62 : {
63 0 : if (unformat (i, "%U", unformat_vlib_pci_addr, &args.addr))
64 : ;
65 0 : else if (unformat (i, "elog"))
66 0 : args.enable_elog = 1;
67 0 : else if (unformat (i, "bind"))
68 0 : args.bind = 1;
69 0 : else if (unformat (i, "gso"))
70 0 : args.enable_gso = 1;
71 0 : else if (unformat (i, "rx-queue-size %u", &size))
72 0 : args.rxq_size = size;
73 0 : else if (unformat (i, "tx-queue-size %u", &size))
74 0 : args.txq_size = size;
75 0 : else if (unformat (i, "num-tx-queues %u", &size))
76 0 : args.txq_num = size;
77 0 : else if (unformat (i, "num-rx-queues %u", &size))
78 0 : args.rxq_num = size;
79 : else
80 : {
81 0 : clib_warning ("unknown input '%U'", format_unformat_error, i);
82 0 : return -99;
83 : }
84 : }
85 :
86 0 : M (VMXNET3_CREATE, mp);
87 :
88 0 : mp->pci_addr = clib_host_to_net_u32 (args.addr.as_u32);
89 0 : mp->enable_elog = clib_host_to_net_u16 (args.enable_elog);
90 0 : mp->rxq_size = clib_host_to_net_u16 (args.rxq_size);
91 0 : mp->txq_size = clib_host_to_net_u16 (args.txq_size);
92 0 : mp->txq_num = clib_host_to_net_u16 (args.txq_num);
93 0 : mp->rxq_num = clib_host_to_net_u16 (args.rxq_num);
94 0 : mp->bind = args.bind;
95 0 : mp->enable_gso = args.enable_gso;
96 :
97 0 : S (mp);
98 0 : W (ret);
99 :
100 0 : return ret;
101 : }
102 :
103 : /* vmxnet3-create reply handler */
104 : static void
105 0 : vl_api_vmxnet3_create_reply_t_handler (vl_api_vmxnet3_create_reply_t * mp)
106 : {
107 0 : vat_main_t *vam = vmxnet3_test_main.vat_main;
108 0 : i32 retval = ntohl (mp->retval);
109 :
110 0 : if (retval == 0)
111 : {
112 0 : fformat (vam->ofp, "created vmxnet3 with sw_if_index %d\n",
113 : ntohl (mp->sw_if_index));
114 : }
115 :
116 0 : vam->retval = retval;
117 0 : vam->result_ready = 1;
118 0 : vam->regenerate_interface_table = 1;
119 0 : }
120 :
121 : /* vmxnet3 delete API */
122 : static int
123 0 : api_vmxnet3_delete (vat_main_t * vam)
124 : {
125 0 : unformat_input_t *i = vam->input;
126 : vl_api_vmxnet3_delete_t *mp;
127 0 : u32 sw_if_index = 0;
128 0 : u8 index_defined = 0;
129 : int ret;
130 :
131 0 : while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
132 : {
133 0 : if (unformat (i, "sw_if_index %u", &sw_if_index))
134 0 : index_defined = 1;
135 : else
136 : {
137 0 : clib_warning ("unknown input '%U'", format_unformat_error, i);
138 0 : return -99;
139 : }
140 : }
141 :
142 0 : if (!index_defined)
143 : {
144 0 : errmsg ("missing sw_if_index\n");
145 0 : return -99;
146 : }
147 :
148 0 : M (VMXNET3_DELETE, mp);
149 :
150 0 : mp->sw_if_index = clib_host_to_net_u32 (sw_if_index);
151 :
152 0 : S (mp);
153 0 : W (ret);
154 :
155 0 : return ret;
156 : }
157 :
158 : static int
159 0 : api_vmxnet3_dump (vat_main_t * vam)
160 : {
161 0 : vmxnet3_test_main_t *vxm = &vmxnet3_test_main;
162 : vl_api_vmxnet3_dump_t *mp;
163 : vl_api_control_ping_t *mp_ping;
164 : int ret;
165 :
166 0 : if (vam->json_output)
167 : {
168 0 : clib_warning ("JSON output not supported for vmxnet3_dump");
169 0 : return -99;
170 : }
171 :
172 0 : M (VMXNET3_DUMP, mp);
173 0 : S (mp);
174 :
175 : /* Use a control ping for synchronization */
176 0 : if (!vxm->ping_id)
177 0 : vxm->ping_id =
178 0 : vl_msg_api_get_msg_index ((u8 *) (VL_API_CONTROL_PING_CRC));
179 0 : mp_ping = vl_msg_api_alloc_as_if_client (sizeof (*mp_ping));
180 0 : mp_ping->_vl_msg_id = htons (vxm->ping_id);
181 0 : mp_ping->client_index = vam->my_client_index;
182 :
183 0 : fformat (vam->ofp, "Sending ping id=%d\n", vxm->ping_id);
184 :
185 0 : vam->result_ready = 0;
186 0 : S (mp_ping);
187 :
188 0 : W (ret);
189 0 : return ret;
190 : }
191 :
192 : static int
193 0 : api_sw_vmxnet3_interface_dump (vat_main_t * vam)
194 : {
195 0 : vmxnet3_test_main_t *vxm = &vmxnet3_test_main;
196 : vl_api_sw_vmxnet3_interface_dump_t *mp;
197 : vl_api_control_ping_t *mp_ping;
198 : int ret;
199 0 : u32 sw_if_index = ~0;
200 0 : unformat_input_t *i = vam->input;
201 :
202 0 : while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
203 : {
204 0 : if (unformat (i, "sw_if_index %d", &sw_if_index))
205 : ;
206 : else
207 0 : break;
208 : }
209 :
210 0 : if (vam->json_output)
211 : {
212 0 : clib_warning ("JSON output not supported for vmxnet3_dump");
213 0 : return -99;
214 : }
215 :
216 0 : M (SW_VMXNET3_INTERFACE_DUMP, mp);
217 0 : mp->sw_if_index = ntohl (sw_if_index);
218 0 : S (mp);
219 :
220 : /* Use a control ping for synchronization */
221 0 : if (!vxm->ping_id)
222 0 : vxm->ping_id =
223 0 : vl_msg_api_get_msg_index ((u8 *) (VL_API_CONTROL_PING_CRC));
224 0 : mp_ping = vl_msg_api_alloc_as_if_client (sizeof (*mp_ping));
225 0 : mp_ping->_vl_msg_id = htons (vxm->ping_id);
226 0 : mp_ping->client_index = vam->my_client_index;
227 :
228 0 : fformat (vam->ofp, "Sending ping id=%d\n", vxm->ping_id);
229 :
230 0 : vam->result_ready = 0;
231 0 : S (mp_ping);
232 :
233 0 : W (ret);
234 0 : return ret;
235 : }
236 :
237 : static u8 *
238 0 : format_pci_addr (u8 * s, va_list * va)
239 : {
240 0 : vlib_pci_addr_t *addr = va_arg (*va, vlib_pci_addr_t *);
241 0 : return format (s, "%04x:%02x:%02x.%x", addr->domain, addr->bus,
242 0 : addr->slot, addr->function);
243 : }
244 :
245 : static void
246 0 : vl_api_vmxnet3_details_t_handler (vl_api_vmxnet3_details_t * mp)
247 : {
248 0 : vat_main_t *vam = vmxnet3_test_main.vat_main;
249 0 : u32 pci_addr = ntohl (mp->pci_addr);
250 : u16 qid;
251 :
252 0 : fformat (vam->ofp, "%s: sw_if_index %u mac %U\n"
253 : " version: %u\n"
254 : " PCI Address: %U\n"
255 : " state %s\n",
256 0 : mp->if_name, ntohl (mp->sw_if_index), format_ethernet_address,
257 0 : mp->hw_addr, mp->version,
258 0 : format_pci_addr, &pci_addr, mp->admin_up_down ? "up" : "down");
259 0 : for (qid = 0; qid < mp->rx_count; qid++)
260 : {
261 0 : vl_api_vmxnet3_rx_list_t *rx_list = &mp->rx_list[qid];
262 0 : fformat (vam->ofp,
263 : " RX Queue %u\n"
264 : " RX completion next index %u\n"
265 : " ring 0 size %u fill %u consume %u produce %u\n"
266 : " ring 1 size %u fill %u consume %u produce %u\n",
267 : qid,
268 0 : ntohs (rx_list->rx_next),
269 0 : ntohs (rx_list->rx_qsize), ntohs (rx_list->rx_fill[0]),
270 0 : ntohs (rx_list->rx_consume[0]),
271 0 : ntohs (rx_list->rx_produce[0]),
272 0 : ntohs (rx_list->rx_qsize), ntohs (rx_list->rx_fill[1]),
273 0 : ntohs (rx_list->rx_consume[1]),
274 0 : ntohs (rx_list->rx_produce[1]));
275 : }
276 0 : for (qid = 0; qid < mp->tx_count; qid++)
277 : {
278 0 : vl_api_vmxnet3_tx_list_t *tx_list = &mp->tx_list[qid];
279 0 : fformat (vam->ofp,
280 : " TX Queue %u\n"
281 : " TX completion next index %u\n"
282 : " size %u consume %u produce %u\n",
283 : qid,
284 0 : ntohs (tx_list->tx_next),
285 0 : ntohs (tx_list->tx_qsize), ntohs (tx_list->tx_consume),
286 0 : ntohs (tx_list->tx_produce));
287 : }
288 0 : }
289 :
290 0 : static void vl_api_sw_vmxnet3_interface_details_t_handler
291 : (vl_api_sw_vmxnet3_interface_details_t * mp)
292 : {
293 0 : vat_main_t *vam = vmxnet3_test_main.vat_main;
294 0 : u32 pci_addr = ntohl (mp->pci_addr);
295 : u16 qid;
296 :
297 0 : fformat (vam->ofp, "%s: sw_if_index %u mac %U\n"
298 : " version: %u\n"
299 : " PCI Address: %U\n"
300 : " state %s\n",
301 0 : mp->if_name, ntohl (mp->sw_if_index), format_ethernet_address,
302 0 : mp->hw_addr, mp->version,
303 0 : format_pci_addr, &pci_addr, mp->admin_up_down ? "up" : "down");
304 0 : for (qid = 0; qid < mp->rx_count; qid++)
305 : {
306 0 : vl_api_vmxnet3_rx_list_t *rx_list = &mp->rx_list[qid];
307 0 : fformat (vam->ofp,
308 : " RX Queue %u\n"
309 : " RX completion next index %u\n"
310 : " ring 0 size %u fill %u consume %u produce %u\n"
311 : " ring 1 size %u fill %u consume %u produce %u\n",
312 : qid,
313 0 : ntohs (rx_list->rx_next),
314 0 : ntohs (rx_list->rx_qsize), ntohs (rx_list->rx_fill[0]),
315 0 : ntohs (rx_list->rx_consume[0]),
316 0 : ntohs (rx_list->rx_produce[0]),
317 0 : ntohs (rx_list->rx_qsize), ntohs (rx_list->rx_fill[1]),
318 0 : ntohs (rx_list->rx_consume[1]),
319 0 : ntohs (rx_list->rx_produce[1]));
320 : }
321 0 : for (qid = 0; qid < mp->tx_count; qid++)
322 : {
323 0 : vl_api_vmxnet3_tx_list_t *tx_list = &mp->tx_list[qid];
324 0 : fformat (vam->ofp,
325 : " TX Queue %u\n"
326 : " TX completion next index %u\n"
327 : " size %u consume %u produce %u\n",
328 : qid,
329 0 : ntohs (tx_list->tx_next),
330 0 : ntohs (tx_list->tx_qsize), ntohs (tx_list->tx_consume),
331 0 : ntohs (tx_list->tx_produce));
332 : }
333 0 : }
334 :
335 : #include <vmxnet3/vmxnet3.api_test.c>
336 :
337 : /*
338 : * fd.io coding-style-patch-verification: ON
339 : *
340 : * Local Variables:
341 : * eval: (c-set-style "gnu")
342 : * End:
343 : */
|