[PATCH net-next v5 13/25] ovpn: store tunnel and transport statistics
From: Antonio Quartulli <antonio@openvpn.net>
Date: 2024-06-27 13:08:07
Subsystem:
networking drivers, openvpn data channel offload, the rest · Maintainers:
Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Antonio Quartulli, Linus Torvalds
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> --- drivers/net/ovpn/Makefile | 1 + drivers/net/ovpn/io.c | 12 ++++++++++ drivers/net/ovpn/peer.c | 3 +++ drivers/net/ovpn/peer.h | 9 ++++++++ drivers/net/ovpn/skb.h | 1 + drivers/net/ovpn/stats.c | 21 +++++++++++++++++ drivers/net/ovpn/stats.h | 47 +++++++++++++++++++++++++++++++++++++++ 7 files changed, 94 insertions(+) create mode 100644 drivers/net/ovpn/stats.c create mode 100644 drivers/net/ovpn/stats.h
diff --git a/drivers/net/ovpn/Makefile b/drivers/net/ovpn/Makefile
index ccdaeced1982..d43fda72646b 100644
--- a/drivers/net/ovpn/Makefile
+++ b/drivers/net/ovpn/Makefile@@ -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
diff --git a/drivers/net/ovpn/io.c b/drivers/net/ovpn/io.c
index 7da1e7e27533..0475440642dd 100644
--- a/drivers/net/ovpn/io.c
+++ b/drivers/net/ovpn/io.c@@ -11,6 +11,7 @@ #include <linux/skbuff.h> #include <net/gro_cells.h> #include <net/gso.h> +#include <net/ip.h> #include "ovpnstruct.h" #include "peer.h"
@@ -19,6 +20,7 @@ #include "crypto_aead.h" #include "netlink.h" #include "proto.h" +#include "socket.h" #include "udp.h" #include "skb.h"
@@ -120,6 +122,11 @@ void ovpn_decrypt_post(struct sk_buff *skb, int ret) goto drop; } + /* increment RX stats */ + ovpn_peer_stats_increment_rx(&peer->vpn_stats, skb->len); + ovpn_peer_stats_increment_rx(&peer->link_stats, + ovpn_skb_cb(skb)->orig_len); + ovpn_netdev_write(peer, skb); /* skb is passed to upper layer - don't free it */ skb = NULL;
@@ -148,6 +155,7 @@ void ovpn_recv(struct ovpn_peer *peer, struct sk_buff *skb) } ovpn_skb_cb(skb)->peer = peer; + ovpn_skb_cb(skb)->orig_len = skb->len; ovpn_decrypt_post(skb, ovpn_aead_decrypt(ks, skb)); }
@@ -176,6 +184,9 @@ void ovpn_encrypt_post(struct sk_buff *skb, int ret) goto err; skb_mark_not_on_list(skb); + ovpn_peer_stats_increment_tx(&peer->link_stats, skb->len); + ovpn_peer_stats_increment_tx(&peer->vpn_stats, + ovpn_skb_cb(skb)->orig_len); switch (peer->sock->sock->sk->sk_protocol) { case IPPROTO_UDP:
@@ -216,6 +227,7 @@ static bool ovpn_encrypt_one(struct ovpn_peer *peer, struct sk_buff *skb) } ovpn_skb_cb(skb)->peer = peer; + ovpn_skb_cb(skb)->orig_len = skb->len; /* take a reference to the peer because the crypto code may run async. * ovpn_encrypt_post() will release it upon completion
diff --git a/drivers/net/ovpn/peer.c b/drivers/net/ovpn/peer.c
index 2a89893b3a50..f633b70bb140 100644
--- a/drivers/net/ovpn/peer.c
+++ b/drivers/net/ovpn/peer.c@@ -18,6 +18,7 @@ #include "main.h" #include "netlink.h" #include "peer.h" +#include "socket.h" /** * ovpn_peer_new - allocate and initialize a new peer object
@@ -47,6 +48,8 @@ struct ovpn_peer *ovpn_peer_new(struct ovpn_struct *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) {
diff --git a/drivers/net/ovpn/peer.h b/drivers/net/ovpn/peer.h
index 70d92cd5bd63..dd4d91dfabb5 100644
--- a/drivers/net/ovpn/peer.h
+++ b/drivers/net/ovpn/peer.h@@ -10,10 +10,15 @@ #ifndef _NET_OVPN_OVPNPEER_H_ #define _NET_OVPN_OVPNPEER_H_ +#include <linux/ptr_ring.h> +#include <net/dst_cache.h> +#include <uapi/linux/ovpn.h> + #include "bind.h" #include "pktid.h" #include "crypto.h" #include "socket.h" +#include "stats.h" #include <net/dst_cache.h> #include <uapi/linux/ovpn.h>
@@ -30,6 +35,8 @@ * @dst_cache: cache for dst_entry used to send to peer * @bind: remote peer binding * @halt: true if ovpn_peer_mark_delete was called + * @vpn_stats: per-peer in-VPN TX/RX stays + * @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
@@ -48,6 +55,8 @@ struct ovpn_peer { struct dst_cache dst_cache; struct ovpn_bind __rcu *bind; bool halt; + 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;
diff --git a/drivers/net/ovpn/skb.h b/drivers/net/ovpn/skb.h
index 44786e34b704..99e5bfe252c0 100644
--- a/drivers/net/ovpn/skb.h
+++ b/drivers/net/ovpn/skb.h@@ -22,6 +22,7 @@ struct ovpn_cb { struct sk_buff *skb; struct ovpn_crypto_key_slot *ks; struct aead_request *req; + size_t orig_len; unsigned int payload_offset; };
diff --git a/drivers/net/ovpn/stats.c b/drivers/net/ovpn/stats.c
new file mode 100644
index 000000000000..a383842c3449
--- /dev/null
+++ b/drivers/net/ovpn/stats.c@@ -0,0 +1,21 @@ +// SPDX-License-Identifier: GPL-2.0 +/* OpenVPN data channel offload + * + * Copyright (C) 2020-2024 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); +}
diff --git a/drivers/net/ovpn/stats.h b/drivers/net/ovpn/stats.h
new file mode 100644
index 000000000000..868f49d25eaa
--- /dev/null
+++ b/drivers/net/ovpn/stats.h@@ -0,0 +1,47 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* OpenVPN data channel offload + * + * Copyright (C) 2020-2024 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_ */
--
2.44.2