Rework broadcast address handling, working towards a unified address struct

This commit is contained in:
Jeremy Lakeman 2012-08-15 15:56:58 +09:30
parent aa5706f9d7
commit 22c6b530ed
8 changed files with 36 additions and 77 deletions

View File

@ -43,6 +43,7 @@ SERVALD_SRC_FILES = \
serval-dna/simulate.c \
serval-dna/srandomdev.c \
serval-dna/str.c \
serval-dna/subscribers.c \
serval-dna/keyring.c \
serval-dna/vomp.c \
serval-dna/lsif.c \

View File

@ -218,8 +218,9 @@ int overlay_frame_process(struct overlay_interface *interface,overlay_frame *f)
// only examine payloads that are broadcasts, or where I'm the next hop
if (overlay_address_is_broadcast(f->nexthop)) {
// Note we can only check for dropping once per payload, as a second test would return true.
if (overlay_broadcast_drop_check(f->nexthop)){
if (debug&DEBUG_OVERLAYFRAMES)
if (debug&(DEBUG_OVERLAYFRAMES|DEBUG_BROADCASTS))
DEBUGF("Dropping frame, duplicate broadcast %s", alloca_tohex_sid(f->nexthop));
RETURN(0);
}

View File

@ -27,11 +27,21 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "serval.h"
#define BROADCAST_LEN 8
struct broadcast{
unsigned char id[BROADCAST_LEN];
};
#define MAX_BPIS 1024
#define BPI_MASK 0x3ff
struct broadcast bpilist[MAX_BPIS];
/* Determine if an address is broadcast */
int overlay_address_is_broadcast(unsigned char *a)
{
int i;
for(i=0;i<(SID_SIZE-8);i++)
for(i=0;i<(SID_SIZE - BROADCAST_LEN);i++)
if (a[i]!=0xff) return 0;
return 1;
}
@ -39,15 +49,11 @@ int overlay_address_is_broadcast(unsigned char *a)
int overlay_broadcast_generate_address(unsigned char *a)
{
int i;
for(i=0;i<(SID_SIZE-8);i++) a[i]=0xff;
for(i=0;i<(SID_SIZE - BROADCAST_LEN);i++) a[i]=0xff;
for(;i<SID_SIZE;i++) a[i]=random()&0xff;
return 0;
}
#define MAX_BPIS 1024
#define BPI_MASK 0x3ff
unsigned char bpilist[MAX_BPIS][8];
int overlay_broadcast_drop_check(unsigned char *a)
{
/* Don't drop frames to non-broadcast addresses */
@ -60,31 +66,21 @@ int overlay_broadcast_drop_check(unsigned char *a)
robustness it is however required. */
int bpi_index=0;
int i;
for(i=0;i<8;i++)
for(i=0;i<BROADCAST_LEN;i++)
{
bpi_index=((bpi_index<<3)&0xfff8)+((bpi_index>>13)&0x7);
bpi_index^=a[24+i];
bpi_index^=a[SID_SIZE - BROADCAST_LEN + i];
}
bpi_index&=BPI_MASK;
if (debug&DEBUG_BROADCASTS)
DEBUGF("BPI %02X%02X%02X%02X%02X%02X%02X%02X resolves to hash bin %d",
a[24],a[25],a[26],a[27],a[28],a[29],a[30],a[31],bpi_index);
int bpiNew=0;
for(i=0;i<8;i++)
{
if (a[24+i]!=bpilist[bpi_index][i]) bpiNew=1;
bpilist[bpi_index][i]=a[24+i];
}
if (bpiNew)
{
if (debug&DEBUG_BROADCASTS) DEBUGF(" BPI is new, so don't drop frame");
return 0; /* don't drop */
}
else
{
if (debug&DEBUG_BROADCASTS) DEBUGF(" BPI is already in our list, so drop the frame to prevent broadcast storms");
return 1; /* drop frame because we have seen this BPI recently */
}
if (memcmp(bpilist[bpi_index].id, a + SID_SIZE - BROADCAST_LEN, BROADCAST_LEN)){
if (debug&DEBUG_BROADCASTS)
DEBUGF("BPI %s is new", alloca_tohex(a + SID_SIZE - BROADCAST_LEN, BROADCAST_LEN));
bcopy(a + SID_SIZE - BROADCAST_LEN, bpilist[bpi_index].id, BROADCAST_LEN);
return 0; /* don't drop */
}else{
if (debug&DEBUG_BROADCASTS)
DEBUGF("BPI %s is a duplicate", alloca_tohex(a + SID_SIZE - BROADCAST_LEN, BROADCAST_LEN));
return 1; /* drop frame because we have seen this BPI recently */
}
}

View File

@ -972,19 +972,16 @@ overlay_stuff_packet(struct outgoing_packet *packet, overlay_txqueue *queue, tim
// TODO stop when the packet is nearly full?
while(frame){
int drop =0;
frame->isBroadcast = overlay_address_is_broadcast(frame->destination);
if (frame->enqueued_at + queue->latencyTarget < now)
drop=1;
else if(frame->isBroadcast)
drop=overlay_broadcast_drop_check(frame->destination);
if (drop){
if (frame->enqueued_at + queue->latencyTarget < now){
DEBUG("Dropping frame due to expiry timeout");
frame = overlay_queue_remove(queue, frame);
continue;
}
/* Note, once we queue a broadcast packet we are committed to sending it out every interface,
even if we hear it from somewhere else in the mean time
*/
if (overlay_resolve_next_hop(frame))
goto skip;

View File

@ -147,7 +147,6 @@ int packetOkOverlay(struct overlay_interface *interface,unsigned char *packet, s
break;
}
int payloadStart = ofs;
int nextPayload = ofs+f.rfs;
if (nextPayload > len){

View File

@ -66,7 +66,6 @@ int overlay_frame_package_fmt1(overlay_frame *p,overlay_buffer *b)
Will pick a next hop if one has not been chosen.
*/
int i;
overlay_buffer *headers;
headers=ob_new(256);
@ -80,33 +79,6 @@ int overlay_frame_package_fmt1(overlay_frame *p,overlay_buffer *b)
/* Build header */
if (p->nexthop_address_status!=OA_RESOLVED) {
if (0) WHYF("next hop is NOT resolved for packet to %s",
alloca_tohex_sid(p->destination));
if (overlay_address_is_broadcast(p->destination)) {
/* Broadcast frames are broadcast rather than unicast to next hop.
Just check if the broadcast frame should be dropped first. */
if (overlay_broadcast_drop_check(p->destination)){
WHY("This broadcast packet ID has been seen recently");
goto cleanup;
}
/* Copy the broadcast address exactly so that we preserve the BPI */
for(i=0;i<SID_SIZE;i++) p->nexthop[i]=p->destination[i];
p->nexthop_address_status=OA_RESOLVED;
} else {
if (overlay_get_nexthop((unsigned char *)p->destination,p->nexthop,&p->nexthop_interface)) {
WHY("could not determine next hop address for payload");
goto cleanup;
}
else p->nexthop_address_status=OA_RESOLVED;
}
} else {
if (0) WHYF("next hop IS resolved for packet to %s",
alloca_tohex_sid(p->destination));
}
if (p->source[0]<0x10) {
// Make sure that addresses do not overload the special address spaces of 0x00*-0x0f*
WHY("packet source address begins with reserved value 0x00-0x0f");
@ -318,6 +290,9 @@ overlay_frame *op_dup(overlay_frame *in)
int overlay_frame_set_broadcast_as_destination(overlay_frame *f)
{
overlay_broadcast_generate_address(f->destination);
// remember the broadcast address we are about to send so we don't sent the packet twice
overlay_broadcast_drop_check(f->destination);
f->isBroadcast=1;
return 0;
}

View File

@ -203,13 +203,8 @@ int overlay_get_nexthop(unsigned char *d,unsigned char *nexthop,int *interface)
DEBUGF("No open path to %s, invalid sid",alloca_tohex_sid(d));
return -1;
}
// Note, broadcast address handling is already done by this point
if (overlay_broadcast_drop_check(d)) return WHY("I have sent that broadcast frame before");
if (overlay_address_is_broadcast(d)) {
bcopy(&d[0],&nexthop[0],SID_SIZE);
return 0;
}
overlay_node *n=overlay_route_find_node(d,SID_SIZE,0 /* don't create if missing */ );
if (!n){
if (debug&DEBUG_OVERLAYROUTING)
@ -353,12 +348,8 @@ int overlay_route_ack_selfannounce(overlay_frame *f,
out->nexthop_address_status=OA_UNINITIALISED;
if (overlay_resolve_next_hop(out)) {
/* no open path, so convert to broadcast */
int i;
for(i=0;i<(SID_SIZE-8);i++) out->nexthop[i]=0xff;
for(i=(SID_SIZE-8);i<SID_SIZE;i++) out->nexthop[i]=random()&0xff;
out->nexthop_address_status=OA_RESOLVED;
overlay_frame_set_broadcast_as_destination(out);
out->ttl=2;
out->isBroadcast=1;
if (debug&DEBUG_OVERLAYROUTING)
DEBUG("Broadcasting ack to selfannounce for hithero unroutable node");
} else

View File

@ -723,7 +723,6 @@ unsigned int overlay_route_hash_sid(const unsigned char *sid);
unsigned char *overlay_get_my_sid();
int overlay_frame_set_me_as_source(overlay_frame *f);
int overlay_frame_set_broadcast_as_destination(overlay_frame *f);
int overlay_broadcast_generate_address(unsigned char *a);
int packetEncipher(unsigned char *packet,int maxlen,int *len,int cryptoflags);
int overlayServerMode();
int overlay_payload_enqueue(int q,overlay_frame *p,int forceBroadcastP);