mirror of
https://github.com/servalproject/serval-dna.git
synced 2025-04-06 18:46:43 +00:00
Close interfaces on socket errors or when not detected
This commit is contained in:
parent
74095e5356
commit
6e7c2196ba
9
lsif.c
9
lsif.c
@ -133,6 +133,7 @@ lsif(void) {
|
||||
ifc.ifc_buf = buf;
|
||||
if(ioctl(sck, SIOCGIFCONF, &ifc) < 0) {
|
||||
WHY_perror("ioctl(SIOCGIFCONF)");
|
||||
close(sck);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -163,8 +164,10 @@ lsif(void) {
|
||||
}
|
||||
|
||||
/* Get broadcast address */
|
||||
if (ioctl(sck, SIOCGIFBRDADDR, ifr, sizeof(*ifr)) == -1)
|
||||
FATAL_perror("ioctl(SIOCGIFBRDADDR)");
|
||||
if (ioctl(sck, SIOCGIFBRDADDR, ifr, sizeof(*ifr)) == -1){
|
||||
WHY_perror("ioctl(SIOCGIFBRDADDR)");
|
||||
continue;
|
||||
}
|
||||
|
||||
broadcast = (struct sockaddr_in *)&ifr->ifr_ifru.ifru_broadaddr;
|
||||
|
||||
@ -177,7 +180,7 @@ lsif(void) {
|
||||
nInterfaces++;
|
||||
}
|
||||
|
||||
if (debug & DEBUG_OVERLAYINTERFACES) DEBUGF("Examined %d interface addresses\n", nInterfaces);
|
||||
if (debug & DEBUG_OVERLAYINTERFACES) DEBUGF("Examined %d interface addresses", nInterfaces);
|
||||
|
||||
close(sck);
|
||||
return 0;
|
||||
|
@ -186,37 +186,44 @@ int overlay_interface_args(const char *arg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void overlay_interface_close(overlay_interface *interface){
|
||||
INFOF("Interface %s is down", interface->name);
|
||||
unschedule(&interface->alarm);
|
||||
unwatch(&interface->alarm);
|
||||
close(interface->alarm.poll.fd);
|
||||
interface->alarm.poll.fd=-1;
|
||||
interface->state=INTERFACE_STATE_DOWN;
|
||||
}
|
||||
|
||||
int
|
||||
overlay_interface_init_socket(int interface, struct sockaddr_in *src_addr, struct sockaddr_in *broadcast) {
|
||||
overlay_interface_init_socket(int interface) {
|
||||
char srctxt[INET_ADDRSTRLEN];
|
||||
|
||||
#define I(X) overlay_interfaces[interface].X
|
||||
bcopy(broadcast, &I(broadcast_address), sizeof(struct sockaddr_in));
|
||||
I(fileP) = 0;
|
||||
|
||||
I(alarm.poll.fd) = socket(PF_INET,SOCK_DGRAM,0);
|
||||
|
||||
if (I(alarm.poll.fd) < 0) {
|
||||
WHY_perror("socket");
|
||||
WHYF("Could not create UDP socket for interface: %s",strerror(errno));
|
||||
goto error;
|
||||
} else
|
||||
INFOF("interface #%d fd=%d",interface, I(alarm.poll.fd));
|
||||
WHY_perror("socket");
|
||||
WHYF("Could not create UDP socket for interface: %s",strerror(errno));
|
||||
goto error;
|
||||
}
|
||||
|
||||
int reuseP = 1;
|
||||
if (setsockopt(I(alarm.poll.fd), SOL_SOCKET, SO_REUSEADDR, &reuseP, sizeof(reuseP)) < 0) {
|
||||
WHY_perror("setsockopt(SO_REUSEADR)");
|
||||
goto error;
|
||||
}
|
||||
WHY_perror("setsockopt(SO_REUSEADR)");
|
||||
goto error;
|
||||
}
|
||||
#ifdef SO_REUSEPORT
|
||||
if (setsockopt(I(alarm.poll.fd), SOL_SOCKET, SO_REUSEPORT, &reuseP, sizeof(reuseP)) < 0) {
|
||||
WHY_perror("setsockopt(SO_REUSEPORT)");
|
||||
goto error;
|
||||
}
|
||||
WHY_perror("setsockopt(SO_REUSEPORT)");
|
||||
goto error;
|
||||
}
|
||||
#endif
|
||||
int broadcastP = 1;
|
||||
if (setsockopt(I(alarm.poll.fd), SOL_SOCKET, SO_BROADCAST, &broadcastP, sizeof(broadcastP)) < 0) {
|
||||
WHY_perror("setsockopt");
|
||||
WHY_perror("setsockopt(SO_BROADCAST)");
|
||||
goto error;
|
||||
}
|
||||
|
||||
@ -225,6 +232,17 @@ overlay_interface_init_socket(int interface, struct sockaddr_in *src_addr, struc
|
||||
a bad signal. */
|
||||
fcntl(I(alarm.poll.fd), F_SETFL, fcntl(I(alarm.poll.fd), F_GETFL, NULL) | O_CLOEXEC);
|
||||
|
||||
#ifdef SO_BINDTODEVICE
|
||||
/*
|
||||
Limit incoming and outgoing packets to this interface, no matter what the routing table says.
|
||||
This should allow for a device with multiple interfaces on the same subnet.
|
||||
Don't abort if this fails, just log it.
|
||||
*/
|
||||
if (setsockopt(I(alarm.poll.fd), SOL_SOCKET, SO_BINDTODEVICE, I(name), strlen(I(name))+1) < 0) {
|
||||
WHY_perror("setsockopt(SO_BINDTODEVICE)");
|
||||
}
|
||||
#endif
|
||||
|
||||
/* @PGS/20120615
|
||||
Use the broadcast address, so that we can reliably receive broadcast
|
||||
traffic on all platforms. BUT on OSX we really need a non-broadcast socket
|
||||
@ -252,11 +270,13 @@ overlay_interface_init_socket(int interface, struct sockaddr_in *src_addr, struc
|
||||
I(alarm.deadline)=I(alarm.alarm)+10;
|
||||
schedule(&I(alarm));
|
||||
|
||||
I(state)=INTERFACE_STATE_UP;
|
||||
|
||||
INFOF("Interface %s addr %s, is up",I(name), inet_ntoa(I(broadcast_address.sin_addr)));
|
||||
return 0;
|
||||
|
||||
error:
|
||||
close(I(alarm.poll.fd));
|
||||
I(alarm.poll.fd)=-1;
|
||||
overlay_interface_close(&overlay_interfaces[interface]);
|
||||
return -1;
|
||||
#undef I
|
||||
}
|
||||
@ -274,7 +294,7 @@ int overlay_interface_init(char *name,struct sockaddr_in *src_addr,struct sockad
|
||||
/* Pick a reasonable default MTU.
|
||||
This will ultimately get tuned by the bandwidth and other properties of the interface */
|
||||
I(mtu)=1200;
|
||||
I(observed)=1;
|
||||
I(state)=INTERFACE_STATE_DOWN;
|
||||
I(bits_per_second)=speed_in_bits;
|
||||
I(port)=port;
|
||||
I(type)=type;
|
||||
@ -324,8 +344,14 @@ int overlay_interface_init(char *name,struct sockaddr_in *src_addr,struct sockad
|
||||
dummy_poll_stats.name="overlay_dummy_poll";
|
||||
I(alarm.stats)=&dummy_poll_stats;
|
||||
schedule(&I(alarm));
|
||||
|
||||
I(state)=INTERFACE_STATE_UP;
|
||||
INFOF("Dummy interface %s is up",I(name));
|
||||
|
||||
} else {
|
||||
if (overlay_interface_init_socket(overlay_interface_count,src_addr,broadcast))
|
||||
bcopy(src_addr, &I(address), sizeof(struct sockaddr_in));
|
||||
bcopy(broadcast, &I(broadcast_address), sizeof(struct sockaddr_in));
|
||||
if (overlay_interface_init_socket(overlay_interface_count))
|
||||
return WHY("overlay_interface_init_socket() failed");
|
||||
}
|
||||
|
||||
@ -344,13 +370,17 @@ void overlay_interface_poll(struct sched_ent *alarm)
|
||||
socklen_t addrlen = sizeof(src_addr);
|
||||
|
||||
if (alarm->poll.revents==0){
|
||||
// tick the interface
|
||||
unsigned long long now = overlay_gettime_ms();
|
||||
int i = (interface - overlay_interfaces);
|
||||
overlay_tick_interface(i, now);
|
||||
alarm->alarm=now+interface->tick_ms;
|
||||
alarm->deadline=alarm->alarm+interface->tick_ms/2;
|
||||
schedule(alarm);
|
||||
|
||||
if (interface->state==INTERFACE_STATE_UP){
|
||||
// tick the interface
|
||||
unsigned long long now = overlay_gettime_ms();
|
||||
int i = (interface - overlay_interfaces);
|
||||
overlay_tick_interface(i, now);
|
||||
alarm->alarm=now+interface->tick_ms;
|
||||
alarm->deadline=alarm->alarm+interface->tick_ms/2;
|
||||
schedule(alarm);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -358,16 +388,20 @@ void overlay_interface_poll(struct sched_ent *alarm)
|
||||
enable stats to accurately count packets received */
|
||||
int recvttl=1;
|
||||
plen = recvwithttl(alarm->poll.fd,packet, sizeof(packet), &recvttl, &src_addr, &addrlen);
|
||||
if (plen != -1) {
|
||||
/* We have a frame from this interface */
|
||||
if (debug&DEBUG_PACKETRX)
|
||||
serval_packetvisualise(open_logging(),"Read from real interface", packet,plen);
|
||||
if (debug&DEBUG_OVERLAYINTERFACES) DEBUGF("Received %d bytes on interface %s",plen,interface->name);
|
||||
if (packetOk(interface,packet,plen,NULL,recvttl,&src_addr,addrlen,1)) {
|
||||
WHY("Malformed packet");
|
||||
// Do we really want to attempt to parse it again?
|
||||
//serval_packetvisualise(open_logging(), "Malformed packet", packet,plen);
|
||||
}
|
||||
if (plen == -1) {
|
||||
WHY_perror("recvwithttl(c)");
|
||||
overlay_interface_close(interface);
|
||||
return;
|
||||
}
|
||||
|
||||
/* We have a frame from this interface */
|
||||
if (debug&DEBUG_PACKETRX)
|
||||
serval_packetvisualise(open_logging(),"Read from real interface", packet,plen);
|
||||
if (debug&DEBUG_OVERLAYINTERFACES) DEBUGF("Received %d bytes on interface %s",plen,interface->name);
|
||||
if (packetOk(interface,packet,plen,NULL,recvttl,&src_addr,addrlen,1)) {
|
||||
WHY("Malformed packet");
|
||||
// Do we really want to attempt to parse it again?
|
||||
//serval_packetvisualise(open_logging(), "Malformed packet", packet,plen);
|
||||
}
|
||||
}
|
||||
|
||||
@ -404,8 +438,6 @@ void overlay_dummy_poll(struct sched_ent *alarm)
|
||||
|
||||
if (alarm->alarm > interface->last_tick_ms + interface->tick_ms)
|
||||
alarm->alarm = interface->last_tick_ms + interface->tick_ms;
|
||||
if (debug&DEBUG_OVERLAYINTERFACES)
|
||||
DEBUGF("At end of input on dummy interface %s", interface->name);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -466,6 +498,9 @@ int overlay_broadcast_ensemble(int interface_number,
|
||||
|
||||
overlay_interface *interface = &overlay_interfaces[interface_number];
|
||||
|
||||
if (interface->state!=INTERFACE_STATE_UP){
|
||||
return WHYF("Cannot send to interface %s as it is down", interface->name);
|
||||
}
|
||||
memset(&s, '\0', sizeof(struct sockaddr_in));
|
||||
if (recipientaddr) {
|
||||
bcopy(recipientaddr,&s,sizeof(struct sockaddr_in));
|
||||
@ -535,8 +570,11 @@ int overlay_broadcast_ensemble(int interface_number,
|
||||
else
|
||||
{
|
||||
if(sendto(interface->alarm.poll.fd,
|
||||
bytes, len, 0, (struct sockaddr *)&s, sizeof(struct sockaddr_in)) != len)
|
||||
return WHY_perror("sendto(c)");
|
||||
bytes, len, 0, (struct sockaddr *)&s, sizeof(struct sockaddr_in)) != len){
|
||||
WHY_perror("sendto(c)");
|
||||
overlay_interface_close(interface);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -575,105 +613,116 @@ overlay_interface_register(char *name,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Search in the exist list of interfaces */
|
||||
for(i = 0; i < overlay_interface_count; i++)
|
||||
if (!strcasecmp(overlay_interfaces[i].name, name))
|
||||
break;
|
||||
int found_interface= -1;
|
||||
|
||||
if (i < overlay_interface_count) {
|
||||
/* We already know about this interface, so just update it. */
|
||||
|
||||
/* Check if the broadcast address is the same
|
||||
TODO: This only applies on Linux because only there can you bind to the bcast addr
|
||||
DOC 20120608
|
||||
*/
|
||||
/* Search in the exist list of interfaces */
|
||||
for(i = 0; i < overlay_interface_count; i++){
|
||||
int broadcast_match = 0;
|
||||
int name_match =0;
|
||||
|
||||
if ((overlay_interfaces[i].broadcast_address.sin_addr.s_addr & 0xffffffff)
|
||||
== (broadcast->sin_addr.s_addr & 0xffffffff)) {
|
||||
/* Same address, mark it as being seen */
|
||||
overlay_interfaces[i].observed = 1;
|
||||
return 0;
|
||||
} else {
|
||||
if (0) {
|
||||
/* Interface has changed.
|
||||
TODO: We should register each address we understand in a list and check them.
|
||||
DOC 20120608 */
|
||||
INFOF("Interface changed %08llx.%08llx vs %08llx.%08llx",
|
||||
/* overlay_interfaces[i].local_address.sin_addr.s_addr */0,
|
||||
overlay_interfaces[i].broadcast_address.sin_addr.s_addr,
|
||||
local->sin_addr.s_addr,
|
||||
broadcast->sin_addr.s_addr);
|
||||
unwatch(&overlay_interfaces[i].alarm);
|
||||
close(overlay_interfaces[i].alarm.poll.fd);
|
||||
overlay_interfaces[i].alarm.poll.fd = -1;
|
||||
if (overlay_interface_init_socket(i, local, broadcast))
|
||||
INFOF("Could not reinitialise changed interface %s", name);
|
||||
}
|
||||
== (broadcast->sin_addr.s_addr & 0xffffffff)){
|
||||
broadcast_match = 1;
|
||||
}
|
||||
} else {
|
||||
/* New interface, so register it */
|
||||
if (overlay_interface_init(name, local, broadcast, me->speed_in_bits, me->port, me->type))
|
||||
WHYF("Could not initialise newly seen interface %s", name);
|
||||
else
|
||||
if (debug & DEBUG_OVERLAYINTERFACES) DEBUGF("Registered interface %s", name);
|
||||
|
||||
name_match = !strcasecmp(overlay_interfaces[i].name, name);
|
||||
|
||||
if (name_match && broadcast_match){
|
||||
// mark this interface as still alive
|
||||
if (overlay_interfaces[i].state==INTERFACE_STATE_DETECTING)
|
||||
overlay_interfaces[i].state=INTERFACE_STATE_UP;
|
||||
|
||||
// try to bring the interface back up again
|
||||
if (overlay_interfaces[i].state==INTERFACE_STATE_DOWN){
|
||||
bcopy(local, &overlay_interfaces[i].address, sizeof(struct sockaddr_in));
|
||||
overlay_interface_init_socket(i);
|
||||
}
|
||||
|
||||
// we already know about this interface, and it's up so stop looking immediately
|
||||
return 0;
|
||||
}
|
||||
|
||||
// remember this slot to bring the interface back up again, even if the address has changed
|
||||
if (name_match && overlay_interfaces[i].state==INTERFACE_STATE_DOWN)
|
||||
found_interface=i;
|
||||
}
|
||||
|
||||
if (found_interface>=0){
|
||||
bcopy(local, &overlay_interfaces[i].address, sizeof(struct sockaddr_in));
|
||||
bcopy(broadcast, &overlay_interfaces[i].broadcast_address, sizeof(struct sockaddr_in));
|
||||
return overlay_interface_init_socket(i);
|
||||
}
|
||||
|
||||
|
||||
/* New interface, so register it */
|
||||
if (overlay_interface_init(name, local, broadcast, me->speed_in_bits, me->port, me->type))
|
||||
return WHYF("Could not initialise newly seen interface %s", name);
|
||||
else
|
||||
if (debug & DEBUG_OVERLAYINTERFACES) DEBUGF("Registered interface %s", name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void overlay_interface_discover(struct sched_ent *alarm){
|
||||
int no_route, i;
|
||||
int i;
|
||||
struct interface_rules *r;
|
||||
struct sockaddr_in dummyaddr;
|
||||
|
||||
/* Mark all interfaces as not observed, so that we know if we need to cull any */
|
||||
int detect_real_interfaces = 0;
|
||||
|
||||
/* Mark all UP interfaces as DETECTING, so we can tell which interfaces are new, and which are dead */
|
||||
for(i = 0; i < overlay_interface_count; i++)
|
||||
overlay_interfaces[i].observed = 0;
|
||||
if (overlay_interfaces[i].state==INTERFACE_STATE_UP)
|
||||
overlay_interfaces[i].state=INTERFACE_STATE_DETECTING;
|
||||
|
||||
/* Check through for any virtual dummy interfaces */
|
||||
for (r = interface_filter; r != NULL; r = r->next) {
|
||||
if (r->namespec[0] != '>')
|
||||
if (r->namespec[0] != '>'){
|
||||
detect_real_interfaces = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
for(i = 0; i < overlay_interface_count; i++)
|
||||
if (!strcasecmp(overlay_interfaces[i].name,r->namespec))
|
||||
if (!strcasecmp(overlay_interfaces[i].name,r->namespec)){
|
||||
if (overlay_interfaces[i].state==INTERFACE_STATE_DETECTING)
|
||||
overlay_interfaces[i].state=INTERFACE_STATE_UP;
|
||||
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 */
|
||||
if (overlay_interface_init(r->namespec,&dummyaddr,&dummyaddr,
|
||||
1000000,PORT_DNA,OVERLAY_INTERFACE_WIFI)) {
|
||||
if (debug & DEBUG_OVERLAYINTERFACES) DEBUGF("Could not initialise newly seen interface %s", r->namespec);
|
||||
}
|
||||
else
|
||||
if (debug & DEBUG_OVERLAYINTERFACES) DEBUGF("Registered interface %s",r->namespec);
|
||||
|
||||
if (i >= overlay_interface_count){
|
||||
/* New interface, so register it */
|
||||
overlay_interface_init(r->namespec,&dummyaddr,&dummyaddr,1000000,PORT_DNA,OVERLAY_INTERFACE_WIFI);
|
||||
}
|
||||
}
|
||||
|
||||
/* Look for real interfaces */
|
||||
no_route = 1;
|
||||
|
||||
if (detect_real_interfaces){
|
||||
int no_route = 1;
|
||||
|
||||
#ifdef HAVE_IFADDRS_H
|
||||
if (no_route != 0)
|
||||
no_route = doifaddrs();
|
||||
if (no_route != 0)
|
||||
no_route = doifaddrs();
|
||||
#endif
|
||||
|
||||
#ifdef SIOCGIFCONF
|
||||
if (no_route != 0)
|
||||
no_route = lsif();
|
||||
if (no_route != 0)
|
||||
no_route = lsif();
|
||||
#endif
|
||||
|
||||
#ifdef linux
|
||||
if (no_route != 0)
|
||||
no_route = scrapeProcNetRoute();
|
||||
if (no_route != 0)
|
||||
no_route = scrapeProcNetRoute();
|
||||
#endif
|
||||
|
||||
if (no_route != 0) {
|
||||
FATAL("Unable to get any interface information");
|
||||
if (no_route != 0) {
|
||||
FATAL("Unable to get any interface information");
|
||||
}
|
||||
}
|
||||
|
||||
// detect if any interfaces have gone away and need to be closed
|
||||
for(i = 0; i < overlay_interface_count; i++)
|
||||
if (overlay_interfaces[i].state==INTERFACE_STATE_DETECTING)
|
||||
overlay_interface_close(&overlay_interfaces[i]);
|
||||
|
||||
alarm->alarm = overlay_gettime_ms()+5000;
|
||||
alarm->deadline = alarm->alarm + 10000;
|
||||
schedule(alarm);
|
||||
@ -822,7 +871,7 @@ void overlay_stuff_packet(struct outgoing_packet *packet, overlay_txqueue *queue
|
||||
int i;
|
||||
for(i=0;i<OVERLAY_MAX_INTERFACES;i++)
|
||||
{
|
||||
if (overlay_interfaces[i].observed>0)
|
||||
if (overlay_interfaces[i].state==INTERFACE_STATE_UP)
|
||||
if (!frame->broadcast_sent_via[i]){
|
||||
overlay_init_packet(packet, i);
|
||||
break;
|
||||
@ -863,7 +912,7 @@ void overlay_stuff_packet(struct outgoing_packet *packet, overlay_txqueue *queue
|
||||
// check if there is still a broadcast to be sent
|
||||
for(i=0;i<OVERLAY_MAX_INTERFACES;i++)
|
||||
{
|
||||
if (overlay_interfaces[i].observed>0)
|
||||
if (overlay_interfaces[i].state==INTERFACE_STATE_UP)
|
||||
if (!frame->broadcast_sent_via[i]){
|
||||
keep_payload=1;
|
||||
break;
|
||||
@ -940,8 +989,9 @@ int overlay_tick_interface(int i, long long now)
|
||||
struct outgoing_packet packet;
|
||||
IN();
|
||||
|
||||
if (overlay_interfaces[i].bits_per_second<1) {
|
||||
/* An interface with no speed budget is for listening only, so doesn't get ticked */
|
||||
/* An interface with no speed budget is for listening only, so doesn't get ticked */
|
||||
if (overlay_interfaces[i].bits_per_second<1
|
||||
|| overlay_interfaces[i].state!=INTERFACE_STATE_UP) {
|
||||
RETURN(0);
|
||||
}
|
||||
|
||||
|
@ -401,7 +401,8 @@ int overlay_get_nexthop(unsigned char *d,unsigned char *nexthop,int *interface)
|
||||
|
||||
*interface=0;
|
||||
for(i=1;i<OVERLAY_MAX_INTERFACES;i++) {
|
||||
if (direct_neighbour->scores[i]>direct_neighbour->scores[*interface]) *interface=i;
|
||||
if (overlay_interfaces[i].state==INTERFACE_STATE_UP &&
|
||||
direct_neighbour->scores[i]>direct_neighbour->scores[*interface]) *interface=i;
|
||||
}
|
||||
if (direct_neighbour->scores[*interface]>0) {
|
||||
bcopy(d,nexthop,SID_SIZE);
|
||||
@ -430,7 +431,8 @@ int overlay_get_nexthop(unsigned char *d,unsigned char *nexthop,int *interface)
|
||||
overlay_route_recalc_neighbour_metrics(neighbour, now);
|
||||
|
||||
for(i=1;i<OVERLAY_MAX_INTERFACES;i++) {
|
||||
if (neighbour->scores[i]*score>best_score) {
|
||||
if (overlay_interfaces[i].state==INTERFACE_STATE_UP &&
|
||||
neighbour->scores[i]*score>best_score) {
|
||||
bcopy(&neighbour->node->sid[0],&nexthop[0],SID_SIZE);
|
||||
*interface=i;
|
||||
best_o=o;
|
||||
@ -847,7 +849,8 @@ int overlay_route_recalc_node_metrics(overlay_node *n,long long now)
|
||||
int i;
|
||||
for(i=0;i<overlay_interface_count;i++)
|
||||
{
|
||||
if (overlay_neighbours[n->neighbour_id].scores[i]>best_score)
|
||||
if (overlay_interfaces[i].state==INTERFACE_STATE_UP &&
|
||||
overlay_neighbours[n->neighbour_id].scores[i]>best_score)
|
||||
{
|
||||
best_score=overlay_neighbours[n->neighbour_id].scores[i];
|
||||
best_observation=-1;
|
||||
@ -935,50 +938,45 @@ int overlay_route_recalc_neighbour_metrics(overlay_neighbour *n,long long now)
|
||||
Also, we might like to take into account the interface we received
|
||||
the announcements on. */
|
||||
for(i=0;i<OVERLAY_MAX_OBSERVATIONS;i++) {
|
||||
if (n->observations[i].valid&&n->observations[i].s1) {
|
||||
/* Work out the interval covered by the observation.
|
||||
The times are represented as lowest 32 bits of a 64-bit
|
||||
millisecond clock. This introduces modulo problems,
|
||||
however by using 32-bit modulo arithmatic here, we avoid
|
||||
most of them. */
|
||||
unsigned int interval=n->observations[i].s2-n->observations[i].s1;
|
||||
if (!n->observations[i].valid ||
|
||||
!n->observations[i].s1 ||
|
||||
n->observations[i].sender_interface>=OVERLAY_MAX_INTERFACES ||
|
||||
overlay_interfaces[n->observations[i].sender_interface].state!=INTERFACE_STATE_UP)
|
||||
continue;
|
||||
|
||||
/* Work out the interval covered by the observation.
|
||||
The times are represented as lowest 32 bits of a 64-bit
|
||||
millisecond clock. This introduces modulo problems,
|
||||
however by using 32-bit modulo arithmatic here, we avoid
|
||||
most of them. */
|
||||
unsigned int interval=n->observations[i].s2-n->observations[i].s1;
|
||||
|
||||
/* Check the observation age, and ignore if too old */
|
||||
int obs_age=now-n->observations[i].time_ms;
|
||||
if (debug&DEBUG_OVERLAYROUTING)
|
||||
DEBUGF("tallying obs: %dms old, %dms long", obs_age,interval);
|
||||
|
||||
/* Ignore very large intervals (>1hour) as being likely to be erroneous.
|
||||
(or perhaps a clock wrap due to the modulo arithmatic)
|
||||
|
||||
One tick per hour should be well and truly slow enough to do
|
||||
50KB per 12 hours, which is the minimum traffic charge rate
|
||||
on an expensive BGAN satellite link.
|
||||
*/
|
||||
if (interval>=3600000 || obs_age>200000)
|
||||
continue;
|
||||
|
||||
/* Check the observation age, and ignore if too old */
|
||||
int obs_age=now-n->observations[i].time_ms;
|
||||
if (debug&DEBUG_OVERLAYROUTING)
|
||||
DEBUGF("tallying obs: %dms old, %dms long", obs_age,interval);
|
||||
if (obs_age>200000) continue;
|
||||
if (debug&DEBUG_OVERLAYROUTING)
|
||||
DEBUGF("adding %dms (interface %d '%s')",
|
||||
interval,n->observations[i].sender_interface,
|
||||
overlay_interfaces[n->observations[i].sender_interface].name);
|
||||
|
||||
/* Ignore very large intervals (>1hour) as being likely to be erroneous.
|
||||
(or perhaps a clock wrap due to the modulo arithmatic)
|
||||
|
||||
One tick per hour should be well and truly slow enough to do
|
||||
50KB per 12 hours, which is the minimum traffic charge rate
|
||||
on an expensive BGAN satellite link.
|
||||
*/
|
||||
if (interval<3600000) {
|
||||
if (debug&DEBUG_OVERLAYROUTING)
|
||||
DEBUGF("adding %dms (interface %d '%s')",
|
||||
interval,n->observations[i].sender_interface,
|
||||
overlay_interfaces[n->observations[i].sender_interface].name);
|
||||
|
||||
/* sender_interface is unsigned, so a single-sided test is sufficient for bounds checking */
|
||||
if (n->observations[i].sender_interface<OVERLAY_MAX_INTERFACES)
|
||||
{
|
||||
ms_observed_200sec[n->observations[i].sender_interface]+=interval;
|
||||
if (obs_age<=5000){
|
||||
ms_observed_5sec[n->observations[i].sender_interface]+=(interval>5000?5000:interval);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
WHY("Invalid interface ID in observation");
|
||||
DEBUGF("XXXXXXX adding %dms (interface %d)",interval,n->observations[i].sender_interface);
|
||||
}
|
||||
}
|
||||
|
||||
if (n->observations[i].time_ms>most_recent_observation) most_recent_observation=n->observations[i].time_ms;
|
||||
ms_observed_200sec[n->observations[i].sender_interface]+=interval;
|
||||
if (obs_age<=5000){
|
||||
ms_observed_5sec[n->observations[i].sender_interface]+=(interval>5000?5000:interval);
|
||||
}
|
||||
|
||||
if (n->observations[i].time_ms>most_recent_observation) most_recent_observation=n->observations[i].time_ms;
|
||||
}
|
||||
|
||||
/* From the sum of observations calculate the metrics.
|
||||
|
20
serval.h
20
serval.h
@ -508,6 +508,11 @@ extern int overlayMode;
|
||||
#define OVERLAY_INTERFACE_WIFI 2
|
||||
#define OVERLAY_INTERFACE_PACKETRADIO 3
|
||||
|
||||
#define INTERFACE_STATE_FREE 0
|
||||
#define INTERFACE_STATE_UP 1
|
||||
#define INTERFACE_STATE_DOWN 2
|
||||
#define INTERFACE_STATE_DETECTING 3
|
||||
|
||||
typedef struct overlay_interface {
|
||||
struct sched_ent alarm;
|
||||
char name[80];
|
||||
@ -540,9 +545,11 @@ typedef struct overlay_interface {
|
||||
int sequence_number;
|
||||
/* XXX need recent packet buffers to support the above */
|
||||
|
||||
/* Broadcast address and netmask, if known
|
||||
/* We need to make sure that interface name and broadcast address is unique for all interfaces that are UP.
|
||||
We bind a separate socket per interface / broadcast address Broadcast address and netmask, if known
|
||||
We really only case about distinct broadcast addresses on interfaces.
|
||||
Also simplifies aliases on interfaces. */
|
||||
struct sockaddr_in address;
|
||||
struct sockaddr_in broadcast_address;
|
||||
|
||||
/* Not necessarily the real MTU, but the largest frame size we are willing to TX on this interface.
|
||||
@ -550,10 +557,11 @@ typedef struct overlay_interface {
|
||||
potentially two quite different values. */
|
||||
int mtu;
|
||||
|
||||
/* If the interface still exists on the local machine.
|
||||
If not, it we keep track of it for a few seconds before purging it, incase of flapping, e.g.,
|
||||
due to DHCP renewal */
|
||||
int observed;
|
||||
/* Use one of the INTERFACE_STATE_* constants to indicate the state of this interface.
|
||||
If the interface stops working or disappears, it will be marked as DOWN and the socket closed.
|
||||
But if it comes back up again, we should try to reuse this structure, even if the broadcast address has changed.
|
||||
*/
|
||||
int state;
|
||||
} overlay_interface;
|
||||
|
||||
/* Maximum interface count is rather arbitrary.
|
||||
@ -862,7 +870,7 @@ long long parse_quantity(char *q);
|
||||
|
||||
int overlay_interface_init(char *name,struct sockaddr_in *src_addr,struct sockaddr_in *broadcast,
|
||||
int speed_in_bits,int port,int type);
|
||||
int overlay_interface_init_socket(int i,struct sockaddr_in *src_addr,struct sockaddr_in *broadcast);
|
||||
int overlay_interface_init_socket(int i);
|
||||
long long overlay_time_until_next_tick();
|
||||
int overlay_rx_messages();
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user