[libvirt] [RFC] [PATCH 3/3] vepa+vsi: Some experimental code for 802.1Qbh

Stefan Berger stefanb at linux.vnet.ibm.com
Thu May 20 20:25:29 UTC 2010


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 at linux.vnet.ibm.com>

---
 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;
 }
 




More information about the libvir-list mailing list