Re-route packets on retransmision if the route has changed

This commit is contained in:
Jeremy Lakeman 2015-03-30 11:27:37 +10:30
parent b048e8874f
commit 13bb8a558d
5 changed files with 51 additions and 39 deletions

View File

@ -476,11 +476,11 @@ int send_please_explain(struct decode_context *context, struct subscriber *sourc
frame->ttl=1;// how will this work with olsr??
if (context->interface){
frame->destination = destination;
frame->destinations[frame->destination_count++].destination=add_destination_ref(context->interface->destination);
frame_add_destination(frame, NULL, context->interface->destination);
struct network_destination *dest = create_unicast_destination(&context->addr, context->interface);
if (dest)
frame->destinations[frame->destination_count++].destination=dest;
frame_add_destination(frame, NULL, dest);
}else{
FATAL("This context doesn't have an interface?");

View File

@ -189,9 +189,8 @@ int overlay_send_probe(struct subscriber *peer, struct network_destination *dest
frame->destination = peer;
frame->ttl=1;
frame->queue=queue;
unsigned dest = frame->destination_count++;
frame->destinations[dest].destination=add_destination_ref(destination);
frame->destinations[dest].next_hop = peer;
frame_add_destination(frame, peer, destination);
if ((frame->payload = ob_new()) == NULL) {
op_free(frame);
return -1;

View File

@ -119,5 +119,7 @@ int op_free(struct overlay_frame *p);
struct overlay_frame *op_dup(struct overlay_frame *f);
int reload_mdp_packet_rules(void);
void frame_remove_destination(struct overlay_frame *frame, int i);
void frame_add_destination(struct overlay_frame *frame, struct subscriber *next_hop, struct network_destination *dest);
#endif //__SERVAL_DNA__OVERLAY_PACKET_H

View File

@ -178,7 +178,8 @@ int _overlay_payload_enqueue(struct __sourceloc __whence, struct overlay_frame *
p->packet_version=1;
if (config.debug.verbose && config.debug.overlayframes)
DEBUGF("Enqueue packet %p", p);
DEBUGF("Enqueue packet to %s",
p->destination?alloca_tohex_sid_t_trunc(p->destination->sid, 14): "broadcast");
if (p->destination_count==0){
if (!p->destination){
@ -278,13 +279,26 @@ int overlay_queue_schedule_next(time_ms_t next_allowed_packet){
return 0;
}
static void remove_destination(struct overlay_frame *frame, int i){
void frame_remove_destination(struct overlay_frame *frame, int i){
release_destination_ref(frame->destinations[i].destination);
frame->destination_count --;
if (i<frame->destination_count)
frame->destinations[i]=frame->destinations[frame->destination_count];
}
void frame_add_destination(struct overlay_frame *frame, struct subscriber *next_hop, struct network_destination *dest){
if (frame->destination_count >= MAX_PACKET_DESTINATIONS)
return;
unsigned i = frame->destination_count++;
frame->destinations[i].destination=add_destination_ref(dest);
frame->destinations[i].next_hop = next_hop;
frame->destinations[i].sent_sequence=-1;
if (config.debug.verbose && config.debug.overlayframes)
DEBUGF("Sending %s on interface %s",
frame->destinations[i].destination->unicast?"unicast":"broadcast",
frame->destinations[i].destination->interface->name);
}
// update the alarm time and return 1 if changed
static int
overlay_calc_queue_time(struct overlay_frame *frame)
@ -359,21 +373,10 @@ overlay_stuff_packet(struct outgoing_packet *packet, overlay_txqueue *queue, tim
goto skip;
// quickly skip payloads that have no chance of fitting
if (packet->buffer && ob_limit(frame->payload) > ob_remaining(packet->buffer))
if (packet->buffer && ob_position(frame->payload) > ob_remaining(packet->buffer))
goto skip;
if (frame->destination_count==0 && frame->destination){
link_add_destinations(frame);
int i=0;
for (i=0;i<frame->destination_count;i++){
frame->destinations[i].sent_sequence=-1;
if (config.debug.verbose && config.debug.overlayframes)
DEBUGF("Sending %s on interface %s",
frame->destinations[i].destination->unicast?"unicast":"broadcast",
frame->destinations[i].destination->interface->name);
}
}
link_add_destinations(frame);
if (frame->mdp_sequence == -1){
frame->mdp_sequence = mdp_sequence = (mdp_sequence+1)&0xFFFF;
@ -397,7 +400,13 @@ overlay_stuff_packet(struct outgoing_packet *packet, overlay_txqueue *queue, tim
FATALF("Destination interface %d is NULL", i);
if (dest->interface->state!=INTERFACE_STATE_UP){
// remove this destination
remove_destination(frame, i);
frame_remove_destination(frame, i);
continue;
}
if (ob_position(frame->payload) > (unsigned)dest->ifconfig.mtu){
WARNF("Skipping packet destination as size %zu > destination mtu %zd",
ob_position(frame->payload), dest->ifconfig.mtu);
frame_remove_destination(frame, i);
continue;
}
// degrade packet version if required to reach the destination
@ -494,15 +503,13 @@ overlay_stuff_packet(struct outgoing_packet *packet, overlay_txqueue *queue, tim
if (!will_retransmit){
if (config.debug.overlayframes)
DEBUGF("Not waiting for retransmission (%d, %d, %d)", frame->packet_version, frame->resend, packet->seq);
remove_destination(frame, destination_index);
frame_remove_destination(frame, destination_index);
if (frame->destination_count==0){
frame = overlay_queue_remove(queue, frame);
continue;
}
}
// TODO recalc route on retransmittion??
skip:
// if we can't send the payload now, check when we should try next
overlay_calc_queue_time(frame);
@ -610,7 +617,7 @@ int overlay_queue_ack(struct subscriber *neighbour, struct network_destination *
frame = overlay_queue_remove(&overlay_tx[i], frame);
continue;
}
remove_destination(frame, j);
frame_remove_destination(frame, j);
}else if (seq_delta < 128 && frame->destination && frame->delay_until>now){
// retransmit asap

View File

@ -912,8 +912,11 @@ static int link_send_neighbours()
if (out->destination->ifconfig.tick_ms>0 && out->destination->unicast){
if (out->destination->last_tx + out->destination->ifconfig.tick_ms < now)
overlay_send_tick_packet(out->destination);
if (out->destination->last_tx + out->destination->ifconfig.tick_ms < ALARM_STRUCT(link_send).alarm)
ALARM_STRUCT(link_send).alarm = out->destination->last_tx + out->destination->ifconfig.tick_ms;
if (out->destination->last_tx + out->destination->ifconfig.tick_ms < ALARM_STRUCT(link_send).alarm){
time_ms_t next_tick = out->destination->last_tx + out->destination->ifconfig.tick_ms;
time_ms_t next_allowed = limit_next_allowed(&out->destination->transfer_limit);
ALARM_STRUCT(link_send).alarm = next_tick < next_allowed ? next_tick : next_allowed;
}
}
out=out->_next;
}
@ -1038,7 +1041,7 @@ int link_add_destinations(struct overlay_frame *frame)
&& directory_service->reachable&REACHABLE)
next_hop = directory_service;
if (next_hop->reachable==REACHABLE_NONE){
if (next_hop->reachable==REACHABLE_NONE && frame->destination_count==0){
// if the destination is a network neighbour, but we haven't established any viable route yet
// we need to add all likely links so that we can send ack's and bootstrap the routing table
struct neighbour *n = get_neighbour(frame->destination, 0);
@ -1046,11 +1049,8 @@ int link_add_destinations(struct overlay_frame *frame)
struct link_out *out = n->out_links;
time_ms_t now = gettime_ms();
while(out){
if (out->timeout>=now && frame->destination_count < MAX_PACKET_DESTINATIONS){
unsigned dest = frame->destination_count++;
frame->destinations[dest].destination = add_destination_ref(out->destination);
frame->destinations[dest].next_hop = next_hop;
}
if (out->timeout>=now && frame->destination_count < MAX_PACKET_DESTINATIONS)
frame_add_destination(frame, next_hop, out->destination);
out = out->_next;
}
}
@ -1060,13 +1060,17 @@ int link_add_destinations(struct overlay_frame *frame)
next_hop = next_hop->next_hop;
if (next_hop->reachable&REACHABLE_DIRECT){
if (frame->destination_count < MAX_PACKET_DESTINATIONS){
unsigned dest = frame->destination_count++;
frame->destinations[dest].destination=add_destination_ref(next_hop->destination);
frame->destinations[dest].next_hop = next_hop;
unsigned i;
// do nothing if this packet is already going the right way
// or remove any stale destinations
for (i=frame->destination_count;i>0;i--){
if (frame->destinations[i-1].destination == next_hop->destination)
return 0;
frame_remove_destination(frame, i-1);
}
}
}else{
frame_add_destination(frame, next_hop, next_hop->destination);
}
}else if (frame->destination_count==0){
char added_interface[OVERLAY_MAX_INTERFACES];
bzero(added_interface, sizeof(added_interface));