Route mulit-hop via unicast links

This commit is contained in:
Jeremy Lakeman 2013-08-09 16:19:45 +09:30
parent 55657623aa
commit 9a50d8a9ef
8 changed files with 118 additions and 102 deletions

View File

@ -262,11 +262,11 @@ static int add_explain_response(struct subscriber *subscriber, void *context){
// if one of our identities is unknown, // if one of our identities is unknown,
// the header of this packet must include our full sid. // the header of this packet must include our full sid.
if (subscriber->reachable==REACHABLE_SELF){ if (subscriber->reachable==REACHABLE_SELF){
subscriber->send_full=1;
if (subscriber==my_subscriber){ if (subscriber==my_subscriber){
response->please_explain->source_full=1; response->please_explain->source_full=1;
return 0; return 0;
} }
subscriber->send_full=1;
} }
// add the whole subscriber id to the payload, stop if we run out of space // add the whole subscriber id to the payload, stop if we run out of space
@ -399,11 +399,11 @@ int send_please_explain(struct decode_context *context, struct subscriber *sourc
if (!context->sender) if (!context->sender)
frame->source_full=1; frame->source_full=1;
if (destination && (destination->reachable & REACHABLE)){ if (destination){
frame->ttl = PAYLOAD_TTL_DEFAULT; // MAX? frame->ttl = PAYLOAD_TTL_DEFAULT; // MAX?
frame->destination = destination; frame->destination = destination;
frame->source_full=1;
}else{ }else{
DEBUGF("Need to send explanation to destination that isn't routable");
// send both a broadcast & unicast response out the same interface this packet arrived on. // send both a broadcast & unicast response out the same interface this packet arrived on.
frame->ttl=1;// how will this work with olsr?? frame->ttl=1;// how will this work with olsr??
if (context->interface){ if (context->interface){

View File

@ -51,6 +51,8 @@ struct overlay_frame {
time_ms_t delay_until; time_ms_t delay_until;
struct packet_destination destinations[MAX_PACKET_DESTINATIONS]; struct packet_destination destinations[MAX_PACKET_DESTINATIONS];
int destination_count; int destination_count;
int transmit_count;
// each payload gets a sequence number that is reused on retransmission // each payload gets a sequence number that is reused on retransmission
int32_t mdp_sequence; int32_t mdp_sequence;

View File

@ -303,6 +303,9 @@ int parseEnvelopeHeader(struct decode_context *context, struct overlay_interface
RETURN(1); RETURN(1);
} }
if (context->packet_version > context->sender->max_packet_version)
context->sender->max_packet_version=context->packet_version;
if (interface->point_to_point && interface->other_device!=context->sender){ if (interface->point_to_point && interface->other_device!=context->sender){
INFOF("Established point to point link with %s on %s", alloca_tohex_sid(context->sender->sid), interface->name); INFOF("Established point to point link with %s on %s", alloca_tohex_sid(context->sender->sid), interface->name);
context->point_to_point_device = context->interface->other_device = context->sender; context->point_to_point_device = context->interface->other_device = context->sender;

View File

@ -152,19 +152,6 @@ int overlay_payload_enqueue(struct overlay_frame *p)
if (!p) return WHY("Cannot queue NULL"); if (!p) return WHY("Cannot queue NULL");
do{
if (p->destination_count>0)
break;
if (!p->destination)
break;
if (p->destination->reachable&REACHABLE)
break;
if (directory_service&&directory_service->reachable&REACHABLE)
break;
return WHYF("Cannot send %x packet, destination %s is unreachable", p->type,
alloca_tohex_sid(p->destination->sid));
} while(0);
if (p->queue>=OQ_MAX) if (p->queue>=OQ_MAX)
return WHY("Invalid queue specified"); return WHY("Invalid queue specified");
@ -199,7 +186,7 @@ int overlay_payload_enqueue(struct overlay_frame *p)
// hook to allow for flooding via olsr // hook to allow for flooding via olsr
olsr_send(p); olsr_send(p);
link_add_broadcast_destinations(p); link_add_destinations(p);
// just drop it now // just drop it now
if (p->destination_count == 0){ if (p->destination_count == 0){
@ -311,15 +298,9 @@ overlay_calc_queue_time(overlay_txqueue *queue, struct overlay_frame *frame){
return 0; return 0;
} }
}else{ }else{
// ignore payload alarm if the destination is currently unreachable
if (!frame->destination){ if (!frame->destination){
return 0; return 0;
} }
if (!(frame->destination->reachable&REACHABLE)){
if (!directory_service || !(directory_service->reachable&REACHABLE)){
return 0;
}
}
} }
if (next_allowed_packet < frame->delay_until) if (next_allowed_packet < frame->delay_until)
@ -366,38 +347,12 @@ overlay_stuff_packet(struct outgoing_packet *packet, overlay_txqueue *queue, tim
if (packet->buffer && ob_limit(frame->payload) > ob_remaining(packet->buffer)) if (packet->buffer && ob_limit(frame->payload) > ob_remaining(packet->buffer))
goto skip; goto skip;
if (frame->destination_count==0){ if (frame->destination_count==0 && frame->destination){
frame->next_hop = frame->destination; link_add_destinations(frame);
if (frame->next_hop){
// Where do we need to route this payload next?
int r = frame->next_hop->reachable;
// first, should we try to bounce this payload off the directory service?
if (r==REACHABLE_NONE &&
directory_service &&
frame->next_hop!=directory_service){
frame->next_hop=directory_service;
r=directory_service->reachable;
}
// do we need to route via a neighbour?
if (r&REACHABLE_INDIRECT){
frame->next_hop = frame->next_hop->next_hop;
r = frame->next_hop->reachable;
}
if (!(r&REACHABLE_DIRECT)){
goto skip;
}
frame->destinations[frame->destination_count++].destination=add_destination_ref(frame->next_hop->destination);
// degrade packet version if required to reach the destination // degrade packet version if required to reach the destination
if (frame->packet_version > frame->next_hop->max_packet_version) if (frame->packet_version > frame->next_hop->max_packet_version)
frame->packet_version = frame->next_hop->max_packet_version; frame->packet_version = frame->next_hop->max_packet_version;
}
} }
int destination_index=-1; int destination_index=-1;
@ -485,6 +440,7 @@ overlay_stuff_packet(struct outgoing_packet *packet, overlay_txqueue *queue, tim
} }
frame->destinations[destination_index].delay_until = now+200; frame->destinations[destination_index].delay_until = now+200;
frame->transmit_count++;
if (config.debug.overlayframes){ if (config.debug.overlayframes){
DEBUGF("Appended payload %p, %d type %x len %d for %s via %s", DEBUGF("Appended payload %p, %d type %x len %d for %s via %s",
@ -495,8 +451,9 @@ overlay_stuff_packet(struct outgoing_packet *packet, overlay_txqueue *queue, tim
} }
// dont retransmit if we aren't sending sequence numbers, or we've been asked not to // dont retransmit if we aren't sending sequence numbers, or we've been asked not to
if (frame->packet_version<1 || frame->resend<=0 || if (frame->packet_version<1 || frame->resend<=0 || packet->seq==-1){
frame->enqueued_at + queue->latencyTarget < frame->destinations[destination_index].delay_until){ if (config.debug.overlayframes)
DEBUGF("Not waiting for retransmission (%d, %d, %d)", frame->packet_version, frame->resend, packet->seq);
remove_destination(frame, destination_index); remove_destination(frame, destination_index);
if (frame->destination_count==0){ if (frame->destination_count==0){
frame = overlay_queue_remove(queue, frame); frame = overlay_queue_remove(queue, frame);

View File

@ -777,7 +777,7 @@ static int link_send_neighbours()
struct link_out *out = n->out_links; struct link_out *out = n->out_links;
while(out){ while(out){
if (out->destination->unicast){ if (out->destination->tick_ms>0 && out->destination->unicast){
if (out->destination->last_tx + out->destination->tick_ms < now) if (out->destination->last_tx + out->destination->tick_ms < now)
overlay_send_tick_packet(out->destination); overlay_send_tick_packet(out->destination);
if (out->destination->last_tx + out->destination->tick_ms < link_send_alarm.alarm) if (out->destination->last_tx + out->destination->tick_ms < link_send_alarm.alarm)
@ -871,8 +871,39 @@ struct link_in * get_neighbour_link(struct neighbour *neighbour, struct overlay_
return link; return link;
} }
int link_add_broadcast_destinations(struct overlay_frame *frame) int link_add_destinations(struct overlay_frame *frame)
{ {
if (frame->destination){
frame->next_hop = frame->destination;
// if the destination is unreachable, but we have a reachable directory service
// forward it through the directory service
if (frame->next_hop->reachable==REACHABLE_NONE
&& directory_service
&& frame->next_hop!=directory_service
&& directory_service->reachable&REACHABLE)
frame->next_hop = directory_service;
if (frame->next_hop->reachable==REACHABLE_NONE){
// if the destination is a neighbour, add all probable destinations
struct neighbour *n = get_neighbour(frame->destination, 0);
if (n){
struct link_out *out = n->out_links;
while(out){
frame->destinations[frame->destination_count++].destination = add_destination_ref(out->destination);
out = out->_next;
}
}
}
if ((frame->next_hop->reachable&REACHABLE)==REACHABLE_INDIRECT)
frame->next_hop = frame->next_hop->next_hop;
if (frame->next_hop->reachable&REACHABLE_DIRECT){
if (frame->destination_count < MAX_PACKET_DESTINATIONS)
frame->destinations[frame->destination_count++].destination=add_destination_ref(frame->next_hop->destination);
}
}else{
char added_interface[OVERLAY_MAX_INTERFACES]; char added_interface[OVERLAY_MAX_INTERFACES];
bzero(added_interface, sizeof(added_interface)); bzero(added_interface, sizeof(added_interface));
@ -892,10 +923,11 @@ int link_add_broadcast_destinations(struct overlay_frame *frame)
} }
} }
if (frame->destination_count < MAX_PACKET_DESTINATIONS)
frame->destinations[frame->destination_count++].destination=add_destination_ref(dest); frame->destinations[frame->destination_count++].destination=add_destination_ref(dest);
} }
} }
}
return 0; return 0;
} }
@ -977,6 +1009,7 @@ static struct link_out *create_out_link(struct neighbour *neighbour, overlay_int
else else
ret->destination = add_destination_ref(interface->destination); ret->destination = add_destination_ref(interface->destination);
ret->timeout = gettime_ms()+ret->destination->tick_ms*2; ret->timeout = gettime_ms()+ret->destination->tick_ms*2;
update_alarm(gettime_ms()+5);
} }
return ret; return ret;
} }

View File

@ -853,7 +853,7 @@ int link_state_legacy_ack(struct overlay_frame *frame, time_ms_t now);
int link_state_ack_soon(struct subscriber *sender); int link_state_ack_soon(struct subscriber *sender);
int link_state_should_forward_broadcast(struct subscriber *transmitter); int link_state_should_forward_broadcast(struct subscriber *transmitter);
int link_unicast_ack(struct subscriber *subscriber, struct overlay_interface *interface, struct sockaddr_in addr); int link_unicast_ack(struct subscriber *subscriber, struct overlay_interface *interface, struct sockaddr_in addr);
int link_add_broadcast_destinations(struct overlay_frame *frame); int link_add_destinations(struct overlay_frame *frame);
int generate_nonce(unsigned char *nonce,int bytes); int generate_nonce(unsigned char *nonce,int bytes);

View File

@ -145,13 +145,13 @@ test_routing() {
wait_until is_published $SIDC wait_until is_published $SIDC
set_instance +B set_instance +B
executeOk_servald route print executeOk_servald route print
assertStdoutGrep --matches=1 "^$SIDA:UNICAST :" assertStdoutGrep --matches=1 "^$SIDA:UNICAST:"
executeOk_servald dna lookup "$DIDC" executeOk_servald dna lookup "$DIDC"
assertStdoutLineCount '==' 1 assertStdoutLineCount '==' 1
assertStdoutGrep --matches=1 "^sid://$SIDC/local/$DIDC:$DIDC:$NAMEC\$" assertStdoutGrep --matches=1 "^sid://$SIDC/local/$DIDC:$DIDC:$NAMEC\$"
set_instance +C set_instance +C
executeOk_servald route print executeOk_servald route print
assertStdoutGrep --matches=1 "^$SIDA:UNICAST :" assertStdoutGrep --matches=1 "^$SIDA:UNICAST:"
executeOk_servald dna lookup "$DIDB" executeOk_servald dna lookup "$DIDB"
assertStdoutLineCount '==' 1 assertStdoutLineCount '==' 1
assertStdoutGrep --matches=1 "^sid://$SIDB/local/$DIDB:$DIDB:$NAMEB\$" assertStdoutGrep --matches=1 "^sid://$SIDB/local/$DIDB:$DIDB:$NAMEB\$"

View File

@ -18,13 +18,6 @@
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# Routing conditions that are known to not be working or covered by tests;
# - No support for multi-hop paths involving any unicast links
# - unicast only links need to be shared in the routing table
# - routing table needs to be shared to unicast only peers
# - unicast IP information should be shared among unicast peers
#
source "${0%/*}/../testframework.sh" source "${0%/*}/../testframework.sh"
source "${0%/*}/../testdefs.sh" source "${0%/*}/../testdefs.sh"
@ -241,29 +234,33 @@ doc_scan="Network scan with isolated clients"
setup_scan() { setup_scan() {
setup_servald setup_servald
assert_no_servald_processes assert_no_servald_processes
foreach_instance +A +B create_single_identity foreach_instance +A +B +C create_single_identity
foreach_instance +A +B add_interface 1 foreach_instance +A +B +C add_interface 1
set_instance +B foreach_instance +A +B +C \
executeOk_servald config \
set interfaces.1.dummy_address 127.0.1.11
foreach_instance +A +B \
executeOk_servald config \ executeOk_servald config \
set interfaces.1.drop_broadcasts 100 set interfaces.1.drop_broadcasts 100
foreach_instance +A +B start_routing_instance foreach_instance +A +B +C start_routing_instance
} }
test_scan() { test_scan() {
set_instance +A set_instance +A
executeOk_servald scan executeOk_servald scan
wait_until scan_completed wait_until scan_completed
wait_until has_seen_instances +B wait_until --timeout=10 has_seen_instances +B +C
executeOk_servald mdp ping --timeout=3 $SIDB 1
tfw_cat --stdout --stderr
executeOk_servald route print executeOk_servald route print
assertStdoutGrep --matches=1 "^$SIDB:UNICAST:" assertStdoutGrep --matches=1 "^$SIDB:UNICAST:"
assertStdoutGrep --matches=1 "^$SIDC:UNICAST:"
executeOk_servald mdp ping --timeout=3 $SIDB 1
tfw_cat --stdout --stderr
set_instance +B
executeOk_servald route print
assertStdoutGrep --matches=1 "^$SIDA:UNICAST:"
assertStdoutGrep --matches=1 "^$SIDC:INDIRECT:"
executeOk_servald mdp ping --timeout=3 $SIDC 1
tfw_cat --stdout --stderr
} }
scan_completed() { scan_completed() {
grep "Scan completed" $LOG||return1 grep "Scan completed" $instance_servald_log || return 1
return 0 return 0
} }
@ -275,7 +272,6 @@ setup_single_filter() {
foreach_instance +A +B add_interface 1 foreach_instance +A +B add_interface 1
set_instance +B set_instance +B
executeOk_servald config \ executeOk_servald config \
set interfaces.1.dummy_address 127.0.1.11 \
set interfaces.1.drop_broadcasts 100 set interfaces.1.drop_broadcasts 100
foreach_instance +A +B start_routing_instance foreach_instance +A +B start_routing_instance
} }
@ -360,6 +356,31 @@ test_multihop_linear() {
assertStdoutGrep --matches=1 "^6:$SIDA\$" assertStdoutGrep --matches=1 "^6:$SIDA\$"
} }
doc_unicast_route="Route across unicast links"
setup_unicast_route() {
setup_servald
assert_no_servald_processes
foreach_instance +A +B +C +D create_single_identity
foreach_instance +A +B add_interface 1
foreach_instance +B +C add_interface 2
foreach_instance +C +D add_interface 3
set_instance +A
executeOk_servald config \
set interfaces.1.drop_broadcasts 100
set_instance +C
executeOk_servald config \
set interfaces.2.drop_broadcasts 100 \
set interfaces.3.drop_broadcasts 100
foreach_instance +A +B +C +D start_routing_instance
}
test_unicast_route() {
wait_until --timeout=20 path_exists +A +B +C +D
wait_until --timeout=5 path_exists +D +C +B +A
set_instance +A
executeOk_servald mdp ping --timeout=3 $SIDD 1
tfw_cat --stdout --stderr
}
setup_offline() { setup_offline() {
setup_servald setup_servald
assert_no_servald_processes assert_no_servald_processes
@ -640,10 +661,10 @@ test_crowded_mess() {
foreach_instance +A +H \ foreach_instance +A +H \
wait_until has_seen_instances +A +H wait_until has_seen_instances +A +H
set_instance +A set_instance +A
executeOk_servald mdp ping --timeout=3 $SIDH 1
tfw_cat --stdout --stderr
executeOk_servald route print executeOk_servald route print
assertStdoutGrep --matches=1 "^$SIDH:INDIRECT:" assertStdoutGrep --matches=1 "^$SIDH:INDIRECT:"
executeOk_servald mdp ping --timeout=3 $SIDH 1
tfw_cat --stdout --stderr
} }
runTests "$@" runTests "$@"