hs-test: cat summary file after a failed test run
[vpp.git] / src / plugins / dev_iavf / virtchnl.c
1 /* SPDX-License-Identifier: Apache-2.0
2  * Copyright (c) 2023 Cisco Systems, Inc.
3  */
4
5 #include <vnet/vnet.h>
6 #include <vnet/dev/dev.h>
7 #include <vnet/dev/counters.h>
8 #include <dev_iavf/iavf.h>
9 #include <dev_iavf/virtchnl.h>
10 #include <dev_iavf/virtchnl_funcs.h>
11 #include <vnet/ethernet/ethernet.h>
12
13 VLIB_REGISTER_LOG_CLASS (iavf_log, static) = {
14   .class_name = "iavf",
15   .subclass_name = "virtchnl",
16 };
17
18 u8 *
19 format_virtchnl_op_name (u8 *s, va_list *args)
20 {
21   virtchnl_op_t op = va_arg (*args, virtchnl_op_t);
22   char *op_names[] = {
23 #define _(a, b) [a] = #b,
24     foreach_virtchnl_op
25 #undef _
26   };
27
28   if (op >= ARRAY_LEN (op_names) || op_names[op] == 0)
29     return format (s, "UNKNOWN(%u)", op);
30
31   return format (s, "%s", op_names[op]);
32 }
33
34 u8 *
35 format_virtchnl_status (u8 *s, va_list *args)
36 {
37   virtchnl_status_t c = va_arg (*args, virtchnl_status_t);
38
39   if (0)
40     ;
41 #define _(a, b) else if (c == a) return format (s, #b);
42   foreach_virtchnl_status
43 #undef _
44     return format (s, "UNKNOWN(%d)", c);
45 }
46
47 static u8 *
48 format_virtchnl_vlan_support_caps (u8 *s, va_list *args)
49 {
50   virtchnl_vlan_support_caps_t v = va_arg (*args, u32);
51   int not_first = 0;
52
53   char *strs[32] = {
54 #define _(a, b, c) [a] = c,
55     foreach_virtchnl_vlan_support_bit
56 #undef _
57   };
58
59   if (v == VIRTCHNL_VLAN_UNSUPPORTED)
60     return format (s, "unsupported");
61
62   for (int i = 0; i < 32; i++)
63     {
64       if ((v & (1 << i)) == 0)
65         continue;
66       if (not_first)
67         s = format (s, " ");
68       if (strs[i])
69         s = format (s, "%s", strs[i]);
70       else
71         s = format (s, "unknown(%u)", i);
72       not_first = 1;
73     }
74   return s;
75 }
76
77 static u8 *
78 format_virtchnl_op_req (u8 *s, va_list *args)
79 {
80   virtchnl_op_t op = va_arg (*args, virtchnl_op_t);
81   void *p = va_arg (*args, void *);
82   u32 indent = format_get_indent (s);
83
84   if (p == 0)
85     return format (s, "no data");
86
87   switch (op)
88     {
89     case VIRTCHNL_OP_VERSION:
90       {
91         virtchnl_version_info_t *r = p;
92         s = format (s, "version: %u.%u", r->major, r->minor);
93       }
94       break;
95     case VIRTCHNL_OP_GET_VF_RESOURCES:
96       {
97         u32 *r = p;
98         s = format (s, "%U", format_iavf_vf_cap_flags, *r);
99       }
100       break;
101     case VIRTCHNL_OP_ENABLE_QUEUES:
102     case VIRTCHNL_OP_DISABLE_QUEUES:
103     case VIRTCHNL_OP_GET_STATS:
104       {
105         virtchnl_queue_select_t *r = p;
106         s = format (s, "vsi %u rx 0x%x tx 0x%x", r->vsi_id, r->rx_queues,
107                     r->tx_queues);
108       }
109       break;
110     case VIRTCHNL_OP_CONFIG_VSI_QUEUES:
111       {
112         virtchnl_vsi_queue_config_info_t *r = p;
113         s = format (s, "vsi %u num_qp %u", r->vsi_id, r->num_queue_pairs);
114         for (int i = 0; i < r->num_queue_pairs; i++)
115           {
116             virtchnl_rxq_info_t *ri = &r->qpair[i].rxq;
117             virtchnl_txq_info_t *ti = &r->qpair[i].txq;
118
119             s = format (s, "\n%U qpair %u", format_white_space, indent + 2, i);
120             s = format (s,
121                         "\n%U rx vsi %u queue %u dma_ring_addr 0x%lx "
122                         "ring_len %u data_sz %u max_pkt_sz %u",
123                         format_white_space, indent + 4, ri->vsi_id,
124                         ri->queue_id, ri->dma_ring_addr, ri->ring_len,
125                         ri->databuffer_size, ri->max_pkt_size);
126             s = format (
127               s, "\n%U tx vsi %u queue %u dma_ring_addr 0x%lx ring_len %u",
128               format_white_space, indent + 4, ti->vsi_id, ti->queue_id,
129               ti->dma_ring_addr, ti->ring_len);
130           }
131       }
132       break;
133     case VIRTCHNL_OP_CONFIG_IRQ_MAP:
134       {
135         virtchnl_irq_map_info_t *r = p;
136         s = format (s, "num_vectors %u", r->num_vectors);
137         for (int i = 0; i < r->num_vectors; i++)
138           {
139             virtchnl_vector_map_t *vecmap = r->vecmap + i;
140             s = format (s,
141                         "\n%Uvsi %u vector_id %u rxq_map 0x%04x txq_map "
142                         "0x%04x rxitr_idx %u txitr_idx %u",
143                         format_white_space, indent + 2, vecmap->vsi_id,
144                         vecmap->vector_id, vecmap->rxq_map, vecmap->txq_map,
145                         vecmap->rxitr_idx, vecmap->txitr_idx);
146           }
147       }
148       break;
149     case VIRTCHNL_OP_CONFIG_RSS_LUT:
150       {
151         virtchnl_rss_lut_t *r = p;
152         s = format (s, "vsi %u entries %u lut", r->vsi_id, r->lut_entries);
153         for (int i = 0; i < r->lut_entries; i++)
154           s = format (s, " %u", r->lut[i]);
155       }
156       break;
157     case VIRTCHNL_OP_CONFIG_RSS_KEY:
158       {
159         virtchnl_rss_key_t *r = p;
160         s = format (s, "vsi %u len %u key ", r->vsi_id, r->key_len);
161         for (int i = 0; i < r->key_len; i++)
162           s = format (s, "%02x", r->key[i]);
163       }
164       break;
165     case VIRTCHNL_OP_ADD_ETH_ADDR:
166     case VIRTCHNL_OP_DEL_ETH_ADDR:
167       {
168         virtchnl_ether_addr_list_t *r = p;
169         s = format (s, "vsi %u num_elements %u elts: ", r->vsi_id,
170                     r->num_elements);
171         for (int i = 0; i < r->num_elements; i++)
172           s = format (s, "%s%U%s%s", i ? ", " : "", format_ethernet_address,
173                       r->list[i].addr, r->list[i].primary ? " primary" : "",
174                       r->list[i].extra ? " extra" : "");
175       }
176       break;
177     case VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE:
178       {
179         virtchnl_promisc_info_t *r = p;
180         s = format (
181           s, "promisc_info: vsi %u flags 0x%x (unicast %s multicast %s)",
182           r->vsi_id, r->flags,
183           r->flags & FLAG_VF_UNICAST_PROMISC ? "on" : "off",
184           r->flags & FLAG_VF_MULTICAST_PROMISC ? "on" : "off");
185       }
186       break;
187     case VIRTCHNL_OP_DISABLE_VLAN_STRIPPING_V2:
188       {
189         virtchnl_vlan_setting_t *r = p;
190         s = format (s,
191                     "vport %u outer_ethertype_setting 0x%x [%U] "
192                     "inner_ethertype_setting 0x%x [%U]",
193                     r->vport_id, r->outer_ethertype_setting,
194                     format_virtchnl_vlan_support_caps,
195                     r->outer_ethertype_setting, r->inner_ethertype_setting,
196                     format_virtchnl_vlan_support_caps,
197                     r->inner_ethertype_setting);
198       }
199       break;
200     default:
201       s = format (s, "unknown op 0x%04x", op);
202       break;
203     };
204   return s;
205 }
206 static u8 *
207 format_virtchnl_op_resp (u8 *s, va_list *args)
208 {
209   virtchnl_op_t op = va_arg (*args, virtchnl_op_t);
210   void *p = va_arg (*args, void *);
211   u32 indent = format_get_indent (s);
212
213   if (p == 0)
214     return format (s, "no data");
215
216   switch (op)
217     {
218     case VIRTCHNL_OP_VERSION:
219       {
220         virtchnl_version_info_t *r = p;
221         s = format (s, "version %u.%u", r->major, r->minor);
222       }
223       break;
224     case VIRTCHNL_OP_GET_VF_RESOURCES:
225       {
226         virtchnl_vf_resource_t *r = p;
227         s =
228           format (s,
229                   "vf_resource: num_vsis %u num_queue_pairs %u "
230                   "max_vectors %u max_mtu %u rss_key_size %u rss_lut_size %u",
231                   r->num_vsis, r->num_queue_pairs, r->max_vectors, r->max_mtu,
232                   r->rss_key_size, r->rss_lut_size);
233         s = format (s, "\n%Uvf_cap_flags 0x%x (%U)", format_white_space,
234                     indent + 2, r->vf_cap_flags, format_iavf_vf_cap_flags,
235                     r->vf_cap_flags);
236         for (int i = 0; i < r->num_vsis; i++)
237           s = format (s,
238                       "\n%Uvsi_resource[%u]: vsi %u num_qp %u vsi_type %u "
239                       "qset_handle %u default_mac_addr %U",
240                       format_white_space, indent + 2, i, r->vsi_res[i].vsi_id,
241                       r->vsi_res[i].num_queue_pairs, r->vsi_res[i].vsi_type,
242                       r->vsi_res[i].qset_handle, format_ethernet_address,
243                       r->vsi_res[i].default_mac_addr);
244       }
245       break;
246     case VIRTCHNL_OP_GET_OFFLOAD_VLAN_V2_CAPS:
247       {
248         virtchnl_vlan_caps_t *r = p;
249         s = format (s, "filtering: ethertype_init 0x%x max_filters %u",
250                     r->filtering.ethertype_init, r->filtering.max_filters);
251         s = format (s, "\n%U outer [%U] inner [%U]", format_white_space,
252                     indent, format_virtchnl_vlan_support_caps,
253                     r->filtering.filtering_support.outer,
254                     format_virtchnl_vlan_support_caps,
255                     r->filtering.filtering_support.inner);
256         s = format (s, "\n%Uoffloads: ethertype_init 0x%x ethertype_match %u",
257                     format_white_space, indent, r->offloads.ethertype_init,
258                     r->offloads.ethertype_match);
259         s = format (s, "\n%U stripping outer [%U] stripping inner [%U]",
260                     format_white_space, indent,
261                     format_virtchnl_vlan_support_caps,
262                     r->offloads.stripping_support.outer,
263                     format_virtchnl_vlan_support_caps,
264                     r->offloads.stripping_support.inner);
265         s = format (s, "\n%U insertion outer [%U] inserion inner [%U]",
266                     format_white_space, indent,
267                     format_virtchnl_vlan_support_caps,
268                     r->offloads.insertion_support.outer,
269                     format_virtchnl_vlan_support_caps,
270                     r->offloads.insertion_support.inner);
271       }
272       break;
273     case VIRTCHNL_OP_GET_STATS:
274       {
275         virtchnl_eth_stats_t *r = p;
276         s = format (s,
277                     "rx: bytes %lu, unicast %lu, multicast %lu, broadcast "
278                     "%lu, discards %lu unknown_protocol %lu",
279                     r->rx_bytes, r->rx_unicast, r->rx_multicast,
280                     r->rx_broadcast, r->rx_discards, r->rx_unknown_protocol);
281         s = format (s, "\n%U", format_white_space, indent);
282         s = format (s,
283                     "tx: bytes %lu, unicast %lu, multicast %lu, broadcast "
284                     "%lu, discards %lu errors %lu",
285                     r->tx_bytes, r->tx_unicast, r->tx_multicast,
286                     r->tx_broadcast, r->tx_discards, r->tx_errors);
287       }
288       break;
289     default:
290       s = format (s, "unknown op 0x%04x", op);
291       break;
292     };
293   return s;
294 }
295
296 vnet_dev_rv_t
297 iavf_virtchnl_req (vlib_main_t *vm, vnet_dev_t *dev, iavf_virtchnl_req_t *r)
298 {
299   iavf_device_t *ad = vnet_dev_get_data (dev);
300   vnet_dev_rv_t rv;
301   iavf_aq_desc_t *d;
302   u8 *b;
303
304   log_debug (dev, "%U req:\n  %U", format_virtchnl_op_name, r->op,
305              format_virtchnl_op_req, r->op, r->req);
306
307   iavf_aq_desc_t txd = {
308     .opcode = IIAVF_AQ_DESC_OP_SEND_TO_PF,
309     .v_opcode = r->op,
310     .flags = { .si = 1 },
311   };
312
313   rv = iavf_aq_atq_enq (vm, dev, &txd, r->req, r->req_sz, 0.5);
314
315   if (rv != VNET_DEV_OK)
316     return rv;
317
318   if (r->no_reply)
319     return VNET_DEV_OK;
320
321 retry:
322   if (!iavf_aq_arq_next_acq (vm, dev, &d, &b, 1.0))
323     {
324       log_err (ad, "timeout waiting for virtchnl response");
325       return VNET_DEV_ERR_TIMEOUT;
326     }
327
328   if (d->v_opcode == VIRTCHNL_OP_EVENT)
329     {
330       if ((d->datalen != sizeof (virtchnl_pf_event_t)) ||
331           ((d->flags.buf) == 0))
332         {
333           log_err (dev, "event message error");
334           return VNET_DEV_ERR_BUG;
335         }
336
337       vec_add1 (ad->events, *(virtchnl_pf_event_t *) b);
338       iavf_aq_arq_next_rel (vm, dev);
339       goto retry;
340     }
341
342   if (d->v_opcode != r->op)
343     {
344       log_err (dev,
345                "unexpected response received [v_opcode = %u, expected %u, "
346                "v_retval %d]",
347                d->v_opcode, r->op, d->v_retval);
348       rv = VNET_DEV_ERR_BUG;
349       goto done;
350     }
351
352   r->status = d->v_retval;
353
354   if (d->v_retval)
355     {
356       log_err (dev, "error [v_opcode = %u, v_retval %d]", d->v_opcode,
357                d->v_retval);
358       rv = VNET_DEV_ERR_BUG;
359       goto done;
360     }
361
362   if (r->resp_sz && d->flags.buf)
363     clib_memcpy_fast (r->resp, b, r->resp_sz);
364
365 done:
366   iavf_aq_arq_next_rel (vm, dev);
367   if (rv == VNET_DEV_OK)
368     log_debug (dev, "%U resp:\n  %U", format_virtchnl_op_name, r->op,
369                format_virtchnl_op_resp, r->op, r->resp);
370   return rv;
371 }