From patchwork Mon Dec 5 16:41:00 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kristof Provost X-Patchwork-Id: 2886 Return-Path: Delivered-To: patchwork@openvpn.net Received: by 2002:a05:622a:418d:b0:3a5:7962:c21f with SMTP id cd13csp1984087qtb; Mon, 5 Dec 2022 09:44:23 -0800 (PST) X-Google-Smtp-Source: AA0mqf7JygOXLur/86qjOMBMyrVad9KznpQSdNWvXDAEkRp7mNeEYtEwiFa05AAoU6cOuBBjC7MD X-Received: by 2002:a17:903:186:b0:189:e149:a1ae with SMTP id z6-20020a170903018600b00189e149a1aemr2824018plg.72.1670262262797; Mon, 05 Dec 2022 09:44:22 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1670262262; cv=none; d=google.com; s=arc-20160816; b=ByuxBOd2OtIa1FMto+9GwmmzqITpgiOqdGf3ZbjfKoVr9w8EaaNRQWBQJFs8wSlyya vyoT8c2UQew5hlKAJqmghkqRtfsv3mYqTDx3V+Ncr3VGBLXwGL+PXRWBy7KMwnTI3wzY zWm0ANKiVKyiJCsbGn/rREQKf6kveCtNoFmyvcb7WvKdpE96m1IzSSHCgi98Nu3yvVuX JkK/4QtL1wwjUH6mwY6AwRfigeZ6allsodakHP3CCx0GwhYM51TpkO12GxIGp4Lis2rd fR24N35TTmpuDo93x/tRJLKYVRkJJDr0+CBYgTHy2r0dgGKJFBYeqRwtiSxmt9iWNbwv VVtQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=errors-to:content-transfer-encoding:reply-to:from:list-subscribe :list-help:list-post:list-archive:list-unsubscribe:list-id :precedence:subject:mime-version:references:in-reply-to:message-id :date:to:dkim-signature:dkim-signature:dkim-signature; bh=+ozOHnh2JxZvLLdI/xas/f/2uxTgZ2gRMdO1pQt7ea8=; b=QcX9iyUVD8tNpfe98Q8jCog+CkydoW7YFYRrwoHxetPJIulAInSa9AqBaMEBUmN9iR 708kSluVE1GCrUyktR516uZlWVcWdxqyuKzxDe/0NIfeshoiDv8lf6mprutkNPnsz6eR z7QpPKXNnxQSe43f0fmo3cqY+BvlEJZyzmcLJOflK9fvD/1j0VEnN22p08Hpa9vsSD3L bXf9dMippWkE9GMhW16hVrxBXL6atC29X8QiFXVxRu6+TmVYTdmkPT5Ua1sWr949Ki8+ PBegHFYXkwMHwvnh9eTWqeSClb4cIvNfB83XN2PoXgy6mPHcdlj2rZ3jwQdCaYcikIz9 zipA== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=OEvF4QaH; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=gFudvMVZ; dkim=neutral (body hash did not verify) header.i=@netgate.com header.s=google header.b=Yxi+m1oV; spf=pass (google.com: domain of openvpn-devel-bounces@lists.sourceforge.net designates 216.105.38.7 as permitted sender) smtp.mailfrom=openvpn-devel-bounces@lists.sourceforge.net; dmarc=pass (p=QUARANTINE sp=NONE dis=NONE) header.from=sourceforge.net Received: from lists.sourceforge.net (lists.sourceforge.net. [216.105.38.7]) by mx.google.com with ESMTPS id p39-20020a056a000a2700b0056cb4662b9csi16273720pfh.16.2022.12.05.09.44.22 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Mon, 05 Dec 2022 09:44:22 -0800 (PST) Received-SPF: pass (google.com: domain of openvpn-devel-bounces@lists.sourceforge.net designates 216.105.38.7 as permitted sender) client-ip=216.105.38.7; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=OEvF4QaH; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=gFudvMVZ; dkim=neutral (body hash did not verify) header.i=@netgate.com header.s=google header.b=Yxi+m1oV; spf=pass (google.com: domain of openvpn-devel-bounces@lists.sourceforge.net designates 216.105.38.7 as permitted sender) smtp.mailfrom=openvpn-devel-bounces@lists.sourceforge.net; dmarc=pass (p=QUARANTINE sp=NONE dis=NONE) header.from=sourceforge.net Received: from [127.0.0.1] (helo=sfs-ml-1.v29.lw.sourceforge.com) by sfs-ml-1.v29.lw.sourceforge.com with esmtp (Exim 4.95) (envelope-from ) id 1p2FUy-0001I2-7n; Mon, 05 Dec 2022 17:43:24 +0000 Received: from [172.30.20.202] (helo=mx.sourceforge.net) by sfs-ml-1.v29.lw.sourceforge.com with esmtps (TLS1.2) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.95) (envelope-from ) id 1p2FUw-0001Hw-ON for openvpn-devel@lists.sourceforge.net; Mon, 05 Dec 2022 17:43:22 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sourceforge.net; s=x; h=Content-Transfer-Encoding:MIME-Version:References: In-Reply-To:Message-Id:Date:Subject:To:From:Sender:Reply-To:Cc:Content-Type: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=z0BSUrxRbYU1z9GrIWvD2IC2EGzqURpyG6MLJ0cUo+Q=; b=OEvF4QaHmNAMUVI52FQ4Ogw5OW 3ktH9IAK0Quk5u/AjPEDUmJYr4RfgJcY16+GxQBfpFz/skWn5PLtdlLdZ1Cv4PWsMv8dYIHYBcXj/ DM9GF7/qBJNFE94jkHF5tb/us1d3ZRbO44RBgM/zFpCD6zk2K3choNRK2zi1RP3hrfik=; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sf.net; s=x ; h=Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-Id: Date:Subject:To:From:Sender:Reply-To:Cc:Content-Type:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=z0BSUrxRbYU1z9GrIWvD2IC2EGzqURpyG6MLJ0cUo+Q=; b=gFudvMVZiyKt3mN+tPvbtQQz3P B5f3VysRy0wcB8tDJLTQigOVzNWaIsYaoOR5vTWMCJG/VvWA865YPoQS7X/cM/AlxvQkYKyNAD/Qi DHs5+tdfYG+YqWcfelP1oj6vZeVTDOL40gVkOf/E/EF5nPnwQmytWQrrwjl9fAUDPfuo=; Received: from mail-ej1-f43.google.com ([209.85.218.43]) by sfi-mx-2.v28.lw.sourceforge.com with esmtps (TLS1.2:ECDHE-RSA-AES128-GCM-SHA256:128) (Exim 4.95) id 1p2FUu-0004Iu-3c for openvpn-devel@lists.sourceforge.net; Mon, 05 Dec 2022 17:43:22 +0000 Received: by mail-ej1-f43.google.com with SMTP id fc4so236753ejc.12 for ; Mon, 05 Dec 2022 09:43:20 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=netgate.com; s=google; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=z0BSUrxRbYU1z9GrIWvD2IC2EGzqURpyG6MLJ0cUo+Q=; b=Yxi+m1oVClIwyCLjAOk2W/0Ja9pamAEN4vMUu8D5hNl0UVRKiKklfVhlATEByiUpfw OTwuqIpCXwtAjgYQ60cADpp85UINhRUBxIyYteukKUQZ+IRCpzk0Qo3Jbg4Hjdes3LUq j5v7VDUVHbhrMLdlWjNXrgJErvtZrwsQw+C4U= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=z0BSUrxRbYU1z9GrIWvD2IC2EGzqURpyG6MLJ0cUo+Q=; b=ElaiOmqiBWjbe5kBBL0JtPFEM6X3iyQMsXcafUteHD8IBvrjDHT1/umwYtXDQuINOv xy+wYY+1ykUA5+SvB+9XibP+CMIB+wO9Qtakntn+BHlEgpjKPtkjvCHBcDM8HI8Ffw8t nWvBdbFNPc7vxQkFl6Ia5Bi49qfwPaOUp2ExXVCUHgioR9s4IpQPseUcpUNDmj4a/SLH AT1vYzhl68621M6jEuarU518xXDTHrjIx621q28hr//22RiJuYNTb9KwAQQBOnKC8uPb H/S8T6d1Hay5gFyxfKikA66j3S/1TlJx93uopblV/AfYbEhI0ylYfhxCo3RfpQEAzBjp 0KJw== X-Gm-Message-State: ANoB5pnlqT3aQGzck8Ml0aP1rf9yoF2Thp/0cjTS5oZ2PRnWJBf0xT7c 7jF2X5zoTZgIYdEVf9rUEGSgswCALGmemVhB X-Received: by 2002:aa7:d417:0:b0:46b:203:f389 with SMTP id z23-20020aa7d417000000b0046b0203f389mr35457487edq.303.1670258466786; Mon, 05 Dec 2022 08:41:06 -0800 (PST) Received: from nut.jupiter.sigsegv.be (ptr-8rfalzsse26o3oo9imw.18120a2.ip6.access.telenet.be. [2a02:1811:2402:bf00:f602:70ff:feae:6e98]) by smtp.googlemail.com with ESMTPSA id 1-20020a170906310100b0073ae9ba9ba8sm6389266ejx.3.2022.12.05.08.41.06 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 05 Dec 2022 08:41:06 -0800 (PST) To: openvpn-devel Date: Mon, 5 Dec 2022 17:41:00 +0100 Message-Id: <20221205164103.9190-2-kprovost@netgate.com> X-Mailer: git-send-email 2.38.1 In-Reply-To: <20221205164103.9190-1-kprovost@netgate.com> References: <20221205164103.9190-1-kprovost@netgate.com> MIME-Version: 1.0 X-Spam-Score: -0.2 (/) X-Spam-Report: Spam detection software, running on the system "util-spamd-2.v13.lw.sourceforge.com", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: From: Kristof Provost When DCO is active userspace doesn't see all of the traffic, so when we access these stats we must update them. Retrieve kernel statistics every time we access the link_(read|write)_bytes values. Content analysis details: (-0.2 points, 6.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [209.85.218.43 listed in list.dnswl.org] -0.0 RCVD_IN_MSPIKE_H2 RBL: Average reputation (+2) [209.85.218.43 listed in wl.mailspike.net] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.0 SPF_PASS SPF: sender matches SPF record 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain X-Headers-End: 1p2FUu-0004Iu-3c Subject: [Openvpn-devel] [PATCH 1/4] Read DCO traffic stats from the kernel X-BeenThere: openvpn-devel@lists.sourceforge.net X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Kristof Provost via Openvpn-devel From: Kristof Provost Reply-To: Kristof Provost Errors-To: openvpn-devel-bounces@lists.sourceforge.net X-getmail-retrieved-from-mailbox: Inbox X-GMAIL-THRID: =?utf-8?q?1751396922461180716?= X-GMAIL-MSGID: =?utf-8?q?1751396922461180716?= From: Kristof Provost When DCO is active userspace doesn't see all of the traffic, so when we access these stats we must update them. Retrieve kernel statistics every time we access the link_(read|write)_bytes values. Introduce a dco_(read|write)_bytes so that we don't clobber the existing statistics, which still count control packets, sent or received directly through the socket. Signed-off-by: Kristof Provost Acked-by: Antonio Quartulli --- src/openvpn/dco.h | 8 ++++ src/openvpn/dco_freebsd.c | 78 ++++++++++++++++++++++++++++++++++ src/openvpn/dco_linux.c | 7 +++ src/openvpn/dco_win.c | 7 +++ src/openvpn/multi.c | 30 +++++++------ src/openvpn/openvpn.h | 2 + src/openvpn/ovpn_dco_freebsd.h | 1 + 7 files changed, 120 insertions(+), 13 deletions(-) diff --git a/src/openvpn/dco.h b/src/openvpn/dco.h index e051db06..e5d89358 100644 --- a/src/openvpn/dco.h +++ b/src/openvpn/dco.h @@ -225,6 +225,14 @@ void dco_install_iroute(struct multi_context *m, struct multi_instance *mi, */ void dco_delete_iroutes(struct multi_context *m, struct multi_instance *mi); +/** + * Update traffic statistics for all peers + * + * @param dco DCO device context + * @param m the server context + **/ +int dco_get_peer_stats(dco_context_t *dco, struct multi_context *m); + /** * Retrieve the list of ciphers supported by the current platform * diff --git a/src/openvpn/dco_freebsd.c b/src/openvpn/dco_freebsd.c index a52ac8c1..5b352859 100644 --- a/src/openvpn/dco_freebsd.c +++ b/src/openvpn/dco_freebsd.c @@ -37,6 +37,7 @@ #include "dco.h" #include "tun.h" #include "crypto.h" +#include "multi.h" #include "ssl_common.h" static nvlist_t * @@ -641,6 +642,83 @@ dco_event_set(dco_context_t *dco, struct event_set *es, void *arg) nvlist_destroy(nvl); } +static void +dco_update_peer_stat(struct multi_context *m, uint32_t peerid, const nvlist_t *nvl) +{ + struct hash_element *he; + struct hash_iterator hi; + + hash_iterator_init(m->hash, &hi); + + while ((he = hash_iterator_next(&hi))) + { + struct multi_instance *mi = (struct multi_instance *) he->value; + + if (mi->context.c2.tls_multi->peer_id != peerid) + continue; + + mi->context.c2.dco_read_bytes = nvlist_get_number(nvl, "in"); + mi->context.c2.dco_write_bytes = nvlist_get_number(nvl, "out"); + + return; + } + + msg(M_INFO, "Peer %d returned by kernel, but not found locally", peerid); +} + +int +dco_get_peer_stats(dco_context_t *dco, struct multi_context *m) +{ + + struct ifdrv drv; + uint8_t buf[4096]; + nvlist_t *nvl; + const nvlist_t *const *nvpeers; + size_t npeers; + int ret; + + if (!dco || !dco->open) + { + return 0; + } + + CLEAR(drv); + snprintf(drv.ifd_name, IFNAMSIZ, "%s", dco->ifname); + drv.ifd_cmd = OVPN_GET_PEER_STATS; + drv.ifd_len = sizeof(buf); + drv.ifd_data = buf; + + ret = ioctl(dco->fd, SIOCGDRVSPEC, &drv); + if (ret) + { + msg(M_WARN | M_ERRNO, "Failed to get peer stats"); + return -EINVAL; + } + + nvl = nvlist_unpack(buf, drv.ifd_len, 0); + if (! nvl) + { + msg(M_WARN, "Failed to unpack nvlist"); + return -EINVAL; + } + + if (! nvlist_exists_nvlist_array(nvl, "peers")) { + /* no peers */ + return 0; + } + + nvpeers = nvlist_get_nvlist_array(nvl, "peers", &npeers); + for (size_t i = 0; i < npeers; i++) + { + const nvlist_t *peer = nvpeers[i]; + uint32_t peerid = nvlist_get_number(peer, "peerid"); + + dco_update_peer_stat(m, peerid, nvlist_get_nvlist(peer, "bytes")); + } + + return 0; +} + const char * dco_get_supported_ciphers() { diff --git a/src/openvpn/dco_linux.c b/src/openvpn/dco_linux.c index 10935820..0306cec3 100644 --- a/src/openvpn/dco_linux.c +++ b/src/openvpn/dco_linux.c @@ -911,6 +911,13 @@ nla_put_failure: return ret; } +int +dco_get_peer_stats(dco_context_t *dco, struct multi_context *m) +{ + /* Not implemented. */ + return 0; +} + bool dco_available(int msglevel) { diff --git a/src/openvpn/dco_win.c b/src/openvpn/dco_win.c index 48a1755a..68ec931c 100644 --- a/src/openvpn/dco_win.c +++ b/src/openvpn/dco_win.c @@ -399,6 +399,13 @@ dco_do_write(dco_context_t *dco, int peer_id, struct buffer *buf) return 0; } +int +dco_get_peer_stats(dco_context_t *dco, struct multi_context *m) +{ + /* Not implemented. */ + return 0; +} + void dco_event_set(dco_context_t *dco, struct event_set *es, void *arg) { diff --git a/src/openvpn/multi.c b/src/openvpn/multi.c index 0a23c2bc..38da87b8 100644 --- a/src/openvpn/multi.c +++ b/src/openvpn/multi.c @@ -538,29 +538,31 @@ multi_del_iroutes(struct multi_context *m, } static void -setenv_stats(struct context *c) +setenv_stats(struct multi_context *m, struct context *c) { - setenv_counter(c->c2.es, "bytes_received", c->c2.link_read_bytes); - setenv_counter(c->c2.es, "bytes_sent", c->c2.link_write_bytes); + dco_get_peer_stats(&m->top.c1.tuntap->dco, m); + + setenv_counter(c->c2.es, "bytes_received", c->c2.link_read_bytes + c->c2.dco_read_bytes); + setenv_counter(c->c2.es, "bytes_sent", c->c2.link_write_bytes + c->c2.dco_write_bytes); } static void -multi_client_disconnect_setenv(struct multi_instance *mi) +multi_client_disconnect_setenv(struct multi_context *m, struct multi_instance *mi) { /* setenv client real IP address */ setenv_trusted(mi->context.c2.es, get_link_socket_info(&mi->context)); /* setenv stats */ - setenv_stats(&mi->context); + setenv_stats(m, &mi->context); /* setenv connection duration */ setenv_long_long(mi->context.c2.es, "time_duration", now - mi->created); } static void -multi_client_disconnect_script(struct multi_instance *mi) +multi_client_disconnect_script(struct multi_context *m, struct multi_instance *mi) { - multi_client_disconnect_setenv(mi); + multi_client_disconnect_setenv(m, mi); if (plugin_defined(mi->context.plugins, OPENVPN_PLUGIN_CLIENT_DISCONNECT)) { @@ -667,7 +669,7 @@ multi_close_instance(struct multi_context *m, if (mi->context.c2.tls_multi->multi_state >= CAS_CONNECT_DONE) { - multi_client_disconnect_script(mi); + multi_client_disconnect_script(m, mi); } close_context(&mi->context, SIGTERM, CC_GC_FREE); @@ -837,6 +839,8 @@ multi_print_status(struct multi_context *m, struct status_output *so, const int status_reset(so); + dco_get_peer_stats(&m->top.c1.tuntap->dco, m); + if (version == 1) { /* @@ -856,8 +860,8 @@ multi_print_status(struct multi_context *m, struct status_output *so, const int status_printf(so, "%s,%s," counter_format "," counter_format ",%s", tls_common_name(mi->context.c2.tls_multi, false), mroute_addr_print(&mi->real, &gc), - mi->context.c2.link_read_bytes, - mi->context.c2.link_write_bytes, + mi->context.c2.link_read_bytes + mi->context.c2.dco_read_bytes, + mi->context.c2.link_write_bytes + mi->context.c2.dco_write_bytes, time_string(mi->created, 0, false, &gc)); } gc_free(&gc); @@ -932,8 +936,8 @@ multi_print_status(struct multi_context *m, struct status_output *so, const int sep, mroute_addr_print(&mi->real, &gc), sep, print_in_addr_t(mi->reporting_addr, IA_EMPTY_IF_UNDEF, &gc), sep, print_in6_addr(mi->reporting_addr_ipv6, IA_EMPTY_IF_UNDEF, &gc), - sep, mi->context.c2.link_read_bytes, - sep, mi->context.c2.link_write_bytes, + sep, mi->context.c2.link_read_bytes + mi->context.c2.dco_read_bytes, + sep, mi->context.c2.link_write_bytes + mi->context.c2.dco_write_bytes, sep, time_string(mi->created, 0, false, &gc), sep, (unsigned int)mi->created, sep, tls_username(mi->context.c2.tls_multi, false), @@ -2752,7 +2756,7 @@ multi_connection_established(struct multi_context *m, struct multi_instance *mi) * did not fail */ if (mi->context.c2.tls_multi->multi_state == CAS_PENDING_DEFERRED_PARTIAL) { - multi_client_disconnect_script(mi); + multi_client_disconnect_script(m, mi); } mi->context.c2.tls_multi->multi_state = CAS_FAILED; diff --git a/src/openvpn/openvpn.h b/src/openvpn/openvpn.h index c543cbf6..5981e4d5 100644 --- a/src/openvpn/openvpn.h +++ b/src/openvpn/openvpn.h @@ -267,8 +267,10 @@ struct context_2 counter_type tun_read_bytes; counter_type tun_write_bytes; counter_type link_read_bytes; + counter_type dco_read_bytes; counter_type link_read_bytes_auth; counter_type link_write_bytes; + counter_type dco_write_bytes; #ifdef PACKET_TRUNCATION_CHECK counter_type n_trunc_tun_read; counter_type n_trunc_tun_write; diff --git a/src/openvpn/ovpn_dco_freebsd.h b/src/openvpn/ovpn_dco_freebsd.h index cf92d597..cc90111e 100644 --- a/src/openvpn/ovpn_dco_freebsd.h +++ b/src/openvpn/ovpn_dco_freebsd.h @@ -61,5 +61,6 @@ enum ovpn_key_cipher { #define OVPN_POLL_PKT _IO('D', 10) #define OVPN_GET_PKT _IO('D', 11) #define OVPN_SET_IFMODE _IO('D', 12) +#define OVPN_GET_PEER_STATS _IO('D', 13) #endif /* ifndef _NET_IF_OVPN_H_ */