From 49e0286b431b54c2e5dd2029133f2e3293a07ed9 Mon Sep 17 00:00:00 2001 From: Jeremy Lakeman Date: Tue, 16 Jul 2013 15:16:07 +0930 Subject: [PATCH] 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 --- conf_schema.h | 1 + overlay_address.c | 47 ++++++++++++++++++++++++++++++++++++----- overlay_address.h | 7 +++++- overlay_interface.c | 16 +++++++++----- overlay_packetformats.c | 15 +++++++++---- overlay_queue.c | 2 ++ serval.h | 6 ++++++ tests/routing | 22 +++++++++++++++++++ 8 files changed, 101 insertions(+), 15 deletions(-) diff --git a/conf_schema.h b/conf_schema.h index a15ce9bc..f543817b 100644 --- a/conf_schema.h +++ b/conf_schema.h @@ -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 diff --git a/overlay_address.c b/overlay_address.c index 6837c1d0..db8e2d36 100644 --- a/overlay_address.c +++ b/overlay_address.c @@ -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"); diff --git a/overlay_address.h b/overlay_address.h index f3cd6851..2f58175d 100644 --- a/overlay_address.h +++ b/overlay_address.h @@ -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; diff --git a/overlay_interface.c b/overlay_interface.c index af832c6e..c3359598 100644 --- a/overlay_interface.c +++ b/overlay_interface.c @@ -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)); + } } } diff --git a/overlay_packetformats.c b/overlay_packetformats.c index b81b70c1..536e97d0 100644 --- a/overlay_packetformats.c +++ b/overlay_packetformats.c @@ -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 diff --git a/overlay_queue.c b/overlay_queue.c index 1a87fc0a..739f66b4 100644 --- a/overlay_queue.c +++ b/overlay_queue.c @@ -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; diff --git a/serval.h b/serval.h index 6ea16dba..255f99bd 100644 --- a/serval.h +++ b/serval.h @@ -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. diff --git a/tests/routing b/tests/routing index 51c39dc6..e1666b39 100755 --- a/tests/routing +++ b/tests/routing @@ -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