From patchwork Tue Mar 21 23:08:07 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Antonio Quartulli X-Patchwork-Id: 3145 Return-Path: Delivered-To: patchwork@openvpn.net Received: by 2002:a05:7300:2310:b0:9f:bfa4:120f with SMTP id r16csp2768751dye; Tue, 21 Mar 2023 16:09:58 -0700 (PDT) X-Google-Smtp-Source: AK7set+quwCehB8RekctCPfYc0BAgMp+VYZibrWuK/Iz7AtrMia5eiEH+OtRJFhSXkwf3/F6cEFq X-Received: by 2002:a05:6a20:2da2:b0:d9:8d85:eb42 with SMTP id bf34-20020a056a202da200b000d98d85eb42mr3083039pzb.26.1679440198608; Tue, 21 Mar 2023 16:09:58 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1679440198; cv=none; d=google.com; s=arc-20160816; b=LVa0aHTyMU0wFsv57Rh8s9neW1uwTH5GqCt2b500Asww+8lsUxI339mS67XQTHeeHn u2qHYtJMdhE0WuU3N2p5wCdgSWEJVOuLhsIJpi/W+4xbLOvJ5o2VDkMKSLrC/22AWHsT Kyq0+RBlninzjgobJnaDsg91pL+xZD8t902F/RbD4k34dJbsJsCg4i8upGLYNtC7+nMu L9RMyja1JpHF7Cu5eP3sVnmKkO8ycmcwiLlfikwqFFUJt+zim6LFCsQqi6YBe/r44ghi blRYJulK6jQfKYnI3qeouxNdOwoadFQmQ7+h1bBonn4Bg5HB+ESW5QMiWSczbBPqT7hh 0dMg== 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:references:in-reply-to:message-id:date:to:from :dkim-signature:dkim-signature:dkim-signature; bh=b6ftHbFAj+Q6pZMAnj9/rixSqB3NITyhC9DO1rE98cM=; b=MFRN21dVuqCiUK4UNAu7U1ARaNoyv4aQEIaFBeQfym60INoEiv84SuxsoMFR++O12+ sYRYfjHh6kHbR99Tb6nBFuXprCwG9WvHLai79K0Qf6rtHsXbJDjYQOVcGdF/irliSSkI NKp6U207NtSv+MsS/gb8R24XHQBdiZYml08LEIfJ9ZtqT52CGU63kfpXzFf+hKQeZ4Gn Ci5roE17RE96i1luI/DFdUOavl9JlrfY9t0wsxoFeSH/YcZDXYgBzhJ/zj7YLwfCtM4b 4r7B4AaUJVkpfwp0rkBi6puNtZrKkGb0tlzhyLnVbXJ22VQZiQDqLyZqPDa9/ioBHQ7S og/w== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=fDwTWqYP; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=cuWuacby; dkim=fail header.i=@unstable.cc header.s=20220809-q8oc header.b=m8S81Eqg; 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 j4-20020a632304000000b0050301265ffcsi14103702pgj.471.2023.03.21.16.09.58 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Tue, 21 Mar 2023 16:09:58 -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=fDwTWqYP; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=cuWuacby; dkim=fail header.i=@unstable.cc header.s=20220809-q8oc header.b=m8S81Eqg; 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-2.v29.lw.sourceforge.com) by sfs-ml-2.v29.lw.sourceforge.com with esmtp (Exim 4.95) (envelope-from ) id 1pel65-0006ti-78; Tue, 21 Mar 2023 23:08:53 +0000 Received: from [172.30.20.202] (helo=mx.sourceforge.net) by sfs-ml-2.v29.lw.sourceforge.com with esmtps (TLS1.2) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.95) (envelope-from ) id 1pel5w-0006tS-VK for openvpn-devel@lists.sourceforge.net; Tue, 21 Mar 2023 23:08:45 +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: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:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=gfJsKfVp8lJ9NMlj3furJuQGKASx3Q964LmDAB+PgxI=; b=fDwTWqYPzAngZtTAATayNndeVD 4JpRzH/gf2NBfEQe/q5o9kU+YPcg4b5FoCKVEQpzQFPKDe5ZDqCdAAmRofXDZw4hqHz210RAM8iBz ScJ9TeCsR+H15qjTumxwaStj1C6QFsCCO9/FNNke7QOQ1MD8DMIahW+gOPXETq5S033k=; 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: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:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=gfJsKfVp8lJ9NMlj3furJuQGKASx3Q964LmDAB+PgxI=; b=cuWuacbyqeX3+vdz96VuX3yBsz 2on7peVh79YJXCvXlrj64xDqNieYYh5JcpgMYdvNdWzCqBicPCOVVcyQgzYBUhbFRmWE2CtcqJ0Qr jsuEx7SujMNmMe/hxF9F/5BLzyxOV13Xxg/YfHxoNUa9irxYhC9Wd44wkZvfHV8hnSGk=; 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 1pel5n-0006zl-Rl for openvpn-devel@lists.sourceforge.net; Tue, 21 Mar 2023 23:08:40 +0000 Received: from smtpauth2.co-bxl (smtpauth2.co-bxl [10.2.0.24]) by wilbur.contactoffice.com (Postfix) with ESMTP id 766FD1A44; Wed, 22 Mar 2023 00:08:29 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; t=1679440109; s=20220809-q8oc; d=unstable.cc; i=a@unstable.cc; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References:MIME-Version:Content-Transfer-Encoding; l=9741; bh=gfJsKfVp8lJ9NMlj3furJuQGKASx3Q964LmDAB+PgxI=; b=m8S81EqgST7aH+pz22mRV+BdbtbyHK/thsjpm72C5+wwFNrMv/qoEybMk3sHOvmI BMfIykIlhAAU+w+eUgZrsx9tC8LhxyRmYrKjRexsPD3b0S8oxVvdYJV4no1XNT/NedE 0bdeQyysrpiS/xQqej33J6Ocy1R6i6XtLsde/kQc84HM34kzcB0yzMBUAfOa2ywNwp6 v4j8bu8UoQAXdwv/BU7s2bNUPz/H42hwjWeHhWJ/S6ppZX6ddizxximNzxCDVqSHwAQ XTfnO+wT0I7/patSX17rfpthFfws5H8jE/h6113pV01CR5KyHubuCCBRtoHyrEeXKPS 3NxLuN6HzQ== Received: by smtp.mailfence.com with ESMTPSA ; Wed, 22 Mar 2023 00:08:24 +0100 (CET) From: Antonio Quartulli To: openvpn-devel@lists.sourceforge.net Date: Wed, 22 Mar 2023 00:08:07 +0100 Message-Id: <20230321230807.1382-1-a@unstable.cc> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230320232034.14828-1-a@unstable.cc> References: 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.1 X-ContactOffice-Account: com:375058688 X-Spam-Score: -0.9 (/) 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: 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 Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid X-Headers-End: 1pel5n-0006zl-Rl Subject: [Openvpn-devel] [PATCH v2] 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?1761020685695753027?= 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 --- Changes from v1: * use m->instances[] instead of iterating over m->hash --- 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..4bbe7e22 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; + } + + uint32_t peer_id = nla_get_u32(tb_peer[OVPN_GET_PEER_RESP_ATTR_PEER_ID]); + struct multi_context *m = arg; + struct multi_instance *mi = m->instances[peer_id]; + if (!mi) + { + msg(D_DCO_DEBUG, "%s: peer %d returned by kernel, but not found locally", + __func__, peer_id); + return NL_SKIP; + } + + dco_update_peer_stat(&mi->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,