Re: [libvirt] [PATCH 2/4] virtnetdev: Add support functions for mac and portprofile associations on a hostdev

2012-03-05 Thread Laine Stump
On 03/04/2012 10:15 PM, Roopa Prabhu wrote:
 From: Roopa Prabhu ropra...@cisco.com

 This patch adds the following:
 - functions to set and get vf configs
 - Functions to replace and store vf configs (Only mac address is handled 
 today.
   But the functions can be easily extended for vlans and other vf configs)
 - function to dump link dev info (This is moved from virnetdevvportprofile.c)

 Signed-off-by: Roopa Prabhu ropra...@cisco.com
 ---
  src/util/virnetdev.c |  531 
 ++
  src/util/virnetdev.h |   19 ++
  2 files changed, 549 insertions(+), 1 deletions(-)

(BTW, I never thought about doing it this way before, but I'm glad you
added the function here in a separate patch from the patch that removes
it from virnetdevvportprofile.c - that makes it easy to open the two
patches side-by-side and verify that it really is moving the same code
(well, mostly).)



 diff --git a/src/util/virnetdev.c b/src/util/virnetdev.c
 index 9d76d47..25f2155 100644
 --- a/src/util/virnetdev.c
 +++ b/src/util/virnetdev.c
 @@ -1127,8 +1127,497 @@ virNetDevGetPhysicalFunction(const char *ifname, char 
 **pfname)
  
  return ret;
  }
 -#else /* !__linux__ */

The functions here that use libnl need to be inside of

  #if defined(__linux__)  defined(HAVE_LIBNL)

since there are linux platforms that don't have libnl, or don't have the
proper LIBNL (RHEL5, in particular, still has libnl-1.0)

  
 +static struct nla_policy ifla_vf_policy[IFLA_VF_MAX+1] = {
 +[IFLA_VF_MAC]   = { .type = NLA_UNSPEC,
 +.maxlen = sizeof(struct ifla_vf_mac) },
 +[IFLA_VF_VLAN]  = { .type = NLA_UNSPEC,
 +.maxlen = sizeof(struct ifla_vf_vlan) },
 +};
 +
 +/**
 + * virNetDevLinkDump:
 + *
 + * @ifname: The name of the interface; only use if ifindex  0
 + * @ifindex: The interface index; may be  0 if ifname is given
 + * @nltarget_kernel: whether to send the message to the kernel or another
 + *   process
 + * @nlattr: pointer to a pointer of netlink attributes that will contain
 + *  the results
 + * @recvbuf: Pointer to the buffer holding the returned netlink response
 + *   message; free it, once not needed anymore
 + * @getPidFunc: Pointer to a function that will be invoked if the kernel
 + *  is not the target of the netlink message but it is to be
 + *  sent to another process.
 + *
 + * Get information about an interface given its name or index.
 + *
 + * Returns 0 on success, -1 on fatal error.
 + */
 +int
 +virNetDevLinkDump(const char *ifname, int ifindex,
 +  bool nltarget_kernel, struct nlattr **tb,
 +  unsigned char **recvbuf,
 +  uint32_t (*getPidFunc)(void))
 +{
 +int rc = 0;
 +struct nlmsghdr *resp;
 +struct nlmsgerr *err;
 +struct ifinfomsg ifinfo = {
 +.ifi_family = AF_UNSPEC,
 +.ifi_index  = ifindex
 +};
 +unsigned int recvbuflen;
 +uint32_t pid = 0;
 +struct nl_msg *nl_msg;
 +
 +*recvbuf = NULL;
 +
 +if (ifindex = 0  virNetDevGetIndex(ifname, ifindex)  0)
 +return -1;
 +
 +ifinfo.ifi_index = ifindex;
 +
 +nl_msg = nlmsg_alloc_simple(RTM_GETLINK, NLM_F_REQUEST);
 +if (!nl_msg) {
 +virReportOOMError();
 +return -1;
 +}
 +
 +if (nlmsg_append(nl_msg,  ifinfo, sizeof(ifinfo), NLMSG_ALIGNTO)  0)
 +goto buffer_too_small;
 +
 +if (ifindex  0  ifname) {
 +if (nla_put(nl_msg, IFLA_IFNAME, strlen(ifname)+1, ifname)  0)
 +goto buffer_too_small;
 +}


Is this bit necessary any more? You've added code above that converts
the ifname into an ifindex, and we've already returned if it wasn't
successful.


 +
 +if (!nltarget_kernel) {
 +pid = getPidFunc();
 +if (pid == 0) {
 +rc = -1;
 +goto cleanup;
 +}
 +}
 +
 +if (virNetlinkCommand(nl_msg, recvbuf, recvbuflen, pid)  0) {
 +rc = -1;
 +goto cleanup;
 +}
 +
 +if (recvbuflen  NLMSG_LENGTH(0) || *recvbuf == NULL)
 +goto malformed_resp;
 +
 +resp = (struct nlmsghdr *)*recvbuf;
 +
 +switch (resp-nlmsg_type) {
 +case NLMSG_ERROR:
 +err = (struct nlmsgerr *)NLMSG_DATA(resp);
 +if (resp-nlmsg_len  NLMSG_LENGTH(sizeof(*err)))
 +goto malformed_resp;
 +
 +if (err-error) {
 +virReportSystemError(-err-error,
 + _(error dumping %s (%d) interface),
 + ifname, ifindex);
 +rc = -1;
 +}
 +break;
 +
 +case GENL_ID_CTRL:
 +case NLMSG_DONE:
 +rc = nlmsg_parse(resp, sizeof(struct ifinfomsg),
 + tb, IFLA_MAX, NULL);
 +if (rc  0)
 +goto malformed_resp;
 +break;
 +
 +default:
 +goto malformed_resp;
 +}
 +
 +if (rc != 0)
 +

Re: [libvirt] [PATCH 2/4] virtnetdev: Add support functions for mac and portprofile associations on a hostdev

2012-03-05 Thread Roopa Prabhu



On 3/5/12 10:23 AM, Laine Stump la...@laine.org wrote:

 On 03/04/2012 10:15 PM, Roopa Prabhu wrote:
 From: Roopa Prabhu ropra...@cisco.com
 
 This patch adds the following:
 - functions to set and get vf configs
 - Functions to replace and store vf configs (Only mac address is handled
 today.
   But the functions can be easily extended for vlans and other vf configs)
 - function to dump link dev info (This is moved from virnetdevvportprofile.c)
 
 Signed-off-by: Roopa Prabhu ropra...@cisco.com
 ---
  src/util/virnetdev.c |  531
 ++
  src/util/virnetdev.h |   19 ++
  2 files changed, 549 insertions(+), 1 deletions(-)
 
 (BTW, I never thought about doing it this way before, but I'm glad you
 added the function here in a separate patch from the patch that removes
 it from virnetdevvportprofile.c - that makes it easy to open the two
 patches side-by-side and verify that it really is moving the same code
 (well, mostly).)
 
 
 
 diff --git a/src/util/virnetdev.c b/src/util/virnetdev.c
 index 9d76d47..25f2155 100644
 --- a/src/util/virnetdev.c
 +++ b/src/util/virnetdev.c
 @@ -1127,8 +1127,497 @@ virNetDevGetPhysicalFunction(const char *ifname, char
 **pfname)
  
  return ret;
  }
 -#else /* !__linux__ */
 
 The functions here that use libnl need to be inside of
 
   #if defined(__linux__)  defined(HAVE_LIBNL)
 
 since there are linux platforms that don't have libnl, or don't have the
 proper LIBNL (RHEL5, in particular, still has libnl-1.0)
 

I was hoping someone will point out what #defines to use here. So thanks. I
will add HAVE_LIBNL. We also need it for IFLA_VF_MAC and VLAN. They were
under HAVE_VIRTPORT before. Can you suggest what I can do here ?
 

  
 +static struct nla_policy ifla_vf_policy[IFLA_VF_MAX+1] = {
 +[IFLA_VF_MAC]   = { .type = NLA_UNSPEC,
 +.maxlen = sizeof(struct ifla_vf_mac) },
 +[IFLA_VF_VLAN]  = { .type = NLA_UNSPEC,
 +.maxlen = sizeof(struct ifla_vf_vlan) },
 +};
 +
 +/**
 + * virNetDevLinkDump:
 + *
 + * @ifname: The name of the interface; only use if ifindex  0
 + * @ifindex: The interface index; may be  0 if ifname is given
 + * @nltarget_kernel: whether to send the message to the kernel or another
 + *   process
 + * @nlattr: pointer to a pointer of netlink attributes that will contain
 + *  the results
 + * @recvbuf: Pointer to the buffer holding the returned netlink response
 + *   message; free it, once not needed anymore
 + * @getPidFunc: Pointer to a function that will be invoked if the kernel
 + *  is not the target of the netlink message but it is to be
 + *  sent to another process.
 + *
 + * Get information about an interface given its name or index.
 + *
 + * Returns 0 on success, -1 on fatal error.
 + */
 +int
 +virNetDevLinkDump(const char *ifname, int ifindex,
 +  bool nltarget_kernel, struct nlattr **tb,
 +  unsigned char **recvbuf,
 +  uint32_t (*getPidFunc)(void))
 +{
 +int rc = 0;
 +struct nlmsghdr *resp;
 +struct nlmsgerr *err;
 +struct ifinfomsg ifinfo = {
 +.ifi_family = AF_UNSPEC,
 +.ifi_index  = ifindex
 +};
 +unsigned int recvbuflen;
 +uint32_t pid = 0;
 +struct nl_msg *nl_msg;
 +
 +*recvbuf = NULL;
 +
 +if (ifindex = 0  virNetDevGetIndex(ifname, ifindex)  0)
 +return -1;
 +
 +ifinfo.ifi_index = ifindex;
 +
 +nl_msg = nlmsg_alloc_simple(RTM_GETLINK, NLM_F_REQUEST);
 +if (!nl_msg) {
 +virReportOOMError();
 +return -1;
 +}
 +
 +if (nlmsg_append(nl_msg,  ifinfo, sizeof(ifinfo), NLMSG_ALIGNTO)  0)
 +goto buffer_too_small;
 +
 +if (ifindex  0  ifname) {
 +if (nla_put(nl_msg, IFLA_IFNAME, strlen(ifname)+1, ifname)  0)
 +goto buffer_too_small;
 +}
 
 
 Is this bit necessary any more? You've added code above that converts
 the ifname into an ifindex, and we've already returned if it wasn't
 successful.
 
 
Ok yes I will remove it. I added the virNetDevGetIndex at the end because
for some reason rhel kernel allowed a ifindex in setlink but not getlink
(And this is a deviation from the upstream kernel). I will fix it.


 +
 +if (!nltarget_kernel) {
 +pid = getPidFunc();
 +if (pid == 0) {
 +rc = -1;
 +goto cleanup;
 +}
 +}
 +
 +if (virNetlinkCommand(nl_msg, recvbuf, recvbuflen, pid)  0) {
 +rc = -1;
 +goto cleanup;
 +}
 +
 +if (recvbuflen  NLMSG_LENGTH(0) || *recvbuf == NULL)
 +goto malformed_resp;
 +
 +resp = (struct nlmsghdr *)*recvbuf;
 +
 +switch (resp-nlmsg_type) {
 +case NLMSG_ERROR:
 +err = (struct nlmsgerr *)NLMSG_DATA(resp);
 +if (resp-nlmsg_len  NLMSG_LENGTH(sizeof(*err)))
 +goto malformed_resp;
 +
 +if (err-error) {
 +

Re: [libvirt] [PATCH 2/4] virtnetdev: Add support functions for mac and portprofile associations on a hostdev

2012-03-05 Thread Roopa Prabhu



On 3/5/12 11:50 AM, Roopa Prabhu ropra...@cisco.com wrote:

 
 
 
 On 3/5/12 10:23 AM, Laine Stump la...@laine.org wrote:
 
 On 03/04/2012 10:15 PM, Roopa Prabhu wrote:
 From: Roopa Prabhu ropra...@cisco.com
 
 This patch adds the following:
 - functions to set and get vf configs
 - Functions to replace and store vf configs (Only mac address is handled
 today.
   But the functions can be easily extended for vlans and other vf configs)
 - function to dump link dev info (This is moved from
 virnetdevvportprofile.c)
 
 Signed-off-by: Roopa Prabhu ropra...@cisco.com
 ---
  src/util/virnetdev.c |  531
 ++
  src/util/virnetdev.h |   19 ++
  2 files changed, 549 insertions(+), 1 deletions(-)
 
 (BTW, I never thought about doing it this way before, but I'm glad you
 added the function here in a separate patch from the patch that removes
 it from virnetdevvportprofile.c - that makes it easy to open the two
 patches side-by-side and verify that it really is moving the same code
 (well, mostly).)
 
 
 
 diff --git a/src/util/virnetdev.c b/src/util/virnetdev.c
 index 9d76d47..25f2155 100644
 --- a/src/util/virnetdev.c
 +++ b/src/util/virnetdev.c
 @@ -1127,8 +1127,497 @@ virNetDevGetPhysicalFunction(const char *ifname,
 char
 **pfname)
  
  return ret;
  }
 -#else /* !__linux__ */
 
 The functions here that use libnl need to be inside of
 
   #if defined(__linux__)  defined(HAVE_LIBNL)
 
 since there are linux platforms that don't have libnl, or don't have the
 proper LIBNL (RHEL5, in particular, still has libnl-1.0)
 
 
 I was hoping someone will point out what #defines to use here. So thanks. I
 will add HAVE_LIBNL. We also need it for IFLA_VF_MAC and VLAN. They were
 under HAVE_VIRTPORT before. Can you suggest what I can do here ?
  
 
Correction: They were under WITH_VIRUALPORT (which has a configure option
and a check for IFLA_VF_PORT_MAX).

We will need a check for IFLA_VF_MAX here.

I think I will try putting this under defined(IFLA_VF_MAX). This should
cover IFLA_VF_MAC and IFLA_VF_VLAN I think. If you have any other
suggestions let me know.

Thanks,
Roopa


--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] [PATCH 2/4] virtnetdev: Add support functions for mac and portprofile associations on a hostdev

2012-03-05 Thread Laine Stump
On 03/05/2012 02:50 PM, Roopa Prabhu wrote:


 On 3/5/12 10:23 AM, Laine Stump la...@laine.org wrote:

 On 03/04/2012 10:15 PM, Roopa Prabhu wrote:
 From: Roopa Prabhu ropra...@cisco.com

 This patch adds the following:
 - functions to set and get vf configs
 - Functions to replace and store vf configs (Only mac address is handled
 today.
   But the functions can be easily extended for vlans and other vf configs)
 - function to dump link dev info (This is moved from 
 virnetdevvportprofile.c)

 Signed-off-by: Roopa Prabhu ropra...@cisco.com
 ---
  src/util/virnetdev.c |  531
 ++
  src/util/virnetdev.h |   19 ++
  2 files changed, 549 insertions(+), 1 deletions(-)
 (BTW, I never thought about doing it this way before, but I'm glad you
 added the function here in a separate patch from the patch that removes
 it from virnetdevvportprofile.c - that makes it easy to open the two
 patches side-by-side and verify that it really is moving the same code
 (well, mostly).)


 diff --git a/src/util/virnetdev.c b/src/util/virnetdev.c
 index 9d76d47..25f2155 100644
 --- a/src/util/virnetdev.c
 +++ b/src/util/virnetdev.c
 @@ -1127,8 +1127,497 @@ virNetDevGetPhysicalFunction(const char *ifname, 
 char
 **pfname)
  
  return ret;
  }
 -#else /* !__linux__ */
 The functions here that use libnl need to be inside of

   #if defined(__linux__)  defined(HAVE_LIBNL)

 since there are linux platforms that don't have libnl, or don't have the
 proper LIBNL (RHEL5, in particular, still has libnl-1.0)

 I was hoping someone will point out what #defines to use here. So thanks. I
 will add HAVE_LIBNL. We also need it for IFLA_VF_MAC and VLAN. They were
 under HAVE_VIRTPORT before. Can you suggest what I can do here ?

I would put it inside HAVE_LIBNL, because that's the library you need to
compile it.

  

  
 +static struct nla_policy ifla_vf_policy[IFLA_VF_MAX+1] = {
 +[IFLA_VF_MAC]   = { .type = NLA_UNSPEC,
 +.maxlen = sizeof(struct ifla_vf_mac) },
 +[IFLA_VF_VLAN]  = { .type = NLA_UNSPEC,
 +.maxlen = sizeof(struct ifla_vf_vlan) },
 +};
 +
 +/**
 + * virNetDevLinkDump:
 + *
 + * @ifname: The name of the interface; only use if ifindex  0
 + * @ifindex: The interface index; may be  0 if ifname is given
 + * @nltarget_kernel: whether to send the message to the kernel or another
 + *   process
 + * @nlattr: pointer to a pointer of netlink attributes that will contain
 + *  the results
 + * @recvbuf: Pointer to the buffer holding the returned netlink response
 + *   message; free it, once not needed anymore
 + * @getPidFunc: Pointer to a function that will be invoked if the kernel
 + *  is not the target of the netlink message but it is to be
 + *  sent to another process.
 + *
 + * Get information about an interface given its name or index.
 + *
 + * Returns 0 on success, -1 on fatal error.
 + */
 +int
 +virNetDevLinkDump(const char *ifname, int ifindex,
 +  bool nltarget_kernel, struct nlattr **tb,
 +  unsigned char **recvbuf,
 +  uint32_t (*getPidFunc)(void))
 +{
 +int rc = 0;
 +struct nlmsghdr *resp;
 +struct nlmsgerr *err;
 +struct ifinfomsg ifinfo = {
 +.ifi_family = AF_UNSPEC,
 +.ifi_index  = ifindex
 +};
 +unsigned int recvbuflen;
 +uint32_t pid = 0;
 +struct nl_msg *nl_msg;
 +
 +*recvbuf = NULL;
 +
 +if (ifindex = 0  virNetDevGetIndex(ifname, ifindex)  0)
 +return -1;
 +
 +ifinfo.ifi_index = ifindex;
 +
 +nl_msg = nlmsg_alloc_simple(RTM_GETLINK, NLM_F_REQUEST);
 +if (!nl_msg) {
 +virReportOOMError();
 +return -1;
 +}
 +
 +if (nlmsg_append(nl_msg,  ifinfo, sizeof(ifinfo), NLMSG_ALIGNTO)  0)
 +goto buffer_too_small;
 +
 +if (ifindex  0  ifname) {
 +if (nla_put(nl_msg, IFLA_IFNAME, strlen(ifname)+1, ifname)  0)
 +goto buffer_too_small;
 +}

 Is this bit necessary any more? You've added code above that converts
 the ifname into an ifindex, and we've already returned if it wasn't
 successful.


 Ok yes I will remove it. I added the virNetDevGetIndex at the end because
 for some reason rhel kernel allowed a ifindex in setlink but not getlink
 (And this is a deviation from the upstream kernel). I will fix it.


 +
 +if (!nltarget_kernel) {
 +pid = getPidFunc();
 +if (pid == 0) {
 +rc = -1;
 +goto cleanup;
 +}
 +}
 +
 +if (virNetlinkCommand(nl_msg, recvbuf, recvbuflen, pid)  0) {
 +rc = -1;
 +goto cleanup;
 +}
 +
 +if (recvbuflen  NLMSG_LENGTH(0) || *recvbuf == NULL)
 +goto malformed_resp;
 +
 +resp = (struct nlmsghdr *)*recvbuf;
 +
 +switch (resp-nlmsg_type) {
 +case NLMSG_ERROR:
 +err = (struct nlmsgerr *)NLMSG_DATA(resp);
 +if (resp-nlmsg_len  

[libvirt] [PATCH 2/4] virtnetdev: Add support functions for mac and portprofile associations on a hostdev

2012-03-04 Thread Roopa Prabhu
From: Roopa Prabhu ropra...@cisco.com

This patch adds the following:
- functions to set and get vf configs
- Functions to replace and store vf configs (Only mac address is handled today.
  But the functions can be easily extended for vlans and other vf configs)
- function to dump link dev info (This is moved from virnetdevvportprofile.c)

Signed-off-by: Roopa Prabhu ropra...@cisco.com
---
 src/util/virnetdev.c |  531 ++
 src/util/virnetdev.h |   19 ++
 2 files changed, 549 insertions(+), 1 deletions(-)


diff --git a/src/util/virnetdev.c b/src/util/virnetdev.c
index 9d76d47..25f2155 100644
--- a/src/util/virnetdev.c
+++ b/src/util/virnetdev.c
@@ -1127,8 +1127,497 @@ virNetDevGetPhysicalFunction(const char *ifname, char 
**pfname)
 
 return ret;
 }
-#else /* !__linux__ */
 
+static struct nla_policy ifla_vf_policy[IFLA_VF_MAX+1] = {
+[IFLA_VF_MAC]   = { .type = NLA_UNSPEC,
+.maxlen = sizeof(struct ifla_vf_mac) },
+[IFLA_VF_VLAN]  = { .type = NLA_UNSPEC,
+.maxlen = sizeof(struct ifla_vf_vlan) },
+};
+
+/**
+ * virNetDevLinkDump:
+ *
+ * @ifname: The name of the interface; only use if ifindex  0
+ * @ifindex: The interface index; may be  0 if ifname is given
+ * @nltarget_kernel: whether to send the message to the kernel or another
+ *   process
+ * @nlattr: pointer to a pointer of netlink attributes that will contain
+ *  the results
+ * @recvbuf: Pointer to the buffer holding the returned netlink response
+ *   message; free it, once not needed anymore
+ * @getPidFunc: Pointer to a function that will be invoked if the kernel
+ *  is not the target of the netlink message but it is to be
+ *  sent to another process.
+ *
+ * Get information about an interface given its name or index.
+ *
+ * Returns 0 on success, -1 on fatal error.
+ */
+int
+virNetDevLinkDump(const char *ifname, int ifindex,
+  bool nltarget_kernel, struct nlattr **tb,
+  unsigned char **recvbuf,
+  uint32_t (*getPidFunc)(void))
+{
+int rc = 0;
+struct nlmsghdr *resp;
+struct nlmsgerr *err;
+struct ifinfomsg ifinfo = {
+.ifi_family = AF_UNSPEC,
+.ifi_index  = ifindex
+};
+unsigned int recvbuflen;
+uint32_t pid = 0;
+struct nl_msg *nl_msg;
+
+*recvbuf = NULL;
+
+if (ifindex = 0  virNetDevGetIndex(ifname, ifindex)  0)
+return -1;
+
+ifinfo.ifi_index = ifindex;
+
+nl_msg = nlmsg_alloc_simple(RTM_GETLINK, NLM_F_REQUEST);
+if (!nl_msg) {
+virReportOOMError();
+return -1;
+}
+
+if (nlmsg_append(nl_msg,  ifinfo, sizeof(ifinfo), NLMSG_ALIGNTO)  0)
+goto buffer_too_small;
+
+if (ifindex  0  ifname) {
+if (nla_put(nl_msg, IFLA_IFNAME, strlen(ifname)+1, ifname)  0)
+goto buffer_too_small;
+}
+
+if (!nltarget_kernel) {
+pid = getPidFunc();
+if (pid == 0) {
+rc = -1;
+goto cleanup;
+}
+}
+
+if (virNetlinkCommand(nl_msg, recvbuf, recvbuflen, pid)  0) {
+rc = -1;
+goto cleanup;
+}
+
+if (recvbuflen  NLMSG_LENGTH(0) || *recvbuf == NULL)
+goto malformed_resp;
+
+resp = (struct nlmsghdr *)*recvbuf;
+
+switch (resp-nlmsg_type) {
+case NLMSG_ERROR:
+err = (struct nlmsgerr *)NLMSG_DATA(resp);
+if (resp-nlmsg_len  NLMSG_LENGTH(sizeof(*err)))
+goto malformed_resp;
+
+if (err-error) {
+virReportSystemError(-err-error,
+ _(error dumping %s (%d) interface),
+ ifname, ifindex);
+rc = -1;
+}
+break;
+
+case GENL_ID_CTRL:
+case NLMSG_DONE:
+rc = nlmsg_parse(resp, sizeof(struct ifinfomsg),
+ tb, IFLA_MAX, NULL);
+if (rc  0)
+goto malformed_resp;
+break;
+
+default:
+goto malformed_resp;
+}
+
+if (rc != 0)
+VIR_FREE(*recvbuf);
+
+cleanup:
+nlmsg_free(nl_msg);
+
+return rc;
+
+malformed_resp:
+nlmsg_free(nl_msg);
+
+virNetDevError(VIR_ERR_INTERNAL_ERROR, %s,
+   _(malformed netlink response message));
+VIR_FREE(*recvbuf);
+return -1;
+
+buffer_too_small:
+nlmsg_free(nl_msg);
+
+virNetDevError(VIR_ERR_INTERNAL_ERROR, %s,
+   _(allocated netlink buffer is too small));
+return -1;
+}
+
+static int
+virNetDevSetVfConfig(const char *ifname, int ifindex, int vf,
+ bool nltarget_kernel, const unsigned char *macaddr,
+ int vlanid, uint32_t (*getPidFunc)(void))
+{
+int rc = -1;
+struct nlmsghdr *resp;
+struct nlmsgerr *err;
+unsigned char *recvbuf = NULL;
+unsigned int recvbuflen = 0;
+uint32_t pid = 0;
+struct nl_msg *nl_msg;
+struct ifinfomsg ifinfo 

[libvirt] [PATCH 2/4] virtnetdev: Add support functions for mac and portprofile associations on a hostdev

2012-03-01 Thread Roopa Prabhu
From: Roopa Prabhu ropra...@cisco.com

This patch adds the following:
- functions to set and get vf configs
- Functions to replace and store vf configs (Only mac address is handled today.
  But the functions can be easily extended for vlans and other vf configs)
- function to dump link dev info (This is moved from virnetdevvportprofile.c)

Signed-off-by: Roopa Prabhu ropra...@cisco.com
---
 src/util/virnetdev.c |  531 ++
 src/util/virnetdev.h |   19 ++
 2 files changed, 549 insertions(+), 1 deletions(-)


diff --git a/src/util/virnetdev.c b/src/util/virnetdev.c
index 9d76d47..25f2155 100644
--- a/src/util/virnetdev.c
+++ b/src/util/virnetdev.c
@@ -1127,8 +1127,497 @@ virNetDevGetPhysicalFunction(const char *ifname, char 
**pfname)
 
 return ret;
 }
-#else /* !__linux__ */
 
+static struct nla_policy ifla_vf_policy[IFLA_VF_MAX+1] = {
+[IFLA_VF_MAC]   = { .type = NLA_UNSPEC,
+.maxlen = sizeof(struct ifla_vf_mac) },
+[IFLA_VF_VLAN]  = { .type = NLA_UNSPEC,
+.maxlen = sizeof(struct ifla_vf_vlan) },
+};
+
+/**
+ * virNetDevLinkDump:
+ *
+ * @ifname: The name of the interface; only use if ifindex  0
+ * @ifindex: The interface index; may be  0 if ifname is given
+ * @nltarget_kernel: whether to send the message to the kernel or another
+ *   process
+ * @nlattr: pointer to a pointer of netlink attributes that will contain
+ *  the results
+ * @recvbuf: Pointer to the buffer holding the returned netlink response
+ *   message; free it, once not needed anymore
+ * @getPidFunc: Pointer to a function that will be invoked if the kernel
+ *  is not the target of the netlink message but it is to be
+ *  sent to another process.
+ *
+ * Get information about an interface given its name or index.
+ *
+ * Returns 0 on success, -1 on fatal error.
+ */
+int
+virNetDevLinkDump(const char *ifname, int ifindex,
+  bool nltarget_kernel, struct nlattr **tb,
+  unsigned char **recvbuf,
+  uint32_t (*getPidFunc)(void))
+{
+int rc = 0;
+struct nlmsghdr *resp;
+struct nlmsgerr *err;
+struct ifinfomsg ifinfo = {
+.ifi_family = AF_UNSPEC,
+.ifi_index  = ifindex
+};
+unsigned int recvbuflen;
+uint32_t pid = 0;
+struct nl_msg *nl_msg;
+
+*recvbuf = NULL;
+
+if (ifindex = 0  virNetDevGetIndex(ifname, ifindex)  0)
+return -1;
+
+ifinfo.ifi_index = ifindex;
+
+nl_msg = nlmsg_alloc_simple(RTM_GETLINK, NLM_F_REQUEST);
+if (!nl_msg) {
+virReportOOMError();
+return -1;
+}
+
+if (nlmsg_append(nl_msg,  ifinfo, sizeof(ifinfo), NLMSG_ALIGNTO)  0)
+goto buffer_too_small;
+
+if (ifindex  0  ifname) {
+if (nla_put(nl_msg, IFLA_IFNAME, strlen(ifname)+1, ifname)  0)
+goto buffer_too_small;
+}
+
+if (!nltarget_kernel) {
+pid = getPidFunc();
+if (pid == 0) {
+rc = -1;
+goto cleanup;
+}
+}
+
+if (virNetlinkCommand(nl_msg, recvbuf, recvbuflen, pid)  0) {
+rc = -1;
+goto cleanup;
+}
+
+if (recvbuflen  NLMSG_LENGTH(0) || *recvbuf == NULL)
+goto malformed_resp;
+
+resp = (struct nlmsghdr *)*recvbuf;
+
+switch (resp-nlmsg_type) {
+case NLMSG_ERROR:
+err = (struct nlmsgerr *)NLMSG_DATA(resp);
+if (resp-nlmsg_len  NLMSG_LENGTH(sizeof(*err)))
+goto malformed_resp;
+
+if (err-error) {
+virReportSystemError(-err-error,
+ _(error dumping %s (%d) interface),
+ ifname, ifindex);
+rc = -1;
+}
+break;
+
+case GENL_ID_CTRL:
+case NLMSG_DONE:
+rc = nlmsg_parse(resp, sizeof(struct ifinfomsg),
+ tb, IFLA_MAX, NULL);
+if (rc  0)
+goto malformed_resp;
+break;
+
+default:
+goto malformed_resp;
+}
+
+if (rc != 0)
+VIR_FREE(*recvbuf);
+
+cleanup:
+nlmsg_free(nl_msg);
+
+return rc;
+
+malformed_resp:
+nlmsg_free(nl_msg);
+
+virNetDevError(VIR_ERR_INTERNAL_ERROR, %s,
+   _(malformed netlink response message));
+VIR_FREE(*recvbuf);
+return -1;
+
+buffer_too_small:
+nlmsg_free(nl_msg);
+
+virNetDevError(VIR_ERR_INTERNAL_ERROR, %s,
+   _(allocated netlink buffer is too small));
+return -1;
+}
+
+static int
+virNetDevSetVfConfig(const char *ifname, int ifindex, int vf,
+ bool nltarget_kernel, const unsigned char *macaddr,
+ int vlanid, uint32_t (*getPidFunc)(void))
+{
+int rc = -1;
+struct nlmsghdr *resp;
+struct nlmsgerr *err;
+unsigned char *recvbuf = NULL;
+unsigned int recvbuflen = 0;
+uint32_t pid = 0;
+struct nl_msg *nl_msg;
+struct ifinfomsg ifinfo