
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