This patch may get 802.1Qbh devices working. I am adding some code to poll for the status of an 802.1Qbh device and loop for a while until the status indicates success. This part for sure needs more work and testing... I am recycling link_dump from a previous patch. Signed-off-by: Stefan Berger <stefanb@xxxxxxxxxxxxxxxxxx> --- src/util/macvtap.c | 116 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) Index: libvirt-acl/src/util/macvtap.c =================================================================== --- libvirt-acl.orig/src/util/macvtap.c +++ libvirt-acl/src/util/macvtap.c @@ -960,6 +960,95 @@ getPortProfileStatus(struct nlmsghdr *nl static int +link_dump(int ifindex, const char *ifname, struct nlattr **tb, + char **recvbuf) +{ + int rc = 0; + char nlmsgbuf[256] = { 0, }; + struct nlmsghdr *nlm = (struct nlmsghdr *)nlmsgbuf, *resp; + struct nlmsgerr *err; + char rtattbuf[64]; + struct rtattr *rta; + struct ifinfomsg i = { + .ifi_family = AF_UNSPEC, + .ifi_index = ifindex + }; + int recvbuflen; + + *recvbuf = NULL; + + nlInit(nlm, NLM_F_REQUEST, RTM_GETLINK); + + if (!nlAppend(nlm, sizeof(nlmsgbuf), &i, sizeof(i))) + goto buffer_too_small; + + if (ifindex < 0 && ifname != NULL) { + rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_IFNAME, + ifname, strlen(ifname) + 1); + if (!rta) + goto buffer_too_small; + + if (!nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len)) + goto buffer_too_small; + } + + if (nlComm(nlm, recvbuf, &recvbuflen) < 0) + return -1; + + 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; + + switch (-err->error) { + case 0: + break; + + default: + virReportSystemError(-err->error, + _("error dumping %d interface"), + ifindex); + rc = -1; + } + break; + + case GENL_ID_CTRL: + case NLMSG_DONE: + if (nlmsg_parse(resp, sizeof(struct ifinfomsg), + tb, IFLA_MAX, ifla_policy)) { + goto malformed_resp; + } + break; + + default: + goto malformed_resp; + } + + if (rc != 0) + VIR_FREE(*recvbuf); + + return rc; + +malformed_resp: + macvtapError(VIR_ERR_INTERNAL_ERROR, "%s", + _("malformed netlink response message")); + VIR_FREE(*recvbuf); + return -1; + +buffer_too_small: + macvtapError(VIR_ERR_INTERNAL_ERROR, "%s", + _("internal buffer is too small")); + return -1; +} + + +static int doPortProfileOpSetLink(bool multicast, const char *ifname, int ifindex, const char *profileId, @@ -1151,6 +1240,10 @@ doPortProfileOpCommon(bool multicast, uint8_t op) { int rc; + char *recvbuf = NULL; + struct nlattr *tb[IFLA_MAX + 1]; + int repeats = 5; + uint16_t status; rc = doPortProfileOpSetLink(multicast, ifname, ifindex, @@ -1167,6 +1260,30 @@ doPortProfileOpCommon(bool multicast, return rc; } + if (!multicast) { + /* 802.1Qbh -- query for status */ + while (--repeats) { + rc = link_dump(ifindex, ifname, tb, &recvbuf); + if (rc) + goto err_exit; + rc = getPortProfileStatus((struct nlmsghdr *)recvbuf, &status); + if (rc == 0) { + if (status == 0) + break; + if (status != 0) { + fprintf(stderr,"Current status: %d\n", status); + rc = 1; + } + } + usleep(10000); + + VIR_FREE(recvbuf); + } + } + +err_exit: + VIR_FREE(recvbuf); + return rc; } -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list