From patchwork Mon Mar 20 23:20:34 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Antonio Quartulli X-Patchwork-Id: 3143 Return-Path: Delivered-To: patchwork@openvpn.net Received: by 2002:a05:7300:2310:b0:9f:bfa4:120f with SMTP id r16csp1998116dye; Mon, 20 Mar 2023 16:21:35 -0700 (PDT) X-Google-Smtp-Source: AK7set93TvZ1Ou0I/UOwi+xfGNpQsGm0MrRABW+jhqp/NXsGXIfS1A3maR7h1/OG7RZcU12g5Hwp X-Received: by 2002:aa7:8ec5:0:b0:625:4f81:bb30 with SMTP id b5-20020aa78ec5000000b006254f81bb30mr494785pfr.21.1679354494866; Mon, 20 Mar 2023 16:21:34 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1679354494; cv=none; d=google.com; s=arc-20160816; b=RbhEf4rgYJSnjmi3omwxabuOgSVzlKIwvzvDy10wHflj5C1AIPxsSDIzfLcQrURNCm ra3nbjlnsYQ3hiRIxu5MREyyPPnvJLflVnGSgy8i18UWJ/Fj+gqedQtzTEACOot/2v/1 fhCyz6SUUftWMdR6jweiV8eVgA96rCEDsf63UFrJXP7QzLnlegBfJCczCho8yObj35UY YGO1IiZmfRTpTOcpJsv3M2EiHXsWp7ZIiF1uP4yhiXN1J2+3pKNMc+IlcSHPZw7SE2/m aD6IXt6PxOSipsCYLrKR9HEJ9F9Ej+/Dc/YolbfpWEyd+mTEZ53VZNZ0jLFQyV725RGY qazg== 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=lcsH+5c3NDQ4QD9O7V/j2dhSVJUusDNc/9BqfIw9LL0=; b=do/mSC7z1Y0JjaLJ4Wl5oRnBIyWimVCw1DkojyTyZxsWRwGOYdCE0eTy/6SVncx4nI fJQRNGh85RQA/YQuZOxQv4e67PE6w/3EFH6t7Ice/dUkkpO0zdetQedvklU77A1wVOQ8 rcCKkD+0SK9630RUik4L3kkVKbi1CZ/0mJpzuvQ3eKIZG/ETeAz3tF9TtJNSY6WfSvuN M1smCARFOO4fhsFxlA2rQZQjUa7FUUaDjVm9+fQIGesdOX7YK4hP95rd0B51Sk2jtJFa GkUR6bvI0eS8kwybsBPvfQhevcQUnQVOnHJYz66MQrFrM3wzlviuh3FpF1odvYUGMsqi Vl7Q== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=alhhZ4ev; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=KouRjrgq; dkim=fail header.i=@unstable.cc header.s=20220809-q8oc header.b=jhZ5NDo1; 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 (lists.sourceforge.net. [216.105.38.7]) by mx.google.com with ESMTPS id t9-20020a056a0021c900b00593a3cabd75si11941347pfj.313.2023.03.20.16.21.34 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Mon, 20 Mar 2023 16:21:34 -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=alhhZ4ev; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=KouRjrgq; dkim=fail header.i=@unstable.cc header.s=20220809-q8oc header.b=jhZ5NDo1; 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-1.v29.lw.sourceforge.com) by sfs-ml-1.v29.lw.sourceforge.com with esmtp (Exim 4.95) (envelope-from ) id 1peOoL-0000Bi-Pa; Mon, 20 Mar 2023 23:21:06 +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 1peOoK-0000Bc-Np for openvpn-devel@lists.sourceforge.net; Mon, 20 Mar 2023 23:21:05 +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=2BpauojXAcm5pQzc/4vjgzv8Vg5Fvb/RjnG/ES+heds=; b=alhhZ4evXn/VD4i4T37BYuWEvl BaJoZQRoV6DyZgIfN5oQire4rxwnMKu1MajAA5DuHQaLoV5N28azDIPGx4PKU/A2DnMYwr99PTGef VkPsAZD0iK3M8+fcV9y+Gac08sLLHZosvyRgyc95ZvTkgxgkDFfQqMmRp9g2QG40jmm0=; 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=2BpauojXAcm5pQzc/4vjgzv8Vg5Fvb/RjnG/ES+heds=; b=K ouRjrgqjTrLEF0j0dT/YukPIRUo1mj/6nOAA610ePWHph09l0uEuYKcywZuOrycI8XFD/9IoIN/N3 xCdlMyGMdNUKUPitKwx4x811wFFYx2+lSoqLgqis5246jTC6bRX9Iw4ArVvgfVsMdDGARf117yDGF Ao1VTNmPkIZZddCo=; Received: from mailout-l3b-97.contactoffice.com ([212.3.242.97]) by sfi-mx-1.v28.lw.sourceforge.com with esmtps (TLS1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.95) id 1peOoH-00EgIc-Qk for openvpn-devel@lists.sourceforge.net; Mon, 20 Mar 2023 23:21:05 +0000 Received: from smtpauth2.co-bxl (smtpauth2.co-bxl [10.2.0.24]) by mailout-l3b-97.contactoffice.com (Postfix) with ESMTP id 13D94AE7; Tue, 21 Mar 2023 00:20:55 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; t=1679354455; s=20220809-q8oc; d=unstable.cc; i=a@unstable.cc; h=From:To:Cc:Subject:Date:Message-Id:MIME-Version:Content-Transfer-Encoding; l=9935; bh=2BpauojXAcm5pQzc/4vjgzv8Vg5Fvb/RjnG/ES+heds=; b=jhZ5NDo1Q7ZTrsCqeDuCdE09fn484RBxQgBPCpJYL2yvSSOUjFM5kIk/nPLGw7Oh HaCqpD/9VsZKE7749a27bpwQ29gNlMEGtNA2FHUlHCciQ+DkKfu7jxmh/iO/Ew5TJJK LRCF2cCg4KMdt42GmUs/Utk1qPy5kitPBW1F7mojG/ws7S+JQFqRB1zndwAelImel+Z IqODSxdND+ieLWj/c0bN2WQvwVkTEEqH+sBPzo22oV5mqmSWKm4FxqJGgD9EszQFzrh KoH3PieKa5+RfSL4RPjLgZ1j6kYj/ZH32DF17v9v37zGirX6xm7pMl+91YTlMfDrc26 ASWuJrb00w== Received: by smtp.mailfence.com with ESMTPSA ; Tue, 21 Mar 2023 00:20:52 +0100 (CET) From: Antonio Quartulli To: openvpn-devel@lists.sourceforge.net Date: Tue, 21 Mar 2023 00:20:34 +0100 Message-Id: <20230320232034.14828-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-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.97 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: 1peOoH-00EgIc-Qk Subject: [Openvpn-devel] [PATCH] 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?1760930818475245873?= 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 --- Pleas, use the latest ovpn-dco master branch! src/openvpn/dco_linux.c | 194 ++++++++++++++++++++++++++++++++--- src/openvpn/ovpn_dco_linux.h | 14 ++- 2 files changed, 190 insertions(+), 18 deletions(-) diff --git a/src/openvpn/dco_linux.c b/src/openvpn/dco_linux.c index 47961849..1f18fa81 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,184 @@ 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 hash_iterator hi; + hash_iterator_init(m->hash, &hi); + + struct hash_element *he; + while ((he = hash_iterator_next(&hi))) + { + struct multi_instance *mi = (struct multi_instance *)he->value; + + if (mi->context.c2.tls_multi->peer_id != peer_id) + { + continue; + } + + dco_update_peer_stat(&mi->context.c2, tb_peer, peer_id); + + return NL_OK; + } + + msg(D_DCO_DEBUG, "%s: peer %d returned by kernel, but not found locally", + __func__, peer_id); + + return NL_SKIP; +} + 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,