1 /*-
2 * SPDX-License-Identifier: BSD-3-Clause
3 *
4 * Copyright (c) 2023-2024 Google LLC
5 *
6 * Redistribution and use in source and binary forms, with or without modification,
7 * are permitted provided that the following conditions are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright notice, this
10 * list of conditions and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright notice,
13 * this list of conditions and the following disclaimer in the documentation
14 * and/or other materials provided with the distribution.
15 *
16 * 3. Neither the name of the copyright holder nor the names of its contributors
17 * may be used to endorse or promote products derived from this software without
18 * specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
24 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
27 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31 #include "gve.h"
32
33 static SYSCTL_NODE(_hw, OID_AUTO, gve, CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
34 "GVE driver parameters");
35
36 bool gve_disable_hw_lro = false;
37 SYSCTL_BOOL(_hw_gve, OID_AUTO, disable_hw_lro, CTLFLAG_RDTUN,
38 &gve_disable_hw_lro, 0, "Controls if hardware LRO is used");
39
40 char gve_queue_format[8];
41 SYSCTL_STRING(_hw_gve, OID_AUTO, queue_format, CTLFLAG_RD,
42 &gve_queue_format, 0, "Queue format being used by the iface");
43
44 char gve_version[8];
45 SYSCTL_STRING(_hw_gve, OID_AUTO, driver_version, CTLFLAG_RD,
46 &gve_version, 0, "Driver version");
47
48 static void
gve_setup_rxq_sysctl(struct sysctl_ctx_list * ctx,struct sysctl_oid_list * child,struct gve_rx_ring * rxq)49 gve_setup_rxq_sysctl(struct sysctl_ctx_list *ctx,
50 struct sysctl_oid_list *child, struct gve_rx_ring *rxq)
51 {
52 struct sysctl_oid *node;
53 struct sysctl_oid_list *list;
54 struct gve_rxq_stats *stats;
55 char namebuf[16];
56
57 snprintf(namebuf, sizeof(namebuf), "rxq%d", rxq->com.id);
58 node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, namebuf,
59 CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "Receive Queue");
60 list = SYSCTL_CHILDREN(node);
61
62 stats = &rxq->stats;
63
64 SYSCTL_ADD_COUNTER_U64(ctx, list, OID_AUTO,
65 "rx_bytes", CTLFLAG_RD,
66 &stats->rbytes, "Bytes received");
67 SYSCTL_ADD_COUNTER_U64(ctx, list, OID_AUTO,
68 "rx_packets", CTLFLAG_RD,
69 &stats->rpackets, "Packets received");
70 SYSCTL_ADD_COUNTER_U64(ctx, list, OID_AUTO, "rx_copybreak_cnt",
71 CTLFLAG_RD, &stats->rx_copybreak_cnt,
72 "Total frags with mbufs allocated for copybreak");
73 SYSCTL_ADD_COUNTER_U64(ctx, list, OID_AUTO, "rx_frag_flip_cnt",
74 CTLFLAG_RD, &stats->rx_frag_flip_cnt,
75 "Total frags that allocated mbuf with page flip");
76 SYSCTL_ADD_COUNTER_U64(ctx, list, OID_AUTO, "rx_frag_copy_cnt",
77 CTLFLAG_RD, &stats->rx_frag_copy_cnt,
78 "Total frags with mbuf that copied payload into mbuf");
79 SYSCTL_ADD_COUNTER_U64(ctx, list, OID_AUTO, "rx_dropped_pkt",
80 CTLFLAG_RD, &stats->rx_dropped_pkt,
81 "Total rx packets dropped");
82 SYSCTL_ADD_COUNTER_U64(ctx, list, OID_AUTO,
83 "rx_dropped_pkt_desc_err", CTLFLAG_RD,
84 &stats->rx_dropped_pkt_desc_err,
85 "Packets dropped due to descriptor error");
86 SYSCTL_ADD_COUNTER_U64(ctx, list, OID_AUTO,
87 "rx_dropped_pkt_buf_post_fail", CTLFLAG_RD,
88 &stats->rx_dropped_pkt_buf_post_fail,
89 "Packets dropped due to failure to post enough buffers");
90 SYSCTL_ADD_COUNTER_U64(ctx, list, OID_AUTO,
91 "rx_dropped_pkt_mbuf_alloc_fail", CTLFLAG_RD,
92 &stats->rx_dropped_pkt_mbuf_alloc_fail,
93 "Packets dropped due to failed mbuf allocation");
94 SYSCTL_ADD_COUNTER_U64(ctx, list, OID_AUTO,
95 "rx_mbuf_dmamap_err", CTLFLAG_RD,
96 &stats->rx_mbuf_dmamap_err,
97 "Number of rx mbufs which couldnt be dma mapped");
98 SYSCTL_ADD_COUNTER_U64(ctx, list, OID_AUTO,
99 "rx_mbuf_mclget_null", CTLFLAG_RD,
100 &stats->rx_mbuf_mclget_null,
101 "Number of times when there were no cluster mbufs");
102 SYSCTL_ADD_U32(ctx, list, OID_AUTO,
103 "rx_completed_desc", CTLFLAG_RD,
104 &rxq->cnt, 0, "Number of descriptors completed");
105 SYSCTL_ADD_U32(ctx, list, OID_AUTO,
106 "num_desc_posted", CTLFLAG_RD,
107 &rxq->fill_cnt, rxq->fill_cnt,
108 "Toal number of descriptors posted");
109 }
110
111 static void
gve_setup_txq_sysctl(struct sysctl_ctx_list * ctx,struct sysctl_oid_list * child,struct gve_tx_ring * txq)112 gve_setup_txq_sysctl(struct sysctl_ctx_list *ctx,
113 struct sysctl_oid_list *child, struct gve_tx_ring *txq)
114 {
115 struct sysctl_oid *node;
116 struct sysctl_oid_list *tx_list;
117 struct gve_txq_stats *stats;
118 char namebuf[16];
119
120 snprintf(namebuf, sizeof(namebuf), "txq%d", txq->com.id);
121 node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, namebuf,
122 CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "Transmit Queue");
123 tx_list = SYSCTL_CHILDREN(node);
124
125 stats = &txq->stats;
126
127 SYSCTL_ADD_U32(ctx, tx_list, OID_AUTO,
128 "tx_posted_desc", CTLFLAG_RD,
129 &txq->req, 0, "Number of descriptors posted by NIC");
130 SYSCTL_ADD_U32(ctx, tx_list, OID_AUTO,
131 "tx_completed_desc", CTLFLAG_RD,
132 &txq->done, 0, "Number of descriptors completed");
133 SYSCTL_ADD_COUNTER_U64(ctx, tx_list, OID_AUTO,
134 "tx_packets", CTLFLAG_RD,
135 &stats->tpackets, "Packets transmitted");
136 SYSCTL_ADD_COUNTER_U64(ctx, tx_list, OID_AUTO,
137 "tx_tso_packets", CTLFLAG_RD,
138 &stats->tso_packet_cnt, "TSO Packets transmitted");
139 SYSCTL_ADD_COUNTER_U64(ctx, tx_list, OID_AUTO,
140 "tx_bytes", CTLFLAG_RD,
141 &stats->tbytes, "Bytes transmitted");
142 SYSCTL_ADD_COUNTER_U64(ctx, tx_list, OID_AUTO,
143 "tx_delayed_pkt_nospace_device", CTLFLAG_RD,
144 &stats->tx_delayed_pkt_nospace_device,
145 "Packets delayed due to no space in device");
146 SYSCTL_ADD_COUNTER_U64(ctx, tx_list, OID_AUTO,
147 "tx_dropped_pkt_nospace_bufring", CTLFLAG_RD,
148 &stats->tx_dropped_pkt_nospace_bufring,
149 "Packets dropped due to no space in br ring");
150 SYSCTL_ADD_COUNTER_U64(ctx, tx_list, OID_AUTO,
151 "tx_dropped_pkt_vlan", CTLFLAG_RD,
152 &stats->tx_dropped_pkt_vlan,
153 "Dropped VLAN packets");
154 SYSCTL_ADD_COUNTER_U64(ctx, tx_list, OID_AUTO,
155 "tx_delayed_pkt_nospace_descring", CTLFLAG_RD,
156 &stats->tx_delayed_pkt_nospace_descring,
157 "Packets delayed due to no space in desc ring");
158 SYSCTL_ADD_COUNTER_U64(ctx, tx_list, OID_AUTO,
159 "tx_delayed_pkt_nospace_compring", CTLFLAG_RD,
160 &stats->tx_delayed_pkt_nospace_compring,
161 "Packets delayed due to no space in comp ring");
162 SYSCTL_ADD_COUNTER_U64(ctx, tx_list, OID_AUTO,
163 "tx_delayed_pkt_nospace_qpl_bufs", CTLFLAG_RD,
164 &stats->tx_delayed_pkt_nospace_qpl_bufs,
165 "Packets delayed due to not enough qpl bufs");
166 SYSCTL_ADD_COUNTER_U64(ctx, tx_list, OID_AUTO,
167 "tx_delayed_pkt_tsoerr", CTLFLAG_RD,
168 &stats->tx_delayed_pkt_tsoerr,
169 "TSO packets delayed due to err in prep errors");
170 SYSCTL_ADD_COUNTER_U64(ctx, tx_list, OID_AUTO,
171 "tx_mbuf_collpase", CTLFLAG_RD,
172 &stats->tx_mbuf_collapse,
173 "tx mbufs that had to be collpased");
174 SYSCTL_ADD_COUNTER_U64(ctx, tx_list, OID_AUTO,
175 "tx_mbuf_defrag", CTLFLAG_RD,
176 &stats->tx_mbuf_defrag,
177 "tx mbufs that had to be defragged");
178 SYSCTL_ADD_COUNTER_U64(ctx, tx_list, OID_AUTO,
179 "tx_mbuf_defrag_err", CTLFLAG_RD,
180 &stats->tx_mbuf_defrag_err,
181 "tx mbufs that failed defrag");
182 SYSCTL_ADD_COUNTER_U64(ctx, tx_list, OID_AUTO,
183 "tx_mbuf_dmamap_enomem_err", CTLFLAG_RD,
184 &stats->tx_mbuf_dmamap_enomem_err,
185 "tx mbufs that could not be dma-mapped due to low mem");
186 SYSCTL_ADD_COUNTER_U64(ctx, tx_list, OID_AUTO,
187 "tx_mbuf_dmamap_err", CTLFLAG_RD,
188 &stats->tx_mbuf_dmamap_err,
189 "tx mbufs that could not be dma-mapped");
190 }
191
192 static void
gve_setup_queue_stat_sysctl(struct sysctl_ctx_list * ctx,struct sysctl_oid_list * child,struct gve_priv * priv)193 gve_setup_queue_stat_sysctl(struct sysctl_ctx_list *ctx, struct sysctl_oid_list *child,
194 struct gve_priv *priv)
195 {
196 int i;
197
198 for (i = 0; i < priv->rx_cfg.num_queues; i++) {
199 gve_setup_rxq_sysctl(ctx, child, &priv->rx[i]);
200 }
201 for (i = 0; i < priv->tx_cfg.num_queues; i++) {
202 gve_setup_txq_sysctl(ctx, child, &priv->tx[i]);
203 }
204 }
205
206 static void
gve_setup_adminq_stat_sysctl(struct sysctl_ctx_list * ctx,struct sysctl_oid_list * child,struct gve_priv * priv)207 gve_setup_adminq_stat_sysctl(struct sysctl_ctx_list *ctx,
208 struct sysctl_oid_list *child, struct gve_priv *priv)
209 {
210 struct sysctl_oid *admin_node;
211 struct sysctl_oid_list *admin_list;
212
213 /* Admin queue stats */
214 admin_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "adminq_stats",
215 CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "Admin Queue statistics");
216 admin_list = SYSCTL_CHILDREN(admin_node);
217
218 SYSCTL_ADD_U32(ctx, admin_list, OID_AUTO, "adminq_prod_cnt", CTLFLAG_RD,
219 &priv->adminq_prod_cnt, 0, "Adminq Commands issued");
220 SYSCTL_ADD_U32(ctx, admin_list, OID_AUTO, "adminq_cmd_fail", CTLFLAG_RD,
221 &priv->adminq_cmd_fail, 0, "Aqminq Failed commands");
222 SYSCTL_ADD_U32(ctx, admin_list, OID_AUTO, "adminq_timeouts", CTLFLAG_RD,
223 &priv->adminq_timeouts, 0, "Adminq Timedout commands");
224 SYSCTL_ADD_U32(ctx, admin_list, OID_AUTO, "adminq_describe_device_cnt",
225 CTLFLAG_RD, &priv->adminq_describe_device_cnt, 0,
226 "adminq_describe_device_cnt");
227 SYSCTL_ADD_U32(ctx, admin_list, OID_AUTO,
228 "adminq_cfg_device_resources_cnt", CTLFLAG_RD,
229 &priv->adminq_cfg_device_resources_cnt, 0,
230 "adminq_cfg_device_resources_cnt");
231 SYSCTL_ADD_U32(ctx, admin_list, OID_AUTO,
232 "adminq_register_page_list_cnt", CTLFLAG_RD,
233 &priv->adminq_register_page_list_cnt, 0,
234 "adminq_register_page_list_cnt");
235 SYSCTL_ADD_U32(ctx, admin_list, OID_AUTO,
236 "adminq_unregister_page_list_cnt", CTLFLAG_RD,
237 &priv->adminq_unregister_page_list_cnt, 0,
238 "adminq_unregister_page_list_cnt");
239 SYSCTL_ADD_U32(ctx, admin_list, OID_AUTO, "adminq_create_tx_queue_cnt",
240 CTLFLAG_RD, &priv->adminq_create_tx_queue_cnt, 0,
241 "adminq_create_tx_queue_cnt");
242 SYSCTL_ADD_U32(ctx, admin_list, OID_AUTO, "adminq_create_rx_queue_cnt",
243 CTLFLAG_RD, &priv->adminq_create_rx_queue_cnt, 0,
244 "adminq_create_rx_queue_cnt");
245 SYSCTL_ADD_U32(ctx, admin_list, OID_AUTO, "adminq_destroy_tx_queue_cnt",
246 CTLFLAG_RD, &priv->adminq_destroy_tx_queue_cnt, 0,
247 "adminq_destroy_tx_queue_cnt");
248 SYSCTL_ADD_U32(ctx, admin_list, OID_AUTO, "adminq_destroy_rx_queue_cnt",
249 CTLFLAG_RD, &priv->adminq_destroy_rx_queue_cnt, 0,
250 "adminq_destroy_rx_queue_cnt");
251 SYSCTL_ADD_U32(ctx, admin_list, OID_AUTO, "adminq_get_ptype_map_cnt",
252 CTLFLAG_RD, &priv->adminq_get_ptype_map_cnt, 0,
253 "adminq_get_ptype_map_cnt");
254 SYSCTL_ADD_U32(ctx, admin_list, OID_AUTO,
255 "adminq_dcfg_device_resources_cnt", CTLFLAG_RD,
256 &priv->adminq_dcfg_device_resources_cnt, 0,
257 "adminq_dcfg_device_resources_cnt");
258 SYSCTL_ADD_U32(ctx, admin_list, OID_AUTO,
259 "adminq_set_driver_parameter_cnt", CTLFLAG_RD,
260 &priv->adminq_set_driver_parameter_cnt, 0,
261 "adminq_set_driver_parameter_cnt");
262 SYSCTL_ADD_U32(ctx, admin_list, OID_AUTO,
263 "adminq_verify_driver_compatibility_cnt", CTLFLAG_RD,
264 &priv->adminq_verify_driver_compatibility_cnt, 0,
265 "adminq_verify_driver_compatibility_cnt");
266 }
267
268 static void
gve_setup_main_stat_sysctl(struct sysctl_ctx_list * ctx,struct sysctl_oid_list * child,struct gve_priv * priv)269 gve_setup_main_stat_sysctl(struct sysctl_ctx_list *ctx,
270 struct sysctl_oid_list *child, struct gve_priv *priv)
271 {
272 struct sysctl_oid *main_node;
273 struct sysctl_oid_list *main_list;
274
275 /* Main stats */
276 main_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "main_stats",
277 CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "Main statistics");
278 main_list = SYSCTL_CHILDREN(main_node);
279
280 SYSCTL_ADD_U32(ctx, main_list, OID_AUTO, "interface_up_cnt", CTLFLAG_RD,
281 &priv->interface_up_cnt, 0, "Times interface was set to up");
282 SYSCTL_ADD_U32(ctx, main_list, OID_AUTO, "interface_down_cnt", CTLFLAG_RD,
283 &priv->interface_down_cnt, 0, "Times interface was set to down");
284 SYSCTL_ADD_U32(ctx, main_list, OID_AUTO, "reset_cnt", CTLFLAG_RD,
285 &priv->reset_cnt, 0, "Times reset");
286 }
287
gve_setup_sysctl(struct gve_priv * priv)288 void gve_setup_sysctl(struct gve_priv *priv)
289 {
290 device_t dev;
291 struct sysctl_ctx_list *ctx;
292 struct sysctl_oid *tree;
293 struct sysctl_oid_list *child;
294
295 dev = priv->dev;
296 ctx = device_get_sysctl_ctx(dev);
297 tree = device_get_sysctl_tree(dev);
298 child = SYSCTL_CHILDREN(tree);
299
300 gve_setup_queue_stat_sysctl(ctx, child, priv);
301 gve_setup_adminq_stat_sysctl(ctx, child, priv);
302 gve_setup_main_stat_sysctl(ctx, child, priv);
303 }
304
305 void
gve_accum_stats(struct gve_priv * priv,uint64_t * rpackets,uint64_t * rbytes,uint64_t * rx_dropped_pkt,uint64_t * tpackets,uint64_t * tbytes,uint64_t * tx_dropped_pkt)306 gve_accum_stats(struct gve_priv *priv, uint64_t *rpackets,
307 uint64_t *rbytes, uint64_t *rx_dropped_pkt, uint64_t *tpackets,
308 uint64_t *tbytes, uint64_t *tx_dropped_pkt)
309 {
310 struct gve_rxq_stats *rxqstats;
311 struct gve_txq_stats *txqstats;
312 int i;
313
314 for (i = 0; i < priv->rx_cfg.num_queues; i++) {
315 rxqstats = &priv->rx[i].stats;
316 *rpackets += counter_u64_fetch(rxqstats->rpackets);
317 *rbytes += counter_u64_fetch(rxqstats->rbytes);
318 *rx_dropped_pkt += counter_u64_fetch(rxqstats->rx_dropped_pkt);
319 }
320
321 for (i = 0; i < priv->tx_cfg.num_queues; i++) {
322 txqstats = &priv->tx[i].stats;
323 *tpackets += counter_u64_fetch(txqstats->tpackets);
324 *tbytes += counter_u64_fetch(txqstats->tbytes);
325 *tx_dropped_pkt += counter_u64_fetch(txqstats->tx_dropped_pkt);
326 }
327 }
328