Commit 5afde873 authored by Juliusz Chroboczek's avatar Juliusz Chroboczek

Merge branch 'rfc6126bis'

parents 8627b6fc 3a4fbbf0
...@@ -582,8 +582,9 @@ main(int argc, char **argv) ...@@ -582,8 +582,9 @@ main(int argc, char **argv)
send_hello(ifp); send_hello(ifp);
send_wildcard_retraction(ifp); send_wildcard_retraction(ifp);
send_self_update(ifp); send_self_update(ifp);
send_multicast_request(ifp, NULL, 0, NULL, 0);
flushupdates(ifp); flushupdates(ifp);
flushbuf(ifp); flushbuf(&ifp->buf);
} }
debugf("Entering main loop.\n"); debugf("Entering main loop.\n");
...@@ -591,6 +592,7 @@ main(int argc, char **argv) ...@@ -591,6 +592,7 @@ main(int argc, char **argv)
while(1) { while(1) {
struct timeval tv; struct timeval tv;
fd_set readfds; fd_set readfds;
struct neighbour *neigh;
gettime(&now); gettime(&now);
...@@ -603,12 +605,14 @@ main(int argc, char **argv) ...@@ -603,12 +605,14 @@ main(int argc, char **argv)
FOR_ALL_INTERFACES(ifp) { FOR_ALL_INTERFACES(ifp) {
if(!if_up(ifp)) if(!if_up(ifp))
continue; continue;
timeval_min(&tv, &ifp->flush_timeout); timeval_min(&tv, &ifp->buf.timeout);
timeval_min(&tv, &ifp->hello_timeout); timeval_min(&tv, &ifp->hello_timeout);
timeval_min(&tv, &ifp->update_timeout); timeval_min(&tv, &ifp->update_timeout);
timeval_min(&tv, &ifp->update_flush_timeout); timeval_min(&tv, &ifp->update_flush_timeout);
} }
timeval_min(&tv, &unicast_flush_timeout); FOR_ALL_NEIGHBOURS(neigh) {
timeval_min(&tv, &neigh->buf.timeout);
}
FD_ZERO(&readfds); FD_ZERO(&readfds);
if(timeval_compare(&tv, &now) > 0) { if(timeval_compare(&tv, &now) > 0) {
int maxfd = 0; int maxfd = 0;
...@@ -770,17 +774,22 @@ main(int argc, char **argv) ...@@ -770,17 +774,22 @@ main(int argc, char **argv)
do_resend(); do_resend();
} }
if(unicast_flush_timeout.tv_sec != 0) {
if(timeval_compare(&now, &unicast_flush_timeout) >= 0)
flush_unicast(1);
}
FOR_ALL_INTERFACES(ifp) { FOR_ALL_INTERFACES(ifp) {
if(!if_up(ifp)) if(!if_up(ifp))
continue; continue;
if(ifp->flush_timeout.tv_sec != 0) { if(ifp->buf.timeout.tv_sec != 0) {
if(timeval_compare(&now, &ifp->flush_timeout) >= 0) if(timeval_compare(&now, &ifp->buf.timeout) >= 0) {
flushbuf(ifp); flushupdates(ifp);
flushbuf(&ifp->buf);
}
}
}
FOR_ALL_NEIGHBOURS(neigh) {
if(neigh->buf.timeout.tv_sec != 0) {
if(timeval_compare(&now, &neigh->buf.timeout) >= 0) {
flushbuf(&neigh->buf);
}
} }
} }
...@@ -803,8 +812,8 @@ main(int argc, char **argv) ...@@ -803,8 +812,8 @@ 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_noupdate(ifp, 10); send_hello_noihu(ifp, 10);
flushbuf(ifp); flushbuf(&ifp->buf);
usleep(roughly(1000)); usleep(roughly(1000));
gettime(&now); gettime(&now);
} }
...@@ -813,8 +822,8 @@ main(int argc, char **argv) ...@@ -813,8 +822,8 @@ 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_noupdate(ifp, 1); send_hello_noihu(ifp, 1);
flushbuf(ifp); flushbuf(&ifp->buf);
usleep(roughly(10000)); usleep(roughly(10000));
gettime(&now); gettime(&now);
interface_up(ifp, 0); interface_up(ifp, 0);
...@@ -1113,7 +1122,7 @@ dump_tables(FILE *out) ...@@ -1113,7 +1122,7 @@ dump_tables(FILE *out)
FOR_ALL_NEIGHBOURS(neigh) { FOR_ALL_NEIGHBOURS(neigh) {
fprintf(out, "Neighbour %s dev %s reach %04x ureach %04x " fprintf(out, "Neighbour %s dev %s reach %04x ureach %04x "
"rxcost %d txcost %d rtt %s rttcost %d chan %d%s.\n", "rxcost %u txcost %d rtt %s rttcost %u chan %d%s.\n",
format_address(neigh->address), format_address(neigh->address),
neigh->ifp->name, neigh->ifp->name,
neigh->hello.reach, neigh->hello.reach,
......
...@@ -24,6 +24,8 @@ THE SOFTWARE. ...@@ -24,6 +24,8 @@ THE SOFTWARE.
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#include <sys/time.h> #include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <assert.h> #include <assert.h>
#ifdef __linux #ifdef __linux
...@@ -560,6 +562,12 @@ parse_anonymous_ifconf(int c, gnc_t gnc, void *closure, ...@@ -560,6 +562,12 @@ parse_anonymous_ifconf(int c, gnc_t gnc, void *closure,
if(c < -1) if(c < -1)
goto error; goto error;
if_conf->faraway = v; if_conf->faraway = v;
} else if(strcmp(token, "unicast") == 0) {
int v;
c = getbool(c, &v, gnc, closure);
if(c < -1)
goto error;
if_conf->unicast = v;
} else if(strcmp(token, "link-quality") == 0) { } else if(strcmp(token, "link-quality") == 0) {
int v; int v;
c = getbool(c, &v, gnc, closure); c = getbool(c, &v, gnc, closure);
...@@ -711,6 +719,7 @@ merge_ifconf(struct interface_conf *dest, ...@@ -711,6 +719,7 @@ merge_ifconf(struct interface_conf *dest,
MERGE(split_horizon); MERGE(split_horizon);
MERGE(lq); MERGE(lq);
MERGE(faraway); MERGE(faraway);
MERGE(unicast);
MERGE(channel); MERGE(channel);
MERGE(enable_timestamps); MERGE(enable_timestamps);
MERGE(rfc6126); MERGE(rfc6126);
......
...@@ -25,6 +25,8 @@ THE SOFTWARE. ...@@ -25,6 +25,8 @@ THE SOFTWARE.
#include <stdio.h> #include <stdio.h>
#include <errno.h> #include <errno.h>
#include <assert.h> #include <assert.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/time.h> #include <sys/time.h>
#include "babeld.h" #include "babeld.h"
......
...@@ -80,8 +80,6 @@ add_interface(char *ifname, struct interface_conf *if_conf) ...@@ -80,8 +80,6 @@ add_interface(char *ifname, struct interface_conf *if_conf)
strncpy(ifp->name, ifname, IF_NAMESIZE); strncpy(ifp->name, ifname, IF_NAMESIZE);
ifp->conf = if_conf ? if_conf : default_interface_conf; ifp->conf = if_conf ? if_conf : default_interface_conf;
ifp->bucket_time = now.tv_sec;
ifp->bucket = BUCKET_TOKENS_MAX;
ifp->hello_seqno = (random() & 0xFFFF); ifp->hello_seqno = (random() & 0xFFFF);
if(interfaces == NULL) if(interfaces == NULL)
...@@ -132,14 +130,14 @@ flush_interface(char *ifname) ...@@ -132,14 +130,14 @@ flush_interface(char *ifname)
/* This should be no more than half the hello interval, so that hellos /* This should be no more than half the hello interval, so that hellos
aren't sent late. The result is in milliseconds. */ aren't sent late. The result is in milliseconds. */
unsigned unsigned
jitter(struct interface *ifp, int urgent) jitter(struct buffered *buf, int urgent)
{ {
unsigned interval = ifp->hello_interval; unsigned interval = buf->flush_interval;
if(urgent) if(urgent)
interval = MIN(interval, 100); interval = MIN(interval, 20);
else else
interval = MIN(interval, 4000); interval = MIN(interval, 2000);
return roughly(interval) / 4; return roughly(interval / 2);
} }
unsigned unsigned
...@@ -297,14 +295,20 @@ interface_up(struct interface *ifp, int up) ...@@ -297,14 +295,20 @@ interface_up(struct interface *ifp, int up)
rc = kernel_setup_interface(1, ifp->name, ifp->ifindex); rc = kernel_setup_interface(1, ifp->name, ifp->ifindex);
if(rc < 0) { if(rc < 0) {
fprintf(stderr, "kernel_setup_interface(%s, %d) failed.\n", fprintf(stderr, "kernel_setup_interface(%s, %u) failed.\n",
ifp->name, ifp->ifindex); ifp->name, ifp->ifindex);
goto fail; goto fail;
} }
memset(&ifp->buf.sin6, 0, sizeof(ifp->buf.sin6));
ifp->buf.sin6.sin6_family = AF_INET6;
memcpy(&ifp->buf.sin6.sin6_addr, protocol_group, 16);
ifp->buf.sin6.sin6_port = htons(protocol_port);
ifp->buf.sin6.sin6_scope_id = ifp->ifindex;
mtu = kernel_interface_mtu(ifp->name, ifp->ifindex); mtu = kernel_interface_mtu(ifp->name, ifp->ifindex);
if(mtu < 0) { if(mtu < 0) {
fprintf(stderr, "Warning: couldn't get MTU of interface %s (%d).\n", fprintf(stderr, "Warning: couldn't get MTU of interface %s (%u).\n",
ifp->name, ifp->ifindex); ifp->name, ifp->ifindex);
mtu = 1280; mtu = 1280;
} }
...@@ -314,27 +318,27 @@ interface_up(struct interface *ifp, int up) ...@@ -314,27 +318,27 @@ interface_up(struct interface *ifp, int up)
/* In IPv6, the minimum MTU is 1280, and every host must be able /* In IPv6, the minimum MTU is 1280, and every host must be able
to reassemble up to 1500 bytes, but I'd rather not rely on this. */ to reassemble up to 1500 bytes, but I'd rather not rely on this. */
if(mtu < 128) { if(mtu < 128) {
fprintf(stderr, "Suspiciously low MTU %d on interface %s (%d).\n", fprintf(stderr, "Suspiciously low MTU %d on interface %s (%u).\n",
mtu, ifp->name, ifp->ifindex); mtu, ifp->name, ifp->ifindex);
mtu = 128; mtu = 128;
} }
if(ifp->sendbuf) if(ifp->buf.buf)
free(ifp->sendbuf); free(ifp->buf.buf);
/* 40 for IPv6 header, 8 for UDP header, 12 for good luck. */ /* 40 for IPv6 header, 8 for UDP header, 12 for good luck. */
ifp->bufsize = mtu - sizeof(packet_header) - 60; ifp->buf.size = mtu - sizeof(packet_header) - 60;
ifp->sendbuf = malloc(ifp->bufsize); ifp->buf.buf = malloc(ifp->buf.size);
if(ifp->sendbuf == NULL) { if(ifp->buf.buf == NULL) {
fprintf(stderr, "Couldn't allocate sendbuf.\n"); fprintf(stderr, "Couldn't allocate sendbuf.\n");
ifp->bufsize = 0; ifp->buf.size = 0;
goto fail; goto fail;
} }
rc = resize_receive_buffer(mtu); rc = resize_receive_buffer(mtu);
if(rc < 0) if(rc < 0)
fprintf(stderr, "Warning: couldn't resize " fprintf(stderr, "Warning: couldn't resize "
"receive buffer for interface %s (%d) (%d bytes).\n", "receive buffer for interface %s (%u) (%d bytes).\n",
ifp->name, ifp->ifindex, mtu); ifp->name, ifp->ifindex, mtu);
type = IF_CONF(ifp, type); type = IF_CONF(ifp, type);
...@@ -345,7 +349,7 @@ interface_up(struct interface *ifp, int up) ...@@ -345,7 +349,7 @@ interface_up(struct interface *ifp, int up)
rc = kernel_interface_wireless(ifp->name, ifp->ifindex); rc = kernel_interface_wireless(ifp->name, ifp->ifindex);
if(rc < 0) { if(rc < 0) {
fprintf(stderr, fprintf(stderr,
"Warning: couldn't determine whether %s (%d) " "Warning: couldn't determine whether %s (%u) "
"is a wireless interface.\n", "is a wireless interface.\n",
ifp->name, ifp->ifindex); ifp->name, ifp->ifindex);
} else if(rc) { } else if(rc) {
...@@ -387,6 +391,9 @@ interface_up(struct interface *ifp, int up) ...@@ -387,6 +391,9 @@ interface_up(struct interface *ifp, int up)
if(IF_CONF(ifp, faraway) == CONFIG_YES) if(IF_CONF(ifp, faraway) == CONFIG_YES)
ifp->flags |= IF_FARAWAY; ifp->flags |= IF_FARAWAY;
if(IF_CONF(ifp, unicast) == CONFIG_YES)
ifp->flags |= IF_UNICAST;
if(IF_CONF(ifp, hello_interval) > 0) if(IF_CONF(ifp, hello_interval) > 0)
ifp->hello_interval = IF_CONF(ifp, hello_interval); ifp->hello_interval = IF_CONF(ifp, hello_interval);
else if(type == IF_TYPE_WIRELESS) else if(type == IF_TYPE_WIRELESS)
...@@ -399,6 +406,10 @@ interface_up(struct interface *ifp, int up) ...@@ -399,6 +406,10 @@ interface_up(struct interface *ifp, int up)
IF_CONF(ifp, update_interval) : IF_CONF(ifp, update_interval) :
ifp->hello_interval * 4; ifp->hello_interval * 4;
/* This must be no more than half the Hello interval, or else
Hellos will arrive late. */
ifp->buf.flush_interval = ifp->hello_interval / 2;
ifp->rtt_decay = ifp->rtt_decay =
IF_CONF(ifp, rtt_decay) > 0 ? IF_CONF(ifp, rtt_decay) > 0 ?
IF_CONF(ifp, rtt_decay) : 42; IF_CONF(ifp, rtt_decay) : 42;
...@@ -411,8 +422,8 @@ interface_up(struct interface *ifp, int up) ...@@ -411,8 +422,8 @@ interface_up(struct interface *ifp, int up)
IF_CONF(ifp, rtt_max) : 120000; IF_CONF(ifp, rtt_max) : 120000;
if(ifp->rtt_max <= ifp->rtt_min) { if(ifp->rtt_max <= ifp->rtt_min) {
fprintf(stderr, fprintf(stderr,
"Uh, rtt-max is less than or equal to rtt-min (%d <= %d). " "Uh, rtt-max is less than or equal to rtt-min (%u <= %u). "
"Setting it to %d.\n", ifp->rtt_max, ifp->rtt_min, "Setting it to %u.\n", ifp->rtt_max, ifp->rtt_min,
ifp->rtt_min + 10000); ifp->rtt_min + 10000);
ifp->rtt_max = ifp->rtt_min + 10000; ifp->rtt_max = ifp->rtt_min + 10000;
} }
...@@ -421,23 +432,20 @@ interface_up(struct interface *ifp, int up) ...@@ -421,23 +432,20 @@ interface_up(struct interface *ifp, int up)
ifp->max_rtt_penalty = 96; ifp->max_rtt_penalty = 96;
if(IF_CONF(ifp, enable_timestamps) == CONFIG_YES) if(IF_CONF(ifp, enable_timestamps) == CONFIG_YES)
ifp->flags |= IF_TIMESTAMPS; ifp->buf.enable_timestamps = 1;
else if(IF_CONF(ifp, enable_timestamps) == CONFIG_NO) else if(IF_CONF(ifp, enable_timestamps) == CONFIG_NO)
ifp->flags &= ~IF_TIMESTAMPS; ifp->buf.enable_timestamps = 0;
else if(type == IF_TYPE_TUNNEL) else if(type == IF_TYPE_TUNNEL)
ifp->flags |= IF_TIMESTAMPS; ifp->buf.enable_timestamps = 1;
else else
ifp->flags &= ~IF_TIMESTAMPS; ifp->buf.enable_timestamps = 0;
if(ifp->max_rtt_penalty > 0 && !(ifp->flags & IF_TIMESTAMPS)) if(ifp->max_rtt_penalty > 0 && !ifp->buf.enable_timestamps)
fprintf(stderr, fprintf(stderr,
"Warning: max_rtt_penalty is set " "Warning: max_rtt_penalty is set "
"but timestamps are disabled on interface %s.\n", "but timestamps are disabled on interface %s.\n",
ifp->name); ifp->name);
if(IF_CONF(ifp, rfc6126) == CONFIG_YES) ifp->buf.rfc6126_compatible = (IF_CONF(ifp, rfc6126) == CONFIG_YES);
ifp->flags |= IF_RFC6126;
else
ifp->flags &= ~IF_RFC6126;
rc = check_link_local_addresses(ifp); rc = check_link_local_addresses(ifp);
if(rc < 0) { if(rc < 0) {
...@@ -472,17 +480,18 @@ interface_up(struct interface *ifp, int up) ...@@ -472,17 +480,18 @@ interface_up(struct interface *ifp, int up)
send_hello(ifp); send_hello(ifp);
if(rc > 0) if(rc > 0)
send_update(ifp, 0, NULL, 0, NULL, 0); send_update(ifp, 0, NULL, 0, NULL, 0);
send_multicast_request(ifp, NULL, 0, NULL, 0);
} else { } else {
flush_interface_routes(ifp, 0); flush_interface_routes(ifp, 0);
ifp->buffered = 0; ifp->buf.len = 0;
ifp->bufsize = 0; ifp->buf.size = 0;
free(ifp->sendbuf); free(ifp->buf.buf);
ifp->num_buffered_updates = 0; ifp->num_buffered_updates = 0;
ifp->update_bufsize = 0; ifp->update_bufsize = 0;
if(ifp->buffered_updates) if(ifp->buffered_updates)
free(ifp->buffered_updates); free(ifp->buffered_updates);
ifp->buffered_updates = NULL; ifp->buffered_updates = NULL;
ifp->sendbuf = NULL; ifp->buf.buf = NULL;
if(ifp->ifindex > 0) { if(ifp->ifindex > 0) {
memset(&mreq, 0, sizeof(mreq)); memset(&mreq, 0, sizeof(mreq));
memcpy(&mreq.ipv6mr_multiaddr, protocol_group, 16); memcpy(&mreq.ipv6mr_multiaddr, protocol_group, 16);
...@@ -558,6 +567,7 @@ check_interfaces(void) ...@@ -558,6 +567,7 @@ check_interfaces(void)
check_interface_channel(ifp); check_interface_channel(ifp);
rc = check_interface_ipv4(ifp); rc = check_interface_ipv4(ifp);
if(rc > 0) { if(rc > 0) {
send_multicast_request(ifp, NULL, 0, NULL, 0);
send_update(ifp, 0, NULL, 0, NULL, 0); send_update(ifp, 0, NULL, 0, NULL, 0);
} }
} }
......
...@@ -45,6 +45,7 @@ struct interface_conf { ...@@ -45,6 +45,7 @@ struct interface_conf {
char split_horizon; char split_horizon;
char lq; char lq;
char faraway; char faraway;
char unicast;
int channel; int channel;
int enable_timestamps; int enable_timestamps;
int rfc6126; int rfc6126;
...@@ -69,16 +70,34 @@ struct interface_conf { ...@@ -69,16 +70,34 @@ struct interface_conf {
#define IF_LQ (1 << 3) #define IF_LQ (1 << 3)
/* Nodes on the far end don't interfere with nodes on the near end. */ /* Nodes on the far end don't interfere with nodes on the near end. */
#define IF_FARAWAY (1 << 4) #define IF_FARAWAY (1 << 4)
/* Send timestamps in Hello and IHU. */ /* Send most TLVs over unicast. */
#define IF_TIMESTAMPS (1 << 5) #define IF_UNICAST (1 << 5)
/* Remain compatible with RFC 6126. */
#define IF_RFC6126 (1 << 6)
/* Only INTERFERING can appear on the wire. */ /* Only INTERFERING can appear on the wire. */
#define IF_CHANNEL_UNKNOWN 0 #define IF_CHANNEL_UNKNOWN 0
#define IF_CHANNEL_INTERFERING 255 #define IF_CHANNEL_INTERFERING 255
#define IF_CHANNEL_NONINTERFERING -2 #define IF_CHANNEL_NONINTERFERING -2
struct buffered {
struct sockaddr_in6 sin6;
char *buf;
int len;
int size;
int flush_interval;
struct timeval timeout;
char enable_timestamps;
char rfc6126_compatible;
char have_id;
char have_nh;
char have_prefix;
unsigned char id[8];
unsigned char nh[4];
unsigned char prefix[16];
/* Relative position of the Hello message in the send buffer, or
(-1) if there is none. */
int hello;
};
struct interface { struct interface {
struct interface *next; struct interface *next;
struct interface_conf *conf; struct interface_conf *conf;
...@@ -88,31 +107,16 @@ struct interface { ...@@ -88,31 +107,16 @@ struct interface {
int channel; int channel;
struct timeval hello_timeout; struct timeval hello_timeout;
struct timeval update_timeout; struct timeval update_timeout;
struct timeval flush_timeout;
struct timeval update_flush_timeout; struct timeval update_flush_timeout;
char name[IF_NAMESIZE]; char name[IF_NAMESIZE];
unsigned char *ipv4; unsigned char *ipv4;
int numll; int numll;
unsigned char (*ll)[16]; unsigned char (*ll)[16];
int buffered; struct buffered buf;
int bufsize;
/* Relative position of the Hello message in the send buffer, or
(-1) if there is none. */
int buffered_hello;
char have_buffered_id;
char have_buffered_nh;
char have_buffered_prefix;
unsigned char buffered_id[8];
unsigned char buffered_nh[4];
unsigned char buffered_prefix[16];
unsigned char *sendbuf;
struct buffered_update *buffered_updates; struct buffered_update *buffered_updates;
int num_buffered_updates; int num_buffered_updates;
int update_bufsize; int update_bufsize;
time_t bucket_time;
unsigned int bucket;
time_t last_update_time; time_t last_update_time;
time_t last_specific_update_time;
unsigned short hello_seqno; unsigned short hello_seqno;
unsigned hello_interval; unsigned hello_interval;
unsigned update_interval; unsigned update_interval;
...@@ -140,7 +144,7 @@ if_up(struct interface *ifp) ...@@ -140,7 +144,7 @@ if_up(struct interface *ifp)
struct interface *add_interface(char *ifname, struct interface_conf *if_conf); struct interface *add_interface(char *ifname, struct interface_conf *if_conf);
int flush_interface(char *ifname); int flush_interface(char *ifname);
unsigned jitter(struct interface *ifp, int urgent); unsigned jitter(struct buffered *buf, int urgent);
unsigned update_jitter(struct interface *ifp, int urgent); unsigned update_jitter(struct interface *ifp, int urgent);
void set_timeout(struct timeval *timeout, int msecs); void set_timeout(struct timeval *timeout, int msecs);
int interface_up(struct interface *ifp, int up); int interface_up(struct interface *ifp, int up);
......
...@@ -446,7 +446,7 @@ netlink_talk(struct nlmsghdr *nh) ...@@ -446,7 +446,7 @@ netlink_talk(struct nlmsghdr *nh)
nh->nlmsg_seq = ++nl_command.seqno; nh->nlmsg_seq = ++nl_command.seqno;
kdebugf("Sending seqno %d from address %p (talk)\n", kdebugf("Sending seqno %d from address %p (talk)\n",
nl_command.seqno, &nl_command.seqno); nl_command.seqno, (void*)&nl_command.seqno);
rc = sendmsg(nl_command.sock, &msg, 0); rc = sendmsg(nl_command.sock, &msg, 0);
if(rc < 0 && (errno == EAGAIN || errno == EINTR)) { if(rc < 0 && (errno == EAGAIN || errno == EINTR)) {
...@@ -514,7 +514,7 @@ netlink_send_dump(int type, void *data, int len) { ...@@ -514,7 +514,7 @@ netlink_send_dump(int type, void *data, int len) {
buf.nh.nlmsg_len = NLMSG_LENGTH(len); buf.nh.nlmsg_len = NLMSG_LENGTH(len);
kdebugf("Sending seqno %d from address %p (dump)\n", kdebugf("Sending seqno %d from address %p (dump)\n",
nl_command.seqno, &nl_command.seqno); nl_command.seqno, (void*)&nl_command.seqno);
rc = sendmsg(nl_command.sock, &msg, 0); rc = sendmsg(nl_command.sock, &msg, 0);
if(rc < buf.nh.nlmsg_len) { if(rc < buf.nh.nlmsg_len) {
...@@ -677,14 +677,18 @@ kernel_setup_interface(int setup, const char *ifname, int ifindex) ...@@ -677,14 +677,18 @@ kernel_setup_interface(int setup, const char *ifname, int ifindex)
fprintf(stderr, fprintf(stderr,
"Warning: cannot save old configuration for %s.\n", "Warning: cannot save old configuration for %s.\n",
ifname); ifname);
if(old_if[i].rp_filter) {
rc = write_proc(buf, 0); rc = write_proc(buf, 0);
if(rc < 0) if(rc < 0)
return -1; return -1;
}
} else { } else {
if(i >= 0 && old_if[i].rp_filter >= 0) if(i >= 0 && old_if[i].rp_filter > 0)
rc = write_proc(buf, old_if[i].rp_filter); rc = write_proc(buf, old_if[i].rp_filter);
else else if(i < 0)
rc = -1; rc = -1;
else
rc = 1;
if(rc < 0) if(rc < 0)
fprintf(stderr, fprintf(stderr,
...@@ -1590,7 +1594,7 @@ add_rule(int prio, const unsigned char *src_prefix, int src_plen, int table) ...@@ -1590,7 +1594,7 @@ add_rule(int prio, const unsigned char *src_prefix, int src_plen, int table)
message_header->nlmsg_len += current_attribute->rta_len; message_header->nlmsg_len += current_attribute->rta_len;
current_attribute = (void*) current_attribute = (void*)
((char*)current_attribute) + current_attribute->rta_len; ((char*)current_attribute + current_attribute->rta_len);
/* src */ /* src */
current_attribute->rta_len = RTA_LENGTH(addr_size); current_attribute->rta_len = RTA_LENGTH(addr_size);
...@@ -1599,7 +1603,7 @@ add_rule(int prio, const unsigned char *src_prefix, int src_plen, int table) ...@@ -1599,7 +1603,7 @@ add_rule(int prio, const unsigned char *src_prefix, int src_plen, int table)
message_header->nlmsg_len += current_attribute->rta_len; message_header->nlmsg_len += current_attribute->rta_len;
current_attribute = (void*) current_attribute = (void*)
((char*)current_attribute) + current_attribute->rta_len; ((char*)current_attribute + current_attribute->rta_len);
/* send message */ /* send message */
if(message_header->nlmsg_len > 64) { if(message_header->nlmsg_len > 64) {
...@@ -1652,7 +1656,7 @@ flush_rule(int prio, int family) ...@@ -1652,7 +1656,7 @@ flush_rule(int prio, int family)
message_header->nlmsg_len += current_attribute->rta_len; message_header->nlmsg_len += current_attribute->rta_len;
current_attribute = (void*) current_attribute = (void*)
((char*)current_attribute) + current_attribute->rta_len; ((char*)current_attribute + current_attribute->rta_len);
/* send message */ /* send message */
if(message_header->nlmsg_len > 64) { if(message_header->nlmsg_len > 64) {
......
...@@ -44,11 +44,13 @@ THE SOFTWARE. ...@@ -44,11 +44,13 @@ THE SOFTWARE.
#include <net/route.h> #include <net/route.h>
#include "babeld.h" #include "babeld.h"
#include "interface.h"
#include "neighbour.h" #include "neighbour.h"
#include "kernel.h" #include "kernel.h"
#include "util.h" #include "util.h"
static int get_sdl(struct sockaddr_dl *sdl, char *ifname); static int get_sdl(struct sockaddr_dl *sdl, char *ifname);
static const unsigned char v4prefix[16] = static const unsigned char v4prefix[16] =
...@@ -586,7 +588,7 @@ print_kernel_route(int add, struct kernel_route *route) ...@@ -586,7 +588,7 @@ print_kernel_route(int add, struct kernel_route *route)
memcpy(ifname,"unk",4); memcpy(ifname,"unk",4);
fprintf(stderr, fprintf(stderr,
"%s kernel route: dest: %s gw: %s metric: %d if: %s(%d) \n", "%s kernel route: dest: %s gw: %s metric: %d if: %s(%u) \n",
add == RTM_ADD ? "Add" : add == RTM_ADD ? "Add" :
add == RTM_DELETE ? "Delete" : "Change", add == RTM_DELETE ? "Delete" : "Change",
format_prefix(route->prefix, route->plen), format_prefix(route->prefix, route->plen),
......
...@@ -145,7 +145,7 @@ local_notify_neighbour_1(struct local_socket *s, ...@@ -145,7 +145,7 @@ local_notify_neighbour_1(struct local_socket *s,
rttbuf[0] = '\0'; rttbuf[0] = '\0';
if(valid_rtt(neigh)) { if(valid_rtt(neigh)) {
rc = snprintf(rttbuf, 64, " rtt %s rttcost %d", rc = snprintf(rttbuf, 64, " rtt %s rttcost %u",
format_thousands(neigh->rtt), neighbour_rttcost(neigh)); format_thousands(neigh->rtt), neighbour_rttcost(neigh));
if(rc < 0 || rc >= 64) if(rc < 0 || rc >= 64)
rttbuf[0] = '\0'; rttbuf[0] = '\0';
...@@ -154,7 +154,7 @@ local_notify_neighbour_1(struct local_socket *s, ...@@ -154,7 +154,7 @@ local_notify_neighbour_1(struct local_socket *s,
rc = snprintf(buf, 512, rc = snprintf(buf, 512,
"%s neighbour %lx address %s " "%s neighbour %lx address %s "
"if %s reach %04x ureach %04x " "if %s reach %04x ureach %04x "
"rxcost %d txcost %d%s cost %d\n", "rxcost %u txcost %u%s cost %u\n",
local_kind(kind), local_kind(kind),
/* Neighbours never move around in memory , so we can use the /* Neighbours never move around in memory , so we can use the
address as a unique identifier. */ address as a unique identifier. */
......
This diff is collapsed.
...@@ -22,9 +22,6 @@ THE SOFTWARE. ...@@ -22,9 +22,6 @@ THE SOFTWARE.
#define MAX_BUFFERED_UPDATES 200 #define MAX_BUFFERED_UPDATES 200
#define BUCKET_TOKENS_MAX 4000
#define BUCKET_TOKENS_PER_SEC 1000
#define MESSAGE_PAD1 0 #define MESSAGE_PAD1 0
#define MESSAGE_PADN 1 #define MESSAGE_PADN 1
#define MESSAGE_ACK_REQ 2 #define MESSAGE_ACK_REQ 2
...@@ -37,15 +34,13 @@ THE SOFTWARE. ...@@ -37,15 +34,13 @@ THE SOFTWARE.
#define MESSAGE_REQUEST 9 #define MESSAGE_REQUEST 9
#define MESSAGE_MH_REQUEST 10 #define MESSAGE_MH_REQUEST 10
/* 11 and 12 are for authentication */ /* 11 and 12 are for authentication */
#define MESSAGE_UPDATE_SRC_SPECIFIC 13
#define MESSAGE_REQUEST_SRC_SPECIFIC 14
#define MESSAGE_MH_REQUEST_SRC_SPECIFIC 15
/* Protocol extension through sub-TLVs. */ /* Protocol extension through sub-TLVs. */
#define SUBTLV_PAD1 0 #define SUBTLV_PAD1 0
#define SUBTLV_PADN 1 #define SUBTLV_PADN 1
#define SUBTLV_DIVERSITY 2 /* Also known as babelz. */ #define SUBTLV_DIVERSITY 2 /* Also known as babelz. */
#define SUBTLV_TIMESTAMP 3 /* Used to compute RTT. */ #define SUBTLV_TIMESTAMP 3 /* Used to compute RTT. */
#define SUBTLV_SOURCE_PREFIX 128 /* Source-specific routing. */
extern unsigned short myseqno; extern unsigned short myseqno;
extern struct timeval seqno_time; extern struct timeval seqno_time;
...@@ -55,16 +50,13 @@ extern int split_horizon; ...@@ -55,16 +50,13 @@ extern int split_horizon;
extern unsigned char packet_header[4]; extern unsigned char packet_header[4];
extern struct neighbour *unicast_neighbour;
extern struct timeval unicast_flush_timeout;
void parse_packet(const unsigned char *from, struct interface *ifp, void parse_packet(const unsigned char *from, struct interface *ifp,
const unsigned char *packet, int packetlen); const unsigned char *packet, int packetlen);
void flushbuf(struct interface *ifp); void flushbuf(struct buffered *buf);
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_noupdate(struct interface *ifp, unsigned interval); void send_hello_noihu(struct interface *ifp, unsigned interval);
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,
...@@ -79,14 +71,15 @@ void update_myseqno(void); ...@@ -79,14 +71,15 @@ void update_myseqno(void);
void send_self_update(struct interface *ifp); void send_self_update(struct interface *ifp);
void send_ihu(struct neighbour *neigh, struct interface *ifp); void send_ihu(struct neighbour *neigh, struct interface *ifp);
void send_marginal_ihu(struct interface *ifp); void send_marginal_ihu(struct interface *ifp);
void send_request(struct interface *ifp, void send_multicast_request(struct interface *ifp,
const unsigned char *prefix, unsigned char plen, const unsigned char *prefix, unsigned char plen,
const unsigned char *src_prefix, unsigned char src_plen); const unsigned char *src_prefix, unsigned char src_plen);
void send_unicast_request(struct neighbour *neigh, void send_unicast_request(struct neighbour *neigh,
const unsigned char *prefix, unsigned char plen, const unsigned char *prefix, unsigned char plen,
const unsigned char *src_prefix, const unsigned char *src_prefix,
unsigned char src_plen); unsigned char src_plen);
void send_multihop_request(struct interface *ifp, void
send_multicast_multihop_request(struct interface *ifp,
const unsigned char *prefix, unsigned char plen, const unsigned char *prefix, unsigned char plen,
const unsigned char *src_prefix, const unsigned char *src_prefix,
unsigned char src_plen, unsigned char src_plen,
......
...@@ -24,6 +24,8 @@ THE SOFTWARE. ...@@ -24,6 +24,8 @@ THE SOFTWARE.
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#include <sys/time.h> #include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <time.h> #include <time.h>
#include <assert.h> #include <assert.h>
...@@ -55,8 +57,6 @@ void ...@@ -55,8 +57,6 @@ void
flush_neighbour(struct neighbour *neigh) flush_neighbour(struct neighbour *neigh)
{ {
flush_neighbour_routes(neigh); flush_neighbour_routes(neigh);
if(unicast_neighbour == neigh)
flush_unicast(1);
flush_resends(neigh); flush_resends(neigh);
if(neighs == neigh) { if(neighs == neigh) {
...@@ -68,6 +68,7 @@ flush_neighbour(struct neighbour *neigh) ...@@ -68,6 +68,7 @@ flush_neighbour(struct neighbour *neigh)
previous->next = neigh->next; previous->next = neigh->next;
} }
local_notify_neighbour(neigh, LOCAL_FLUSH); local_notify_neighbour(neigh, LOCAL_FLUSH);
free(neigh->buf.buf);
free(neigh); free(neigh);
} }
...@@ -76,6 +77,7 @@ find_neighbour(const unsigned char *address, struct interface *ifp) ...@@ -76,6 +77,7 @@ find_neighbour(const unsigned char *address, struct interface *ifp)
{ {
struct neighbour *neigh; struct neighbour *neigh;
const struct timeval zero = {0, 0}; const struct timeval zero = {0, 0};
char *buf;
neigh = find_neighbour_nocreate(address, ifp); neigh = find_neighbour_nocreate(address, ifp);
if(neigh) if(neigh)
...@@ -84,8 +86,15 @@ find_neighbour(const unsigned char *address, struct interface *ifp) ...@@ -84,8 +86,15 @@ find_neighbour(const unsigned char *address, struct interface *ifp)
debugf("Creating neighbour %s on %s.\n", debugf("Creating neighbour %s on %s.\n",
format_address(address), ifp->name); format_address(address), ifp->name);
buf = malloc(ifp->buf.size);
if(buf == NULL) {
perror("malloc(neighbour->buf)");
return NULL;
}
neigh = calloc(1, sizeof(struct neighbour)); neigh = calloc(1, sizeof(struct neighbour));
if(neigh == NULL) { if(neigh == NULL) {
free(buf);
perror("malloc(neighbour)"); perror("malloc(neighbour)");
return NULL; return NULL;
} }
...@@ -98,6 +107,13 @@ find_neighbour(const unsigned char *address, struct interface *ifp) ...@@ -98,6 +107,13 @@ find_neighbour(const unsigned char *address, struct interface *ifp)
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;
neigh->buf.buf = buf;
neigh->buf.size = ifp->buf.size;
neigh->buf.flush_interval = ifp->buf.flush_interval;
neigh->buf.sin6.sin6_family = AF_INET6;
memcpy(&neigh->buf.sin6.sin6_addr, address, 16);
neigh->buf.sin6.sin6_port = htons(protocol_port);
neigh->buf.sin6.sin6_scope_id = ifp->ifindex;
neigh->next = neighs; neigh->next = neighs;
neighs = neigh; neighs = neigh;
local_notify_neighbour(neigh, LOCAL_ADD); local_notify_neighbour(neigh, LOCAL_ADD);
...@@ -135,6 +151,11 @@ update_neighbour(struct neighbour *neigh, struct hello_history *hist, ...@@ -135,6 +151,11 @@ update_neighbour(struct neighbour *neigh, struct hello_history *hist,
missed_hellos = 0; missed_hellos = 0;
rc = 1; rc = 1;
} else if(missed_hellos < 0) { } else if(missed_hellos < 0) {
/* Late hello. Probably due to the link layer buffering
packets during a link outage or a cpu overload. */
fprintf(stderr,
"Late hello: bufferbloated neighbor %s\n",
format_address(neigh->address));
hist->reach <<= -missed_hellos; hist->reach <<= -missed_hellos;
missed_hellos = 0; missed_hellos = 0;
rc = 1; rc = 1;
......
...@@ -44,6 +44,7 @@ struct neighbour { ...@@ -44,6 +44,7 @@ struct neighbour {
unsigned int rtt; unsigned int rtt;
struct timeval rtt_time; struct timeval rtt_time;
struct interface *ifp; struct interface *ifp;
struct buffered buf;
}; };
extern struct neighbour *neighs; extern struct neighbour *neighs;
......
...@@ -24,13 +24,15 @@ THE SOFTWARE. ...@@ -24,13 +24,15 @@ THE SOFTWARE.
#include <time.h> #include <time.h>
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include "babeld.h" #include "babeld.h"
#include "util.h" #include "util.h"
#include "interface.h"
#include "neighbour.h" #include "neighbour.h"
#include "resend.h" #include "resend.h"
#include "message.h" #include "message.h"
#include "interface.h"
#include "configuration.h" #include "configuration.h"
struct timeval resend_time = {0, 0}; struct timeval resend_time = {0, 0};
...@@ -304,10 +306,12 @@ do_resend() ...@@ -304,10 +306,12 @@ do_resend()
if(timeval_compare(&now, &timeout) >= 0) { if(timeval_compare(&now, &timeout) >= 0) {
switch(resend->kind) { switch(resend->kind) {
case RESEND_REQUEST: case RESEND_REQUEST:
send_multihop_request(resend->ifp, send_multicast_multihop_request(resend->ifp,
resend->prefix, resend->plen, resend->prefix, resend->plen,
resend->src_prefix, resend->src_plen, resend->src_prefix,
resend->seqno, resend->id, 127); resend->src_plen,
resend->seqno, resend->id,
127);
break; break;
case RESEND_UPDATE: case RESEND_UPDATE:
send_update(resend->ifp, 1, send_update(resend->ifp, 1,
......
...@@ -1139,7 +1139,7 @@ send_triggered_update(struct babel_route *route, struct source *oldsrc, ...@@ -1139,7 +1139,7 @@ send_triggered_update(struct babel_route *route, struct source *oldsrc,
if(oldmetric < INFINITY) { if(oldmetric < INFINITY) {
if(newmetric >= oldmetric + 288) { if(newmetric >= oldmetric + 288) {
send_request(NULL, route->src->prefix, route->src->plen, send_multicast_request(NULL, route->src->prefix, route->src->plen,
route->src->src_prefix, route->src->src_plen); route->src->src_prefix, route->src->src_plen);
} }
} }
......
...@@ -24,6 +24,8 @@ THE SOFTWARE. ...@@ -24,6 +24,8 @@ THE SOFTWARE.
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <sys/time.h> #include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <assert.h> #include <assert.h>
#include "babeld.h" #include "babeld.h"
......
...@@ -302,7 +302,7 @@ format_thousands(unsigned int value) ...@@ -302,7 +302,7 @@ format_thousands(unsigned int value)
static char buf[4][15]; static char buf[4][15];
static int i = 0; static int i = 0;
i = (i + 1) % 4; i = (i + 1) % 4;
snprintf(buf[i], 15, "%d.%.3d", value / 1000, value % 1000); snprintf(buf[i], 15, "%u.%.3u", value / 1000, value % 1000);
return buf[i]; return buf[i];
} }
......
...@@ -88,7 +88,7 @@ unsigned char *normalize_prefix(unsigned char *restrict ret, ...@@ -88,7 +88,7 @@ unsigned char *normalize_prefix(unsigned char *restrict ret,
const unsigned char *restrict prefix, const unsigned char *restrict prefix,
unsigned char plen); unsigned char plen);
const char *format_address(const unsigned char *address); const char *format_address(const unsigned char *address);
const char *format_prefix(const unsigned char *address, unsigned char prefix); const char *format_prefix(const unsigned char *prefix, unsigned char plen);
const char *format_eui64(const unsigned char *eui); const char *format_eui64(const unsigned char *eui);
const char *format_thousands(unsigned int value); const char *format_thousands(unsigned int value);
int parse_address(const char *address, unsigned char *addr_r, int *af_r); int parse_address(const char *address, unsigned char *addr_r, int *af_r);
...@@ -161,4 +161,3 @@ static inline void kdebugf(const char *format, ...) { return; } ...@@ -161,4 +161,3 @@ static inline void kdebugf(const char *format, ...) { return; }
#endif #endif
#endif #endif
This diff is collapsed.
...@@ -34,10 +34,10 @@ struct xroute_stream; ...@@ -34,10 +34,10 @@ struct xroute_stream;
struct xroute *find_xroute(const unsigned char *prefix, unsigned char plen, struct xroute *find_xroute(const unsigned char *prefix, unsigned char plen,
const unsigned char *src_prefix, unsigned char src_plen); const unsigned char *src_prefix, unsigned char src_plen);
void flush_xroute(struct xroute *xroute);
int add_xroute(unsigned char prefix[16], unsigned char plen, int add_xroute(unsigned char prefix[16], unsigned char plen,
unsigned char src_prefix[16], unsigned char src_plen, unsigned char src_prefix[16], unsigned char src_plen,
unsigned short metric, unsigned int ifindex, int proto); unsigned short metric, unsigned int ifindex, int proto);
void flush_xroute(struct xroute *xroute);
int xroutes_estimate(void); int xroutes_estimate(void);
struct xroute_stream *xroute_stream(); struct xroute_stream *xroute_stream();
struct xroute *xroute_stream_next(struct xroute_stream *stream); struct xroute *xroute_stream_next(struct xroute_stream *stream);
......
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