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