Re: [Qemu-devel] [PATCH v5] qemu-ga: Add guest-network-info command
* Michal Privoznik [2012-02-28 09:38]: > This command returns an array of: > > [ifname, hwaddr, [ipaddr, ipaddr_family, prefix] ] > > for each interface in the system. > Currently, only IPv4 and IPv6 are supported. What about vlans and bonding info? > > Signed-off-by: Michal Privoznik > --- > diff to v4: > -change return type > > diff to v3: > -use ctpop32() instead of separate count_one_bits() > > diff to v2: > -Properly set IP addr family for IPv6 > > diff to v1: > -move from guest-getip to guest-network-info > -replace black boxed algorithm for population count > -several coding styles improvements > > qapi-schema-guest.json | 62 +++ > qga/commands-posix.c | 197 > > 2 files changed, 259 insertions(+), 0 deletions(-) > > diff --git a/qapi-schema-guest.json b/qapi-schema-guest.json > index 706925d..41ea2bf 100644 > --- a/qapi-schema-guest.json > +++ b/qapi-schema-guest.json > @@ -295,3 +295,65 @@ > ## > { 'command': 'guest-fsfreeze-thaw', >'returns': 'int' } > + > +## > +# @GuestIpAddressType: > +# > +# An enumeration of supported IP address types > +# > +# @ipv4: IP version 4 > +# > +# @ipv6: IP version 6 > +# > +# Since: 1.1 > +## > +{ 'enum': 'GuestIpAddressType', > + 'data': [ 'ipv4', 'ipv6' ] } > + > +## > +# @GuestIpAddress: > +# > +# @ip-address: IP address > +# > +# @ip-address-type: Type of @ip-address (e.g. ipv4, ipv6) > +# > +# @prefix: Network prefix length of @ip-address > +# > +# Since: 1.1 > +## > +{ 'type': 'GuestIpAddress', > + 'data': {'ip-address': 'str', > + 'ip-address-type': 'GuestIpAddressType', > + 'prefix': 'int'} } > + > +## > +# @GuestNetworkInterface: > +# > +# @name: The name of interface for which info are being delivered > +# > +# @hardware-address: Hardware address of @name > +# > +# @ip-addresses: List of addresses assigned to @name > +# > +# Since: 1.1 > +## > +{ 'type': 'GuestNetworkInterface', > + 'data': {'name': 'str', > + '*hardware-address': 'str', > + '*ip-addresses': ['GuestIpAddress'] } } > + > +## > +# @guest-network-info: > +# > +# Get list of guest IP addresses, MAC addresses > +# and netmasks. > +# > +# Returns: List of GuestNetworkInfo on success. > +# > +# Since: 1.1 > +## > +{ 'type': 'GuestNetworkInfo', > + 'data': { 'interfaces': ['GuestNetworkInterface'] } } > + > +{ 'command': 'guest-network-info', > + 'returns': 'GuestNetworkInfo' } > diff --git a/qga/commands-posix.c b/qga/commands-posix.c > index 126127a..095507b 100644 > --- a/qga/commands-posix.c > +++ b/qga/commands-posix.c > @@ -5,6 +5,7 @@ > * > * Authors: > * Michael Roth > + * Michal Privoznik > * > * This work is licensed under the terms of the GNU GPL, version 2 or later. > * See the COPYING file in the top-level directory. > @@ -23,10 +24,15 @@ > > #include > #include > +#include > +#include > +#include > +#include > #include "qga/guest-agent-core.h" > #include "qga-qmp-commands.h" > #include "qerror.h" > #include "qemu-queue.h" > +#include "host-utils.h" > > static GAState *ga_state; > > @@ -526,3 +532,194 @@ void ga_command_state_init(GAState *s, GACommandState > *cs) > #endif > ga_command_state_add(cs, guest_file_init, NULL); > } > + > +static GuestNetworkInterfaceList * > +guest_find_interface(GuestNetworkInterfaceList *head, > + const char *name) > +{ > +for (; head; head = head->next) { > +if (strcmp(head->value->name, name) == 0) { > +break; > +} > +} > + > +return head; > +} > + > +/* > + * Build information about guest interfaces > + */ > +static GuestNetworkInterfaceList *guest_build_interfaces_info(Error **errp) > +{ > +GuestNetworkInterfaceList *head = NULL, *cur_item = NULL; > +struct ifaddrs *ifap, *ifa; > +char err_msg[512]; > + > +if (getifaddrs(&ifap) < 0) { > +snprintf(err_msg, sizeof(err_msg), > + "getifaddrs failed: %s", strerror(errno)); > +error_set(errp, QERR_QGA_COMMAND_FAILED, err_msg); > +goto error; > +} > + > +for (ifa = ifap; ifa; ifa = ifa->ifa_next) { > +GuestNetworkInterfaceList *info; > +GuestIpAddressList **address_list = NULL, *address_item = NULL; > +char addr4[INET_ADDRSTRLEN]; > +char addr6[INET6_ADDRSTRLEN]; > +int sock; > +struct ifreq ifr; > +unsigned char *mac_addr; > +void *p; > + > +g_debug("Processing %s interface", ifa->ifa_name); > + > +info = guest_find_interface(head, ifa->ifa_name); > + > +if (!info) { > +info = g_malloc0(sizeof(*info)); > +info->value = g_malloc0(sizeof(*info->value)); > +info->value->name = g_strdup(ifa->ifa_name); > + > +if (!cur_item) { > +head = cur_item = info; > +} else { > +cur_item->next = info; > +cur_item = info; > +
[Qemu-devel] [PATCH v5] qemu-ga: Add guest-network-info command
This command returns an array of: [ifname, hwaddr, [ipaddr, ipaddr_family, prefix] ] for each interface in the system. Currently, only IPv4 and IPv6 are supported. Signed-off-by: Michal Privoznik --- diff to v4: -change return type diff to v3: -use ctpop32() instead of separate count_one_bits() diff to v2: -Properly set IP addr family for IPv6 diff to v1: -move from guest-getip to guest-network-info -replace black boxed algorithm for population count -several coding styles improvements qapi-schema-guest.json | 62 +++ qga/commands-posix.c | 197 2 files changed, 259 insertions(+), 0 deletions(-) diff --git a/qapi-schema-guest.json b/qapi-schema-guest.json index 706925d..41ea2bf 100644 --- a/qapi-schema-guest.json +++ b/qapi-schema-guest.json @@ -295,3 +295,65 @@ ## { 'command': 'guest-fsfreeze-thaw', 'returns': 'int' } + +## +# @GuestIpAddressType: +# +# An enumeration of supported IP address types +# +# @ipv4: IP version 4 +# +# @ipv6: IP version 6 +# +# Since: 1.1 +## +{ 'enum': 'GuestIpAddressType', + 'data': [ 'ipv4', 'ipv6' ] } + +## +# @GuestIpAddress: +# +# @ip-address: IP address +# +# @ip-address-type: Type of @ip-address (e.g. ipv4, ipv6) +# +# @prefix: Network prefix length of @ip-address +# +# Since: 1.1 +## +{ 'type': 'GuestIpAddress', + 'data': {'ip-address': 'str', + 'ip-address-type': 'GuestIpAddressType', + 'prefix': 'int'} } + +## +# @GuestNetworkInterface: +# +# @name: The name of interface for which info are being delivered +# +# @hardware-address: Hardware address of @name +# +# @ip-addresses: List of addresses assigned to @name +# +# Since: 1.1 +## +{ 'type': 'GuestNetworkInterface', + 'data': {'name': 'str', + '*hardware-address': 'str', + '*ip-addresses': ['GuestIpAddress'] } } + +## +# @guest-network-info: +# +# Get list of guest IP addresses, MAC addresses +# and netmasks. +# +# Returns: List of GuestNetworkInfo on success. +# +# Since: 1.1 +## +{ 'type': 'GuestNetworkInfo', + 'data': { 'interfaces': ['GuestNetworkInterface'] } } + +{ 'command': 'guest-network-info', + 'returns': 'GuestNetworkInfo' } diff --git a/qga/commands-posix.c b/qga/commands-posix.c index 126127a..095507b 100644 --- a/qga/commands-posix.c +++ b/qga/commands-posix.c @@ -5,6 +5,7 @@ * * Authors: * Michael Roth + * Michal Privoznik * * This work is licensed under the terms of the GNU GPL, version 2 or later. * See the COPYING file in the top-level directory. @@ -23,10 +24,15 @@ #include #include +#include +#include +#include +#include #include "qga/guest-agent-core.h" #include "qga-qmp-commands.h" #include "qerror.h" #include "qemu-queue.h" +#include "host-utils.h" static GAState *ga_state; @@ -526,3 +532,194 @@ void ga_command_state_init(GAState *s, GACommandState *cs) #endif ga_command_state_add(cs, guest_file_init, NULL); } + +static GuestNetworkInterfaceList * +guest_find_interface(GuestNetworkInterfaceList *head, + const char *name) +{ +for (; head; head = head->next) { +if (strcmp(head->value->name, name) == 0) { +break; +} +} + +return head; +} + +/* + * Build information about guest interfaces + */ +static GuestNetworkInterfaceList *guest_build_interfaces_info(Error **errp) +{ +GuestNetworkInterfaceList *head = NULL, *cur_item = NULL; +struct ifaddrs *ifap, *ifa; +char err_msg[512]; + +if (getifaddrs(&ifap) < 0) { +snprintf(err_msg, sizeof(err_msg), + "getifaddrs failed: %s", strerror(errno)); +error_set(errp, QERR_QGA_COMMAND_FAILED, err_msg); +goto error; +} + +for (ifa = ifap; ifa; ifa = ifa->ifa_next) { +GuestNetworkInterfaceList *info; +GuestIpAddressList **address_list = NULL, *address_item = NULL; +char addr4[INET_ADDRSTRLEN]; +char addr6[INET6_ADDRSTRLEN]; +int sock; +struct ifreq ifr; +unsigned char *mac_addr; +void *p; + +g_debug("Processing %s interface", ifa->ifa_name); + +info = guest_find_interface(head, ifa->ifa_name); + +if (!info) { +info = g_malloc0(sizeof(*info)); +info->value = g_malloc0(sizeof(*info->value)); +info->value->name = g_strdup(ifa->ifa_name); + +if (!cur_item) { +head = cur_item = info; +} else { +cur_item->next = info; +cur_item = info; +} +} + +if (!info->value->has_hardware_address && +ifa->ifa_flags & SIOCGIFHWADDR) { +/* we haven't obtained HW address yet */ +sock = socket(PF_INET, SOCK_STREAM, 0); +if (sock == -1) { +snprintf(err_msg, sizeof(err_msg), + "failed to create socket: %s", strerror(errno)); +error_set(errp, QERR_QGA_COMMAND_FAILED, err_ms