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