diff mbox series

[v7,RESEND] qga: Add support network interface statistics in guest-network-get-interfaces command

Message ID 1505206466-23361-1-git-send-email-lu.zhipeng@zte.com.cn
State New
Headers show
Series [v7,RESEND] qga: Add support network interface statistics in guest-network-get-interfaces command | expand

Commit Message

ZhiPeng Lu Sept. 12, 2017, 8:54 a.m. UTC
we can get the network interface statistics inside a virtual machine by
guest-network-get-interfaces command. it is very useful for us to monitor
and analyze network traffic.

Signed-off-by: ZhiPeng Lu <lu.zhipeng@zte.com.cn>

---
v1->v2:
 - correct some spelling mistake and add the stats data to the
   guest-network-get-interfaces command instead of adding a new command.
v2-v3:
 - optimize function implementation
v3->v4:
 - modify compile error
v4->v5:
 - rename some temporary variables and add str_trim_off function for
   calculating the space num in front of the string in guest_get_network_stats
v5->v6:
 - use g_strchug instead of str_trim_off implemented by myself
v6->v7:
 - add implementation for windows
---
 qga/commands-posix.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 qga/commands-win32.c | 48 +++++++++++++++++++++++++++++++++++
 qga/qapi-schema.json | 38 ++++++++++++++++++++++++++-
 3 files changed, 156 insertions(+), 2 deletions(-)

Comments

Michael Roth Oct. 26, 2017, 12:59 a.m. UTC | #1
Quoting ZhiPeng Lu (2017-09-12 03:54:26)
> we can get the network interface statistics inside a virtual machine by
> guest-network-get-interfaces command. it is very useful for us to monitor
> and analyze network traffic.
> 
> Signed-off-by: ZhiPeng Lu <lu.zhipeng@zte.com.cn>

Thanks, applied to qga tree:
  https://github.com/mdroth/qemu/commits/qga

There were a few issues that I noted below, but I tested on linux/windows
and things seem to be working well so I fixed them up in my tree.

> 
> ---
> v1->v2:
>  - correct some spelling mistake and add the stats data to the
>    guest-network-get-interfaces command instead of adding a new command.
> v2-v3:
>  - optimize function implementation
> v3->v4:
>  - modify compile error
> v4->v5:
>  - rename some temporary variables and add str_trim_off function for
>    calculating the space num in front of the string in guest_get_network_stats
> v5->v6:
>  - use g_strchug instead of str_trim_off implemented by myself
> v6->v7:
>  - add implementation for windows
> ---
>  qga/commands-posix.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++-
>  qga/commands-win32.c | 48 +++++++++++++++++++++++++++++++++++
>  qga/qapi-schema.json | 38 ++++++++++++++++++++++++++-
>  3 files changed, 156 insertions(+), 2 deletions(-)
> 
> diff --git a/qga/commands-posix.c b/qga/commands-posix.c
> index ab0c63d..da5dba0 100644
> --- a/qga/commands-posix.c
> +++ b/qga/commands-posix.c
> @@ -1643,6 +1643,65 @@ guest_find_interface(GuestNetworkInterfaceList *head,
>      return head;
>  }
> 
> +static int guest_get_network_stats(const char *name,
> +                       GuestNetworkInterfaceStat *stats)
> +{
> +    int name_len;
> +    char const *devinfo = "/proc/net/dev";
> +    FILE *fp;
> +    char *line = NULL, *colon;
> +    size_t n;

Not sure if it affects behavior in practice, but getline() documentation
states that *line is only allocated if *line == NULL *and* n == 0. So we
should set n to 0 before each call to be safe.

> +    fp = fopen(devinfo, "r");
> +    if (!fp) {
> +        return -1;
> +    }
> +    name_len = strlen(name);
> +    while (getline(&line, &n, fp) != -1) {

Since 'line' is being allocated by getline(), we need to free it after
each call, or rely on it to realloc and then free that value before
returning. The latter seems simpler in this case.

> +        long long dummy;
> +        long long rx_bytes;
> +        long long rx_packets;
> +        long long rx_errs;
> +        long long rx_dropped;
> +        long long tx_bytes;
> +        long long tx_packets;
> +        long long tx_errs;
> +        long long tx_dropped;
> +        char *trim_line;
> +        trim_line = g_strchug(line);
> +        if (trim_line[0] == '\0') {
> +            continue;
> +        }
> +        colon = strchr(trim_line, ':');
> +        if (!colon) {
> +            continue;
> +        }
> +        if (colon - name_len  == trim_line &&
> +           strncmp(trim_line, name, name_len) == 0) {
> +            if (sscanf(colon + 1,
> +                "%lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld",
> +                  &rx_bytes, &rx_packets, &rx_errs, &rx_dropped,
> +                  &dummy, &dummy, &dummy, &dummy,
> +                  &tx_bytes, &tx_packets, &tx_errs, &tx_dropped,
> +                  &dummy, &dummy, &dummy, &dummy) != 16) {
> +                continue;
> +            }
> +            stats->rx_bytes = rx_bytes;
> +            stats->rx_packets = rx_packets;
> +            stats->rx_errs = rx_errs;
> +            stats->rx_dropped = rx_dropped;
> +            stats->tx_bytes = tx_bytes;
> +            stats->tx_packets = tx_packets;
> +            stats->tx_errs = tx_errs;
> +            stats->tx_dropped = tx_dropped;
> +            fclose(fp);
> +            return 0;
> +        }
> +    }
> +    fclose(fp);
> +    g_debug("/proc/net/dev: Interface not found");

Reporting the specific interface name might be useful here.

> +    return -1;
> +}
> +
>  /*
>   * Build information about guest interfaces
>   */
> @@ -1659,6 +1718,7 @@ GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **errp)
>      for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
>          GuestNetworkInterfaceList *info;
>          GuestIpAddressList **address_list = NULL, *address_item = NULL;
> +        GuestNetworkInterfaceStat  *interface_stat = NULL;
>          char addr4[INET_ADDRSTRLEN];
>          char addr6[INET6_ADDRSTRLEN];
>          int sock;
> @@ -1778,7 +1838,17 @@ GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **errp)
> 
>          info->value->has_ip_addresses = true;
> 
> -
> +        if (!info->value->has_statistics) {
> +            interface_stat = g_malloc0(sizeof(*interface_stat));
> +            if (guest_get_network_stats(info->value->name,
> +                interface_stat) == -1) {
> +                info->value->has_statistics = false;
> +                g_free(interface_stat);
> +            } else {
> +                info->value->statistics = interface_stat;
> +                info->value->has_statistics = true;
> +            }
> +        }
>      }
> 
>      freeifaddrs(ifap);
> diff --git a/qga/commands-win32.c b/qga/commands-win32.c
> index 619dbd2..e891253 100644
> --- a/qga/commands-win32.c
> +++ b/qga/commands-win32.c
> @@ -1152,6 +1152,42 @@ out:
>  }
>  #endif
> 
> +static DWORD get_interface_index(const char *guid)
> +{
> +    ULONG index;
> +    DWORD status;
> +    wchar_t wbuf[512];
> +    snwprintf(wbuf, sizeof(wbuf), L"\\device\\tcpip_%s", guid);
> +    wbuf[sizeof(wbuf) - 1] = 0;

wchar_t can be larger than 1 byte, so using sizeof(wchar_t[]) as an
index into a wchar_t[] can cause an overrun.

> +    status = GetAdapterIndex (wbuf, &index);
> +    if (status != NO_ERROR) {
> +        return (DWORD)~0;
> +    } else {
> +        return index;
> +    }
> +}
> +static int guest_get_network_stats(const char *name,
> +                       GuestNetworkInterfaceStat *stats)
> +{
> +    DWORD IfIndex = 0;
> +    MIB_IFROW aMib_ifrow;
> +    memset(&aMib_ifrow, 0, sizeof(aMib_ifrow));
> +    IfIndex = get_interface_index(name);

Per CODING_STYLE variable names should be lowercase with "_" for
separating words

> +    aMib_ifrow.dwIndex = IfIndex;
> +    if (NO_ERROR == GetIfEntry(&aMib_ifrow)) {
> +        stats->rx_bytes = aMib_ifrow.dwInOctets;
> +        stats->rx_packets = aMib_ifrow.dwInUcastPkts;
> +        stats->rx_errs = aMib_ifrow.dwInErrors;
> +        stats->rx_dropped = aMib_ifrow.dwInDiscards;
> +        stats->tx_bytes = aMib_ifrow.dwOutOctets;
> +        stats->tx_packets = aMib_ifrow.dwOutUcastPkts;
> +        stats->tx_errs = aMib_ifrow.dwOutErrors;
> +        stats->tx_dropped = aMib_ifrow.dwOutDiscards;
> +        return 0;
> +    }
> +    return -1;
> +}
> +
>  GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **errp)
>  {
>      IP_ADAPTER_ADDRESSES *adptr_addrs, *addr;
> @@ -1159,6 +1195,7 @@ GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **errp)
>      GuestNetworkInterfaceList *head = NULL, *cur_item = NULL;
>      GuestIpAddressList *head_addr, *cur_addr;
>      GuestNetworkInterfaceList *info;
> +    GuestNetworkInterfaceStat *interface_stat = NULL;
>      GuestIpAddressList *address_item = NULL;
>      unsigned char *mac_addr;
>      char *addr_str;
> @@ -1238,6 +1275,17 @@ GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **errp)
>              info->value->has_ip_addresses = true;
>              info->value->ip_addresses = head_addr;
>          }
> +        if (!info->value->has_statistics) {
> +            interface_stat = g_malloc0(sizeof(*interface_stat));
> +            if (guest_get_network_stats(addr->AdapterName,
> +                interface_stat) == -1) {
> +                info->value->has_statistics = false;
> +                g_free(interface_stat);
> +            } else {
> +                info->value->statistics = interface_stat;
> +                info->value->has_statistics = true;
> +            }
> +        }
>      }
>      WSACleanup();
>  out:
> diff --git a/qga/qapi-schema.json b/qga/qapi-schema.json
> index 90a0c86..17884c7 100644
> --- a/qga/qapi-schema.json
> +++ b/qga/qapi-schema.json
> @@ -643,6 +643,38 @@
>             'prefix': 'int'} }
> 
>  ##
> +# @GuestNetworkInterfaceStat:
> +#
> +# @rx-bytes: total bytes received
> +#
> +# @rx-packets: total packets received
> +#
> +# @rx-errs: bad packets received
> +#
> +# @rx-dropped: receiver dropped packets
> +#
> +# @tx-bytes: total bytes transmitted
> +#
> +# @tx-packets: total packets transmitted
> +#
> +# @tx-errs: packet transmit problems
> +#
> +# @tx-dropped: dropped packets transmitted
> +#
> +# Since: 2.11
> +##
> +{ 'struct': 'GuestNetworkInterfaceStat',
> +  'data': {'rx-bytes': 'uint64',
> +            'rx-packets': 'uint64',
> +            'rx-errs': 'uint64',
> +            'rx-dropped': 'uint64',
> +            'tx-bytes': 'uint64',
> +            'tx-packets': 'uint64',
> +            'tx-errs': 'uint64',
> +            'tx-dropped': 'uint64'
> +           } }
> +
> +##
>  # @GuestNetworkInterface:
>  #
>  # @name: The name of interface for which info are being delivered
> @@ -651,12 +683,16 @@
>  #
>  # @ip-addresses: List of addresses assigned to @name
>  #
> +# @statistics: various statistic counters related to @name
> +# (since 2.11)
> +#
>  # Since: 1.1
>  ##
>  { 'struct': 'GuestNetworkInterface',
>    'data': {'name': 'str',
>             '*hardware-address': 'str',
> -           '*ip-addresses': ['GuestIpAddress'] } }
> +           '*ip-addresses': ['GuestIpAddress'],
> +           '*statistics': 'GuestNetworkInterfaceStat' } }
> 
>  ##
>  # @guest-network-get-interfaces:
> -- 
> 1.8.3.1
>
ZhiPeng Lu Oct. 26, 2017, 1:42 a.m. UTC | #2
Pj4gKyAgICBpZiAoTk9fRVJST1IgPT0gR2V0SWZFbnRyeSgmYU1pYl9pZnJvdykpIHsNCg0KDQoN
Cg0KDQoNCnRoYW5rcywNCg0KDQpJIGZvdW5kIG1heSBiZSBvdmVyZmxvdyB1c2luZyBHZXRJZkVu
dHJ5LHRodXMgR2V0SWZFbnRyeTIgaW5zdGVhZCBvZiBHZXRJZkVudHJ5Lg0KDQoNCg0KDQoNCg0K
DQoNCg0KDQoNCuS4uuS6huiuqeaCqOeahFZQbGF06Jma5ouf5py65pWF6Zqc5ZKMZG9ja2Vy5pWF
6Zqc5b6X5Yiw6auY5pWI55qE5aSE55CG77yM6K+35LiK5oql5pWF6Zqc5YiwOiAkVlBsYXTmioDm
nK/mlK/mjIHjgIINCg0KDQroiqblv5fmnIsgbHV6aGlwZW5nDQoNCg0KDQoNCg0KDQpJVOW8gOWP
keW3peeoi+W4iCBJVCBEZXZlbG9wbWVudApFbmdpbmVlcg0K5pON5L2c57O757uf5Lqn5ZOB6YOo
L+S4reW/g+eglOeptumZoi/ns7vnu5/kuqflk4EgT1MgUHJvZHVjdCBEZXB0Li9DZW50cmFsIFLv
vIZEIEluc3RpdHV0ZS9TeXN0ZW0gUHJvZHVjdA0KDQoNCg0KDQoNCg0KDQoNCg0K5Zub5bed55yB
5oiQ6YO95biC5aSp5bqc5aSn6YGT5Lit5q61ODAw5Y+3DQpFOiBsdS56aGlwZW5nQHp0ZS5jb20u
Y24gDQp3d3cuenRlLmNvbS5jbg0KDQoNCg0KDQoNCg0KDQoNCg0KDQrljp/lp4vpgq7ku7YNCg0K
DQoNCg0K5Y+R5Lu25Lq677yaIDxtZHJvdGhAbGludXgudm5ldC5pYm0uY29tPjsNCuaUtuS7tuS6
uu+8muiKpuW/l+acizEwMTA4MjcyOw0K5oqE6YCB5Lq677yaIDxxZW11LWRldmVsQG5vbmdudS5v
cmc+O+iKpuW/l+acizEwMTA4MjcyOw0K5pelIOacnyDvvJoyMDE35bm0MTDmnIgyNuaXpSAwOTow
MA0K5Li7IOmimCDvvJpSZTogW1BBVENIIHY3IFJFU0VORF0gcWdhOiBBZGQgc3VwcG9ydCBuZXR3
b3JrIGludGVyZmFjZSBzdGF0aXN0aWNzIGluZ3Vlc3QtbmV0d29yay1nZXQtaW50ZXJmYWNlcyBj
b21tYW5kDQoNCg0KDQoNCg0KDQpRdW90aW5nIFpoaVBlbmcgTHUgKDIwMTctMDktMTIgMDM6NTQ6
MjYpDQo+IHdlIGNhbiBnZXQgdGhlIG5ldHdvcmsgaW50ZXJmYWNlIHN0YXRpc3RpY3MgaW5zaWRl
IGEgdmlydHVhbCBtYWNoaW5lIGJ5DQo+IGd1ZXN0LW5ldHdvcmstZ2V0LWludGVyZmFjZXMgY29t
bWFuZC4gaXQgaXMgdmVyeSB1c2VmdWwgZm9yIHVzIHRvIG1vbml0b3INCj4gYW5kIGFuYWx5emUg
bmV0d29yayB0cmFmZmljLg0KPiANCj4gU2lnbmVkLW9mZi1ieTogWmhpUGVuZyBMdSA8bHUuemhp
cGVuZ0B6dGUuY29tLmNuPg0KDQpUaGFua3MsIGFwcGxpZWQgdG8gcWdhIHRyZWU6DQogIGh0dHBz
Oi8vZ2l0aHViLmNvbS9tZHJvdGgvcWVtdS9jb21taXRzL3FnYQ0KDQpUaGVyZSB3ZXJlIGEgZmV3
IGlzc3VlcyB0aGF0IEkgbm90ZWQgYmVsb3csIGJ1dCBJIHRlc3RlZCBvbiBsaW51eC93aW5kb3dz
DQphbmQgdGhpbmdzIHNlZW0gdG8gYmUgd29ya2luZyB3ZWxsIHNvIEkgZml4ZWQgdGhlbSB1cCBp
biBteSB0cmVlLg0KDQo+IA0KPiAtLS0NCj4gdjEtPnYyOg0KPiAgLSBjb3JyZWN0IHNvbWUgc3Bl
bGxpbmcgbWlzdGFrZSBhbmQgYWRkIHRoZSBzdGF0cyBkYXRhIHRvIHRoZQ0KPiAgICBndWVzdC1u
ZXR3b3JrLWdldC1pbnRlcmZhY2VzIGNvbW1hbmQgaW5zdGVhZCBvZiBhZGRpbmcgYSBuZXcgY29t
bWFuZC4NCj4gdjItdjM6DQo+ICAtIG9wdGltaXplIGZ1bmN0aW9uIGltcGxlbWVudGF0aW9uDQo+
IHYzLT52NDoNCj4gIC0gbW9kaWZ5IGNvbXBpbGUgZXJyb3INCj4gdjQtPnY1Og0KPiAgLSByZW5h
bWUgc29tZSB0ZW1wb3JhcnkgdmFyaWFibGVzIGFuZCBhZGQgc3RyX3RyaW1fb2ZmIGZ1bmN0aW9u
IGZvcg0KPiAgICBjYWxjdWxhdGluZyB0aGUgc3BhY2UgbnVtIGluIGZyb250IG9mIHRoZSBzdHJp
bmcgaW4gZ3Vlc3RfZ2V0X25ldHdvcmtfc3RhdHMNCj4gdjUtPnY2Og0KPiAgLSB1c2UgZ19zdHJj
aHVnIGluc3RlYWQgb2Ygc3RyX3RyaW1fb2ZmIGltcGxlbWVudGVkIGJ5IG15c2VsZg0KPiB2Ni0+
djc6DQo+ICAtIGFkZCBpbXBsZW1lbnRhdGlvbiBmb3Igd2luZG93cw0KPiAtLS0NCj4gIHFnYS9j
b21tYW5kcy1wb3NpeC5jIHwgNzIgKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysr
KysrKysrKysrKysrKysrLQ0KPiAgcWdhL2NvbW1hbmRzLXdpbjMyLmMgfCA0OCArKysrKysrKysr
KysrKysrKysrKysrKysrKysrKysrKysrKw0KPiAgcWdhL3FhcGktc2NoZW1hLmpzb24gfCAzOCAr
KysrKysrKysrKysrKysrKysrKysrKysrKy0NCj4gIDMgZmlsZXMgY2hhbmdlZCwgMTU2IGluc2Vy
dGlvbnMoKyksIDIgZGVsZXRpb25zKC0pDQo+IA0KPiBkaWZmIC0tZ2l0IGEvcWdhL2NvbW1hbmRz
LXBvc2l4LmMgYi9xZ2EvY29tbWFuZHMtcG9zaXguYw0KPiBpbmRleCBhYjBjNjNkLi5kYTVkYmEw
IDEwMDY0NA0KPiAtLS0gYS9xZ2EvY29tbWFuZHMtcG9zaXguYw0KPiArKysgYi9xZ2EvY29tbWFu
ZHMtcG9zaXguYw0KPiBAQCAtMTY0Myw2ICsxNjQzLDY1IEBAIGd1ZXN0X2ZpbmRfaW50ZXJmYWNl
KEd1ZXN0TmV0d29ya0ludGVyZmFjZUxpc3QgKmhlYWQsDQo+ICAgICAgcmV0dXJuIGhlYWQ7DQo+
ICB9DQo+IA0KPiArc3RhdGljIGludCBndWVzdF9nZXRfbmV0d29ya19zdGF0cyhjb25zdCBjaGFy
ICpuYW1lLA0KPiArICAgICAgICAgICAgICAgICAgICAgICBHdWVzdE5ldHdvcmtJbnRlcmZhY2VT
dGF0ICpzdGF0cykNCj4gK3sNCj4gKyAgICBpbnQgbmFtZV9sZW47DQo+ICsgICAgY2hhciBjb25z
dCAqZGV2aW5mbyA9ICIvcHJvYy9uZXQvZGV2IjsNCj4gKyAgICBGSUxFICpmcDsNCj4gKyAgICBj
aGFyICpsaW5lID0gTlVMTCwgKmNvbG9uOw0KPiArICAgIHNpemVfdCBuOw0KDQpOb3Qgc3VyZSBp
ZiBpdCBhZmZlY3RzIGJlaGF2aW9yIGluIHByYWN0aWNlLCBidXQgZ2V0bGluZSgpIGRvY3VtZW50
YXRpb24NCnN0YXRlcyB0aGF0ICpsaW5lIGlzIG9ubHkgYWxsb2NhdGVkIGlmICpsaW5lID09IE5V
TEwgKmFuZCogbiA9PSAwLiBTbyB3ZQ0Kc2hvdWxkIHNldCBuIHRvIDAgYmVmb3JlIGVhY2ggY2Fs
bCB0byBiZSBzYWZlLg0KDQo+ICsgICAgZnAgPSBmb3BlbihkZXZpbmZvLCAiciIpOw0KPiArICAg
IGlmICghZnApIHsNCj4gKyAgICAgICAgcmV0dXJuIC0xOw0KPiArICAgIH0NCj4gKyAgICBuYW1l
X2xlbiA9IHN0cmxlbihuYW1lKTsNCj4gKyAgICB3aGlsZSAoZ2V0bGluZSgmbGluZSwgJm4sIGZw
KSAhPSAtMSkgew0KDQpTaW5jZSAnbGluZScgaXMgYmVpbmcgYWxsb2NhdGVkIGJ5IGdldGxpbmUo
KSwgd2UgbmVlZCB0byBmcmVlIGl0IGFmdGVyDQplYWNoIGNhbGwsIG9yIHJlbHkgb24gaXQgdG8g
cmVhbGxvYyBhbmQgdGhlbiBmcmVlIHRoYXQgdmFsdWUgYmVmb3JlDQpyZXR1cm5pbmcuIFRoZSBs
YXR0ZXIgc2VlbXMgc2ltcGxlciBpbiB0aGlzIGNhc2UuDQoNCj4gKyAgICAgICAgbG9uZyBsb25n
IGR1bW15Ow0KPiArICAgICAgICBsb25nIGxvbmcgcnhfYnl0ZXM7DQo+ICsgICAgICAgIGxvbmcg
bG9uZyByeF9wYWNrZXRzOw0KPiArICAgICAgICBsb25nIGxvbmcgcnhfZXJyczsNCj4gKyAgICAg
ICAgbG9uZyBsb25nIHJ4X2Ryb3BwZWQ7DQo+ICsgICAgICAgIGxvbmcgbG9uZyB0eF9ieXRlczsN
Cj4gKyAgICAgICAgbG9uZyBsb25nIHR4X3BhY2tldHM7DQo+ICsgICAgICAgIGxvbmcgbG9uZyB0
eF9lcnJzOw0KPiArICAgICAgICBsb25nIGxvbmcgdHhfZHJvcHBlZDsNCj4gKyAgICAgICAgY2hh
ciAqdHJpbV9saW5lOw0KPiArICAgICAgICB0cmltX2xpbmUgPSBnX3N0cmNodWcobGluZSk7DQo+
ICsgICAgICAgIGlmICh0cmltX2xpbmVbMF0gPT0gJ1wwJykgew0KPiArICAgICAgICAgICAgY29u
dGludWU7DQo+ICsgICAgICAgIH0NCj4gKyAgICAgICAgY29sb24gPSBzdHJjaHIodHJpbV9saW5l
LCAnOicpOw0KPiArICAgICAgICBpZiAoIWNvbG9uKSB7DQo+ICsgICAgICAgICAgICBjb250aW51
ZTsNCj4gKyAgICAgICAgfQ0KPiArICAgICAgICBpZiAoY29sb24gLSBuYW1lX2xlbiAgPT0gdHJp
bV9saW5lICYmDQo+ICsgICAgICAgICAgIHN0cm5jbXAodHJpbV9saW5lLCBuYW1lLCBuYW1lX2xl
bikgPT0gMCkgew0KPiArICAgICAgICAgICAgaWYgKHNzY2FuZihjb2xvbiArIDEsDQo+ICsgICAg
ICAgICAgICAgICAgIiVsbGQgJWxsZCAlbGxkICVsbGQgJWxsZCAlbGxkICVsbGQgJWxsZCAlbGxk
ICVsbGQgJWxsZCAlbGxkICVsbGQgJWxsZCAlbGxkICVsbGQiLA0KPiArICAgICAgICAgICAgICAg
ICAgJnJ4X2J5dGVzLCAmcnhfcGFja2V0cywgJnJ4X2VycnMsICZyeF9kcm9wcGVkLA0KPiArICAg
ICAgICAgICAgICAgICAgJmR1bW15LCAmZHVtbXksICZkdW1teSwgJmR1bW15LA0KPiArICAgICAg
ICAgICAgICAgICAgJnR4X2J5dGVzLCAmdHhfcGFja2V0cywgJnR4X2VycnMsICZ0eF9kcm9wcGVk
LA0KPiArICAgICAgICAgICAgICAgICAgJmR1bW15LCAmZHVtbXksICZkdW1teSwgJmR1bW15KSAh
PSAxNikgew0KPiArICAgICAgICAgICAgICAgIGNvbnRpbnVlOw0KPiArICAgICAgICAgICAgfQ0K
PiArICAgICAgICAgICAgc3RhdHMtPnJ4X2J5dGVzID0gcnhfYnl0ZXM7DQo+ICsgICAgICAgICAg
ICBzdGF0cy0+cnhfcGFja2V0cyA9IHJ4X3BhY2tldHM7DQo+ICsgICAgICAgICAgICBzdGF0cy0+
cnhfZXJycyA9IHJ4X2VycnM7DQo+ICsgICAgICAgICAgICBzdGF0cy0+cnhfZHJvcHBlZCA9IHJ4
X2Ryb3BwZWQ7DQo+ICsgICAgICAgICAgICBzdGF0cy0+dHhfYnl0ZXMgPSB0eF9ieXRlczsNCj4g
KyAgICAgICAgICAgIHN0YXRzLT50eF9wYWNrZXRzID0gdHhfcGFja2V0czsNCj4gKyAgICAgICAg
ICAgIHN0YXRzLT50eF9lcnJzID0gdHhfZXJyczsNCj4gKyAgICAgICAgICAgIHN0YXRzLT50eF9k
cm9wcGVkID0gdHhfZHJvcHBlZDsNCj4gKyAgICAgICAgICAgIGZjbG9zZShmcCk7DQo+ICsgICAg
ICAgICAgICByZXR1cm4gMDsNCj4gKyAgICAgICAgfQ0KPiArICAgIH0NCj4gKyAgICBmY2xvc2Uo
ZnApOw0KPiArICAgIGdfZGVidWcoIi9wcm9jL25ldC9kZXY6IEludGVyZmFjZSBub3QgZm91bmQi
KTsNCg0KUmVwb3J0aW5nIHRoZSBzcGVjaWZpYyBpbnRlcmZhY2UgbmFtZSBtaWdodCBiZSB1c2Vm
dWwgaGVyZS4NCg0KPiArICAgIHJldHVybiAtMTsNCj4gK30NCj4gKw0KPiAgLyoNCj4gICAqIEJ1
aWxkIGluZm9ybWF0aW9uIGFib3V0IGd1ZXN0IGludGVyZmFjZXMNCj4gICAqLw0KPiBAQCAtMTY1
OSw2ICsxNzE4LDcgQEAgR3Vlc3ROZXR3b3JrSW50ZXJmYWNlTGlzdCAqcW1wX2d1ZXN0X25ldHdv
cmtfZ2V0X2ludGVyZmFjZXMoRXJyb3IgKiplcnJwKQ0KPiAgICAgIGZvciAoaWZhID0gaWZhcDsg
aWZhOyBpZmEgPSBpZmEtPmlmYV9uZXh0KSB7DQo+ICAgICAgICAgIEd1ZXN0TmV0d29ya0ludGVy
ZmFjZUxpc3QgKmluZm87DQo+ICAgICAgICAgIEd1ZXN0SXBBZGRyZXNzTGlzdCAqKmFkZHJlc3Nf
bGlzdCA9IE5VTEwsICphZGRyZXNzX2l0ZW0gPSBOVUxMOw0KPiArICAgICAgICBHdWVzdE5ldHdv
cmtJbnRlcmZhY2VTdGF0ICAqaW50ZXJmYWNlX3N0YXQgPSBOVUxMOw0KPiAgICAgICAgICBjaGFy
IGFkZHI0W0lORVRfQUREUlNUUkxFTl07DQo+ICAgICAgICAgIGNoYXIgYWRkcjZbSU5FVDZfQURE
UlNUUkxFTl07DQo+ICAgICAgICAgIGludCBzb2NrOw0KPiBAQCAtMTc3OCw3ICsxODM4LDE3IEBA
IEd1ZXN0TmV0d29ya0ludGVyZmFjZUxpc3QgKnFtcF9ndWVzdF9uZXR3b3JrX2dldF9pbnRlcmZh
Y2VzKEVycm9yICoqZXJycCkNCj4gDQo+ICAgICAgICAgIGluZm8tPnZhbHVlLT5oYXNfaXBfYWRk
cmVzc2VzID0gdHJ1ZTsNCj4gDQo+IC0NCj4gKyAgICAgICAgaWYgKCFpbmZvLT52YWx1ZS0+aGFz
X3N0YXRpc3RpY3MpIHsNCj4gKyAgICAgICAgICAgIGludGVyZmFjZV9zdGF0ID0gZ19tYWxsb2Mw
KHNpemVvZigqaW50ZXJmYWNlX3N0YXQpKTsNCj4gKyAgICAgICAgICAgIGlmIChndWVzdF9nZXRf
bmV0d29ya19zdGF0cyhpbmZvLT52YWx1ZS0+bmFtZSwNCj4gKyAgICAgICAgICAgICAgICBpbnRl
cmZhY2Vfc3RhdCkgPT0gLTEpIHsNCj4gKyAgICAgICAgICAgICAgICBpbmZvLT52YWx1ZS0+aGFz
X3N0YXRpc3RpY3MgPSBmYWxzZTsNCj4gKyAgICAgICAgICAgICAgICBnX2ZyZWUoaW50ZXJmYWNl
X3N0YXQpOw0KPiArICAgICAgICAgICAgfSBlbHNlIHsNCj4gKyAgICAgICAgICAgICAgICBpbmZv
LT52YWx1ZS0+c3RhdGlzdGljcyA9IGludGVyZmFjZV9zdGF0Ow0KPiArICAgICAgICAgICAgICAg
IGluZm8tPnZhbHVlLT5oYXNfc3RhdGlzdGljcyA9IHRydWU7DQo+ICsgICAgICAgICAgICB9DQo+
ICsgICAgICAgIH0NCj4gICAgICB9DQo+IA0KPiAgICAgIGZyZWVpZmFkZHJzKGlmYXApOw0KPiBk
aWZmIC0tZ2l0IGEvcWdhL2NvbW1hbmRzLXdpbjMyLmMgYi9xZ2EvY29tbWFuZHMtd2luMzIuYw0K
PiBpbmRleCA2MTlkYmQyLi5lODkxMjUzIDEwMDY0NA0KPiAtLS0gYS9xZ2EvY29tbWFuZHMtd2lu
MzIuYw0KPiArKysgYi9xZ2EvY29tbWFuZHMtd2luMzIuYw0KPiBAQCAtMTE1Miw2ICsxMTUyLDQy
IEBAIG91dDoNCj4gIH0NCj4gICNlbmRpZg0KPiANCj4gK3N0YXRpYyBEV09SRCBnZXRfaW50ZXJm
YWNlX2luZGV4KGNvbnN0IGNoYXIgKmd1aWQpDQo+ICt7DQo+ICsgICAgVUxPTkcgaW5kZXg7DQo+
ICsgICAgRFdPUkQgc3RhdHVzOw0KPiArICAgIHdjaGFyX3Qgd2J1Zls1MTJdOw0KPiArICAgIHNu
d3ByaW50Zih3YnVmLCBzaXplb2Yod2J1ZiksIEwiXFxkZXZpY2VcXHRjcGlwXyVzIiwgZ3VpZCk7
DQo+ICsgICAgd2J1ZltzaXplb2Yod2J1ZikgLSAxXSA9IDA7DQoNCndjaGFyX3QgY2FuIGJlIGxh
cmdlciB0aGFuIDEgYnl0ZSwgc28gdXNpbmcgc2l6ZW9mKHdjaGFyX3RbXSkgYXMgYW4NCmluZGV4
IGludG8gYSB3Y2hhcl90W10gY2FuIGNhdXNlIGFuIG92ZXJydW4uDQoNCj4gKyAgICBzdGF0dXMg
PSBHZXRBZGFwdGVySW5kZXggKHdidWYsICZpbmRleCk7DQo+ICsgICAgaWYgKHN0YXR1cyAhPSBO
T19FUlJPUikgew0KPiArICAgICAgICByZXR1cm4gKERXT1JEKX4wOw0KPiArICAgIH0gZWxzZSB7
DQo+ICsgICAgICAgIHJldHVybiBpbmRleDsNCj4gKyAgICB9DQo+ICt9DQo+ICtzdGF0aWMgaW50
IGd1ZXN0X2dldF9uZXR3b3JrX3N0YXRzKGNvbnN0IGNoYXIgKm5hbWUsDQo+ICsgICAgICAgICAg
ICAgICAgICAgICAgIEd1ZXN0TmV0d29ya0ludGVyZmFjZVN0YXQgKnN0YXRzKQ0KPiArew0KPiAr
ICAgIERXT1JEIElmSW5kZXggPSAwOw0KPiArICAgIE1JQl9JRlJPVyBhTWliX2lmcm93Ow0KPiAr
ICAgIG1lbXNldCgmYU1pYl9pZnJvdywgMCwgc2l6ZW9mKGFNaWJfaWZyb3cpKTsNCj4gKyAgICBJ
ZkluZGV4ID0gZ2V0X2ludGVyZmFjZV9pbmRleChuYW1lKTsNCg0KUGVyIENPRElOR19TVFlMRSB2
YXJpYWJsZSBuYW1lcyBzaG91bGQgYmUgbG93ZXJjYXNlIHdpdGggIl8iIGZvcg0Kc2VwYXJhdGlu
ZyB3b3Jkcw0KDQo+ICsgICAgYU1pYl9pZnJvdy5kd0luZGV4ID0gSWZJbmRleDsNCj4gKyAgICBp
ZiAoTk9fRVJST1IgPT0gR2V0SWZFbnRyeSgmYU1pYl9pZnJvdykpIHsNCj4gKyAgICAgICAgc3Rh
dHMtPnJ4X2J5dGVzID0gYU1pYl9pZnJvdy5kd0luT2N0ZXRzOw0KPiArICAgICAgICBzdGF0cy0+
cnhfcGFja2V0cyA9IGFNaWJfaWZyb3cuZHdJblVjYXN0UGt0czsNCj4gKyAgICAgICAgc3RhdHMt
PnJ4X2VycnMgPSBhTWliX2lmcm93LmR3SW5FcnJvcnM7DQo+ICsgICAgICAgIHN0YXRzLT5yeF9k
cm9wcGVkID0gYU1pYl9pZnJvdy5kd0luRGlzY2FyZHM7DQo+ICsgICAgICAgIHN0YXRzLT50eF9i
eXRlcyA9IGFNaWJfaWZyb3cuZHdPdXRPY3RldHM7DQo+ICsgICAgICAgIHN0YXRzLT50eF9wYWNr
ZXRzID0gYU1pYl9pZnJvdy5kd091dFVjYXN0UGt0czsNCj4gKyAgICAgICAgc3RhdHMtPnR4X2Vy
cnMgPSBhTWliX2lmcm93LmR3T3V0RXJyb3JzOw0KPiArICAgICAgICBzdGF0cy0+dHhfZHJvcHBl
ZCA9IGFNaWJfaWZyb3cuZHdPdXREaXNjYXJkczsNCj4gKyAgICAgICAgcmV0dXJuIDA7DQo+ICsg
ICAgfQ0KPiArICAgIHJldHVybiAtMTsNCj4gK30NCj4gKw0KPiAgR3Vlc3ROZXR3b3JrSW50ZXJm
YWNlTGlzdCAqcW1wX2d1ZXN0X25ldHdvcmtfZ2V0X2ludGVyZmFjZXMoRXJyb3IgKiplcnJwKQ0K
PiAgew0KPiAgICAgIElQX0FEQVBURVJfQUREUkVTU0VTICphZHB0cl9hZGRycywgKmFkZHI7DQo+
IEBAIC0xMTU5LDYgKzExOTUsNyBAQCBHdWVzdE5ldHdvcmtJbnRlcmZhY2VMaXN0ICpxbXBfZ3Vl
c3RfbmV0d29ya19nZXRfaW50ZXJmYWNlcyhFcnJvciAqKmVycnApDQo+ICAgICAgR3Vlc3ROZXR3
b3JrSW50ZXJmYWNlTGlzdCAqaGVhZCA9IE5VTEwsICpjdXJfaXRlbSA9IE5VTEw7DQo+ICAgICAg
R3Vlc3RJcEFkZHJlc3NMaXN0ICpoZWFkX2FkZHIsICpjdXJfYWRkcjsNCj4gICAgICBHdWVzdE5l
dHdvcmtJbnRlcmZhY2VMaXN0ICppbmZvOw0KPiArICAgIEd1ZXN0TmV0d29ya0ludGVyZmFjZVN0
YXQgKmludGVyZmFjZV9zdGF0ID0gTlVMTDsNCj4gICAgICBHdWVzdElwQWRkcmVzc0xpc3QgKmFk
ZHJlc3NfaXRlbSA9IE5VTEw7DQo+ICAgICAgdW5zaWduZWQgY2hhciAqbWFjX2FkZHI7DQo+ICAg
ICAgY2hhciAqYWRkcl9zdHI7DQo+IEBAIC0xMjM4LDYgKzEyNzUsMTcgQEAgR3Vlc3ROZXR3b3Jr
SW50ZXJmYWNlTGlzdCAqcW1wX2d1ZXN0X25ldHdvcmtfZ2V0X2ludGVyZmFjZXMoRXJyb3IgKipl
cnJwKQ0KPiAgICAgICAgICAgICAgaW5mby0+dmFsdWUtPmhhc19pcF9hZGRyZXNzZXMgPSB0cnVl
Ow0KPiAgICAgICAgICAgICAgaW5mby0+dmFsdWUtPmlwX2FkZHJlc3NlcyA9IGhlYWRfYWRkcjsN
Cj4gICAgICAgICAgfQ0KPiArICAgICAgICBpZiAoIWluZm8tPnZhbHVlLT5oYXNfc3RhdGlzdGlj
cykgew0KPiArICAgICAgICAgICAgaW50ZXJmYWNlX3N0YXQgPSBnX21hbGxvYzAoc2l6ZW9mKCpp
bnRlcmZhY2Vfc3RhdCkpOw0KPiArICAgICAgICAgICAgaWYgKGd1ZXN0X2dldF9uZXR3b3JrX3N0
YXRzKGFkZHItPkFkYXB0ZXJOYW1lLA0KPiArICAgICAgICAgICAgICAgIGludGVyZmFjZV9zdGF0
KSA9PSAtMSkgew0KPiArICAgICAgICAgICAgICAgIGluZm8tPnZhbHVlLT5oYXNfc3RhdGlzdGlj
cyA9IGZhbHNlOw0KPiArICAgICAgICAgICAgICAgIGdfZnJlZShpbnRlcmZhY2Vfc3RhdCk7DQo+
ICsgICAgICAgICAgICB9IGVsc2Ugew0KPiArICAgICAgICAgICAgICAgIGluZm8tPnZhbHVlLT5z
dGF0aXN0aWNzID0gaW50ZXJmYWNlX3N0YXQ7DQo+ICsgICAgICAgICAgICAgICAgaW5mby0+dmFs
dWUtPmhhc19zdGF0aXN0aWNzID0gdHJ1ZTsNCj4gKyAgICAgICAgICAgIH0NCj4gKyAgICAgICAg
fQ0KPiAgICAgIH0NCj4gICAgICBXU0FDbGVhbnVwKCk7DQo+ICBvdXQ6DQo+IGRpZmYgLS1naXQg
YS9xZ2EvcWFwaS1zY2hlbWEuanNvbiBiL3FnYS9xYXBpLXNjaGVtYS5qc29uDQo+IGluZGV4IDkw
YTBjODYuLjE3ODg0YzcgMTAwNjQ0DQo+IC0tLSBhL3FnYS9xYXBpLXNjaGVtYS5qc29uDQo+ICsr
KyBiL3FnYS9xYXBpLXNjaGVtYS5qc29uDQo+IEBAIC02NDMsNiArNjQzLDM4IEBADQo+ICAgICAg
ICAgICAgICdwcmVmaXgnOiAnaW50J30gfQ0KPiANCj4gICMjDQo+ICsjIEBHdWVzdE5ldHdvcmtJ
bnRlcmZhY2VTdGF0Og0KPiArIw0KPiArIyBAcngtYnl0ZXM6IHRvdGFsIGJ5dGVzIHJlY2VpdmVk
DQo+ICsjDQo+ICsjIEByeC1wYWNrZXRzOiB0b3RhbCBwYWNrZXRzIHJlY2VpdmVkDQo+ICsjDQo+
ICsjIEByeC1lcnJzOiBiYWQgcGFja2V0cyByZWNlaXZlZA0KPiArIw0KPiArIyBAcngtZHJvcHBl
ZDogcmVjZWl2ZXIgZHJvcHBlZCBwYWNrZXRzDQo+ICsjDQo+ICsjIEB0eC1ieXRlczogdG90YWwg
Ynl0ZXMgdHJhbnNtaXR0ZWQNCj4gKyMNCj4gKyMgQHR4LXBhY2tldHM6IHRvdGFsIHBhY2tldHMg
dHJhbnNtaXR0ZWQNCj4gKyMNCj4gKyMgQHR4LWVycnM6IHBhY2tldCB0cmFuc21pdCBwcm9ibGVt
cw0KPiArIw0KPiArIyBAdHgtZHJvcHBlZDogZHJvcHBlZCBwYWNrZXRzIHRyYW5zbWl0dGVkDQo+
ICsjDQo+ICsjIFNpbmNlOiAyLjExDQo+ICsjIw0KPiAreyAnc3RydWN0JzogJ0d1ZXN0TmV0d29y
a0ludGVyZmFjZVN0YXQnLA0KPiArICAnZGF0YSc6IHsncngtYnl0ZXMnOiAndWludDY0JywNCj4g
KyAgICAgICAgICAgICdyeC1wYWNrZXRzJzogJ3VpbnQ2NCcsDQo+ICsgICAgICAgICAgICAncngt
ZXJycyc6ICd1aW50NjQnLA0KPiArICAgICAgICAgICAgJ3J4LWRyb3BwZWQnOiAndWludDY0JywN
Cj4gKyAgICAgICAgICAgICd0eC1ieXRlcyc6ICd1aW50NjQnLA0KPiArICAgICAgICAgICAgJ3R4
LXBhY2tldHMnOiAndWludDY0JywNCj4gKyAgICAgICAgICAgICd0eC1lcnJzJzogJ3VpbnQ2NCcs
DQo+ICsgICAgICAgICAgICAndHgtZHJvcHBlZCc6ICd1aW50NjQnDQo+ICsgICAgICAgICAgIH0g
fQ0KPiArDQo+ICsjIw0KPiAgIyBAR3Vlc3ROZXR3b3JrSW50ZXJmYWNlOg0KPiAgIw0KPiAgIyBA
bmFtZTogVGhlIG5hbWUgb2YgaW50ZXJmYWNlIGZvciB3aGljaCBpbmZvIGFyZSBiZWluZyBkZWxp
dmVyZWQNCj4gQEAgLTY1MSwxMiArNjgzLDE2IEBADQo+ICAjDQo+ICAjIEBpcC1hZGRyZXNzZXM6
IExpc3Qgb2YgYWRkcmVzc2VzIGFzc2lnbmVkIHRvIEBuYW1lDQo+ICAjDQo+ICsjIEBzdGF0aXN0
aWNzOiB2YXJpb3VzIHN0YXRpc3RpYyBjb3VudGVycyByZWxhdGVkIHRvIEBuYW1lDQo+ICsjIChz
aW5jZSAyLjExKQ0KPiArIw0KPiAgIyBTaW5jZTogMS4xDQo+ICAjIw0KPiAgeyAnc3RydWN0Jzog
J0d1ZXN0TmV0d29ya0ludGVyZmFjZScsDQo+ICAgICdkYXRhJzogeyduYW1lJzogJ3N0cicsDQo+
ICAgICAgICAgICAgICcqaGFyZHdhcmUtYWRkcmVzcyc6ICdzdHInLA0KPiAtICAgICAgICAgICAn
KmlwLWFkZHJlc3Nlcyc6IFsnR3Vlc3RJcEFkZHJlc3MnXSB9IH0NCj4gKyAgICAgICAgICAgJypp
cC1hZGRyZXNzZXMnOiBbJ0d1ZXN0SXBBZGRyZXNzJ10sDQo+ICsgICAgICAgICAgICcqc3RhdGlz
dGljcyc6ICdHdWVzdE5ldHdvcmtJbnRlcmZhY2VTdGF0JyB9IH0NCj4gDQo+ICAjIw0KPiAgIyBA
Z3Vlc3QtbmV0d29yay1nZXQtaW50ZXJmYWNlczoNCj4gLS0gDQo+IDEuOC4zLjENCj4=
Michael Roth Oct. 27, 2017, 12:44 a.m. UTC | #3
Quoting lu.zhipeng@zte.com.cn (2017-10-25 20:42:10)
> 
> >> +    if (NO_ERROR == GetIfEntry(&aMib_ifrow)) {
> 
> 
> thanks,
> 
> I found may be overflow using GetIfEntry,thus GetIfEntry2 instead of 
> GetIfEntry.

I tried your fix-up patch at:
 https://patch-diff.githubusercontent.com/raw/mdroth/qemu/pull/5.patch

but ran into the compile issue below in a Fedora 20 mingw64 build environment.
It looks like you need MIB_IF_ROW2 instead of MIB_IFROW2, and even then it
looks like the struct fields are different and need to be fixed up.

I'll keep the current patch as it stands, but please send a tested
standalone fix against the qga tree to the list so we can get this case
addressed before rc0. I would also suggest we disable w32 stats completely
if GetIfEntry2() isn't available, since dealing with overflows is painful
from a management perspective.


x86_64-w64-mingw32-gcc -I/home/mdroth/qemu-build-w64/qga -Iqga -I/home/mdroth/w/qemu4.git/tcg -I/home/mdroth/w/qemu4.git/tcg/i386 -I. -I/home/mdroth/w/qemu4.git -I/home/mdroth/w/qemu4.git/accel/tcg -I/home/mdroth/w/qemu4.git/include -I/usr/x86_64-w64-mingw32/sys-root/mingw/include/pixman-1  -I/home/mdroth/w/qemu4.git/dtc/libfdt -Werror -mms-bitfields -I/usr/x86_64-w64-mingw32/sys-root/mingw/include/glib-2.0 -I/usr/x86_64-w64-mingw32/sys-root/mingw/lib/glib-2.0/include  -m64 -mcx16 -mthreads -D__USE_MINGW_ANSI_STDIO=1 -DWIN32_LEAN_AND_MEAN -DWINVER=0x501 -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -Wstrict-prototypes -Wredundant-decls -Wall -Wundef -Wwrite-strings -Wmissing-prototypes -fno-strict-aliasing -fno-common -fwrapv  -Wall -Wendif-labels -Wno-missing-include-dirs -Wempty-body -Wnested-externs -Wformat-security -Wformat-y2k -Winit-self -Wignored-qualifiers -Wold-style-declaration -Wold-style-definition -Wtype-limits -fstack-protector-all -isystem /home/mdroth/w/vss-win32/ -I/home/mdroth/w/qemu4.git/tests -I qga/qapi-generated -MMD -MP -MT qga/service-win32.o -MF qga/service-win32.d -O2 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -g   -c -o qga/service-win32.o /home/mdroth/w/qemu4.git/qga/service-win32.c
/home/mdroth/w/qemu4.git/qga/commands-win32.c: In function 'guest_get_network_stats':
/home/mdroth/w/qemu4.git/qga/commands-win32.c:1200:20: error: 'MIB_IF_ROW2' has no member named 'dwIndex'
         a_mid_ifrow.dwIndex = if_index;
                    ^
/home/mdroth/w/qemu4.git/qga/commands-win32.c:1202:42: error: 'MIB_IF_ROW2' has no member named 'dwInOctets'
             stats->rx_bytes = a_mid_ifrow.dwInOctets;
                                          ^
/home/mdroth/w/qemu4.git/qga/commands-win32.c:1203:44: error: 'MIB_IF_ROW2' has no member named 'dwInUcastPkts'
             stats->rx_packets = a_mid_ifrow.dwInUcastPkts;
                                            ^
/home/mdroth/w/qemu4.git/qga/commands-win32.c:1204:41: error: 'MIB_IF_ROW2' has no member named 'dwInErrors'
             stats->rx_errs = a_mid_ifrow.dwInErrors;
                                         ^
/home/mdroth/w/qemu4.git/qga/commands-win32.c:1205:44: error: 'MIB_IF_ROW2' has no member named 'dwInDiscards'
             stats->rx_dropped = a_mid_ifrow.dwInDiscards;
                                            ^
/home/mdroth/w/qemu4.git/qga/commands-win32.c:1206:42: error: 'MIB_IF_ROW2' has no member named 'dwOutOctets'
             stats->tx_bytes = a_mid_ifrow.dwOutOctets;
                                          ^
/home/mdroth/w/qemu4.git/qga/commands-win32.c:1207:44: error: 'MIB_IF_ROW2' has no member named 'dwOutUcastPkts'
             stats->tx_packets = a_mid_ifrow.dwOutUcastPkts;
                                            ^
/home/mdroth/w/qemu4.git/qga/commands-win32.c:1208:41: error: 'MIB_IF_ROW2' has no member named 'dwOutErrors'
             stats->tx_errs = a_mid_ifrow.dwOutErrors;
                                         ^
/home/mdroth/w/qemu4.git/qga/commands-win32.c:1209:44: error: 'MIB_IF_ROW2' has no member named 'dwOutDiscards'
             stats->tx_dropped = a_mid_ifrow.dwOutDiscards;
                                            ^
make: *** [qga/commands-win32.o] Error 1
make: *** Waiting for unfinished jobs....

> 
> 
> 为了让您的VPlat虚拟机故障和docker故障得到高效的处理,请上报故障到: $VPlat技术支
> 持。
> 
> 芦志朋 luzhipeng
> 
> 
> IT开发工程师 IT Development Engineer
> 操作系统产品部/中心研究院/系统产品 OS Product Dept./Central R&D Institute/
> System Product
> 
> 
> [cid]          [cid]
>                四川省成都市天府大道中段800号
>                E: lu.zhipeng@zte.com.cn
>                www.zte.com.cn
> 
> 原始邮件
> 发件人: <mdroth@linux.vnet.ibm.com>;
> 收件人:芦志朋10108272;
> 抄送人: <qemu-devel@nongnu.org>;芦志朋10108272;
> 日期:2017年10月26日 09:00
> 主题:Re: [PATCH v7 RESEND] qga: Add support network interface statistics
> inguest-network-get-interfaces command
> 
> 
> Quoting ZhiPeng Lu (2017-09-12 03:54:26)
> > we can get the network interface statistics inside a virtual machine by
> > guest-network-get-interfaces command. it is very useful for us to monitor
> > and analyze network traffic.
> > 
> > Signed-off-by: ZhiPeng Lu <lu.zhipeng@zte.com.cn>
> 
> Thanks, applied to qga tree:
>   https://github.com/mdroth/qemu/commits/qga
> 
> There were a few issues that I noted below, but I tested on linux/windows
> and things seem to be working well so I fixed them up in my tree.
> 
> > 
> > ---
> > v1->v2:
> >  - correct some spelling mistake and add the stats data to the
> >    guest-network-get-interfaces command instead of adding a new command.
> > v2-v3:
> >  - optimize function implementation
> > v3->v4:
> >  - modify compile error
> > v4->v5:
> >  - rename some temporary variables and add str_trim_off function for
> >
>     calculating the space num in front of the string in guest_get_network_stats
> > v5->v6:
> >  - use g_strchug instead of str_trim_off implemented by myself
> > v6->v7:
> >  - add implementation for windows
> > ---
> >  qga/commands-posix.c |
>  72 +++++++++++++++++++++++++++++++++++++++++++++++++++-
> >  qga/commands-win32.c | 48 +++++++++++++++++++++++++++++++++++
> >  qga/qapi-schema.json | 38 ++++++++++++++++++++++++++-
> >  3 files changed, 156 insertions(+), 2 deletions(-)
> > 
> > diff --git a/qga/commands-posix.c b/qga/commands-posix.c
> > index ab0c63d..da5dba0 100644
> > --- a/qga/commands-posix.c
> > +++ b/qga/commands-posix.c
> > @@ -1643,6 +1643,65 @@ guest_find_interface(GuestNetworkInterfaceList *head,
> >      return head;
> >  }
> > 
> > +static int guest_get_network_stats(const char *name,
> > +                       GuestNetworkInterfaceStat *stats)
> > +{
> > +    int name_len;
> > +    char const *devinfo = "/proc/net/dev";
> > +    FILE *fp;
> > +    char *line = NULL, *colon;
> > +    size_t n;
> 
> Not sure if it affects behavior in practice, but getline() documentation
> states that *line is only allocated if *line == NULL *and* n == 0. So we
> should set n to 0 before each call to be safe.
> 
> > +    fp = fopen(devinfo, "r");
> > +    if (!fp) {
> > +        return -1;
> > +    }
> > +    name_len = strlen(name);
> > +    while (getline(&line, &n, fp) != -1) {
> 
> Since 'line' is being allocated by getline(), we need to free it after
> each call, or rely on it to realloc and then free that value before
> returning. The latter seems simpler in this case.
> 
> > +        long long dummy;
> > +        long long rx_bytes;
> > +        long long rx_packets;
> > +        long long rx_errs;
> > +        long long rx_dropped;
> > +        long long tx_bytes;
> > +        long long tx_packets;
> > +        long long tx_errs;
> > +        long long tx_dropped;
> > +        char *trim_line;
> > +        trim_line = g_strchug(line);
> > +        if (trim_line[0] == '\0') {
> > +            continue;
> > +        }
> > +        colon = strchr(trim_line, ':');
> > +        if (!colon) {
> > +            continue;
> > +        }
> > +        if (colon - name_len  == trim_line &&
> > +           strncmp(trim_line, name, name_len) == 0) {
> > +            if (sscanf(colon + 1,
> >
>  +                "%lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld",
> > +                  &rx_bytes, &rx_packets, &rx_errs, &rx_dropped,
> > +                  &dummy, &dummy, &dummy, &dummy,
> > +                  &tx_bytes, &tx_packets, &tx_errs, &tx_dropped,
> > +                  &dummy, &dummy, &dummy, &dummy) != 16) {
> > +                continue;
> > +            }
> > +            stats->rx_bytes = rx_bytes;
> > +            stats->rx_packets = rx_packets;
> > +            stats->rx_errs = rx_errs;
> > +            stats->rx_dropped = rx_dropped;
> > +            stats->tx_bytes = tx_bytes;
> > +            stats->tx_packets = tx_packets;
> > +            stats->tx_errs = tx_errs;
> > +            stats->tx_dropped = tx_dropped;
> > +            fclose(fp);
> > +            return 0;
> > +        }
> > +    }
> > +    fclose(fp);
> > +    g_debug("/proc/net/dev: Interface not found");
> 
> Reporting the specific interface name might be useful here.
> 
> > +    return -1;
> > +}
> > +
> >  /*
> >   * Build information about guest interfaces
> >   */
> >
>  @@ -1659,6 +1718,7 @@ GuestNetworkInterfaceList *qmp_guest_network_get_interfaces
> (Error **errp)
> >      for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
> >          GuestNetworkInterfaceList *info;
> >          GuestIpAddressList **address_list = NULL, *address_item = NULL;
> > +        GuestNetworkInterfaceStat  *interface_stat = NULL;
> >          char addr4[INET_ADDRSTRLEN];
> >          char addr6[INET6_ADDRSTRLEN];
> >          int sock;
> >
>  @@ -1778,7 +1838,17 @@ GuestNetworkInterfaceList *qmp_guest_network_get_interfaces
> (Error **errp)
> > 
> >          info->value->has_ip_addresses = true;
> > 
> > -
> > +        if (!info->value->has_statistics) {
> > +            interface_stat = g_malloc0(sizeof(*interface_stat));
> > +            if (guest_get_network_stats(info->value->name,
> > +                interface_stat) == -1) {
> > +                info->value->has_statistics = false;
> > +                g_free(interface_stat);
> > +            } else {
> > +                info->value->statistics = interface_stat;
> > +                info->value->has_statistics = true;
> > +            }
> > +        }
> >      }
> > 
> >      freeifaddrs(ifap);
> > diff --git a/qga/commands-win32.c b/qga/commands-win32.c
> > index 619dbd2..e891253 100644
> > --- a/qga/commands-win32.c
> > +++ b/qga/commands-win32.c
> > @@ -1152,6 +1152,42 @@ out:
> >  }
> >  #endif
> > 
> > +static DWORD get_interface_index(const char *guid)
> > +{
> > +    ULONG index;
> > +    DWORD status;
> > +    wchar_t wbuf[512];
> > +    snwprintf(wbuf, sizeof(wbuf), L"\\device\\tcpip_%s", guid);
> > +    wbuf[sizeof(wbuf) - 1] = 0;
> 
> wchar_t can be larger than 1 byte, so using sizeof(wchar_t[]) as an
> index into a wchar_t[] can cause an overrun.
> 
> > +    status = GetAdapterIndex (wbuf, &index);
> > +    if (status != NO_ERROR) {
> > +        return (DWORD)~0;
> > +    } else {
> > +        return index;
> > +    }
> > +}
> > +static int guest_get_network_stats(const char *name,
> > +                       GuestNetworkInterfaceStat *stats)
> > +{
> > +    DWORD IfIndex = 0;
> > +    MIB_IFROW aMib_ifrow;
> > +    memset(&aMib_ifrow, 0, sizeof(aMib_ifrow));
> > +    IfIndex = get_interface_index(name);
> 
> Per CODING_STYLE variable names should be lowercase with "_" for
> separating words
> 
> > +    aMib_ifrow.dwIndex = IfIndex;
> > +    if (NO_ERROR == GetIfEntry(&aMib_ifrow)) {
> > +        stats->rx_bytes = aMib_ifrow.dwInOctets;
> > +        stats->rx_packets = aMib_ifrow.dwInUcastPkts;
> > +        stats->rx_errs = aMib_ifrow.dwInErrors;
> > +        stats->rx_dropped = aMib_ifrow.dwInDiscards;
> > +        stats->tx_bytes = aMib_ifrow.dwOutOctets;
> > +        stats->tx_packets = aMib_ifrow.dwOutUcastPkts;
> > +        stats->tx_errs = aMib_ifrow.dwOutErrors;
> > +        stats->tx_dropped = aMib_ifrow.dwOutDiscards;
> > +        return 0;
> > +    }
> > +    return -1;
> > +}
> > +
> >  GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **errp)
> >  {
> >      IP_ADAPTER_ADDRESSES *adptr_addrs, *addr;
> >
>  @@ -1159,6 +1195,7 @@ GuestNetworkInterfaceList *qmp_guest_network_get_interfaces
> (Error **errp)
> >      GuestNetworkInterfaceList *head = NULL, *cur_item = NULL;
> >      GuestIpAddressList *head_addr, *cur_addr;
> >      GuestNetworkInterfaceList *info;
> > +    GuestNetworkInterfaceStat *interface_stat = NULL;
> >      GuestIpAddressList *address_item = NULL;
> >      unsigned char *mac_addr;
> >      char *addr_str;
> >
>  @@ -1238,6 +1275,17 @@ GuestNetworkInterfaceList *qmp_guest_network_get_interfaces
> (Error **errp)
> >              info->value->has_ip_addresses = true;
> >              info->value->ip_addresses = head_addr;
> >          }
> > +        if (!info->value->has_statistics) {
> > +            interface_stat = g_malloc0(sizeof(*interface_stat));
> > +            if (guest_get_network_stats(addr->AdapterName,
> > +                interface_stat) == -1) {
> > +                info->value->has_statistics = false;
> > +                g_free(interface_stat);
> > +            } else {
> > +                info->value->statistics = interface_stat;
> > +                info->value->has_statistics = true;
> > +            }
> > +        }
> >      }
> >      WSACleanup();
> >  out:
> > diff --git a/qga/qapi-schema.json b/qga/qapi-schema.json
> > index 90a0c86..17884c7 100644
> > --- a/qga/qapi-schema.json
> > +++ b/qga/qapi-schema.json
> > @@ -643,6 +643,38 @@
> >             'prefix': 'int'} }
> > 
> >  ##
> > +# @GuestNetworkInterfaceStat:
> > +#
> > +# @rx-bytes: total bytes received
> > +#
> > +# @rx-packets: total packets received
> > +#
> > +# @rx-errs: bad packets received
> > +#
> > +# @rx-dropped: receiver dropped packets
> > +#
> > +# @tx-bytes: total bytes transmitted
> > +#
> > +# @tx-packets: total packets transmitted
> > +#
> > +# @tx-errs: packet transmit problems
> > +#
> > +# @tx-dropped: dropped packets transmitted
> > +#
> > +# Since: 2.11
> > +##
> > +{ 'struct': 'GuestNetworkInterfaceStat',
> > +  'data': {'rx-bytes': 'uint64',
> > +            'rx-packets': 'uint64',
> > +            'rx-errs': 'uint64',
> > +            'rx-dropped': 'uint64',
> > +            'tx-bytes': 'uint64',
> > +            'tx-packets': 'uint64',
> > +            'tx-errs': 'uint64',
> > +            'tx-dropped': 'uint64'
> > +           } }
> > +
> > +##
> >  # @GuestNetworkInterface:
> >  #
> >  # @name: The name of interface for which info are being delivered
> > @@ -651,12 +683,16 @@
> >  #
> >  # @ip-addresses: List of addresses assigned to @name
> >  #
> > +# @statistics: various statistic counters related to @name
> > +# (since 2.11)
> > +#
> >  # Since: 1.1
> >  ##
> >  { 'struct': 'GuestNetworkInterface',
> >    'data': {'name': 'str',
> >             '*hardware-address': 'str',
> > -           '*ip-addresses': ['GuestIpAddress'] } }
> > +           '*ip-addresses': ['GuestIpAddress'],
> > +           '*statistics': 'GuestNetworkInterfaceStat' } }
> > 
> >  ##
> >  # @guest-network-get-interfaces:
> > -- 
> > 1.8.3.1
> > 
> 
>
diff mbox series

Patch

diff --git a/qga/commands-posix.c b/qga/commands-posix.c
index ab0c63d..da5dba0 100644
--- a/qga/commands-posix.c
+++ b/qga/commands-posix.c
@@ -1643,6 +1643,65 @@  guest_find_interface(GuestNetworkInterfaceList *head,
     return head;
 }
 
+static int guest_get_network_stats(const char *name,
+                       GuestNetworkInterfaceStat *stats)
+{
+    int name_len;
+    char const *devinfo = "/proc/net/dev";
+    FILE *fp;
+    char *line = NULL, *colon;
+    size_t n;
+    fp = fopen(devinfo, "r");
+    if (!fp) {
+        return -1;
+    }
+    name_len = strlen(name);
+    while (getline(&line, &n, fp) != -1) {
+        long long dummy;
+        long long rx_bytes;
+        long long rx_packets;
+        long long rx_errs;
+        long long rx_dropped;
+        long long tx_bytes;
+        long long tx_packets;
+        long long tx_errs;
+        long long tx_dropped;
+        char *trim_line;
+        trim_line = g_strchug(line);
+        if (trim_line[0] == '\0') {
+            continue;
+        }
+        colon = strchr(trim_line, ':');
+        if (!colon) {
+            continue;
+        }
+        if (colon - name_len  == trim_line &&
+           strncmp(trim_line, name, name_len) == 0) {
+            if (sscanf(colon + 1,
+                "%lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld",
+                  &rx_bytes, &rx_packets, &rx_errs, &rx_dropped,
+                  &dummy, &dummy, &dummy, &dummy,
+                  &tx_bytes, &tx_packets, &tx_errs, &tx_dropped,
+                  &dummy, &dummy, &dummy, &dummy) != 16) {
+                continue;
+            }
+            stats->rx_bytes = rx_bytes;
+            stats->rx_packets = rx_packets;
+            stats->rx_errs = rx_errs;
+            stats->rx_dropped = rx_dropped;
+            stats->tx_bytes = tx_bytes;
+            stats->tx_packets = tx_packets;
+            stats->tx_errs = tx_errs;
+            stats->tx_dropped = tx_dropped;
+            fclose(fp);
+            return 0;
+        }
+    }
+    fclose(fp);
+    g_debug("/proc/net/dev: Interface not found");
+    return -1;
+}
+
 /*
  * Build information about guest interfaces
  */
@@ -1659,6 +1718,7 @@  GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **errp)
     for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
         GuestNetworkInterfaceList *info;
         GuestIpAddressList **address_list = NULL, *address_item = NULL;
+        GuestNetworkInterfaceStat  *interface_stat = NULL;
         char addr4[INET_ADDRSTRLEN];
         char addr6[INET6_ADDRSTRLEN];
         int sock;
@@ -1778,7 +1838,17 @@  GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **errp)
 
         info->value->has_ip_addresses = true;
 
-
+        if (!info->value->has_statistics) {
+            interface_stat = g_malloc0(sizeof(*interface_stat));
+            if (guest_get_network_stats(info->value->name,
+                interface_stat) == -1) {
+                info->value->has_statistics = false;
+                g_free(interface_stat);
+            } else {
+                info->value->statistics = interface_stat;
+                info->value->has_statistics = true;
+            }
+        }
     }
 
     freeifaddrs(ifap);
diff --git a/qga/commands-win32.c b/qga/commands-win32.c
index 619dbd2..e891253 100644
--- a/qga/commands-win32.c
+++ b/qga/commands-win32.c
@@ -1152,6 +1152,42 @@  out:
 }
 #endif
 
+static DWORD get_interface_index(const char *guid)
+{
+    ULONG index;
+    DWORD status;
+    wchar_t wbuf[512];
+    snwprintf(wbuf, sizeof(wbuf), L"\\device\\tcpip_%s", guid);
+    wbuf[sizeof(wbuf) - 1] = 0;
+    status = GetAdapterIndex (wbuf, &index);
+    if (status != NO_ERROR) {
+        return (DWORD)~0;
+    } else {
+        return index;
+    }
+}
+static int guest_get_network_stats(const char *name,
+                       GuestNetworkInterfaceStat *stats)
+{
+    DWORD IfIndex = 0;
+    MIB_IFROW aMib_ifrow;
+    memset(&aMib_ifrow, 0, sizeof(aMib_ifrow));
+    IfIndex = get_interface_index(name);
+    aMib_ifrow.dwIndex = IfIndex;
+    if (NO_ERROR == GetIfEntry(&aMib_ifrow)) {
+        stats->rx_bytes = aMib_ifrow.dwInOctets;
+        stats->rx_packets = aMib_ifrow.dwInUcastPkts;
+        stats->rx_errs = aMib_ifrow.dwInErrors;
+        stats->rx_dropped = aMib_ifrow.dwInDiscards;
+        stats->tx_bytes = aMib_ifrow.dwOutOctets;
+        stats->tx_packets = aMib_ifrow.dwOutUcastPkts;
+        stats->tx_errs = aMib_ifrow.dwOutErrors;
+        stats->tx_dropped = aMib_ifrow.dwOutDiscards;
+        return 0;
+    }
+    return -1;
+}
+
 GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **errp)
 {
     IP_ADAPTER_ADDRESSES *adptr_addrs, *addr;
@@ -1159,6 +1195,7 @@  GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **errp)
     GuestNetworkInterfaceList *head = NULL, *cur_item = NULL;
     GuestIpAddressList *head_addr, *cur_addr;
     GuestNetworkInterfaceList *info;
+    GuestNetworkInterfaceStat *interface_stat = NULL;
     GuestIpAddressList *address_item = NULL;
     unsigned char *mac_addr;
     char *addr_str;
@@ -1238,6 +1275,17 @@  GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **errp)
             info->value->has_ip_addresses = true;
             info->value->ip_addresses = head_addr;
         }
+        if (!info->value->has_statistics) {
+            interface_stat = g_malloc0(sizeof(*interface_stat));
+            if (guest_get_network_stats(addr->AdapterName,
+                interface_stat) == -1) {
+                info->value->has_statistics = false;
+                g_free(interface_stat);
+            } else {
+                info->value->statistics = interface_stat;
+                info->value->has_statistics = true;
+            }
+        }
     }
     WSACleanup();
 out:
diff --git a/qga/qapi-schema.json b/qga/qapi-schema.json
index 90a0c86..17884c7 100644
--- a/qga/qapi-schema.json
+++ b/qga/qapi-schema.json
@@ -643,6 +643,38 @@ 
            'prefix': 'int'} }
 
 ##
+# @GuestNetworkInterfaceStat:
+#
+# @rx-bytes: total bytes received
+#
+# @rx-packets: total packets received
+#
+# @rx-errs: bad packets received
+#
+# @rx-dropped: receiver dropped packets
+#
+# @tx-bytes: total bytes transmitted
+#
+# @tx-packets: total packets transmitted
+#
+# @tx-errs: packet transmit problems
+#
+# @tx-dropped: dropped packets transmitted
+#
+# Since: 2.11
+##
+{ 'struct': 'GuestNetworkInterfaceStat',
+  'data': {'rx-bytes': 'uint64',
+            'rx-packets': 'uint64',
+            'rx-errs': 'uint64',
+            'rx-dropped': 'uint64',
+            'tx-bytes': 'uint64',
+            'tx-packets': 'uint64',
+            'tx-errs': 'uint64',
+            'tx-dropped': 'uint64'
+           } }
+
+##
 # @GuestNetworkInterface:
 #
 # @name: The name of interface for which info are being delivered
@@ -651,12 +683,16 @@ 
 #
 # @ip-addresses: List of addresses assigned to @name
 #
+# @statistics: various statistic counters related to @name
+# (since 2.11)
+#
 # Since: 1.1
 ##
 { 'struct': 'GuestNetworkInterface',
   'data': {'name': 'str',
            '*hardware-address': 'str',
-           '*ip-addresses': ['GuestIpAddress'] } }
+           '*ip-addresses': ['GuestIpAddress'],
+           '*statistics': 'GuestNetworkInterfaceStat' } }
 
 ##
 # @guest-network-get-interfaces: