Scott Feldman <scofeldm@cisco.com> wrote on 05/20/2010 03:22:12 PM:

>
> Next steps for V3, etc:
>
> 1) merge with Stefan's latest patch, as much as possible


Yes. Try to make it a patch on top of my V5 patch...

> 2) assign VM device mac addr to eth and set macvtap mac addr to random


Hm, why is this necessary? I have tested the macvtap device and always set it to the address that libvirt assigned to it and that happened to be the same as the one inside the VM? Is this something specific to your underlying driver?

> 3) figure out where host_uuid lives


I posted a message a while ago. It's not anywhere right now and should probably be provided via libvirt.conf overriding dmidecode, but dmidecode being used if its output is valid and resorting to a temporary (between libvirt restart) host uuid if everything fails...


> diff --git a/src/util/macvtap.c b/src/util/macvtap.c
> index 1f8dd29..7803bc8 100644
> --- a/src/util/macvtap.c
> +++ b/src/util/macvtap.c
> @@ -85,14 +85,14 @@ static void nlClose(int fd)
>   * buffer will be returned.
>   */
>  static
> -int nlComm(struct nlmsghdr *nlmsg,
> +int nlComm(struct nlmsghdr *nlmsg, int nlgroups,
>             char **respbuf, int *respbuflen)
>  {
>      int rc = 0;
>      struct sockaddr_nl nladdr = {
>              .nl_family = AF_NETLINK,
>              .nl_pid    = 0,
> -            .nl_groups = 0,
> +            .nl_groups = nlgroups,


I think if only you use this function, nlgroups can be 0 here. I would use different code to use multicast for talking to lldpad.

>      };
>      int rcvChunkSize = 1024; // expecting less than that
>      int rcvoffset = 0;
> @@ -192,6 +192,27 @@ nlAppend(struct nlmsghdr *nlm, int totlen,
> const void *data, int datalen)
>      return pos;
>  }
>  
> +#define NLMSG_TAIL(nmsg) \
> +  ((struct rtattr *) (((char *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len)))
> +
> +static struct rtattr *nlNest(struct nlmsghdr *nlm, int totlen, int type)
> +{
> +    struct rtattr *nest = NLMSG_TAIL(nlm);
> +
> +    if (nlm->nlmsg_len + NLMSG_ALIGN(sizeof(*nest)) > totlen)
> +   return NULL;
> +    nest->rta_type = type;
> +    nest->rta_len = RTA_LENGTH(0);
> +    nlm->nlmsg_len += sizeof(*nest);
> +    nlAlign(nlm);
> +    return nest;
> +}
> +
> +static int nlNestEnd(struct nlmsghdr *nlm, struct rtattr *nest)
> +{
> +    nest->rta_len = (char *)NLMSG_TAIL(nlm) - (char *)nest;
> +    return nlm->nlmsg_len;
> +}
>  


At some point in the future someone may want to change all this netlink stuff to use libnl -- except for maybe in the case of the multicast message that I am sending in one of my patches and using select with a timeout to wait for a response from (future) lldpad where I am not sure whether an equivalent function exists in libnl...

> +#if 0
> +static int
> +get_host_uuid(char *host_uuid, int len)


this is not active code ... skipping it

> +
> +static int
> +portProfileIdMcast(const char *linkdev,
> +                   const char request,
> +                   const char *profileid,
> +                   const unsigned short *instance_uuid,
> +                   const unsigned short *host_uuid)
> +{
> +    struct rtattr *port_self;
> +    char nlmsgbuf[512];
> +    struct nlmsghdr *nlm = (struct nlmsghdr *)nlmsgbuf, *resp;
> +    struct ifinfomsg infomsg = { .ifi_family = AF_UNSPEC };
> +    char rtattbuf[256];
> +    struct rtattr *rta;
> +    char *recvbuf = NULL;
> +    int recvbuflen;
> +    struct nlmsgerr *err;
> +    int rc = 0;
> +
> +    memset(&nlmsgbuf, 0, sizeof(nlmsgbuf));
> +    nlInit(nlm, NLM_F_REQUEST, RTM_SETLINK);
> +
> +    if (!nlAppend(nlm, sizeof(nlmsgbuf), &infomsg, sizeof(infomsg)))
> +        goto buffer_too_small;
> +
> +    rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_IFNAME,
> +                       linkdev, strlen(linkdev) + 1);
> +    if (!rta)
> +        goto buffer_too_small;
> +
> +    if (!nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len))
> +        goto buffer_too_small;
> +
> +    port_self = nlNest(nlm, sizeof(nlmsgbuf), IFLA_PORT_SELF);
> +    if (!port_self)
> +        return -1;
> +
> +    switch (request) {
> +    case PORT_REQUEST_ASSOCIATE:
> +        if (profileid && strlen(profileid)) {
> +            rta = rtattrCreate(rtattbuf, sizeof(rtattbuf),
> +                               IFLA_PORT_PROFILE,
> +                               profileid, strlen(profileid) + 1);
> +            if (!rta)
> +                goto buffer_too_small;
> +
> +            if (!nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len))
> +                goto buffer_too_small;
> +        }
> +        if (instance_uuid) {
> +            rta = rtattrCreate(rtattbuf, sizeof(rtattbuf),
> +                               IFLA_PORT_INSTANCE_UUID,
> +                               instance_uuid, PORT_UUID_MAX);
> +            if (!rta)
> +                goto buffer_too_small;
> +
> +            if (!nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len))
> +                goto buffer_too_small;
> +        }
> +        if (host_uuid) {
> +            rta = rtattrCreate(rtattbuf, sizeof(rtattbuf),
> +                               IFLA_PORT_HOST_UUID,
> +                               host_uuid, PORT_UUID_MAX);
> +            if (!rta)
> +                goto buffer_too_small;
> +
> +            if (!nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len))
> +                goto buffer_too_small;
> +        }
> +        break;
> +    case PORT_REQUEST_DISASSOCIATE:
> +        break;
> +    }
> +
> +    rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_PORT_REQUEST,
> +                       &request, 1);
> +    if (!rta)
> +        goto buffer_too_small;
> +
> +    if (!nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len))
> +        goto buffer_too_small;
> +
> +    nlNestEnd(nlm, port_self);
> +
> +    if (nlComm(nlm, RTNLGRP_LINK, &recvbuf, &recvbuflen) < 0)
> +        return -1;
> +

I know that it doesn't work like this in the netlink multicast case where libvirt will receive an error from the kernel and hopefully some time later a response from lldpad. Still it would be nice if we could use common code here for both technologies, but the unicast vs. multicast receiver code makes it quite different. Have a look at my patches.

    Stefan