From nobody Sat May 4 14:12:02 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of redhat.com designates 216.205.24.124 as permitted sender) client-ip=216.205.24.124; envelope-from=libvir-list-bounces@redhat.com; helo=us-smtp-delivery-124.mimecast.com; Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of redhat.com designates 216.205.24.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=fail(p=none dis=none) header.from=bytedance.com ARC-Seal: i=1; a=rsa-sha256; t=1600828405; cv=none; d=zohomail.com; s=zohoarc; b=NAuIQkMG6niW+YRrzE9t4D2V8FDZ5EVGXD2dmvNDSjZx4IkgL1vtjsEoeZpdMCbZNRjMcNIxhH+MA3R+Geo32+AlhC2rqRll7V7HY6YG5einb21oLK6OfBauHlQHHo2iygfXOJwECP1SzlYDKDOQt6+/CSSePXFuDaev5b7Ix/0= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1600828405; h=Content-Type:Cc:Date:From:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:Message-ID:Sender:Subject:To; bh=63qbYdAHGJwhwAy3EzbWVESN2g8LCyD8f14b0ZlvtmU=; b=LhapcsPGnNhDlMGzfep9iVqLH8HQDS6Vg+hQFzyXNzEkNXOdGmnGA+SVKS3AgD6ols2pToJUPvMaSFZ4Ttv+dMEs1gOGQ/CaEw17k12Wwzq1QbBil79vatt3wRfXToxxU2nxIqXZzIQqnZHDg44hkciSTmWh8cCUM2z6C3iR5e4= ARC-Authentication-Results: i=1; mx.zohomail.com; spf=pass (zohomail.com: domain of redhat.com designates 216.205.24.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [216.205.24.124]) by mx.zohomail.com with SMTPS id 1600828405043164.16946272500013; Tue, 22 Sep 2020 19:33:25 -0700 (PDT) Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-197-lrCQnmqRNwaHbzud2QKtGw-1; Tue, 22 Sep 2020 22:33:21 -0400 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 7E259802B5D; Wed, 23 Sep 2020 02:33:15 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.20]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 2DD7D9CBA; Wed, 23 Sep 2020 02:33:14 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id 72DCD1826D2C; Wed, 23 Sep 2020 02:33:10 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id 08N2X7A3024334 for ; Tue, 22 Sep 2020 22:33:08 -0400 Received: by smtp.corp.redhat.com (Postfix) id D59F1F00E4; Wed, 23 Sep 2020 02:33:07 +0000 (UTC) Received: from mimecast-mx02.redhat.com (mimecast01.extmail.prod.ext.rdu2.redhat.com [10.11.55.17]) by smtp.corp.redhat.com (Postfix) with ESMTPS id D0DB9F00E8 for ; Wed, 23 Sep 2020 02:33:05 +0000 (UTC) Received: from us-smtp-1.mimecast.com (us-smtp-delivery-1.mimecast.com [205.139.110.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-SHA384 (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 8F2718582A3 for ; Wed, 23 Sep 2020 02:33:05 +0000 (UTC) Received: from mail-pg1-f196.google.com (mail-pg1-f196.google.com [209.85.215.196]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-568-1243Beu5Nf69KQD56AQ8dw-1; Tue, 22 Sep 2020 22:33:03 -0400 Received: by mail-pg1-f196.google.com with SMTP id f2so13437038pgd.3 for ; Tue, 22 Sep 2020 19:33:03 -0700 (PDT) Received: from libai.bytedance.net ([61.120.150.71]) by smtp.gmail.com with ESMTPSA id bx22sm3426829pjb.23.2020.09.22.19.32.59 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Tue, 22 Sep 2020 19:33:01 -0700 (PDT) X-MC-Unique: lrCQnmqRNwaHbzud2QKtGw-1 X-MC-Unique: 1243Beu5Nf69KQD56AQ8dw-1 X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=63qbYdAHGJwhwAy3EzbWVESN2g8LCyD8f14b0ZlvtmU=; b=Jb1lGswRsFaQTrvM0Oe5pbF16oW0c2pf4n/vhTEupH7zqZHvqMcvMk+ga1krexzd5s GA9boE02fpiAPfhpa8r/TMFmIwv6ZNYC0nZsdagSyDCZ/grOOm6lDHeIgKqT04Wnn4gI xg+IJxjVUtUnRniXIiEk5aIjUDH7pH1hdrYZYbJa0Uigj+QAGi1Hq7M37rviWKbOAeK8 GWx0lCmYGTJBPMliK0KK0tvfxpsxtyaB62/F+JLUzi/BEMAiNuPKLNUfZItyGkkRnhRv lsSVOAvp1B2vIZgrVfY8aPrC3dhj1+CBu5xrFoAG292iNlvSEGv3iUJVaq9+o6cHMrWu La0w== X-Gm-Message-State: AOAM531nkmrKZV8sSvHMFp6te7Jggg0LgiNqinp+jsGatEFIuPgyQ5nR /0vYQP5dMQWEcaH+pdWO+wV2xCNM3cSJGlj+ X-Google-Smtp-Source: ABdhPJxYVOw7G0Syc30fEKEktK8Bc1CZG/QS0jZ1pIJKKxJAL+LHTpQKuRDrP/uMUFQTx+sNGlUpcw== X-Received: by 2002:a63:1a66:: with SMTP id a38mr5752257pgm.253.1600828382021; Tue, 22 Sep 2020 19:33:02 -0700 (PDT) From: zhenwei pi To: laine@redhat.com, berrange@redhat.com Subject: [PATCH v2] util: support PCI passthrough net device stats collection Date: Wed, 23 Sep 2020 10:32:54 +0800 Message-Id: <20200923023254.478341-1-pizhenwei@bytedance.com> X-Mimecast-Impersonation-Protect: Policy=CLT - Impersonation Protection Definition; Similar Internal Domain=false; Similar Monitored External Domain=false; Custom External Domain=false; Mimecast External Domain=false; Newly Observed Domain=false; Internal User Name=false; Custom Display Name List=false; Reply-to Address Mismatch=false; Targeted Threat Dictionary=false; Mimecast Threat Dictionary=false; Custom Threat Dictionary=false; X-Scanned-By: MIMEDefang 2.79 on 10.11.54.5 X-loop: libvir-list@redhat.com Cc: libvir-list@redhat.com, zhenwei pi X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=libvir-list-bounces@redhat.com X-Mimecast-Spam-Score: 2 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Collect PCI passthrough net device stats from kernel by netlink API. Currently, libvirt can not get PCI passthrough net device stats, run command: #virsh domifstat instance --interface=3D52:54:00:2d:b2:35 error: Failed to get interface stats instance 52:54:00:2d:b2:35 error: internal error: Interface name not provided The PCI device(usually SR-IOV virtual function device) is detached while it's used in PCI passthrough mode. And we can not parse this device from /proc/net/dev any more. In this patch, libvirt check net device is VF of not firstly, then query virNetDevVFInterfaceStats(new API). virNetDevVFInterfaceStats parses VFs info of all PFs, compares MAC address until the two MAC addresses match. '#ip -s link show' can get the same result. Instead of parsing the output result, implement this feature by libnl API. Notice that this feature deponds on driver of PF. Test on Mellanox ConnectX-4 Lx, it works well. Also test on Intel Corporation 82599ES, it works, but only get 0. (ip-link command get the same result). Signed-off-by: zhenwei pi --- src/libvirt_private.syms | 1 + src/qemu/qemu_driver.c | 3 ++ src/util/virnetdev.c | 137 +++++++++++++++++++++++++++++++++++++++++++= ++++ src/util/virnetdev.h | 5 ++ 4 files changed, 146 insertions(+) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index bdbe3431b8..bcc40b8d69 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2585,6 +2585,7 @@ virNetDevSetRcvMulti; virNetDevSetupControl; virNetDevSysfsFile; virNetDevValidateConfig; +virNetDevVFInterfaceStats; =20 =20 # util/virnetdevbandwidth.h diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index ae715c01d7..f554010c40 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -10196,6 +10196,9 @@ qemuDomainInterfaceStats(virDomainPtr dom, if (virDomainNetGetActualType(net) =3D=3D VIR_DOMAIN_NET_TYPE_VHOSTUSE= R) { if (virNetDevOpenvswitchInterfaceStats(net->ifname, stats) < 0) goto cleanup; + } else if (virDomainNetGetActualType(net) =3D=3D VIR_DOMAIN_NET_TYPE_H= OSTDEV) { + if (virNetDevVFInterfaceStats(&net->mac, stats) < 0) + goto cleanup; } else { if (virNetDevTapInterfaceStats(net->ifname, stats, !virDomainNetTypeSharesHostView(net= )) < 0) diff --git a/src/util/virnetdev.c b/src/util/virnetdev.c index e1a4cc2bef..377f25aae7 100644 --- a/src/util/virnetdev.c +++ b/src/util/virnetdev.c @@ -1489,6 +1489,7 @@ static struct nla_policy ifla_vf_policy[IFLA_VF_MAX+1= ] =3D { .maxlen =3D sizeof(struct ifla_vf_mac) }, [IFLA_VF_VLAN] =3D { .type =3D NLA_UNSPEC, .maxlen =3D sizeof(struct ifla_vf_vlan) }, + [IFLA_VF_STATS] =3D { .type =3D NLA_NESTED }, }; =20 =20 @@ -2265,6 +2266,132 @@ virNetDevSetNetConfig(const char *linkdev, int vf, return 0; } =20 +static struct nla_policy ifla_vfstats_policy[IFLA_VF_STATS_MAX+1] =3D { + [IFLA_VF_STATS_RX_PACKETS] =3D { .type =3D NLA_U64 }, + [IFLA_VF_STATS_TX_PACKETS] =3D { .type =3D NLA_U64 }, + [IFLA_VF_STATS_RX_BYTES] =3D { .type =3D NLA_U64 }, + [IFLA_VF_STATS_TX_BYTES] =3D { .type =3D NLA_U64 }, + [IFLA_VF_STATS_BROADCAST] =3D { .type =3D NLA_U64 }, + [IFLA_VF_STATS_MULTICAST] =3D { .type =3D NLA_U64 }, +}; + +static int +virNetDevParseVfStats(struct nlattr **tb, virMacAddrPtr mac, + virDomainInterfaceStatsPtr stats) +{ + int ret =3D -1, len; + struct ifla_vf_mac *vf_lladdr; + struct nlattr *nla, *t[IFLA_VF_MAX+1]; + struct nlattr *stb[IFLA_VF_STATS_MAX+1]; + + if (tb =3D=3D NULL || mac =3D=3D NULL || stats =3D=3D NULL) { + return -1; + } + + if (!tb[IFLA_VFINFO_LIST]) + return -1; + + len =3D nla_len(tb[IFLA_VFINFO_LIST]); + + for (nla =3D nla_data(tb[IFLA_VFINFO_LIST]); nla_ok(nla, len); + nla =3D nla_next(nla, &len)) { + ret =3D nla_parse(t, IFLA_VF_MAX, nla_data(nla), nla_len(nla), + ifla_vf_policy); + if (ret < 0) + return -1; + + if (t[IFLA_VF_MAC] =3D=3D NULL) { + continue; + } + + vf_lladdr =3D nla_data(t[IFLA_VF_MAC]); + if (virMacAddrCmpRaw(mac, vf_lladdr->mac)) { + continue; + } + + if (t[IFLA_VF_STATS]) { + ret =3D nla_parse_nested(stb, IFLA_VF_STATS_MAX, + t[IFLA_VF_STATS], + ifla_vfstats_policy); + if (ret < 0) + return -1; + + stats->rx_bytes =3D nla_get_u64(stb[IFLA_VF_STATS_RX_BYTES]); + stats->tx_bytes =3D nla_get_u64(stb[IFLA_VF_STATS_TX_BYTES]); + stats->rx_packets =3D nla_get_u64(stb[IFLA_VF_STATS_RX_PACKETS= ]); + stats->tx_packets =3D nla_get_u64(stb[IFLA_VF_STATS_TX_PACKETS= ]); + } + return 0; + } + + return ret; +} + +/** + * virNetDevVFInterfaceStats: + * @mac: MAC address of the VF interface + * @stats: returns stats of the VF interface + * + * Get the VF interface from kernel by netlink. + * Returns 0 on success, -1 on failure. + */ +int +virNetDevVFInterfaceStats(virMacAddrPtr mac, + virDomainInterfaceStatsPtr stats) +{ + FILE *fp; + char line[256], *colon, *ifname; + int rc =3D -1; + void *nlData =3D NULL; + struct nlattr *tb[IFLA_MAX + 1] =3D {NULL, }; + char *sysfsDevicePath =3D NULL; + + fp =3D fopen("/proc/net/dev", "r"); + if (!fp) { + virReportSystemError(errno, "%s", + _("Could not open /proc/net/dev")); + return -1; + } + + /* get all PCI net devices, and parse VFs list from netlink API. + * compare MAC address, collect device stats if matching. + */ + while (fgets(line, sizeof(line), fp)) { + /* The line looks like: + * " eth0:..." + * Split it at the colon. and strip blank from head. + */ + colon =3D strchr(line, ':'); + if (!colon) + continue; + *colon =3D '\0'; + ifname =3D line; + while ((*ifname =3D=3D ' ') && (ifname < colon)) + ifname++; + + if (virNetDevSysfsFile(&sysfsDevicePath, ifname, "device") < 0) + break; + + if (virNetDevIsPCIDevice(sysfsDevicePath)) { + rc =3D virNetlinkDumpLink(ifname, -1, &nlData, tb, 0, 0); + if (rc < 0) { + rc =3D -1; + goto cleanup; + } + + rc =3D virNetDevParseVfStats(tb, mac, stats); + VIR_FREE(nlData); + if (rc =3D=3D 0) + goto cleanup; + } + VIR_FREE(sysfsDevicePath); + } + + cleanup: + VIR_FREE(sysfsDevicePath); + VIR_FORCE_FCLOSE(fp); + return rc; +} =20 #else /* defined(__linux__) && defined(WITH_LIBNL) && defined(IFLA_VF_MAX= ) */ =20 @@ -2309,6 +2436,16 @@ virNetDevSetNetConfig(const char *linkdev G_GNUC_UNU= SED, } =20 =20 +int +virNetDevVFInterfaceStats(virMacAddrPtr mac G_GNUC_UNUSED, + virDomainInterfaceStatsPtr stats G_GNUC_UNUSED) +{ + virReportSystemError(ENOSYS, "%s", + _("Unable to get VF net device stats on this plat= form")); + return -1; +} + + #endif /* defined(__linux__) && defined(WITH_LIBNL) && defined(IFLA_VF_MAX= ) */ =20 VIR_ENUM_IMPL(virNetDevIfState, diff --git a/src/util/virnetdev.h b/src/util/virnetdev.h index 5f581323ed..ff59d9d341 100644 --- a/src/util/virnetdev.h +++ b/src/util/virnetdev.h @@ -312,4 +312,9 @@ int virNetDevSysfsFile(char **pf_sysfs_device_link, int virNetDevRunEthernetScript(const char *ifname, const char *script) G_GNUC_NO_INLINE; =20 +int virNetDevVFInterfaceStats(virMacAddrPtr mac, + virDomainInterfaceStatsPtr stats) +ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); + + G_DEFINE_AUTOPTR_CLEANUP_FUNC(virNetDevRxFilter, virNetDevRxFilterFree); --=20 2.11.0