Specify that unicast traffic should use unicast UDP packets

This commit is contained in:
Jeremy Lakeman 2013-01-29 11:57:13 +11:00
parent 88f7fef992
commit b35c1aca43
9 changed files with 100 additions and 24 deletions

View File

@ -334,13 +334,15 @@ ATOM(struct pattern_list, match, PATTERN_LIST_EMPTY, cf_opt_pattern_list,
STRING(256, dummy, "", cf_opt_str_nonempty,, "Path of dummy file, absolute or relative to server.dummy_interface_dir")
ATOM(struct in_addr, dummy_address, (struct in_addr){htonl(0x7F000001)}, cf_opt_in_addr,, "Dummy interface address")
ATOM(struct in_addr, dummy_netmask, (struct in_addr){htonl(0xFFFFFF00)}, cf_opt_in_addr,, "Dummy interface netmask")
ATOM(int, dummy_filter_broadcasts, 0, cf_opt_int_boolean,, "If true, drop all incoming broadcast packets")
ATOM(char, dummy_filter_broadcasts, 0, cf_opt_char_boolean,, "If true, drop all incoming broadcast packets")
ATOM(char, dummy_filter_unicasts, 0, cf_opt_char_boolean,, "If true, drop all incoming unicast packets")
ATOM(short, type, OVERLAY_INTERFACE_WIFI, cf_opt_interface_type,, "Type of network interface")
ATOM(uint16_t, port, RHIZOME_HTTP_PORT, cf_opt_uint16_nonzero,, "Port number for network interface")
ATOM(int, packet_interval, -1, cf_opt_int,, "Minimum interval between packets in microseconds")
ATOM(int, mdp_tick_ms, -1, cf_opt_int32_nonneg,, "Override MDP tick interval for this interface")
ATOM(char, send_broadcasts, 1, cf_opt_char_boolean,, "If false, don't send any broadcast packets")
ATOM(int, default_route, 0, cf_opt_int_boolean,, "If true, use this interface as a default route")
ATOM(char, default_route, 0, cf_opt_char_boolean,, "If true, use this interface as a default route")
ATOM(char, prefer_unicast, 0, cf_opt_char_boolean,, "If true, send unicast data as unicast IP packets if available")
END_STRUCT
ARRAY(interface_list, SORTED NO_DUPLICATES)

View File

@ -72,6 +72,7 @@ struct subscriber{
struct sockaddr_in address;
time_ms_t last_stun_request;
time_ms_t last_probe;
time_ms_t last_probe_response;
time_ms_t last_rx;
time_ms_t last_acked;
time_ms_t last_tx;

View File

@ -397,6 +397,8 @@ overlay_interface_init(const char *name, struct in_addr src_addr, struct in_addr
return WHYF("Invalid tick interval %d specified for interface %s", interface->tick_ms, name);
limit_init(&interface->transfer_limit, packet_interval);
interface->prefer_unicast = ifconfig->prefer_unicast;
if (ifconfig->dummy[0]) {
interface->fileP = 1;
@ -421,6 +423,7 @@ overlay_interface_init(const char *name, struct in_addr src_addr, struct in_addr
interface->broadcast_address.sin_port = htons(PORT_DNA);
interface->broadcast_address.sin_addr.s_addr = interface->address.sin_addr.s_addr | ~interface->netmask.s_addr;
interface->drop_broadcasts = ifconfig->dummy_filter_broadcasts;
interface->drop_unicasts = ifconfig->dummy_filter_unicasts;
/* Seek to end of file as initial reading point */
interface->recv_offset = lseek(interface->alarm.poll.fd,0,SEEK_END);
@ -586,7 +589,7 @@ void overlay_dummy_poll(struct sched_ent *alarm)
if (config.debug.packetrx)
DEBUG_packet_visualise("Read from dummy interface", packet.payload, packet.payload_length);
if (memcmp(&packet.dst_addr, &interface->address, sizeof(packet.dst_addr))==0 ||
if (((!interface->drop_unicasts) && memcmp(&packet.dst_addr, &interface->address, sizeof(packet.dst_addr))==0) ||
((!interface->drop_broadcasts) &&
memcmp(&packet.dst_addr, &interface->broadcast_address, sizeof(packet.dst_addr))==0)){

View File

@ -225,18 +225,20 @@ overlay_mdp_service_probe(overlay_mdp_frame *mdp)
}
struct subscriber *peer = find_subscriber(mdp->out.src.sid, SID_SIZE, 0);
if (peer->reachable == REACHABLE_SELF)
RETURN(0);
struct probe_contents probe;
bcopy(&mdp->out.payload, &probe, sizeof(struct probe_contents));
if (probe.addr.sin_family!=AF_INET)
RETURN(WHY("Unsupported address family"));
if (peer->reachable == REACHABLE_NONE || peer->reachable == REACHABLE_INDIRECT || (peer->reachable & REACHABLE_ASSUMED)){
peer->interface = &overlay_interfaces[probe.interface];
peer->address.sin_family = AF_INET;
peer->address.sin_addr = probe.addr.sin_addr;
peer->address.sin_port = probe.addr.sin_port;
set_reachable(peer, REACHABLE_UNICAST);
}
peer->last_probe_response = gettime_ms();
peer->interface = &overlay_interfaces[probe.interface];
peer->address.sin_family = AF_INET;
peer->address.sin_addr = probe.addr.sin_addr;
peer->address.sin_port = probe.addr.sin_port;
set_reachable(peer, REACHABLE_UNICAST | (peer->reachable & REACHABLE_DIRECT));
RETURN(0);
}

View File

@ -235,23 +235,24 @@ int packetOkOverlay(struct overlay_interface *interface,unsigned char *packet, s
// TODO probe unicast links when we detect an address change.
// always update the IP address we heard them from, even if we don't need to use it right now
context.sender->address = f.recvaddr;
// if this is a dummy announcement for a node that isn't in our routing table
if (context.sender->reachable == REACHABLE_NONE) {
context.sender->interface = interface;
context.sender->address = f.recvaddr;
context.sender->last_probe = 0;
// assume for the moment, that we can reply with the same packet type
if (packet_flags&PACKET_UNICAST){
/* Note the probe payload must be queued before any SID/SAS request so we can force the packet to have a full sid */
overlay_send_probe(context.sender, f.recvaddr, interface, OQ_MESH_MANAGEMENT);
set_reachable(context.sender, REACHABLE_UNICAST|REACHABLE_ASSUMED);
}else{
set_reachable(context.sender, REACHABLE_BROADCAST|REACHABLE_ASSUMED);
}
}
/* Note the probe payload must be queued before any SID/SAS request so we can force the packet to have a full sid */
if (context.sender->last_probe==0 || now - context.sender->last_probe > 5000)
overlay_send_probe(context.sender, f.recvaddr, interface, OQ_MESH_MANAGEMENT);
if ((!(packet_flags&PACKET_UNICAST)) && context.sender->last_acked + interface->tick_ms <= now){
overlay_route_ack_selfannounce(interface,
context.sender->last_acked>now - 3*interface->tick_ms?context.sender->last_acked:now,
@ -259,6 +260,7 @@ int packetOkOverlay(struct overlay_interface *interface,unsigned char *packet, s
context.sender->last_acked = now;
}
}
if (packet_flags & PACKET_UNICAST)

View File

@ -165,6 +165,10 @@ int overlay_payload_enqueue(struct overlay_frame *p)
if (p->queue>=OQ_MAX)
return WHY("Invalid queue specified");
/* queue a unicast probe if we haven't for a while. */
if (p->destination && (p->destination->last_probe==0 || gettime_ms() - p->destination->last_probe > 5000))
overlay_send_probe(p->destination, p->destination->address, p->destination->interface, OQ_MESH_MANAGEMENT);
overlay_txqueue *queue = &overlay_tx[p->queue];
if (config.debug.packettx)
@ -346,6 +350,17 @@ overlay_stuff_packet(struct outgoing_packet *packet, overlay_txqueue *queue, tim
frame->interface = frame->next_hop->interface;
// if both broadcast and unicast are available, pick on based on interface preference
if ((r&(REACHABLE_UNICAST|REACHABLE_BROADCAST))==(REACHABLE_UNICAST|REACHABLE_BROADCAST)){
if (frame->interface->prefer_unicast){
r=REACHABLE_UNICAST;
// used by tests
if (config.debug.overlayframes)
DEBUGF("Choosing to send via unicast for %s", alloca_tohex_sid(frame->destination->sid));
}else
r=REACHABLE_BROADCAST;
}
if(r&REACHABLE_UNICAST){
frame->recvaddr = frame->next_hop->address;
frame->unicast = 1;

View File

@ -411,6 +411,9 @@ int overlay_route_recalc_node_metrics(overlay_node *n, time_ms_t now)
best_observation=-1;
reachable=REACHABLE_BROADCAST;
interface = &overlay_interfaces[i];
// if we've probed this unicast link, preserve the status
if ((n->subscriber->reachable&REACHABLE_UNICAST) && !(n->subscriber->reachable&REACHABLE_ASSUMED))
reachable|=REACHABLE_UNICAST;
}
}
}
@ -455,6 +458,7 @@ int overlay_route_recalc_node_metrics(overlay_node *n, time_ms_t now)
n->subscriber->next_hop = next_hop;
break;
case REACHABLE_BROADCAST:
case REACHABLE_BROADCAST|REACHABLE_UNICAST:
n->subscriber->interface = interface;
break;
}

View File

@ -354,7 +354,8 @@ typedef struct overlay_interface {
char name[256];
int recv_offset;
int fileP; // dummyP
int drop_broadcasts;
char drop_broadcasts;
char drop_unicasts;
int port;
int type;
/* Number of milli-seconds per tick for this interface, which is basically related to the
@ -371,11 +372,11 @@ typedef struct overlay_interface {
unsigned tick_ms; /* milliseconds per tick */
struct subscriber *next_advert;
int send_broadcasts;
char send_broadcasts;
char prefer_unicast;
/* The time of the last tick on this interface in milli seconds */
time_ms_t last_tick_ms;
/* How many times have we abbreviated our address since we last announced it in full? */
int ticks_since_sent_full_address;
/* sequence number of last packet sent on this interface.
Used to allow NACKs that can request retransmission of recent packets.

View File

@ -75,7 +75,7 @@ test_single_link() {
executeOk_servald mdp ping $SIDB 1
tfw_cat --stdout --stderr
executeOk_servald route print
assertStdoutGrep --matches=1 "^$SIDB:BROADCAST :"
assertStdoutGrep --matches=1 "^$SIDB:BROADCAST UNICAST :"
}
setup_multiple_nodes() {
@ -98,9 +98,9 @@ test_multiple_nodes() {
executeOk_servald mdp ping $SIDD 1
tfw_cat --stdout --stderr
executeOk_servald route print
assertStdoutGrep --matches=1 "^$SIDB:BROADCAST :"
assertStdoutGrep --matches=1 "^$SIDC:BROADCAST :"
assertStdoutGrep --matches=1 "^$SIDD:BROADCAST :"
assertStdoutGrep --matches=1 "^$SIDB:BROADCAST "
assertStdoutGrep --matches=1 "^$SIDC:BROADCAST "
assertStdoutGrep --matches=1 "^$SIDD:BROADCAST "
}
setup_scan() {
@ -134,6 +134,52 @@ test_scan() {
assertStdoutGrep --matches=1 "^$SIDB:UNICAST :"
}
setup_broadcast_only() {
setup_servald
assert_no_servald_processes
foreach_instance +A +B create_single_identity
foreach_instance +A +B add_interface 1
foreach_instance +A +B \
executeOk_servald config \
set interfaces.1.dummy_filter_unicasts 1
foreach_instance +A +B start_routing_instance
}
doc_broadcast_only="Broadcast packets only"
test_broadcast_only() {
foreach_instance +A +B \
wait_until has_seen_instances +A +B
set_instance +A
executeOk_servald mdp ping $SIDB 1
tfw_cat --stdout --stderr
executeOk_servald route print
assertStdoutGrep --matches=1 "^$SIDB:BROADCAST :"
}
setup_prefer_unicast() {
setup_servald
assert_no_servald_processes
foreach_instance +A +B create_single_identity
foreach_instance +A +B add_interface 1
foreach_instance +A +B \
executeOk_servald config \
set interfaces.1.prefer_unicast 1 \
set debug.overlayframes 1
foreach_instance +A +B start_routing_instance
}
doc_prefer_unicast="Prefer unicast packets"
test_prefer_unicast() {
foreach_instance +A +B \
wait_until has_seen_instances +A +B
set_instance +A
executeOk_servald mdp ping $SIDB 1
tfw_cat --stdout --stderr
executeOk_servald route print
assertStdoutGrep --matches=1 "^$SIDB:BROADCAST UNICAST :"
assertGrep "$instance_servald_log" 'Choosing to send via unicast'
}
setup_multihop_linear() {
setup_servald
assert_no_servald_processes
@ -152,7 +198,7 @@ test_multihop_linear() {
executeOk_servald mdp ping $SIDD 1
tfw_cat --stdout --stderr
executeOk_servald route print
assertStdoutGrep --matches=1 "^$SIDB:BROADCAST :"
assertStdoutGrep --matches=1 "^$SIDB:BROADCAST UNICAST :"
assertStdoutGrep --matches=1 "^$SIDC:INDIRECT :"
assertStdoutGrep --matches=1 "^$SIDD:INDIRECT :"
}