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 |
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 >
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=
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 --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:
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(-)