From nobody Mon Feb 9 05:00:58 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) client-ip=209.132.183.28; envelope-from=libvir-list-bounces@redhat.com; helo=mx1.redhat.com; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1562138490; cv=none; d=zoho.com; s=zohoarc; b=hvDXPIoOsOHkka28d3MfON6Yme+Io+YsE5Fyi6kjcXaMJ8Xh7KZYBpRMW5SQSl8tjDgBScDHy2ycMSbZrPFnPrgCzNnbw3ETL/f0T5GPQtuIAzsnl3Deh8IuG+GN1ha7bLYTn5NzfMcevGY3khmaEghMP3Ht/+L4alW4z1p9WgU= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1562138490; h=Content-Type:Content-Transfer-Encoding:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=K1ACnfu5YX5LECRoPeLov8h1jcFbmNHTDLgbFTNpJFU=; b=Ewg51wPaV/TM9ZlJqtih4rzswc2MGDvTFOZFLKyNvEPdm9vtdLQCSxDDifSni3y0aOJTptGTRPWXWSjODP+dA4xiZQic0TPRWUhY2XB7jg5YY55ZzULdOLQA/mFjV8MTc1bzkdspM4RufmNx7tj5IG8lrtAJRhIpBeGxG/OgFMA= ARC-Authentication-Results: i=1; mx.zoho.com; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass header.from= (p=none dis=none) header.from= Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by mx.zohomail.com with SMTPS id 1562138490460611.1140853589612; Wed, 3 Jul 2019 00:21:30 -0700 (PDT) Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id E782485A04; Wed, 3 Jul 2019 07:21:25 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.21]) by smtp.corp.redhat.com (Postfix) with ESMTPS id C357B174A7; Wed, 3 Jul 2019 07:21:24 +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 4DD4B4EBC5; Wed, 3 Jul 2019 07:21:23 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id x637JYPK019922 for ; Wed, 3 Jul 2019 03:19:34 -0400 Received: by smtp.corp.redhat.com (Postfix) id 4A47A7840D; Wed, 3 Jul 2019 07:19:34 +0000 (UTC) Received: from localhost.localdomain (ovpn-204-217.brq.redhat.com [10.40.204.217]) by smtp.corp.redhat.com (Postfix) with ESMTP id A40C218EC7 for ; Wed, 3 Jul 2019 07:19:30 +0000 (UTC) From: Michal Privoznik To: libvir-list@redhat.com Date: Wed, 3 Jul 2019 09:19:18 +0200 Message-Id: <62f9779c25af1a0b49fa21098e494d058e096844.1562138162.git.mprivozn@redhat.com> In-Reply-To: References: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-loop: libvir-list@redhat.com Subject: [libvirt] [PATCH 1/3] virNetDevOpenvswitchInterfaceStats: Optimize for speed 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: , Content-Transfer-Encoding: quoted-printable Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.26]); Wed, 03 Jul 2019 07:21:28 +0000 (UTC) Content-Type: text/plain; charset="utf-8" We run 'ovs-vsctl' nine times (first to find if interface is there and then eight times =3D for each stats member separately). This is very inefficient. I've found a way to run it once and with a bit of help from virJSON module we can parse out stats we need. Signed-off-by: Michal Privoznik --- src/util/virnetdevopenvswitch.c | 111 +++++++++++++++++++++----------- 1 file changed, 74 insertions(+), 37 deletions(-) diff --git a/src/util/virnetdevopenvswitch.c b/src/util/virnetdevopenvswitc= h.c index c99ecfbf15..0fe64bedab 100644 --- a/src/util/virnetdevopenvswitch.c +++ b/src/util/virnetdevopenvswitch.c @@ -28,6 +28,7 @@ #include "virmacaddr.h" #include "virstring.h" #include "virlog.h" +#include "virjson.h" =20 #define VIR_FROM_THIS VIR_FROM_NONE =20 @@ -311,58 +312,94 @@ int virNetDevOpenvswitchInterfaceStats(const char *ifname, virDomainInterfaceStatsPtr stats) { - char *tmp; - bool gotStats =3D false; VIR_AUTOPTR(virCommand) cmd =3D NULL; VIR_AUTOFREE(char *) output =3D NULL; + VIR_AUTOPTR(virJSONValue) jsonStats =3D NULL; + virJSONValuePtr jsonMap =3D NULL; + size_t i; =20 - /* Just ensure the interface exists in ovs */ cmd =3D virCommandNew(OVSVSCTL); virNetDevOpenvswitchAddTimeout(cmd); - virCommandAddArgList(cmd, "get", "Interface", ifname, "name", NULL); + virCommandAddArgList(cmd, "--if-exists", "--format=3Dlist", "--data=3D= json", + "--no-headings", "--columns=3Dstatistics", "list", + "Interface", ifname, NULL); virCommandSetOutputBuffer(cmd, &output); =20 - if (virCommandRun(cmd, NULL) < 0) { + /* The above command returns either: + * 1) empty string if @ifname doesn't exist, or + * 2) a JSON array, for instance: + * ["map",[["collisions",0],["rx_bytes",0],["rx_crc_err",0],["rx_dr= opped",0], + * ["rx_errors",0],["rx_frame_err",0],["rx_over_err",0],["rx_packet= s",0], + * ["tx_bytes",12406],["tx_dropped",0],["tx_errors",0],["tx_packets= ",173]]] + */ + + if (virCommandRun(cmd, NULL) < 0 || + STREQ_NULLABLE(output, "")) { /* no ovs-vsctl or interface 'ifname' doesn't exists in ovs */ virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Interface not found")); return -1; } =20 -#define GET_STAT(name, member) \ - do { \ - VIR_FREE(output); \ - virCommandFree(cmd); \ - cmd =3D virCommandNew(OVSVSCTL); \ - virNetDevOpenvswitchAddTimeout(cmd); \ - virCommandAddArgList(cmd, "--if-exists", "get", "Interface", \ - ifname, "statistics:" name, NULL); \ - virCommandSetOutputBuffer(cmd, &output); \ - if (virCommandRun(cmd, NULL) < 0 || !output || !*output || *output= =3D=3D '\n') { \ - stats->member =3D -1; \ - } else { \ - if (virStrToLong_ll(output, &tmp, 10, &stats->member) < 0 || \ - *tmp !=3D '\n') { \ - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", \ - _("Fail to parse ovs-vsctl output")); \ - return -1; \ - } \ - gotStats =3D true; \ - } \ - } while (0) + if (!(jsonStats =3D virJSONValueFromString(output)) || + !virJSONValueIsArray(jsonStats) || + !(jsonMap =3D virJSONValueArrayGet(jsonStats, 1))) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unable to parse ovs-vsctl output")); + return -1; + } =20 - /* The TX/RX fields appear to be swapped here - * because this is the host view. */ - GET_STAT("rx_bytes", tx_bytes); - GET_STAT("rx_packets", tx_packets); - GET_STAT("rx_errors", tx_errs); - GET_STAT("rx_dropped", tx_drop); - GET_STAT("tx_bytes", rx_bytes); - GET_STAT("tx_packets", rx_packets); - GET_STAT("tx_errors", rx_errs); - GET_STAT("tx_dropped", rx_drop); + stats->rx_bytes =3D stats->rx_packets =3D stats->rx_errs =3D stats->rx= _drop =3D -1; + stats->tx_bytes =3D stats->tx_packets =3D stats->tx_errs =3D stats->tx= _drop =3D -1; =20 - if (!gotStats) { + for (i =3D 0; i < virJSONValueArraySize(jsonMap); i++) { + virJSONValuePtr item =3D virJSONValueArrayGet(jsonMap, i); + virJSONValuePtr jsonKey; + virJSONValuePtr jsonVal; + const char *key; + long long val; + + if (!item || + (!(jsonKey =3D virJSONValueArrayGet(item, 0))) || + (!(jsonVal =3D virJSONValueArrayGet(item, 1))) || + (!(key =3D virJSONValueGetString(jsonKey))) || + (virJSONValueGetNumberLong(jsonVal, &val) < 0)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Malformed ovs-vsctl output")); + return -1; + } + + /* The TX/RX fields appear to be swapped here + * because this is the host view. */ + if (STREQ(key, "rx_bytes")) { + stats->tx_bytes =3D val; + } else if (STREQ(key, "rx_packets")) { + stats->tx_packets =3D val; + } else if (STREQ(key, "rx_errors")) { + stats->tx_errs =3D val; + } else if (STREQ(key, "rx_dropped")) { + stats->tx_drop =3D val; + } else if (STREQ(key, "tx_bytes")) { + stats->rx_bytes =3D val; + } else if (STREQ(key, "tx_packets")) { + stats->rx_packets =3D val; + } else if (STREQ(key, "tx_errors")) { + stats->rx_errs =3D val; + } else if (STREQ(key, "tx_dropped")) { + stats->rx_drop =3D val; + } else { + VIR_DEBUG("Unused ovs-vsctl stat key=3D%s val=3D%lld", key, va= l); + } + } + + if (stats->rx_bytes =3D=3D -1 && + stats->rx_packets =3D=3D -1 && + stats->rx_errs =3D=3D -1 && + stats->rx_drop =3D=3D -1 && + stats->tx_bytes =3D=3D -1 && + stats->tx_packets =3D=3D -1 && + stats->tx_errs =3D=3D -1 && + stats->tx_drop =3D=3D -1) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Interface doesn't have any statistics")); return -1; --=20 2.21.0 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list