blob: 5d2b4f382d10c13ec233442afbb906e698fb0282 [file] [log] [blame]
/*
**************************************************************************
* Copyright (c) 2017, 2020, The Linux Foundation. All rights reserved.
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
* above copyright notice and this permission notice appear in all copies.
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
**************************************************************************
*/
/*
* nss_dtlsmgr_ctx_stats.c
* NSS DTLS Manager context statistics
*/
#include <linux/atomic.h>
#include <linux/crypto.h>
#include <linux/debugfs.h>
#include <linux/module.h>
#include <linux/rtnetlink.h>
#include <linux/types.h>
#include <linux/version.h>
#include <nss_api_if.h>
#include <nss_dtlsmgr.h>
#include "nss_dtlsmgr_private.h"
#define NSS_DTLSMGR_STATS_MAX_STR_LENGTH 64
#define NSS_DTLSMGR_STATS_EXTRA_LINES 16
extern struct nss_dtlsmgr g_dtls;
/*
* nss_dtlsmgr_ctx_fill_hw_error_stats()
* Fill hardware error statistics
*/
static ssize_t nss_dtlsmgr_ctx_fill_hw_error_stats(struct nss_dtlsmgr_stats *stats, char *buf,
ssize_t max_buf_len, ssize_t len)
{
int i;
len += snprintf(buf + len, max_buf_len, "\nHardware Errors\n---------------\n");
len += snprintf(buf + len, max_buf_len, "length_error = %lld\n", stats->fail_hw.len_error);
len += snprintf(buf + len, max_buf_len, "token_error = %lld\n", stats->fail_hw.token_error);
len += snprintf(buf + len, max_buf_len, "bypass_error = %lld\n", stats->fail_hw.bypass_error);
len += snprintf(buf + len, max_buf_len, "config_error = %lld\n", stats->fail_hw.config_error);
len += snprintf(buf + len, max_buf_len, "algo_error = %lld\n", stats->fail_hw.algo_error);
len += snprintf(buf + len, max_buf_len, "hash_ovf_error = %lld\n", stats->fail_hw.hash_ovf_error);
len += snprintf(buf + len, max_buf_len, "ttl_error = %lld\n", stats->fail_hw.ttl_error);
len += snprintf(buf + len, max_buf_len, "csum_error = %lld\n", stats->fail_hw.csum_error);
len += snprintf(buf + len, max_buf_len, "timeout_error = %lld\n", stats->fail_hw.timeout_error);
len += snprintf(buf + len, max_buf_len, "\nClassifcation Errors\n---------------------\n");
for (i = 0; i < NSS_DTLS_CMN_CLE_MAX; i++) {
/*
* Don't print if there are no errors
*/
if (!stats->fail_cle[i])
continue;
len += snprintf(buf + len, max_buf_len, "cle_error_%02d - %lld\n", i, stats->fail_cle[i]);
}
return len;
}
/*
* nss_dtlsmgr_ctx_encap_stats_read()
* Read the DTLS encapsulation statistics.
*/
static ssize_t nss_dtlsmgr_ctx_encap_stats_read(struct file *filep, char __user *buffer, size_t count, loff_t *ppos)
{
struct nss_dtlsmgr_ctx *ctx = filep->private_data;
struct nss_dtlsmgr_stats *stats;
ssize_t max_buf_len, len, ret;
char *buf;
NSS_DTLSMGR_VERIFY_MAGIC(ctx);
/*
* (Lines of output) * (Max string length)
*/
max_buf_len = ((sizeof(*stats) / sizeof(uint64_t)) + NSS_DTLSMGR_STATS_EXTRA_LINES) *
NSS_DTLSMGR_STATS_MAX_STR_LENGTH;
buf = vzalloc(max_buf_len);
if (!buf) {
nss_dtlsmgr_warn("Failed to allocate memory for statistic buffer");
return 0;
}
/*
* Fill encap statistics
*/
stats = &ctx->encap.stats;
len = snprintf(buf, max_buf_len, "ENCAPSULATION INTERFACE (%d) STATISTICS\n", ctx->encap.ifnum);
len += snprintf(buf + len, max_buf_len - len, "rx_packets = %lld\n", stats->rx_packets);
len += snprintf(buf + len, max_buf_len - len, "rx_bytes = %lld\n", stats->rx_bytes);
len += snprintf(buf + len, max_buf_len - len, "rx_dropped = %lld\n", stats->rx_dropped);
len += snprintf(buf + len, max_buf_len - len, "rx_single_rec = %lld\n", stats->rx_single_rec);
len += snprintf(buf + len, max_buf_len - len, "rx_multi_rec = %lld\n", stats->rx_multi_rec);
len += snprintf(buf + len, max_buf_len - len, "tx_packets = %lld\n", stats->tx_packets);
len += snprintf(buf + len, max_buf_len - len, "tx_bytes = %lld\n", stats->tx_bytes);
len += snprintf(buf + len, max_buf_len - len, "fail_crypto_resource = %lld\n", stats->fail_crypto_resource);
len += snprintf(buf + len, max_buf_len - len, "fail_crypto_enqueue = %lld\n", stats->fail_crypto_enqueue);
len += snprintf(buf + len, max_buf_len - len, "fail_headroom = %lld\n", stats->fail_headroom);
len += snprintf(buf + len, max_buf_len - len, "fail_tailroom = %lld\n", stats->fail_tailroom);
len += snprintf(buf + len, max_buf_len - len, "fail_queue = %lld\n", stats->fail_queue);
len += snprintf(buf + len, max_buf_len - len, "fail_queue_nexthop = %lld\n", stats->fail_queue_nexthop);
len += snprintf(buf + len, max_buf_len - len, "fail_pbuf_alloc = %lld\n", stats->fail_pbuf_alloc);
len += snprintf(buf + len, max_buf_len - len, "fail_pbuf_linear = %lld\n", stats->fail_pbuf_linear);
len += snprintf(buf + len, max_buf_len - len, "fail_pbuf_stats = %lld\n", stats->fail_pbuf_stats);
len += snprintf(buf + len, max_buf_len - len, "fail_pbuf_align = %lld\n", stats->fail_pbuf_align);
len += snprintf(buf + len, max_buf_len - len, "fail_ctx_active = %lld\n", stats->fail_ctx_active);
len += snprintf(buf + len, max_buf_len - len, "fail_hwctx_active = %lld\n", stats->fail_hwctx_active);
len += snprintf(buf + len, max_buf_len - len, "fail_cipher = %lld\n", stats->fail_cipher);
len += snprintf(buf + len, max_buf_len - len, "fail_auth = %lld\n", stats->fail_auth);
len += snprintf(buf + len, max_buf_len - len, "fail_seq_overflow = %lld\n", stats->fail_seq_ovf);
len += snprintf(buf + len, max_buf_len - len, "fail_host_tx = %lld\n", stats->fail_host_tx);
len += snprintf(buf + len, max_buf_len - len, "fail_host_rx = %lld\n", stats->fail_host_rx);
/* Returns total number of bytes written to the buffer */
len = nss_dtlsmgr_ctx_fill_hw_error_stats(stats, buf, max_buf_len, len);
ret = simple_read_from_buffer(buffer, count, ppos, buf, len);
vfree(buf);
return ret;
}
/*
* nss_dtlsmgr_ctx_decap_stats_read()
* Read the DTLS decapsulation statistics.
*/
static ssize_t nss_dtlsmgr_ctx_decap_stats_read(struct file *filep, char __user *buffer, size_t count, loff_t *ppos)
{
struct nss_dtlsmgr_ctx *ctx = filep->private_data;
struct nss_dtlsmgr_stats *stats;
ssize_t max_buf_len, ret;
ssize_t len = 0;
char *buf;
NSS_DTLSMGR_VERIFY_MAGIC(ctx);
/*
* (Lines of output) * (Max string length)
*/
max_buf_len = ((sizeof(*stats) / sizeof(uint64_t)) + NSS_DTLSMGR_STATS_EXTRA_LINES) *
NSS_DTLSMGR_STATS_MAX_STR_LENGTH;
buf = vzalloc(max_buf_len);
if (!buf) {
nss_dtlsmgr_warn("Failed to allocate memory for statistic buffer");
return 0;
}
/*
* Fill decap statistics
*/
stats = &ctx->decap.stats;
len += snprintf(buf, max_buf_len - len, "DECAPSULATION INTERFACE (%d) STATISTICS\n", ctx->decap.ifnum);
len += snprintf(buf + len, max_buf_len - len, "rx_packets = %lld\n", stats->rx_packets);
len += snprintf(buf + len, max_buf_len - len, "rx_bytes = %lld\n", stats->rx_bytes);
len += snprintf(buf + len, max_buf_len - len, "rx_dropped = %lld\n", stats->rx_dropped);
len += snprintf(buf + len, max_buf_len - len, "rx_single_rec = %lld\n", stats->rx_single_rec);
len += snprintf(buf + len, max_buf_len - len, "rx_multi_rec = %lld\n", stats->rx_multi_rec);
len += snprintf(buf + len, max_buf_len - len, "tx_packets = %lld\n", stats->tx_packets);
len += snprintf(buf + len, max_buf_len - len, "tx_bytes = %lld\n", stats->tx_bytes);
len += snprintf(buf + len, max_buf_len - len, "fail_crypto_resource = %lld\n", stats->fail_crypto_resource);
len += snprintf(buf + len, max_buf_len - len, "fail_crypto_enqueue = %lld\n", stats->fail_crypto_enqueue);
len += snprintf(buf + len, max_buf_len - len, "fail_version = %lld\n", stats->fail_ver);
len += snprintf(buf + len, max_buf_len - len, "fail_epoch = %lld\n", stats->fail_epoch);
len += snprintf(buf + len, max_buf_len - len, "fail_dtls_record = %lld\n", stats->fail_dtls_record);
len += snprintf(buf + len, max_buf_len - len, "fail_capwap = %lld\n", stats->fail_capwap);
len += snprintf(buf + len, max_buf_len - len, "fail_replay = %lld\n", stats->fail_replay);
len += snprintf(buf + len, max_buf_len - len, "fail_replay_dup = %lld\n", stats->fail_replay_dup);
len += snprintf(buf + len, max_buf_len - len, "fail_replay_window = %lld\n", stats->fail_replay_win);
len += snprintf(buf + len, max_buf_len - len, "fail_queue = %lld\n", stats->fail_queue);
len += snprintf(buf + len, max_buf_len - len, "fail_queue_nexthop = %lld\n", stats->fail_queue_nexthop);
len += snprintf(buf + len, max_buf_len - len, "fail_pbuf_alloc = %lld\n", stats->fail_pbuf_alloc);
len += snprintf(buf + len, max_buf_len - len, "fail_pbuf_linear = %lld\n", stats->fail_pbuf_linear);
len += snprintf(buf + len, max_buf_len - len, "fail_pbuf_stats = %lld\n", stats->fail_pbuf_stats);
len += snprintf(buf + len, max_buf_len - len, "fail_pbuf_align = %lld\n", stats->fail_pbuf_align);
len += snprintf(buf + len, max_buf_len - len, "fail_ctx_active = %lld\n", stats->fail_ctx_active);
len += snprintf(buf + len, max_buf_len - len, "fail_hwctx_active = %lld\n", stats->fail_hwctx_active);
len += snprintf(buf + len, max_buf_len - len, "fail_cipher = %lld\n", stats->fail_cipher);
len += snprintf(buf + len, max_buf_len - len, "fail_auth = %lld\n", stats->fail_auth);
len += snprintf(buf + len, max_buf_len - len, "fail_seq_overflow = %lld\n", stats->fail_seq_ovf);
len += snprintf(buf + len, max_buf_len - len, "fail_block_length = %lld\n", stats->fail_blk_len);
len += snprintf(buf + len, max_buf_len - len, "fail_hash_length = %lld\n", stats->fail_hash_len);
len += snprintf(buf + len, max_buf_len - len, "fail_host_tx = %lld\n", stats->fail_host_tx);
len += snprintf(buf + len, max_buf_len - len, "fail_host_rx = %lld\n", stats->fail_host_rx);
/* Returns total number of bytes written to the buffer */
len = nss_dtlsmgr_ctx_fill_hw_error_stats(stats, buf, max_buf_len, len);
ret = simple_read_from_buffer(buffer, count, ppos, buf, len);
vfree(buf);
return ret;
}
/*
* Context file operation structure instance
*/
static const struct file_operations nss_dtlsmgr_encap_stats_op = {
.owner = THIS_MODULE,
.open = simple_open,
.read = nss_dtlsmgr_ctx_encap_stats_read,
};
static const struct file_operations nss_dtlsmgr_decap_stats_op = {
.owner = THIS_MODULE,
.open = simple_open,
.read = nss_dtlsmgr_ctx_decap_stats_read,
};
/*
* nss_dtlmsgr_create_debugfs()
* Create debugfs files to display session statistics.
*/
int nss_dtlsmgr_create_debugfs(struct nss_dtlsmgr_ctx *ctx)
{
struct nss_dtlsmgr *drv = &g_dtls;
ctx->dentry = debugfs_create_dir(ctx->dev->name, drv->root_dir);
if (!ctx->dentry) {
nss_dtlsmgr_warn("failed to create debugfs directory");
return -1;
}
debugfs_create_file("encap_stats", S_IRUGO, ctx->dentry, ctx, &nss_dtlsmgr_encap_stats_op);
debugfs_create_file("decap_stats", S_IRUGO, ctx->dentry, ctx, &nss_dtlsmgr_decap_stats_op);
return 0;
}