Commit d2da6d17 authored by Juliusz Chroboczek's avatar Juliusz Chroboczek

Implement last-ditch send moderation.

parent 18811d3d
......@@ -607,6 +607,8 @@ add_network(char *ifname, int ifindex, int mtu,
}
nets[numnets].sendbuf = p;
nets[numnets].buffered = 0;
nets[numnets].bucket_time = now.tv_sec;
nets[numnets].bucket = 0;
numnets++;
return &nets[numnets - 1];
}
......
......@@ -70,6 +70,8 @@ struct network {
struct timeval flush_time;
int bufsize;
unsigned char *sendbuf;
int bucket_time;
unsigned int bucket;
unsigned char hello_seqno;
unsigned int hello_interval;
unsigned int self_update_interval;
......
......@@ -157,6 +157,28 @@ parse_packet(const unsigned char *from, struct network *net,
return;
}
/* Under normal circumstances, there are enough moderation mechanisms
elsewhere in the protocol to make sure that this last-ditch check
should never trigger. But I'm superstitious. */
static int
check_bucket(struct network *net)
{
if(net->bucket > 0 && now.tv_sec > net->bucket_time) {
net->bucket =
MAX(0, net->bucket - 40 * (now.tv_sec - net->bucket_time));
}
net->bucket_time = now.tv_sec;
if(net->bucket < 400) {
net->bucket++;
return 1;
} else {
return 0;
}
}
void
flushbuf(struct network *net)
{
......@@ -171,6 +193,7 @@ flushbuf(struct network *net)
if(net->buffered > 0) {
debugf(" (flushing %d buffered bytes on %s)\n",
net->buffered, net->ifname);
if(check_bucket(net)) {
memset(&sin6, 0, sizeof(sin6));
sin6.sin6_family = AF_INET6;
memcpy(&sin6.sin6_addr, protocol_group, 16);
......@@ -182,6 +205,10 @@ flushbuf(struct network *net)
(struct sockaddr*)&sin6, sizeof(sin6));
if(rc < 0)
perror("send");
} else {
fprintf(stderr, "Warning: bucket full, dropping packet to %s.\n",
net->ifname);
}
}
VALGRIND_MAKE_MEM_UNDEFINED(net->sendbuf, net->bufsize);
net->buffered = 0;
......@@ -273,6 +300,7 @@ send_unicast_packet(struct neighbour *neigh, unsigned char *buf, int buflen)
struct sockaddr_in6 sin6;
int rc;
if(check_bucket(neigh->network)) {
memset(&sin6, 0, sizeof(sin6));
sin6.sin6_family = AF_INET6;
memcpy(&sin6.sin6_addr, neigh->address, 16);
......@@ -284,6 +312,10 @@ send_unicast_packet(struct neighbour *neigh, unsigned char *buf, int buflen)
(struct sockaddr*)&sin6, sizeof(sin6));
if(rc < 0)
perror("send(unicast)");
} else {
fprintf(stderr, "Warning: bucket full, dropping packet to %s.\n",
neigh->network->ifname);
}
}
......
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