Commit 0db7e63b authored by Juliusz Chroboczek's avatar Juliusz Chroboczek

Implement sending of unicast and unscheduled IHUs.

This just implements the sending functions, it doesn't actually do anything
with them yet.
parent 928454f5
...@@ -814,7 +814,7 @@ main(int argc, char **argv) ...@@ -814,7 +814,7 @@ main(int argc, char **argv)
send_wildcard_retraction(ifp); send_wildcard_retraction(ifp);
/* Make sure that we expire quickly from our neighbours' /* Make sure that we expire quickly from our neighbours'
association caches. */ association caches. */
send_hello_noihu(ifp, 10); send_multicast_hello(ifp, 10, 1);
flushbuf(&ifp->buf, ifp); flushbuf(&ifp->buf, ifp);
usleep(roughly(1000)); usleep(roughly(1000));
gettime(&now); gettime(&now);
...@@ -824,7 +824,7 @@ main(int argc, char **argv) ...@@ -824,7 +824,7 @@ main(int argc, char **argv)
continue; continue;
/* Make sure they got it. */ /* Make sure they got it. */
send_wildcard_retraction(ifp); send_wildcard_retraction(ifp);
send_hello_noihu(ifp, 1); send_multicast_hello(ifp, 1, 1);
flushbuf(&ifp->buf, ifp); flushbuf(&ifp->buf, ifp);
usleep(roughly(10000)); usleep(roughly(10000));
gettime(&now); gettime(&now);
......
...@@ -1024,45 +1024,86 @@ send_ack(struct neighbour *neigh, unsigned short nonce, unsigned short interval) ...@@ -1024,45 +1024,86 @@ send_ack(struct neighbour *neigh, unsigned short nonce, unsigned short interval)
schedule_flush_ms(&neigh->buf, roughly(interval * 6)); schedule_flush_ms(&neigh->buf, roughly(interval * 6));
} }
static void
buffer_hello(struct buffered *buf, struct interface *ifp,
unsigned short seqno, unsigned interval, int unicast)
{
int timestamp = !!(ifp->flags & IF_TIMESTAMPS);
start_message(buf, ifp, MESSAGE_HELLO, timestamp ? 12 : 6);
buf->hello = buf->len - 2;
accumulate_short(buf, unicast ? 0x8000 : 0);
accumulate_short(buf, seqno);
accumulate_short(buf, interval > 0xFFFF ? 0xFFFF : interval);
if(timestamp) {
/* Sub-TLV containing the local time of emission. We use a
Pad4 sub-TLV, which we'll fill just before sending. */
accumulate_byte(buf, SUBTLV_PADN);
accumulate_byte(buf, 4);
accumulate_int(buf, 0);
}
end_message(&ifp->buf, MESSAGE_HELLO, timestamp ? 12 : 6);
}
void void
send_hello_noihu(struct interface *ifp, unsigned interval) send_multicast_hello(struct interface *ifp, unsigned interval, int force)
{ {
if(!if_up(ifp))
return;
if(interval == 0 && (ifp->flags & IF_RFC6126) != 0)
/* Unscheduled hellos are incompatible with RFC 6126. */
return;
/* This avoids sending multiple hellos in a single packet, which breaks /* This avoids sending multiple hellos in a single packet, which breaks
link quality estimation. */ link quality estimation. */
if(ifp->buf.hello >= 0) { if(ifp->buf.hello >= 0) {
flushupdates(ifp); if(force) {
flushbuf(&ifp->buf, ifp); flushupdates(ifp);
flushbuf(&ifp->buf, ifp);
} else {
return;
}
} }
ifp->hello_seqno = seqno_plus(ifp->hello_seqno, 1); ifp->hello_seqno = seqno_plus(ifp->hello_seqno, 1);
set_timeout(&ifp->hello_timeout, ifp->hello_interval); if(interval > 0)
set_timeout(&ifp->hello_timeout, ifp->hello_interval);
if(!if_up(ifp))
return;
debugf("Sending hello %d (%d) to %s.\n", debugf("Sending hello %d (%d) to %s.\n",
ifp->hello_seqno, interval, ifp->name); ifp->hello_seqno, interval, ifp->name);
start_message(&ifp->buf, ifp, MESSAGE_HELLO, buffer_hello(&ifp->buf, ifp, ifp->hello_seqno, interval, 0);
(ifp->flags & IF_TIMESTAMPS) ? 12 : 6); }
ifp->buf.hello = ifp->buf.len - 2;
accumulate_short(&ifp->buf, 0); void
accumulate_short(&ifp->buf, ifp->hello_seqno); send_unicast_hello(struct neighbour *neigh, unsigned interval, int force)
accumulate_short(&ifp->buf, interval > 0xFFFF ? 0xFFFF : interval); {
if((ifp->flags & IF_TIMESTAMPS) != 0) { if(!if_up(neigh->ifp))
/* Sub-TLV containing the local time of emission. We use a return;
Pad4 sub-TLV, which we'll fill just before sending. */
accumulate_byte(&ifp->buf, SUBTLV_PADN); if((neigh->ifp->flags & IF_RFC6126) != 0)
accumulate_byte(&ifp->buf, 4); /* Unicast hellos are incompatible with RFC 6126. */
accumulate_int(&ifp->buf, 0); return;
if(neigh->buf.hello >= 0) {
if(force)
flushbuf(&neigh->buf, neigh->ifp);
else
return;
} }
end_message(&ifp->buf, MESSAGE_HELLO, (ifp->flags & IF_TIMESTAMPS) ? 12 : 6);
neigh->hello_seqno = seqno_plus(neigh->hello_seqno, 1);
debugf("Sending unicast hello %d (%d) on %s.\n",
neigh->hello_seqno, interval, neigh->ifp->name);
buffer_hello(&neigh->buf, neigh->ifp, neigh->hello_seqno, interval, 1);
} }
void void
send_hello(struct interface *ifp) send_hello(struct interface *ifp)
{ {
send_hello_noihu(ifp, (ifp->hello_interval + 9) / 10); send_multicast_hello(ifp, (ifp->hello_interval + 9) / 10, 1);
/* Send full IHU every 3 hellos, and marginal IHU each time */ /* Send full IHU every 3 hellos, and marginal IHU each time */
if(ifp->hello_seqno % 3 == 0) if(ifp->hello_seqno % 3 == 0)
send_ihu(NULL, ifp); send_ihu(NULL, ifp);
......
...@@ -55,7 +55,8 @@ void flushbuf(struct buffered *buf, struct interface *ifp); ...@@ -55,7 +55,8 @@ void flushbuf(struct buffered *buf, struct interface *ifp);
void flushupdates(struct interface *ifp); void flushupdates(struct interface *ifp);
void send_ack(struct neighbour *neigh, unsigned short nonce, void send_ack(struct neighbour *neigh, unsigned short nonce,
unsigned short interval); unsigned short interval);
void send_hello_noihu(struct interface *ifp, unsigned interval); void send_multicast_hello(struct interface *ifp, unsigned interval, int force);
void send_unicast_hello(struct neighbour *neigh, unsigned interval, int force);
void send_hello(struct interface *ifp); void send_hello(struct interface *ifp);
void flush_unicast(int dofree); void flush_unicast(int dofree);
void send_update(struct interface *ifp, int urgent, void send_update(struct interface *ifp, int urgent,
......
...@@ -32,8 +32,9 @@ struct neighbour { ...@@ -32,8 +32,9 @@ struct neighbour {
/* This is -1 when unknown, so don't make it unsigned */ /* This is -1 when unknown, so don't make it unsigned */
unsigned char address[16]; unsigned char address[16];
struct hello_history hello; struct hello_history hello;
struct hello_history uhello; /* for Unicast hellos */ struct hello_history uhello; /* for Unicast Hellos */
unsigned short txcost; unsigned short txcost;
unsigned short hello_seqno; /* for Unicast Hellos */
struct timeval ihu_time; struct timeval ihu_time;
unsigned short ihu_interval; /* in centiseconds */ unsigned short ihu_interval; /* in centiseconds */
/* Used for RTT estimation. */ /* Used for RTT estimation. */
......
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