<br><tt><font size=2>libvir-list-bounces@redhat.com wrote on 05/25/2010
09:00:26 AM:<br>
<br>
</font></tt>
<br><tt><font size=2>> <br>
> Scott Feldman wrote:<br>
> > From: Scott Feldman <scofeldm@cisco.com><br>
> ...<br>
> > diff --git a/configure.ac b/configure.ac<br>
> ...<br>
> > -if test "$with_macvtap" = "yes"; then<br>
> > +if test "$with_macvtap" = "yes" || "$with_virtualport"
= "yes"; then<br>
> <br>
> Hi Scott,<br>
> <br>
> The above introduces a syntax error.<br>
> Fix it by inserting a "test" after the "||":</font></tt>
<br>
<br><tt><font size=2>My bad. Will fix it.</font></tt>
<br>
<br><tt><font size=2><br>
> > +static int<br>
> > +nlCommWaitSuccess(struct nlmsghdr *nlmsg, int nl_groups,<br>
> > +                  char
**respbuf, int *respbuflen, long to_usecs)<br>
> <br>
> The parameters, respbuflen and nl_groups make sense only when<br>
> non-negative, so my reflex is to make their types reflect that.<br>
> Any reason not to use an unsigned type in those cases?</font></tt>
<br>
<br><tt><font size=2>nl_groups should be uint32_t or even __u32 to reflect
the kernel includes.</font></tt>
<br><tt><font size=2>I'll fix them.</font></tt>
<br><tt><font size=2><br>
> <br>
> This "to_usecs" parameter is in the same boat, in that it
is<br>
> logically non-negative.  I suggest using unsigned long long<br>
> for it, since technically (with the two longs in struct timeval)<br>
> a portable timeout can be as large as 2^31 * 1000^2 microseconds.</font></tt>
<br>
<br><tt><font size=2>I'll do that.</font></tt>
<br><tt><font size=2><br>
> Also, it'd be nice to rename it to "timeout_usecs", since
"to_usecs"<br>
> made me think of a flag that says whether to convert "to microseconds".<br>
> </font></tt>
<br>
<br>
<br><tt><font size=2>Will rename the variable.</font></tt>
<br><tt><font size=2><br>
> > +{<br>
> > +    int rc = 0;<br>
> > +    struct sockaddr_nl nladdr = {<br>
> > +            .nl_family = AF_NETLINK,<br>
> > +            .nl_pid    =
getpid(),<br>
> > +            .nl_groups = nl_groups,<br>
> > +    };<br>
> > +    int rcvChunkSize = 1024; // expecting less than
that<br>
> > +    int rcvoffset = 0;<br>
> <br>
> This should be of type size_t.</font></tt>
<br>
<br><tt><font size=2>Ok.</font></tt>
<br><tt><font size=2><br>
> It is used as an accumulator, and we do add nbytes (of type ssize_t)
to it,<br>
> and (esp!) use it as an array index, so its type must be unsigned.<br>
> Otherwise, overflow could be exploitable.<br>
> <br>
> > +    ssize_t nbytes;<br>
> > +    int n;<br>
> > +    struct timeval tv = {<br>
> > +        .tv_sec  = to_usecs / MICROSEC_PER_SEC,<br>
> > +        .tv_usec = to_usecs % MICROSEC_PER_SEC,<br>
> > +    };<br>
> > +    fd_set rfds;<br>
> <br>
> At least "n" and "rfds" are used only in the while
loop,<br>
> so their declarations belong "down" there, too.</font></tt>
<br>
<br><tt><font size=2>Sure, I'll move them.</font></tt>
<br><tt><font size=2><br>
> <br>
> > +    bool gotvalid = false;<br>
> <br>
> Personal preference:<br>
> I find that a name like "got_valid" is easier to read than
a<br>
> variablenamewithnoseparatorbetweenwords.</font></tt>
<br><tt><font size=2>> Same for rcvoffset vs. rcv_offset, etc.</font></tt>
<br>
<br><tt><font size=2>Ok. I can rename them as well.</font></tt>
<br><tt><font size=2><br>
> <br>
> > +    int fd = nlOpen();<br>
> > +    static uint32_t seq = 0x1234;<br>
> > +    uint32_t myseq = seq++;<br>
> > +    uint32_t mypid = getpid();<br>
> > +<br>
> > +    if (fd < 0)<br>
> > +        return -1;<br>
> > +<br>
> > +    nlmsg->nlmsg_pid = mypid;<br>
> > +    nlmsg->nlmsg_seq = myseq;<br>
> > +    nlmsg->nlmsg_flags |= NLM_F_ACK;<br>
> > +<br>
> > +    nbytes = sendto(fd, (void *)nlmsg, nlmsg->nlmsg_len,
0,<br>
> > +                  
 (struct sockaddr *)&nladdr, sizeof(nladdr));<br>
> > +    if (nbytes < 0) {<br>
> > +        virReportSystemError(errno,<br>
> > +                  
          "%s", _("cannot send
to netlink socket"));<br>
> > +        rc = -1;<br>
> > +        goto err_exit;<br>
> > +    }<br>
> > +<br>
> > +    while (!gotvalid) {<br>
> > +        rcvoffset = 0;<br>
> > +        while (1) {<br>
> > +            socklen_t addrlen
= sizeof(nladdr);<br>
> > +<br>
> > +            if (VIR_REALLOC_N(*respbuf,
rcvoffset+rcvChunkSize) < 0) {<br>
> > +                virReportOOMError();<br>
> > +                rc =
-1;<br>
> > +                goto
err_exit;<br>
> > +            }<br>
> > +<br>
> > +            FD_ZERO(&rfds);<br>
> > +            FD_SET(fd, &rfds);<br>
> > +<br>
> > +            n = select(fd + 1,
&rfds, NULL, NULL, &tv);<br>
> > +            if (n == 0) {<br>
> <br>
> That handles the case of an expired timeout.<br>
> However, if select fails, it returns -1.<br>
> You should diagnose that failure rather than going<br>
> ahead and reading from "fd".</font></tt>
<br>
<br><tt><font size=2>I'll dump an error and will return in case of -1.</font></tt>
<br><tt><font size=2><br>
> <br>
> > +                rc =
-1;<br>
> > +                goto
err_exit;<br>
> > +            }<br>
> > +<br>
> > +            nbytes = recvfrom(fd,
&((*respbuf)[rcvoffset]), <br>
> rcvChunkSize, 0,<br>
> > +                  
           (struct sockaddr *)&nladdr,
&addrlen);<br>
> > +            if (nbytes < 0)
{<br>
> > +                if (errno
== EAGAIN || errno == EINTR)<br>
> > +                  
 continue;<br>
> > +                virReportSystemError(errno,
"%s",<br>
> > +                  
                  _("error
receiving from <br>
> netlink socket"));<br>
> > +                rc =
-1;<br>
> > +                goto
err_exit;<br>
> > +            }<br>
> > +            rcvoffset += nbytes;<br>
> > +            break;<br>
> > +        }<br>
> > +        *respbuflen = rcvoffset;<br>
> > +<br>
> > +        /* check message for error */<br>
> > +        if (*respbuflen > NLMSG_LENGTH(0)
&& *respbuf != NULL) {<br>
> > +            struct nlmsghdr *resp
= (struct nlmsghdr *)*respbuf;<br>
> > +            struct nlmsgerr *err;<br>
> > +<br>
> > +            if (resp->nlmsg_pid
!= mypid ||<br>
> > +                resp->nlmsg_seq
!= myseq)<br>
> > +                continue;<br>
> > +<br>
> > +            /* skip reflected
message */<br>
> > +            if (resp->nlmsg_type
& 0x10)<br>
> > +                continue;<br>
> > +<br>
> > +            switch (resp->nlmsg_type)
{<br>
> > +               case NLMSG_ERROR:<br>
> > +                  err
= (struct nlmsgerr *)NLMSG_DATA(resp);<br>
> > +                  if
(resp->nlmsg_len >= NLMSG_LENGTH(sizeof(*err))) {<br>
> > +                  
   if (-err->error != EOPNOTSUPP) {<br>
> <br>
> I'm used to seeing this:<br>
>                    
     if (err->error != -EOPNOTSUPP) {<br>
> why do you do it the other way?</font></tt>
<br><tt><font size=2>> Such differences are generally discouraged.</font></tt>
<br>
<br><tt><font size=2>Alright. Will fix it.</font></tt>
<br><tt><font size=2><br>
> <br>
> > +                  
       /* assuming error msg from daemon */<br>
> > +                  
       gotvalid = true;<br>
> > +                  
       break;<br>
> > +                  
   }<br>
> > +                  }<br>
> > +                  /*
whatever this is, skip it */<br>
> > +                  VIR_FREE(*respbuf);<br>
> > +                  *respbuf
= NULL;<br>
> <br>
> The above is a dead store, since VIR_FREE has just done that.</font></tt>
<br>
<br><tt><font size=2>Ok.</font></tt>
<br><tt><font size=2><br>
> <br>
> > +                  *respbuflen
= 0;<br>
> > +                  break;<br>
> > +<br>
> > +               case NLMSG_DONE:<br>
> > +                  gotvalid
= true;<br>
> > +                  break;<br>
> > +<br>
> > +               default:<br>
> > +                  VIR_FREE(*respbuf);<br>
> > +                  *respbuf
= NULL;<br>
> <br>
> Likewise.  Remove the dead store.</font></tt>
<br>
<br><tt><font size=2>Ok.</font></tt>
<br><tt><font size=2><br>
> <br>
> > +                  *respbuflen
= 0;<br>
> > +                  break;<br>
> > +            }<br>
> > +        }<br>
> > +    }<br>
> > +<br>
> > +err_exit:<br>
> > +    if (rc == -1) {<br>
> > +        VIR_FREE(*respbuf);<br>
> > +        *respbuf = NULL;<br>
> <br>
> Likewise.  Remove the dead store.</font></tt>
<br>
<br><tt><font size=2>OK.<br>
> <br>
> > +        *respbuflen = 0;<br>
> > +    }<br>
> > +<br>
> > +    nlClose(fd);<br>
> > +    return rc;<br>
> > +}<br>
> > +<br>
> > +# endif<br>
> ...<br>
> <br>
> > +static int<br>
> > +link_dump(int ifindex, struct nlattr **tb, char **recvbuf)<br>
> > +{<br>
> > +    int rc = 0;<br>
> > +    char nlmsgbuf[256] = { 0, };<br>
> > +    struct nlmsghdr *nlm = (struct nlmsghdr *)nlmsgbuf,
*resp;<br>
> > +    struct nlmsgerr *err;<br>
> > +    struct ifinfomsg i = {<br>
> > +        .ifi_family = AF_UNSPEC,<br>
> > +        .ifi_index  = ifindex<br>
> > +    };<br>
> <br>
> When I first read the "sizeof(i)" below I did a double take.<br>
> I'd prefer a name that does not make me think of an integer index.</font></tt>
<br>
<br><tt><font size=2>Will fix this.</font></tt>
<br><tt><font size=2><br>
> <br>
> > +    int recvbuflen;<br>
> > +<br>
> > +    *recvbuf = NULL;<br>
> > +<br>
> > +    nlInit(nlm, NLM_F_REQUEST, RTM_GETLINK);<br>
> > +<br>
> > +    if (!nlAppend(nlm, sizeof(nlmsgbuf), &i, sizeof(i)))<br>
> > +        goto buffer_too_small;<br>
> > +<br>
> > +    if (nlComm(nlm, recvbuf, &recvbuflen) <
0)<br>
> > +        return -1;<br>
> > +<br>
> > +    if (recvbuflen < NLMSG_LENGTH(0) || *recvbuf
== NULL)<br>
> > +        goto malformed_resp;<br>
> > +<br>
> > +    resp = (struct nlmsghdr *)*recvbuf;<br>
> > +<br>
> > +    switch (resp->nlmsg_type) {<br>
> > +    case NLMSG_ERROR:<br>
> > +        err = (struct nlmsgerr *)NLMSG_DATA(resp);<br>
> > +        if (resp->nlmsg_len < NLMSG_LENGTH(sizeof(*err)))<br>
> > +            goto malformed_resp;<br>
> > +<br>
> > +        switch (-err->error) {<br>
> <br>
> Please remove the unary "-", since it's not used here.</font></tt>
<br>
<br><tt><font size=2>Ok.</font></tt>
<br><tt><font size=2><br>
> <br>
> > +        case 0:<br>
> > +        break;<br>
> <br>
> That "break;" should be indented.</font></tt>
<br>
<br><tt><font size=2>Ok.</font></tt>
<br><tt><font size=2><br>
> <br>
> > +<br>
> > +        default:<br>
> > +            virReportSystemError(-err->error,<br>
> > +                  
              _("error dumping
%d interface"),<br>
> > +                  
              ifindex);<br>
> > +            rc = -1;<br>
> > +        }<br>
> > +    break;<br>
> <br>
> Same here.  Indent.</font></tt>
<br><tt><font size=2><br>
> <br>
> > +<br>
> > +    case GENL_ID_CTRL:<br>
> > +    case NLMSG_DONE:<br>
> > +        if (nlmsg_parse(resp, sizeof(struct
ifinfomsg),<br>
> > +                  
     tb, IFLA_MAX, ifla_policy)) {<br>
> > +            goto malformed_resp;<br>
> > +        }<br>
> > +    break;<br>
> <br>
> And here.  Indent the "break".<br>
> <br>
> > +<br>
> > +    default:<br>
> > +        goto malformed_resp;<br>
> > +    }<br>
> > +<br>
> > +    if (rc != 0)<br>
> > +        VIR_FREE(*recvbuf);<br>
> > +<br>
> > +    return rc;<br>
> > +<br>
> > +malformed_resp:<br>
> > +    macvtapError(VIR_ERR_INTERNAL_ERROR, "%s",<br>
> > +                 _("malformed
netlink response message"));<br>
> > +    VIR_FREE(*recvbuf);<br>
> > +    return -1;<br>
> > +<br>
> > +buffer_too_small:<br>
> > +    macvtapError(VIR_ERR_INTERNAL_ERROR, "%s",<br>
> > +                 _("internal
buffer is too small"));<br>
> > +    return -1;<br>
> > +}<br>
> ...<br>
> > +static int<br>
> > +doPortProfileOpSetLink(bool multicast,<br>
> > +                  
    int ifindex,<br>
> > +                  
    const char *profileId,<br>
> > +                  
    struct ifla_port_vsi *portVsi,<br>
> > +                  
    const unsigned char *instanceId,<br>
> > +                  
    const unsigned char *hostUUID,<br>
> > +                  
    int32_t vf,<br>
> > +                  
    uint8_t op)<br>
> > +{<br>
> > +    int rc = 0;<br>
> > +    char nlmsgbuf[256];<br>
> > +    struct nlmsghdr *nlm = (struct nlmsghdr *)nlmsgbuf,
*resp;<br>
> > +    struct nlmsgerr *err;<br>
> > +    char rtattbuf[64];<br>
> <br>
> Can you use a symbolic constant instead of "64" ?<br>
</font></tt>
<br><tt><font size=2>Had a previous patch adding that but it was abandoned.
Will re-add this.</font></tt>
<br>
<br><tt><font size=2>> <br>
> > +    struct rtattr *rta, *vfports, *vfport;<br>
> > +    struct ifinfomsg ifinfo = {<br>
> > +        .ifi_family = AF_UNSPEC,<br>
> > +        .ifi_index  = ifindex,<br>
> > +    };<br>
> > +    char *recvbuf = NULL;<br>
> > +    int recvbuflen = 0;<br>
> > +<br>
> > +    memset(&nlmsgbuf, 0, sizeof(nlmsgbuf));<br>
> > +<br>
> > +    nlInit(nlm, NLM_F_REQUEST, RTM_SETLINK);<br>
> > +<br>
> > +    if (!nlAppend(nlm, sizeof(nlmsgbuf), &ifinfo,
sizeof(ifinfo)))<br>
> > +        goto buffer_too_small;<br>
> > +<br>
> > +    if (vf == PORT_SELF_VF) {<br>
> > +        rta = rtattrCreate(rtattbuf, sizeof(rtattbuf),
<br>
> IFLA_PORT_SELF, NULL, 0);<br>
> > +    } else {<br>
> > +        rta = rtattrCreate(rtattbuf, sizeof(rtattbuf),
<br>
> IFLA_VF_PORTS, NULL, 0);<br>
> > +        if (!rta)<br>
> > +            goto buffer_too_small;<br>
> > +<br>
> > +        if (!(vfports = nlAppend(nlm, sizeof(nlmsgbuf),<br>
> > +                  
              rtattbuf, rta->rta_len)))<br>
> > +            goto buffer_too_small;<br>
> > +<br>
> > +        /* beging nesting vfports */<br>
> <br>
> Typo.<br>
> s/beging/begin/</font></tt>
<br>
<br><tt><font size=2>Ok.</font></tt>
<br><tt><font size=2><br>
> <br>
> > +        rta = rtattrCreate(rtattbuf, sizeof(rtattbuf),
<br>
> IFLA_VF_PORT, NULL, 0);<br>
> > +    }<br>
> > +<br>
> > +    if (!rta)<br>
> > +        goto buffer_too_small;<br>
> > +<br>
> > +    if (!(vfport = nlAppend(nlm, sizeof(nlmsgbuf),
rtattbuf, <br>
> rta->rta_len)))<br>
> > +        goto buffer_too_small;<br>
> > +<br>
> > +    if (profileId) {<br>
> > +        rta = rtattrCreate(rtattbuf, sizeof(rtattbuf),
IFLA_PORT_PROFILE,<br>
> > +                  
        profileId, strlen(profileId) + 1);<br>
> > +        if (!rta)<br>
> > +            goto buffer_too_small;<br>
> > +<br>
> > +        if (!nlAppend(nlm, sizeof(nlmsgbuf),
rtattbuf, rta->rta_len))<br>
> > +            goto buffer_too_small;<br>
> > +    }<br>
> > +<br>
> > +    if (portVsi) {<br>
> > +        rta = rtattrCreate(rtattbuf, sizeof(rtattbuf),
IFLA_PORT_VSI_TYPE,<br>
> > +                  
        portVsi, sizeof(*portVsi));<br>
> > +        if (!rta)<br>
> > +            goto buffer_too_small;<br>
> > +<br>
> > +        if (!nlAppend(nlm, sizeof(nlmsgbuf),
rtattbuf, rta->rta_len))<br>
> > +            goto buffer_too_small;<br>
> > +    }<br>
> > +<br>
> > +    if (instanceId) {<br>
> > +        rta = rtattrCreate(rtattbuf, sizeof(rtattbuf),
<br>
> IFLA_PORT_INSTANCE_UUID,<br>
> > +                  
        instanceId, VIR_UUID_BUFLEN);<br>
> > +        if (!rta)<br>
> > +            goto buffer_too_small;<br>
> > +<br>
> > +        if (!nlAppend(nlm, sizeof(nlmsgbuf),
rtattbuf, rta->rta_len))<br>
> > +            goto buffer_too_small;<br>
> > +    }<br>
> > +<br>
> > +    if (hostUUID) {<br>
> > +        rta = rtattrCreate(rtattbuf, sizeof(rtattbuf),
IFLA_PORT_HOST_UUID,<br>
> > +                  
        hostUUID, VIR_UUID_BUFLEN);<br>
> > +        if (!rta)<br>
> > +            goto buffer_too_small;<br>
> > +<br>
> > +        if (!nlAppend(nlm, sizeof(nlmsgbuf),
rtattbuf, rta->rta_len))<br>
> > +            goto buffer_too_small;<br>
> > +    }<br>
> > +<br>
> > +    if (vf != PORT_SELF_VF) {<br>
> > +        rta = rtattrCreate(rtattbuf, sizeof(rtattbuf),
IFLA_PORT_VF,<br>
> > +                  
        &vf, sizeof(vf));<br>
> > +        if (!rta)<br>
> > +            goto buffer_too_small;<br>
> > +<br>
> > +        if (!nlAppend(nlm, sizeof(nlmsgbuf),
rtattbuf, rta->rta_len))<br>
> > +            goto buffer_too_small;<br>
> > +    }<br>
> > +<br>
> > +    rta = rtattrCreate(rtattbuf, sizeof(rtattbuf),
IFLA_PORT_REQUEST,<br>
> > +                  
    &op, sizeof(op));<br>
> > +    if (!rta)<br>
> > +        goto buffer_too_small;<br>
> > +<br>
> > +    if (!nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf,
rta->rta_len))<br>
> > +        goto buffer_too_small;<br>
> <br>
> There is too much duplication in the above 6 clauses.<br>
> Can you factor out a tiny helper function to make this more<br>
> readable/maintainable?<br>
> <br>
> At the very least, combine the two<br>
> "if...goto buffer_too_small" stmts into one:<br>
> <br>
>            if (!rta || !nlAppend(nlm,
sizeof(nlmsgbuf), rtattbuf, <br>
> rta->rta_len))</font></tt>
<br>
<br><tt><font size=2>Alright. Will do. Though this may also tough existing
code.</font></tt>
<br>
<br><tt><font size=2><br>
>                goto buffer_too_small;<br>
> > +<br>
> > +    /* end nesting of vport */<br>
> > +    vfport->rta_len  = (char *)nlm + nlm->nlmsg_len
- (char *)vfport;<br>
> > +<br>
> > +    if (vf != PORT_SELF_VF) {<br>
> > +        /* end nesting of vfports */<br>
> > +        vfports->rta_len = (char *)nlm
+ nlm->nlmsg_len - (char *)vfports;<br>
> > +    }<br>
> > +<br>
> > +    if (!multicast) {<br>
> > +        if (nlComm(nlm, &recvbuf, &recvbuflen)
< 0)<br>
> > +            return -1;<br>
> > +    } else {<br>
> > +        if (nlCommWaitSuccess(nlm, RTMGRP_LINK,
&recvbuf, &recvbuflen,<br>
> > +                  
           5 * MICROSEC_PER_SEC) < 0)<br>
> > +            return -1;<br>
> > +    }<br>
> > +<br>
> > +    if (recvbuflen < NLMSG_LENGTH(0) || recvbuf
== NULL)<br>
> > +        goto malformed_resp;<br>
> > +<br>
> > +    resp = (struct nlmsghdr *)recvbuf;<br>
> > +<br>
> > +    switch (resp->nlmsg_type) {<br>
> > +    case NLMSG_ERROR:<br>
> > +        err = (struct nlmsgerr *)NLMSG_DATA(resp);<br>
> > +        if (resp->nlmsg_len < NLMSG_LENGTH(sizeof(*err)))<br>
> > +            goto malformed_resp;<br>
> ><br>
> > +        switch (-err->error) {<br>
> > +        case 0:<br>
> > +        break;<br>
> <br>
> Indent the break:<br>
>            case 0:<br>
>                break;<br>
> <br>
> Actually, since there's only one action here,<br>
> just drop the switch in favor of a simple "if" stmt.<br>
> (same with the other switch (-err->error) above)<br>
> That makes the resulting code shorter by 4 lines per switch stmt.</font></tt>
<br>
<br><tt><font size=2>Ok. Had done that to be consistent with other code.</font></tt>
<br><tt><font size=2><br>
> <br>
>            if (err->error) {<br>
>                virReportSystemError(-err->error,<br>
>                    _("error
during virtual port configuration of ifindex %d"),<br>
>                    ifindex);<br>
>                rc = -1;<br>
>            }<br>
> <br>
> > +        default:<br>
> > +            virReportSystemError(-err->error,<br>
> > +                _("error
during virtual port configuration of ifindex %d"),<br>
> > +                ifindex);<br>
> > +            rc = -1;<br>
> > +        }<br>
> > +    break;<br>
> <br>
> Indent.</font></tt>
<br>
<br><tt><font size=2>Ok.</font></tt>
<br><tt><font size=2><br>
> <br>
> > +<br>
> > +    case NLMSG_DONE:<br>
> > +    break;<br>
> <br>
> Indent.</font></tt>
<br>
<br><tt><font size=2>Ok.<br>
> <br>
> > +<br>
> > +    default:<br>
> > +        goto malformed_resp;<br>
> > +    }<br>
> > +<br>
> > +    VIR_FREE(recvbuf);<br>
> > +<br>
> > +    return rc;<br>
> > +<br>
> > +malformed_resp:<br>
> > +    macvtapError(VIR_ERR_INTERNAL_ERROR, "%s",<br>
> > +                 _("malformed
netlink response message"));<br>
> > +    VIR_FREE(recvbuf);<br>
> > +    return -1;<br>
> > +<br>
> > +buffer_too_small:<br>
> > +    macvtapError(VIR_ERR_INTERNAL_ERROR, "%s",<br>
> > +                 _("internal
buffer is too small"));<br>
> > +    return -1;<br>
> > +}<br>
> > +<br>
> > +<br>
> > +static int<br>
> > +doPortProfileOpCommon(bool multicast,<br>
> > +                  
   int ifindex,<br>
> > +                  
   const char *profileId,<br>
> > +                  
   struct ifla_port_vsi *portVsi,<br>
> > +                  
   const unsigned char *instanceId,<br>
> > +                  
   const unsigned char *hostUUID,<br>
> > +                  
   int32_t vf,<br>
> > +                  
   uint8_t op)<br>
> > +{<br>
> > +    int rc;<br>
> > +    char *recvbuf = NULL;<br>
> > +    struct nlattr *tb[IFLA_MAX + 1];<br>
> > +    int repeats = 80;<br>
> <br>
> This can (hence should) be unsigned.<br>
> This number is obviously related to the 125000-microsecond<br>
> sleep below.  Consider adding a comment saying up to how long<br>
> we should wait for a result.</font></tt>
<br>
<br><tt><font size=2>I'll add some math to this.</font></tt>
<br><tt><font size=2><br>
> <br>
> > +    uint16_t status = 0;<br>
> > +<br>
> > +    rc = doPortProfileOpSetLink(multicast,<br>
> > +                  
             ifindex,<br>
> > +                  
             profileId,<br>
> > +                  
             portVsi,<br>
> > +                  
             instanceId,<br>
> > +                  
             hostUUID,<br>
> > +                  
             vf,<br>
> > +                  
             op);<br>
> > +<br>
> > +    if (rc != 0) {<br>
> > +        macvtapError(VIR_ERR_INTERNAL_ERROR,
"%s",<br>
> > +                  
  _("sending of PortProfileRequest failed."));<br>
> > +        return rc;<br>
> > +    }<br>
> > +<br>
> > +    if (!multicast) {<br>
> > +        while (--repeats) {<br>
> > +            rc = link_dump(ifindex,
tb, &recvbuf);<br>
> > +            if (rc)<br>
> > +                goto
err_exit;<br>
> > +            rc = getPortProfileStatus(tb,
vf, &status);<br>
> > +            if (rc == 0) {<br>
> <br>
> What if getPortProfileStatus returns something other than 0?<br>
> Currently, when that happens, this code just ignores it (failure?)<br>
> sleeps and retries.<br>
> Doesn't failure to get status deserve an error just<br>
> as much as when we do get status that indicates a failure?</font></tt>
<br>
<br><tt><font size=2>Yes, it should. Should only happen, though, if we
are all of a sudden on a wrong kernel...</font></tt>
<br><tt><font size=2><br>
> <br>
> > +                if (status
== PORT_PROFILE_RESPONSE_SUCCESS ||<br>
> > +                  
 status == PORT_VDP_RESPONSE_SUCCESS) {<br>
> > +                  
 break;<br>
> > +                } else
if (status == PORT_PROFILE_RESPONSE_INPROGRESS) {<br>
> > +                  
 // keep trying...<br>
> > +                } else
{<br>
> > +                  
 virReportSystemError(EINVAL,<br>
> > +                  
     _("error %d during port-profile setlink <br>
> on ifindex %d"),<br>
> > +                  
     status, ifindex);<br>
> > +                  
 rc = 1;<br>
> > +                  
 break;<br>
> > +                }<br>
> > +            }<br>
> > +            usleep(125000);<br>
> <br>
> Magic constant?<br>
> How did you determine this number?<br>
> How often are we expected to hit it?<br>
> Please add a comment.</font></tt>
<br>
<br><tt><font size=2>This *may* be something I suggested -- to wait for
1/8 sec. Not sure whether this is</font></tt>
<br><tt><font size=2>too much, or not fast enough, but more like a shot
into the 'blue'.</font></tt>
<br><tt><font size=2><br>
> <br>
> > +            VIR_FREE(recvbuf);<br>
> > +        }<br>
> > +    }<br>
> > +</font></tt>
<br><tt><font size=2>> > +    if (status == PORT_PROFILE_RESPONSE_INPROGRESS)
{<br>
> > +        macvtapError(VIR_ERR_INTERNAL_ERROR,
"%s",<br>
> > +                  
  _("port-profile setlink timed out"));<br>
> > +        rc = -ETIMEDOUT;<br>
> > +    }<br>
> > +<br>
> > +err_exit:<br>
> > +    VIR_FREE(recvbuf);<br>
> > +<br>
> > +    return rc;<br>
> > +}<br>
> > +<br>
> > +# endif /* IFLA_PORT_MAX */<br>
> <br>
> --<br>
> libvir-list mailing list<br>
> libvir-list@redhat.com<br>
> </font></tt><a href="https://www.redhat.com/mailman/listinfo/libvir-list"><tt><font size=2>https://www.redhat.com/mailman/listinfo/libvir-list</font></tt></a><tt><font size=2><br>
</font></tt>
<br><tt><font size=2>I'll post v7 addressing the comments.</font></tt>
<br>
<br><tt><font size=2>   Stefan</font></tt>
<br>