diff --git a/hlrdata.c b/hlrdata.c index ddf742e4..67da27e1 100644 --- a/hlrdata.c +++ b/hlrdata.c @@ -369,7 +369,7 @@ int hlrSetVariable(unsigned char *hlr,int hofs,int varid,int varinstance, if (debug>1) fprintf(stderr,"h->var_id=%02x, h->h->var_instance=%02x, h->entry_offset=%x\n", h->var_id,h->var_instance,h->entry_offset); if ((h->var_idvar_id==varid&&h->var_instancevar_id&0x80)&&(h->var_id==varid&&h->var_instanceentry_offset; if (debug>1) fprintf(stderr,"Found variable instance prior: hlr_offset=%d.\n",hlr_offset); @@ -390,19 +390,19 @@ int hlrSetVariable(unsigned char *hlr,int hofs,int varid,int varinstance, if (h&&hlr_offset>-1) { if (debug>2) printf("hlr_offset=%d\n",hlr_offset); - if (h&&h->var_id==varid&&h->var_instance==varinstance) + if (h&&h->var_id==varid&&((h->var_instance==varinstance)||(!(h->var_id&0x80)))) { - int existing_size; + int existing_size; /* Replace existing value */ - if (debug) fprintf(stderr,"Replacing value in HLR\n"); - existing_size=1+2+(h->var_id&0x80?1:0)+h->value_len; - hlrMakeSpace(hlr,hofs,hlr_offset,1+2+len+(varid&0x80?1:0)-existing_size); + if (debug) fprintf(stderr,"Replacing value in HLR:\n"); + existing_size=1+2+((h->var_id&0x80)?1:0)+h->value_len; + hlrMakeSpace(hlr,hofs,hlr_offset,1+2+len+((varid&0x80)?1:0)-existing_size); } else { /* Insert value here */ if (debug) fprintf(stderr,"Inserting value in HLR\n"); - hlrMakeSpace(hlr,hofs,hlr_offset,1+2+len+(varid&0x80?1:0)); + hlrMakeSpace(hlr,hofs,hlr_offset,1+2+len+((varid&0x80)?1:0)); } } else @@ -410,7 +410,7 @@ int hlrSetVariable(unsigned char *hlr,int hofs,int varid,int varinstance, /* HLR record has no entries, or this entry needs to go at the end, so insert value at end of the record */ if (debug) fprintf(stderr,"Inserting value at end of HLR @ 0x%x\n",hlr_size); - hlrMakeSpace(hlr,hofs,hlr_size,1+2+len+(varid&0x80?1:0)); + hlrMakeSpace(hlr,hofs,hlr_size,1+2+len+((varid&0x80)?1:0)); hlr_offset=hlr_size; } @@ -435,14 +435,24 @@ int hlrStowValue(unsigned char *hlr,int hofs,int hlr_offset, int hlrMakeSpace(unsigned char *hlr,int hofs,int hlr_offset,int bytes) { int length; + int shifted_bytes=hlr_size-(hofs+hlr_offset+bytes); + /* Don't read past end of file */ + if (bytes<0) shifted_bytes+=bytes; + /* Deal with easy case first */ if (!bytes) return 0; + if (debug>2) { + fprintf(stderr,"hlrMakeSpace: Inserting %d bytes at offset %d with hofs=%d. shifted bytes=%d\n", + bytes,hlr_offset,hofs,shifted_bytes); + fflush(stderr); + } + /* Shift rest of HLR up/down. If down, back-fill bytes with zeros. */ bcopy(&hlr[hofs+hlr_offset],&hlr[hofs+hlr_offset+bytes], - hlr_size-(hofs+hlr_offset+bytes)); - if (bytes<0) bzero(&hlr[hlr_size-bytes],0-bytes); + shifted_bytes); + if (bytes<0) bzero(&hlr[hlr_size+bytes],0-bytes); /* Update record length */ length=hlrGetRecordLength(hlr,hofs); diff --git a/mphlr.h b/mphlr.h index 750e7959..444abf00 100644 --- a/mphlr.h +++ b/mphlr.h @@ -707,4 +707,40 @@ int rfs_length(int l); int rfs_encode(int l,unsigned char *b); int rfs_decode(unsigned char *b,int *offset); +#define OVERLAY_SENDER_PREFIX_LENGTH 12 +typedef struct overlay_node_observation { + int valid; + + /* Sequence numbers are handled as ranges because the tick + rate can vary between interfaces, and we want to be able to + estimate the reliability of links to nodes that may have + several available interfaces. + We don't want sequence numbers to wrap too often, but we + would also like to support fairly fast ticking interfaces, + e.g., for gigabit type links. So lets go with 1ms granularity. */ + int sequence_range_low; + int sequence_range_high; + long long rx_time; + unsigned char sender_prefix[OVERLAY_SENDER_PREFIX_LENGTH]; +} overlay_node_observation; + +/* Keep track of last 32 observations of a node. + Hopefully this is enough, if not, we will increase */ +#define OVERLAY_MAX_OBSERVATIONS 32 + +typedef struct overlay_node { + unsigned char sid[SID_SIZE]; + int neighbour_id; /* 0=not a neighbour */ + long long last_observation_time_ms; + int most_recent_observation_id; + overlay_node_observation observations[OVERLAY_MAX_OBSERVATIONS]; +} overlay_node; + +long long overlay_gettime_ms(); +int overlay_route_init(int mb_ram); +int overlay_route_saw_selfannounce_ack(overlay_frame *f,long long now); +int overlay_route_recalc_node_metrics(overlay_node *n); +int overlay_route_saw_selfannounce(overlay_frame *f,long long now); +overlay_node *overlay_route_find_node(unsigned char *sid,int createP); +unsigned int overlay_route_hash_sid(unsigned char *sid); int overlay_route_init(int mb_ram); diff --git a/overlay.c b/overlay.c index 1b509f3e..89205f46 100644 --- a/overlay.c +++ b/overlay.c @@ -122,6 +122,8 @@ int overlay_frame_process(int interface,overlay_frame *f) { if (!f) return WHY("f==NULL"); + long long now=overlay_gettime_ms(); + /* 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 @@ -225,10 +227,10 @@ int overlay_frame_process(int interface,overlay_frame *f) switch(f->type) { case OF_TYPE_SELFANNOUNCE: - overlay_route_saw_selfannounce(f); + overlay_route_saw_selfannounce(f,now); break; case OF_TYPE_SELFANNOUNCE_ACK: - overlay_route_saw_selfannounce_ack(f); + overlay_route_saw_selfannounce_ack(f,now); break; default: return WHY("Support for that f->type not yet implemented"); diff --git a/overlay_interface.c b/overlay_interface.c index ee571aa0..b87355a9 100644 --- a/overlay_interface.c +++ b/overlay_interface.c @@ -25,7 +25,7 @@ time_t overlay_sequence_start_time; /* Do we need to repeat our abbreviation policy? */ int overlay_interface_repeat_abbreviation_policy[OVERLAY_MAX_INTERFACES]={1}; -int overlay_update_sequence_number() +long long overlay_gettime_ms() { struct timeval nowtv; if (gettimeofday(&nowtv,NULL)) @@ -35,6 +35,12 @@ int overlay_update_sequence_number() long long now=(nowtv.tv_sec-overlay_sequence_start_time)*1000LL; now=now+nowtv.tv_usec/1000; + return now; +} + +int overlay_update_sequence_number() +{ + long long now=overlay_gettime_ms(); overlay_sequence_number=now&0xffffffff; return 0; } diff --git a/overlay_route.c b/overlay_route.c index 95b8488c..5a43e860 100644 --- a/overlay_route.c +++ b/overlay_route.c @@ -100,33 +100,6 @@ */ -#define OVERLAY_SENDER_PREFIX_LENGTH 12 -typedef struct overlay_node_observation { - int valid; - - /* Sequence numbers are handled as ranges because the tick - rate can vary between interfaces, and we want to be able to - estimate the reliability of links to nodes that may have - several available interfaces. - We don't want sequence numbers to wrap too often, but we - would also like to support fairly fast ticking interfaces, - e.g., for gigabit type links. So lets go with 1ms granularity. */ - int sequence_range_low; - int sequence_range_high; - long long rx_time; - unsigned char sender_prefix[OVERLAY_SENDER_PREFIX_LENGTH]; -} overlay_node_observation; - -/* Keep track of last 32 observations of a node. - Hopefully this is enough, if not, we will increase */ -#define OVERLAY_MAX_OBSERVATIONS 32 - -typedef struct overlay_node { - unsigned char sid[SID_SIZE]; - int neighbour_id; /* 0=not a neighbour */ - int most_recent_observation_id; - overlay_node_observation observations[OVERLAY_MAX_OBSERVATIONS]; -} overlay_node; /* For fast handling we will have a number of bins that will be indexed by the first few bits of the peer's SIDs, and a number of entries in each bin to @@ -395,9 +368,16 @@ overlay_node *overlay_route_find_node(unsigned char *sid,int createP) return &overlay_nodes[bin_number][free_slot]; } -int overlay_route_saw_selfannounce(overlay_frame *f) +int overlay_route_ack_selfannounce(overlay_frame *f) +{ + return WHY("Not implemented"); +} + +int overlay_route_saw_selfannounce(overlay_frame *f,long long now) { /* XXX send ack out even if we have no structures setup? */ + overlay_route_ack_selfannounce(f); + if (!overlay_neighbours) return 0; /* Lookup node in node cache */ @@ -424,12 +404,22 @@ int overlay_route_saw_selfannounce(overlay_frame *f) n->observations[obs_index].valid=1; n->most_recent_observation_id=obs_index; - /* Recalculate link score for this node */ + n->last_observation_time_ms=now; - return WHY("Not implemented"); + /* Recalculate link score for this node */ + if (overlay_route_recalc_node_metrics(n)) return WHY("recalc_node_metrics() failed."); + + return 0; } -int overlay_route_saw_selfannounce_ack(overlay_frame *f) +/* Recalculate node reachability metric. */ +int overlay_route_recalc_node_metrics(overlay_node *n) +{ + return WHY("Not Implemented"); + +} + +int overlay_route_saw_selfannounce_ack(overlay_frame *f,long long now) { if (!overlay_neighbours) return 0; return WHY("Not implemented"); diff --git a/packetformats.c b/packetformats.c index cb652364..38e46949 100644 --- a/packetformats.c +++ b/packetformats.c @@ -277,9 +277,11 @@ int packetAddVariableRequest(unsigned char *packet,int packet_maxlen,int *packet return setReason("Requested unknown HLR variable"); } itemId=vars[itemId].id; - if (instance<-1) return setReason("Asked for illegal variable value instance"); - if (instance>0xfe) return setReason("Asked for illegal variable value instance"); - if ((itemId<0x80)&&instance) return setReason("Asked for secondary value of single-value variable"); + if (instance<-1) return setReason("Asked for illegal variable value instance (<-1)"); + if (instance>0xfe) return setReason("Asked for illegal variable value instance (>0xfe)"); + if ((instance!=-1)&&(itemId<0x80)&&instance) { + return setReason("Asked for secondary value of single-value variable for read"); + } if (start_offset<0||start_offset>0xffff) return setReason("Asked for illegal variable value starting offset"); if (bytes<0||(start_offset+bytes)>0xffff) { if (debug) fprintf(stderr,"Asked for %d bytes at offset %d\n",bytes,start_offset); @@ -290,8 +292,7 @@ int packetAddVariableRequest(unsigned char *packet,int packet_maxlen,int *packet CHECK_PACKET_LEN(1+1+((itemId&0x80)?1:0)+2+2); packet[(*packet_len)++]=ACTION_GET; packet[(*packet_len)++]=itemId; - if (instance==-1) instance=0xff; - if (itemId&0x80) packet[(*packet_len)++]=instance; + if (itemId&0x80) { packet[(*packet_len)++]=instance; } packet[(*packet_len)++]=start_offset>>8; packet[(*packet_len)++]=start_offset&0xff; packet[(*packet_len)++]=bytes>>8; @@ -315,9 +316,11 @@ int packetAddVariableWrite(unsigned char *packet,int packet_maxlen, if (debug>1) printf("packetAddVariableWrite(start=%d,len=%d,flags=%d)\n",start_offset,value_len,flags); /* Sanity check */ - if (instance<0) return setReason("Asked for illegal variable value instance"); - if (instance>0xfe) return setReason("Asked for illegal variable value instance"); - if ((itemId<0x80)&&instance) return setReason("Asked for secondary value of single-value variable"); + if (itemId&0x80) { + if (instance<0) return setReason("Asked for illegal variable value instance (<0)"); + if (instance>0xfe) return setReason("Asked for illegal variable value instance (>0xfe)"); + } + if ((itemId<0x80)&&instance&&(instance!=-1)) return setReason("Asked for secondary value of single-value variable for write"); if (start_offset<0||start_offset>0xffff) return setReason("Asked for illegal variable value starting offset"); if (max_offset<0||max_offset>0xffff) return setReason("Asked for illegal variable value ending offset"); @@ -352,7 +355,7 @@ int extractRequest(unsigned char *packet,int *packet_ofs,int packet_len, *itemId=packet[(*packet_ofs)++]; - if ((*itemId)&0x80) *instance=packet[(*packet_ofs)++]; + if ((*itemId)&0x80) *instance=packet[(*packet_ofs)++]; else *instance=0; if (*instance==0xff) *instance=-1; *start_offset=packet[(*packet_ofs)++]<<8; diff --git a/server.c b/server.c index 04112008..208b902b 100644 --- a/server.c +++ b/server.c @@ -306,13 +306,19 @@ int processRequest(unsigned char *packet,int len, unsigned char data[MAX_DATA_BYTES+16]; int dlen=0; int sendDone=0; - int var_id=packet[pofs+1]; - int instance=packet[pofs+2]; - int offset=(packet[pofs+3]<<8)+packet[pofs+4]; + + if (debug>2) dump("Request bytes",&packet[pofs],8); + + pofs++; + int var_id=packet[pofs]; + int instance=-1; + if (var_id&0x80) instance=packet[++pofs]; + pofs++; + int offset=(packet[pofs]<<8)+packet[pofs+1]; pofs+=2; char *hlr_sid=NULL; - pofs+=7; - if (debug>2) dump("Request bytes",&packet[pofs],8); + pofs+=3; + if (debug>1) fprintf(stderr,"Processing ACTION_GET (var_id=%02x, instance=%02x, pofs=0x%x, len=%d)\n",var_id,instance,pofs,len); ofs=0;