Refactor packet envelope and sid abbreviation reading and writing

This commit is contained in:
Jeremy Lakeman 2012-07-17 15:30:50 +09:30
parent 7fb1fd7938
commit ddba8033e4
10 changed files with 458 additions and 506 deletions

312
overlay.c
View File

@ -182,238 +182,124 @@ int overlay_frame_process(struct overlay_interface *interface,overlay_frame *f)
long long now=overlay_gettime_ms();
if (f->source_address_status==OA_RESOLVED&&overlay_address_is_local(f->source))
RETURN(WHY("Dropping frame claiming to come from myself."));
if (debug&DEBUG_OVERLAYFRAMES)
DEBUGF(">>> Received frame (type=%02x, bytes=%d)",f->type,f->payload?f->payload->length:-1);
if (debug&DEBUG_OVERLAYFRAMES) DEBUGF(">>> Received frame (type=%02x, bytes=%d)",f->type,f->payload?f->payload->length:-1);
/* First order of business is whether the nexthop address has been resolved.
If not, we need to think about asking for it to be resolved.
The trouble is that we do not want to trigger a Hanson Event (a storm of
please explains/resolution requests). Yet, we do not want to delay
communications unnecessarily.
The simple solution for now is to queue the address for resolution request
in our next tick. If we see another resolution request for the same
address in the mean time, then we can cancel our request */
switch (f->nexthop_address_status)
{
case OA_UNINITIALISED:
/* Um? Right. */
RETURN(WHY("frame passed with ununitialised nexthop address"));
break;
case OA_RESOLVED:
/* Great, we have the address, so we can get on with things */
break;
case OA_PLEASEEXPLAIN:
RETURN(-1); // WHY("Address cannot be resolved -- aborting packet processing.");
/* XXX Should send a please explain to get this address resolved. */
break;
case OA_UNSUPPORTED:
default:
// TODO tell the sender
/* If we don't support the address format, we should probably tell
the sender. Again, we queue this up, and cancel it if someone else
tells them in the meantime to avoid an Opposition Event (like a Hanson
Event, but repeatedly berating any node that holds a different policy
to itself. */
WHY("Packet with unsupported address format");
RETURN(-1);
break;
// only examine payloads that are broadcasts, or where I'm the next hop
if (overlay_address_is_broadcast(f->nexthop)) {
if (overlay_broadcast_drop_check(f->nexthop)){
if (debug&DEBUG_OVERLAYFRAMES)
DEBUGF("Dropping frame, duplicate broadcast %s", alloca_tohex_sid(f->nexthop));
RETURN(0);
}
/* Okay, nexthop is valid, so let's see if it is us */
int forMe=0,i;
}else if (!overlay_address_is_local(f->nexthop)){
if (debug&DEBUG_OVERLAYFRAMES)
DEBUGF("Dropping frame, not addressed to me %s", alloca_tohex_sid(f->nexthop));
RETURN(0);
}
int broadcast=overlay_address_is_broadcast(f->destination);
int ultimatelyForMe=0;
int broadcast=0;
int nhbroadcast=overlay_address_is_broadcast(f->nexthop);
int duplicateBroadcast=0;
if (nhbroadcast) {
if (overlay_broadcast_drop_check(f->nexthop)) duplicateBroadcast=1;
forMe=1; }
if (overlay_address_is_local(f->nexthop)) forMe=1;
if (forMe) {
/* It's for us, so resolve the addresses */
if (overlay_frame_resolve_addresses(f))
RETURN(WHY("Failed to resolve destination and sender addresses in frame"));
broadcast=overlay_address_is_broadcast(f->destination);
if (debug&DEBUG_OVERLAYFRAMES) {
strbuf b = strbuf_alloca(1024);
strbuf_sprintf(b, "Destination for this frame is (resolve code=%d): ", f->destination_address_status);
if (f->destination_address_status==OA_RESOLVED)
for(i=0;i<SID_SIZE;i++)
strbuf_sprintf(b, "%02x", f->destination[i]);
else
strbuf_puts(b, "???");
DEBUG(strbuf_str(b));
strbuf_reset(b);
strbuf_sprintf(b, "Source for this frame is (resolve code=%d): ", f->source_address_status);
if (f->source_address_status==OA_RESOLVED)
for(i=0;i<SID_SIZE;i++)
strbuf_sprintf(b, "%02x", f->source[i]);
else
strbuf_puts(b, "???");
DEBUG(strbuf_str(b));
}
if (f->source_address_status!=OA_RESOLVED) {
if (debug&DEBUG_OVERLAYFRAMES) WHY("Source address could not be resolved, so dropping frame.");
RETURN(-1);
}
if (overlay_address_is_local(f->source))
{
/* not that noteworthy, as when listening to a broadcast socket
you hear everything you send. */
if (debug&DEBUG_OVERLAYROUTING)
WHY("Dropping frame claiming to come from myself.");
RETURN(-1);
}
if (f->destination_address_status==OA_RESOLVED) {
if (overlay_address_is_broadcast(f->destination))
{ ultimatelyForMe=1; broadcast=1; }
if (overlay_address_is_local(f->destination)) ultimatelyForMe=1;
} else {
if (debug&DEBUG_OVERLAYFRAMES) WHY("Destination address could not be resolved, so dropping frame.");
RETURN(WHY("could not resolve destination address"));
}
}
if (debug&DEBUG_OVERLAYFRAMES) {
DEBUGF("This frame does%s have me listed as next hop.", forMe?"":" not");
DEBUGF("This frame is%s for me.", ultimatelyForMe?"":" not");
DEBUGF("This frame is%s%s broadcast.", broadcast?"":" not",duplicateBroadcast?" a duplicate":"");
}
if (duplicateBroadcast) {
if (0) DEBUG("Packet is duplicate broadcast");
RETURN(0);
}
/* Not for us? Then just ignore it */
if (!forMe) {
RETURN(0);
if (broadcast){
ultimatelyForMe = 1;
// Note that we assume a broadcast destination address is the same as the broadcast nexthop address
// we should decide to drop the packet based on the nexthop address.
}else{
if (overlay_address_is_local(f->destination))
ultimatelyForMe = 1;
}
f->ttl--;
// Never ever forward these types
if ((f->type==OF_TYPE_SELFANNOUNCE)
||(f->type==OF_TYPE_RHIZOME_ADVERT))
f->ttl=0;
/* Is this a frame we have to forward on? */
if (((!ultimatelyForMe)||broadcast)&&(f->ttl>1))
if (((!ultimatelyForMe)||broadcast)&&(f->ttl>0))
{
/* Yes, it is. */
if (broadcast&&(!duplicateBroadcast)&&
((f->type==OF_TYPE_SELFANNOUNCE)
||(f->type==OF_TYPE_RHIZOME_ADVERT)
))
{
// Don't forward broadcast self-announcement packets as that is O(n^2) with
// traffic. We have other means to propagating the mesh topology information.
// Similarly, rhizome advertisement traffic is always link local, so don't
// forward that either.
if (debug&DEBUG_BROADCASTS)
if (duplicateBroadcast)
DEBUG("Dropping broadcast frame (BPI seen before)");
} else {
if (debug&DEBUG_OVERLAYFRAMES) DEBUG("Forwarding frame");
int dontForward=0;
if (!broadcast) {
if (overlay_get_nexthop(f->destination,f->nexthop,&f->nexthop_interface))
WHYF("Could not find next hop for %s* - dropping frame",
alloca_tohex(f->destination, 7));
dontForward=1;
}
f->ttl--;
int forward=1;
if (!broadcast)
{
if (overlay_get_nexthop(f->destination,f->nexthop,&f->nexthop_interface))
WHYF("Could not find next hop for %s* - dropping frame",
alloca_tohex(f->destination, 7));
forward=0;
}
if (0)
DEBUGF("considering forwarding frame to %s (forme=%d, bcast=%d, dup=%d)",
alloca_tohex_sid(f->destination),ultimatelyForMe,broadcast,
duplicateBroadcast);
if (0)
DEBUGF("considering forwarding frame to %s (forme=%d, bcast=%d)",
alloca_tohex_sid(f->destination),ultimatelyForMe,broadcast);
if (overlay_address_is_broadcast(f->destination))
{
/* if nexthop and destination address are the same, and nexthop was shown
not to be a duplicate, then we don't need to test the destination
address for being a duplicate broadcast. */
int sameAsNextHop=1,i;
for(i=0;i<SID_SIZE;i++)
if (f->nexthop[i]!=f->destination[i])
{ sameAsNextHop=0; break; }
if ((!sameAsNextHop)&&overlay_broadcast_drop_check(f->destination))
duplicateBroadcast=1;
if (duplicateBroadcast) {
DEBUGF("reject src is %s", alloca_tohex_sid(f->source));
DEBUGF("reject nexthop is %s", alloca_tohex_sid(f->nexthop));
DEBUGF("reject destination is %s", alloca_tohex_sid(f->destination));
RETURN(WHY("Not forwarding or reading duplicate broadcast"));
}
if (forward) {
if (debug&DEBUG_OVERLAYFRAMES)
DEBUG("Forwarding frame");
/* Queue frame for dispatch.
Don't forget to put packet in the correct queue based on type.
(e.g., mesh management, voice, video, ordinary or opportunistic).
But the really important bit is to clone the frame, since the
structure we are looking at here must be left as is and returned
to the caller to do as they please */
overlay_frame *qf=op_dup(f);
if (!qf) WHY("Could not clone frame for queuing");
else {
int qn=OQ_ORDINARY;
/* Make sure voice traffic gets priority */
if ((qf->type&OF_TYPE_BITS)==OF_TYPE_DATA_VOICE) {
qn=OQ_ISOCHRONOUS_VOICE;
rhizome_saw_voice_traffic();
}
if (!dontForward) {
/* Queue frame for dispatch.
Don't forget to put packet in the correct queue based on type.
(e.g., mesh management, voice, video, ordinary or opportunistic).
But the really important bit is to clone the frame, since the
structure we are looking at here must be left as is and returned
to the caller to do as they please */
overlay_frame *qf=op_dup(f);
if (!qf) WHY("Could not clone frame for queuing");
else {
int qn=OQ_ORDINARY;
/* Make sure voice traffic gets priority */
if ((qf->type&OF_TYPE_BITS)==OF_TYPE_DATA_VOICE) {
qn=OQ_ISOCHRONOUS_VOICE;
rhizome_saw_voice_traffic();
}
if (0) WHY("queuing frame for forwarding");
if (overlay_payload_enqueue(qn,qf,0)) {
WHY("failed to enqueue forwarded payload");
op_free(qf);
}
if (0) WHY("queuing frame for forwarding");
if (overlay_payload_enqueue(qn,qf,0)) {
WHY("failed to enqueue forwarded payload");
op_free(qf);
}
}
/* If the frame was a broadcast frame, then we need to hang around
so that we can process it, since we are one of the recipients.
Otherwise, return triumphant. */
if (!broadcast) RETURN(0);
}
}
int id = (interface - overlay_interfaces);
switch(f->type)
{
case OF_TYPE_SELFANNOUNCE:
overlay_route_saw_selfannounce(f,now);
break;
case OF_TYPE_SELFANNOUNCE_ACK:
overlay_route_saw_selfannounce_ack(f,now);
break;
case OF_TYPE_NODEANNOUNCE:
overlay_route_saw_advertisements(id,f,now);
break;
case OF_TYPE_RHIZOME_ADVERT:
overlay_rhizome_saw_advertisements(id,f,now);
break;
case OF_TYPE_DATA:
case OF_TYPE_DATA_VOICE:
if (0) {
DEBUG("saw mdp containing frame");
DEBUGF(" src = %s\n", alloca_tohex_sid(f->source));
DEBUGF(" nxt = %s\n", alloca_tohex_sid(f->nexthop));
DEBUGF(" dst = %s\n", alloca_tohex_sid(f->destination));
dump("payload", f->payload->bytes, f->payload->length);
// process payloads with broadcast or our sid as destination
if (ultimatelyForMe){
int id = (interface - overlay_interfaces);
switch(f->type)
{
case OF_TYPE_SELFANNOUNCE:
overlay_route_saw_selfannounce(f,now);
break;
case OF_TYPE_SELFANNOUNCE_ACK:
overlay_route_saw_selfannounce_ack(f,now);
break;
case OF_TYPE_NODEANNOUNCE:
overlay_route_saw_advertisements(id,f,now);
break;
case OF_TYPE_RHIZOME_ADVERT:
overlay_rhizome_saw_advertisements(id,f,now);
break;
case OF_TYPE_DATA:
case OF_TYPE_DATA_VOICE:
if (0) {
DEBUG("saw mdp containing frame");
DEBUGF(" src = %s\n", alloca_tohex_sid(f->source));
DEBUGF(" nxt = %s\n", alloca_tohex_sid(f->nexthop));
DEBUGF(" dst = %s\n", alloca_tohex_sid(f->destination));
dump("payload", f->payload->bytes, f->payload->length);
}
overlay_saw_mdp_containing_frame(f,now);
break;
default:
DEBUGF("Unsupported f->type=0x%x",f->type);
RETURN(WHY("Support for that f->type not yet implemented"));
break;
}
overlay_saw_mdp_containing_frame(f,now);
break;
default:
DEBUGF("Unsupported f->type=0x%x",f->type);
RETURN(WHY("Support for that f->type not yet implemented"));
break;
}
}
RETURN(0);
}

View File

@ -173,7 +173,7 @@ int overlay_abbreviate_cache_address(unsigned char *sid)
/* Work out the index in the cache where this address would go.
The XOR 1 is to make sure that all zeroes address doesn't live in index 0,
which would otherwise result in it being detected as already present. */
int index=(((sid[0]<<16)|(sid[0]<<8)|sid[2])>>cache->shift)^1;
int index=(((sid[0]<<16)|(sid[1]<<8)|sid[2])>>cache->shift)^1;
/* Does the stored address match the one we have been passed? */
if (!memcmp(sid,&cache->sids[index].b[0],SID_SIZE))
@ -183,10 +183,7 @@ int overlay_abbreviate_cache_address(unsigned char *sid)
/* Not yet in cache, so store it */
bcopy(sid,&cache->sids[index].b[0],SID_SIZE);
if (debug&DEBUG_OVERLAYABBREVIATIONS) {
fprintf(stderr,"Cached address ");
int i;
for(i=0;i<SID_SIZE;i++) fprintf(stderr,"%02x",cache->sids[index].b[i]);
fprintf(stderr,"\n");
DEBUGF("Cached address %s", alloca_tohex_sid(sid));
}
return 0;
@ -235,6 +232,7 @@ int overlay_abbreviate_append_address(overlay_buffer *b,unsigned char *a)
}
if (r) return r;
b->length+=count;
overlay_abbreviate_set_most_recent_address(a);
return 0;
}
@ -246,11 +244,25 @@ int overlay_abbreviate_address(unsigned char *in,unsigned char *out,int *ofs)
if (!in) return WHY("in==NULL");
if (in[0]<0x10) return WHY("Invalid address - 0x00-0x0f are reserved prefixes.");
/* Is this the same as the current sender? */
if (overlay_abbreviate_current_sender_set){
for(i=0;i<SID_SIZE;i++)
if (in[i]!=overlay_abbreviate_current_sender.b[i])
break;
if (i==SID_SIZE) {
out[(*ofs)++]=OA_CODE_SELF;
return 0;
}
}
/* Try repeating previous address */
for(i=0;i<SID_SIZE;i++) if (in[i]!=overlay_abbreviate_previous_address.b[i]) break;
for(i=0;i<SID_SIZE;i++)
if (in[i]!=overlay_abbreviate_previous_address.b[i])
break;
if (i==SID_SIZE) {
out[(*ofs)++]=OA_CODE_PREVIOUS;
return 0; }
return 0;
}
/* Is it a broadcast address? */
if (overlay_address_is_broadcast(in)) {
@ -332,7 +344,8 @@ int overlay_abbreviate_address(unsigned char *in,unsigned char *out,int *ofs)
int overlay_abbreviate_expand_address(unsigned char *in,int *inofs,unsigned char *out,int *ofs)
{
int bytes=0,r;
if (debug&DEBUG_OVERLAYABBREVIATIONS) DEBUGF("Address first byte/abbreviation code=%02x (input offset=%d)\n",in[*inofs],*inofs);
if (debug&DEBUG_OVERLAYABBREVIATIONS)
DEBUGF("Address first byte/abbreviation code=%02x (input offset=%d)\n",in[*inofs],*inofs);
switch(in[*inofs])
{
case OA_CODE_02: case OA_CODE_04: case OA_CODE_0C:
@ -352,7 +365,7 @@ int overlay_abbreviate_expand_address(unsigned char *in,int *inofs,unsigned char
(*ofs)+=SID_SIZE;
return OA_RESOLVED;
} else {
if (debug&DEBUG_OVERLAYABBREVIATIONS) DEBUGF("Cannot resolve OA_CODE_SELF until we can resolve sender's address.\n");
WARN("Cannot resolve OA_CODE_SELF if the packet doesn't start with a self announcement.\n");
return OA_UNINITIALISED;
}
case OA_CODE_INDEX: /* single byte index look up */
@ -361,7 +374,8 @@ int overlay_abbreviate_expand_address(unsigned char *in,int *inofs,unsigned char
r=overlay_abbreviate_cache_lookup(overlay_neighbours[overlay_abbreviate_current_sender_id].one_byte_index_address_prefixes[in[*inofs]],
out,ofs,OVERLAY_SENDER_PREFIX_LENGTH,0);
(*inofs)++;
overlay_abbreviate_set_most_recent_address(&out[*ofs]);
if (r==OA_RESOLVED)
overlay_abbreviate_set_most_recent_address(&out[*ofs]);
(*inofs)++;
return r;
case OA_CODE_PREVIOUS: /* Same as last address */
@ -374,13 +388,15 @@ int overlay_abbreviate_expand_address(unsigned char *in,int *inofs,unsigned char
if (in[*inofs]==0x09) bytes=1;
r=overlay_abbreviate_cache_lookup(&in[(*inofs)+1],out,ofs,3,bytes);
(*inofs)+=1+3+bytes;
overlay_abbreviate_set_most_recent_address(&out[(*ofs)-SID_SIZE]);
if (r==OA_RESOLVED)
overlay_abbreviate_set_most_recent_address(&out[(*ofs)-SID_SIZE]);
return r;
case OA_CODE_PREFIX7: case OA_CODE_PREFIX7_INDEX1: /* 7-byte prefix */
if (in[*inofs]==OA_CODE_PREFIX7_INDEX1) bytes=1;
r=overlay_abbreviate_cache_lookup(&in[(*inofs)+1],out,ofs,7,bytes);
(*inofs)+=1+7+bytes;
overlay_abbreviate_set_most_recent_address(&out[(*ofs)-SID_SIZE]);
if (r==OA_RESOLVED)
overlay_abbreviate_set_most_recent_address(&out[(*ofs)-SID_SIZE]);
return r;
case OA_CODE_PREFIX11: case OA_CODE_PREFIX11_INDEX1: case OA_CODE_PREFIX11_INDEX2: /* 11-byte prefix */
bytes=0;
@ -388,7 +404,8 @@ int overlay_abbreviate_expand_address(unsigned char *in,int *inofs,unsigned char
if (in[*inofs]==OA_CODE_PREFIX11_INDEX2) bytes=2;
r=overlay_abbreviate_cache_lookup(&in[(*inofs)+1],out,ofs,11,bytes);
(*inofs)+=1+11+bytes;
overlay_abbreviate_set_most_recent_address(&out[(*ofs)-SID_SIZE]);
if (r==OA_RESOLVED)
overlay_abbreviate_set_most_recent_address(&out[(*ofs)-SID_SIZE]);
return r;
case OA_CODE_BROADCAST: /* broadcast */
memset(&out[*ofs],0xff,SID_SIZE-8);
@ -396,7 +413,7 @@ int overlay_abbreviate_expand_address(unsigned char *in,int *inofs,unsigned char
/* Copy Broadcast Packet Identifier */
{ int i; for(i=0;i<8;i++) out[(*ofs)+24+i]=in[(*inofs)+i]; }
if (debug&DEBUG_BROADCASTS)
fprintf(stderr,"Expanded broadcast address with "
DEBUGF("Expanded broadcast address with "
"BPI=%02X%02X%02X%02X%02X%02X%02X%02X\n",
in[(*inofs)+0],in[(*inofs)+1],in[(*inofs)+2],in[(*inofs)+3],
in[(*inofs)+4],in[(*inofs)+5],in[(*inofs)+6],in[(*inofs)+7]);
@ -411,7 +428,7 @@ int overlay_abbreviate_expand_address(unsigned char *in,int *inofs,unsigned char
bcopy(&in[*inofs],&out[*ofs],SID_SIZE);
if (bytes) overlay_abbreviate_remember_index(bytes,&in[*inofs],&in[(*inofs)+SID_SIZE]);
overlay_abbreviate_cache_address(&in[*inofs]);
overlay_abbreviate_set_most_recent_address(&out[*ofs]);
overlay_abbreviate_set_most_recent_address(&in[*inofs]);
(*inofs)+=SID_SIZE+bytes;
return OA_RESOLVED;
}
@ -419,6 +436,8 @@ int overlay_abbreviate_expand_address(unsigned char *in,int *inofs,unsigned char
int overlay_abbreviate_lookup_sender_id()
{
if (!overlay_abbreviate_current_sender_set)
return WHY("Sender has not been set");
overlay_neighbour *neh=overlay_route_get_neighbour_structure(overlay_abbreviate_current_sender.b,SID_SIZE,1 /* create if needed */);
if (!neh) { overlay_abbreviate_current_sender_id=-1; return WHY("Could not find sender in neighbour list"); }
/* Okay, so the following is a little tortuous in asking our parent who we are instead of just knowing,
@ -457,7 +476,7 @@ int overlay_abbreviate_cache_lookup(unsigned char *in,unsigned char *out,int *of
if (!cache) return OA_PLEASEEXPLAIN; /* No cache? Then ask for address in full */
/* Work out the index in the cache where this address would live */
int index=(((in[0]<<16)|(in[0]<<8)|in[2])>>cache->shift)^1;
int index=(((in[0]<<16)|(in[1]<<8)|in[2])>>cache->shift)^1;
int i;
if (debug&DEBUG_OVERLAYABBREVIATIONS) {
@ -469,7 +488,7 @@ int overlay_abbreviate_cache_lookup(unsigned char *in,unsigned char *out,int *of
if (in[0]<0x10) {
/* Illegal address */
if (debug&DEBUG_OVERLAYABBREVIATIONS)
fprintf(stderr,"Passed an illegal address (first byte <0x10)\n");
DEBUGF("Passed an illegal address (first byte <0x10)");
return OA_UNSUPPORTED;
}
@ -488,7 +507,7 @@ int overlay_abbreviate_cache_lookup(unsigned char *in,unsigned char *out,int *of
->keypairs[kp]->public_key,prefix_bytes))
{
if (debug&DEBUG_OVERLAYABBREVIATIONS)
WHY("Found reference to local address.");
DEBUG("Found reference to local address.");
bcopy(&keyring->contexts[cn]->identities[id]
->keypairs[kp]->public_key[0],&out[(*ofs)],SID_SIZE);
(*ofs)+=SID_SIZE;
@ -497,7 +516,7 @@ int overlay_abbreviate_cache_lookup(unsigned char *in,unsigned char *out,int *of
}
if (debug&DEBUG_OVERLAYABBREVIATIONS)
WHY("Encountered unresolvable address -- are we asking for explanation?");
DEBUG("Encountered unresolvable address -- are we asking for explanation?");
return OA_PLEASEEXPLAIN;
}
@ -505,11 +524,9 @@ int overlay_abbreviate_cache_lookup(unsigned char *in,unsigned char *out,int *of
colliding prefixes and ask the sender to resolve them for us, or better yet dynamically
size the prefix length based on whether any given short prefix has collided */
if (debug&DEBUG_OVERLAYABBREVIATIONS) {
/* It is here, so let's return it */
fprintf(stderr,"I think I looked up the following: ");
for(i=0;i<SID_SIZE;i++) fprintf(stderr,"%02x",cache->sids[index].b[i]);
fprintf(stderr,"\n");
/* It is here, so let's return it */
if (debug&DEBUG_OVERLAYABBREVIATIONS) {
DEBUGF("I think I looked up the following: %s", alloca_tohex_sid(cache->sids[index].b));
}
bcopy(&cache->sids[index].b[0],&out[(*ofs)],SID_SIZE);

View File

@ -101,7 +101,9 @@ int overlay_route_add_advertisements(overlay_buffer *e)
ob_append_byte(e,OA_CODE_BROADCAST);
for(i=0;i<8;i++) ob_append_byte(e,random()&0xff); /* random BPI */
ob_append_byte(e,OA_CODE_PREVIOUS);
ob_append_byte(e,OA_CODE_SELF);
overlay_abbreviate_clear_most_recent_address();
overlay_abbreviate_append_address(e, overlay_get_my_sid());
while (slots>0&&oad_request_count) {
oad_request_count--;
@ -195,32 +197,41 @@ int overlay_route_saw_advertisements(int i,overlay_frame *f, long long now)
=overlay_abbreviate_cache_lookup(&f->payload->bytes[ofs],to,&out_len,
6 /* prefix length */,
0 /* no index code to process */);
if (r==OA_PLEASEEXPLAIN) {
/* Unresolved address -- TODO ask someone to resolve it for us. */
WARN("Dispatch PLEASEEXPLAIN not implemented");
goto next;
}
int score=f->payload->bytes[6];
int gateways_en_route=f->payload->bytes[7];
/* Don't record routes to ourselves */
if (overlay_address_is_local(to)) {
if (debug & DEBUG_OVERLAYROUTING)
DEBUGF("Ignore announcement about me (%s)", alloca_tohex_sid(to));
goto next;
}
/* Don't let nodes advertise paths to themselves!
(paths to self get detected through selfannouncements and selfannouncement acks) */
if (memcmp(&overlay_abbreviate_current_sender.b[0],to,SID_SIZE))
{
/* Discount score by score to sender */
score*=sender_score;
score=score>>8;
if (r==OA_RESOLVED) {
/* File it */
overlay_route_record_link(now,to,&overlay_abbreviate_current_sender.b[0],
i,
/* time range that this advertisement covers.
XXX - Make it up for now. */
now-2500,now,
score,gateways_en_route);
} else if (r==OA_PLEASEEXPLAIN) {
/* Unresolved address -- ask someone to resolve it for us. */
WARN("Dispatch PLEASEEXPLAIN not implemented");
}
}
if (!memcmp(&overlay_abbreviate_current_sender.b[0],to,SID_SIZE)){
if (debug & DEBUG_OVERLAYROUTING)
DEBUGF("Ignore announcement about neighbour (%s)", alloca_tohex_sid(to));
goto next;
}
if (r==OA_RESOLVED) {
/* File it */
overlay_route_record_link(now,to,&overlay_abbreviate_current_sender.b[0],
i,
/* time range that this advertisement covers.
XXX - Make it up for now. */
now-2500,now,
score,gateways_en_route);
}
next:
ofs+=8;
}

View File

@ -365,7 +365,8 @@ void overlay_interface_poll(struct sched_ent *alarm)
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");
serval_packetvisualise(open_logging(), "Malformed packet", packet,plen);
// Do we really want to attempt to parse it again?
//serval_packetvisualise(open_logging(), "Malformed packet", packet,plen);
}
}
}
@ -456,7 +457,7 @@ int overlay_broadcast_ensemble(int interface_number,
unsigned char *bytes,int len)
{
struct sockaddr_in s;
if (debug&DEBUG_PACKETTX)
{
DEBUGF("Sending this packet via interface #%d",interface_number);
@ -733,19 +734,20 @@ int overlay_queue_dump(overlay_txqueue *q)
}
int overlay_resolve_next_hop(overlay_frame *frame){
IN();
if (frame->nexthop_address_status==OA_RESOLVED)
return 0;
RETURN(0);
if (frame->isBroadcast)
bcopy(&frame->destination,&frame->nexthop,SID_SIZE);
else if (overlay_get_nexthop((unsigned char *)frame->destination,frame->nexthop,&frame->nexthop_interface)){
// TODO new code?
frame->nexthop_address_status=OA_UNSUPPORTED;
return -1;
RETURN(-1);
}
frame->nexthop_address_status=OA_RESOLVED;
return 0;
RETURN(0);
}
void overlay_init_packet(struct outgoing_packet *packet, int interface){
@ -754,6 +756,9 @@ void overlay_init_packet(struct outgoing_packet *packet, int interface){
packet->buffer=ob_new(packet->interface->mtu);
ob_limitsize(packet->buffer, packet->interface->mtu);
ob_append_bytes(packet->buffer,magic_header,4);
overlay_abbreviate_clear_most_recent_address();
overlay_abbreviate_unset_current_sender();
}
// update the alarm time and return 1 if changed
@ -908,6 +913,7 @@ int overlay_fill_send_packet(struct outgoing_packet *packet, long long now){
overlay_broadcast_ensemble(packet->i,NULL,packet->buffer->bytes,packet->buffer->length);
}
ob_free(packet->buffer);
overlay_abbreviate_clear_most_recent_address();
RETURN(1);
}
RETURN(0);
@ -925,7 +931,6 @@ void overlay_send_packet(struct sched_ent *alarm){
void overlay_update_queue_schedule(overlay_txqueue *queue, overlay_frame *frame){
if (overlay_calc_queue_time(queue, frame)){
unschedule(&next_packet);
DEBUGF("Scheduled next packet in %dms", next_packet.alarm - overlay_gettime_ms());
schedule(&next_packet);
}
}

View File

@ -922,7 +922,6 @@ int overlay_mdp_dispatch(overlay_mdp_frame *mdp,int userGeneratedFrameP,
overlay_frame_set_broadcast_as_destination(frame);
else{
bcopy(&mdp->out.dst.sid[0],frame->destination,SID_SIZE);
frame->destination_address_status=OA_RESOLVED;
}
int q=OQ_ORDINARY;

View File

@ -18,7 +18,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "serval.h"
#include "strbuf.h"
struct sockaddr_in loopback = {
.sin_family=0,
@ -101,9 +101,12 @@ int packetOkOverlay(struct overlay_interface *interface,unsigned char *packet, s
bzero(&f,sizeof(overlay_frame));
if (recvaddr->sa_family==AF_INET)
if (recvaddr->sa_family==AF_INET){
f.recvaddr=recvaddr;
else {
if (debug&DEBUG_OVERLAYFRAMES)
DEBUG("Received overlay packet");
} else {
if (interface->fileP) {
/* dummy interface, so tell to use 0.0.0.0 */
f.recvaddr=(struct sockaddr *)&loopback;
@ -114,21 +117,18 @@ int packetOkOverlay(struct overlay_interface *interface,unsigned char *packet, s
overlay_abbreviate_unset_current_sender();
// TODO put sender of packet and sequence number in envelope header
// Then we can quickly drop reflected broadcast packets
// currently we see annoying errors as we attempt to parse each payload
// plus with a sequence number we can detect dropped packets and nack them for retransmission
/* Skip magic bytes and version */
for(ofs=4;ofs<len;)
{
/* Clear out the data structure ready for next frame */
f.nexthop_address_status=OA_UNINITIALISED;
f.destination_address_status=OA_UNINITIALISED;
f.source_address_status=OA_UNINITIALISED;
/* Get normal form of packet type and modifiers */
f.type=packet[ofs]&OF_TYPE_BITS;
f.modifiers=packet[ofs]&OF_MODIFIER_BITS;
if (debug&DEBUG_PACKETFORMATS)
DEBUGF("f.type=0x%02x, f.modifiers=0x%02x, ofs=%d", f.type, f.modifiers, ofs);
switch(packet[ofs]&OF_TYPE_BITS)
{
case OF_TYPE_EXTENDED20:
@ -162,63 +162,124 @@ int packetOkOverlay(struct overlay_interface *interface,unsigned char *packet, s
break;
}
if (f.rfs > len - ofs)
return WHYF("Payload length %d is too long for the remaining packet buffer %d", f.rfs, len - ofs);
int payloadStart = ofs;
int nextPayload = ofs+f.rfs;
if (nextPayload > len){
WHYF("Payload length %d is too long for the remaining packet buffer %d", f.rfs, len - ofs);
break;
}
/* Always attempt to resolve all of the addresses in a packet, or we could fail to understand an important payload
eg, peer sends two payloads travelling in opposite directions;
[Next, Dest, Sender] forwarding a payload we just send, so Sender == Me
[Next, Dest, Sender] delivering a payload to us so Next == Me
But Next would be encoded as OA_CODE_PREVIOUS, so we must parse all three addresses,
even if Next is obviously not intended for us
*/
/* Now extract the next hop address */
int alen=0;
int offset=ofs;
f.nexthop_address_status=overlay_abbreviate_expand_address(packet,&offset,f.nexthop,&alen);
if (debug&DEBUG_PACKETFORMATS) {
if (f.nexthop_address_status==OA_RESOLVED)
DEBUGF("next hop address is %s", alloca_tohex_sid(f.nexthop));
int nexthop_address_status=overlay_abbreviate_expand_address(packet,&ofs,f.nexthop,&alen);
if (ofs>nextPayload){
WARN("Next hop address didn't fit in payload");
break;
}
/* Now just make the rest of the frame available via the received frame structure, as the
frame may not be for us, so there is no point wasting time and energy if we don't have
to.
*/
f.bytes=&packet[offset];
f.bytecount=f.rfs-(offset-ofs);
if (f.bytecount<0) {
f.bytecount=0;
if (debug&DEBUG_PACKETFORMATS) DEBUGF("f.rfs=%02x, offset=%02x, ofs=%02x", f.rfs, offset, ofs);
return WHY("negative residual byte count after extracting addresses from frame header");
}
/* Finally process the frame */
overlay_frame_process(interface,&f);
/* Skip the rest of the bytes in this frame so that we can examine the next one in this
ensemble */
if (debug&DEBUG_PACKETFORMATS) DEBUGF("next ofs=%d, f.rfs=%d, len=%d", ofs, f.rfs, len);
ofs+=f.rfs;
alen=0;
int destination_address_status=overlay_abbreviate_expand_address(packet,&ofs,f.destination,&alen);
if (ofs>nextPayload){
WARN("Destination address didn't fit in payload");
break;
}
alen=0;
int source_address_status=overlay_abbreviate_expand_address(packet,&ofs,f.source,&alen);
if (ofs>nextPayload){
WARN("Source address didn't fit in payload");
break;
}
// TODO respond with OA_PLEASEEXPLAIN's?
if (debug&DEBUG_OVERLAYFRAMES) {
DEBUGF("Type=0x%02x", f.type);
strbuf b = strbuf_alloca(1024);
strbuf_sprintf(b, "Next Hop for this frame is (resolve code=%d): ", nexthop_address_status);
if (nexthop_address_status==OA_RESOLVED)
strbuf_sprintf(b, "%s", alloca_tohex_sid(f.nexthop));
else
strbuf_puts(b, "???");
DEBUG(strbuf_str(b));
strbuf_reset(b);
strbuf_sprintf(b, "Destination for this frame is (resolve code=%d): ", destination_address_status);
if (destination_address_status==OA_RESOLVED)
strbuf_sprintf(b, "%s", alloca_tohex_sid(f.destination));
else
strbuf_puts(b, "???");
DEBUG(strbuf_str(b));
strbuf_reset(b);
strbuf_sprintf(b, "Source for this frame is (resolve code=%d): ", source_address_status);
if (source_address_status==OA_RESOLVED)
strbuf_sprintf(b, "%s", alloca_tohex_sid(f.source));
else
strbuf_puts(b, "???");
DEBUG(strbuf_str(b));
}
if (f.nexthop[0]==0 || f.destination[0]==0 || f.source[0]==0){
WHY("Addresses expanded incorrectly");
dump("Addresses expanded incorrectly", &packet[payloadStart], ofs - payloadStart);
break;
}
if (nexthop_address_status!=OA_RESOLVED
|| destination_address_status!=OA_RESOLVED
|| source_address_status!=OA_RESOLVED){
WARN("Unable to resolve all payload addresses");
// we have to stop now as we can't be certain about the destination of any other payloads in this packet.
break;
}
/* not that noteworthy, as when listening to a broadcast socket
you hear everything you send. */
if (overlay_address_is_local(f.source)){
// skip the remainder of any packet that we know we sent
// TODO add our id to the header
if (f.type==OF_TYPE_SELFANNOUNCE)
break;
}else{
// TODO refactor all packet parsing to only allocate additional memory for the payload
// if it needs to be queued for forwarding.
if (!f.payload)
f.payload=ob_new(nextPayload - ofs);
else
f.payload->length=0;
if (!f.payload){
WHY("calloc(overlay_buffer) failed.");
break;
}
if (ob_append_bytes(f.payload,&packet[ofs],nextPayload - ofs)){
WHY("ob_append_bytes() failed.");
break;
}
/* Finally process the frame */
overlay_frame_process(interface,&f);
}
/* Jump to the next payload offset */
ofs = nextPayload;
}
if (0) INFOF("Finished processing overlay packet");
return 0;
}
int overlay_frame_resolve_addresses(overlay_frame *f)
{
/* Get destination and source addresses and set pointers to payload appropriately */
int alen=0;
int offset=0;
overlay_abbreviate_set_most_recent_address(f->nexthop);
f->destination_address_status=overlay_abbreviate_expand_address(f->bytes,&offset,f->destination,&alen);
alen=0;
f->source_address_status=overlay_abbreviate_expand_address(f->bytes,&offset,f->source,&alen);
if (debug&DEBUG_OVERLAYABBREVIATIONS)
DEBUGF("Wrote %d bytes into source address: %s", alen, alloca_tohex(f->source, alen));
/* Copy payload into overlay_buffer structure */
if (f->bytecount-offset<0) return WHY("Abbreviated ddresses run past end of packet");
if (!f->payload) f->payload=ob_new(f->bytecount-offset); else f->payload->length=0;
if (!f->payload) return WHY("calloc(overlay_buffer) failed.");
if (ob_append_bytes(f->payload,&f->bytes[offset],f->bytecount-offset))
return WHY("ob_append_bytes() failed.");
if (f.payload)
ob_free(f.payload);
return 0;
}
@ -307,7 +368,9 @@ int overlay_add_selfannouncement(int interface,overlay_buffer *b)
}
/* Make note that this is the most recent address we have set */
overlay_abbreviate_set_most_recent_address(sid);
/* And the sender for any other addresses in this packet */
overlay_abbreviate_set_current_sender(sid);
/* Sequence number range. Based on one tick per milli-second. */
if (ob_append_int(b,overlay_interfaces[interface].last_tick_ms))

View File

@ -148,11 +148,8 @@ int overlay_frame_package_fmt1(overlay_frame *p,overlay_buffer *b)
/* Write out addresses as abbreviated as possible */
overlay_abbreviate_append_address(headers,p->nexthop);
overlay_abbreviate_set_most_recent_address(p->nexthop);
overlay_abbreviate_append_address(headers,p->destination);
overlay_abbreviate_set_most_recent_address(p->destination);
overlay_abbreviate_append_address(headers,p->source);
overlay_abbreviate_set_most_recent_address(p->source);
int addrs_len=headers->length-addrs_start;
int actual_len=addrs_len+p->payload->length;
@ -332,8 +329,6 @@ int overlay_frame_set_neighbour_as_source(overlay_frame *f,overlay_neighbour *n)
{
if (!n) return WHY("Neighbour was null");
bcopy(n->node->sid,f->source,SID_SIZE);
f->source_address_status=OA_RESOLVED;
return 0;
}
@ -341,16 +336,12 @@ int overlay_frame_set_neighbour_as_destination(overlay_frame *f,overlay_neighbou
{
if (!n) return WHY("Neighbour was null");
bcopy(n->node->sid,f->destination,SID_SIZE);
f->destination_address_status=OA_RESOLVED;
return 0;
}
int overlay_frame_set_broadcast_as_destination(overlay_frame *f)
{
overlay_broadcast_generate_address(f->destination);
f->destination_address_status=OA_RESOLVED;
return 0;
}
@ -378,8 +369,5 @@ int overlay_frame_set_me_as_source(overlay_frame *f)
unsigned char *sid=overlay_get_my_sid();
if (!sid) return WHY("overlay_get_my_sid() failed.");
bcopy(sid,f->source,SID_SIZE);
f->source_address_status=OA_RESOLVED;
return 0;
}

View File

@ -367,6 +367,12 @@ int overlay_get_nexthop(unsigned char *d,unsigned char *nexthop,int *interface)
{
int i;
if (*d==0){
if (debug&DEBUG_OVERLAYROUTING)
DEBUGF("No open path to %s, invalid sid",alloca_tohex_sid(d));
return -1;
}
if (overlay_broadcast_drop_check(d)) return WHY("I have sent that broadcast frame before");
if (overlay_address_is_broadcast(d)) {
bcopy(&d[0],&nexthop[0],SID_SIZE);
@ -375,65 +381,71 @@ int overlay_get_nexthop(unsigned char *d,unsigned char *nexthop,int *interface)
if (!overlay_neighbours) return WHY("I have no neighbours");
overlay_neighbour *direct_neighbour=overlay_route_get_neighbour_structure(d,SID_SIZE,
0 /* don't create if
missing */);
if (direct_neighbour) {
overlay_node *n=overlay_route_find_node(d,SID_SIZE,0 /* don't create if missing */ );
if (!n){
if (debug&DEBUG_OVERLAYROUTING)
DEBUGF("No open path to %s, unknown peer",alloca_tohex_sid(d));
return -1;
}
long long now = overlay_gettime_ms();
overlay_neighbour *direct_neighbour=NULL;
if (n->neighbour_id){
direct_neighbour = &overlay_neighbours[n->neighbour_id];
overlay_route_recalc_neighbour_metrics(direct_neighbour, now);
/* Is a direct neighbour.
So in the absence of any better indirect route, we pick the interface that
we can hear this neighbour on the most reliably, and then send the frame
via that interface and directly addressed to the recipient. */
bcopy(d,nexthop,SID_SIZE);
*interface=0;
for(i=1;i<OVERLAY_MAX_INTERFACES;i++) {
if (direct_neighbour->scores[i]>direct_neighbour->scores[*interface]) *interface=i;
}
if (direct_neighbour->scores[*interface]>0) {
if (0) DEBUGF("nexthop is %s",alloca_tohex_sid(nexthop));
return 0;
bcopy(d,nexthop,SID_SIZE);
if (0) DEBUGF("nexthop is %s",alloca_tohex_sid(nexthop));
return 0;
}
// otherwise fall through
}
{
/* Is not a direct neighbour.
XXX - Very simplistic for now. */
overlay_node *n=overlay_route_find_node(d,SID_SIZE,0 /* don't create if missing */ );
if (n) {
int o;
int best_score=0;
int best_o=-1;
for(o=0;o<OVERLAY_MAX_OBSERVATIONS;o++) {
int score=n->observations[o].observed_score;
overlay_neighbour *neighbour
=overlay_route_get_neighbour_structure
(n->observations[o].sender_prefix,OVERLAY_SENDER_PREFIX_LENGTH,0);
if (neighbour && neighbour!=direct_neighbour) {
for(i=1;i<OVERLAY_MAX_INTERFACES;i++) {
if (neighbour->scores[i]*score>best_score) {
bcopy(&neighbour->node->sid[0],&nexthop[0],SID_SIZE);
*interface=i;
best_o=o;
best_score=score;
}
}
/* Is not a direct neighbour.
XXX - Very simplistic for now. */
int o;
int best_score=0;
int best_o=-1;
for(o=0;o<OVERLAY_MAX_OBSERVATIONS;o++) {
int score=n->observations[o].observed_score;
if (!score)
continue;
overlay_neighbour *neighbour
=overlay_route_get_neighbour_structure
(n->observations[o].sender_prefix,OVERLAY_SENDER_PREFIX_LENGTH,0);
if (neighbour && neighbour!=direct_neighbour) {
overlay_route_recalc_neighbour_metrics(neighbour, now);
for(i=1;i<OVERLAY_MAX_INTERFACES;i++) {
if (neighbour->scores[i]*score>best_score) {
bcopy(&neighbour->node->sid[0],&nexthop[0],SID_SIZE);
*interface=i;
best_o=o;
best_score=score;
}
}
if (best_o>-1) {
return 0;
} else {
if (1||debug&DEBUG_OVERLAYROUTING)
DEBUGF("No open path to %s, no good neighbour observations",alloca_tohex_sid(d));
return -1;
}
} else {
if (1||debug&DEBUG_OVERLAYROUTING)
DEBUGF("No open path to %s, unknown peer",alloca_tohex_sid(d));
return -1;
}
}
if (best_o>-1) {
return 0;
} else {
if (debug&DEBUG_OVERLAYROUTING)
DEBUGF("No open path to %s, no good neighbour observations",alloca_tohex_sid(d));
return -1;
}
}
unsigned int overlay_route_hash_sid(const unsigned char *sid)
@ -451,20 +463,19 @@ unsigned int overlay_route_hash_sid(const unsigned char *sid)
/* Mask out extranous bits to return only a valid bin number */
bin&=(overlay_bin_count-1);
if (debug&DEBUG_OVERLAYROUTING) {
if (debug&DEBUG_OVERLAYROUTING)
DEBUGF("Address %s resolves to bin #%d", alloca_tohex_sid(sid), bin);
int zeroes=0;
for (i=0;i<SID_SIZE;i++)
if (!sid[i])
zeroes++;
if (zeroes>8)
DEBUG("Looks like corrupt memory or packet!");
}
return bin;
}
overlay_node *overlay_route_find_node(const unsigned char *sid, int prefixLen, int createP)
{
if (*sid==0 || prefixLen<overlay_route_hash_bytes){
INFOF("Sid %s/%d cannot ever become a node!", alloca_tohex_sid(sid), prefixLen);
return NULL;
}
int bin_number = overlay_route_hash_sid(sid);
if (bin_number < 0) {
WHY("negative bin number");
@ -472,15 +483,24 @@ overlay_node *overlay_route_find_node(const unsigned char *sid, int prefixLen, i
}
int free_slot = -1;
overlay_node *found=NULL;
{
int slot;
for (slot = 0; slot < overlay_bin_size; slot++)
if (memcmp(sid, overlay_nodes[bin_number][slot].sid, prefixLen) == 0)
return &overlay_nodes[bin_number][slot];
else if (overlay_nodes[bin_number][slot].sid[0]==0)
if (overlay_nodes[bin_number][slot].sid[0]==0)
free_slot = slot;
else if (memcmp(sid, overlay_nodes[bin_number][slot].sid, prefixLen) == 0){
if (found){
INFOF("SID prefix %d %s is not unique", prefixLen, alloca_tohex_sid(sid));
return NULL;
}
found = &overlay_nodes[bin_number][slot];
}
}
if (found)
return found;
/* Didn't find it */
if (!createP) return NULL;
@ -565,10 +585,7 @@ int overlay_route_ack_selfannounce(overlay_frame *f,
has not yet begun to be built), then we need to set the nexthop to broadcast. */
out->nexthop_address_status=OA_UNINITIALISED;
{
unsigned char nexthop[SID_SIZE];
int next_hop_interface=-1;
int r=overlay_get_nexthop(out->destination,nexthop,&next_hop_interface);
if (r) {
if (overlay_resolve_next_hop(out)) {
/* no open path, so convert to broadcast */
int i;
for(i=0;i<(SID_SIZE-8);i++) out->nexthop[i]=0xff;
@ -678,23 +695,31 @@ int overlay_route_make_neighbour(overlay_node *n)
overlay_neighbour *overlay_route_get_neighbour_structure(unsigned char *packed_sid,
int prefixLen,int createP)
{
IN();
if (overlay_address_is_local(packed_sid)) {
WHY("asked for neighbour structure for myself");
return NULL;
RETURN(NULL);
}
overlay_node *n=overlay_route_find_node(packed_sid,prefixLen,createP);
if (!n) {
// WHY("Could not find node record for observed node");
return NULL;
RETURN(NULL);
}
/* Check if node is already a neighbour, or if not, make it one */
if (!n->neighbour_id) if (overlay_route_make_neighbour(n)) { WHY("overlay_route_make_neighbour() failed"); return NULL; }
if (!n->neighbour_id){
if (!createP)
RETURN(NULL);
if (overlay_route_make_neighbour(n)) {
WHY("overlay_route_make_neighbour() failed");
RETURN(NULL);
}
}
/* Get neighbour structure */
return &overlay_neighbours[n->neighbour_id];
RETURN(&overlay_neighbours[n->neighbour_id]);
}
int overlay_route_i_can_hear_node(unsigned char *who,int sender_interface,
@ -715,44 +740,24 @@ int overlay_route_node_can_hear_me(unsigned char *who,int sender_interface,
2. Replace oldest observation with this observation.
3. Update score of how reliably we can hear this node */
/* Ignore traffic from ourselves. */
if (overlay_address_is_local(who))
{
DEBUGF("I can hear myself. How odd");
return 0;
}
/* Find node, or create entry if it hasn't been seen before */
overlay_node *n=overlay_route_find_node(who,SID_SIZE,1 /* create if necessary */);
if (!n) return WHY("Could not find node record for observed node");
/* Check if node is already a neighbour, or if not, make it one */
if (!n->neighbour_id) if (overlay_route_make_neighbour(n)) return WHY("overlay_route_make_neighbour() failed");
/* Get neighbour structure */
if (n->neighbour_id<0||n->neighbour_id>overlay_max_neighbours)
{ WHY("n->neighbour_id set to illegal value");
return -1;
}
overlay_neighbour *neh=&overlay_neighbours[n->neighbour_id];
overlay_neighbour *neh=overlay_route_get_neighbour_structure(who,SID_SIZE,1 /* create if necessary */);
if (!neh)
return -1;
int obs_index=neh->most_recent_observation_id;
int mergedP=0;
int merge=0;
/* See if this observation is contiguous with a previous one, if so, merge.
This not only reduces the number of observation slots we need, but dramatically speeds up
the scanning of recent observations when re-calculating observation scores. */
while (neh->observations[obs_index].valid&&(neh->observations[obs_index].s2>=(s1-1)))
while (neh->observations[obs_index].valid && (neh->observations[obs_index].s2>=(s1-1)))
{
if (neh->observations[obs_index].sender_interface==sender_interface)
{
if (0) DEBUGF("merging observation in slot #%d",obs_index);
if (!neh->observations[obs_index].s1)
neh->observations[obs_index].s1=neh->observations[obs_index].s2;
neh->observations[obs_index].s2=s2;
neh->observations[obs_index].sender_interface=sender_interface;
neh->observations[obs_index].time_ms=now;
mergedP=1;
if (debug&DEBUG_OVERLAYROUTING)
DEBUGF("merging observation in slot #%d",obs_index);
merge=1;
break;
}
@ -760,25 +765,28 @@ int overlay_route_node_can_hear_me(unsigned char *who,int sender_interface,
if (obs_index<0) obs_index=OVERLAY_MAX_OBSERVATIONS-1;
}
if (!mergedP) {
if (!merge) {
/* Replace oldest observation with this one */
obs_index=neh->most_recent_observation_id+1;
if (obs_index>=OVERLAY_MAX_OBSERVATIONS) obs_index=0;
if (0) DEBUGF("storing observation in slot #%d",obs_index);
neh->observations[obs_index].valid=0;
neh->observations[obs_index].time_ms=now;
if (debug&DEBUG_OVERLAYROUTING)
DEBUGF("storing observation in slot #%d",obs_index);
neh->observations[obs_index].s1=s1;
neh->observations[obs_index].s2=s2;
neh->observations[obs_index].sender_interface=sender_interface;
neh->observations[obs_index].valid=1;
}
neh->observations[obs_index].s2=s2;
neh->observations[obs_index].sender_interface=sender_interface;
neh->observations[obs_index].time_ms=now;
neh->observations[obs_index].valid=1;
neh->most_recent_observation_id=obs_index;
neh->last_observation_time_ms=now;
/* force updating of stats for neighbour if we have added an observation */
neh->last_metric_update=0;
/* Update reachability metrics for node */
if (overlay_route_recalc_neighbour_metrics(neh,now)) WHY("overlay_route_recalc_neighbour_metrics() failed");
if (overlay_route_recalc_neighbour_metrics(neh,now))
return -1;
if (debug&DEBUG_OVERLAYROUTEMONITOR) overlay_route_dump();
return 0;
@ -786,25 +794,20 @@ int overlay_route_node_can_hear_me(unsigned char *who,int sender_interface,
int overlay_route_saw_selfannounce(overlay_frame *f,long long now)
{
if (overlay_address_is_local(f->source)) return 0;
IN();
unsigned int s1,s2;
unsigned char sender_interface;
overlay_neighbour *n=overlay_route_get_neighbour_structure(f->source,SID_SIZE,
1 /* make neighbour if not yet one */);
if (!n) return WHY("overlay_route_get_neighbour_structure() failed");
if (!n){
RETURN(-1);
}
/* Record current sender for reference by addresses in subsequent frames in the
ensemble */
overlay_abbreviate_set_current_sender(f->source);
/* Ignore self announcements from ourselves */
if (overlay_address_is_local(f->source)) {
if(0) DEBUG("Ignoring selfannouncement from myself");
return 0;
}
s1=ntohl(*((int*)&f->payload->bytes[0]));
s2=ntohl(*((int*)&f->payload->bytes[4]));
sender_interface=f->payload->bytes[8];
@ -815,17 +818,9 @@ int overlay_route_saw_selfannounce(overlay_frame *f,long long now)
overlay_route_i_can_hear_node(f->source,sender_interface,s1,s2,now);
/* Ignore self-announcements from ourself. */
if (overlay_address_is_local(&f->source[0]))
{
// XXX But we should make note that we have loop-back to this interface
WHY("One or more interfaces loops back to this one, or someone is naughtily forwarding packets between interfaces.");
return 0;
}
overlay_route_ack_selfannounce(f,s1,s2,sender_interface,n);
return 0;
RETURN(0);
}
/* XXX Think about scheduling this node's score for readvertising? */
@ -908,9 +903,16 @@ int overlay_route_recalc_neighbour_metrics(overlay_neighbour *n,long long now)
int i;
long long most_recent_observation=0;
if (!n->node)
return 0;
if (debug&DEBUG_OVERLAYROUTING)
DEBUGF("Updating neighbour metrics for %s", alloca_tohex_sid(n->node->sid));
/* Only update every half-second */
if ((now-n->last_metric_update)<500) {
if (0) DEBUGF("refusing to update metric too often (last at %lldms, now=%lldms)",
if (debug&DEBUG_OVERLAYROUTING)
DEBUGF("refusing to update metric too often (last at %lldms, now=%lldms)",
n->last_metric_update,now);
return 0;
}
@ -939,7 +941,8 @@ int overlay_route_recalc_neighbour_metrics(overlay_neighbour *n,long long now)
/* Check the observation age, and ignore if too old */
int obs_age=now-n->observations[i].time_ms;
if (0) DEBUGF("tallying obs: %dms old, %dms long", obs_age,interval);
if (debug&DEBUG_OVERLAYROUTING)
DEBUGF("tallying obs: %dms old, %dms long", obs_age,interval);
if (obs_age>200000) continue;
/* Ignore very large intervals (>1hour) as being likely to be erroneous.
@ -950,7 +953,7 @@ int overlay_route_recalc_neighbour_metrics(overlay_neighbour *n,long long now)
on an expensive BGAN satellite link.
*/
if (interval<3600000) {
if (debug&DEBUG_VERBOSE_IO)
if (debug&DEBUG_OVERLAYROUTING)
DEBUGF("adding %dms (interface %d '%s')",
interval,n->observations[i].sender_interface,
overlay_interfaces[n->observations[i].sender_interface].name);
@ -959,8 +962,9 @@ int overlay_route_recalc_neighbour_metrics(overlay_neighbour *n,long long now)
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;
if (obs_age<=5000){
ms_observed_5sec[n->observations[i].sender_interface]+=(interval>5000?5000:interval);
}
}
else
{
@ -987,19 +991,19 @@ int overlay_route_recalc_neighbour_metrics(overlay_neighbour *n,long long now)
int contrib_200=ms_observed_200sec[i]/(200000/128);
int contrib_5=ms_observed_5sec[i]/(5000/128);
if (contrib_5<1) score=contrib_200/2; else
score=contrib_5+contrib_200;
if (contrib_5<1)
score=contrib_200/2;
else
score=contrib_5+contrib_200;
/* Deal with invalid sequence number ranges */
if (score<0) score=0; if (score>255) score=255;
if (score<1) score=1;
if (score>255) score=255;
}
/* Reduce score by 1 point for each second we have not seen anything from it */
score-=(now-most_recent_observation)/1000;
if (score<0) score=0;
n->scores[i]=score;
if ((debug&DEBUG_OVERLAYROUTING)&&score) DEBUGF("Neighbour score on interface #%d = %d (observations for %dms)",i,score,ms_observed_200sec[i]);
if ((debug&DEBUG_OVERLAYROUTING)&&score)
DEBUGF("Neighbour score on interface #%d = %d (observations for %dms)",i,score,ms_observed_200sec[i]);
}
return 0;
@ -1029,9 +1033,12 @@ int overlay_route_recalc_neighbour_metrics(overlay_neighbour *n,long long now)
*/
int overlay_route_saw_selfannounce_ack(overlay_frame *f,long long now)
{
if (0) DEBUGF("processing selfannounce ack (payload length=%d)",f->payload->length);
if (debug&DEBUG_OVERLAYROUTING)
DEBUGF("processing selfannounce ack (payload length=%d)",f->payload->length);
if (!overlay_neighbours) {
if (0) DEBUG("no neighbours, so returning immediately");
if (debug&DEBUG_OVERLAYROUTING)
DEBUG("no neighbours, so returning immediately");
return 0;
}
@ -1043,15 +1050,8 @@ int overlay_route_saw_selfannounce_ack(overlay_frame *f,long long now)
int iface=f->payload->bytes[8];
// Call something like the following for each link
if (f->source_address_status==OA_RESOLVED&&
f->destination_address_status==OA_RESOLVED) {
if (0) DEBUGF("f->source=%s, f->destination=%s",
alloca_tohex_sid(f->source),alloca_tohex_sid(f->destination));
overlay_route_record_link(now,f->source,f->source,iface,s1,s2,
0 /* no associated score */,
0 /* no gateways in between */);
} else WHY("address(es) not resolved");
overlay_route_node_can_hear_me(f->source,iface,s1,s2,now);
return 0;
}
@ -1068,25 +1068,9 @@ int overlay_route_record_link(long long now,unsigned char *to,
score, gateways_en_route
);
if (sender_interface>OVERLAY_MAX_INTERFACES) return 0;
/* Don't record routes to ourselves */
if (overlay_address_is_local(to)) {
if (sender_interface>OVERLAY_MAX_INTERFACES || score == 0) {
if (debug & DEBUG_OVERLAYROUTING)
DEBUGF("Ignore self announce ack addressed to me (%s)", alloca_tohex_sid(to));
return 0;
}
if (memcmp(to, via, SID_SIZE) == 0) {
/* It's a neighbour observation */
if (debug & DEBUG_OVERLAYROUTING)
DEBUGF("%s is my neighbour", alloca_tohex_sid(to));
overlay_route_node_can_hear_me(to,sender_interface,s1,s2,now);
}
if (score == 0) {
if (debug & DEBUG_OVERLAYROUTING)
DEBUG("non-scoring report");
DEBUG("invalid report");
return 0;
}
@ -1250,6 +1234,9 @@ void overlay_route_tick(struct sched_ent *alarm)
overlay_route_tick_node_bundle_size,overlay_route_tick_next_node_bin_id);
/* Go through some of neighbour list */
// TODO This doesn't seem to be reliable
// note that neighbour metrics are now re-calculated in overlay_get_nexthop when we need them
n=overlay_route_tick_neighbour_bundle_size;
if (n<1) n=1;
while(n--)
@ -1318,8 +1305,9 @@ void overlay_route_tick(struct sched_ent *alarm)
taking into account the age of the most recent observation */
int overlay_route_tick_neighbour(int neighbour_id,long long now)
{
if (overlay_route_recalc_neighbour_metrics(&overlay_neighbours[neighbour_id],now))
WHY("overlay_route_recalc_neighbour_metrics() failed");
if (neighbour_id>0)
if (overlay_route_recalc_neighbour_metrics(&overlay_neighbours[neighbour_id],now))
WHY("overlay_route_recalc_neighbour_metrics() failed");
return 0;
}

View File

@ -115,7 +115,8 @@ int overlay_rhizome_add_advertisements(int interface_number,overlay_buffer *e)
ob_append_byte(e,OA_CODE_BROADCAST);
{ int i; for(i=0;i<8;i++) ob_append_byte(e,random()&0xff); } /* BPI for broadcast */
ob_append_byte(e,OA_CODE_PREVIOUS);
ob_append_byte(e,OA_CODE_SELF);
overlay_abbreviate_clear_most_recent_address();
overlay_abbreviate_append_address(e, overlay_get_my_sid());
/* Randomly choose whether to advertise manifests or BARs first. */
int skipmanifests=random()&1;

View File

@ -445,19 +445,13 @@ typedef struct overlay_frame {
int nexthop_interface; /* which interface the next hop should be attempted on */
unsigned char destination[32];
int destination_address_status;
unsigned char source[32];
int source_address_status;
/* IPv4 node frame was received from (if applicable) */
struct sockaddr *recvaddr;
/* Frame content from destination address onwards */
int bytecount;
unsigned char *bytes;
/* Actual payload */
// TODO refactor *all* packet parsing so that the payload is not copied or allocated unless it must be forwarded.
struct overlay_buffer *payload;
int rfs; /* remainder of frame size */