Commit 21045b56 authored by Juliusz Chroboczek's avatar Juliusz Chroboczek

Implement protocol version 1.

This is not compatible with version 0.  Uses 24-byte messages and
doesn't distinguish routes from xroutes.
parent b9f132d5
This diff is collapsed.
...@@ -21,12 +21,10 @@ THE SOFTWARE. ...@@ -21,12 +21,10 @@ THE SOFTWARE.
*/ */
#define MAXROUTES 512 #define MAXROUTES 512
#define MAXDESTS 1024 #define MAXSRCS 1024
#define MAXNEIGHBOURS 128 #define MAXNEIGHBOURS 128
#define MAXNETS 8 #define MAXNETS 8
#define MAXXROUTES 128 #define MAXXROUTES 64
#define MAXMYXROUTES 64
#define MAX_BUFFERED_UPDATES 100
#define INFINITY ((unsigned short)(~0)) #define INFINITY ((unsigned short)(~0))
...@@ -68,7 +66,7 @@ struct network { ...@@ -68,7 +66,7 @@ struct network {
int hello_time; int hello_time;
int self_update_time; int self_update_time;
int update_time; int update_time;
int txcost_time; int ihu_time;
char ifname[IF_NAMESIZE]; char ifname[IF_NAMESIZE];
int buffered; int buffered;
struct timeval flush_time; struct timeval flush_time;
...@@ -77,10 +75,10 @@ struct network { ...@@ -77,10 +75,10 @@ struct network {
int bucket_time; int bucket_time;
unsigned int bucket; unsigned int bucket;
int activity_time; int activity_time;
unsigned char hello_seqno; unsigned short hello_seqno;
unsigned int hello_interval; unsigned int hello_interval;
unsigned int self_update_interval; unsigned int self_update_interval;
unsigned int txcost_interval; unsigned int ihu_interval;
}; };
extern struct timeval now; extern struct timeval now;
...@@ -92,7 +90,7 @@ extern unsigned char myid[16]; ...@@ -92,7 +90,7 @@ extern unsigned char myid[16];
extern struct network nets[MAXNETS]; extern struct network nets[MAXNETS];
extern int numnets; extern int numnets;
extern const unsigned char zeroes[16]; extern const unsigned char zeroes[16], ones[16];
extern int protocol_port; extern int protocol_port;
extern unsigned char protocol_group[16]; extern unsigned char protocol_group[16];
......
...@@ -96,7 +96,7 @@ write_proc(char *filename, int value) ...@@ -96,7 +96,7 @@ write_proc(char *filename, int value)
} }
struct netlink { struct netlink {
unsigned int seqno; unsigned short seqno;
int sock; int sock;
struct sockaddr_nl sockaddr; struct sockaddr_nl sockaddr;
socklen_t socklen; socklen_t socklen;
......
This diff is collapsed.
...@@ -20,7 +20,9 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ...@@ -20,7 +20,9 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE. THE SOFTWARE.
*/ */
extern unsigned char seqno; #define MAX_BUFFERED_UPDATES 200
extern unsigned short myseqno;
extern int seqno_time; extern int seqno_time;
extern int seqno_interval; extern int seqno_interval;
...@@ -29,25 +31,26 @@ extern unsigned int update_jitter; ...@@ -29,25 +31,26 @@ extern unsigned int update_jitter;
extern int add_cost; extern int add_cost;
extern int parasitic; extern int parasitic;
extern int silent_time; extern int silent_time;
extern int broadcast_txcost; extern int broadcast_ihu;
extern int split_horizon; extern int split_horizon;
extern struct timeval update_flush_time; extern struct timeval update_flush_time;
extern const unsigned char packet_header[4]; extern const unsigned char packet_header[8];
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 len); const unsigned char *packet, int len);
void flushbuf(struct network *net); void flushbuf(struct network *net);
void send_hello(struct network *net); void send_hello(struct network *net);
void send_request(struct network *net, struct destination *dest, void send_request(struct network *net,
int hopcount, int seqno); const unsigned char *prefix, unsigned char plen);
void send_unicast_request(struct neighbour *neigh, struct destination *dest, void send_unicast_request(struct neighbour *neigh,
int hopcount, int seqno); const unsigned char *prefix, unsigned char plen);
void send_update(struct destination *dest, struct network *net); void send_update(struct network *net,
const unsigned char *prefix, unsigned char plen);
void send_self_update(struct network *net, int force_seqno); void send_self_update(struct network *net, int force_seqno);
void send_self_retract(struct network *net); void send_self_retract(struct network *net);
void send_neighbour_update(struct neighbour *neigh, struct network *net); void send_neighbour_update(struct neighbour *neigh, struct network *net);
void send_txcost(struct neighbour *neigh, struct network *net); void send_ihu(struct neighbour *neigh, struct network *net);
void schedule_flush_now(struct network *net); void schedule_flush_now(struct network *net);
void flushupdates(void); void flushupdates(void);
......
...@@ -29,9 +29,8 @@ THE SOFTWARE. ...@@ -29,9 +29,8 @@ THE SOFTWARE.
#include "babel.h" #include "babel.h"
#include "util.h" #include "util.h"
#include "neighbour.h" #include "neighbour.h"
#include "destination.h" #include "source.h"
#include "route.h" #include "route.h"
#include "xroute.h"
#include "message.h" #include "message.h"
struct neighbour neighs[MAXNEIGHBOURS]; struct neighbour neighs[MAXNEIGHBOURS];
...@@ -40,15 +39,14 @@ int numneighs = 0; ...@@ -40,15 +39,14 @@ int numneighs = 0;
void void
flush_neighbour(struct neighbour *neigh) flush_neighbour(struct neighbour *neigh)
{ {
flush_neighbour_xroutes(neigh);
flush_neighbour_routes(neigh); flush_neighbour_routes(neigh);
memset(neigh, 0, sizeof(*neigh)); memset(neigh, 0, sizeof(*neigh));
if(neigh == &neighs[numneighs - 1]) { VALGRIND_MAKE_MEM_UNDEFINED(neigh, sizeof(*neigh));
neigh->id[0] = 0xFF;
while(numneighs > 0 && neighs[numneighs - 1].id[0] == 0xFF) {
numneighs--; numneighs--;
VALGRIND_MAKE_MEM_UNDEFINED(neigh, sizeof(*neigh)); VALGRIND_MAKE_MEM_UNDEFINED(&neighs[numneighs],
} else { sizeof(neighs[numneighs]));
VALGRIND_MAKE_MEM_UNDEFINED(neigh, sizeof(*neigh));
neigh->id[0] = 0xFF;
} }
} }
...@@ -71,6 +69,7 @@ add_neighbour(const unsigned char *id, const unsigned char *address, ...@@ -71,6 +69,7 @@ add_neighbour(const unsigned char *id, const unsigned char *address,
struct network *net) struct network *net)
{ {
struct neighbour *neigh; struct neighbour *neigh;
const struct timeval zero = {0, 0};
int i; int i;
if(id[0] == 0xFF) { if(id[0] == 0xFF) {
...@@ -104,11 +103,10 @@ add_neighbour(const unsigned char *id, const unsigned char *address, ...@@ -104,11 +103,10 @@ add_neighbour(const unsigned char *id, const unsigned char *address,
} }
memcpy(neigh->id, id, 16); memcpy(neigh->id, id, 16);
memcpy(neigh->address, address, 16); memcpy(neigh->address, address, 16);
neigh->hello_interval = 0;
neigh->reach = 0; neigh->reach = 0;
neigh->txcost = INFINITY; neigh->txcost = INFINITY;
neigh->txcost_time = now.tv_sec; neigh->ihu_time = now.tv_sec;
neigh->hello_time = 0; neigh->hello_time = zero;
neigh->hello_interval = 0; neigh->hello_interval = 0;
neigh->hello_seqno = -1; neigh->hello_seqno = -1;
neigh->network = net; neigh->network = net;
...@@ -116,19 +114,23 @@ add_neighbour(const unsigned char *id, const unsigned char *address, ...@@ -116,19 +114,23 @@ add_neighbour(const unsigned char *id, const unsigned char *address,
return neigh; return neigh;
} }
void /* Recompute a neighbour's rxcost. Return true if anything changed. */
int
update_neighbour(struct neighbour *neigh, int hello, int hello_interval) update_neighbour(struct neighbour *neigh, int hello, int hello_interval)
{ {
int missed_hellos; int missed_hellos;
int rc = 0;
if(hello < 0) { if(hello < 0) {
if(neigh->hello_interval <= 0) if(neigh->hello_interval <= 0)
return; return rc;
missed_hellos = missed_hellos = (timeval_minus_msec(&now, &neigh->hello_time) -
(now.tv_sec - 3 - neigh->hello_time) / neigh->hello_interval; neigh->hello_interval * 6) /
(neigh->hello_interval * 10);
if(missed_hellos <= 0) if(missed_hellos <= 0)
return; return rc;
neigh->hello_time += missed_hellos * neigh->hello_interval; timeval_plus_msec(&neigh->hello_time, &neigh->hello_time,
missed_hellos * neigh->hello_interval * 10);
} else { } else {
if(neigh->hello_seqno >= 0 && neigh->reach > 0) { if(neigh->hello_seqno >= 0 && neigh->reach > 0) {
missed_hellos = seqno_minus(hello, neigh->hello_seqno) - 1; missed_hellos = seqno_minus(hello, neigh->hello_seqno) - 1;
...@@ -137,97 +139,120 @@ update_neighbour(struct neighbour *neigh, int hello, int hello_interval) ...@@ -137,97 +139,120 @@ update_neighbour(struct neighbour *neigh, int hello, int hello_interval)
didn't notice. */ didn't notice. */
neigh->reach <<= -missed_hellos; neigh->reach <<= -missed_hellos;
missed_hellos = 0; missed_hellos = 0;
rc = 1;
} }
} else { } else {
missed_hellos = 0; missed_hellos = 0;
} }
neigh->hello_time = now.tv_sec; neigh->hello_time = now;
neigh->hello_interval = hello_interval; neigh->hello_interval = hello_interval;
} }
neigh->reach >>= missed_hellos; if(missed_hellos > 0) {
missed_hellos = 0; neigh->reach >>= missed_hellos;
missed_hellos = 0;
rc = 1;
}
if(hello >= 0) { if(hello >= 0) {
neigh->hello_seqno = hello; neigh->hello_seqno = hello;
neigh->reach >>= 1; neigh->reach >>= 1;
neigh->reach |= 0x8000; neigh->reach |= 0x8000;
if((neigh->reach & 0xFC00) == 0xFC00)
return rc;
else
rc = 1;
} }
/* Make sure to give neighbours some feedback early after association */ /* Make sure to give neighbours some feedback early after association */
if((neigh->reach & 0xFC00) == 0x8000) { if((neigh->reach & 0xFC00) == 0x8000) {
/* A new neighbour */ /* A new neighbour */
send_hello(neigh->network); send_hello(neigh->network);
send_txcost(neigh, NULL); send_ihu(neigh, NULL);
} else { } else {
/* Don't send hellos, in order to avoid a positive feedback loop. */ /* Don't send hellos, in order to avoid a positive feedback loop. */
int a = (neigh->reach & 0xC000); int a = (neigh->reach & 0xC000);
int b = (neigh->reach & 0x3000); int b = (neigh->reach & 0x3000);
if((a == 0xC000 && b == 0) || (a == 0 && b == 0x3000)) { if((a == 0xC000 && b == 0) || (a == 0 && b == 0x3000)) {
/* Reachability is either 1100 or 0011 */ /* Reachability is either 1100 or 0011 */
send_txcost(neigh, NULL); send_ihu(neigh, NULL);
send_self_update(neigh->network, 0); send_self_update(neigh->network, 0);
send_neighbour_update(neigh, NULL); send_neighbour_update(neigh, NULL);
} }
} }
if((neigh->reach & 0xFF00) == 0xC000) { if((neigh->reach & 0xFC00) == 0xC000) {
/* This is a newish neighbour. If we don't have another route to it, /* This is a newish neighbour. If we don't have another route to it,
request a full route dump. This assumes that the neighbour's ID request a full route dump. This assumes that the neighbour's id
is also its IP address. */ is also its IP address and that it is exporting a route to itself. */
struct destination *dest;
struct route *route = NULL; struct route *route = NULL;
dest = find_destination(neigh->id, 0, 0); if(!martian_prefix(neigh->id, 128))
if(dest) route = find_installed_route(neigh->id, 128);
route = find_installed_route(dest);
if(!route || route->metric >= INFINITY || route->nexthop == neigh) if(!route || route->metric >= INFINITY || route->nexthop == neigh)
send_unicast_request(neigh, NULL, 0, -1); send_unicast_request(neigh, NULL, 0);
} }
return rc;
} }
void int
check_neighbour(struct neighbour *neigh) check_neighbours()
{ {
update_neighbour(neigh, -1, 0); int i, changed;
if(neigh->reach == 0) { int msecs = 50000;
flush_neighbour(neigh);
return; debugf("Checking neighbours.\n");
}
for(i = 0; i < numneighs; i++) {
if(neighs[i].id[0] == 0xFF)
continue;
if(!neigh->network->wired) { changed = update_neighbour(&neighs[i], -1, 0);
while(neigh->txcost < INFINITY &&
neigh->txcost_time <= now.tv_sec - 40) { if(neighs[i].reach == 0 ||
neigh->txcost = MIN((int)neigh->txcost * 3 / 2, INFINITY); timeval_minus_msec(&now, &neighs[i].hello_time) > 300000) {
neigh->txcost_time += 10; flush_neighbour(&neighs[i]);
continue;
} }
if(changed)
update_neighbour_metric(&neighs[i]);
if(neighs[i].hello_interval > 0)
msecs = MIN(msecs, neighs[i].hello_interval * 10);
} }
return msecs;
} }
int int
neighbour_rxcost(struct neighbour *neigh) neighbour_rxcost(struct neighbour *neigh)
{ {
update_neighbour(neigh, -1, 0); int delay;
if((neigh->reach & 0xF800) == 0) unsigned short reach = neigh->reach;
delay = timeval_minus_msec(&now, &neigh->hello_time);
if((reach & 0xF800) == 0 || delay >= 180000) {
return INFINITY; return INFINITY;
else if(neigh->network->wired) { } else if(neigh->network->wired) {
if((neigh->reach & 0xE000) != 0) { /* To lose one hello is a misfortune, to lose two is carelessness. */
int c = neigh->network->cost; if((reach & 0xC000) == 0xC000)
int d = now.tv_sec - neigh->hello_time; return neigh->network->cost;
if(d >= 60) else if((reach & 0xC000) == 0)
c = (c * (d - 40) + 19) / 20; return INFINITY;
return MIN(c, INFINITY); else if((reach & 0x2000))
} else { return neigh->network->cost;
else
return INFINITY; return INFINITY;
}
} else { } else {
int r = (neigh->reach & 0x7FFF) + ((neigh->reach & 0x8000) >> 1); int sreach = (reach & 0x7FFF) + ((reach & 0x8000) >> 1);
/* 0 <= r <= 0xBFFF */ /* 0 <= sreach <= 0xBFFF */
int c = (0xC000 * 0x100) / r; int cost = (0xC000 * neigh->network->cost) / (sreach + 1);
int d = now.tv_sec - neigh->hello_time; /* cost >= network->cost */
if(d >= 40) if(delay >= 40000)
c = (c * (d - 20) + 10) / 20; cost = (cost * (delay - 20000) + 10000) / 20000;
return MIN(c + neigh->network->cost, INFINITY); return MIN(cost, INFINITY);
} }
} }
...@@ -236,6 +261,9 @@ neighbour_cost(struct neighbour *neigh) ...@@ -236,6 +261,9 @@ neighbour_cost(struct neighbour *neigh)
{ {
int a, b; int a, b;
if(now.tv_sec - neigh->ihu_time >= 180)
return INFINITY;
a = neigh->txcost; a = neigh->txcost;
if(a >= INFINITY) if(a >= INFINITY)
......
...@@ -26,10 +26,10 @@ struct neighbour { ...@@ -26,10 +26,10 @@ struct neighbour {
unsigned short reach; unsigned short reach;
unsigned short txcost; unsigned short txcost;
/* This is -1 when unknown, so don't make it unsigned */ /* This is -1 when unknown, so don't make it unsigned */
short int hello_seqno; int hello_seqno;
int txcost_time; int ihu_time;
int hello_time; struct timeval hello_time;
int hello_interval; unsigned short hello_interval; /* in centiseconds */
struct network *network; struct network *network;
}; };
...@@ -42,7 +42,7 @@ struct neighbour *find_neighbour(const unsigned char *address, ...@@ -42,7 +42,7 @@ struct neighbour *find_neighbour(const unsigned char *address,
struct neighbour * struct neighbour *
add_neighbour(const unsigned char *id, const unsigned char *address, add_neighbour(const unsigned char *id, const unsigned char *address,
struct network *net); struct network *net);
void update_neighbour(struct neighbour *neigh, int hello, int hello_interval); int update_neighbour(struct neighbour *neigh, int hello, int hello_interval);
void check_neighbour(struct neighbour *neigh); int check_neighbours(void);
int neighbour_rxcost(struct neighbour *neigh); int neighbour_rxcost(struct neighbour *neigh);
int neighbour_cost(struct neighbour *neigh); int neighbour_cost(struct neighbour *neigh);
This diff is collapsed.
...@@ -20,13 +20,11 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ...@@ -20,13 +20,11 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE. THE SOFTWARE.
*/ */
struct xroute;
struct route { struct route {
struct destination *dest; struct source *src;
unsigned short metric; unsigned short metric;
unsigned short refmetric; unsigned short refmetric;
unsigned char seqno; unsigned short seqno;
struct neighbour *nexthop; struct neighbour *nexthop;
int time; int time;
int origtime; int origtime;
...@@ -39,22 +37,33 @@ extern int kernel_metric; ...@@ -39,22 +37,33 @@ extern int kernel_metric;
extern int route_timeout_delay; extern int route_timeout_delay;
extern int route_gc_delay; extern int route_gc_delay;
struct route *find_route(struct destination *dest, struct neighbour *nexthop); struct route *find_route(const unsigned char *prefix, unsigned char plen,
struct route *find_installed_route(struct destination *dest); struct neighbour *nexthop);
struct route *find_installed_route(const unsigned char *prefix,
unsigned char plen);
void flush_route(struct route *route); void flush_route(struct route *route);
void flush_neighbour_routes(struct neighbour *neigh); void flush_neighbour_routes(struct neighbour *neigh);
unsigned int metric_to_kernel(int metric); unsigned int metric_to_kernel(int metric);
void install_route(struct route *route); void install_route(struct route *route);
void uninstall_route(struct route *route); void uninstall_route(struct route *route);
void change_route_metric(struct route *route, int newmetric);
int route_feasible(struct route *route); int route_feasible(struct route *route);
int update_feasible(unsigned char seqno, unsigned short refmetric, int update_feasible(const unsigned char *a,
struct destination *dest); const unsigned char *p, unsigned char plen,
struct route *find_best_route(struct destination *dest); unsigned short seqno, unsigned short refmetric);
struct route *find_best_route(const unsigned char *prefix, unsigned char plen);
struct route *install_best_route(const unsigned char prefix[16],
unsigned char plen);
void update_neighbour_metric(struct neighbour *neigh); void update_neighbour_metric(struct neighbour *neigh);
void update_route_metric(struct route *route); void update_route_metric(struct route *route);
struct route *update_route(const unsigned char *d, int seqno, int refmetric, struct route *update_route(const unsigned char *a,
struct neighbour *nexthop, const unsigned char *p, unsigned char plen,
struct xroute *pxroutes, int numpxroutes); unsigned short seqno, unsigned short refmetric,
struct neighbour *nexthop);
void consider_route(struct route *route); void consider_route(struct route *route);
void change_route_metric(struct route *route, int newmetric); void send_triggered_update(struct route *route,
void send_triggered_update(struct route *route, int oldmetric); struct source *oldsrc, int oldmetric);
void trigger_route_change(struct route *route,
struct source *oldsrc, unsigned short oldmetric);
void route_lost(struct source *src, int oldmetric);
void expire_routes(void);
...@@ -23,107 +23,86 @@ THE SOFTWARE. ...@@ -23,107 +23,86 @@ THE SOFTWARE.
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <assert.h>
#include "babel.h" #include "babel.h"
#include "util.h" #include "util.h"
#include "destination.h" #include "source.h"
struct destination dests[MAXDESTS]; struct source srcs[MAXSRCS];
int numdests = 0; int numsrcs = 0;
struct destination * struct source *
find_destination(const unsigned char *d, int create, unsigned char seqno) find_source(const unsigned char *a, const unsigned char *p, unsigned char plen,
int create, unsigned short seqno)
{ {
int i; int i;
for(i = 0; i < numdests; i++) { for(i = 0; i < numsrcs; i++) {
/* This should really be a hash table. For now, check the /* This should really be a hash table. For now, check the
last byte first. */ last byte first. */
if(dests[i].address[15] != d[15]) if(srcs[i].address[15] != a[15])
continue; continue;
if(memcmp(dests[i].address, d, 16) == 0) if(memcmp(srcs[i].address, a, 16) != 0)
return &dests[i]; continue;
if(source_match(&srcs[i], p, plen))
return &srcs[i];
} }
if(!create) if(!create)
return NULL; return NULL;
if(numdests >= MAXDESTS) { if(numsrcs >= MAXSRCS) {
fprintf(stderr, "Too many destinations.\n"); fprintf(stderr, "Too many sources.\n");
return NULL; return NULL;
} }
memcpy(dests[numdests].address, d, 16); memcpy(srcs[numsrcs].address, a, 16);
dests[numdests].seqno = seqno; memcpy(srcs[numsrcs].prefix, p, 16);
dests[numdests].metric = INFINITY; srcs[numsrcs].plen = plen;
dests[numdests].time = now.tv_sec; srcs[numsrcs].seqno = seqno;
dests[numdests].requested_seqno = -1; srcs[numsrcs].metric = INFINITY;
dests[numdests].requested_net = NULL; srcs[numsrcs].time = now.tv_sec;
return &dests[numdests++]; return &srcs[numsrcs++];
} }
void struct source *
update_destination(struct destination *dest, find_recent_source(const unsigned char *p, unsigned char plen)
unsigned char seqno, unsigned short metric)
{ {
if(seqno_compare(dest->seqno, seqno) < 0 || int i;
(dest->seqno == seqno && dest->metric > metric)) { struct source *src = NULL;
dest->seqno = seqno;
dest->metric = metric;
}
dest->time = now.tv_sec;
if(dest->requested_seqno >= 0) {
if(seqno_minus(dest->requested_seqno, seqno) >= 16) {
/* Stale data? */
dest->requested_seqno = -1;
dest->requested_net = NULL;
}
}
}
void for(i = 0; i < numsrcs; i++) {
notice_request(struct destination *dest, unsigned char seqno, if(!source_match(&srcs[i], p, plen))
struct network *net) continue;
{ if(!src || src->time < srcs[i].time)
if(dest->requested_seqno < 0) { src = &srcs[i];
dest->requested_seqno = seqno;
dest->requested_net = net;
} else {
if(seqno_compare(dest->requested_seqno, seqno) < 0)
dest->requested_seqno = seqno;
if(net == NULL || net != dest->requested_net)
dest->requested_net = NULL;
} }
return src;
} }
int int
request_requested(struct destination *dest, unsigned char seqno, source_match(struct source *src,
struct network *net) const unsigned char *p, unsigned char plen)
{ {
if(dest->requested_seqno < 0) if(src->plen != plen)
return 0; return 0;
if(src->prefix[15] != p[15])
if(seqno_compare(dest->requested_seqno, seqno) < 0)
return 0; return 0;
if(memcmp(src->prefix, p, 16) != 0)
if(dest->requested_net == NULL)
return 1;
if(net == NULL || net != dest->requested_net)
return 0; return 0;
return 1; return 1;
} }
void void
satisfy_request(struct destination *dest, unsigned char seqno, update_source(struct source *src,
struct network *net) unsigned short seqno, unsigned short metric)
{ {
if(dest->requested_seqno >= 0) { if(metric >= INFINITY)
if(net == NULL || net == dest->requested_net) { return;
if(seqno_compare(seqno, dest->requested_seqno) >= 0) {
dest->requested_seqno = -1; if(seqno_compare(src->seqno, seqno) < 0 ||
dest->requested_net = NULL; (src->seqno == seqno && src->metric > metric)) {
} src->seqno = seqno;
} src->metric = metric;
} }
src->time = now.tv_sec;
} }
...@@ -20,22 +20,22 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ...@@ -20,22 +20,22 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE. THE SOFTWARE.
*/ */
struct destination { struct source {
unsigned char address[16]; unsigned char address[16];
unsigned char seqno; unsigned char prefix[16];
unsigned char plen;
unsigned short seqno;
unsigned short metric; unsigned short metric;
int time; int time;
int requested_seqno;
struct network *requested_net;
}; };
struct destination *find_destination(const unsigned char *d, int source_match(struct source *src,
int create, unsigned char seqno); const unsigned char *p, unsigned char plen);
void update_destination(struct destination *dest, struct source *find_source(const unsigned char *a,
unsigned char seqno, unsigned short metric); const unsigned char *p,
void notice_request(struct destination *dest, unsigned char seqno, unsigned char plen,
struct network *net); int create, unsigned short seqno);
int request_requested(struct destination *dest, unsigned char seqno, struct source *find_recent_source(const unsigned char *p,
struct network *net); unsigned char plen);
void satisfy_request(struct destination *dest, unsigned char seqno, void update_source(struct source *src,
struct network *net); unsigned short seqno, unsigned short metric);
...@@ -38,7 +38,7 @@ seqno_compare(unsigned char s1, unsigned char s2) ...@@ -38,7 +38,7 @@ seqno_compare(unsigned char s1, unsigned char s2)
{ {
if(s1 == s2) if(s1 == s2)
return 0; return 0;
else if(((s2 - s1) & 0xFF) < 128) else if(((s2 - s1) & 0xFFFF) < 0x8000)
return -1; return -1;
else else
return 1; return 1;
...@@ -49,10 +49,10 @@ seqno_minus(unsigned char s1, unsigned char s2) ...@@ -49,10 +49,10 @@ seqno_minus(unsigned char s1, unsigned char s2)
{ {
if(s1 == s2) if(s1 == s2)
return 0; return 0;
else if(((s2 - s1) & 0xFF) < 128) else if(((s2 - s1) & 0xFFFF) < 0x8000)
return -(int)((s2 - s1) & 0xFF); return -(int)((s2 - s1) & 0xFFFF);
else else
return ((s1 - s2) & 0xFF); return ((s1 - s2) & 0xFFFF);
} }
void void
...@@ -75,6 +75,20 @@ timeval_minus_msec(const struct timeval *s1, const struct timeval *s2) ...@@ -75,6 +75,20 @@ timeval_minus_msec(const struct timeval *s1, const struct timeval *s2)
(s1->tv_usec - s2->tv_usec) / 1000; (s1->tv_usec - s2->tv_usec) / 1000;
} }
void
timeval_plus_msec(struct timeval *d, const struct timeval *s, int msecs)
{
int usecs;
d->tv_sec = s->tv_sec + msecs / 1000;
usecs = s->tv_usec + (msecs % 1000) * 1000;
if(usecs < 1000000) {
d->tv_usec = usecs;
} else {
d->tv_usec = usecs - 1000000;
d->tv_sec++;
}
}
int int
timeval_compare(const struct timeval *s1, const struct timeval *s2) timeval_compare(const struct timeval *s1, const struct timeval *s2)
{ {
...@@ -122,6 +136,38 @@ do_debugf(const char *format, ...) ...@@ -122,6 +136,38 @@ do_debugf(const char *format, ...)
fflush(stderr); fflush(stderr);
} }
int
in_prefix(const unsigned char *address,
const unsigned char *prefix, unsigned char plen)
{
unsigned char m;
if(plen > 128)
plen = 128;
if(memcmp(address, prefix, plen / 8) != 0)
return 0;
m = 0xFF << (8 - (plen % 8));
return ((address[plen / 8] & m) == (prefix[plen / 8] & m));
}
const unsigned char *
mask_prefix(const unsigned char *prefix, unsigned char plen)
{
static unsigned char ret[16];
if(plen > 128)
plen = 128;
memset(ret, 0, 16);
memcpy(ret, prefix, plen / 8);
if(plen % 8 != 0)
ret[plen / 8] = 0xFF << (8 - (plen % 8));
return (const unsigned char *)ret;
}
const char * const char *
format_address(const unsigned char *address) format_address(const unsigned char *address)
{ {
...@@ -131,6 +177,19 @@ format_address(const unsigned char *address) ...@@ -131,6 +177,19 @@ format_address(const unsigned char *address)
return inet_ntop(AF_INET6, address, buf[i], INET6_ADDRSTRLEN); return inet_ntop(AF_INET6, address, buf[i], INET6_ADDRSTRLEN);
} }
const char *
format_prefix(const unsigned char *prefix, unsigned char plen)
{
static char buf[4][INET6_ADDRSTRLEN + 4];
static int i = 0;
int n;
i = (i + 1) % 4;
inet_ntop(AF_INET6, prefix, buf[i], INET6_ADDRSTRLEN);
n = strlen(buf[i]);
snprintf(buf[i] + n, INET6_ADDRSTRLEN + 4 - n, "/%d", plen);
return buf[i];
}
int int
parse_address(const char *address, unsigned char *addr_r) parse_address(const char *address, unsigned char *addr_r)
{ {
...@@ -146,12 +205,12 @@ parse_address(const char *address, unsigned char *addr_r) ...@@ -146,12 +205,12 @@ parse_address(const char *address, unsigned char *addr_r)
} }
int int
parse_net(const char *net, unsigned char *prefix_r, unsigned short *plen_r) parse_net(const char *net, unsigned char *prefix_r, unsigned char *plen_r)
{ {
char buf[INET6_ADDRSTRLEN]; char buf[INET6_ADDRSTRLEN];
char *slash, *end; char *slash, *end;
unsigned char prefix[16]; unsigned char prefix[16];
unsigned short plen; long plen;
int rc; int rc;
if(strcmp(net, "default") == 0) { if(strcmp(net, "default") == 0) {
...@@ -173,11 +232,11 @@ parse_net(const char *net, unsigned char *prefix_r, unsigned short *plen_r) ...@@ -173,11 +232,11 @@ parse_net(const char *net, unsigned char *prefix_r, unsigned short *plen_r)
if(rc < 0) if(rc < 0)
return rc; return rc;
plen = strtol(slash + 1, &end, 0); plen = strtol(slash + 1, &end, 0);
if(*end != '\0') if(*end != '\0' || plen < 0 || plen > 128)
return -1; return -1;
} }
} }
memcpy(prefix_r, prefix, 16); memcpy(prefix_r, mask_prefix(prefix, plen), 16);
*plen_r = plen; *plen_r = plen;
return 0; return 0;
} }
......
...@@ -20,28 +20,36 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ...@@ -20,28 +20,36 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE. THE SOFTWARE.
*/ */
int seqno_compare(unsigned char s1, unsigned char s2) int seqno_compare(unsigned short s1, unsigned short s2)
ATTRIBUTE ((const)); ATTRIBUTE ((const));
int seqno_minus(unsigned char s1, unsigned char s2) int seqno_minus(unsigned short s1, unsigned short s2)
ATTRIBUTE ((const)); ATTRIBUTE ((const));
void timeval_minus(struct timeval *d, void timeval_minus(struct timeval *d,
const struct timeval *s1, const struct timeval *s2); const struct timeval *s1, const struct timeval *s2);
int timeval_minus_msec(const struct timeval *s1, const struct timeval *s2) int timeval_minus_msec(const struct timeval *s1, const struct timeval *s2)
ATTRIBUTE ((pure)); ATTRIBUTE ((pure));
void timeval_plus_msec(struct timeval *d,
const struct timeval *s, int msecs);
int timeval_compare(const struct timeval *s1, const struct timeval *s2) int timeval_compare(const struct timeval *s1, const struct timeval *s2)
ATTRIBUTE ((pure)); ATTRIBUTE ((pure));
void timeval_min(struct timeval *d, const struct timeval *s); void timeval_min(struct timeval *d, const struct timeval *s);
void timeval_min_sec(struct timeval *d, int secs); void timeval_min_sec(struct timeval *d, int secs);
void do_debugf(const char *format, ...) ATTRIBUTE ((format (printf, 1, 2))); void do_debugf(const char *format, ...) ATTRIBUTE ((format (printf, 1, 2)));
int in_prefix(const unsigned char *address,
const unsigned char *prefix, unsigned char plen)
ATTRIBUTE ((pure));
const unsigned char *mask_prefix(const unsigned char *prefix,
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);
int parse_address(const char *address, unsigned char *addr_r); int parse_address(const char *address, unsigned char *addr_r);
int parse_net(const char *net, unsigned char *prefix_r, unsigned short *plen_r); int parse_net(const char *net, unsigned char *prefix_r, unsigned char *plen_r);
int wait_for_fd(int direction, int fd, int msecs); int wait_for_fd(int direction, int fd, int msecs);
int martian_prefix(const unsigned char *prefix, int plen); int martian_prefix(const unsigned char *prefix, int plen);
/* If debugging is disabled, we want to avoid calling format_address /* If debugging is disabled, we want to avoid calling format_address
for every omitted debugging message. So debug is a macro. But for every omitted debugging message. So debug is a macro. But
vararg macros are not portable... */ vararg macros are not portable. */
#if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L #if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L
#define debugf(...) \ #define debugf(...) \
do { \ do { \
......
This diff is collapsed.
...@@ -20,38 +20,17 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ...@@ -20,38 +20,17 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE. THE SOFTWARE.
*/ */
struct route; int check_xroutes(void);
struct xroute { struct xroute {
unsigned char prefix[16]; unsigned char prefix[16];
unsigned short plen; unsigned char plen;
struct destination *gateway; char exported;
struct neighbour *nexthop; unsigned short metric;
int cost;
int metric;
int time;
int installed;
}; };
extern struct xroute xroutes[MAXXROUTES]; extern struct xroute xroutes[MAXXROUTES];
extern int numxroutes; extern int numxroutes;
extern struct xroute myxroutes[MAXMYXROUTES]; struct xroute *find_exported_xroute(const unsigned char *prefix,
extern int nummyxroutes; unsigned char plen);
extern int xroute_gc_delay;
extern int xroute_hold_delay;
void install_xroute(struct xroute *xroute);
void uninstall_xroute(struct xroute *xroute);
void consider_xroute(struct xroute *xroute);
void consider_all_xroutes(struct route *route);
void flush_xroute(struct xroute *xroute);
void flush_neighbour_xroutes(struct neighbour *neigh);
void retract_xroutes(struct destination *gateway, struct neighbour *nexthop,
const struct xroute *except, int numexcept);
struct xroute * update_xroute(const unsigned char *prefix, unsigned short plen,
struct destination *gateway,
struct neighbour *nexthop, int cost);
void update_xroute_metric(struct xroute *xroute, int cost);
int check_myxroutes(void);
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