<div dir="ltr"><br><br><br>On Tue, Aug 27, 2013 at 6:06 PM, Daniel P. Berrange <<a href="mailto:berrange@redhat.com">berrange@redhat.com</a>> wrote:<br>><br>> On Sun, Aug 25, 2013 at 04:45:41AM +0530, Nehal J Wani wrote:<br>
> > diff --git a/include/libvirt/<a href="http://libvirt.h.in">libvirt.h.in</a> b/include/libvirt/<a href="http://libvirt.h.in">libvirt.h.in</a><br>> > index a47e33c..deb1e1f 100644<br>> > --- a/include/libvirt/<a href="http://libvirt.h.in">libvirt.h.in</a><br>
> > +++ b/include/libvirt/<a href="http://libvirt.h.in">libvirt.h.in</a><br>> > @@ -2044,6 +2044,39 @@ int                     virDomainGetInterfaceParameters (virDomainPtr dom,<br>> >                                                           virTypedParameterPtr params,<br>
> >                                                           int *nparams, unsigned int flags);<br>> ><br>> > +typedef enum {<br>> > +    VIR_IP_ADDR_TYPE_IPV4,<br>> > +    VIR_IP_ADDR_TYPE_IPV6,<br>
> > +<br>> > +#ifdef VIR_ENUM_SENTINELS<br>> > +    VIR_IP_ADDR_TYPE_LAST<br>> > +#endif<br>> > +} virIPAddrType;<br>> > +<br>> > +<br>> > +typedef struct _virDomainInterfaceIPAddress virDomainIPAddress;<br>
> > +typedef virDomainIPAddress *virDomainIPAddressPtr;<br>> > +struct _virDomainInterfaceIPAddress {<br>> > +    int type;       /* virIPAddrType */<br>> > +    char *addr;     /* IP address */<br>
> > +    int prefix;     /* IP address prefix */<br>> > +};<br>><br>> s/int/unsigned int/ since there's no reason for prefix to ever<br>> be negative.<br>><br>> > +<br>> > +typedef struct _virDomainInterface virDomainInterface;<br>
> > +typedef virDomainInterface *virDomainInterfacePtr;<br>> > +struct _virDomainInterface {<br>> > +    char *name;                     /* interface name */<br>> > +    char *hwaddr;                   /* hardware address */<br>
> > +    unsigned int naddrs;            /* number of items in @addrs */<br>> > +    virDomainIPAddressPtr addrs;    /* array of IP addresses */<br>> > +};<br>> > +<br>> > +int virDomainInterfacesAddresses (virDomainPtr dom,<br>
> > +                                  virDomainInterfacePtr **ifaces,<br>> > +                                  unsigned int flags);<br>><br>> Don't put a space between the function name & opening bracket.<br>
><br>> The double pluralization reads oddly to me. I'd suggest we<br>> just name this  'virDomainInterfaceAddresses'<br>><br>> ie remove the 's' from "Interfaces" here, and in all similarly<br>
> named functions in this series.<br>><div><br><div>The double pluralization was chosen because there are multiple</div><div>IP Addresses per interface and there are multiple interfaces. If we</div><div>choose to use 'virDomainInterfaceAddresses', then it would look</div>
<div>as if this function will report all the IP Addresses related to a single</div><div>Interface only.</div><div><br>> > +<br>> > +void virDomainInterfaceFree (virDomainInterfacePtr iface);<br>><br>> Likewise.<br>
><br>> > diff --git a/src/driver.h b/src/driver.h<br>> > index be64333..8b6182e 100644<br>> > --- a/src/driver.h<br>> > +++ b/src/driver.h<br>> > @@ -518,6 +518,11 @@ typedef int<br>> >                                        unsigned int flags);<br>
> ><br>> >  typedef int<br>> > +(*virDrvDomainInterfacesAddresses)(virDomainPtr dom,<br>> > +                                   virDomainInterfacePtr **ifaces,<br>> > +                                   unsigned int flags);<br>
> > +<br>> > +typedef int<br>> >  (*virDrvDomainMemoryStats)(virDomainPtr domain,<br>> >                             struct _virDomainMemoryStat *stats,<br>> >                             unsigned int nr_stats,<br>
> > @@ -1238,6 +1243,7 @@ struct _virDriver {<br>> >      virDrvDomainInterfaceStats domainInterfaceStats;<br>> >      virDrvDomainSetInterfaceParameters domainSetInterfaceParameters;<br>> >      virDrvDomainGetInterfaceParameters domainGetInterfaceParameters;<br>
> > +    virDrvDomainInterfacesAddresses    domainInterfacesAddresses;<br>> >      virDrvDomainMemoryStats domainMemoryStats;<br>> >      virDrvDomainBlockPeek domainBlockPeek;<br>> >      virDrvDomainMemoryPeek domainMemoryPeek;<br>
> > diff --git a/src/libvirt.c b/src/libvirt.c<br>> > index 07a3fd5..05e3a03 100644<br>> > --- a/src/libvirt.c<br>> > +++ b/src/libvirt.c<br>> > @@ -8643,6 +8643,94 @@ error:<br>> >      return -1;<br>
> >  }<br>> ><br>> > + /**<br>> > + * virDomainInterfacesAddresses:<br>> > + * @dom: domain object<br>> > + * @ifaces: pointer to an array of pointers pointing interface objects<br>> > + * @flags: extra flags; not used yet, so callers should always pass 0<br>
> > + *<br>> > + * Return a pointer to the allocated array of interfaces present in given<br>> > + * domain along with their IP and MAC addresses. Note that single interface<br>> > + * can have multiple or even 0 IP address.<br>
> > + *<br>> > + * This API dynamically allocates the virDomainInterfacePtr struct based<br>> > + * on how many interfaces domain @dom has, usually there's 1:1 correlation.<br>> > + * The count of the interfaces is returned as the return value.<br>
> > + *<br>> > + * Note that for some hypervisors, a configured guest agent is needed<br>> > + * for successful return from this API. Moreover, if guest agent is<br>> > + * used then the interface name is the one seen by guest OS. To match<br>
> > + * such interface with the one from @dom XML use MAC address or IP range.<br>> > + *<br>> > + * @ifaces->name is never NULL, @ifaces->hwaddr might be NULL.<br>> > + *<br>> > + * The caller *must* free @ifaces when no longer needed. Usual use<br>
> > + * case looks like this:<br>> > + *<br>> > + * virDomainInterfacePtr *ifaces = NULL;<br>> > + * int ifaces_count = 0;<br>> > + * size_t i, j;<br>> > + * virDomainPtr dom = ... obtain a domain here ...;<br>
> > + *<br>> > + * if ((ifaces_count = virDomainInterfacesAddresses(dom, &ifaces, 0)) < 0)<br>> > + *     goto cleanup;<br>> > + *<br>> > + * ... do something with returned values, for example:<br>
> > + * for (i = 0; i < ifaces_count; i++) {<br>> > + *     printf("name: %s", ifaces[i]->name);<br>> > + *     if (ifaces[i]->hwaddr)<br>> > + *         printf(" hwaddr: %s", ifaces[i]->hwaddr);<br>
> > + *<br>> > + *     for (j = 0; j < ifaces[i]->naddrs; j++) {<br>> > + *         virDomainIPAddressPtr ip_addr = ifaces[i]->addrs + j;<br>> > + *         printf("[addr: %s prefix: %d type: %d]",<br>
> > + *                ip_addr->addr, ip_addr->prefix, ip_addr->type);<br>> > + *     }<br>> > + *     printf("\n");<br>> > + * }<br>> > + *<br>> > + * cleanup:<br>> > + * for (i = 0; i < ifaces_count; i++)<br>
> > + *     virDomainInterfaceFree(ifaces[i]);<br>> > + * free(ifaces);<br>> > + *<br>> > + * Returns the number of interfaces on success, -1 in case of error.<br>> > + */<br>> > +int<br>
> > +virDomainInterfacesAddresses(virDomainPtr dom,<br>> > +                             virDomainInterfacePtr **ifaces,<br>> > +                             unsigned int flags)<br>> > +{<br>> > +    virConnectPtr conn;<br>
> > +<br>> > +    VIR_DOMAIN_DEBUG(dom, "ifaces=%p, flags=%x", ifaces, flags);<br>> > +<br>> > +    virResetLastError();<br>> > +<br>> > +    if (!VIR_IS_CONNECTED_DOMAIN(dom)) {<br>
> > +        virLibDomainError(VIR_ERR_INVALID_DOMAIN, __FUNCTION__);<br>> > +        goto error;<br>><br>> You must following existing practice and call virDispatchError(NULL)<br>> and 'return -1' here immediately.<br>
><br>> > +    }<br>> > +<br>> > +    conn = dom->conn;<br>> > +<br>> > +    virCheckNonNullArgGoto(ifaces, error);<br>> > +<br>> > +    if (conn->driver->domainInterfacesAddresses) {<br>
> > +        int ret;<br>> > +        ret = conn->driver->domainInterfacesAddresses(dom, ifaces, flags);<br>> > +        if (ret < 0)<br>> > +            goto error;<br>> > +        return ret;<br>
> > +    }<br>> > +<br>> > +    virLibConnError(VIR_ERR_NO_SUPPORT, __FUNCTION__);<br>> > +<br>> > +error:<br>> > +    virDispatchError(dom ? dom->conn : NULL);<br>><br>> This is not safe. VIR_IS_CONNECTED_DOMAIN does more than just<br>
> check whether 'dom' is NULL, so you must not dereference<br>> 'dom' if that check fails.<br>><br>> > +<br>> > +/**<br>> > + * virDomainInterfaceFree:<br>> > + * @iface: an interface object<br>
> > + *<br>> > + * Free the interface object. The data structure is<br>> > + * freed and should not be used thereafter.<br>> > + */<br>> > +void<br>> > +virDomainInterfaceFree(virDomainInterfacePtr iface)<br>
> > +{<br>> > +    if (iface) {<br>><br>> The usual coding style in libvirt for this is<br>><br>>    if (!iface)<br>>      return;<br>><br>> > +        size_t i;<br>> > +        VIR_FREE(iface->name);<br>
> > +        VIR_FREE(iface->hwaddr);<br>> > +        for (i = 0; i < iface->naddrs; i++)<br>> > +            VIR_FREE(iface->addrs[i].addr);<br>> > +        VIR_FREE(iface->addrs);<br>
> > +    }<br>> > +    VIR_FREE(iface);<br>> > +}<br>><br>><br>> Regards,<br>> Daniel<br>> --<br>> |: <a href="http://berrange.com">http://berrange.com</a>      -o-    <a href="http://www.flickr.com/photos/dberrange/">http://www.flickr.com/photos/dberrange/</a> :|<br>
> |: <a href="http://libvirt.org">http://libvirt.org</a>              -o-             <a href="http://virt-manager.org">http://virt-manager.org</a> :|<br>> |: <a href="http://autobuild.org">http://autobuild.org</a>       -o-         <a href="http://search.cpan.org/~danberr/">http://search.cpan.org/~danberr/</a> :|<br>
> |: <a href="http://entangle-photo.org">http://entangle-photo.org</a>       -o-       <a href="http://live.gnome.org/gtk-vnc">http://live.gnome.org/gtk-vnc</a> :|<br><br><br><br><br>--<br>Nehal J Wani<br>UG3, BTech CS+MS(CL)<br>
IIIT-Hyderabad<br><br></div></div></div>