git: 18a30fd39be7 - main - if_ovpn: start tracking per-peer packets/bytes in/out

From: Kristof Provost <kp_at_FreeBSD.org>
Date: Wed, 14 Dec 2022 05:49:42 UTC
The branch main has been updated by kp:

URL: https://cgit.FreeBSD.org/src/commit/?id=18a30fd39be77de7e56e30ceacc90f4c8833cfc9

commit 18a30fd39be77de7e56e30ceacc90f4c8833cfc9
Author:     Kristof Provost <kp@FreeBSD.org>
AuthorDate: 2022-11-26 13:22:23 +0000
Commit:     Kristof Provost <kp@FreeBSD.org>
CommitDate: 2022-12-14 05:48:58 +0000

    if_ovpn: start tracking per-peer packets/bytes in/out
    
    OpenVPN will introduce a mechanism to retrieve per-peer statistics.
    Start tracking those so we can return them to userspace when queried.
    
    Sponsored by:   Rubicon Communications, LLC ("Netgate")
    Differential Revision:  https://reviews.freebsd.org/D37603
---
 sys/net/if_ovpn.c | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/sys/net/if_ovpn.c b/sys/net/if_ovpn.c
index 256d7d56bada..6686315fbf01 100644
--- a/sys/net/if_ovpn.c
+++ b/sys/net/if_ovpn.c
@@ -122,6 +122,14 @@ struct ovpn_notification {
 
 struct ovpn_softc;
 
+struct ovpn_peer_counters {
+	uint64_t	pkt_in;
+	uint64_t	pkt_out;
+	uint64_t	bytes_in;
+	uint64_t	bytes_out;
+};
+#define OVPN_PEER_COUNTER_SIZE (sizeof(struct ovpn_peer_counters)/sizeof(uint64_t))
+
 struct ovpn_kpeer {
 	RB_ENTRY(ovpn_kpeer)	 tree;
 	int			 refcount;
@@ -142,6 +150,8 @@ struct ovpn_kpeer {
 	uint32_t		*last_active;
 	struct callout		 ping_send;
 	struct callout		 ping_rcv;
+
+	counter_u64_t		 counters[OVPN_PEER_COUNTER_SIZE];
 };
 
 struct ovpn_counters {
@@ -219,6 +229,9 @@ VNET_DEFINE_STATIC(struct if_clone *, ovpn_cloner);
 #define OVPN_COUNTER_ADD(sc, name, val)	\
 	counter_u64_add(sc->counters[offsetof(struct ovpn_counters, name) / \
 	    sizeof(uint64_t)], val)
+#define OVPN_PEER_COUNTER_ADD(p, name, val)	\
+	counter_u64_add(p->counters[offsetof(struct ovpn_peer_counters, name) / \
+	    sizeof(uint64_t)], val)
 
 #define TO_IN(x)		((struct sockaddr_in *)(x))
 #define TO_IN6(x)		((struct sockaddr_in6 *)(x))
@@ -499,6 +512,7 @@ ovpn_new_peer(struct ifnet *ifp, const nvlist_t *nvl)
 	peer->tx_seq = 1;
 	peer->refcount = 1;
 	peer->last_active = uma_zalloc_pcpu(pcpu_zone_4, M_WAITOK | M_ZERO);
+	COUNTER_ARRAY_ALLOC(peer->counters, OVPN_PEER_COUNTER_SIZE, M_WAITOK);
 
 	if (nvlist_exists_binary(nvl, "vpn_ipv4")) {
 		size_t len;
@@ -606,6 +620,7 @@ error_locked:
 	OVPN_WUNLOCK(sc);
 error:
 	free(name, M_SONAME);
+	COUNTER_ARRAY_FREE(peer->counters, OVPN_PEER_COUNTER_SIZE);
 	uma_zfree_pcpu(pcpu_zone_4, peer->last_active);
 	free(peer, M_OVPN);
 done:
@@ -1404,6 +1419,8 @@ ovpn_finish_rx(struct ovpn_softc *sc, struct mbuf *m,
 
 	OVPN_COUNTER_ADD(sc, received_data_pkts, 1);
 	OVPN_COUNTER_ADD(sc, tunnel_bytes_received, m->m_pkthdr.len);
+	OVPN_PEER_COUNTER_ADD(peer, pkt_in, 1);
+	OVPN_PEER_COUNTER_ADD(peer, bytes_in, m->m_pkthdr.len);
 
 	/* Receive the packet on our interface. */
 	m->m_pkthdr.rcvif = sc->ifp;
@@ -1740,6 +1757,9 @@ ovpn_transmit_to_peer(struct ifnet *ifp, struct mbuf *m,
 	seq = htonl(seq);
 	ohdr->seq = seq;
 
+	OVPN_PEER_COUNTER_ADD(peer, pkt_out, 1);
+	OVPN_PEER_COUNTER_ADD(peer, bytes_out, len);
+
 	if (key->encrypt->cipher == OVPN_CIPHER_ALG_NONE) {
 		ret = ovpn_encap(sc, peer->peerid, m);
 		if (_ovpn_lock_trackerp != NULL)