[libvirt] [V2 PATCH] V2 port-profile ID support using new IFLA_VF_PORTS netlink msg

Stefan Berger stefanb at us.ibm.com
Thu May 20 20:52:44 UTC 2010


Scott Feldman <scofeldm at 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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://listman.redhat.com/archives/libvir-list/attachments/20100520/42577294/attachment-0001.htm>


More information about the libvir-list mailing list