Added support for using a dummy interface to allow testing of multiple mesh

nodes on the same machine.  Also handly for linking to unusual interfaces
such as the UHF radio dongles we are planning.
This commit is contained in:
gardners 2011-08-13 13:17:49 +02:00
parent c8229c8517
commit ec1fe22e93
2 changed files with 106 additions and 27 deletions

View File

@ -386,6 +386,7 @@ extern int overlayMode;
typedef struct overlay_interface { typedef struct overlay_interface {
char name[80]; char name[80];
int socket; int socket;
int fd;
int bits_per_second; int bits_per_second;
int port; int port;
int type; int type;

View File

@ -178,18 +178,31 @@ int overlay_interface_init(char *name,struct sockaddr_in src_addr,struct sockadd
This will ultimately get tuned by the bandwidth and other properties of the interface */ This will ultimately get tuned by the bandwidth and other properties of the interface */
I(mtu)=1200; I(mtu)=1200;
I(observed)=1;
I(bits_per_second)=speed_in_bits; I(bits_per_second)=speed_in_bits;
I(port)=port; I(port)=port;
I(type)=type; I(type)=type;
I(tick_ms)=500; I(tick_ms)=500;
I(last_tick_ms)=0;
I(fd)=0;
switch(type) { switch(type) {
case OVERLAY_INTERFACE_PACKETRADIO: I(tick_ms)=15000; break; case OVERLAY_INTERFACE_PACKETRADIO: I(tick_ms)=15000; break;
case OVERLAY_INTERFACE_ETHERNET: I(tick_ms)=500; break; case OVERLAY_INTERFACE_ETHERNET: I(tick_ms)=500; break;
case OVERLAY_INTERFACE_WIFI: I(tick_ms)=500; break; case OVERLAY_INTERFACE_WIFI: I(tick_ms)=500; break;
} }
if (name[0]=='>') {
I(fd) = open(&name[1],O_APPEND|O_NONBLOCK|O_RDWR);
if (I(fd)<1)
return WHY("could not open dummy interface file for append");
/* Seek to end of file as initial reading point */
I(socket)=lseek(I(fd),0,SEEK_END); /* socket gets reused to hold file offset */
/* XXX later add pretend location information so that we can decide which "packets" to receive
based on closeness */
} else {
if (overlay_interface_init_socket(overlay_interface_count,src_addr,broadcast,netmask)) if (overlay_interface_init_socket(overlay_interface_count,src_addr,broadcast,netmask))
return WHY("overlay_interface_init_socket() failed"); return WHY("overlay_interface_init_socket() failed");
}
overlay_interface_count++; overlay_interface_count++;
#undef I(X) #undef I(X)
@ -221,6 +234,20 @@ int overlay_rx_messages()
unsigned int addrlen=sizeof(src_addr); unsigned int addrlen=sizeof(src_addr);
unsigned char transaction_id[8]; unsigned char transaction_id[8];
if (overlay_interfaces[i].fd) {
/* Read from dummy interface file */
lseek(overlay_interfaces[i].fd,overlay_interfaces[i].socket,SEEK_SET);
if (read(overlay_interfaces[i].fd,packet,overlay_interfaces[i].mtu)==overlay_interfaces[i].mtu)
{
overlay_interfaces[i].socket+=overlay_interfaces[i].mtu;
plen=overlay_interfaces[i].mtu;
bzero(&transaction_id[0],8);
bzero(&src_addr,sizeof(src_addr));
if (!packetOk(packet,plen,transaction_id,&src_addr,addrlen,1)) WHY("Malformed packet from dummy interface");
}
else { c[i]=0; count--; }
} else {
/* Read from UDP socket */
plen=recvfrom(overlay_interfaces[i].socket,packet,sizeof(packet),MSG_DONTWAIT, plen=recvfrom(overlay_interfaces[i].socket,packet,sizeof(packet),MSG_DONTWAIT,
&src_addr,&addrlen); &src_addr,&addrlen);
if (plen<0) { c[i]=0; count--; } else { if (plen<0) { c[i]=0; count--; } else {
@ -231,6 +258,7 @@ int overlay_rx_messages()
if (!packetOk(packet,plen,transaction_id,&src_addr,addrlen,1)) WHY("Malformed packet"); if (!packetOk(packet,plen,transaction_id,&src_addr,addrlen,1)) WHY("Malformed packet");
} }
} }
}
return 0; return 0;
} }
@ -250,7 +278,7 @@ int overlay_tx_messages()
/* XXX Go through queue and separate into per-interface queues? */ /* XXX Go through queue and separate into per-interface queues? */
return 0; return WHY("not implemented");
} }
int overlay_broadcast_ensemble(int interface_number,unsigned char *bytes,int len) int overlay_broadcast_ensemble(int interface_number,unsigned char *bytes,int len)
@ -263,6 +291,19 @@ int overlay_broadcast_ensemble(int interface_number,unsigned char *bytes,int len
fprintf(stderr,"Port=%d\n",overlay_interfaces[interface_number].port); fprintf(stderr,"Port=%d\n",overlay_interfaces[interface_number].port);
s.sin_port = htons( overlay_interfaces[interface_number].port ); s.sin_port = htons( overlay_interfaces[interface_number].port );
if (overlay_interfaces[interface_number].fd)
{
if (write(overlay_interfaces[interface_number].fd,bytes,overlay_interfaces[interface_number].mtu)
!=overlay_interfaces[interface_number].mtu)
{
perror("write()");
return WHY("write() failed");
}
else
return 0;
}
else
{
if(sendto(overlay_interfaces[interface_number].socket, bytes, len, 0, (struct sockaddr *)&s, sizeof(struct sockaddr_in)) < 0) if(sendto(overlay_interfaces[interface_number].socket, bytes, len, 0, (struct sockaddr *)&s, sizeof(struct sockaddr_in)) < 0)
{ {
/* Failed to send */ /* Failed to send */
@ -272,6 +313,7 @@ int overlay_broadcast_ensemble(int interface_number,unsigned char *bytes,int len
else else
/* Sent okay */ /* Sent okay */
return 0; return 0;
}
} }
int overlay_interface_discover() int overlay_interface_discover()
@ -288,6 +330,28 @@ int overlay_interface_discover()
/* Mark all interfaces as not observed, so that we know if we need to cull any */ /* Mark all interfaces as not observed, so that we know if we need to cull any */
for(i=0;i<overlay_interface_count;i++) overlay_interfaces[i].observed--; for(i=0;i<overlay_interface_count;i++) overlay_interfaces[i].observed--;
/* Check through for any virtual dummy interfaces */
struct interface_rules *r=interface_filter;
while(r) {
if (r->namespec[0]=='>') {
for(i=0;i<overlay_interface_count;i++) if (!strcasecmp(overlay_interfaces[i].name,r->namespec)) break;
if (i<overlay_interface_count)
/* We already know about this interface, so just update it */
overlay_interfaces[i].observed=1;
else {
/* New interface, so register it */
struct sockaddr_in dummyaddr;
if (overlay_interface_init(r->namespec,dummyaddr,dummyaddr,dummyaddr,
1000000,PORT_DNA,OVERLAY_INTERFACE_WIFI))
WHY("Could not initialise newly seen interface");
else
fprintf(stderr,"Registered interface %s\n",r->namespec);
}
}
r=r->next;
}
/* Check through actual network interfaces */
for (ifa=ifaddr;ifa!=NULL;ifa=ifa->ifa_next) { for (ifa=ifaddr;ifa!=NULL;ifa=ifa->ifa_next) {
family=ifa->ifa_addr->sa_family; family=ifa->ifa_addr->sa_family;
switch(family) { switch(family) {
@ -308,6 +372,7 @@ int overlay_interface_discover()
r=r->next; r=r->next;
} }
if (me&&(!me->excludeP)) { if (me&&(!me->excludeP)) {
fprintf(stderr,"Interface %s is interesting.\n",name);
/* We should register or update this interface. */ /* We should register or update this interface. */
int i; int i;
for(i=0;i<overlay_interface_count;i++) if (!strcasecmp(overlay_interfaces[i].name,(char *)name)) break; for(i=0;i<overlay_interface_count;i++) if (!strcasecmp(overlay_interfaces[i].name,(char *)name)) break;
@ -334,6 +399,8 @@ int overlay_interface_discover()
if (overlay_interface_init((char *)name,local,broadcast,netmask, if (overlay_interface_init((char *)name,local,broadcast,netmask,
me->speed_in_bits,me->port,me->type)) me->speed_in_bits,me->port,me->type))
WHY("Could not initialise newly seen interface"); WHY("Could not initialise newly seen interface");
else
fprintf(stderr,"Registered interface %s\n",name);
} }
} }
break; break;
@ -341,8 +408,7 @@ int overlay_interface_discover()
} }
} }
#endif #endif
freeifaddrs(ifaddr);
/* XXX Cull any non-observed interfaces */
return 0; return 0;
} }
@ -464,15 +530,19 @@ int overlay_check_ticks()
return WHY("gettimeofday() failed"); return WHY("gettimeofday() failed");
/* Get current time in milliseconds */ /* Get current time in milliseconds */
now=nowtv.tv_sec*1000; now=nowtv.tv_sec*1000LL;
now=now+nowtv.tv_usec/1000; now=now+nowtv.tv_usec/1000;
/* Now check if the next tick time for the interfaces is no later than that time. /* Now check if the next tick time for the interfaces is no later than that time.
If so, trigger a tick on the interface. */ If so, trigger a tick on the interface. */
fprintf(stderr,"Examining %d interfaces.\n",overlay_interface_count);
for(i=0;i<overlay_interface_count;i++) for(i=0;i<overlay_interface_count;i++)
{ {
/* Only tick live interfaces */ /* Only tick live interfaces */
if (overlay_interfaces[i].observed>0) if (overlay_interfaces[i].observed>0)
{
fprintf(stderr,"Interface %s ticks every %dms, last at %lld.\n",overlay_interfaces[i].name,
overlay_interfaces[i].tick_ms,overlay_interfaces[i].last_tick_ms);
if (now>=overlay_interfaces[i].last_tick_ms+overlay_interfaces[i].tick_ms) if (now>=overlay_interfaces[i].last_tick_ms+overlay_interfaces[i].tick_ms)
{ {
/* This interface is due for a tick */ /* This interface is due for a tick */
@ -480,6 +550,9 @@ int overlay_check_ticks()
overlay_interfaces[i].last_tick_ms=now; overlay_interfaces[i].last_tick_ms=now;
} }
} }
else
fprintf(stderr,"Interface %s is awol.\n",overlay_interfaces[i].name);
}
return 0; return 0;
} }
@ -492,11 +565,16 @@ long long overlay_time_until_next_tick()
struct timeval tv; struct timeval tv;
gettimeofday(&tv,NULL); gettimeofday(&tv,NULL);
now=tv.tv_sec*1000+tv.tv_usec/1000; now=tv.tv_sec*1000LL+tv.tv_usec/1000;
int i; int i;
fprintf(stderr,"Tick-check on %d interfaces at %lldms\n",overlay_interface_count,now);
for(i=0;i<overlay_interface_count;i++) for(i=0;i<overlay_interface_count;i++)
if (overlay_interfaces[i].observed>0)
{ {
fprintf(stderr,"Interface %s ticks every %dms, last at %lld.\n",overlay_interfaces[i].name,
overlay_interfaces[i].tick_ms,overlay_interfaces[i].last_tick_ms);
long long thistick=(overlay_interfaces[i].last_tick_ms+overlay_interfaces[i].tick_ms)-now; long long thistick=(overlay_interfaces[i].last_tick_ms+overlay_interfaces[i].tick_ms)-now;
if (thistick<0) thistick=0; if (thistick<0) thistick=0;
if (thistick<nexttick) nexttick=thistick; if (thistick<nexttick) nexttick=thistick;