Commit 917ea3ee authored by Juliusz Chroboczek's avatar Juliusz Chroboczek

Move hello history into a separate structure.

parent 58673129
...@@ -1117,7 +1117,7 @@ dump_tables(FILE *out) ...@@ -1117,7 +1117,7 @@ dump_tables(FILE *out)
"rtt %s rttcost %d chan %d%s.\n", "rtt %s rttcost %d chan %d%s.\n",
format_address(neigh->address), format_address(neigh->address),
neigh->ifp->name, neigh->ifp->name,
neigh->reach, neigh->hello.reach,
neighbour_rxcost(neigh), neighbour_rxcost(neigh),
neigh->txcost, neigh->txcost,
format_thousands(neigh->rtt), format_thousands(neigh->rtt),
......
...@@ -160,7 +160,7 @@ local_notify_neighbour_1(struct local_socket *s, ...@@ -160,7 +160,7 @@ local_notify_neighbour_1(struct local_socket *s,
(unsigned long int)neigh, (unsigned long int)neigh,
format_address(neigh->address), format_address(neigh->address),
neigh->ifp->name, neigh->ifp->name,
neigh->reach, neigh->hello.reach,
neighbour_rxcost(neigh), neighbour_rxcost(neigh),
neighbour_txcost(neigh), neighbour_txcost(neigh),
rttbuf, rttbuf,
......
...@@ -441,7 +441,7 @@ parse_packet(const unsigned char *from, struct interface *ifp, ...@@ -441,7 +441,7 @@ parse_packet(const unsigned char *from, struct interface *ifp,
if(message[2] & 0x80) if(message[2] & 0x80)
/* Unicast, ignored for now. */ /* Unicast, ignored for now. */
goto done; goto done;
changed = update_neighbour(neigh, seqno, interval); changed = update_neighbour(neigh, &neigh->hello, seqno, interval);
update_neighbour_metric(neigh, changed); update_neighbour_metric(neigh, changed);
if(interval > 0) if(interval > 0)
/* Multiply by 3/2 to allow hellos to expire. */ /* Multiply by 3/2 to allow hellos to expire. */
...@@ -1837,7 +1837,7 @@ send_marginal_ihu(struct interface *ifp) ...@@ -1837,7 +1837,7 @@ send_marginal_ihu(struct interface *ifp)
FOR_ALL_NEIGHBOURS(neigh) { FOR_ALL_NEIGHBOURS(neigh) {
if(ifp && neigh->ifp != ifp) if(ifp && neigh->ifp != ifp)
continue; continue;
if(neigh->txcost >= 384 || (neigh->reach & 0xF000) != 0xF000) if(neigh->txcost >= 384 || (neigh->hello.reach & 0xF000) != 0xF000)
send_ihu(neigh, ifp); send_ihu(neigh, ifp);
} }
} }
......
...@@ -90,11 +90,11 @@ find_neighbour(const unsigned char *address, struct interface *ifp) ...@@ -90,11 +90,11 @@ find_neighbour(const unsigned char *address, struct interface *ifp)
return NULL; return NULL;
} }
neigh->hello_seqno = -1; neigh->hello.seqno = -1;
memcpy(neigh->address, address, 16); memcpy(neigh->address, address, 16);
neigh->txcost = INFINITY; neigh->txcost = INFINITY;
neigh->ihu_time = now; neigh->ihu_time = now;
neigh->hello_time = zero; neigh->hello.time = zero;
neigh->hello_rtt_receive_time = zero; neigh->hello_rtt_receive_time = zero;
neigh->rtt_time = zero; neigh->rtt_time = zero;
neigh->ifp = ifp; neigh->ifp = ifp;
...@@ -108,33 +108,34 @@ find_neighbour(const unsigned char *address, struct interface *ifp) ...@@ -108,33 +108,34 @@ find_neighbour(const unsigned char *address, struct interface *ifp)
/* Recompute a neighbour's rxcost. Return true if anything changed. /* Recompute a neighbour's rxcost. Return true if anything changed.
This does not call local_notify_neighbour, see update_neighbour_metric. */ This does not call local_notify_neighbour, see update_neighbour_metric. */
int int
update_neighbour(struct neighbour *neigh, int hello, int hello_interval) update_neighbour(struct neighbour *neigh, struct hello_history *hist,
int hello, int hello_interval)
{ {
int missed_hellos; int missed_hellos;
int rc = 0; int rc = 0;
if(hello < 0) { if(hello < 0) {
if(neigh->hello_interval <= 0) if(hist->interval <= 0)
return rc; return rc;
missed_hellos = missed_hellos =
((int)timeval_minus_msec(&now, &neigh->hello_time) - ((int)timeval_minus_msec(&now, &hist->time) -
neigh->hello_interval * 7) / hist->interval * 7) /
(neigh->hello_interval * 10); (hist->interval * 10);
if(missed_hellos <= 0) if(missed_hellos <= 0)
return rc; return rc;
timeval_add_msec(&neigh->hello_time, &neigh->hello_time, timeval_add_msec(&hist->time, &hist->time,
missed_hellos * neigh->hello_interval * 10); missed_hellos * hist->interval * 10);
} else { } else {
if(neigh->hello_seqno >= 0 && neigh->reach > 0) { if(hist->seqno >= 0 && hist->reach > 0) {
missed_hellos = seqno_minus(hello, neigh->hello_seqno) - 1; missed_hellos = seqno_minus(hello, hist->seqno) - 1;
if(missed_hellos < -8) { if(missed_hellos < -8) {
/* Probably a neighbour that rebooted and lost its seqno. /* Probably a neighbour that rebooted and lost its seqno.
Reboot the universe. */ Reboot the universe. */
neigh->reach = 0; hist->reach = 0;
missed_hellos = 0; missed_hellos = 0;
rc = 1; rc = 1;
} else if(missed_hellos < 0) { } else if(missed_hellos < 0) {
neigh->reach <<= -missed_hellos; hist->reach <<= -missed_hellos;
missed_hellos = 0; missed_hellos = 0;
rc = 1; rc = 1;
} }
...@@ -142,41 +143,41 @@ update_neighbour(struct neighbour *neigh, int hello, int hello_interval) ...@@ -142,41 +143,41 @@ update_neighbour(struct neighbour *neigh, int hello, int hello_interval)
missed_hellos = 0; missed_hellos = 0;
} }
if(hello_interval != 0) { if(hello_interval != 0) {
neigh->hello_time = now; hist->time = now;
neigh->hello_interval = hello_interval; hist->interval = hello_interval;
} }
} }
if(missed_hellos > 0) { if(missed_hellos > 0) {
neigh->reach >>= missed_hellos; hist->reach >>= missed_hellos;
neigh->hello_seqno = seqno_plus(neigh->hello_seqno, missed_hellos); hist->seqno = seqno_plus(hist->seqno, missed_hellos);
missed_hellos = 0; missed_hellos = 0;
rc = 1; rc = 1;
} }
if(hello >= 0) { if(hello >= 0) {
neigh->hello_seqno = hello; hist->seqno = hello;
neigh->reach >>= 1; hist->reach >>= 1;
neigh->reach |= 0x8000; hist->reach |= 0x8000;
if((neigh->reach & 0xFC00) != 0xFC00) if((hist->reach & 0xFC00) != 0xFC00)
rc = 1; rc = 1;
} }
/* Make sure to give neighbours some feedback early after association */ /* Make sure to give neighbours some feedback early after association */
if((neigh->reach & 0xBF00) == 0x8000) { if((hist->reach & 0xBF00) == 0x8000) {
/* A new neighbour */ /* A new neighbour */
send_hello(neigh->ifp); send_hello(neigh->ifp);
} else { } else {
/* Don't send hellos, in order to avoid a positive feedback loop. */ /* Don't send hellos, in order to avoid a positive feedback loop. */
int a = (neigh->reach & 0xC000); int a = (hist->reach & 0xC000);
int b = (neigh->reach & 0x3000); int b = (hist->reach & 0x3000);
if((a == 0xC000 && b == 0) || (a == 0 && b == 0x3000)) { if((a == 0xC000 && b == 0) || (a == 0 && b == 0x3000)) {
/* Reachability is either 1100 or 0011 */ /* Reachability is either 1100 or 0011 */
send_self_update(neigh->ifp); send_self_update(neigh->ifp);
} }
} }
if((neigh->reach & 0xFC00) == 0xC000) { if((hist->reach & 0xFC00) == 0xC000) {
/* This is a newish neighbour, let's request a full route dump. /* This is a newish neighbour, let's request a full route dump.
We ought to avoid this when the network is dense */ We ought to avoid this when the network is dense */
send_unicast_request(neigh, NULL, 0, NULL, 0); send_unicast_request(neigh, NULL, 0, NULL, 0);
...@@ -196,7 +197,7 @@ reset_txcost(struct neighbour *neigh) ...@@ -196,7 +197,7 @@ reset_txcost(struct neighbour *neigh)
return 0; return 0;
/* If we're losing a lot of packets, we probably lost an IHU too */ /* If we're losing a lot of packets, we probably lost an IHU too */
if(delay >= 180000 || (neigh->reach & 0xFFF0) == 0 || if(delay >= 180000 || (neigh->hello.reach & 0xFFF0) == 0 ||
(neigh->ihu_interval > 0 && (neigh->ihu_interval > 0 &&
delay >= neigh->ihu_interval * 10 * 10)) { delay >= neigh->ihu_interval * 10 * 10)) {
neigh->txcost = INFINITY; neigh->txcost = INFINITY;
...@@ -224,11 +225,11 @@ check_neighbours() ...@@ -224,11 +225,11 @@ check_neighbours()
neigh = neighs; neigh = neighs;
while(neigh) { while(neigh) {
changed = update_neighbour(neigh, -1, 0); changed = update_neighbour(neigh, &neigh->hello, -1, 0);
if(neigh->reach == 0 || if(neigh->hello.reach == 0 ||
neigh->hello_time.tv_sec > now.tv_sec || /* clock stepped */ neigh->hello.time.tv_sec > now.tv_sec || /* clock stepped */
timeval_minus_msec(&now, &neigh->hello_time) > 300000) { timeval_minus_msec(&now, &neigh->hello.time) > 300000) {
struct neighbour *old = neigh; struct neighbour *old = neigh;
neigh = neigh->next; neigh = neigh->next;
flush_neighbour(old); flush_neighbour(old);
...@@ -240,8 +241,8 @@ check_neighbours() ...@@ -240,8 +241,8 @@ check_neighbours()
update_neighbour_metric(neigh, changed); update_neighbour_metric(neigh, changed);
if(neigh->hello_interval > 0) if(neigh->hello.interval > 0)
msecs = MIN(msecs, neigh->hello_interval * 10); msecs = MIN(msecs, neigh->hello.interval * 10);
if(neigh->ihu_interval > 0) if(neigh->ihu_interval > 0)
msecs = MIN(msecs, neigh->ihu_interval * 10); msecs = MIN(msecs, neigh->ihu_interval * 10);
neigh = neigh->next; neigh = neigh->next;
...@@ -254,9 +255,9 @@ unsigned ...@@ -254,9 +255,9 @@ unsigned
neighbour_rxcost(struct neighbour *neigh) neighbour_rxcost(struct neighbour *neigh)
{ {
unsigned delay; unsigned delay;
unsigned short reach = neigh->reach; unsigned short reach = neigh->hello.reach;
delay = timeval_minus_msec(&now, &neigh->hello_time); delay = timeval_minus_msec(&now, &neigh->hello.time);
if((reach & 0xFFF0) == 0 || delay >= 180000) { if((reach & 0xFFF0) == 0 || delay >= 180000) {
return INFINITY; return INFINITY;
......
...@@ -20,16 +20,20 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ...@@ -20,16 +20,20 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE. THE SOFTWARE.
*/ */
struct hello_history {
unsigned short reach;
unsigned short interval; /* in centiseconds */
int seqno;
struct timeval time;
};
struct neighbour { struct neighbour {
struct neighbour *next; struct neighbour *next;
/* This is -1 when unknown, so don't make it unsigned */ /* This is -1 when unknown, so don't make it unsigned */
int hello_seqno;
unsigned char address[16]; unsigned char address[16];
unsigned short reach; struct hello_history hello;
unsigned short txcost; unsigned short txcost;
struct timeval hello_time;
struct timeval ihu_time; struct timeval ihu_time;
unsigned short hello_interval; /* in centiseconds */
unsigned short ihu_interval; /* in centiseconds */ unsigned short ihu_interval; /* in centiseconds */
/* Used for RTT estimation. */ /* Used for RTT estimation. */
/* Absolute time (modulo 2^32) at which the Hello was sent, /* Absolute time (modulo 2^32) at which the Hello was sent,
...@@ -50,7 +54,8 @@ int neighbour_valid(struct neighbour *neigh); ...@@ -50,7 +54,8 @@ int neighbour_valid(struct neighbour *neigh);
void flush_neighbour(struct neighbour *neigh); void flush_neighbour(struct neighbour *neigh);
struct neighbour *find_neighbour(const unsigned char *address, struct neighbour *find_neighbour(const unsigned char *address,
struct interface *ifp); struct interface *ifp);
int update_neighbour(struct neighbour *neigh, int hello, int hello_interval); int update_neighbour(struct neighbour *neigh, struct hello_history *hist,
int hello, int hello_interval);
unsigned check_neighbours(void); unsigned check_neighbours(void);
unsigned neighbour_txcost(struct neighbour *neigh); unsigned neighbour_txcost(struct neighbour *neigh);
unsigned neighbour_rxcost(struct neighbour *neigh); unsigned neighbour_rxcost(struct neighbour *neigh);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment