Resend last ACK if it is explicitly NACKed

This commit is contained in:
Jeremy Lakeman 2013-05-15 14:27:38 +09:30
parent e5856225cf
commit e519633f7a
5 changed files with 52 additions and 7 deletions

View File

@ -33,6 +33,8 @@ struct overlay_frame {
unsigned char ttl;
unsigned char queue;
char resend;
void *send_context;
int (*send_hook)(struct overlay_frame *, int seq, void *context);
/* Mark which interfaces the frame has been sent on,
so that we can ensure that broadcast frames get sent

View File

@ -253,7 +253,7 @@ int parseEnvelopeHeader(struct decode_context *context, struct overlay_interface
sender_interface = ob_get(buffer);
if (packet_flags & PACKET_SEQ)
sender_seq = ob_get(buffer);
sender_seq = ob_get(buffer)&0xFF;
if (context->sender){
// ignore packets that have been reflected back to me

View File

@ -287,7 +287,7 @@ overlay_calc_queue_time(overlay_txqueue *queue, struct overlay_frame *frame){
// ignore payload alarm if the destination is currently unreachable
return 0;
}while(0);
time_ms_t next_allowed_packet=0;
if (frame->interface){
// don't include interfaces which are currently transmitting using a serial buffer
@ -467,12 +467,23 @@ overlay_stuff_packet(struct outgoing_packet *packet, overlay_txqueue *queue, tim
if (frame->interface!=packet->interface || memcmp(&packet->dest, &frame->recvaddr, sizeof(packet->dest))!=0){
goto skip;
}
}
}
if (frame->send_hook){
// last minute check if we really want to send this frame, or track when we sent it
if (frame->send_hook(frame, packet->seq, frame->send_context)){
// drop packet
frame = overlay_queue_remove(queue, frame);
continue;
}
}
if (overlay_frame_append_payload(&packet->context, packet->interface, frame, packet->buffer)){
// payload was not queued
goto skip;
}
if (frame->sent_seq!=-1 && config.debug.overlayframes)
DEBUGF("Retransmitted frame from seq %d in seq %d", frame->sent_seq, packet->seq);
frame->sent_seq = packet->seq;
sent:

View File

@ -87,6 +87,7 @@ struct neighbour{
// next link update
time_ms_t next_neighbour_update;
time_ms_t last_update;
int last_update_seq;
time_ms_t rtt;
int ack_counter;
@ -157,6 +158,7 @@ static struct neighbour *get_neighbour(struct subscriber *subscriber, char creat
n = emalloc_zero(sizeof(struct neighbour));
n->subscriber = subscriber;
n->_next = neighbours;
n->last_update_seq = -1;
// TODO measure min/max rtt
n->rtt = 120;
neighbours = n;
@ -565,7 +567,18 @@ static int neighbour_find_best_link(struct neighbour *n)
return 0;
}
static int send_neighbour_link(struct neighbour *n){
static int neighbour_link_sent(struct overlay_frame *frame, int sequence, void *context)
{
struct subscriber *subscriber = context;
struct neighbour *neighbour = get_neighbour(subscriber, 1);
neighbour->last_update_seq = sequence;
if (config.debug.linkstate && config.debug.verbose)
DEBUGF("LINK STATE; ack sent to neighbour %s in seq %d", alloca_tohex_sid(subscriber->sid), sequence);
return 0;
}
static int send_neighbour_link(struct neighbour *n)
{
IN();
if (!n->best_link)
RETURN(-1);
@ -582,6 +595,9 @@ static int send_neighbour_link(struct neighbour *n){
frame->ttl=1;
frame->queue=OQ_MESH_MANAGEMENT;
frame->payload = ob_new();
frame->send_hook = neighbour_link_sent;
frame->send_context = n->subscriber;
if (n->subscriber->reachable & REACHABLE_DIRECT && (!(n->subscriber->reachable&REACHABLE_ASSUMED))){
frame->destination_resolved = 1;
frame->interface = n->subscriber->interface;
@ -907,7 +923,23 @@ int link_receive(overlay_mdp_frame *mdp)
version++;
// process acks / nacks
overlay_queue_ack(sender, interface, ack_mask, ack_seq);
if (ack_seq!=-1){
overlay_queue_ack(sender, interface, ack_mask, ack_seq);
// did they miss our last ack?
if (neighbour->last_update_seq!=-1){
int seq_delta = (ack_seq - neighbour->last_update_seq)&0xFF;
if (seq_delta <= 32 && (seq_delta==0 || ack_mask&(1<<(seq_delta-1)))){
neighbour->last_update_seq = -1;
}else if(seq_delta < 128){
// send another ack asap
if (config.debug.linkstate && config.debug.verbose)
DEBUGF("LINK STATE; neighbour %s missed ack %d, queue another", alloca_tohex_sid(sender->sid), neighbour->last_update_seq);
neighbour->next_neighbour_update=now;
update_alarm(neighbour->next_neighbour_update);
}
}
}
link->last_ack_seq = ack_seq;
}

View File

@ -363,7 +363,7 @@ test_multi_interface() {
wait_until multi_has_link $SIDA
}
doc_ping_unreliable="Ping over an unreliable link"
doc_ping_unreliable="Ping over a 1-hop unreliable link"
setup_ping_unreliable() {
setup_servald
assert_no_servald_processes
@ -380,7 +380,7 @@ test_ping_unreliable() {
wait_until path_exists +A +B
wait_until path_exists +B +A
set_instance +A
executeOk_servald mdp ping $SIDB 40
executeOk_servald mdp ping --interval=0.020 --timeout=1 $SIDB 500
tfw_cat --stdout --stderr
}