David Stevens/Beaverton/IBM@IBMUS wrote on 05/09/2011 04:11:19 PM:


> + */
> +
> +#include <config.h>
> +
> +#ifdef HAVE_LIBPCAP
> +#include <pcap.h>
> +#endif


This is the only place you check for HAVE_LIBPCAP. Basically when it's not available the snooping doesn't work and VMs referencing filters that have
the variable 'IP' no user-given value cannot start. The part checking again for HAVE_LIBPCAP further down seems to be missing.


> +virNWFilterDHCPSnoopReq(virConnectPtr conn,
> +                        virNWFilterTechDriverPtr techdriver ATTRIBUTE_UNUSED,
> +                        enum virDomainNetType nettype ATTRIBUTE_UNUSED,
> +                        virNWFilterDefPtr filter ATTRIBUTE_UNUSED,
> +                        const char *ifname ATTRIBUTE_UNUSED,
> +                        virNWFilterHashTablePtr vars ATTRIBUTE_UNUSED,
> +                        virNWFilterDriverStatePtr driver ATTRIBUTE_UNUSED)
> +{
> +    struct virNWFilterSnoopReq *req;
> +
> +    req = virHashLookup(SnoopReqs, ifname);


Presumably multiple threads can be here, so you'll have to protect the hash table 'SnoopReqs' from concurrent accesses -- everywhere.

> +    if (req)
> +        return 0;
> +    if (VIR_ALLOC(req) < 0) {
> +        virReportOOMError();
> +        return 1;
> +    }
> +
> +    req->conn = conn;
> +    req->techdriver = techdriver;
> +    req->nettype = nettype;
> +    req->filter = filter;
> +    req->ifname = strdup(ifname);
> +    req->vars = virNWFilterHashTableCreate(0);
> +    if (!req->vars) {
> +        virReportOOMError();
> +        return 1;
> +    }
> +    if (virNWFilterHashTablePutAll(vars, req->vars)) {
> +        virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
> +                               _("virNWFilterDHCPSnoopReq: can't
> copy variables"
> +                                " on if %s"), ifname);
> +        return 1;
> +    }
> +    req->driver = driver;
> +    req->start = req->end = 0;
> +
> +    if (virHashAddEntry(SnoopReqs, ifname, req)) {


Also protect it here.

> +        VIR_FREE(req);
> +        virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
> +                               _("virNWFilterDHCPSnoopReq req add failed on"
> +                                "interface \"%s\""), ifname);
> +        return 1;
> +    }
> +    if (pthread_create(&req->thread, NULL, virNWFilterDHCPSnoop, req) != 0) {
> +        (void) virHashRemoveEntry(SnoopReqs, ifname);


... and here ...

> +        VIR_FREE(req);
> +        virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
> +                               _("virNWFilterDHCPSnoopReq
> pthread_create failed"
> +                                " oninterface \"%s\""), ifname);
> +        return 1;
> +    }
> +    return 0;
> +}
> +
> +/*
> + * freeReq - hash table free function to kill a request
> + */
> +static void
> +freeReq(void *req0, const void *name ATTRIBUTE_UNUSED)
> +{
> +    struct virNWFilterSnoopReq *req = (struct virNWFilterSnoopReq *) req0;
> +
> +    if (!req)
> +        return;
> +
> +    req->die = 1;
> +}
> +
> +int
> +virNWFilterDHCPSnoopInit(void)
> +{
> +    if (SnoopReqs)

> +        return 0;
> +    SnoopReqs = virHashCreate(0, freeReq);
> +    if (!SnoopReqs) {
> +        virReportOOMError();
> +        return -1;
> +    }
> +    return 0;
> +}
> +
> +void
> +virNWFilterDHCPSnoopEnd(const char *ifname)
> +{
> +    if (!SnoopReqs)
> +        return;
> +    if (ifname)
> +        virHashRemoveEntry(SnoopReqs, ifname);


.. and again protect here. Since SnoopReqs is a global variable, maybe wrap the hash table operations into functions of their own.

Great work! It's overall pretty complex. I'll try it at some point.

Regards,
   Stefan