blob: 9d4a37af2b37ac95aa298b852bf09cf98aba5052 [file] [log] [blame]
/*
**************************************************************************
* Copyright (c) 2015, 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_l2tpv2_stats.c
*
* This file is the NSS l2tpv2 stats handler functions
*/
#include <linux/types.h>
#if IS_ENABLED(CONFIG_NF_FLOW_TABLE)
#include <net/netfilter/nf_flow_table.h>
#endif
#include <linux/ppp_channel.h>
#include <nss_api_if.h>
#include <nss_dynamic_interface.h>
#include <linux/l2tp.h>
#include <net/sock.h>
#include <linux/if_pppox.h>
#include <linux/ppp_defs.h>
#include <linux/version.h>
#include <linux/../../net/l2tp/l2tp_core.h>
#include "nss_connmgr_l2tpv2.h"
/*
* NSS l2tpv2 debug macros
*/
#if (NSS_L2TP_DEBUG_LEVEL < 1)
#define nss_l2tpv2_stats_assert(fmt, args...)
#else
#define nss_l2tpv2_stats_assert(c) BUG_ON(!(c));
#endif
#if defined(CONFIG_DYNAMIC_DEBUG)
/*
* Compile messages for dynamic enable/disable
*/
#define nss_l2tpv2_stats_warning(s, ...) pr_debug("%s[%d]:" s, __func__, __LINE__, ##__VA_ARGS__)
#define nss_l2tpv2_stats_info(s, ...) pr_debug("%s[%d]:" s, __func__, __LINE__, ##__VA_ARGS__)
#define nss_l2tpv2_stats_trace(s, ...) pr_debug("%s[%d]:" s, __func__, __LINE__, ##__VA_ARGS__)
#else
/*
* Statically compile messages at different levels
*/
#if (NSS_L2TP_DEBUG_LEVEL < 2)
#define nss_l2tpv2_stats_warning(s, ...)
#else
#define nss_l2tpv2_stats_warning(s, ...) pr_warn("%s[%d]:" s, __func__, __LINE__, ##__VA_ARGS__)
#endif
#if (NSS_L2TP_DEBUG_LEVEL < 3)
#define nss_l2tpv2_stats_info(s, ...)
#else
#define nss_l2tpv2_stats_info(s, ...) pr_notice("%s[%d]:" s, __func__, __LINE__, ##__VA_ARGS__)
#endif
#if (NSS_L2TP_DEBUG_LEVEL < 4)
#define nss_l2tpv2_stats_trace(s, ...)
#else
#define nss_l2tpv2_stats_trace(s, ...) pr_info("%s[%d]:" s, __func__, __LINE__, ##__VA_ARGS__)
#endif
#endif
/*
* nss_l2tpv2_update_dev_stats()
* Handle stats message for l2tpv2 data messages
*/
void nss_l2tpv2_update_dev_stats(struct net_device *dev, struct nss_l2tpv2_sync_session_stats_msg *sync_stats)
{
struct l2tp_tunnel *tunnel;
struct l2tp_session *session;
struct nss_connmgr_l2tpv2_data data;
struct l2tp_stats l2tp_stats;
int err;
if (!dev) {
return;
}
dev_hold(dev);
memset(&l2tp_stats, 0, sizeof(struct l2tp_stats));
/*
* Get tunnel id
*/
err = nss_connmgr_l2tpv2_get_data(dev, &data);
if (err) {
dev_put(dev);
return;
}
/*
* Update tunnel & session stats
*/
#if (LINUX_VERSION_CODE <= KERNEL_VERSION(4, 12, 0))
tunnel = l2tp_tunnel_find(dev_net(dev), data.l2tpv2.tunnel.tunnel_id);
if (!tunnel) {
dev_put(dev);
return;
}
tunnel_hold(tunnel);
session = l2tp_session_find(dev_net(dev), tunnel, data.l2tpv2.session.session_id);
if (!session) {
tunnel_put(tunnel);
dev_put(dev);
return;
}
session_hold(session);
#else
tunnel = l2tp_tunnel_get(dev_net(dev), data.l2tpv2.tunnel.tunnel_id);
if (!tunnel) {
dev_put(dev);
return;
}
session = l2tp_tunnel_get_session(tunnel, data.l2tpv2.session.session_id);
if (!session) {
tunnel_put(tunnel);
dev_put(dev);
return;
}
#endif
atomic_long_set(&l2tp_stats.tx_packets, (long)sync_stats->node_stats.tx_packets);
atomic_long_set(&l2tp_stats.tx_bytes, (long)sync_stats->node_stats.tx_bytes);
atomic_long_set(&l2tp_stats.tx_errors, (long)sync_stats->tx_errors);
atomic_long_set(&l2tp_stats.rx_packets, (long)sync_stats->node_stats.rx_packets);
atomic_long_set(&l2tp_stats.rx_bytes, (long)sync_stats->node_stats.rx_bytes);
atomic_long_set(&l2tp_stats.rx_errors, (long)sync_stats->rx_errors);
atomic_long_set(&l2tp_stats.rx_seq_discards, (long)sync_stats->rx_seq_discards);
atomic_long_set(&l2tp_stats.rx_oos_packets, (long)(sync_stats->rx_oos_packets));
l2tp_stats_update(tunnel, session, &l2tp_stats);
session_put(session);
tunnel_put(tunnel);
/*
* Update ppp stats
*/
ppp_update_stats(dev,
(unsigned long)sync_stats->node_stats.rx_packets,
(unsigned long)sync_stats->node_stats.rx_bytes,
(unsigned long)sync_stats->node_stats.tx_packets,
(unsigned long)sync_stats->node_stats.tx_bytes,
(unsigned long)sync_stats->rx_errors,
(unsigned long)sync_stats->tx_errors,
(unsigned long)nss_cmn_rx_dropped_sum(&sync_stats->node_stats),
(unsigned long)sync_stats->tx_dropped);
dev_put(dev);
}