7be78d0279
The tool comes from https://github.com/jsoref Signed-off-by: Josh Soref <jsoref@gmail.com> Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
244 lines
6.0 KiB
C
244 lines
6.0 KiB
C
/* SPDX-License-Identifier: BSD-3-Clause
|
|
* Copyright(c) 2021 Intel Corporation
|
|
*/
|
|
|
|
#include <rte_ipsec.h>
|
|
#include <rte_telemetry.h>
|
|
#include <rte_malloc.h>
|
|
#include "sa.h"
|
|
|
|
|
|
struct ipsec_telemetry_entry {
|
|
LIST_ENTRY(ipsec_telemetry_entry) next;
|
|
const struct rte_ipsec_sa *sa;
|
|
};
|
|
static LIST_HEAD(ipsec_telemetry_head, ipsec_telemetry_entry)
|
|
ipsec_telemetry_list = LIST_HEAD_INITIALIZER();
|
|
|
|
static int
|
|
handle_telemetry_cmd_ipsec_sa_list(const char *cmd __rte_unused,
|
|
const char *params __rte_unused,
|
|
struct rte_tel_data *data)
|
|
{
|
|
struct ipsec_telemetry_entry *entry;
|
|
rte_tel_data_start_array(data, RTE_TEL_U64_VAL);
|
|
|
|
LIST_FOREACH(entry, &ipsec_telemetry_list, next) {
|
|
const struct rte_ipsec_sa *sa = entry->sa;
|
|
rte_tel_data_add_array_u64(data, rte_be_to_cpu_32(sa->spi));
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* Handle IPsec SA statistics telemetry request
|
|
*
|
|
* Return dict of SA's with dict of key/value counters
|
|
*
|
|
* {
|
|
* "SA_SPI_XX": {"count": 0, "bytes": 0, "errors": 0},
|
|
* "SA_SPI_YY": {"count": 0, "bytes": 0, "errors": 0}
|
|
* }
|
|
*
|
|
*/
|
|
static int
|
|
handle_telemetry_cmd_ipsec_sa_stats(const char *cmd __rte_unused,
|
|
const char *params,
|
|
struct rte_tel_data *data)
|
|
{
|
|
struct ipsec_telemetry_entry *entry;
|
|
const struct rte_ipsec_sa *sa;
|
|
uint32_t sa_spi = 0;
|
|
|
|
if (params) {
|
|
sa_spi = rte_cpu_to_be_32((uint32_t)strtoul(params, NULL, 0));
|
|
if (sa_spi == 0)
|
|
return -EINVAL;
|
|
}
|
|
|
|
rte_tel_data_start_dict(data);
|
|
|
|
LIST_FOREACH(entry, &ipsec_telemetry_list, next) {
|
|
char sa_name[64];
|
|
sa = entry->sa;
|
|
static const char *name_pkt_cnt = "count";
|
|
static const char *name_byte_cnt = "bytes";
|
|
static const char *name_error_cnt = "errors";
|
|
struct rte_tel_data *sa_data;
|
|
|
|
/* If user provided SPI only get telemetry for that SA */
|
|
if (sa_spi && (sa_spi != sa->spi))
|
|
continue;
|
|
|
|
/* allocate telemetry data struct for SA telemetry */
|
|
sa_data = rte_tel_data_alloc();
|
|
if (!sa_data)
|
|
return -ENOMEM;
|
|
|
|
rte_tel_data_start_dict(sa_data);
|
|
|
|
/* add telemetry key/values pairs */
|
|
rte_tel_data_add_dict_u64(sa_data, name_pkt_cnt,
|
|
sa->statistics.count);
|
|
|
|
rte_tel_data_add_dict_u64(sa_data, name_byte_cnt,
|
|
sa->statistics.bytes -
|
|
(sa->statistics.count * sa->hdr_len));
|
|
|
|
rte_tel_data_add_dict_u64(sa_data, name_error_cnt,
|
|
sa->statistics.errors.count);
|
|
|
|
/* generate telemetry label */
|
|
snprintf(sa_name, sizeof(sa_name), "SA_SPI_%i",
|
|
rte_be_to_cpu_32(sa->spi));
|
|
|
|
/* add SA telemetry to dictionary container */
|
|
rte_tel_data_add_dict_container(data, sa_name, sa_data, 0);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
handle_telemetry_cmd_ipsec_sa_details(const char *cmd __rte_unused,
|
|
const char *params,
|
|
struct rte_tel_data *data)
|
|
{
|
|
struct ipsec_telemetry_entry *entry;
|
|
const struct rte_ipsec_sa *sa;
|
|
uint32_t sa_spi = 0;
|
|
|
|
if (params)
|
|
sa_spi = rte_cpu_to_be_32((uint32_t)strtoul(params, NULL, 0));
|
|
/* valid SPI needed */
|
|
if (sa_spi == 0)
|
|
return -EINVAL;
|
|
|
|
|
|
rte_tel_data_start_dict(data);
|
|
|
|
LIST_FOREACH(entry, &ipsec_telemetry_list, next) {
|
|
uint64_t mode;
|
|
sa = entry->sa;
|
|
if (sa_spi != sa->spi)
|
|
continue;
|
|
|
|
/* add SA configuration key/values pairs */
|
|
rte_tel_data_add_dict_string(data, "Type",
|
|
(sa->type & RTE_IPSEC_SATP_PROTO_MASK) ==
|
|
RTE_IPSEC_SATP_PROTO_AH ? "AH" : "ESP");
|
|
|
|
rte_tel_data_add_dict_string(data, "Direction",
|
|
(sa->type & RTE_IPSEC_SATP_DIR_MASK) ==
|
|
RTE_IPSEC_SATP_DIR_IB ? "Inbound" : "Outbound");
|
|
|
|
mode = sa->type & RTE_IPSEC_SATP_MODE_MASK;
|
|
|
|
if (mode == RTE_IPSEC_SATP_MODE_TRANS) {
|
|
rte_tel_data_add_dict_string(data, "Mode", "Transport");
|
|
} else {
|
|
rte_tel_data_add_dict_string(data, "Mode", "Tunnel");
|
|
|
|
if ((sa->type & RTE_IPSEC_SATP_NATT_MASK) ==
|
|
RTE_IPSEC_SATP_NATT_ENABLE) {
|
|
if (sa->type & RTE_IPSEC_SATP_MODE_TUNLV4) {
|
|
rte_tel_data_add_dict_string(data,
|
|
"Tunnel-Type",
|
|
"IPv4-UDP");
|
|
} else if (sa->type &
|
|
RTE_IPSEC_SATP_MODE_TUNLV6) {
|
|
rte_tel_data_add_dict_string(data,
|
|
"Tunnel-Type",
|
|
"IPv6-UDP");
|
|
}
|
|
} else {
|
|
if (sa->type & RTE_IPSEC_SATP_MODE_TUNLV4) {
|
|
rte_tel_data_add_dict_string(data,
|
|
"Tunnel-Type",
|
|
"IPv4");
|
|
} else if (sa->type &
|
|
RTE_IPSEC_SATP_MODE_TUNLV6) {
|
|
rte_tel_data_add_dict_string(data,
|
|
"Tunnel-Type",
|
|
"IPv6");
|
|
}
|
|
}
|
|
}
|
|
|
|
rte_tel_data_add_dict_string(data,
|
|
"extended-sequence-number",
|
|
(sa->type & RTE_IPSEC_SATP_ESN_MASK) ==
|
|
RTE_IPSEC_SATP_ESN_ENABLE ?
|
|
"enabled" : "disabled");
|
|
|
|
if ((sa->type & RTE_IPSEC_SATP_DIR_MASK) ==
|
|
RTE_IPSEC_SATP_DIR_IB)
|
|
|
|
if (sa->sqn.inb.rsn[sa->sqn.inb.rdidx])
|
|
rte_tel_data_add_dict_u64(data,
|
|
"sequence-number",
|
|
sa->sqn.inb.rsn[sa->sqn.inb.rdidx]->sqn);
|
|
else
|
|
rte_tel_data_add_dict_u64(data,
|
|
"sequence-number", 0);
|
|
else
|
|
rte_tel_data_add_dict_u64(data, "sequence-number",
|
|
sa->sqn.outb);
|
|
|
|
rte_tel_data_add_dict_string(data,
|
|
"explicit-congestion-notification",
|
|
(sa->type & RTE_IPSEC_SATP_ECN_MASK) ==
|
|
RTE_IPSEC_SATP_ECN_ENABLE ?
|
|
"enabled" : "disabled");
|
|
|
|
rte_tel_data_add_dict_string(data,
|
|
"copy-DSCP",
|
|
(sa->type & RTE_IPSEC_SATP_DSCP_MASK) ==
|
|
RTE_IPSEC_SATP_DSCP_ENABLE ?
|
|
"enabled" : "disabled");
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int
|
|
rte_ipsec_telemetry_sa_add(const struct rte_ipsec_sa *sa)
|
|
{
|
|
struct ipsec_telemetry_entry *entry = rte_zmalloc(NULL,
|
|
sizeof(struct ipsec_telemetry_entry), 0);
|
|
if (entry == NULL)
|
|
return -ENOMEM;
|
|
entry->sa = sa;
|
|
LIST_INSERT_HEAD(&ipsec_telemetry_list, entry, next);
|
|
return 0;
|
|
}
|
|
|
|
void
|
|
rte_ipsec_telemetry_sa_del(const struct rte_ipsec_sa *sa)
|
|
{
|
|
struct ipsec_telemetry_entry *entry;
|
|
LIST_FOREACH(entry, &ipsec_telemetry_list, next) {
|
|
if (sa == entry->sa) {
|
|
LIST_REMOVE(entry, next);
|
|
rte_free(entry);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
RTE_INIT(rte_ipsec_telemetry_init)
|
|
{
|
|
rte_telemetry_register_cmd("/ipsec/sa/list",
|
|
handle_telemetry_cmd_ipsec_sa_list,
|
|
"Return list of IPsec SAs with telemetry enabled.");
|
|
rte_telemetry_register_cmd("/ipsec/sa/stats",
|
|
handle_telemetry_cmd_ipsec_sa_stats,
|
|
"Returns IPsec SA statistics. Parameters: int sa_spi");
|
|
rte_telemetry_register_cmd("/ipsec/sa/details",
|
|
handle_telemetry_cmd_ipsec_sa_details,
|
|
"Returns IPsec SA configuration. Parameters: int sa_spi");
|
|
}
|