mirror of
https://github.com/servalproject/serval-dna.git
synced 2024-12-18 20:57:56 +00:00
Route mulit-hop via unicast links
This commit is contained in:
parent
55657623aa
commit
9a50d8a9ef
@ -262,11 +262,11 @@ static int add_explain_response(struct subscriber *subscriber, void *context){
|
||||
// if one of our identities is unknown,
|
||||
// the header of this packet must include our full sid.
|
||||
if (subscriber->reachable==REACHABLE_SELF){
|
||||
subscriber->send_full=1;
|
||||
if (subscriber==my_subscriber){
|
||||
response->please_explain->source_full=1;
|
||||
return 0;
|
||||
}
|
||||
subscriber->send_full=1;
|
||||
}
|
||||
|
||||
// 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)
|
||||
frame->source_full=1;
|
||||
|
||||
if (destination && (destination->reachable & REACHABLE)){
|
||||
if (destination){
|
||||
frame->ttl = PAYLOAD_TTL_DEFAULT; // MAX?
|
||||
frame->destination = destination;
|
||||
frame->source_full=1;
|
||||
}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.
|
||||
frame->ttl=1;// how will this work with olsr??
|
||||
if (context->interface){
|
||||
|
@ -51,6 +51,8 @@ struct overlay_frame {
|
||||
time_ms_t delay_until;
|
||||
struct packet_destination destinations[MAX_PACKET_DESTINATIONS];
|
||||
int destination_count;
|
||||
int transmit_count;
|
||||
|
||||
// each payload gets a sequence number that is reused on retransmission
|
||||
int32_t mdp_sequence;
|
||||
|
||||
|
@ -303,6 +303,9 @@ int parseEnvelopeHeader(struct decode_context *context, struct overlay_interface
|
||||
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){
|
||||
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;
|
||||
|
@ -152,19 +152,6 @@ int overlay_payload_enqueue(struct overlay_frame *p)
|
||||
|
||||
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)
|
||||
return WHY("Invalid queue specified");
|
||||
|
||||
@ -199,7 +186,7 @@ int overlay_payload_enqueue(struct overlay_frame *p)
|
||||
// hook to allow for flooding via olsr
|
||||
olsr_send(p);
|
||||
|
||||
link_add_broadcast_destinations(p);
|
||||
link_add_destinations(p);
|
||||
|
||||
// just drop it now
|
||||
if (p->destination_count == 0){
|
||||
@ -311,15 +298,9 @@ overlay_calc_queue_time(overlay_txqueue *queue, struct overlay_frame *frame){
|
||||
return 0;
|
||||
}
|
||||
}else{
|
||||
// ignore payload alarm if the destination is currently unreachable
|
||||
if (!frame->destination){
|
||||
return 0;
|
||||
}
|
||||
if (!(frame->destination->reachable&REACHABLE)){
|
||||
if (!directory_service || !(directory_service->reachable&REACHABLE)){
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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))
|
||||
goto skip;
|
||||
|
||||
if (frame->destination_count==0){
|
||||
frame->next_hop = frame->destination;
|
||||
if (frame->destination_count==0 && 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
|
||||
if (frame->packet_version > frame->next_hop->max_packet_version)
|
||||
frame->packet_version = frame->next_hop->max_packet_version;
|
||||
|
||||
}
|
||||
// degrade packet version if required to reach the destination
|
||||
if (frame->packet_version > frame->next_hop->max_packet_version)
|
||||
frame->packet_version = frame->next_hop->max_packet_version;
|
||||
}
|
||||
|
||||
int destination_index=-1;
|
||||
@ -485,7 +440,8 @@ overlay_stuff_packet(struct outgoing_packet *packet, overlay_txqueue *queue, tim
|
||||
}
|
||||
|
||||
frame->destinations[destination_index].delay_until = now+200;
|
||||
|
||||
frame->transmit_count++;
|
||||
|
||||
if (config.debug.overlayframes){
|
||||
DEBUGF("Appended payload %p, %d type %x len %d for %s via %s",
|
||||
frame, frame->mdp_sequence,
|
||||
@ -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
|
||||
if (frame->packet_version<1 || frame->resend<=0 ||
|
||||
frame->enqueued_at + queue->latencyTarget < frame->destinations[destination_index].delay_until){
|
||||
if (frame->packet_version<1 || frame->resend<=0 || packet->seq==-1){
|
||||
if (config.debug.overlayframes)
|
||||
DEBUGF("Not waiting for retransmission (%d, %d, %d)", frame->packet_version, frame->resend, packet->seq);
|
||||
remove_destination(frame, destination_index);
|
||||
if (frame->destination_count==0){
|
||||
frame = overlay_queue_remove(queue, frame);
|
||||
|
75
route_link.c
75
route_link.c
@ -777,7 +777,7 @@ static int link_send_neighbours()
|
||||
|
||||
struct link_out *out = n->out_links;
|
||||
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)
|
||||
overlay_send_tick_packet(out->destination);
|
||||
if (out->destination->last_tx + out->destination->tick_ms < link_send_alarm.alarm)
|
||||
@ -871,31 +871,63 @@ struct link_in * get_neighbour_link(struct neighbour *neighbour, struct overlay_
|
||||
return link;
|
||||
}
|
||||
|
||||
int link_add_broadcast_destinations(struct overlay_frame *frame)
|
||||
int link_add_destinations(struct overlay_frame *frame)
|
||||
{
|
||||
char added_interface[OVERLAY_MAX_INTERFACES];
|
||||
bzero(added_interface, sizeof(added_interface));
|
||||
|
||||
struct neighbour *neighbour = neighbours;
|
||||
for(;neighbour;neighbour = neighbour->_next){
|
||||
if (neighbour->subscriber->reachable&REACHABLE_DIRECT){
|
||||
struct network_destination *dest = neighbour->subscriber->destination;
|
||||
// TODO set packet version per destination
|
||||
if (frame->packet_version > neighbour->subscriber->max_packet_version)
|
||||
frame->packet_version = neighbour->subscriber->max_packet_version;
|
||||
|
||||
if (!dest->unicast){
|
||||
// make sure we only add broadcast interfaces once
|
||||
int id = dest->interface - overlay_interfaces;
|
||||
if (added_interface[id]){
|
||||
continue;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
frame->destinations[frame->destination_count++].destination=add_destination_ref(dest);
|
||||
}
|
||||
|
||||
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];
|
||||
bzero(added_interface, sizeof(added_interface));
|
||||
|
||||
struct neighbour *neighbour = neighbours;
|
||||
for(;neighbour;neighbour = neighbour->_next){
|
||||
if (neighbour->subscriber->reachable&REACHABLE_DIRECT){
|
||||
struct network_destination *dest = neighbour->subscriber->destination;
|
||||
// TODO set packet version per destination
|
||||
if (frame->packet_version > neighbour->subscriber->max_packet_version)
|
||||
frame->packet_version = neighbour->subscriber->max_packet_version;
|
||||
|
||||
if (!dest->unicast){
|
||||
// make sure we only add broadcast interfaces once
|
||||
int id = dest->interface - overlay_interfaces;
|
||||
if (added_interface[id]){
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (frame->destination_count < MAX_PACKET_DESTINATIONS)
|
||||
frame->destinations[frame->destination_count++].destination=add_destination_ref(dest);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -977,6 +1009,7 @@ static struct link_out *create_out_link(struct neighbour *neighbour, overlay_int
|
||||
else
|
||||
ret->destination = add_destination_ref(interface->destination);
|
||||
ret->timeout = gettime_ms()+ret->destination->tick_ms*2;
|
||||
update_alarm(gettime_ms()+5);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
2
serval.h
2
serval.h
@ -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_should_forward_broadcast(struct subscriber *transmitter);
|
||||
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);
|
||||
|
||||
|
@ -145,13 +145,13 @@ test_routing() {
|
||||
wait_until is_published $SIDC
|
||||
set_instance +B
|
||||
executeOk_servald route print
|
||||
assertStdoutGrep --matches=1 "^$SIDA:UNICAST :"
|
||||
assertStdoutGrep --matches=1 "^$SIDA:UNICAST:"
|
||||
executeOk_servald dna lookup "$DIDC"
|
||||
assertStdoutLineCount '==' 1
|
||||
assertStdoutGrep --matches=1 "^sid://$SIDC/local/$DIDC:$DIDC:$NAMEC\$"
|
||||
set_instance +C
|
||||
executeOk_servald route print
|
||||
assertStdoutGrep --matches=1 "^$SIDA:UNICAST :"
|
||||
assertStdoutGrep --matches=1 "^$SIDA:UNICAST:"
|
||||
executeOk_servald dna lookup "$DIDB"
|
||||
assertStdoutLineCount '==' 1
|
||||
assertStdoutGrep --matches=1 "^sid://$SIDB/local/$DIDB:$DIDB:$NAMEB\$"
|
||||
|
@ -18,13 +18,6 @@
|
||||
# along with this program; if not, write to the Free Software
|
||||
# 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%/*}/../testdefs.sh"
|
||||
@ -241,29 +234,33 @@ doc_scan="Network scan with isolated clients"
|
||||
setup_scan() {
|
||||
setup_servald
|
||||
assert_no_servald_processes
|
||||
foreach_instance +A +B create_single_identity
|
||||
foreach_instance +A +B add_interface 1
|
||||
set_instance +B
|
||||
executeOk_servald config \
|
||||
set interfaces.1.dummy_address 127.0.1.11
|
||||
foreach_instance +A +B \
|
||||
foreach_instance +A +B +C create_single_identity
|
||||
foreach_instance +A +B +C add_interface 1
|
||||
foreach_instance +A +B +C \
|
||||
executeOk_servald config \
|
||||
set interfaces.1.drop_broadcasts 100
|
||||
foreach_instance +A +B start_routing_instance
|
||||
foreach_instance +A +B +C start_routing_instance
|
||||
}
|
||||
test_scan() {
|
||||
set_instance +A
|
||||
executeOk_servald scan
|
||||
wait_until scan_completed
|
||||
wait_until has_seen_instances +B
|
||||
executeOk_servald mdp ping --timeout=3 $SIDB 1
|
||||
tfw_cat --stdout --stderr
|
||||
wait_until --timeout=10 has_seen_instances +B +C
|
||||
executeOk_servald route print
|
||||
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() {
|
||||
grep "Scan completed" $LOG||return1
|
||||
grep "Scan completed" $instance_servald_log || return 1
|
||||
return 0
|
||||
}
|
||||
|
||||
@ -275,7 +272,6 @@ setup_single_filter() {
|
||||
foreach_instance +A +B add_interface 1
|
||||
set_instance +B
|
||||
executeOk_servald config \
|
||||
set interfaces.1.dummy_address 127.0.1.11 \
|
||||
set interfaces.1.drop_broadcasts 100
|
||||
foreach_instance +A +B start_routing_instance
|
||||
}
|
||||
@ -360,6 +356,31 @@ test_multihop_linear() {
|
||||
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_servald
|
||||
assert_no_servald_processes
|
||||
@ -640,10 +661,10 @@ test_crowded_mess() {
|
||||
foreach_instance +A +H \
|
||||
wait_until has_seen_instances +A +H
|
||||
set_instance +A
|
||||
executeOk_servald mdp ping --timeout=3 $SIDH 1
|
||||
tfw_cat --stdout --stderr
|
||||
executeOk_servald route print
|
||||
assertStdoutGrep --matches=1 "^$SIDH:INDIRECT:"
|
||||
executeOk_servald mdp ping --timeout=3 $SIDH 1
|
||||
tfw_cat --stdout --stderr
|
||||
}
|
||||
|
||||
runTests "$@"
|
||||
|
Loading…
Reference in New Issue
Block a user