mirror of
https://github.com/servalproject/serval-dna.git
synced 2024-12-18 20:57:56 +00:00
Specify that unicast traffic should use unicast UDP packets
This commit is contained in:
parent
88f7fef992
commit
b35c1aca43
@ -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")
|
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_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(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(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(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, 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(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(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
|
END_STRUCT
|
||||||
|
|
||||||
ARRAY(interface_list, SORTED NO_DUPLICATES)
|
ARRAY(interface_list, SORTED NO_DUPLICATES)
|
||||||
|
@ -72,6 +72,7 @@ struct subscriber{
|
|||||||
struct sockaddr_in address;
|
struct sockaddr_in address;
|
||||||
time_ms_t last_stun_request;
|
time_ms_t last_stun_request;
|
||||||
time_ms_t last_probe;
|
time_ms_t last_probe;
|
||||||
|
time_ms_t last_probe_response;
|
||||||
time_ms_t last_rx;
|
time_ms_t last_rx;
|
||||||
time_ms_t last_acked;
|
time_ms_t last_acked;
|
||||||
time_ms_t last_tx;
|
time_ms_t last_tx;
|
||||||
|
@ -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);
|
return WHYF("Invalid tick interval %d specified for interface %s", interface->tick_ms, name);
|
||||||
|
|
||||||
limit_init(&interface->transfer_limit, packet_interval);
|
limit_init(&interface->transfer_limit, packet_interval);
|
||||||
|
|
||||||
|
interface->prefer_unicast = ifconfig->prefer_unicast;
|
||||||
|
|
||||||
if (ifconfig->dummy[0]) {
|
if (ifconfig->dummy[0]) {
|
||||||
interface->fileP = 1;
|
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_port = htons(PORT_DNA);
|
||||||
interface->broadcast_address.sin_addr.s_addr = interface->address.sin_addr.s_addr | ~interface->netmask.s_addr;
|
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_broadcasts = ifconfig->dummy_filter_broadcasts;
|
||||||
|
interface->drop_unicasts = ifconfig->dummy_filter_unicasts;
|
||||||
|
|
||||||
/* Seek to end of file as initial reading point */
|
/* Seek to end of file as initial reading point */
|
||||||
interface->recv_offset = lseek(interface->alarm.poll.fd,0,SEEK_END);
|
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)
|
if (config.debug.packetrx)
|
||||||
DEBUG_packet_visualise("Read from dummy interface", packet.payload, packet.payload_length);
|
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) &&
|
((!interface->drop_broadcasts) &&
|
||||||
memcmp(&packet.dst_addr, &interface->broadcast_address, sizeof(packet.dst_addr))==0)){
|
memcmp(&packet.dst_addr, &interface->broadcast_address, sizeof(packet.dst_addr))==0)){
|
||||||
|
|
||||||
|
@ -225,18 +225,20 @@ overlay_mdp_service_probe(overlay_mdp_frame *mdp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct subscriber *peer = find_subscriber(mdp->out.src.sid, SID_SIZE, 0);
|
struct subscriber *peer = find_subscriber(mdp->out.src.sid, SID_SIZE, 0);
|
||||||
|
if (peer->reachable == REACHABLE_SELF)
|
||||||
|
RETURN(0);
|
||||||
|
|
||||||
struct probe_contents probe;
|
struct probe_contents probe;
|
||||||
bcopy(&mdp->out.payload, &probe, sizeof(struct probe_contents));
|
bcopy(&mdp->out.payload, &probe, sizeof(struct probe_contents));
|
||||||
if (probe.addr.sin_family!=AF_INET)
|
if (probe.addr.sin_family!=AF_INET)
|
||||||
RETURN(WHY("Unsupported address family"));
|
RETURN(WHY("Unsupported address family"));
|
||||||
|
|
||||||
if (peer->reachable == REACHABLE_NONE || peer->reachable == REACHABLE_INDIRECT || (peer->reachable & REACHABLE_ASSUMED)){
|
peer->last_probe_response = gettime_ms();
|
||||||
peer->interface = &overlay_interfaces[probe.interface];
|
peer->interface = &overlay_interfaces[probe.interface];
|
||||||
peer->address.sin_family = AF_INET;
|
peer->address.sin_family = AF_INET;
|
||||||
peer->address.sin_addr = probe.addr.sin_addr;
|
peer->address.sin_addr = probe.addr.sin_addr;
|
||||||
peer->address.sin_port = probe.addr.sin_port;
|
peer->address.sin_port = probe.addr.sin_port;
|
||||||
set_reachable(peer, REACHABLE_UNICAST);
|
set_reachable(peer, REACHABLE_UNICAST | (peer->reachable & REACHABLE_DIRECT));
|
||||||
}
|
|
||||||
RETURN(0);
|
RETURN(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -235,23 +235,24 @@ int packetOkOverlay(struct overlay_interface *interface,unsigned char *packet, s
|
|||||||
|
|
||||||
// TODO probe unicast links when we detect an address change.
|
// 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 this is a dummy announcement for a node that isn't in our routing table
|
||||||
if (context.sender->reachable == REACHABLE_NONE) {
|
if (context.sender->reachable == REACHABLE_NONE) {
|
||||||
context.sender->interface = interface;
|
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
|
// assume for the moment, that we can reply with the same packet type
|
||||||
if (packet_flags&PACKET_UNICAST){
|
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);
|
set_reachable(context.sender, REACHABLE_UNICAST|REACHABLE_ASSUMED);
|
||||||
}else{
|
}else{
|
||||||
set_reachable(context.sender, REACHABLE_BROADCAST|REACHABLE_ASSUMED);
|
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){
|
if ((!(packet_flags&PACKET_UNICAST)) && context.sender->last_acked + interface->tick_ms <= now){
|
||||||
overlay_route_ack_selfannounce(interface,
|
overlay_route_ack_selfannounce(interface,
|
||||||
context.sender->last_acked>now - 3*interface->tick_ms?context.sender->last_acked:now,
|
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;
|
context.sender->last_acked = now;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (packet_flags & PACKET_UNICAST)
|
if (packet_flags & PACKET_UNICAST)
|
||||||
|
@ -165,6 +165,10 @@ int overlay_payload_enqueue(struct overlay_frame *p)
|
|||||||
if (p->queue>=OQ_MAX)
|
if (p->queue>=OQ_MAX)
|
||||||
return WHY("Invalid queue specified");
|
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];
|
overlay_txqueue *queue = &overlay_tx[p->queue];
|
||||||
|
|
||||||
if (config.debug.packettx)
|
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;
|
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){
|
if(r&REACHABLE_UNICAST){
|
||||||
frame->recvaddr = frame->next_hop->address;
|
frame->recvaddr = frame->next_hop->address;
|
||||||
frame->unicast = 1;
|
frame->unicast = 1;
|
||||||
|
@ -411,6 +411,9 @@ int overlay_route_recalc_node_metrics(overlay_node *n, time_ms_t now)
|
|||||||
best_observation=-1;
|
best_observation=-1;
|
||||||
reachable=REACHABLE_BROADCAST;
|
reachable=REACHABLE_BROADCAST;
|
||||||
interface = &overlay_interfaces[i];
|
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;
|
n->subscriber->next_hop = next_hop;
|
||||||
break;
|
break;
|
||||||
case REACHABLE_BROADCAST:
|
case REACHABLE_BROADCAST:
|
||||||
|
case REACHABLE_BROADCAST|REACHABLE_UNICAST:
|
||||||
n->subscriber->interface = interface;
|
n->subscriber->interface = interface;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
9
serval.h
9
serval.h
@ -354,7 +354,8 @@ typedef struct overlay_interface {
|
|||||||
char name[256];
|
char name[256];
|
||||||
int recv_offset;
|
int recv_offset;
|
||||||
int fileP; // dummyP
|
int fileP; // dummyP
|
||||||
int drop_broadcasts;
|
char drop_broadcasts;
|
||||||
|
char drop_unicasts;
|
||||||
int port;
|
int port;
|
||||||
int type;
|
int type;
|
||||||
/* Number of milli-seconds per tick for this interface, which is basically related to the
|
/* 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 */
|
unsigned tick_ms; /* milliseconds per tick */
|
||||||
struct subscriber *next_advert;
|
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 */
|
/* The time of the last tick on this interface in milli seconds */
|
||||||
time_ms_t last_tick_ms;
|
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.
|
/* sequence number of last packet sent on this interface.
|
||||||
Used to allow NACKs that can request retransmission of recent packets.
|
Used to allow NACKs that can request retransmission of recent packets.
|
||||||
|
@ -75,7 +75,7 @@ test_single_link() {
|
|||||||
executeOk_servald mdp ping $SIDB 1
|
executeOk_servald mdp ping $SIDB 1
|
||||||
tfw_cat --stdout --stderr
|
tfw_cat --stdout --stderr
|
||||||
executeOk_servald route print
|
executeOk_servald route print
|
||||||
assertStdoutGrep --matches=1 "^$SIDB:BROADCAST :"
|
assertStdoutGrep --matches=1 "^$SIDB:BROADCAST UNICAST :"
|
||||||
}
|
}
|
||||||
|
|
||||||
setup_multiple_nodes() {
|
setup_multiple_nodes() {
|
||||||
@ -98,9 +98,9 @@ test_multiple_nodes() {
|
|||||||
executeOk_servald mdp ping $SIDD 1
|
executeOk_servald mdp ping $SIDD 1
|
||||||
tfw_cat --stdout --stderr
|
tfw_cat --stdout --stderr
|
||||||
executeOk_servald route print
|
executeOk_servald route print
|
||||||
assertStdoutGrep --matches=1 "^$SIDB:BROADCAST :"
|
assertStdoutGrep --matches=1 "^$SIDB:BROADCAST "
|
||||||
assertStdoutGrep --matches=1 "^$SIDC:BROADCAST :"
|
assertStdoutGrep --matches=1 "^$SIDC:BROADCAST "
|
||||||
assertStdoutGrep --matches=1 "^$SIDD:BROADCAST :"
|
assertStdoutGrep --matches=1 "^$SIDD:BROADCAST "
|
||||||
}
|
}
|
||||||
|
|
||||||
setup_scan() {
|
setup_scan() {
|
||||||
@ -134,6 +134,52 @@ test_scan() {
|
|||||||
assertStdoutGrep --matches=1 "^$SIDB:UNICAST :"
|
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_multihop_linear() {
|
||||||
setup_servald
|
setup_servald
|
||||||
assert_no_servald_processes
|
assert_no_servald_processes
|
||||||
@ -152,7 +198,7 @@ test_multihop_linear() {
|
|||||||
executeOk_servald mdp ping $SIDD 1
|
executeOk_servald mdp ping $SIDD 1
|
||||||
tfw_cat --stdout --stderr
|
tfw_cat --stdout --stderr
|
||||||
executeOk_servald route print
|
executeOk_servald route print
|
||||||
assertStdoutGrep --matches=1 "^$SIDB:BROADCAST :"
|
assertStdoutGrep --matches=1 "^$SIDB:BROADCAST UNICAST :"
|
||||||
assertStdoutGrep --matches=1 "^$SIDC:INDIRECT :"
|
assertStdoutGrep --matches=1 "^$SIDC:INDIRECT :"
|
||||||
assertStdoutGrep --matches=1 "^$SIDD:INDIRECT :"
|
assertStdoutGrep --matches=1 "^$SIDD:INDIRECT :"
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user