Reduce packet header size for point-to-point links

- new interface.x.point_to_point config
- disable local echo for point to point dummy interfaces
- add ME and YOU sid abbreviation codes after learning other sid
This commit is contained in:
Jeremy Lakeman 2013-07-16 15:16:07 +09:30
parent ea2e55c62c
commit 49e0286b43
8 changed files with 101 additions and 15 deletions

View File

@ -443,6 +443,7 @@ ATOM(bool_t, send_broadcasts, 1, boolean,, "If false, don't send
ATOM(bool_t, default_route, 0, boolean,, "If true, use this interface as a default route")
ATOM(bool_t, prefer_unicast, 0, boolean,, "If true, send unicast data as unicast IP packets if available")
ATOM(bool_t, debug, 0, boolean,, "If true, log details of every outgoing packet")
ATOM(bool_t, point_to_point, 0, boolean,, "If true, assume there will only be two devices on this interface")
ATOM(bool_t, ctsrts, 0, boolean,, "If true, enable CTS/RTS hardware handshaking")
ATOM(int32_t, uartbps, 57600, int32_rs232baudrate,, "Speed of serial UART link speed (which may be different to serial device link speed)")
END_STRUCT

View File

@ -39,6 +39,8 @@ static struct broadcast bpilist[MAX_BPIS];
#define OA_CODE_SELF 0xff
#define OA_CODE_PREVIOUS 0xfe
#define OA_CODE_P2P_YOU 0xfd
#define OA_CODE_P2P_ME 0xfc
// each node has 16 slots based on the next 4 bits of a subscriber id
// each slot either points to another tree node or a struct subscriber.
@ -204,22 +206,37 @@ int overlay_address_append(struct decode_context *context, struct overlay_buffer
{
if (!subscriber)
return WHY("No address supplied");
if (context && subscriber==context->sender){
if(context
&& context->packet_version>=1
&& context->interface
&& subscriber == context->interface->other_device
&& context->interface->point_to_point){
if (ob_append_byte(b, OA_CODE_P2P_YOU))
return -1;
}else if(context
&& context->packet_version>=1
&& context->interface
&& !subscriber->send_full
&& subscriber == my_subscriber
&& context->interface->other_device
&& context->interface->point_to_point
&& (!context->encoding_header || !context->interface->local_echo)){
if (ob_append_byte(b, OA_CODE_P2P_ME))
return -1;
}else if (context && subscriber==context->sender){
if (ob_append_byte(b, OA_CODE_SELF))
return -1;
}else if(context && subscriber==context->previous){
if (ob_append_byte(b, OA_CODE_PREVIOUS))
return -1;
}else{
int len=SID_SIZE;
if (subscriber->send_full){
subscriber->send_full=0;
}else{
len=(subscriber->abbreviate_len+2)/2;
if (subscriber->reachable==REACHABLE_SELF)
if (context && context->encoding_header)
len++;
if (len>SID_SIZE)
len=SID_SIZE;
@ -328,6 +345,26 @@ int overlay_address_parse(struct decode_context *context, struct overlay_buffer
return WHY("Buffer too small");
switch(len){
case OA_CODE_P2P_YOU:
if (context->interface && context->interface->point_to_point){
*subscriber=my_subscriber;
context->previous=my_subscriber;
}else{
WHYF("Could not resolve address on %s, this isn't a configured point to point link", context->interface->name);
context->invalid_addresses=1;
}
return 0;
case OA_CODE_P2P_ME:
if (context->interface && context->interface->point_to_point && context->interface->other_device){
*subscriber=context->interface->other_device;
context->previous=*subscriber;
}else{
WHYF("Could not resolve address on %s, I don't know who is on the other end of this link!", context->interface->name);
context->invalid_addresses=1;
}
return 0;
case OA_CODE_SELF:
if (!context->sender){
INFO("Could not resolve address, sender has not been set");

View File

@ -106,7 +106,12 @@ struct decode_context{
int packet_version;
int encapsulation;
struct sockaddr_in addr;
int invalid_addresses;
union{
// only valid while decoding
int invalid_addresses;
// only valid while encoding
int encoding_header;
};
struct overlay_frame *please_explain;
struct subscriber *sender;
struct subscriber *previous;

View File

@ -392,6 +392,7 @@ overlay_interface_init(const char *name, struct in_addr src_addr, struct in_addr
interface->state=INTERFACE_STATE_DOWN;
interface->alarm.poll.fd=0;
interface->debug = ifconfig->debug;
interface->point_to_point = ifconfig->point_to_point;
// How often do we announce ourselves on this interface?
int tick_ms=-1;
@ -469,12 +470,15 @@ overlay_interface_init(const char *name, struct in_addr src_addr, struct in_addr
interface->address.sin_addr = src_addr;
interface->broadcast_address.sin_addr = broadcast;
interface->netmask = netmask;
interface->local_echo = 1;
if (overlay_interface_init_socket(overlay_interface_count))
return WHY("overlay_interface_init_socket() failed");
}else{
char read_file[1024];
interface->local_echo = interface->point_to_point?0:1;
strbuf d = strbuf_local(read_file, sizeof read_file);
strbuf_path_join(d, serval_instancepath(), config.server.interface_path, ifconfig->file, NULL);
if (strbuf_overrun(d))
@ -642,9 +646,12 @@ static void interface_read_file(struct overlay_interface *interface)
if (config.debug.packetrx)
DEBUG_packet_visualise("Read from dummy interface", packet.payload, packet.payload_length);
if (!should_drop(interface, packet.dst_addr)){
if (should_drop(interface, packet.dst_addr) || (packet.pid == getpid() && !interface->local_echo)){
if (config.debug.packetrx)
DEBUGF("Ignoring packet from %d, addressed to %s:%d", packet.pid,
inet_ntoa(packet.dst_addr.sin_addr), ntohs(packet.dst_addr.sin_port));
}else{
if (packetOkOverlay(interface, packet.payload, packet.payload_length, -1,
(struct sockaddr*)&packet.src_addr, sizeof(packet.src_addr))<0) {
if (config.debug.rejecteddata) {
@ -653,8 +660,7 @@ static void interface_read_file(struct overlay_interface *interface)
dump("the malformed packet",packet.payload,packet.payload_length);
}
}
}else if (config.debug.packetrx)
DEBUGF("Ignoring packet addressed to %s:%d", inet_ntoa(packet.dst_addr.sin_addr), ntohs(packet.dst_addr.sin_port));
}
}
}

View File

@ -47,9 +47,10 @@ int overlay_packet_init_header(int packet_version, int encapsulation,
return -1;
if (ob_append_byte(buff, encapsulation))
return -1;
context->encoding_header=1;
if (overlay_address_append(context, buff, my_subscriber))
return -1;
context->encoding_header=0;
context->sender = my_subscriber;
int flags=0;
@ -258,7 +259,11 @@ int parseEnvelopeHeader(struct decode_context *context, struct overlay_interface
IN();
time_ms_t now = gettime_ms();
context->interface = interface;
context->sender_interface = 0;
context->packet_version = ob_get(buffer);
if (context->packet_version < 0 || context->packet_version > SUPPORTED_PACKET_VERSION)
RETURN(WHYF("Packet version %d not recognised.", context->packet_version));
@ -271,9 +276,6 @@ int parseEnvelopeHeader(struct decode_context *context, struct overlay_interface
int packet_flags = ob_get(buffer);
context->sender_interface = 0;
context->interface = interface;
int sender_seq = -1;
if (packet_flags & PACKET_INTERFACE)
@ -293,6 +295,11 @@ int parseEnvelopeHeader(struct decode_context *context, struct overlay_interface
if (context->sender->max_packet_version < context->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->interface->other_device = context->sender;
}
// TODO probe unicast links when we detect an address change.
// if this is a dummy announcement for a node that isn't in our routing table

View File

@ -271,11 +271,13 @@ overlay_init_packet(struct outgoing_packet *packet, struct subscriber *destinati
int unicast, int packet_version,
overlay_interface *interface, struct sockaddr_in addr){
packet->interface = interface;
packet->context.interface = interface;
packet->i = (interface - overlay_interfaces);
packet->dest=addr;
packet->buffer=ob_new();
packet->seq=-1;
packet->packet_version = packet_version;
packet->context.packet_version = packet_version;
if (unicast)
packet->unicast_subscriber = destination;

View File

@ -403,7 +403,13 @@ typedef struct overlay_interface {
char prefer_unicast;
// can we use this interface for routes to addresses in other subnets?
int default_route;
// should we log more debug info on this interace? eg hex dumps of packets
char debug;
char local_echo;
// can we assume there will only be two devices on this interface?
char point_to_point;
struct subscriber *other_device;
/* Number of milli-seconds per tick for this interface, which is basically related to the
the typical TX range divided by the maximum expected speed of nodes in the network.

View File

@ -185,6 +185,28 @@ test_mismatched_encap() {
tfw_cat --stdout --stderr
}
doc_single_p2p="Start 2 instances on a point to point link"
setup_single_p2p() {
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.debug 1 \
set interfaces.1.encapsulation single \
set interfaces.1.point_to_point on
foreach_instance +A +B start_routing_instance
}
test_single_p2p() {
wait_until path_exists +A +B
wait_until path_exists +B +A
assertGrep "$instance_servald_log" 'Established point to point link'
set_instance +A
executeOk_servald mdp ping --timeout=3 $SIDB 1
tfw_cat --stdout --stderr
}
doc_slip_encoding="Test slip encoding and decoding"
setup_slip_encoding() {
setup_servald