Commit bc8bf2cd authored by Mike Hibler's avatar Mike Hibler

Allow client to specify a multicast "keep alive" with -K.

Experiment: lets see if this helps revive stuck multicast sessions.
With "-K <seconds>", the client will send a IGMP-leave/IGMP-join after
<seconds> of no received packets.
parent 27278d74
...@@ -57,6 +57,7 @@ int tracing = 0; ...@@ -57,6 +57,7 @@ int tracing = 0;
char traceprefix[64]; char traceprefix[64];
int randomize = 1; int randomize = 1;
int zero = 0; int zero = 0;
int keepalive;
int portnum; int portnum;
struct in_addr mcastaddr; struct in_addr mcastaddr;
struct in_addr mcastif; struct in_addr mcastif;
...@@ -137,7 +138,7 @@ ClientStats_t Stats; ...@@ -137,7 +138,7 @@ ClientStats_t Stats;
#endif #endif
char *usagestr = char *usagestr =
"usage: frisbee [-drzbn] [-s #] <-p #> <-m ipaddr> <output filename>\n" "usage: frisbee [-drzbnN] [-s #] <-m ipaddr> <-p #> <output filename>\n"
" -d Turn on debugging. Multiple -d options increase output.\n" " -d Turn on debugging. Multiple -d options increase output.\n"
" -r Randomly delay first request by up to one second.\n" " -r Randomly delay first request by up to one second.\n"
" -z Zero fill unused block ranges (default is to seek past).\n" " -z Zero fill unused block ranges (default is to seek past).\n"
...@@ -149,6 +150,7 @@ char *usagestr = ...@@ -149,6 +150,7 @@ char *usagestr =
" -i mcastif Specify a multicast interface in dotted notation.\n" " -i mcastif Specify a multicast interface in dotted notation.\n"
" -s slice Output to DOS slice (DOS numbering 1-4)\n" " -s slice Output to DOS slice (DOS numbering 1-4)\n"
" NOTE: Must specify a raw disk device for output filename.\n" " NOTE: Must specify a raw disk device for output filename.\n"
" -K seconds Send a multicast keep alive after a period of inactivity.\n"
"\n" "\n"
"tuning options (if you don't know what they are, don't use em!):\n" "tuning options (if you don't know what they are, don't use em!):\n"
" -C MB Max MB of memory to use for network chunk buffering.\n" " -C MB Max MB of memory to use for network chunk buffering.\n"
...@@ -191,7 +193,7 @@ main(int argc, char **argv) ...@@ -191,7 +193,7 @@ main(int argc, char **argv)
int dostype = -1; int dostype = -1;
int slice = 0; int slice = 0;
while ((ch = getopt(argc, argv, "dhp:m:s:i:tbznT:r:E:D:C:W:S:M:R:I:ON")) != -1) while ((ch = getopt(argc, argv, "dhp:m:s:i:tbznT:r:E:D:C:W:S:M:R:I:ONK:")) != -1)
switch(ch) { switch(ch) {
case 'd': case 'd':
debug++; debug++;
...@@ -306,6 +308,12 @@ main(int argc, char **argv) ...@@ -306,6 +308,12 @@ main(int argc, char **argv)
nodecompress = 1; nodecompress = 1;
break; break;
case 'K':
keepalive = atoi(optarg);
if (keepalive < 0)
keepalive = 0;
break;
case 'h': case 'h':
case '?': case '?':
default: default:
...@@ -459,6 +467,14 @@ main(int argc, char **argv) ...@@ -459,6 +467,14 @@ main(int argc, char **argv)
DiskStatusCallback = WriterStatusCallback; DiskStatusCallback = WriterStatusCallback;
} }
/*
* Set the MC keepalive counter (but only if we are multicasting!)
*/
if (broadcast || (ntohl(mcastaddr.s_addr) >> 28) != 14)
keepalive = 0;
if (keepalive)
log("Enabling MC keepalive at %d seconds", keepalive);
PlayFrisbee(); PlayFrisbee();
if (tracing) { if (tracing) {
...@@ -499,12 +515,14 @@ void * ...@@ -499,12 +515,14 @@ void *
ClientRecvThread(void *arg) ClientRecvThread(void *arg)
{ {
Packet_t packet, *p = &packet; Packet_t packet, *p = &packet;
int IdleCounter, BackOff; int IdleCounter, BackOff, KACounter;
static int gotone; static int gotone;
if (debug) if (debug)
log("Receive pthread starting up ..."); log("Receive pthread starting up ...");
KACounter = keepalive * TIMEOUT_HZ;
/* /*
* Use this to control the rate at which we request blocks. * Use this to control the rate at which we request blocks.
* The IdleCounter is how many ticks we let pass without a * The IdleCounter is how many ticks we let pass without a
...@@ -549,6 +567,23 @@ ClientRecvThread(void *arg) ...@@ -549,6 +567,23 @@ ClientRecvThread(void *arg)
*/ */
if (PacketReceive(p) != 0) { if (PacketReceive(p) != 0) {
pthread_testcancel(); pthread_testcancel();
/*
* See if we should send a keep alive
*/
if (KACounter == 1) {
/* If for some reason it fails, stop trying */
if (debug)
log("sending keepalive...");
if (NetMCKeepAlive()) {
log("Multicast keepalive failed, "
"disabling keepalive");
keepalive = 0;
}
KACounter = keepalive * TIMEOUT_HZ;
} else if (KACounter > 1)
KACounter--;
if (--IdleCounter <= 0) { if (--IdleCounter <= 0) {
if (gotone) if (gotone)
DOSTAT(recvidles++); DOSTAT(recvidles++);
...@@ -569,6 +604,8 @@ ClientRecvThread(void *arg) ...@@ -569,6 +604,8 @@ ClientRecvThread(void *arg)
continue; continue;
} }
pthread_testcancel(); pthread_testcancel();
if (keepalive)
KACounter = keepalive * TIMEOUT_HZ;
gotone = 1; gotone = 1;
if (! PacketValid(p, TotalChunkCount)) { if (! PacketValid(p, TotalChunkCount)) {
......
...@@ -320,7 +320,7 @@ typedef struct { ...@@ -320,7 +320,7 @@ typedef struct {
int GetSockbufSize(void); int GetSockbufSize(void);
int ClientNetInit(void); int ClientNetInit(void);
int ServerNetInit(void); int ServerNetInit(void);
int ServerNetMCKeepAlive(void); int NetMCKeepAlive(void);
unsigned long ClientNetID(void); unsigned long ClientNetID(void);
int PacketReceive(Packet_t *p); int PacketReceive(Packet_t *p);
void PacketSend(Packet_t *p, int *resends); void PacketSend(Packet_t *p, int *resends);
......
...@@ -249,7 +249,7 @@ ServerNetInit(void) ...@@ -249,7 +249,7 @@ ServerNetInit(void)
* We need a better way to do this! * We need a better way to do this!
*/ */
int int
ServerNetMCKeepAlive(void) NetMCKeepAlive(void)
{ {
struct ip_mreq mreq; struct ip_mreq mreq;
......
...@@ -604,7 +604,7 @@ ServerRecvThread(void *arg) ...@@ -604,7 +604,7 @@ ServerRecvThread(void *arg)
pthread_testcancel(); pthread_testcancel();
if (PacketReceive(p) != 0) { if (PacketReceive(p) != 0) {
if (keepalive && ++idles > keepalive) { if (keepalive && ++idles > keepalive) {
if (ServerNetMCKeepAlive()) { if (NetMCKeepAlive()) {
warning("Multicast keepalive failed"); warning("Multicast keepalive failed");
if (++kafails > 5) { if (++kafails > 5) {
warning("too many failures, disabled"); warning("too many failures, disabled");
......
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