From 5dd6f9ce06412e2cab9aa36b787804f2e48464b9 Mon Sep 17 00:00:00 2001 From: gardners Date: Thu, 18 Aug 2011 02:15:13 +0930 Subject: [PATCH] Progress towards core overlay mesh routing data structures. --- overlay.c | 34 +++++++------ overlay_route.c | 124 +++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 143 insertions(+), 15 deletions(-) diff --git a/overlay.c b/overlay.c index e57f8167..c0db696f 100644 --- a/overlay.c +++ b/overlay.c @@ -196,21 +196,27 @@ int overlay_frame_process(int interface,overlay_frame *f) { /* Yes, it is. */ int len=0; - if (overlay_get_nexthop(f->destination,f->nexthop,&len)) - return WHY("Could not find next hop for host - dropping frame"); - f->ttl--; - /* Queue frame for dispatch */ - /* XXX We currently have separate overlay_payload structures for sending and - overlay_frame for receiving. Need to harmonise this. Multiple conversions - are wasteful. We really should be able to cope with a single structure. */ - - WHY("forwarding of frame not implemented"); - - /* If the frame was a broadcast frame, then we need to hang around - so that we can process it, since we are one of the recipients. - Otherwise, return triumphant. */ - if (!broadcast) return 0; + if (broadcast&&(f->type==OF_TYPE_SELFANNOUNCE)) { + // Don't forward broadcast self-announcement packets as that is O(n^2) with + // traffic. We have other means to propagating the mesh topology information. + } else { + if (overlay_get_nexthop(f->destination,f->nexthop,&len)) + return WHY("Could not find next hop for host - dropping frame"); + f->ttl--; + /* Queue frame for dispatch */ + /* XXX We currently have separate overlay_payload structures for sending and + overlay_frame for receiving. Need to harmonise this. Multiple conversions + are wasteful. We really should be able to cope with a single structure. */ + + + WHY("forwarding of frame not implemented"); + + /* If the frame was a broadcast frame, then we need to hang around + so that we can process it, since we are one of the recipients. + Otherwise, return triumphant. */ + if (!broadcast) return 0; + } } switch(f->type) diff --git a/overlay_route.c b/overlay_route.c index 7ef91e01..1d684f3e 100644 --- a/overlay_route.c +++ b/overlay_route.c @@ -1,5 +1,126 @@ #include "mphlr.h" +/* + Here we implement the actual routing algorithm which is heavily based on BATMAN. + + The fundamental difference is that we want to allow the mesh to grow beyond the + size that could ordinarily be accomodated by the available bandwidth. Some + explanation follows. + + BATMAN operates by having nodes periodically send "hello" or originator messages, + either with a limited distribution or with a sufficiently high TTL to spread + over the whole network. + + The latter results in a super-linear bandwidth requirement as the network grows + in size. + + What we wish to do is to implement the BATMAN concept, but using link-local traffic + only. To do this we need to change the high-TTL originator frames into something + equivalent, but that does not get automatic network-wide distribution. + + What seems possible is to implement the BATMAN approach for link-local neighbours, + and then have each node periodically announce the link-score to the peers that + they know about, whether link-local or more distant. If the number of reported + peers is left unconstrained, super-linear bandwidth consumption will still occur. + + However, if the number of peers that each node announces is limited, then bandwidth + will be capped at a constant factor (which can be chosen based on the bandwidth + available). The trade-off being that each node will only be able to see some number + of "nearest" peers based on the available bandwidth. + + This seems an entirely reasonable outcome, and at least on the surface would appear + to solve our problem of wanting to allow a global-scale mesh, even if only local + connectivity is possible, in contrast to existing mesh protocols that will not allow + any connectivity once the number of nodes grows beyond a certain point. + + Remaining challenges that we have to think through are how to add a hierarchical + element to the mesh that might allow us to route traffic beyond a nodes' + neighbourhood of peers. + + There is some hope to extend the effective range beyond the immediate neighbourhood + to some degree by rotating the peers that a node reports on, so that a larger total + set of nodes becomes known to the mesh, in return for less frequent updates on their + link scores and optimal routes. + + This actually makes some logical sense, as the general direction in which to route + a frame to a distant node is less likely to change more slowly than for nearer nodes. + So we will attempt this. + + With some careful thought, this statistical announcement of peers also serves to allow + long-range but very low bandwidth links, e.g., satellite or dial-up, as well as long-shot + WiFi where bandwidth is less constrained. + + Questions arise as to the possibility of introducing routing loops through the use of + stale information. So we will certainly need to have some idea of the freshness of + routing data. + + Finally, all this works only for bidirectional links. We will need to think about how + to handle mono-directional links. BATMAN does this well, but I don't have the documentation + here at 36,000 feet to digest it and think about how to incorporate it. + + Related to this we need to continue thinking about how to handle intermittant links in a more + formal sense, including getting an idea of when nodes might reappear. + + Turning to the practical side of things, we need to keep track of reachability scores for + nodes via each of our immediate neighbours. Recognising the statistical nature of + the announcments, we probably want to keep track of some that have ceased to be neighbours + in case they become neighbours again. + + Probably it makes more sense to have a list of known nodes and the most recent and + highest scoring nodes by which we may reach them, complete with the sequence numbers of last + observation that they are based upon, and possibly more information down the track to + support intermittant links. + +*/ + +typedef struct overlay_node_observation { + int valid; + + /* Sequence numbers are handled as ranges because the tick + rate can vary between interfaces, and we want to be able to + estimate the reliability of links to nodes that may have + several available interfaces. + We don't want sequence numbers to wrap too often, but we + would also like to support fairly fast ticking interfaces, + e.g., for gigabit type links. So lets go with 1ms granularity. */ + int sequence_range_low; + int sequence_range_high; + long long rx_time; + unsigned char sender[SID_SIZE]; +} overlay_node_observation; + +/* Keep track of last 32 observations of a node. + Hopefully this is enough, if not, we will increase */ +#define OVERLAY_MAX_OBSERVATIONS 32 + +typedef struct overlay_node { + unsigned char sid[SID_SIZE]; + int neighbour_id; /* 0=not a neighbour */ + int most_recent_observation_id; + overlay_node_observation observations[OVERLAY_MAX_OBSERVATIONS]; +} overlay_node; + +/* For fast handling we will have a number of bins that will be indexed by the + first few bits of the peer's SIDs, and a number of entries in each bin to + handle hash collissions while still allowing us to have static memory usage. */ +int overlay_bin_count=0; +int overlay_bin_size=0; +overlay_node *overlay_nodes[]=NULL; + +/* We also need to keep track of which nodes are our direct neighbours. + This means we need to keep an eye on how recently we received DIRECT announcements + from nodes, and keep a list of the most recent ones. The challenge is to keep the + list ordered without having to do copies or have nasty linked-list structures that + require lots of random memory reads to resolve. + + The simplest approach is to maintain a large cache of neighbours and practise random + replacement. If is however succecptible to cache flushing attacks by adversaries, so + we will need something smarter in the long term. +*/ +int overlay_max_neighbours=0; +int overlay_neighbour_count=0; +overlay_node *overlay_neighbours[]=NULL; + int overlay_get_nexthop(unsigned char *d,unsigned char *nexthop,int *nexthoplen) { return WHY("Not implemented"); @@ -7,7 +128,8 @@ int overlay_get_nexthop(unsigned char *d,unsigned char *nexthop,int *nexthoplen) int overlay_route_saw_selfannounce(overlay_frame *f) { - return WHY("Not implemented"); + + return WHY("Not implemented"); } int overlay_route_saw_selfannounce_ack(overlay_frame *f)