Neighbour score calculation more or less in place,

just need to add aging of concatenated observation records so that
scores start dropping as soon as a node stops being observed.
This commit is contained in:
gardners 2011-09-04 16:38:54 +09:30
parent c06b75f5c9
commit f86089c9c8
2 changed files with 96 additions and 20 deletions

11
mphlr.h
View File

@ -735,7 +735,8 @@ typedef struct overlay_node_observation {
} overlay_node_observation;
/* Keep track of last 32 observations of a node.
Hopefully this is enough, if not, we will increase */
Hopefully this is enough, if not, we will increase.
To keep the requirement down we will collate contigious observations on each interface. */
#define OVERLAY_MAX_OBSERVATIONS 32
typedef struct overlay_node {
@ -752,12 +753,18 @@ typedef struct overlay_neighbour {
int most_recent_observation_id;
overlay_neighbour_observation observations[OVERLAY_MAX_OBSERVATIONS];
overlay_node *node;
/* Scores of visibility from each of the neighbours interfaces.
This is so that the sender knows which interface to use to reach us.
*/
unsigned char scores[OVERLAY_MAX_INTERFACES];
} overlay_neighbour;
long long overlay_gettime_ms();
int overlay_route_init(int mb_ram);
int overlay_route_saw_selfannounce_ack(int interface,overlay_frame *f,long long now);
int overlay_route_recalc_node_metrics(overlay_node *n);
int overlay_route_recalc_node_metrics(overlay_node *n,long long now);
int overlay_route_recalc_neighbour_metrics(overlay_neighbour *n,long long now);
int overlay_route_saw_selfannounce(int interface,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);

View File

@ -413,23 +413,52 @@ int overlay_route_i_can_hear(unsigned char *who,int sender_interface,unsigned in
/* Get neighbour structure */
overlay_neighbour *neh=&overlay_neighbours[n->neighbour_id];
/* Replace oldest observation with this one */
int obs_index=neh->most_recent_observation_id+1;
if (obs_index>=OVERLAY_MAX_OBSERVATIONS) obs_index=0;
neh->observations[obs_index].valid=0;
neh->observations[obs_index].time_ms=now;
neh->observations[obs_index].s1=s1;
neh->observations[obs_index].s2=s2;
neh->observations[obs_index].sender_interface=sender_interface;
neh->observations[obs_index].receiver_interface=receiver_interface;
neh->observations[obs_index].valid=1;
neh->most_recent_observation_id=obs_index;
neh->last_observation_time_ms=now;
int obs_index=neh->most_recent_observation_id;
int mergedP=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)))
{
if (neh->observations[obs_index].sender_interface==sender_interface)
{
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].receiver_interface=receiver_interface;
neh->observations[obs_index].time_ms=now;
fprintf(stderr,">>> Merging observations.\n");
mergedP=1;
break;
}
obs_index--;
if (obs_index<0) obs_index=OVERLAY_MAX_OBSERVATIONS-1;
}
if (!mergedP) {
/* Replace oldest observation with this one */
obs_index=neh->most_recent_observation_id+1;
if (obs_index>=OVERLAY_MAX_OBSERVATIONS) obs_index=0;
neh->observations[obs_index].valid=0;
neh->observations[obs_index].time_ms=now;
neh->observations[obs_index].s1=s1;
neh->observations[obs_index].s2=s2;
neh->observations[obs_index].sender_interface=sender_interface;
neh->observations[obs_index].receiver_interface=receiver_interface;
neh->observations[obs_index].valid=1;
neh->most_recent_observation_id=obs_index;
neh->last_observation_time_ms=now;
}
WHY("stored observation");
/* Update reachability metrics for node */
if (overlay_route_recalc_node_metrics(n)) WHY("overlay_route_recalc_node_metrics() failed");
if (overlay_route_recalc_neighbour_metrics(neh,now)) WHY("overlay_route_recalc_neighbour_metrics() failed");
return WHY("Not implemented");
return 0;
}
int overlay_route_saw_selfannounce(int interface,overlay_frame *f,long long now)
@ -473,11 +502,16 @@ int overlay_someoneelse_can_hear(unsigned char *hearer,unsigned char *who,unsign
n->last_observation_time_ms=now;
/* Recalculate link score for this node */
if (overlay_route_recalc_node_metrics(n)) return WHY("recalc_node_metrics() failed.");
if (overlay_route_recalc_node_metrics(n,now)) return WHY("recalc_node_metrics() failed.");
return 0;
}
int overlay_route_recalc_node_metrics(overlay_node *n,long long now)
{
return WHY("Not implemented.");
}
/* Recalculate node reachability metric, but only for directly connected nodes,
i.e., link-local neighbours.
@ -490,7 +524,7 @@ int overlay_someoneelse_can_hear(unsigned char *hearer,unsigned char *who,unsign
The sequence numbers are all based on a milli-second clock.
*/
int overlay_route_recalc_node_metrics(overlay_node *n)
int overlay_route_recalc_neighbour_metrics(overlay_neighbour *n,long long now)
{
int i;
@ -498,11 +532,46 @@ int overlay_route_recalc_node_metrics(overlay_node *n)
int ms_observed[OVERLAY_MAX_INTERFACES];
for(i=0;i<OVERLAY_MAX_INTERFACES;i++) ms_observed[i]=0;
/* XXX This simple accumulation scheme does not weed out duplicates */
/* XXX This simple accumulation scheme does not weed out duplicates, nor weight for recency of
communication.
Also, we might like to take into account the interface we received
the announcements on. */
for(i=0;i<OVERLAY_MAX_OBSERVATIONS;i++)
/* Only count observations less than 200 seconds old.
XXX Down the track we will have a mechanism for older observations so that we can report
intermittent paths */
if (n->observations[i].valid&&n->observations[i].s1&&((now-n->observations[i].time_ms)<200000)) {
/* No need to do wrap-around calculation as the following is modulo 2^32 also */
unsigned int interval=n->observations[i].s2-n->observations[i].s1;
fprintf(stderr,"adding %dms\n",interval);
ms_observed[n->observations[i].sender_interface]+=interval;
}
/* From the sum of observations calculate the metrics.
We want the score to climb quickly and then plateu.
For fast calculation we will use a step-wise linear approach, similar to that used in
DNA sequence comparison. */
for(i=0;i<OVERLAY_MAX_INTERFACES;i++) {
int score;
if (ms_observed[i]==0) {
// Not observed at all
score=0;
} else {
int seconds_observed=ms_observed[i]/1000;
if ((1+ms_observed[i]/100)<100) score=1+ms_observed[i]/100; // 1 - 99
else if ((100+(ms_observed[i]/500-20))<200) score=100+(ms_observed[i]/500-20); // 100 - 199
else if ((200+(ms_observed[i]/3000-20))<255) score=200+(ms_observed[i]/3000-20); // 200 - 254
else score=255;
}
return WHY("Not Implemented");
/* XXX We should reduce the score by an age factor in case the most recent observation is stale
n->scores[i]=score;
if (debug>2&&score) fprintf(stderr,"Neighbour score on interface #%d = %d (observations for %dms)\n",i,score,ms_observed[i]);
}
return 0;
}
int overlay_route_saw_selfannounce_ack(int interface,overlay_frame *f,long long now)