Commit 09ad13ee authored by Mike Hibler's avatar Mike Hibler

Have device threads stop snooping packets if there are no clients.

parent 472d7fee
/* /*
* EMULAB-COPYRIGHT * EMULAB-COPYRIGHT
* Copyright (c) 2000-2002 University of Utah and the Flux Group. * Copyright (c) 2000-2003 University of Utah and the Flux Group.
* All rights reserved. * All rights reserved.
*/ */
...@@ -224,11 +224,16 @@ extern int opterr; ...@@ -224,11 +224,16 @@ extern int opterr;
extern int optreset; extern int optreset;
/* /*
* Lock used to make sure that the threads don't clobber the pakcet counts. * Lock used to make sure that the threads don't clobber the packet counts.
* We just use one big fat lock for all of them. * We just use one big fat lock for all of them.
*/ */
pthread_mutex_t lock; pthread_mutex_t lock;
/*
* Condition variable for device threads to wait on for activity.
*/
pthread_cond_t cond;
/* /*
* Pakcet counts for the three types of packets that we care about. * Pakcet counts for the three types of packets that we care about.
*/ */
...@@ -245,6 +250,11 @@ pcap_t *pcap_devs[MAX_INTERFACES]; ...@@ -245,6 +250,11 @@ pcap_t *pcap_devs[MAX_INTERFACES];
*/ */
int client_connected[MAX_CLIENTS]; int client_connected[MAX_CLIENTS];
/*
* Number of active clients. When count is zero, the device is closed.
*/
volatile int active;
int MAX(int a, int b) { if ((a) > (b)) return (a); else return (b); } int MAX(int a, int b) { if ((a) > (b)) return (a); else return (b); }
void usage(char *progname) { void usage(char *progname) {
...@@ -388,6 +398,7 @@ int main (int argc, char **argv) { ...@@ -388,6 +398,7 @@ int main (int argc, char **argv) {
bzero(client_connected,sizeof(client_connected)); bzero(client_connected,sizeof(client_connected));
pthread_mutex_init(&lock,NULL); pthread_mutex_init(&lock,NULL);
pthread_cond_init(&cond,NULL);
#ifdef EMULAB #ifdef EMULAB
/* /*
...@@ -667,6 +678,7 @@ int main (int argc, char **argv) { ...@@ -667,6 +678,7 @@ int main (int argc, char **argv) {
args->cli = 0; args->cli = 0;
args->interval = filetime; args->interval = filetime;
client_connected[0] = 1; client_connected[0] = 1;
active = 1;
pthread_create(&thread,NULL,feedclient,args); pthread_create(&thread,NULL,feedclient,args);
} }
...@@ -729,6 +741,13 @@ int main (int argc, char **argv) { ...@@ -729,6 +741,13 @@ int main (int argc, char **argv) {
if (!client_connected[i]) { if (!client_connected[i]) {
/* printf("New client is %i\n",i); */ /* printf("New client is %i\n",i); */
client_connected[i] = 1; client_connected[i] = 1;
if (active >= MAX_CLIENTS) {
fprintf(stderr, "active count screwed\n");
exit(1);
}
if (++active == 1)
pthread_cond_broadcast(&cond);
printf("Now have %d clients\n", active);
break; break;
} }
} }
...@@ -766,6 +785,7 @@ void *feedclient(void *args) { ...@@ -766,6 +785,7 @@ void *feedclient(void *args) {
int i; int i;
struct timeval next_time, now, interval_tv; struct timeval next_time, now, interval_tv;
int dropped; int dropped;
int called = 0;
s_args = (struct feedclient_args*)args; s_args = (struct feedclient_args*)args;
cli = s_args->cli; cli = s_args->cli;
...@@ -901,11 +921,17 @@ void *feedclient(void *args) { ...@@ -901,11 +921,17 @@ void *feedclient(void *args) {
/* /*
* Drop information is not kept per-interface, so we just * Drop information is not kept per-interface, so we just
* grab it from one of them. * grab it from one of them. Note that since we close all
* devices when no one is active, it is possible that the
* device threads have not yet reopened their devices when
* we reach here.
*/ */
if (pcap_stats(pcap_devs[0],&ps)) { if (pcap_devs[0] == 0 || pcap_stats(pcap_devs[0], &ps)) {
printf("Unable to get stats\n"); if (!called) {
exit(1); fprintf(stderr,
"WARNING: unable to get drop stats\n");
called = 1;
}
} }
/* /*
...@@ -927,7 +953,15 @@ void *feedclient(void *args) { ...@@ -927,7 +953,15 @@ void *feedclient(void *args) {
perror("write"); perror("write");
} }
/* printf("Client %i disconnected\n",cli);*/ /* printf("Client %i disconnected\n",cli);*/
pthread_mutex_lock(&lock);
if (client_connected[cli] == 0 || active <= 0) {
fprintf(stderr, "active count screwed\n");
exit(1);
}
client_connected[cli] = 0; client_connected[cli] = 0;
active--;
printf("Now have %d clients\n", active);
pthread_mutex_unlock(&lock);
/* /*
* Client disconnected - exit the loop * Client disconnected - exit the loop
*/ */
...@@ -958,15 +992,21 @@ void *readpackets(void *args) { ...@@ -958,15 +992,21 @@ void *readpackets(void *args) {
sizeof(struct tcphdr); sizeof(struct tcphdr);
sargs = (struct readpackets_args*)args; sargs = (struct readpackets_args*)args;
again:
pthread_mutex_lock(&lock);
while (active == 0)
pthread_cond_wait(&cond, &lock);
pthread_mutex_unlock(&lock);
/* /*
* NOTE: We set the timeout to a full second - if we set it lower, we * NOTE: We set the timeout to a full second - if we set it lower, we
* don't get to see packets until a certain number have been buffered * don't get to see packets until a certain number have been buffered
* up, for some reason. * up, for some reason.
*/ */
dev = pcap_open_live(sargs->devname,size,1,1,ebuf); dev = pcap_open_live(sargs->devname, size, 1, 1, ebuf);
if (!dev) { if (!dev) {
fprintf(stderr,"Failed to open %s: %s\n",sargs->devname,ebuf); fprintf(stderr, "Failed to open %s: %s\n",
sargs->devname, ebuf);
exit(1); exit(1);
} }
...@@ -984,14 +1024,23 @@ void *readpackets(void *args) { ...@@ -984,14 +1024,23 @@ void *readpackets(void *args) {
pcap_lookupnet(sargs->devname, &net, &mask, ebuf); pcap_lookupnet(sargs->devname, &net, &mask, ebuf);
pcap_compile(dev, &filter, "", 0, net); pcap_compile(dev, &filter, "", 0, net);
pcap_setfilter(dev, &filter); pcap_setfilter(dev, &filter);
pcap_freecode(&filter);
#endif #endif
if (pcap_loop((pcap_t *)dev,-1,got_packet,&(sargs->index))) { /*
printf("Failed to start pcap_loop for %s\n",sargs->devname); * We don't bother to lock the access to active. If it gets cleared
exit(1); * immediately after a test, we make an extra loop. If it gets set
* immediately after, we do an extra open/close of the device.
* Neither case is life threatening.
*/
while (active > 0) {
if (pcap_dispatch(dev, -1, got_packet, &sargs->index) < 0) {
printf("pcap_dispatch failed for %s\n", sargs->devname);
exit(1);
}
} }
pcap_close(dev);
return NULL; goto again;
} }
/* /*
...@@ -1135,7 +1184,6 @@ void got_packet(u_char *args, const struct pcap_pkthdr *header, ...@@ -1135,7 +1184,6 @@ void got_packet(u_char *args, const struct pcap_pkthdr *header,
} }
} }
pthread_mutex_unlock(&lock); pthread_mutex_unlock(&lock);
} }
/* /*
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment