mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-04-07 05:06:08 -04:00
ovpn: store tunnel and transport statistics
Byte/packet counters for in-tunnel and transport streams are now initialized and updated as needed. To be exported via netlink. Signed-off-by: Antonio Quartulli <antonio@openvpn.net> Link: https://patch.msgid.link/20250415-b4-ovpn-v26-10-577f6097b964@openvpn.net Reviewed-by: Sabrina Dubroca <sd@queasysnail.net> Tested-by: Oleksandr Natalenko <oleksandr@natalenko.name> Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
committed by
Paolo Abeni
parent
8534731dbf
commit
04ca14955f
@@ -17,4 +17,5 @@ ovpn-y += netlink-gen.o
|
||||
ovpn-y += peer.o
|
||||
ovpn-y += pktid.o
|
||||
ovpn-y += socket.o
|
||||
ovpn-y += stats.o
|
||||
ovpn-y += udp.o
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <linux/skbuff.h>
|
||||
#include <net/gro_cells.h>
|
||||
#include <net/gso.h>
|
||||
#include <net/ip.h>
|
||||
|
||||
#include "ovpnpriv.h"
|
||||
#include "peer.h"
|
||||
@@ -55,9 +56,11 @@ static void ovpn_netdev_write(struct ovpn_peer *peer, struct sk_buff *skb)
|
||||
/* cause packet to be "received" by the interface */
|
||||
pkt_len = skb->len;
|
||||
ret = gro_cells_receive(&peer->ovpn->gro_cells, skb);
|
||||
if (likely(ret == NET_RX_SUCCESS))
|
||||
if (likely(ret == NET_RX_SUCCESS)) {
|
||||
/* update RX stats with the size of decrypted packet */
|
||||
ovpn_peer_stats_increment_rx(&peer->vpn_stats, pkt_len);
|
||||
dev_dstats_rx_add(peer->ovpn->dev, pkt_len);
|
||||
}
|
||||
}
|
||||
|
||||
void ovpn_decrypt_post(void *data, int ret)
|
||||
@@ -152,6 +155,8 @@ void ovpn_recv(struct ovpn_peer *peer, struct sk_buff *skb)
|
||||
struct ovpn_crypto_key_slot *ks;
|
||||
u8 key_id;
|
||||
|
||||
ovpn_peer_stats_increment_rx(&peer->link_stats, skb->len);
|
||||
|
||||
/* get the key slot matching the key ID in the received packet */
|
||||
key_id = ovpn_key_id_from_skb(skb);
|
||||
ks = ovpn_crypto_key_id_to_slot(&peer->crypto, key_id);
|
||||
@@ -175,6 +180,7 @@ void ovpn_encrypt_post(void *data, int ret)
|
||||
struct sk_buff *skb = data;
|
||||
struct ovpn_socket *sock;
|
||||
struct ovpn_peer *peer;
|
||||
unsigned int orig_len;
|
||||
|
||||
/* encryption is happening asynchronously. This function will be
|
||||
* called later by the crypto callback with a proper return value
|
||||
@@ -194,6 +200,7 @@ void ovpn_encrypt_post(void *data, int ret)
|
||||
goto err;
|
||||
|
||||
skb_mark_not_on_list(skb);
|
||||
orig_len = skb->len;
|
||||
|
||||
rcu_read_lock();
|
||||
sock = rcu_dereference(peer->sock);
|
||||
@@ -208,6 +215,8 @@ void ovpn_encrypt_post(void *data, int ret)
|
||||
/* no transport configured yet */
|
||||
goto err_unlock;
|
||||
}
|
||||
|
||||
ovpn_peer_stats_increment_tx(&peer->link_stats, orig_len);
|
||||
/* skb passed down the stack - don't free it */
|
||||
skb = NULL;
|
||||
err_unlock:
|
||||
@@ -322,6 +331,7 @@ netdev_tx_t ovpn_net_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
goto drop;
|
||||
}
|
||||
|
||||
ovpn_peer_stats_increment_tx(&peer->vpn_stats, skb->len);
|
||||
ovpn_send(ovpn, skb_list.next, peer);
|
||||
|
||||
return NETDEV_TX_OK;
|
||||
|
||||
@@ -61,6 +61,8 @@ struct ovpn_peer *ovpn_peer_new(struct ovpn_priv *ovpn, u32 id)
|
||||
ovpn_crypto_state_init(&peer->crypto);
|
||||
spin_lock_init(&peer->lock);
|
||||
kref_init(&peer->refcount);
|
||||
ovpn_peer_stats_init(&peer->vpn_stats);
|
||||
ovpn_peer_stats_init(&peer->link_stats);
|
||||
|
||||
ret = dst_cache_init(&peer->dst_cache, GFP_KERNEL);
|
||||
if (ret < 0) {
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
#include "crypto.h"
|
||||
#include "socket.h"
|
||||
#include "stats.h"
|
||||
|
||||
/**
|
||||
* struct ovpn_peer - the main remote peer object
|
||||
@@ -27,6 +28,8 @@
|
||||
* @crypto: the crypto configuration (ciphers, keys, etc..)
|
||||
* @dst_cache: cache for dst_entry used to send to peer
|
||||
* @bind: remote peer binding
|
||||
* @vpn_stats: per-peer in-VPN TX/RX stats
|
||||
* @link_stats: per-peer link/transport TX/RX stats
|
||||
* @delete_reason: why peer was deleted (i.e. timeout, transport error, ..)
|
||||
* @lock: protects binding to peer (bind)
|
||||
* @refcount: reference counter
|
||||
@@ -45,6 +48,8 @@ struct ovpn_peer {
|
||||
struct ovpn_crypto_state crypto;
|
||||
struct dst_cache dst_cache;
|
||||
struct ovpn_bind __rcu *bind;
|
||||
struct ovpn_peer_stats vpn_stats;
|
||||
struct ovpn_peer_stats link_stats;
|
||||
enum ovpn_del_peer_reason delete_reason;
|
||||
spinlock_t lock; /* protects bind */
|
||||
struct kref refcount;
|
||||
|
||||
21
drivers/net/ovpn/stats.c
Normal file
21
drivers/net/ovpn/stats.c
Normal file
@@ -0,0 +1,21 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* OpenVPN data channel offload
|
||||
*
|
||||
* Copyright (C) 2020-2025 OpenVPN, Inc.
|
||||
*
|
||||
* Author: James Yonan <james@openvpn.net>
|
||||
* Antonio Quartulli <antonio@openvpn.net>
|
||||
*/
|
||||
|
||||
#include <linux/atomic.h>
|
||||
|
||||
#include "stats.h"
|
||||
|
||||
void ovpn_peer_stats_init(struct ovpn_peer_stats *ps)
|
||||
{
|
||||
atomic64_set(&ps->rx.bytes, 0);
|
||||
atomic64_set(&ps->rx.packets, 0);
|
||||
|
||||
atomic64_set(&ps->tx.bytes, 0);
|
||||
atomic64_set(&ps->tx.packets, 0);
|
||||
}
|
||||
47
drivers/net/ovpn/stats.h
Normal file
47
drivers/net/ovpn/stats.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* OpenVPN data channel offload
|
||||
*
|
||||
* Copyright (C) 2020-2025 OpenVPN, Inc.
|
||||
*
|
||||
* Author: James Yonan <james@openvpn.net>
|
||||
* Antonio Quartulli <antonio@openvpn.net>
|
||||
* Lev Stipakov <lev@openvpn.net>
|
||||
*/
|
||||
|
||||
#ifndef _NET_OVPN_OVPNSTATS_H_
|
||||
#define _NET_OVPN_OVPNSTATS_H_
|
||||
|
||||
/* one stat */
|
||||
struct ovpn_peer_stat {
|
||||
atomic64_t bytes;
|
||||
atomic64_t packets;
|
||||
};
|
||||
|
||||
/* rx and tx stats combined */
|
||||
struct ovpn_peer_stats {
|
||||
struct ovpn_peer_stat rx;
|
||||
struct ovpn_peer_stat tx;
|
||||
};
|
||||
|
||||
void ovpn_peer_stats_init(struct ovpn_peer_stats *ps);
|
||||
|
||||
static inline void ovpn_peer_stats_increment(struct ovpn_peer_stat *stat,
|
||||
const unsigned int n)
|
||||
{
|
||||
atomic64_add(n, &stat->bytes);
|
||||
atomic64_inc(&stat->packets);
|
||||
}
|
||||
|
||||
static inline void ovpn_peer_stats_increment_rx(struct ovpn_peer_stats *stats,
|
||||
const unsigned int n)
|
||||
{
|
||||
ovpn_peer_stats_increment(&stats->rx, n);
|
||||
}
|
||||
|
||||
static inline void ovpn_peer_stats_increment_tx(struct ovpn_peer_stats *stats,
|
||||
const unsigned int n)
|
||||
{
|
||||
ovpn_peer_stats_increment(&stats->tx, n);
|
||||
}
|
||||
|
||||
#endif /* _NET_OVPN_OVPNSTATS_H_ */
|
||||
Reference in New Issue
Block a user