Commit 70e80799 authored by Juliusz Chroboczek's avatar Juliusz Chroboczek

Maintain buffered_updates per network.

This makes multi-interface nodes less noisy.
parent f98459d5
...@@ -52,17 +52,6 @@ unsigned short myseqno = 0; ...@@ -52,17 +52,6 @@ unsigned short myseqno = 0;
struct timeval seqno_time = {0, 0}; struct timeval seqno_time = {0, 0};
int seqno_interval = -1; int seqno_interval = -1;
struct buffered_update {
unsigned char id[8];
unsigned char prefix[16];
unsigned char plen;
unsigned char pad[3];
};
struct buffered_update buffered_updates[MAX_BUFFERED_UPDATES]
ATTRIBUTE ((aligned (4)));
struct network *update_net = NULL;
int updates = 0;
#define UNICAST_BUFSIZE 1024 #define UNICAST_BUFSIZE 1024
int unicast_buffered = 0; int unicast_buffered = 0;
unsigned char *unicast_buffer = NULL; unsigned char *unicast_buffer = NULL;
...@@ -841,7 +830,7 @@ compare_buffered_updates(const void *av, const void *bv) ...@@ -841,7 +830,7 @@ compare_buffered_updates(const void *av, const void *bv)
} }
void void
flushupdates(struct network *network) flushupdates(struct network *net)
{ {
struct xroute *xroute; struct xroute *xroute;
struct route *route; struct route *route;
...@@ -849,31 +838,39 @@ flushupdates(struct network *network) ...@@ -849,31 +838,39 @@ flushupdates(struct network *network)
unsigned char last_plen = 0xFF; unsigned char last_plen = 0xFF;
int i; int i;
if(network && network != update_net) if(net == NULL) {
struct network *n;
FOR_ALL_NETS(n)
flushupdates(n);
return; return;
}
if(net->num_buffered_updates > 0) {
struct buffered_update *b = net->buffered_updates;
int n = net->num_buffered_updates;
net->buffered_updates = NULL;
net->update_bufsize = 0;
net->num_buffered_updates = 0;
if(updates > 0) { if(!net->up)
int n = updates; goto done;
struct network *net = update_net;
updates = 0;
update_net = NULL;
debugf(" (flushing %d buffered updates)\n", n); debugf(" (flushing %d buffered updates on %s (%d))\n",
n, net->ifname, net->ifindex);
/* In order to send fewer update messages, we want to send updates /* In order to send fewer update messages, we want to send updates
with the same router-id together, with IPv6 going out before IPv4. */ with the same router-id together, with IPv6 going out before IPv4. */
for(i = 0; i < n; i++) { for(i = 0; i < n; i++) {
route = find_installed_route(buffered_updates[i].prefix, route = find_installed_route(b[i].prefix, b[i].plen);
buffered_updates[i].plen);
if(route) if(route)
memcpy(buffered_updates[i].id, route->src->id, 8); memcpy(b[i].id, route->src->id, 8);
else else
memcpy(buffered_updates[i].id, myid, 8); memcpy(b[i].id, myid, 8);
} }
qsort(buffered_updates, n, sizeof(struct buffered_update), qsort(b, n, sizeof(struct buffered_update), compare_buffered_updates);
compare_buffered_updates);
for(i = 0; i < n; i++) { for(i = 0; i < n; i++) {
unsigned short seqno; unsigned short seqno;
...@@ -884,13 +881,12 @@ flushupdates(struct network *network) ...@@ -884,13 +881,12 @@ flushupdates(struct network *network)
compare with the previous update. */ compare with the previous update. */
if(last_prefix) { if(last_prefix) {
if(buffered_updates[i].plen == last_plen && if(b[i].plen == last_plen &&
memcmp(buffered_updates[i].prefix, last_prefix, 16) == 0) memcmp(b[i].prefix, last_prefix, 16) == 0)
continue; continue;
} }
xroute = find_xroute(buffered_updates[i].prefix, xroute = find_xroute(b[i].prefix, b[i].plen);
buffered_updates[i].plen);
if(xroute) { if(xroute) {
really_send_update(net, myid, really_send_update(net, myid,
xroute->prefix, xroute->plen, xroute->prefix, xroute->plen,
...@@ -899,8 +895,7 @@ flushupdates(struct network *network) ...@@ -899,8 +895,7 @@ flushupdates(struct network *network)
last_plen = xroute->plen; last_plen = xroute->plen;
continue; continue;
} }
route = find_installed_route(buffered_updates[i].prefix, route = find_installed_route(b[i].prefix, b[i].plen);
buffered_updates[i].plen);
if(route) { if(route) {
seqno = route->seqno; seqno = route->seqno;
metric = route->metric; metric = route->metric;
...@@ -920,8 +915,8 @@ flushupdates(struct network *network) ...@@ -920,8 +915,8 @@ flushupdates(struct network *network)
} }
} }
schedule_flush_now(net); schedule_flush_now(net);
VALGRIND_MAKE_MEM_UNDEFINED(&buffered_updates, done:
sizeof(buffered_updates)); free(b);
} }
update_flush_timeout.tv_sec = 0; update_flush_timeout.tv_sec = 0;
update_flush_timeout.tv_usec = 0; update_flush_timeout.tv_usec = 0;
...@@ -944,15 +939,32 @@ static void ...@@ -944,15 +939,32 @@ static void
buffer_update(struct network *net, buffer_update(struct network *net,
const unsigned char *prefix, unsigned char plen) const unsigned char *prefix, unsigned char plen)
{ {
flushupdates(net); if(net->num_buffered_updates > 0 &&
net->num_buffered_updates >= net->update_bufsize)
flushupdates(net);
update_net = net; if(net->update_bufsize == 0) {
int n;
assert(net->buffered_updates == NULL);
n = MAX(net->bufsize / 16, 4);
again:
net->buffered_updates = malloc(n * sizeof(struct buffered_update));
if(net->buffered_updates == NULL) {
perror("malloc(buffered_updates)");
if(n > 4) {
n = 4;
goto again;
}
return;
}
net->update_bufsize = n;
net->num_buffered_updates = 0;
}
if(updates >= MAX_BUFFERED_UPDATES) memcpy(net->buffered_updates[net->num_buffered_updates].prefix,
flushupdates(net); prefix, 16);
memcpy(buffered_updates[updates].prefix, prefix, 16); net->buffered_updates[net->num_buffered_updates].plen = plen;
buffered_updates[updates].plen = plen; net->num_buffered_updates++;
updates++;
} }
void void
......
...@@ -56,7 +56,7 @@ extern struct timeval unicast_flush_timeout; ...@@ -56,7 +56,7 @@ extern struct timeval unicast_flush_timeout;
void parse_packet(const unsigned char *from, struct network *net, void parse_packet(const unsigned char *from, struct network *net,
const unsigned char *packet, int packetlen); const unsigned char *packet, int packetlen);
void flushbuf(struct network *net); void flushbuf(struct network *net);
void flushupdates(struct network *network); void flushupdates(struct network *net);
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 network *net, unsigned interval); void send_hello_noupdate(struct network *net, unsigned interval);
......
...@@ -292,6 +292,10 @@ network_up(struct network *net, int up) ...@@ -292,6 +292,10 @@ network_up(struct network *net, int up)
net->buffered = 0; net->buffered = 0;
net->bufsize = 0; net->bufsize = 0;
free(net->sendbuf); free(net->sendbuf);
net->num_buffered_updates = 0;
net->update_bufsize = 0;
if(net->buffered_updates)
free(net->buffered_updates);
net->sendbuf = NULL; net->sendbuf = NULL;
if(net->ifindex > 0) { if(net->ifindex > 0) {
memset(&mreq, 0, sizeof(mreq)); memset(&mreq, 0, sizeof(mreq));
......
...@@ -20,6 +20,13 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ...@@ -20,6 +20,13 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE. THE SOFTWARE.
*/ */
struct buffered_update {
unsigned char id[8];
unsigned char prefix[16];
unsigned char plen;
unsigned char pad[3];
};
struct network { struct network {
struct network *next; struct network *next;
char up; char up;
...@@ -47,6 +54,9 @@ struct network { ...@@ -47,6 +54,9 @@ struct network {
unsigned char buffered_nh[4]; unsigned char buffered_nh[4];
unsigned char buffered_prefix[16]; unsigned char buffered_prefix[16];
unsigned char *sendbuf; unsigned char *sendbuf;
struct buffered_update *buffered_updates;
int num_buffered_updates;
int update_bufsize;
time_t bucket_time; time_t bucket_time;
unsigned int bucket; unsigned int bucket;
time_t activity_time; time_t activity_time;
......
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