Re: [libvirt] [PATCH 2/4] virtnetdev: Add support functions for mac and portprofile associations on a hostdev
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
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
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
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
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
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