Establish a unicast link to a configured host on demand

This commit is contained in:
Jeremy Lakeman 2016-01-20 17:00:08 +10:30
parent d0da910b19
commit 389f16d2bb
7 changed files with 68 additions and 21 deletions

View File

@ -37,6 +37,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "overlay_packet.h"
#include "overlay_buffer.h"
#include "conf.h"
#include "overlay_interface.h"
#include "keyring.h"
#include "serval.h" // for overlay_send_frame()
@ -91,8 +92,6 @@ static void directory_send_keyring(struct subscriber *directory_service){
static void directory_update(struct sched_ent *alarm){
if (directory_service){
// always attempt to reload the address, may depend on DNS resolution
load_subscriber_address(directory_service);
if (directory_service->reachable & REACHABLE){
directory_send_keyring(directory_service);
@ -100,8 +99,14 @@ static void directory_update(struct sched_ent *alarm){
alarm->alarm = gettime_ms() + DIRECTORY_UPDATE_INTERVAL;
alarm->deadline = alarm->alarm + 10000;
schedule(alarm);
}else
INFOF("Directory service is not reachable");
}else{
// always attempt to reload the address, may depend on DNS resolution
struct network_destination *destination = load_subscriber_address(directory_service);
if (destination){
overlay_send_probe(directory_service, destination, OQ_MESH_MANAGEMENT);
release_destination_ref(destination);
}
}
}
}

View File

@ -118,7 +118,7 @@ struct subscriber *_find_subscriber(struct __sourceloc, const unsigned char *sid
void enum_subscribers(struct subscriber *start, int(*callback)(struct subscriber *, void *), void *context);
int set_reachable(struct subscriber *subscriber, struct network_destination *destination, struct subscriber *next_hop);
int load_subscriber_address(struct subscriber *subscriber);
struct network_destination *load_subscriber_address(struct subscriber *subscriber);
int process_explain(struct overlay_frame *frame);
int overlay_broadcast_drop_check(struct broadcast *addr);

View File

@ -524,8 +524,10 @@ int overlay_destination_configure(struct network_destination *dest, const struct
return WHYF("No tick interval specified for destination");
if (dest->ifconfig.reachable_timeout_ms<0)
dest->ifconfig.reachable_timeout_ms = tick_ms>0 ? tick_ms * 5 : 2500;
dest->ifconfig.reachable_timeout_ms = dest->ifconfig.tick_ms>0 ? dest->ifconfig.tick_ms * 5 : 2500;
DEBUGF(linkstate, "Configured destination, tick %d, reachable %d",
dest->ifconfig.tick_ms,
dest->ifconfig.reachable_timeout_ms);
limit_init(&dest->transfer_limit, dest->ifconfig.packet_interval);

View File

@ -106,20 +106,22 @@ int resolve_name(const char *name, struct in_addr *addr){
}
// load a unicast address from configuration
int load_subscriber_address(struct subscriber *subscriber)
struct network_destination *load_subscriber_address(struct subscriber *subscriber)
{
if (!subscriber || subscriber->reachable&REACHABLE)
return 0;
if (!subscriber || subscriber->reachable != REACHABLE_NONE)
return NULL;
int i = config_host_list__get(&config.hosts, &subscriber->sid);
// No unicast configuration? just return.
if (i == -1)
return 1;
return NULL;
const struct config_host *hostc = &config.hosts.av[i].value;
overlay_interface *interface = NULL;
if (*hostc->interface){
interface = overlay_interface_find_name(hostc->interface);
if (!interface)
return WHY("Can't find configured interface");
if (!interface){
WARNF("Can't find configured interface %s", hostc->interface);
return NULL;
}
}
struct socket_address addr;
bzero(&addr, sizeof(addr));
@ -130,19 +132,14 @@ int load_subscriber_address(struct subscriber *subscriber)
if (addr.inet.sin_addr.s_addr==INADDR_NONE){
if (interface || overlay_interface_get_default()){
if (resolve_name(hostc->host, &addr.inet.sin_addr))
return -1;
return NULL;
}else{
// interface isnt up yet
return 1;
return NULL;
}
}
DEBUGF(overlayrouting, "Loaded address %s for %s", alloca_socket_address(&addr), alloca_tohex_sid_t(subscriber->sid));
struct network_destination *destination = create_unicast_destination(&addr, interface);
if (!destination)
return -1;
int ret=overlay_send_probe(subscriber, destination, OQ_MESH_MANAGEMENT);
release_destination_ref(destination);
return ret;
return create_unicast_destination(&addr, interface);
}
/* Collection of unicast echo responses to detect working links */

View File

@ -1079,6 +1079,15 @@ int link_add_destinations(struct overlay_frame *frame)
}
}
if (next_hop->reachable==REACHABLE_NONE && frame->destination_count==0){
// check config for a hardcoded address
struct network_destination *destination = load_subscriber_address(frame->destination);
if (destination){
frame_add_destination(frame, next_hop, destination);
release_destination_ref(destination);
}
}
if ((next_hop->reachable&REACHABLE)==REACHABLE_INDIRECT)
next_hop = next_hop->next_hop;

View File

@ -105,6 +105,7 @@ configure_node() {
set debug.overlayinterfaces Yes \
set debug.linkstate Yes \
set interfaces.0.file dummy1 \
set interfaces.0.type wifi \
set interfaces.0.socket_type file \
set interfaces.0.broadcast.send off \
set interfaces.0.broadcast.drop on \

View File

@ -445,6 +445,39 @@ test_scan_one() {
tfw_cat --stdout --stderr
}
setup_fixedAddress() {
setup_servald
assert_no_servald_processes
foreach_instance +A +B create_single_identity
foreach_instance +A +B executeOk_servald config \
set server.interface_path "$SERVALD_VAR" \
set interfaces.0.file dummy1 \
set interfaces.0.socket_type file \
set interfaces.0.type wifi \
set interfaces.0.broadcast.send off \
set interfaces.0.broadcast.drop on \
set interfaces.0.default_route 1 \
set interfaces.0.dummy_netmask 255.255.255.0
set_instance +A
executeOk_servald config \
set hosts.$SIDB.address 10.0.2.1 \
set interfaces.0.dummy_address 10.0.1.1
set_instance +B
executeOk_servald config \
set interfaces.0.dummy_address 10.0.2.1
touch "$SERVALD_VAR/dummy1"
foreach_instance +A +B start_servald_server
foreach_instance +A +B \
wait_until interface_up
}
doc_fixedAddress="Establish a link from a configured fixed address"
test_fixedAddress() {
set_instance +A
executeOk_servald mdp ping --timeout=3 $SIDB 5
tfw_cat --stdout
wait_until path_exists +A +B
}
scan_completed() {
$GREP "Scan completed" $instance_servald_log || return 1
return 0