From patchwork Wed Mar 22 19:27:57 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Antonio Quartulli X-Patchwork-Id: 3154 Return-Path: Delivered-To: patchwork@openvpn.net Received: by 2002:a05:7300:2310:b0:9f:bfa4:120f with SMTP id r16csp3452713dye; Wed, 22 Mar 2023 12:28:50 -0700 (PDT) X-Google-Smtp-Source: AK7set9YpSg8I0hfv5OM/GSSryPdlRlT3HVzvLUWRnMmL8ey6thxrM8eEwcBGkgOAhdCnGgFxJxV X-Received: by 2002:a17:902:e54f:b0:1a0:4531:af58 with SMTP id n15-20020a170902e54f00b001a04531af58mr4410191plf.63.1679513330442; Wed, 22 Mar 2023 12:28:50 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1679513330; cv=none; d=google.com; s=arc-20160816; b=0ZVxwt5b3crzpl5RVogxTFSLL/SCkAC5kTNyrkTlhWXEX+JUFfuDX9J8zbYtFwK26y win1k+EhW99TOGe5fgG2j4IpkeZsosulFpVIwQSYtMgHDNseFApBYHHdIIKGAXQWHFE0 cXvet2t3BT61kGvfadv1dVEB+BppTImUTaf8oSAmxO7zvRMPpV4oMLPyVareXT1YggH9 xAEobHyltKzZUOvx7kfjkxUoTK3j2WXqifTag7bGHmmjDy5G3MQ+7gL/ojjOdP97JcUX ccWRLE7NSy5uOdMhlJZWcji/RWu+hitQhhv7epblVScwXugXR1eXE7r6oihi0MAUa/Ln RkGQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=errors-to:content-transfer-encoding:cc:list-subscribe:list-help :list-post:list-archive:list-unsubscribe:list-id:precedence:subject :mime-version:message-id:date:to:from:dkim-signature:dkim-signature :dkim-signature; bh=1lC1g0fcNbzOtN8dCrdrWrbYX/XLcRr/3lxmJCeJ5p8=; b=UuCGedXqiOhypl0B2TfFtnaIs4E9yNyWOv/VlWfgL9lbl0dGPPkkdGaO9DBft65/hO uS+VvxyRnax0yLZD+bt21i8544bwyORqJW+6GcNh+h2rsdm7FbwHGCJpLEliPyqlNBVD IqLE/L46ms07FxdUlsX1bYIjP5kBtgFxgFvjHkjuML8TsTyH3W92EvgL1lNTC9pc7DQf UVChs4eGGGZ5+ltcDKXGGXVbpfslsPrZre0SkyCNSktlfxi0cNL1R73WXaHsL0WIsD7x DIGSBJvh74YTRDh8Te2YiGtonRJw+rSyghY/1iabm28F6STiCvYlpNsS9QYtdUZbw7l5 2hPA== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b="bcTtQCl/"; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=QjdJFzk8; dkim=fail header.i=@unstable.cc header.s=20220809-q8oc header.b=iUZZlYK6; 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 Received: from lists.sourceforge.net ([216.105.38.7]) by mx.google.com with ESMTPS id kx7-20020a170902f94700b0019c14335fc0si15586891plb.70.2023.03.22.12.28.50 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Wed, 22 Mar 2023 12:28:50 -0700 (PDT) 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="bcTtQCl/"; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=QjdJFzk8; dkim=fail header.i=@unstable.cc header.s=20220809-q8oc header.b=iUZZlYK6; 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 Received: from [127.0.0.1] (helo=sfs-ml-4.v29.lw.sourceforge.com) by sfs-ml-4.v29.lw.sourceforge.com with esmtp (Exim 4.95) (envelope-from ) id 1pf489-0006U1-D4; Wed, 22 Mar 2023 19:28:19 +0000 Received: from [172.30.20.202] (helo=mx.sourceforge.net) by sfs-ml-4.v29.lw.sourceforge.com with esmtps (TLS1.2) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.95) (envelope-from ) id 1pf488-0006Tr-0O for openvpn-devel@lists.sourceforge.net; Wed, 22 Mar 2023 19:28:18 +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:Message-Id: Date:Subject:Cc:To:From:Sender:Reply-To:Content-Type:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:In-Reply-To:References:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=PuuLPFBwx+6BHOYzzGqxw+tszjds2mGRW368xGBZS7o=; b=bcTtQCl/TN1XRqKOFXJT962ap4 h0QQdBJxB2ygbrqbXc8pEgr5fTEkrtTwCYX1rgXwoW0Er0BXGwtW5MSBgCg3cChCwQkTtPR/anI/p e/fUCET9rmxk8yOs94Wp8gbxxSFGFByYW/LeYhCyYQglkdTeashaZU3UKcMQFhCxPusw=; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sf.net; s=x ; h=Content-Transfer-Encoding:MIME-Version:Message-Id:Date:Subject:Cc:To:From :Sender:Reply-To:Content-Type:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To: References:List-Id:List-Help:List-Unsubscribe:List-Subscribe:List-Post: List-Owner:List-Archive; bh=PuuLPFBwx+6BHOYzzGqxw+tszjds2mGRW368xGBZS7o=; b=Q jdJFzk8NVLiMUvBs1nUWwIOv4fSoWb9J5udra+OSQnuwQN0xPABnuZTjrsUt3NJhMT5uSPjNBQp3k BJK1SPho+peQkiL3seR3/XyYz/iwe6zbZjX0PhNDFqkslFamH36HK1jC0BFHkihQYD1U+GnLeb3wd nX0AkYvqg6RO4DR4=; Received: from wilbur.contactoffice.com ([212.3.242.68]) by sfi-mx-2.v28.lw.sourceforge.com with esmtps (TLS1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.95) id 1pf484-0000hY-O7 for openvpn-devel@lists.sourceforge.net; Wed, 22 Mar 2023 19:28:17 +0000 Received: from smtpauth2.co-bxl (smtpauth2.co-bxl [10.2.0.24]) by wilbur.contactoffice.com (Postfix) with ESMTP id 2578B2037; Wed, 22 Mar 2023 20:28:06 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; t=1679513286; s=20220809-q8oc; d=unstable.cc; i=a@unstable.cc; h=From:To:Cc:Subject:Date:Message-Id:MIME-Version:Content-Transfer-Encoding; l=9849; bh=PuuLPFBwx+6BHOYzzGqxw+tszjds2mGRW368xGBZS7o=; b=iUZZlYK6X9Qc9WbKjAD0KZmO6TRiCJ5OtEGj/ESW69+7u5qj6mIrMhcCHEdRK/jD apS+fgWEOImfJFCt85XTN8fUrosAH8ea0pNQoJ5iG/DAW3nnknBavUQL2qxCCyINlp7 9EYgKYHPBaOOdh4l9d0O+IROQqx9wEccL/jbXkPl2XDHC9JxqTNkBUlGslezStgs39Z 9KXNuhwTlm3vmI0aXcewEUZceKRjpqxxE0v1cX31vFbfxO9nrAbOw276nW+s9uOW7aD qYPUv+e5+HGWZoLjtqIVPyNmWiQdhV+WIyOMhmEkkTCalv08nE/BB/ajjUpAJ3kAkne t5Cyekx4RQ== Received: by smtp.mailfence.com with ESMTPSA ; Wed, 22 Mar 2023 20:28:01 +0100 (CET) From: Antonio Quartulli To: openvpn-devel@lists.sourceforge.net Date: Wed, 22 Mar 2023 20:27:57 +0100 Message-Id: <20230322192757.20767-1-a@unstable.cc> X-Mailer: git-send-email 2.39.2 MIME-Version: 1.0 X-Spam-Flag: NO X-Spam-Status: No, hits=-2.9 required=4.7 symbols=ALL_TRUSTED, BAYES_00 device=10.2.0.20 X-ContactOffice-Account: com:375058688 X-Spam-Score: -0.9 (/) X-Spam-Report: Spam detection software, running on the system "util-spamd-1.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: With this API it is possible to retrieve the stats for a specific peer or for all peers and then update the userspace counters with the value reported by DCO. Change-Id: Ia3990b86b1be7ca844fb1674b39ce0d60528ccff Signed-off-by: Antonio Quartulli --- Content analysis details: (-0.9 points, 6.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.7 RCVD_IN_DNSWL_LOW RBL: Sender listed at https://www.dnswl.org/, low trust [212.3.242.68 listed in list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain X-Headers-End: 1pf484-0000hY-O7 Subject: [Openvpn-devel] [PATCH v4] dco-linux: implement dco_get_peer_stats{, multi} API 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: , Cc: Antonio Quartulli Errors-To: openvpn-devel-bounces@lists.sourceforge.net X-getmail-retrieved-from-mailbox: Inbox X-GMAIL-THRID: =?utf-8?q?1760930818475245873?= X-GMAIL-MSGID: =?utf-8?q?1761097369713906437?= With this API it is possible to retrieve the stats for a specific peer or for all peers and then update the userspace counters with the value reported by DCO. Change-Id: Ia3990b86b1be7ca844fb1674b39ce0d60528ccff Signed-off-by: Antonio Quartulli Acked-by: Gert Doering --- Changes from v1: * use m->instances[] instead of iterating over m->hash Changes from v2: * added boundary check on peer-id Changes from v3: * use one check only instead of two --- src/openvpn/dco_linux.c | 183 ++++++++++++++++++++++++++++++++--- src/openvpn/ovpn_dco_linux.h | 14 ++- 2 files changed, 179 insertions(+), 18 deletions(-) diff --git a/src/openvpn/dco_linux.c b/src/openvpn/dco_linux.c index 47961849..317f9dc0 100644 --- a/src/openvpn/dco_linux.c +++ b/src/openvpn/dco_linux.c @@ -41,6 +41,7 @@ #include "tun.h" #include "ssl.h" #include "fdmisc.h" +#include "multi.h" #include "ssl_verify.h" #include "ovpn_dco_linux.h" @@ -168,16 +169,17 @@ ovpn_nl_recvmsgs(dco_context_t *dco, const char *prefix) * @param dco The dco context to use * @param nl_msg the message to use * @param cb An optional callback if the caller expects an answer + * @param cb_arg An optional param to pass to the callback * @param prefix A prefix to report in the error message to give the user context * @return status of sending the message */ static int ovpn_nl_msg_send(dco_context_t *dco, struct nl_msg *nl_msg, ovpn_nl_cb cb, - const char *prefix) + void *cb_arg, const char *prefix) { dco->status = 1; - nl_cb_set(dco->nl_cb, NL_CB_VALID, NL_CB_CUSTOM, cb, dco); + nl_cb_set(dco->nl_cb, NL_CB_VALID, NL_CB_CUSTOM, cb, cb_arg); nl_send_auto(dco->nl_sock, nl_msg); while (dco->status == 1) @@ -268,7 +270,7 @@ dco_new_peer(dco_context_t *dco, unsigned int peerid, int sd, } nla_nest_end(nl_msg, attr); - ret = ovpn_nl_msg_send(dco, nl_msg, NULL, __func__); + ret = ovpn_nl_msg_send(dco, nl_msg, NULL, NULL, __func__); nla_put_failure: nlmsg_free(nl_msg); @@ -489,7 +491,7 @@ dco_swap_keys(dco_context_t *dco, unsigned int peerid) NLA_PUT_U32(nl_msg, OVPN_SWAP_KEYS_ATTR_PEER_ID, peerid); nla_nest_end(nl_msg, attr); - ret = ovpn_nl_msg_send(dco, nl_msg, NULL, __func__); + ret = ovpn_nl_msg_send(dco, nl_msg, NULL, NULL, __func__); nla_put_failure: nlmsg_free(nl_msg); @@ -513,7 +515,7 @@ dco_del_peer(dco_context_t *dco, unsigned int peerid) NLA_PUT_U32(nl_msg, OVPN_DEL_PEER_ATTR_PEER_ID, peerid); nla_nest_end(nl_msg, attr); - ret = ovpn_nl_msg_send(dco, nl_msg, NULL, __func__); + ret = ovpn_nl_msg_send(dco, nl_msg, NULL, NULL, __func__); nla_put_failure: nlmsg_free(nl_msg); @@ -539,7 +541,7 @@ dco_del_key(dco_context_t *dco, unsigned int peerid, NLA_PUT_U8(nl_msg, OVPN_DEL_KEY_ATTR_KEY_SLOT, slot); nla_nest_end(nl_msg, attr); - ret = ovpn_nl_msg_send(dco, nl_msg, NULL, __func__); + ret = ovpn_nl_msg_send(dco, nl_msg, NULL, NULL, __func__); nla_put_failure: nlmsg_free(nl_msg); @@ -596,7 +598,7 @@ dco_new_key(dco_context_t *dco, unsigned int peerid, int keyid, nla_nest_end(nl_msg, attr); - ret = ovpn_nl_msg_send(dco, nl_msg, NULL, __func__); + ret = ovpn_nl_msg_send(dco, nl_msg, NULL, NULL, __func__); nla_put_failure: nlmsg_free(nl_msg); @@ -625,7 +627,7 @@ dco_set_peer(dco_context_t *dco, unsigned int peerid, keepalive_timeout); nla_nest_end(nl_msg, attr); - ret = ovpn_nl_msg_send(dco, nl_msg, NULL, __func__); + ret = ovpn_nl_msg_send(dco, nl_msg, NULL, NULL, __func__); nla_put_failure: nlmsg_free(nl_msg); @@ -706,7 +708,7 @@ ovpn_get_mcast_id(dco_context_t *dco) int ret = -EMSGSIZE; NLA_PUT_STRING(nl_msg, CTRL_ATTR_FAMILY_NAME, OVPN_NL_NAME); - ret = ovpn_nl_msg_send(dco, nl_msg, mcast_family_handler, __func__); + ret = ovpn_nl_msg_send(dco, nl_msg, mcast_family_handler, dco, __func__); nla_put_failure: nlmsg_free(nl_msg); @@ -819,18 +821,173 @@ dco_do_read(dco_context_t *dco) return ovpn_nl_recvmsgs(dco, __func__); } +static void +dco_update_peer_stat(struct context_2 *c2, struct nlattr *tb[], uint32_t id) +{ + if (tb[OVPN_GET_PEER_RESP_ATTR_LINK_RX_BYTES]) + { + c2->dco_read_bytes = nla_get_u64(tb[OVPN_GET_PEER_RESP_ATTR_LINK_RX_BYTES]); + msg(D_DCO_DEBUG, "%s / dco_read_bytes: %lu", __func__, + c2->dco_read_bytes); + } + else + { + msg(M_WARN, "%s: no link RX bytes provided in reply for peer %u", + __func__, id); + } + + if (tb[OVPN_GET_PEER_RESP_ATTR_LINK_TX_BYTES]) + { + c2->dco_write_bytes = nla_get_u64(tb[OVPN_GET_PEER_RESP_ATTR_LINK_TX_BYTES]); + msg(D_DCO_DEBUG, "%s / dco_write_bytes: %lu", __func__, + c2->dco_write_bytes); + } + else + { + msg(M_WARN, "%s: no link TX bytes provided in reply for peer %u", + __func__, id); + } + + if (tb[OVPN_GET_PEER_RESP_ATTR_VPN_RX_BYTES]) + { + c2->tun_read_bytes = nla_get_u64(tb[OVPN_GET_PEER_RESP_ATTR_VPN_RX_BYTES]); + msg(D_DCO_DEBUG, "%s / tun_read_bytes: %lu", __func__, + c2->tun_read_bytes); + } + else + { + msg(M_WARN, "%s: no VPN RX bytes provided in reply for peer %u", + __func__, id); + } + + if (tb[OVPN_GET_PEER_RESP_ATTR_VPN_TX_BYTES]) + { + c2->tun_write_bytes = nla_get_u64(tb[OVPN_GET_PEER_RESP_ATTR_VPN_TX_BYTES]); + msg(D_DCO_DEBUG, "%s / tun_write_bytes: %lu", __func__, + c2->tun_write_bytes); + } + else + { + msg(M_WARN, "%s: no VPN TX bytes provided in reply for peer %u", + __func__, id); + } +} + +int +dco_parse_peer_multi(struct nl_msg *msg, void *arg) +{ + struct nlattr *tb[OVPN_ATTR_MAX + 1]; + struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); + + msg(D_DCO_DEBUG, "%s: parsing message...", __func__); + + nla_parse(tb, OVPN_ATTR_MAX, genlmsg_attrdata(gnlh, 0), + genlmsg_attrlen(gnlh, 0), NULL); + + if (!tb[OVPN_ATTR_GET_PEER]) + { + return NL_SKIP; + } + + struct nlattr *tb_peer[OVPN_GET_PEER_RESP_ATTR_MAX + 1]; + + nla_parse(tb_peer, OVPN_GET_PEER_RESP_ATTR_MAX, + nla_data(tb[OVPN_ATTR_GET_PEER]), + nla_len(tb[OVPN_ATTR_GET_PEER]), NULL); + + if (!tb_peer[OVPN_GET_PEER_RESP_ATTR_PEER_ID]) + { + msg(M_WARN, "%s: no peer-id provided in reply", __func__); + return NL_SKIP; + } + + struct multi_context *m = arg; + uint32_t peer_id = nla_get_u32(tb_peer[OVPN_GET_PEER_RESP_ATTR_PEER_ID]); + + if (peer_id >= m->max_clients || !m->instances[peer_id]) + { + msg(M_WARN, "%s: cannot store DCO stats for peer %u", __func__, + peer_id); + return NL_SKIP; + } + + dco_update_peer_stat(&m->instances[peer_id]->context.c2, tb_peer, peer_id); + + return NL_OK; +} + int dco_get_peer_stats_multi(dco_context_t *dco, struct multi_context *m) { - /* Not implemented. */ - return 0; + msg(D_DCO_DEBUG, "%s", __func__); + + struct nl_msg *nl_msg = ovpn_dco_nlmsg_create(dco, OVPN_CMD_GET_PEER); + + nlmsg_hdr(nl_msg)->nlmsg_flags |= NLM_F_DUMP; + + return ovpn_nl_msg_send(dco, nl_msg, dco_parse_peer_multi, m, __func__); +} + +static int +dco_parse_peer(struct nl_msg *msg, void *arg) +{ + struct context *c = arg; + struct nlattr *tb[OVPN_ATTR_MAX + 1]; + struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); + + msg(D_DCO_DEBUG, "%s: parsing message...", __func__); + + nla_parse(tb, OVPN_ATTR_MAX, genlmsg_attrdata(gnlh, 0), + genlmsg_attrlen(gnlh, 0), NULL); + + if (!tb[OVPN_ATTR_GET_PEER]) + { + msg(D_DCO_DEBUG, "%s: malformed reply", __func__); + return NL_SKIP; + } + + struct nlattr *tb_peer[OVPN_GET_PEER_RESP_ATTR_MAX + 1]; + + nla_parse(tb_peer, OVPN_GET_PEER_RESP_ATTR_MAX, + nla_data(tb[OVPN_ATTR_GET_PEER]), + nla_len(tb[OVPN_ATTR_GET_PEER]), NULL); + + if (!tb_peer[OVPN_GET_PEER_RESP_ATTR_PEER_ID]) + { + msg(M_WARN, "%s: no peer-id provided in reply", __func__); + return NL_SKIP; + } + + uint32_t peer_id = nla_get_u32(tb_peer[OVPN_GET_PEER_RESP_ATTR_PEER_ID]); + if (c->c2.tls_multi->dco_peer_id != peer_id) + { + return NL_SKIP; + } + + dco_update_peer_stat(&c->c2, tb_peer, peer_id); + + return NL_OK; } int dco_get_peer_stats(struct context *c) { - /* Not implemented. */ - return 0; + uint32_t peer_id = c->c2.tls_multi->dco_peer_id; + msg(D_DCO_DEBUG, "%s: peer-id %d", __func__, peer_id); + + dco_context_t *dco = &c->c1.tuntap->dco; + struct nl_msg *nl_msg = ovpn_dco_nlmsg_create(dco, OVPN_CMD_GET_PEER); + struct nlattr *attr = nla_nest_start(nl_msg, OVPN_ATTR_GET_PEER); + int ret = -EMSGSIZE; + + NLA_PUT_U32(nl_msg, OVPN_GET_PEER_ATTR_PEER_ID, peer_id); + nla_nest_end(nl_msg, attr); + + ret = ovpn_nl_msg_send(dco, nl_msg, dco_parse_peer, c, __func__); + +nla_put_failure: + nlmsg_free(nl_msg); + return ret; } bool diff --git a/src/openvpn/ovpn_dco_linux.h b/src/openvpn/ovpn_dco_linux.h index d3fd9a89..73e19b59 100644 --- a/src/openvpn/ovpn_dco_linux.h +++ b/src/openvpn/ovpn_dco_linux.h @@ -2,7 +2,7 @@ /* * OpenVPN data channel accelerator * - * Copyright (C) 2019-2022 OpenVPN, Inc. + * Copyright (C) 2019-2023 OpenVPN, Inc. * * Author: James Yonan * Antonio Quartulli @@ -188,10 +188,14 @@ enum ovpn_netlink_get_peer_response_attrs { OVPN_GET_PEER_RESP_ATTR_LOCAL_PORT, OVPN_GET_PEER_RESP_ATTR_KEEPALIVE_INTERVAL, OVPN_GET_PEER_RESP_ATTR_KEEPALIVE_TIMEOUT, - OVPN_GET_PEER_RESP_ATTR_RX_BYTES, - OVPN_GET_PEER_RESP_ATTR_TX_BYTES, - OVPN_GET_PEER_RESP_ATTR_RX_PACKETS, - OVPN_GET_PEER_RESP_ATTR_TX_PACKETS, + OVPN_GET_PEER_RESP_ATTR_VPN_RX_BYTES, + OVPN_GET_PEER_RESP_ATTR_VPN_TX_BYTES, + OVPN_GET_PEER_RESP_ATTR_VPN_RX_PACKETS, + OVPN_GET_PEER_RESP_ATTR_VPN_TX_PACKETS, + OVPN_GET_PEER_RESP_ATTR_LINK_RX_BYTES, + OVPN_GET_PEER_RESP_ATTR_LINK_TX_BYTES, + OVPN_GET_PEER_RESP_ATTR_LINK_RX_PACKETS, + OVPN_GET_PEER_RESP_ATTR_LINK_TX_PACKETS, __OVPN_GET_PEER_RESP_ATTR_AFTER_LAST, OVPN_GET_PEER_RESP_ATTR_MAX = __OVPN_GET_PEER_RESP_ATTR_AFTER_LAST - 1,