1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(C) 2022 Marvell.
3  */
4 
5 #include <rte_telemetry.h>
6 
7 #include <roc_api.h>
8 
9 #include "cnxk_ethdev.h"
10 
11 #define STR_MAXLEN 20
12 #define W0_MAXLEN  21
13 
14 static int
15 copy_outb_sa_9k(struct rte_tel_data *d, uint32_t i, void *sa)
16 {
17 	struct roc_onf_ipsec_outb_sa *out_sa;
18 	union {
19 		struct roc_ie_onf_sa_ctl ctl;
20 		uint64_t u64;
21 	} w0;
22 	char strw0[W0_MAXLEN];
23 	char str[STR_MAXLEN];
24 
25 	out_sa = (struct roc_onf_ipsec_outb_sa *)sa;
26 	w0.ctl = out_sa->ctl;
27 
28 	snprintf(str, sizeof(str), "outsa_w0_%u", i);
29 	snprintf(strw0, sizeof(strw0), "%" PRIu64, w0.u64);
30 	rte_tel_data_add_dict_string(d, str, strw0);
31 
32 	snprintf(str, sizeof(str), "outsa_src_%u", i);
33 	rte_tel_data_add_dict_u64(d, str, out_sa->udp_src);
34 
35 	snprintf(str, sizeof(str), "outsa_dst_%u", i);
36 	rte_tel_data_add_dict_u64(d, str, out_sa->udp_dst);
37 
38 	snprintf(str, sizeof(str), "outsa_isrc_%u", i);
39 	rte_tel_data_add_dict_u64(d, str, out_sa->ip_src);
40 
41 	snprintf(str, sizeof(str), "outsa_idst_%u", i);
42 	rte_tel_data_add_dict_u64(d, str, out_sa->ip_dst);
43 
44 	return 0;
45 }
46 
47 static int
48 copy_inb_sa_9k(struct rte_tel_data *d, uint32_t i, void *sa)
49 {
50 	struct roc_onf_ipsec_inb_sa *in_sa;
51 	union {
52 		struct roc_ie_onf_sa_ctl ctl;
53 		uint64_t u64;
54 	} w0;
55 	char strw0[W0_MAXLEN];
56 	char str[STR_MAXLEN];
57 
58 	in_sa = (struct roc_onf_ipsec_inb_sa *)sa;
59 	w0.ctl = in_sa->ctl;
60 
61 	snprintf(str, sizeof(str), "insa_w0_%u", i);
62 	snprintf(strw0, sizeof(strw0), "%" PRIu64, w0.u64);
63 	rte_tel_data_add_dict_string(d, str, strw0);
64 
65 	snprintf(str, sizeof(str), "insa_esnh_%u", i);
66 	rte_tel_data_add_dict_u64(d, str, in_sa->esn_hi);
67 
68 	snprintf(str, sizeof(str), "insa_esnl_%u", i);
69 	rte_tel_data_add_dict_u64(d, str, in_sa->esn_low);
70 
71 	return 0;
72 }
73 
74 static int
75 copy_outb_sa_10k(struct rte_tel_data *d, uint32_t i, void *sa)
76 {
77 	struct roc_ot_ipsec_outb_sa *out_sa;
78 	struct rte_tel_data *outer_hdr;
79 	char str[STR_MAXLEN];
80 	char s64[W0_MAXLEN];
81 	uint32_t j;
82 
83 	out_sa = (struct roc_ot_ipsec_outb_sa *)sa;
84 
85 	snprintf(str, sizeof(str), "outsa_w0_%u", i);
86 	snprintf(s64, sizeof(s64), "%" PRIu64, out_sa->w0.u64);
87 	rte_tel_data_add_dict_string(d, str, s64);
88 
89 	snprintf(str, sizeof(str), "outsa_w1_%u", i);
90 	snprintf(s64, sizeof(s64), "%" PRIu64, out_sa->w1.u64);
91 	rte_tel_data_add_dict_string(d, str, s64);
92 
93 	snprintf(str, sizeof(str), "outsa_w2_%u", i);
94 	snprintf(s64, sizeof(s64), "%" PRIu64, out_sa->w2.u64);
95 	rte_tel_data_add_dict_string(d, str, s64);
96 
97 	snprintf(str, sizeof(str), "outsa_w10_%u", i);
98 	snprintf(s64, sizeof(s64), "%" PRIu64, out_sa->w10.u64);
99 	rte_tel_data_add_dict_string(d, str, s64);
100 
101 	outer_hdr = rte_tel_data_alloc();
102 	if (!outer_hdr) {
103 		plt_err("Could not allocate space for outer header");
104 		return -ENOMEM;
105 	}
106 
107 	rte_tel_data_start_array(outer_hdr, RTE_TEL_U64_VAL);
108 
109 	for (j = 0; j < RTE_DIM(out_sa->outer_hdr.ipv6.src_addr); j++)
110 		rte_tel_data_add_array_u64(outer_hdr,
111 					   out_sa->outer_hdr.ipv6.src_addr[j]);
112 
113 	for (j = 0; j < RTE_DIM(out_sa->outer_hdr.ipv6.dst_addr); j++)
114 		rte_tel_data_add_array_u64(outer_hdr,
115 					   out_sa->outer_hdr.ipv6.dst_addr[j]);
116 
117 	snprintf(str, sizeof(str), "outsa_outer_hdr_%u", i);
118 	rte_tel_data_add_dict_container(d, str, outer_hdr, 0);
119 
120 	snprintf(str, sizeof(str), "outsa_errctl_%u", i);
121 	snprintf(s64, sizeof(s64), "%" PRIu64, out_sa->ctx.err_ctl.u64);
122 	rte_tel_data_add_dict_string(d, str, s64);
123 
124 	snprintf(str, sizeof(str), "outsa_esnval_%u", i);
125 	snprintf(s64, sizeof(s64), "%" PRIu64, out_sa->ctx.esn_val);
126 	rte_tel_data_add_dict_string(d, str, s64);
127 
128 	snprintf(str, sizeof(str), "outsa_hl_%u", i);
129 	snprintf(s64, sizeof(s64), "%" PRIu64, out_sa->ctx.hard_life);
130 	rte_tel_data_add_dict_string(d, str, s64);
131 
132 	snprintf(str, sizeof(str), "outsa_sl_%u", i);
133 	snprintf(s64, sizeof(s64), "%" PRIu64, out_sa->ctx.soft_life);
134 	rte_tel_data_add_dict_string(d, str, s64);
135 
136 	snprintf(str, sizeof(str), "outsa_octs_%u", i);
137 	snprintf(s64, sizeof(s64), "%" PRIu64, out_sa->ctx.mib_octs);
138 	rte_tel_data_add_dict_string(d, str, s64);
139 
140 	snprintf(str, sizeof(str), "outsa_pkts_%u", i);
141 	snprintf(s64, sizeof(s64), "%" PRIu64, out_sa->ctx.mib_pkts);
142 	rte_tel_data_add_dict_string(d, str, s64);
143 
144 	return 0;
145 }
146 
147 static int
148 copy_inb_sa_10k(struct rte_tel_data *d, uint32_t i, void *sa)
149 {
150 	struct roc_ot_ipsec_inb_sa *in_sa;
151 	struct rte_tel_data *outer_hdr;
152 	char str[STR_MAXLEN];
153 	char s64[W0_MAXLEN];
154 	uint32_t j;
155 
156 	in_sa = (struct roc_ot_ipsec_inb_sa *)sa;
157 
158 	snprintf(str, sizeof(str), "insa_w0_%u", i);
159 	snprintf(s64, sizeof(s64), "%" PRIu64, in_sa->w0.u64);
160 	rte_tel_data_add_dict_string(d, str, s64);
161 
162 	snprintf(str, sizeof(str), "insa_w1_%u", i);
163 	snprintf(s64, sizeof(s64), "%" PRIu64, in_sa->w1.u64);
164 	rte_tel_data_add_dict_string(d, str, s64);
165 
166 	snprintf(str, sizeof(str), "insa_w2_%u", i);
167 	snprintf(s64, sizeof(s64), "%" PRIu64, in_sa->w2.u64);
168 	rte_tel_data_add_dict_string(d, str, s64);
169 
170 	snprintf(str, sizeof(str), "insa_w10_%u", i);
171 	snprintf(s64, sizeof(s64), "%" PRIu64, in_sa->w10.u64);
172 	rte_tel_data_add_dict_string(d, str, s64);
173 
174 	outer_hdr = rte_tel_data_alloc();
175 	if (!outer_hdr) {
176 		plt_err("Could not allocate space for outer header");
177 		return -ENOMEM;
178 	}
179 
180 	rte_tel_data_start_array(outer_hdr, RTE_TEL_U64_VAL);
181 
182 	for (j = 0; j < RTE_DIM(in_sa->outer_hdr.ipv6.src_addr); j++)
183 		rte_tel_data_add_array_u64(outer_hdr,
184 					   in_sa->outer_hdr.ipv6.src_addr[j]);
185 
186 	for (j = 0; j < RTE_DIM(in_sa->outer_hdr.ipv6.dst_addr); j++)
187 		rte_tel_data_add_array_u64(outer_hdr,
188 					   in_sa->outer_hdr.ipv6.dst_addr[j]);
189 
190 	snprintf(str, sizeof(str), "insa_outer_hdr_%u", i);
191 	rte_tel_data_add_dict_container(d, str, outer_hdr, 0);
192 
193 	snprintf(str, sizeof(str), "insa_arbase_%u", i);
194 	snprintf(s64, sizeof(s64), "%" PRIu64, in_sa->ctx.ar_base);
195 	rte_tel_data_add_dict_string(d, str, s64);
196 
197 	snprintf(str, sizeof(str), "insa_ar_validm_%u", i);
198 	snprintf(s64, sizeof(s64), "%" PRIu64, in_sa->ctx.ar_valid_mask);
199 	rte_tel_data_add_dict_string(d, str, s64);
200 
201 	snprintf(str, sizeof(str), "insa_hl_%u", i);
202 	snprintf(s64, sizeof(s64), "%" PRIu64, in_sa->ctx.hard_life);
203 	rte_tel_data_add_dict_string(d, str, s64);
204 
205 	snprintf(str, sizeof(str), "insa_sl_%u", i);
206 	snprintf(s64, sizeof(s64), "%" PRIu64, in_sa->ctx.soft_life);
207 	rte_tel_data_add_dict_string(d, str, s64);
208 
209 	snprintf(str, sizeof(str), "insa_octs_%u", i);
210 	snprintf(s64, sizeof(s64), "%" PRIu64, in_sa->ctx.mib_octs);
211 	rte_tel_data_add_dict_string(d, str, s64);
212 
213 	snprintf(str, sizeof(str), "insa_pkts_%u", i);
214 	snprintf(s64, sizeof(s64), "%" PRIu64, in_sa->ctx.mib_pkts);
215 	rte_tel_data_add_dict_string(d, str, s64);
216 
217 	return 0;
218 }
219 
220 static int
221 ethdev_sec_tel_handle_info(const char *cmd __rte_unused, const char *params,
222 			   struct rte_tel_data *d)
223 {
224 	struct cnxk_eth_sec_sess *eth_sec, *tvar;
225 	struct rte_eth_dev *eth_dev;
226 	struct cnxk_eth_dev *dev;
227 	uint16_t port_id;
228 	char *end_p;
229 	uint32_t i;
230 	int ret;
231 
232 	port_id = strtoul(params, &end_p, 0);
233 	if (errno != 0)
234 		return -EINVAL;
235 
236 	if (*end_p != '\0')
237 		plt_err("Extra parameters passed to telemetry, ignoring it");
238 
239 	if (!rte_eth_dev_is_valid_port(port_id)) {
240 		plt_err("Invalid port id %u", port_id);
241 		return -EINVAL;
242 	}
243 
244 	eth_dev = &rte_eth_devices[port_id];
245 	if (!eth_dev) {
246 		plt_err("Ethdev not available");
247 		return -EINVAL;
248 	}
249 
250 	dev = cnxk_eth_pmd_priv(eth_dev);
251 
252 	rte_tel_data_start_dict(d);
253 
254 	rte_tel_data_add_dict_int(d, "nb_outb_sa", dev->outb.nb_sess);
255 
256 	i = 0;
257 	if (dev->tx_offloads & RTE_ETH_TX_OFFLOAD_SECURITY) {
258 		tvar = NULL;
259 		RTE_TAILQ_FOREACH_SAFE(eth_sec, &dev->outb.list, entry, tvar) {
260 			if (roc_model_is_cn10k())
261 				ret = copy_outb_sa_10k(d, i++, eth_sec->sa);
262 			else
263 				ret = copy_outb_sa_9k(d, i++, eth_sec->sa);
264 			if (ret < 0)
265 				return ret;
266 		}
267 	}
268 
269 	rte_tel_data_add_dict_int(d, "nb_inb_sa", dev->inb.nb_sess);
270 
271 	i = 0;
272 	if (dev->rx_offloads & RTE_ETH_RX_OFFLOAD_SECURITY) {
273 		tvar = NULL;
274 		RTE_TAILQ_FOREACH_SAFE(eth_sec, &dev->inb.list, entry, tvar) {
275 			if (roc_model_is_cn10k())
276 				ret = copy_inb_sa_10k(d, i++, eth_sec->sa);
277 			else
278 				ret = copy_inb_sa_9k(d, i++, eth_sec->sa);
279 			if (ret < 0)
280 				return ret;
281 		}
282 	}
283 
284 	return 0;
285 }
286 
287 RTE_INIT(cnxk_ipsec_init_telemetry)
288 {
289 	rte_telemetry_register_cmd("/cnxk/ipsec/info",
290 				   ethdev_sec_tel_handle_info,
291 				   "Returns ipsec info. Parameters: port id");
292 }
293