mirror of
https://github.com/torvalds/linux.git
synced 2026-05-28 00:53:34 +02: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:
parent
8534731dbf
commit
04ca14955f
|
|
@ -17,4 +17,5 @@ ovpn-y += netlink-gen.o
|
||||||
ovpn-y += peer.o
|
ovpn-y += peer.o
|
||||||
ovpn-y += pktid.o
|
ovpn-y += pktid.o
|
||||||
ovpn-y += socket.o
|
ovpn-y += socket.o
|
||||||
|
ovpn-y += stats.o
|
||||||
ovpn-y += udp.o
|
ovpn-y += udp.o
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
#include <linux/skbuff.h>
|
#include <linux/skbuff.h>
|
||||||
#include <net/gro_cells.h>
|
#include <net/gro_cells.h>
|
||||||
#include <net/gso.h>
|
#include <net/gso.h>
|
||||||
|
#include <net/ip.h>
|
||||||
|
|
||||||
#include "ovpnpriv.h"
|
#include "ovpnpriv.h"
|
||||||
#include "peer.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 */
|
/* cause packet to be "received" by the interface */
|
||||||
pkt_len = skb->len;
|
pkt_len = skb->len;
|
||||||
ret = gro_cells_receive(&peer->ovpn->gro_cells, skb);
|
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 */
|
/* 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);
|
dev_dstats_rx_add(peer->ovpn->dev, pkt_len);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ovpn_decrypt_post(void *data, int ret)
|
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;
|
struct ovpn_crypto_key_slot *ks;
|
||||||
u8 key_id;
|
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 */
|
/* get the key slot matching the key ID in the received packet */
|
||||||
key_id = ovpn_key_id_from_skb(skb);
|
key_id = ovpn_key_id_from_skb(skb);
|
||||||
ks = ovpn_crypto_key_id_to_slot(&peer->crypto, key_id);
|
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 sk_buff *skb = data;
|
||||||
struct ovpn_socket *sock;
|
struct ovpn_socket *sock;
|
||||||
struct ovpn_peer *peer;
|
struct ovpn_peer *peer;
|
||||||
|
unsigned int orig_len;
|
||||||
|
|
||||||
/* encryption is happening asynchronously. This function will be
|
/* encryption is happening asynchronously. This function will be
|
||||||
* called later by the crypto callback with a proper return value
|
* 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;
|
goto err;
|
||||||
|
|
||||||
skb_mark_not_on_list(skb);
|
skb_mark_not_on_list(skb);
|
||||||
|
orig_len = skb->len;
|
||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
sock = rcu_dereference(peer->sock);
|
sock = rcu_dereference(peer->sock);
|
||||||
|
|
@ -208,6 +215,8 @@ void ovpn_encrypt_post(void *data, int ret)
|
||||||
/* no transport configured yet */
|
/* no transport configured yet */
|
||||||
goto err_unlock;
|
goto err_unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ovpn_peer_stats_increment_tx(&peer->link_stats, orig_len);
|
||||||
/* skb passed down the stack - don't free it */
|
/* skb passed down the stack - don't free it */
|
||||||
skb = NULL;
|
skb = NULL;
|
||||||
err_unlock:
|
err_unlock:
|
||||||
|
|
@ -322,6 +331,7 @@ netdev_tx_t ovpn_net_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||||
goto drop;
|
goto drop;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ovpn_peer_stats_increment_tx(&peer->vpn_stats, skb->len);
|
||||||
ovpn_send(ovpn, skb_list.next, peer);
|
ovpn_send(ovpn, skb_list.next, peer);
|
||||||
|
|
||||||
return NETDEV_TX_OK;
|
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);
|
ovpn_crypto_state_init(&peer->crypto);
|
||||||
spin_lock_init(&peer->lock);
|
spin_lock_init(&peer->lock);
|
||||||
kref_init(&peer->refcount);
|
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);
|
ret = dst_cache_init(&peer->dst_cache, GFP_KERNEL);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@
|
||||||
|
|
||||||
#include "crypto.h"
|
#include "crypto.h"
|
||||||
#include "socket.h"
|
#include "socket.h"
|
||||||
|
#include "stats.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct ovpn_peer - the main remote peer object
|
* struct ovpn_peer - the main remote peer object
|
||||||
|
|
@ -27,6 +28,8 @@
|
||||||
* @crypto: the crypto configuration (ciphers, keys, etc..)
|
* @crypto: the crypto configuration (ciphers, keys, etc..)
|
||||||
* @dst_cache: cache for dst_entry used to send to peer
|
* @dst_cache: cache for dst_entry used to send to peer
|
||||||
* @bind: remote peer binding
|
* @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, ..)
|
* @delete_reason: why peer was deleted (i.e. timeout, transport error, ..)
|
||||||
* @lock: protects binding to peer (bind)
|
* @lock: protects binding to peer (bind)
|
||||||
* @refcount: reference counter
|
* @refcount: reference counter
|
||||||
|
|
@ -45,6 +48,8 @@ struct ovpn_peer {
|
||||||
struct ovpn_crypto_state crypto;
|
struct ovpn_crypto_state crypto;
|
||||||
struct dst_cache dst_cache;
|
struct dst_cache dst_cache;
|
||||||
struct ovpn_bind __rcu *bind;
|
struct ovpn_bind __rcu *bind;
|
||||||
|
struct ovpn_peer_stats vpn_stats;
|
||||||
|
struct ovpn_peer_stats link_stats;
|
||||||
enum ovpn_del_peer_reason delete_reason;
|
enum ovpn_del_peer_reason delete_reason;
|
||||||
spinlock_t lock; /* protects bind */
|
spinlock_t lock; /* protects bind */
|
||||||
struct kref refcount;
|
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_ */
|
||||||
Loading…
Reference in New Issue
Block a user