xref: /dpdk/lib/ipsec/ipsec_telemetry.c (revision b4f0a9bb5807a4f0a4904595bb85a9a386696311)
168977baaSRadu Nicolau /* SPDX-License-Identifier: BSD-3-Clause
268977baaSRadu Nicolau  * Copyright(c) 2021 Intel Corporation
368977baaSRadu Nicolau  */
468977baaSRadu Nicolau 
572b452c5SDmitry Kozlyuk #include <stdlib.h>
668977baaSRadu Nicolau #include <rte_ipsec.h>
768977baaSRadu Nicolau #include <rte_telemetry.h>
868977baaSRadu Nicolau #include <rte_malloc.h>
968977baaSRadu Nicolau #include "sa.h"
1068977baaSRadu Nicolau 
1168977baaSRadu Nicolau 
1268977baaSRadu Nicolau struct ipsec_telemetry_entry {
1368977baaSRadu Nicolau 	LIST_ENTRY(ipsec_telemetry_entry) next;
1468977baaSRadu Nicolau 	const struct rte_ipsec_sa *sa;
1568977baaSRadu Nicolau };
1668977baaSRadu Nicolau static LIST_HEAD(ipsec_telemetry_head, ipsec_telemetry_entry)
1768977baaSRadu Nicolau 		ipsec_telemetry_list = LIST_HEAD_INITIALIZER();
1868977baaSRadu Nicolau 
1968977baaSRadu Nicolau static int
handle_telemetry_cmd_ipsec_sa_list(const char * cmd __rte_unused,const char * params __rte_unused,struct rte_tel_data * data)2068977baaSRadu Nicolau handle_telemetry_cmd_ipsec_sa_list(const char *cmd __rte_unused,
2168977baaSRadu Nicolau 		const char *params __rte_unused,
2268977baaSRadu Nicolau 		struct rte_tel_data *data)
2368977baaSRadu Nicolau {
2468977baaSRadu Nicolau 	struct ipsec_telemetry_entry *entry;
252d2c55e4SBruce Richardson 	rte_tel_data_start_array(data, RTE_TEL_UINT_VAL);
2668977baaSRadu Nicolau 
2768977baaSRadu Nicolau 	LIST_FOREACH(entry, &ipsec_telemetry_list, next) {
2868977baaSRadu Nicolau 		const struct rte_ipsec_sa *sa = entry->sa;
29*af0785a2SBruce Richardson 		rte_tel_data_add_array_uint(data, rte_be_to_cpu_32(sa->spi));
3068977baaSRadu Nicolau 	}
3168977baaSRadu Nicolau 
3268977baaSRadu Nicolau 	return 0;
3368977baaSRadu Nicolau }
3468977baaSRadu Nicolau 
3568977baaSRadu Nicolau /**
3668977baaSRadu Nicolau  * Handle IPsec SA statistics telemetry request
3768977baaSRadu Nicolau  *
3868977baaSRadu Nicolau  * Return dict of SA's with dict of key/value counters
3968977baaSRadu Nicolau  *
4068977baaSRadu Nicolau  * {
4168977baaSRadu Nicolau  *     "SA_SPI_XX": {"count": 0, "bytes": 0, "errors": 0},
4268977baaSRadu Nicolau  *     "SA_SPI_YY": {"count": 0, "bytes": 0, "errors": 0}
4368977baaSRadu Nicolau  * }
4468977baaSRadu Nicolau  */
4568977baaSRadu Nicolau static int
handle_telemetry_cmd_ipsec_sa_stats(const char * cmd __rte_unused,const char * params,struct rte_tel_data * data)4668977baaSRadu Nicolau handle_telemetry_cmd_ipsec_sa_stats(const char *cmd __rte_unused,
4768977baaSRadu Nicolau 		const char *params,
4868977baaSRadu Nicolau 		struct rte_tel_data *data)
4968977baaSRadu Nicolau {
5068977baaSRadu Nicolau 	struct ipsec_telemetry_entry *entry;
5168977baaSRadu Nicolau 	const struct rte_ipsec_sa *sa;
5268977baaSRadu Nicolau 	uint32_t sa_spi = 0;
5368977baaSRadu Nicolau 
5468977baaSRadu Nicolau 	if (params) {
5568977baaSRadu Nicolau 		sa_spi = rte_cpu_to_be_32((uint32_t)strtoul(params, NULL, 0));
5668977baaSRadu Nicolau 		if (sa_spi == 0)
5768977baaSRadu Nicolau 			return -EINVAL;
5868977baaSRadu Nicolau 	}
5968977baaSRadu Nicolau 
6068977baaSRadu Nicolau 	rte_tel_data_start_dict(data);
6168977baaSRadu Nicolau 
6268977baaSRadu Nicolau 	LIST_FOREACH(entry, &ipsec_telemetry_list, next) {
6368977baaSRadu Nicolau 		char sa_name[64];
6468977baaSRadu Nicolau 		sa = entry->sa;
6568977baaSRadu Nicolau 		static const char *name_pkt_cnt = "count";
6668977baaSRadu Nicolau 		static const char *name_byte_cnt = "bytes";
6768977baaSRadu Nicolau 		static const char *name_error_cnt = "errors";
6868977baaSRadu Nicolau 		struct rte_tel_data *sa_data;
6968977baaSRadu Nicolau 
7068977baaSRadu Nicolau 		/* If user provided SPI only get telemetry for that SA */
7168977baaSRadu Nicolau 		if (sa_spi && (sa_spi != sa->spi))
7268977baaSRadu Nicolau 			continue;
7368977baaSRadu Nicolau 
7468977baaSRadu Nicolau 		/* allocate telemetry data struct for SA telemetry */
7568977baaSRadu Nicolau 		sa_data = rte_tel_data_alloc();
7668977baaSRadu Nicolau 		if (!sa_data)
7768977baaSRadu Nicolau 			return -ENOMEM;
7868977baaSRadu Nicolau 
7968977baaSRadu Nicolau 		rte_tel_data_start_dict(sa_data);
8068977baaSRadu Nicolau 
8168977baaSRadu Nicolau 		/* add telemetry key/values pairs */
82*af0785a2SBruce Richardson 		rte_tel_data_add_dict_uint(sa_data, name_pkt_cnt,
8368977baaSRadu Nicolau 					   sa->statistics.count);
8468977baaSRadu Nicolau 
85*af0785a2SBruce Richardson 		rte_tel_data_add_dict_uint(sa_data, name_byte_cnt,
8668977baaSRadu Nicolau 					   sa->statistics.bytes -
8768977baaSRadu Nicolau 					   (sa->statistics.count * sa->hdr_len));
8868977baaSRadu Nicolau 
89*af0785a2SBruce Richardson 		rte_tel_data_add_dict_uint(sa_data, name_error_cnt,
9068977baaSRadu Nicolau 					   sa->statistics.errors.count);
9168977baaSRadu Nicolau 
9268977baaSRadu Nicolau 		/* generate telemetry label */
9368977baaSRadu Nicolau 		snprintf(sa_name, sizeof(sa_name), "SA_SPI_%i",
9468977baaSRadu Nicolau 				rte_be_to_cpu_32(sa->spi));
9568977baaSRadu Nicolau 
9668977baaSRadu Nicolau 		/* add SA telemetry to dictionary container */
9768977baaSRadu Nicolau 		rte_tel_data_add_dict_container(data, sa_name, sa_data, 0);
9868977baaSRadu Nicolau 	}
9968977baaSRadu Nicolau 
10068977baaSRadu Nicolau 	return 0;
10168977baaSRadu Nicolau }
10268977baaSRadu Nicolau 
10368977baaSRadu Nicolau static int
handle_telemetry_cmd_ipsec_sa_details(const char * cmd __rte_unused,const char * params,struct rte_tel_data * data)10468977baaSRadu Nicolau handle_telemetry_cmd_ipsec_sa_details(const char *cmd __rte_unused,
10568977baaSRadu Nicolau 		const char *params,
10668977baaSRadu Nicolau 		struct rte_tel_data *data)
10768977baaSRadu Nicolau {
10868977baaSRadu Nicolau 	struct ipsec_telemetry_entry *entry;
10968977baaSRadu Nicolau 	const struct rte_ipsec_sa *sa;
11068977baaSRadu Nicolau 	uint32_t sa_spi = 0;
11168977baaSRadu Nicolau 
11268977baaSRadu Nicolau 	if (params)
11368977baaSRadu Nicolau 		sa_spi = rte_cpu_to_be_32((uint32_t)strtoul(params, NULL, 0));
11468977baaSRadu Nicolau 	/* valid SPI needed */
11568977baaSRadu Nicolau 	if (sa_spi == 0)
11668977baaSRadu Nicolau 		return -EINVAL;
11768977baaSRadu Nicolau 
11868977baaSRadu Nicolau 
11968977baaSRadu Nicolau 	rte_tel_data_start_dict(data);
12068977baaSRadu Nicolau 
12168977baaSRadu Nicolau 	LIST_FOREACH(entry, &ipsec_telemetry_list, next) {
12268977baaSRadu Nicolau 		uint64_t mode;
12368977baaSRadu Nicolau 		sa = entry->sa;
12468977baaSRadu Nicolau 		if (sa_spi != sa->spi)
12568977baaSRadu Nicolau 			continue;
12668977baaSRadu Nicolau 
12768977baaSRadu Nicolau 		/* add SA configuration key/values pairs */
12868977baaSRadu Nicolau 		rte_tel_data_add_dict_string(data, "Type",
12968977baaSRadu Nicolau 			(sa->type & RTE_IPSEC_SATP_PROTO_MASK) ==
13068977baaSRadu Nicolau 			RTE_IPSEC_SATP_PROTO_AH ? "AH" : "ESP");
13168977baaSRadu Nicolau 
13268977baaSRadu Nicolau 		rte_tel_data_add_dict_string(data, "Direction",
13368977baaSRadu Nicolau 			(sa->type & RTE_IPSEC_SATP_DIR_MASK) ==
13468977baaSRadu Nicolau 			RTE_IPSEC_SATP_DIR_IB ?	"Inbound" : "Outbound");
13568977baaSRadu Nicolau 
13668977baaSRadu Nicolau 		mode = sa->type & RTE_IPSEC_SATP_MODE_MASK;
13768977baaSRadu Nicolau 
13868977baaSRadu Nicolau 		if (mode == RTE_IPSEC_SATP_MODE_TRANS) {
13968977baaSRadu Nicolau 			rte_tel_data_add_dict_string(data, "Mode", "Transport");
14068977baaSRadu Nicolau 		} else {
14168977baaSRadu Nicolau 			rte_tel_data_add_dict_string(data, "Mode", "Tunnel");
14268977baaSRadu Nicolau 
14368977baaSRadu Nicolau 			if ((sa->type & RTE_IPSEC_SATP_NATT_MASK) ==
14468977baaSRadu Nicolau 				RTE_IPSEC_SATP_NATT_ENABLE) {
14568977baaSRadu Nicolau 				if (sa->type & RTE_IPSEC_SATP_MODE_TUNLV4) {
14668977baaSRadu Nicolau 					rte_tel_data_add_dict_string(data,
14768977baaSRadu Nicolau 						"Tunnel-Type",
14868977baaSRadu Nicolau 						"IPv4-UDP");
14968977baaSRadu Nicolau 				} else if (sa->type &
15068977baaSRadu Nicolau 						RTE_IPSEC_SATP_MODE_TUNLV6) {
15168977baaSRadu Nicolau 					rte_tel_data_add_dict_string(data,
15268977baaSRadu Nicolau 						"Tunnel-Type",
15374176aecSRadu Nicolau 						"IPv6-UDP");
15468977baaSRadu Nicolau 				}
15568977baaSRadu Nicolau 			} else {
15668977baaSRadu Nicolau 				if (sa->type & RTE_IPSEC_SATP_MODE_TUNLV4) {
15768977baaSRadu Nicolau 					rte_tel_data_add_dict_string(data,
15868977baaSRadu Nicolau 						"Tunnel-Type",
15974176aecSRadu Nicolau 						"IPv4");
16068977baaSRadu Nicolau 				} else if (sa->type &
16168977baaSRadu Nicolau 						RTE_IPSEC_SATP_MODE_TUNLV6) {
16268977baaSRadu Nicolau 					rte_tel_data_add_dict_string(data,
16368977baaSRadu Nicolau 						"Tunnel-Type",
16474176aecSRadu Nicolau 						"IPv6");
16568977baaSRadu Nicolau 				}
16668977baaSRadu Nicolau 			}
16768977baaSRadu Nicolau 		}
16868977baaSRadu Nicolau 
16968977baaSRadu Nicolau 		rte_tel_data_add_dict_string(data,
17068977baaSRadu Nicolau 				"extended-sequence-number",
17168977baaSRadu Nicolau 				(sa->type & RTE_IPSEC_SATP_ESN_MASK) ==
17268977baaSRadu Nicolau 				 RTE_IPSEC_SATP_ESN_ENABLE ?
17368977baaSRadu Nicolau 				"enabled" : "disabled");
17468977baaSRadu Nicolau 
17568977baaSRadu Nicolau 		if ((sa->type & RTE_IPSEC_SATP_DIR_MASK) ==
17668977baaSRadu Nicolau 			RTE_IPSEC_SATP_DIR_IB)
17768977baaSRadu Nicolau 
17868977baaSRadu Nicolau 			if (sa->sqn.inb.rsn[sa->sqn.inb.rdidx])
179*af0785a2SBruce Richardson 				rte_tel_data_add_dict_uint(data,
18068977baaSRadu Nicolau 							   "sequence-number",
18168977baaSRadu Nicolau 							   sa->sqn.inb.rsn[sa->sqn.inb.rdidx]->sqn);
18268977baaSRadu Nicolau 			else
183*af0785a2SBruce Richardson 				rte_tel_data_add_dict_uint(data,
184*af0785a2SBruce Richardson 							   "sequence-number",
185*af0785a2SBruce Richardson 							   0);
18668977baaSRadu Nicolau 		else
187*af0785a2SBruce Richardson 			rte_tel_data_add_dict_uint(data, "sequence-number",
18868977baaSRadu Nicolau 						   sa->sqn.outb);
18968977baaSRadu Nicolau 
19068977baaSRadu Nicolau 		rte_tel_data_add_dict_string(data,
19168977baaSRadu Nicolau 				"explicit-congestion-notification",
19268977baaSRadu Nicolau 				(sa->type & RTE_IPSEC_SATP_ECN_MASK) ==
19368977baaSRadu Nicolau 				RTE_IPSEC_SATP_ECN_ENABLE ?
19468977baaSRadu Nicolau 				"enabled" : "disabled");
19568977baaSRadu Nicolau 
19668977baaSRadu Nicolau 		rte_tel_data_add_dict_string(data,
19768977baaSRadu Nicolau 				"copy-DSCP",
19868977baaSRadu Nicolau 				(sa->type & RTE_IPSEC_SATP_DSCP_MASK) ==
19968977baaSRadu Nicolau 				RTE_IPSEC_SATP_DSCP_ENABLE ?
20068977baaSRadu Nicolau 				"enabled" : "disabled");
20168977baaSRadu Nicolau 	}
20268977baaSRadu Nicolau 
20368977baaSRadu Nicolau 	return 0;
20468977baaSRadu Nicolau }
20568977baaSRadu Nicolau 
20668977baaSRadu Nicolau 
20768977baaSRadu Nicolau int
rte_ipsec_telemetry_sa_add(const struct rte_ipsec_sa * sa)20868977baaSRadu Nicolau rte_ipsec_telemetry_sa_add(const struct rte_ipsec_sa *sa)
20968977baaSRadu Nicolau {
21068977baaSRadu Nicolau 	struct ipsec_telemetry_entry *entry = rte_zmalloc(NULL,
21168977baaSRadu Nicolau 			sizeof(struct ipsec_telemetry_entry), 0);
21268977baaSRadu Nicolau 	if (entry == NULL)
21368977baaSRadu Nicolau 		return -ENOMEM;
21468977baaSRadu Nicolau 	entry->sa = sa;
21568977baaSRadu Nicolau 	LIST_INSERT_HEAD(&ipsec_telemetry_list, entry, next);
21668977baaSRadu Nicolau 	return 0;
21768977baaSRadu Nicolau }
21868977baaSRadu Nicolau 
21968977baaSRadu Nicolau void
rte_ipsec_telemetry_sa_del(const struct rte_ipsec_sa * sa)22068977baaSRadu Nicolau rte_ipsec_telemetry_sa_del(const struct rte_ipsec_sa *sa)
22168977baaSRadu Nicolau {
22268977baaSRadu Nicolau 	struct ipsec_telemetry_entry *entry;
22368977baaSRadu Nicolau 	LIST_FOREACH(entry, &ipsec_telemetry_list, next) {
22468977baaSRadu Nicolau 		if (sa == entry->sa) {
22568977baaSRadu Nicolau 			LIST_REMOVE(entry, next);
22668977baaSRadu Nicolau 			rte_free(entry);
22768977baaSRadu Nicolau 			return;
22868977baaSRadu Nicolau 		}
22968977baaSRadu Nicolau 	}
23068977baaSRadu Nicolau }
23168977baaSRadu Nicolau 
23268977baaSRadu Nicolau 
RTE_INIT(rte_ipsec_telemetry_init)23368977baaSRadu Nicolau RTE_INIT(rte_ipsec_telemetry_init)
23468977baaSRadu Nicolau {
23568977baaSRadu Nicolau 	rte_telemetry_register_cmd("/ipsec/sa/list",
23668977baaSRadu Nicolau 		handle_telemetry_cmd_ipsec_sa_list,
23768977baaSRadu Nicolau 		"Return list of IPsec SAs with telemetry enabled.");
23868977baaSRadu Nicolau 	rte_telemetry_register_cmd("/ipsec/sa/stats",
23968977baaSRadu Nicolau 		handle_telemetry_cmd_ipsec_sa_stats,
2407be78d02SJosh Soref 		"Returns IPsec SA statistics. Parameters: int sa_spi");
24168977baaSRadu Nicolau 	rte_telemetry_register_cmd("/ipsec/sa/details",
24268977baaSRadu Nicolau 		handle_telemetry_cmd_ipsec_sa_details,
24368977baaSRadu Nicolau 		"Returns IPsec SA configuration. Parameters: int sa_spi");
24468977baaSRadu Nicolau }
245