xref: /dpdk/drivers/net/cnxk/cnxk_ethdev_sec_telemetry.c (revision d74ed1628f7e3772593be6c48f364816ae85e448)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(C) 2022 Marvell.
3  */
4 
5 #include <ctype.h>
6 
7 #include <rte_telemetry.h>
8 
9 #include <roc_api.h>
10 
11 #include "cnxk_ethdev.h"
12 
13 #define STR_MAXLEN 20
14 #define W0_MAXLEN  21
15 
16 static int
17 copy_outb_sa_9k(struct rte_tel_data *d, uint32_t i, void *sa)
18 {
19 	union {
20 		struct roc_ie_on_sa_ctl ctl;
21 		uint64_t u64;
22 	} w0;
23 	struct roc_ie_on_outb_sa *out_sa;
24 	char strw0[W0_MAXLEN];
25 	char str[STR_MAXLEN];
26 
27 	out_sa = (struct roc_ie_on_outb_sa *)sa;
28 	w0.ctl = out_sa->common_sa.ctl;
29 
30 	snprintf(str, sizeof(str), "outsa_w0_%u", i);
31 	snprintf(strw0, sizeof(strw0), "%" PRIu64, w0.u64);
32 	rte_tel_data_add_dict_string(d, str, strw0);
33 
34 	return 0;
35 }
36 
37 static int
38 copy_inb_sa_9k(struct rte_tel_data *d, uint32_t i, void *sa)
39 {
40 	union {
41 		struct roc_ie_on_sa_ctl ctl;
42 		uint64_t u64;
43 	} w0;
44 	struct roc_ie_on_inb_sa *in_sa;
45 	char strw0[W0_MAXLEN];
46 	char str[STR_MAXLEN];
47 
48 	in_sa = (struct roc_ie_on_inb_sa *)sa;
49 	w0.ctl = in_sa->common_sa.ctl;
50 
51 	snprintf(str, sizeof(str), "insa_w0_%u", i);
52 	snprintf(strw0, sizeof(strw0), "%" PRIu64, w0.u64);
53 	rte_tel_data_add_dict_string(d, str, strw0);
54 
55 	snprintf(str, sizeof(str), "insa_esnh_%u", i);
56 	rte_tel_data_add_dict_uint(d, str, in_sa->common_sa.seq_t.th);
57 
58 	snprintf(str, sizeof(str), "insa_esnl_%u", i);
59 	rte_tel_data_add_dict_uint(d, str, in_sa->common_sa.seq_t.tl);
60 
61 	return 0;
62 }
63 
64 static int
65 copy_outb_sa_10k(struct rte_tel_data *d, uint32_t i, void *sa)
66 {
67 	struct roc_ot_ipsec_outb_sa *out_sa;
68 	struct rte_tel_data *outer_hdr;
69 	char str[STR_MAXLEN];
70 	char s64[W0_MAXLEN];
71 	uint32_t j;
72 
73 	out_sa = (struct roc_ot_ipsec_outb_sa *)sa;
74 
75 	snprintf(str, sizeof(str), "outsa_w0_%u", i);
76 	snprintf(s64, sizeof(s64), "%" PRIu64, out_sa->w0.u64);
77 	rte_tel_data_add_dict_string(d, str, s64);
78 
79 	snprintf(str, sizeof(str), "outsa_w1_%u", i);
80 	snprintf(s64, sizeof(s64), "%" PRIu64, out_sa->w1.u64);
81 	rte_tel_data_add_dict_string(d, str, s64);
82 
83 	snprintf(str, sizeof(str), "outsa_w2_%u", i);
84 	snprintf(s64, sizeof(s64), "%" PRIu64, out_sa->w2.u64);
85 	rte_tel_data_add_dict_string(d, str, s64);
86 
87 	snprintf(str, sizeof(str), "outsa_w10_%u", i);
88 	snprintf(s64, sizeof(s64), "%" PRIu64, out_sa->w10.u64);
89 	rte_tel_data_add_dict_string(d, str, s64);
90 
91 	outer_hdr = rte_tel_data_alloc();
92 	if (!outer_hdr) {
93 		plt_err("Could not allocate space for outer header");
94 		return -ENOMEM;
95 	}
96 
97 	rte_tel_data_start_array(outer_hdr, RTE_TEL_UINT_VAL);
98 
99 	for (j = 0; j < RTE_DIM(out_sa->outer_hdr.ipv6.src_addr); j++)
100 		rte_tel_data_add_array_uint(outer_hdr,
101 					    out_sa->outer_hdr.ipv6.src_addr[j]);
102 
103 	for (j = 0; j < RTE_DIM(out_sa->outer_hdr.ipv6.dst_addr); j++)
104 		rte_tel_data_add_array_uint(outer_hdr,
105 					    out_sa->outer_hdr.ipv6.dst_addr[j]);
106 
107 	snprintf(str, sizeof(str), "outsa_outer_hdr_%u", i);
108 	rte_tel_data_add_dict_container(d, str, outer_hdr, 0);
109 
110 	snprintf(str, sizeof(str), "outsa_errctl_%u", i);
111 	snprintf(s64, sizeof(s64), "%" PRIu64, out_sa->ctx.err_ctl.u64);
112 	rte_tel_data_add_dict_string(d, str, s64);
113 
114 	snprintf(str, sizeof(str), "outsa_esnval_%u", i);
115 	snprintf(s64, sizeof(s64), "%" PRIu64, out_sa->ctx.esn_val);
116 	rte_tel_data_add_dict_string(d, str, s64);
117 
118 	snprintf(str, sizeof(str), "outsa_hl_%u", i);
119 	snprintf(s64, sizeof(s64), "%" PRIu64, out_sa->ctx.hard_life);
120 	rte_tel_data_add_dict_string(d, str, s64);
121 
122 	snprintf(str, sizeof(str), "outsa_sl_%u", i);
123 	snprintf(s64, sizeof(s64), "%" PRIu64, out_sa->ctx.soft_life);
124 	rte_tel_data_add_dict_string(d, str, s64);
125 
126 	snprintf(str, sizeof(str), "outsa_octs_%u", i);
127 	snprintf(s64, sizeof(s64), "%" PRIu64, out_sa->ctx.mib_octs);
128 	rte_tel_data_add_dict_string(d, str, s64);
129 
130 	snprintf(str, sizeof(str), "outsa_pkts_%u", i);
131 	snprintf(s64, sizeof(s64), "%" PRIu64, out_sa->ctx.mib_pkts);
132 	rte_tel_data_add_dict_string(d, str, s64);
133 
134 	return 0;
135 }
136 
137 static int
138 copy_inb_sa_10k(struct rte_tel_data *d, uint32_t i, void *sa)
139 {
140 	struct roc_ot_ipsec_inb_sa *in_sa;
141 	struct rte_tel_data *outer_hdr;
142 	char str[STR_MAXLEN];
143 	char s64[W0_MAXLEN];
144 	uint32_t j;
145 
146 	in_sa = (struct roc_ot_ipsec_inb_sa *)sa;
147 
148 	snprintf(str, sizeof(str), "insa_w0_%u", i);
149 	snprintf(s64, sizeof(s64), "%" PRIu64, in_sa->w0.u64);
150 	rte_tel_data_add_dict_string(d, str, s64);
151 
152 	snprintf(str, sizeof(str), "insa_w1_%u", i);
153 	snprintf(s64, sizeof(s64), "%" PRIu64, in_sa->w1.u64);
154 	rte_tel_data_add_dict_string(d, str, s64);
155 
156 	snprintf(str, sizeof(str), "insa_w2_%u", i);
157 	snprintf(s64, sizeof(s64), "%" PRIu64, in_sa->w2.u64);
158 	rte_tel_data_add_dict_string(d, str, s64);
159 
160 	snprintf(str, sizeof(str), "insa_w10_%u", i);
161 	snprintf(s64, sizeof(s64), "%" PRIu64, in_sa->w10.u64);
162 	rte_tel_data_add_dict_string(d, str, s64);
163 
164 	outer_hdr = rte_tel_data_alloc();
165 	if (!outer_hdr) {
166 		plt_err("Could not allocate space for outer header");
167 		return -ENOMEM;
168 	}
169 
170 	rte_tel_data_start_array(outer_hdr, RTE_TEL_UINT_VAL);
171 
172 	for (j = 0; j < RTE_DIM(in_sa->outer_hdr.ipv6.src_addr); j++)
173 		rte_tel_data_add_array_uint(outer_hdr,
174 					    in_sa->outer_hdr.ipv6.src_addr[j]);
175 
176 	for (j = 0; j < RTE_DIM(in_sa->outer_hdr.ipv6.dst_addr); j++)
177 		rte_tel_data_add_array_uint(outer_hdr,
178 					    in_sa->outer_hdr.ipv6.dst_addr[j]);
179 
180 	snprintf(str, sizeof(str), "insa_outer_hdr_%u", i);
181 	rte_tel_data_add_dict_container(d, str, outer_hdr, 0);
182 
183 	snprintf(str, sizeof(str), "insa_arbase_%u", i);
184 	snprintf(s64, sizeof(s64), "%" PRIu64, in_sa->ctx.ar_base);
185 	rte_tel_data_add_dict_string(d, str, s64);
186 
187 	snprintf(str, sizeof(str), "insa_ar_validm_%u", i);
188 	snprintf(s64, sizeof(s64), "%" PRIu64, in_sa->ctx.ar_valid_mask);
189 	rte_tel_data_add_dict_string(d, str, s64);
190 
191 	snprintf(str, sizeof(str), "insa_hl_%u", i);
192 	snprintf(s64, sizeof(s64), "%" PRIu64, in_sa->ctx.hard_life);
193 	rte_tel_data_add_dict_string(d, str, s64);
194 
195 	snprintf(str, sizeof(str), "insa_sl_%u", i);
196 	snprintf(s64, sizeof(s64), "%" PRIu64, in_sa->ctx.soft_life);
197 	rte_tel_data_add_dict_string(d, str, s64);
198 
199 	snprintf(str, sizeof(str), "insa_octs_%u", i);
200 	snprintf(s64, sizeof(s64), "%" PRIu64, in_sa->ctx.mib_octs);
201 	rte_tel_data_add_dict_string(d, str, s64);
202 
203 	snprintf(str, sizeof(str), "insa_pkts_%u", i);
204 	snprintf(s64, sizeof(s64), "%" PRIu64, in_sa->ctx.mib_pkts);
205 	rte_tel_data_add_dict_string(d, str, s64);
206 
207 	return 0;
208 }
209 
210 /* n_vals is the number of params to be parsed. */
211 static int
212 parse_params(const char *params, uint32_t *vals, size_t n_vals)
213 {
214 	char dlim[2] = ",";
215 	char *params_args;
216 	size_t count = 0;
217 	char *token;
218 
219 	if (vals == NULL || params == NULL || strlen(params) == 0)
220 		return -1;
221 
222 	/* strtok expects char * and param is const char *. Hence on using
223 	 * params as "const char *" compiler throws warning.
224 	 */
225 	params_args = strdup(params);
226 	if (params_args == NULL)
227 		return -1;
228 
229 	token = strtok(params_args, dlim);
230 	while (token && isdigit(*token) && count < n_vals) {
231 		vals[count++] = strtoul(token, NULL, 10);
232 		token = strtok(NULL, dlim);
233 	}
234 
235 	free(params_args);
236 
237 	if (count < n_vals)
238 		return -1;
239 
240 	return 0;
241 }
242 
243 static int
244 ethdev_sec_tel_handle_sa_info(const char *cmd __rte_unused, const char *params,
245 			      struct rte_tel_data *d)
246 {
247 	struct cnxk_eth_sec_sess *eth_sec, *tvar;
248 	struct rte_eth_dev *eth_dev;
249 	struct cnxk_eth_dev *dev;
250 	uint32_t port_id, sa_idx;
251 	uint32_t vals[2] = {0};
252 	uint32_t i;
253 	int ret;
254 
255 	if (params == NULL || strlen(params) == 0 || !isdigit(*params))
256 		return -EINVAL;
257 
258 	if (parse_params(params, vals, RTE_DIM(vals)) < 0)
259 		return -EINVAL;
260 
261 	port_id = vals[0];
262 	sa_idx = vals[1];
263 
264 	if (!rte_eth_dev_is_valid_port(port_id)) {
265 		plt_err("Invalid port id %u", port_id);
266 		return -EINVAL;
267 	}
268 
269 	eth_dev = &rte_eth_devices[port_id];
270 	if (!eth_dev) {
271 		plt_err("Ethdev not available");
272 		return -EINVAL;
273 	}
274 	dev = cnxk_eth_pmd_priv(eth_dev);
275 
276 	rte_tel_data_start_dict(d);
277 
278 	i = 0;
279 	if (dev->tx_offloads & RTE_ETH_TX_OFFLOAD_SECURITY) {
280 		tvar = NULL;
281 		RTE_TAILQ_FOREACH_SAFE(eth_sec, &dev->outb.list, entry, tvar) {
282 			if (eth_sec->sa_idx == sa_idx) {
283 				rte_tel_data_add_dict_int(d, "outb_sa", 1);
284 				if (roc_model_is_cn10k())
285 					ret = copy_outb_sa_10k(d, i, eth_sec->sa);
286 				else
287 					ret = copy_outb_sa_9k(d, i, eth_sec->sa);
288 				if (ret < 0)
289 					return ret;
290 				break;
291 			}
292 		}
293 	}
294 
295 	i = 0;
296 	if (dev->rx_offloads & RTE_ETH_RX_OFFLOAD_SECURITY) {
297 		tvar = NULL;
298 		RTE_TAILQ_FOREACH_SAFE(eth_sec, &dev->inb.list, entry, tvar) {
299 			if (eth_sec->sa_idx == sa_idx) {
300 				rte_tel_data_add_dict_int(d, "inb_sa", 1);
301 				if (roc_model_is_cn10k())
302 					ret = copy_inb_sa_10k(d, i, eth_sec->sa);
303 				else
304 					ret = copy_inb_sa_9k(d, i, eth_sec->sa);
305 				if (ret < 0)
306 					return ret;
307 				break;
308 			}
309 		}
310 	}
311 	return 0;
312 }
313 
314 static int
315 ethdev_sec_tel_handle_info(const char *cmd __rte_unused, const char *params,
316 			   struct rte_tel_data *d)
317 {
318 	uint32_t min_outb_sa = UINT32_MAX, max_outb_sa = 0;
319 	uint32_t min_inb_sa = UINT32_MAX, max_inb_sa = 0;
320 	struct cnxk_eth_sec_sess *eth_sec, *tvar;
321 	struct rte_eth_dev *eth_dev;
322 	struct cnxk_eth_dev *dev;
323 	uint16_t port_id;
324 	char *end_p;
325 
326 	if (params == NULL || strlen(params) == 0 || !isdigit(*params))
327 		return -EINVAL;
328 
329 	port_id = strtoul(params, &end_p, 0);
330 	if (errno != 0)
331 		return -EINVAL;
332 
333 	if (*end_p != '\0')
334 		plt_err("Extra parameters passed to telemetry, ignoring it");
335 
336 	if (!rte_eth_dev_is_valid_port(port_id)) {
337 		plt_err("Invalid port id %u", port_id);
338 		return -EINVAL;
339 	}
340 
341 	eth_dev = &rte_eth_devices[port_id];
342 	if (!eth_dev) {
343 		plt_err("Ethdev not available");
344 		return -EINVAL;
345 	}
346 
347 	dev = cnxk_eth_pmd_priv(eth_dev);
348 
349 	rte_tel_data_start_dict(d);
350 
351 	rte_tel_data_add_dict_int(d, "nb_outb_sa", dev->outb.nb_sess);
352 
353 	if (!dev->outb.nb_sess)
354 		min_outb_sa = 0;
355 
356 	if (dev->tx_offloads & RTE_ETH_TX_OFFLOAD_SECURITY) {
357 		tvar = NULL;
358 		RTE_TAILQ_FOREACH_SAFE(eth_sec, &dev->outb.list, entry, tvar) {
359 			if (eth_sec->sa_idx < min_outb_sa)
360 				min_outb_sa = eth_sec->sa_idx;
361 			if (eth_sec->sa_idx > max_outb_sa)
362 				max_outb_sa = eth_sec->sa_idx;
363 		}
364 		rte_tel_data_add_dict_int(d, "min_outb_sa", min_outb_sa);
365 		rte_tel_data_add_dict_int(d, "max_outb_sa", max_outb_sa);
366 	}
367 
368 	rte_tel_data_add_dict_int(d, "nb_inb_sa", dev->inb.nb_sess);
369 
370 	if (!dev->inb.nb_sess)
371 		min_inb_sa = 0;
372 
373 	if (dev->rx_offloads & RTE_ETH_RX_OFFLOAD_SECURITY) {
374 		tvar = NULL;
375 		RTE_TAILQ_FOREACH_SAFE(eth_sec, &dev->inb.list, entry, tvar) {
376 			if (eth_sec->sa_idx < min_inb_sa)
377 				min_inb_sa = eth_sec->sa_idx;
378 			if (eth_sec->sa_idx > max_inb_sa)
379 				max_inb_sa = eth_sec->sa_idx;
380 		}
381 		rte_tel_data_add_dict_int(d, "min_inb_sa", min_inb_sa);
382 		rte_tel_data_add_dict_int(d, "max_inb_sa", max_inb_sa);
383 	}
384 
385 	return 0;
386 }
387 
388 RTE_INIT(cnxk_ipsec_init_telemetry)
389 {
390 	rte_telemetry_register_cmd("/cnxk/ipsec/info",
391 				   ethdev_sec_tel_handle_info,
392 				   "Returns number of SA's and Max and Min SA. Parameters: port id");
393 	rte_telemetry_register_cmd("/cnxk/ipsec/sa_info",
394 				   ethdev_sec_tel_handle_sa_info,
395 				   "Returns ipsec info. Parameters: port id & sa_idx");
396 }
397