2012-11-21 02:22:39 +00:00
/*
2013-12-04 06:26:55 +00:00
Copyright ( C ) 2012 - 2013 Serval Project Inc .
2012-11-21 02:22:39 +00:00
This program is free software ; you can redistribute it and / or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation ; either version 2
of the License , or ( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 , USA .
*/
2013-11-25 06:13:32 +00:00
# include <assert.h>
2012-11-20 06:11:06 +00:00
# include "serval.h"
2012-12-11 05:29:46 +00:00
# include "conf.h"
2012-11-20 06:11:06 +00:00
# include "overlay_buffer.h"
2013-12-09 07:15:47 +00:00
# include "overlay_interface.h"
2012-11-20 06:11:06 +00:00
# include "overlay_packet.h"
2013-11-25 04:35:33 +00:00
# include "radio_link.h"
2012-11-20 06:11:06 +00:00
# include "str.h"
2012-11-22 00:25:54 +00:00
# include "strbuf.h"
2015-08-31 05:48:08 +00:00
# include "route_link.h"
2012-11-20 06:11:06 +00:00
typedef struct overlay_txqueue {
struct overlay_frame * first ;
struct overlay_frame * last ;
int length ; /* # frames in queue */
int maxLength ; /* max # frames in queue before we consider ourselves congested */
2013-05-27 03:40:58 +00:00
int small_packet_grace_interval ;
2012-11-20 06:11:06 +00:00
/* Latency target in ms for this traffic class.
Frames older than the latency target will get dropped . */
int latencyTarget ;
} overlay_txqueue ;
overlay_txqueue overlay_tx [ OQ_MAX ] ;
2013-08-08 05:50:31 +00:00
// short lived data while we are constructing an outgoing packet
2012-11-20 06:11:06 +00:00
struct outgoing_packet {
2013-08-08 05:50:31 +00:00
struct network_destination * destination ;
int seq ;
2013-05-24 04:22:31 +00:00
int packet_version ;
2012-12-04 04:17:57 +00:00
int header_length ;
2012-11-20 06:11:06 +00:00
struct overlay_buffer * buffer ;
2012-11-22 22:34:42 +00:00
struct decode_context context ;
2012-11-20 06:11:06 +00:00
} ;
2013-05-27 03:40:58 +00:00
# define SMALL_PACKET_SIZE (400)
2013-05-24 04:22:31 +00:00
int32_t mdp_sequence = 0 ;
2012-11-20 06:11:06 +00:00
struct sched_ent next_packet ;
struct profile_total send_packet ;
static void overlay_send_packet ( struct sched_ent * alarm ) ;
2013-12-09 07:52:18 +00:00
static int overlay_calc_queue_time ( struct overlay_frame * frame ) ;
2012-11-20 06:11:06 +00:00
int overlay_queue_init ( ) {
/* Set default congestion levels for queues */
int i ;
for ( i = 0 ; i < OQ_MAX ; i + + ) {
overlay_tx [ i ] . maxLength = 100 ;
2015-11-30 03:52:45 +00:00
overlay_tx [ i ] . latencyTarget = 0 ; // no QOS time limit by default, depend on per destination timeouts
2013-05-27 03:40:58 +00:00
overlay_tx [ i ] . small_packet_grace_interval = 5 ;
2012-11-20 06:11:06 +00:00
}
/* expire voice/video call packets much sooner, as they just aren't any use if late */
2012-12-19 00:08:17 +00:00
overlay_tx [ OQ_ISOCHRONOUS_VOICE ] . maxLength = 20 ;
2012-11-20 06:11:06 +00:00
overlay_tx [ OQ_ISOCHRONOUS_VOICE ] . latencyTarget = 200 ;
2013-05-27 03:40:58 +00:00
2012-11-20 06:11:06 +00:00
overlay_tx [ OQ_ISOCHRONOUS_VIDEO ] . latencyTarget = 200 ;
2013-05-27 03:40:58 +00:00
2015-03-30 03:45:08 +00:00
overlay_tx [ OQ_OPPORTUNISTIC ] . small_packet_grace_interval = 100 ;
2013-05-27 03:40:58 +00:00
return 0 ;
2012-11-20 06:11:06 +00:00
}
/* remove and free a payload from the queue */
static struct overlay_frame *
overlay_queue_remove ( overlay_txqueue * queue , struct overlay_frame * frame ) {
struct overlay_frame * prev = frame - > prev ;
struct overlay_frame * next = frame - > next ;
if ( prev )
prev - > next = next ;
else if ( frame = = queue - > first )
queue - > first = next ;
if ( next )
next - > prev = prev ;
else if ( frame = = queue - > last )
queue - > last = prev ;
queue - > length - - ;
2013-08-08 05:50:31 +00:00
while ( frame - > destination_count > 0 )
release_destination_ref ( frame - > destinations [ - - frame - > destination_count ] . destination ) ;
2012-11-20 06:11:06 +00:00
op_free ( frame ) ;
return next ;
}
2012-12-07 03:39:55 +00:00
#if 0 // unused
2012-11-20 06:11:06 +00:00
static int
overlay_queue_dump ( overlay_txqueue * q )
{
strbuf b = strbuf_alloca ( 8192 ) ;
struct overlay_frame * f ;
strbuf_sprintf ( b , " overlay_txqueue @ 0x%p \n " , q ) ;
strbuf_sprintf ( b , " length=%d \n " , q - > length ) ;
strbuf_sprintf ( b , " maxLenght=%d \n " , q - > maxLength ) ;
strbuf_sprintf ( b , " latencyTarget=%d milli-seconds \n " , q - > latencyTarget ) ;
strbuf_sprintf ( b , " first=%p \n " , q - > first ) ;
f = q - > first ;
while ( f ) {
strbuf_sprintf ( b , " %p: ->next=%p, ->prev=%p \n " ,
f , f - > next , f - > prev ) ;
if ( f = = f - > next ) {
strbuf_sprintf ( b , " LOOP! \n " ) ; break ;
}
f = f - > next ;
}
strbuf_sprintf ( b , " last=%p \n " , q - > last ) ;
f = q - > last ;
while ( f ) {
strbuf_sprintf ( b , " %p: ->next=%p, ->prev=%p \n " ,
f , f - > next , f - > prev ) ;
if ( f = = f - > prev ) {
strbuf_sprintf ( b , " LOOP! \n " ) ; break ;
}
f = f - > prev ;
}
2015-07-06 08:19:49 +00:00
_DEBUG ( strbuf_str ( b ) ) ;
2012-11-20 06:11:06 +00:00
return 0 ;
}
2012-12-07 03:39:55 +00:00
# endif
2012-11-20 06:11:06 +00:00
2013-01-28 02:35:24 +00:00
int overlay_queue_remaining ( int queue ) {
if ( queue < 0 | | queue > = OQ_MAX )
return - 1 ;
return overlay_tx [ queue ] . maxLength - overlay_tx [ queue ] . length ;
}
2014-06-28 10:47:26 +00:00
int _overlay_payload_enqueue ( struct __sourceloc __whence , struct overlay_frame * p )
2012-11-20 06:11:06 +00:00
{
/* Add payload p to queue q.
Queues get scanned from first to last , so we should append new entries
on the end of the queue .
Complain if there are too many frames in the queue .
*/
2013-11-25 06:13:32 +00:00
assert ( p ! = NULL ) ;
assert ( p - > queue < OQ_MAX ) ;
assert ( p - > payload ! = NULL ) ;
2014-06-28 10:47:26 +00:00
p - > whence = __whence ;
2012-11-20 06:11:06 +00:00
overlay_txqueue * queue = & overlay_tx [ p - > queue ] ;
2013-05-15 02:03:43 +00:00
2012-11-20 06:11:06 +00:00
2013-11-25 06:13:32 +00:00
if ( ob_overrun ( p - > payload ) )
return WHY ( " Packet content overrun -- not queueing " ) ;
2012-11-20 06:11:06 +00:00
2016-05-23 05:27:03 +00:00
if ( ob_position ( p - > payload ) > = MDP_OVERLAY_MTU )
2016-03-16 00:01:09 +00:00
FATALF ( " Queued packet len %u is too big " , ob_position ( p - > payload ) ) ;
2013-11-25 06:13:32 +00:00
2012-11-20 06:11:06 +00:00
if ( queue - > length > = queue - > maxLength )
return WHYF ( " Queue #%d congested (size = %d) " ,p->queue,queue->maxLength) ;
2013-08-08 05:50:31 +00:00
2013-07-08 06:31:58 +00:00
// it should be safe to try sending all packets with an mdp sequence
if ( p - > packet_version < = 0 )
p - > packet_version = 1 ;
2015-07-06 08:19:49 +00:00
if ( IF_DEBUG ( verbose ) )
DEBUGF ( overlayframes , " Enqueue packet to %s " ,
p - > destination ? alloca_tohex_sid_t_trunc ( p - > destination - > sid , 14 ) : " broadcast " ) ;
2013-08-08 05:50:31 +00:00
if ( p - > destination_count = = 0 ) {
if ( ! p - > destination ) {
2012-12-04 04:17:57 +00:00
// hook to allow for flooding via olsr
olsr_send ( p ) ;
2013-08-09 06:49:45 +00:00
link_add_destinations ( p ) ;
2013-08-08 05:50:31 +00:00
2012-12-04 04:17:57 +00:00
// just drop it now
2013-08-08 05:50:31 +00:00
if ( p - > destination_count = = 0 ) {
2015-07-06 08:19:49 +00:00
DEBUGF ( mdprequests , " Not transmitting, as we have nowhere to send it " ) ;
2014-03-27 03:01:43 +00:00
// free the packet and return success.
op_free ( p ) ;
return 0 ;
2013-05-29 01:44:26 +00:00
}
2012-11-20 06:11:06 +00:00
}
2013-08-08 05:50:31 +00:00
// allow the packet to be resent
if ( p - > resend = = 0 )
p - > resend = 1 ;
2015-06-22 03:00:18 +00:00
} else {
p - > manual_destinations = 1 ;
2013-08-08 05:50:31 +00:00
}
2013-08-29 05:35:32 +00:00
int i = 0 ;
for ( i = 0 ; i < p - > destination_count ; i + + ) {
p - > destinations [ i ] . sent_sequence = - 1 ;
2015-07-06 08:19:49 +00:00
if ( IF_DEBUG ( verbose ) )
DEBUGF ( overlayframes , " Sending %s on interface %s " ,
p - > destinations [ i ] . destination - > unicast ? " unicast " : " broadcast " ,
p - > destinations [ i ] . destination - > interface - > name ) ;
2012-11-20 06:11:06 +00:00
}
struct overlay_frame * l = queue - > last ;
if ( l ) l - > next = p ;
p - > prev = l ;
p - > next = NULL ;
p - > enqueued_at = gettime_ms ( ) ;
2013-05-24 04:22:31 +00:00
p - > mdp_sequence = - 1 ;
2012-11-20 06:11:06 +00:00
queue - > last = p ;
if ( ! queue - > first ) queue - > first = p ;
queue - > length + + ;
2012-12-15 23:35:32 +00:00
if ( p - > queue = = OQ_ISOCHRONOUS_VOICE )
rhizome_saw_voice_traffic ( ) ;
2012-11-20 06:11:06 +00:00
2013-12-09 07:52:18 +00:00
overlay_calc_queue_time ( p ) ;
2012-11-20 06:11:06 +00:00
return 0 ;
}
2013-11-25 06:13:32 +00:00
static int
2013-08-08 05:50:31 +00:00
overlay_init_packet ( struct outgoing_packet * packet , int packet_version ,
2013-11-25 06:13:32 +00:00
struct network_destination * destination )
{
2013-08-08 05:50:31 +00:00
packet - > context . interface = destination - > interface ;
2013-11-25 06:13:32 +00:00
if ( ( packet - > buffer = ob_new ( ) ) = = NULL )
return - 1 ;
2013-05-24 04:22:31 +00:00
packet - > packet_version = packet_version ;
2013-07-16 05:46:07 +00:00
packet - > context . packet_version = packet_version ;
2013-08-13 05:46:17 +00:00
packet - > destination = add_destination_ref ( destination ) ;
2013-08-09 02:48:14 +00:00
if ( destination - > sequence_number < 0 )
packet - > seq = - 1 ;
else
packet - > seq = destination - > sequence_number = ( destination - > sequence_number + 1 ) & 0xFFFF ;
2015-03-16 01:52:38 +00:00
ob_limitsize ( packet - > buffer , destination - > ifconfig . mtu ) ;
2013-11-25 06:13:32 +00:00
int i = destination - > interface - overlay_interfaces ;
2015-03-16 01:52:38 +00:00
if ( overlay_packet_init_header ( packet_version , destination - > ifconfig . encapsulation ,
2013-11-25 06:13:32 +00:00
& packet - > context , packet - > buffer ,
destination - > unicast ,
i , packet - > seq ) = = - 1
) {
ob_free ( packet - > buffer ) ;
packet - > buffer = NULL ;
return - 1 ;
}
2012-12-04 04:17:57 +00:00
packet - > header_length = ob_position ( packet - > buffer ) ;
2015-07-06 08:19:49 +00:00
DEBUGF ( overlayframes , " Creating %d packet for interface %s, seq %d, %s " ,
packet_version ,
destination - > interface - > name , destination - > sequence_number ,
alloca_socket_address ( & destination - > address )
) ;
2013-11-25 06:13:32 +00:00
return 0 ;
2012-11-20 06:11:06 +00:00
}
2013-02-06 06:40:43 +00:00
int overlay_queue_schedule_next ( time_ms_t next_allowed_packet ) {
if ( next_packet . alarm = = 0 | | next_allowed_packet < next_packet . alarm ) {
if ( ! next_packet . function ) {
next_packet . function = overlay_send_packet ;
send_packet . name = " overlay_send_packet " ;
next_packet . stats = & send_packet ;
}
unschedule ( & next_packet ) ;
next_packet . alarm = next_allowed_packet ;
// small grace period, we want to read incoming IO first
next_packet . deadline = next_allowed_packet + 15 ;
schedule ( & next_packet ) ;
}
return 0 ;
}
2015-03-30 00:57:37 +00:00
void frame_remove_destination ( struct overlay_frame * frame , int i ) {
2015-07-06 08:19:49 +00:00
DEBUGF ( overlayframes , " Remove %s destination on interface %s " ,
frame - > destinations [ i ] . destination - > unicast ? " unicast " : " broadcast " ,
frame - > destinations [ i ] . destination - > interface - > name
) ;
2013-08-08 05:50:31 +00:00
release_destination_ref ( frame - > destinations [ i ] . destination ) ;
frame - > destination_count - - ;
if ( i < frame - > destination_count )
frame - > destinations [ i ] = frame - > destinations [ frame - > destination_count ] ;
}
2015-03-30 00:57:37 +00:00
void frame_add_destination ( struct overlay_frame * frame , struct subscriber * next_hop , struct network_destination * dest ) {
2015-08-03 01:42:39 +00:00
if ( ( ! dest - > ifconfig . send ) | | frame - > destination_count > = MAX_PACKET_DESTINATIONS )
2015-03-30 00:57:37 +00:00
return ;
2015-08-03 01:42:39 +00:00
2015-03-30 00:57:37 +00:00
unsigned i = frame - > destination_count + + ;
frame - > destinations [ i ] . destination = add_destination_ref ( dest ) ;
frame - > destinations [ i ] . next_hop = next_hop ;
frame - > destinations [ i ] . sent_sequence = - 1 ;
2015-07-06 08:19:49 +00:00
DEBUGF ( overlayframes , " Add %s destination on interface %s " ,
frame - > destinations [ i ] . destination - > unicast ? " unicast " : " broadcast " ,
frame - > destinations [ i ] . destination - > interface - > name
) ;
2015-03-30 00:57:37 +00:00
}
2012-11-20 06:11:06 +00:00
// update the alarm time and return 1 if changed
static int
2013-12-09 07:52:18 +00:00
overlay_calc_queue_time ( struct overlay_frame * frame )
{
2013-08-08 05:50:31 +00:00
2012-12-13 07:20:09 +00:00
time_ms_t next_allowed_packet = 0 ;
2013-08-08 05:50:31 +00:00
// check all interfaces
if ( frame - > destination_count > 0 ) {
2012-12-13 07:20:09 +00:00
int i ;
2013-08-08 05:50:31 +00:00
for ( i = 0 ; i < frame - > destination_count ; i + + )
2012-12-13 07:20:09 +00:00
{
2013-11-25 04:35:33 +00:00
if ( radio_link_is_busy ( frame - > destinations [ i ] . destination - > interface ) )
2013-08-27 11:13:56 +00:00
continue ;
2013-08-08 05:50:31 +00:00
time_ms_t next_packet = limit_next_allowed ( & frame - > destinations [ i ] . destination - > transfer_limit ) ;
2013-08-29 05:35:32 +00:00
if ( frame - > destinations [ i ] . transmit_time ) {
time_ms_t delay_until = frame - > destinations [ i ] . transmit_time + frame - > destinations [ i ] . destination - > resend_delay ;
if ( next_packet < delay_until )
next_packet = delay_until ;
}
2012-12-13 07:20:09 +00:00
if ( next_allowed_packet = = 0 | | next_packet < next_allowed_packet )
next_allowed_packet = next_packet ;
}
2013-08-08 05:50:31 +00:00
if ( next_allowed_packet = = 0 ) {
return 0 ;
}
} else {
if ( ! frame - > destination ) {
2012-12-19 00:08:17 +00:00
return 0 ;
2013-08-08 05:50:31 +00:00
}
2012-12-13 07:20:09 +00:00
}
2012-12-04 04:17:57 +00:00
2013-08-08 05:50:31 +00:00
if ( next_allowed_packet < frame - > delay_until )
next_allowed_packet = frame - > delay_until ;
if ( next_allowed_packet < frame - > enqueued_at )
next_allowed_packet = frame - > enqueued_at ;
2013-05-15 02:03:43 +00:00
2013-05-27 03:40:58 +00:00
if ( ob_position ( frame - > payload ) < SMALL_PACKET_SIZE & &
next_allowed_packet < frame - > enqueued_at + overlay_tx [ frame - > queue ] . small_packet_grace_interval )
next_allowed_packet = frame - > enqueued_at + overlay_tx [ frame - > queue ] . small_packet_grace_interval ;
2013-02-06 06:40:43 +00:00
overlay_queue_schedule_next ( next_allowed_packet ) ;
2012-11-20 06:11:06 +00:00
2012-12-19 00:08:17 +00:00
return 0 ;
2012-11-20 06:11:06 +00:00
}
static void
2014-06-26 07:17:23 +00:00
overlay_stuff_packet ( struct outgoing_packet * packet , overlay_txqueue * queue , time_ms_t now , strbuf debug ) {
2012-11-20 06:11:06 +00:00
struct overlay_frame * frame = queue - > first ;
// TODO stop when the packet is nearly full?
while ( frame ) {
2015-03-30 03:45:08 +00:00
if ( queue - > latencyTarget ! = 0 & & frame - > enqueued_at + queue - > latencyTarget < now ) {
2015-11-30 03:52:45 +00:00
DEBUGF ( ack , " Dropping frame (%p) type %x (length %zu) for %s due to expiry timeout " ,
frame , frame - > type , frame - > payload - > checkpointLength ,
2015-07-06 08:19:49 +00:00
frame - > destination ? alloca_tohex_sid_t ( frame - > destination - > sid ) : " All "
) ;
2012-11-20 06:11:06 +00:00
frame = overlay_queue_remove ( queue , frame ) ;
continue ;
}
2012-12-13 07:20:09 +00:00
2013-08-08 05:50:31 +00:00
/* Note, once we queue a broadcast packet we are currently
* committed to sending it to every destination ,
* even if we hear it from somewhere else in the mean time
2012-11-20 06:11:06 +00:00
*/
2013-05-15 02:03:43 +00:00
// ignore payloads that are waiting for ack / nack resends
2013-08-08 05:50:31 +00:00
if ( frame - > delay_until > now )
2013-05-15 02:03:43 +00:00
goto skip ;
2015-03-16 01:52:38 +00:00
if ( packet - > buffer & & packet - > destination - > ifconfig . encapsulation = = ENCAP_SINGLE )
2013-08-08 05:50:31 +00:00
goto skip ;
2012-12-13 07:20:09 +00:00
// quickly skip payloads that have no chance of fitting
2015-03-30 00:57:37 +00:00
if ( packet - > buffer & & ob_position ( frame - > payload ) > ob_remaining ( packet - > buffer ) )
2012-12-13 07:20:09 +00:00
goto skip ;
2015-06-22 03:00:18 +00:00
if ( ! frame - > manual_destinations )
link_add_destinations ( frame ) ;
2013-08-08 05:50:31 +00:00
2015-06-22 01:13:54 +00:00
if ( frame - > mdp_sequence ! = - 1 & & ( ( mdp_sequence - frame - > mdp_sequence ) & 0xFFFF ) > = 64 ) {
2014-06-28 10:47:26 +00:00
// too late, we've sent too many packets for the next hop to correctly de-duplicate
2015-07-06 08:19:49 +00:00
DEBUGF ( overlayframes , " Retransmition of frame %p mdp seq %d, is too late to be de-duplicated " ,
frame , frame - > mdp_sequence ) ;
2014-06-28 10:47:26 +00:00
frame = overlay_queue_remove ( queue , frame ) ;
continue ;
}
2013-08-08 05:50:31 +00:00
int destination_index = - 1 ;
{
int i ;
for ( i = frame - > destination_count - 1 ; i > = 0 ; i - - ) {
struct network_destination * dest = frame - > destinations [ i ] . destination ;
if ( ! dest )
FATALF ( " Destination %d is NULL " , i ) ;
if ( ! dest - > interface )
FATALF ( " Destination interface %d is NULL " , i ) ;
if ( dest - > interface - > state ! = INTERFACE_STATE_UP ) {
// remove this destination
2015-03-30 00:57:37 +00:00
frame_remove_destination ( frame , i ) ;
continue ;
}
2015-03-30 03:45:08 +00:00
if ( frame - > enqueued_at + dest - > ifconfig . transmit_timeout_ms < now ) {
2015-11-30 03:52:45 +00:00
DEBUGF ( ack , " Dropping %p, %s packet destination for %s sent w. seq %d, %dms ago " ,
frame , dest - > unicast ? " unicast " : " broadcast " ,
frame - > whence . function , frame - > destinations [ i ] . sent_sequence ,
( int ) ( gettime_ms ( ) - frame - > destinations [ i ] . transmit_time ) ) ;
2015-03-30 03:45:08 +00:00
frame_remove_destination ( frame , i ) ;
continue ;
}
2015-03-30 00:57:37 +00:00
if ( ob_position ( frame - > payload ) > ( unsigned ) dest - > ifconfig . mtu ) {
WARNF ( " Skipping packet destination as size %zu > destination mtu %zd " ,
ob_position ( frame - > payload ) , dest - > ifconfig . mtu ) ;
frame_remove_destination ( frame , i ) ;
2013-08-08 05:50:31 +00:00
continue ;
}
2014-09-23 04:17:48 +00:00
// degrade packet version if required to reach the destination
if ( frame - > destinations [ i ] . next_hop
& & frame - > packet_version > frame - > destinations [ i ] . next_hop - > max_packet_version )
frame - > packet_version = frame - > destinations [ i ] . next_hop - > max_packet_version ;
2013-08-08 05:50:31 +00:00
2013-08-29 05:35:32 +00:00
if ( frame - > destinations [ i ] . transmit_time & &
frame - > destinations [ i ] . transmit_time + frame - > destinations [ i ] . destination - > resend_delay > now )
2013-08-08 05:50:31 +00:00
continue ;
2012-11-20 06:11:06 +00:00
2012-12-03 03:14:31 +00:00
if ( packet - > buffer ) {
2013-08-08 05:50:31 +00:00
if ( frame - > packet_version ! = packet - > packet_version )
continue ;
2012-12-03 03:14:31 +00:00
2013-08-08 05:50:31 +00:00
// is this packet going our way?
if ( dest = = packet - > destination ) {
destination_index = i ;
2012-12-13 07:20:09 +00:00
break ;
2012-12-03 03:14:31 +00:00
}
2013-08-08 05:50:31 +00:00
} else {
// skip this interface if the stream tx buffer has data
2013-11-25 04:35:33 +00:00
if ( radio_link_is_busy ( dest - > interface ) )
2012-12-03 03:14:31 +00:00
continue ;
2013-08-08 05:50:31 +00:00
2015-03-16 01:52:38 +00:00
// can we send a packet to this destination now?
2013-08-08 05:50:31 +00:00
if ( limit_is_allowed ( & dest - > transfer_limit ) )
continue ;
// send a packet to this destination
if ( frame - > source_full )
2016-06-15 07:38:25 +00:00
get_my_subscriber ( ) - > send_full = 1 ;
2013-11-25 06:13:32 +00:00
if ( overlay_init_packet ( packet , frame - > packet_version , dest ) ! = - 1 ) {
2014-06-26 07:17:23 +00:00
if ( debug ) {
strbuf_sprintf ( debug , " building packet %s %s %d [ " ,
packet - > destination - > interface - > name ,
alloca_socket_address ( & packet - > destination - > address ) ,
packet - > seq ) ;
}
2013-11-25 06:13:32 +00:00
destination_index = i ;
frame - > destinations [ i ] . sent_sequence = dest - > sequence_number ;
break ;
}
2012-11-20 06:11:06 +00:00
}
}
}
2013-08-08 05:50:31 +00:00
if ( frame - > destination_count = = 0 ) {
frame = overlay_queue_remove ( queue , frame ) ;
continue ;
2013-05-15 04:57:38 +00:00
}
2012-12-03 03:14:31 +00:00
2013-08-08 05:50:31 +00:00
if ( destination_index = = - 1 )
goto skip ;
2013-05-15 04:57:38 +00:00
if ( frame - > send_hook ) {
// last minute check if we really want to send this frame, or track when we sent it
2015-06-22 03:00:18 +00:00
if ( frame - > send_hook ( frame , packet - > destination , packet - > seq , frame - > send_context ) ) {
2013-05-15 04:57:38 +00:00
// drop packet
frame = overlay_queue_remove ( queue , frame ) ;
continue ;
}
}
2013-08-30 07:54:52 +00:00
2015-06-22 01:13:54 +00:00
if ( frame - > mdp_sequence = = - 1 ) {
frame - > mdp_sequence = mdp_sequence = ( mdp_sequence + 1 ) & 0xFFFF ;
}
2013-08-30 07:54:52 +00:00
char will_retransmit = 1 ;
if ( frame - > packet_version < 1 | | frame - > resend < = 0 | | packet - > seq = = - 1 )
will_retransmit = 0 ;
2015-03-16 01:52:38 +00:00
if ( overlay_frame_append_payload ( & packet - > context , packet - > destination - > ifconfig . encapsulation , frame ,
2014-09-23 04:17:48 +00:00
frame - > destinations [ destination_index ] . next_hop , packet - > buffer , will_retransmit ) ) {
2013-07-15 05:59:14 +00:00
// payload was not queued, delay the next attempt slightly
2013-08-08 05:50:31 +00:00
frame - > delay_until = now + 5 ;
2013-07-15 05:59:14 +00:00
goto skip ;
2013-05-24 04:22:31 +00:00
}
2013-08-29 05:35:32 +00:00
2014-09-23 04:17:48 +00:00
frame - > transmit_count + + ;
2013-08-29 05:35:32 +00:00
{
struct packet_destination * dest = & frame - > destinations [ destination_index ] ;
dest - > sent_sequence = dest - > destination - > sequence_number ;
dest - > transmit_time = now ;
2014-09-23 04:17:48 +00:00
if ( debug )
strbuf_sprintf ( debug , " %d(%s), " , frame - > mdp_sequence , frame - > whence . function ) ;
2015-07-06 08:19:49 +00:00
DEBUGF ( overlayframes , " Appended payload %p, %d type %x len %zd for %s via %s " ,
frame , frame - > mdp_sequence ,
frame - > type , ob_position ( frame - > payload ) ,
frame - > destination ? alloca_tohex_sid_t ( frame - > destination - > sid ) : " All " ,
dest - > next_hop ? alloca_tohex_sid_t ( dest - > next_hop - > sid ) : alloca_tohex ( frame - > broadcast_id . id , BROADCAST_LEN )
) ;
2013-08-29 05:35:32 +00:00
}
2013-02-07 04:46:07 +00:00
2013-08-08 05:50:31 +00:00
// dont retransmit if we aren't sending sequence numbers, or we've been asked not to
2013-08-30 07:54:52 +00:00
if ( ! will_retransmit ) {
2015-07-06 08:19:49 +00:00
DEBUGF ( overlayframes , " Not waiting for retransmission (%d, %d, %d) " , frame - > packet_version , frame - > resend , packet - > seq ) ;
2015-03-30 00:57:37 +00:00
frame_remove_destination ( frame , destination_index ) ;
2013-08-08 05:50:31 +00:00
if ( frame - > destination_count = = 0 ) {
frame = overlay_queue_remove ( queue , frame ) ;
continue ;
2012-11-20 06:11:06 +00:00
}
}
2013-05-22 03:57:41 +00:00
2012-11-20 06:11:06 +00:00
skip :
2012-12-04 04:17:57 +00:00
// if we can't send the payload now, check when we should try next
2013-12-09 07:52:18 +00:00
overlay_calc_queue_time ( frame ) ;
2012-11-20 06:11:06 +00:00
frame = frame - > next ;
}
}
// fill a packet from our outgoing queues and send it
static int
2014-06-26 07:17:23 +00:00
overlay_fill_send_packet ( struct outgoing_packet * packet , time_ms_t now , strbuf debug ) {
2012-11-20 06:11:06 +00:00
IN ( ) ;
2013-08-13 05:46:17 +00:00
int i ;
int ret = 0 ;
2014-06-26 07:17:23 +00:00
2012-11-20 06:11:06 +00:00
// while we're looking at queues, work out when to schedule another packet
unschedule ( & next_packet ) ;
next_packet . alarm = 0 ;
next_packet . deadline = 0 ;
for ( i = 0 ; i < OQ_MAX ; i + + ) {
overlay_txqueue * queue = & overlay_tx [ i ] ;
2014-06-26 07:17:23 +00:00
overlay_stuff_packet ( packet , queue , now , debug ) ;
2012-11-20 06:11:06 +00:00
}
if ( packet - > buffer ) {
2014-06-26 07:17:23 +00:00
if ( debug ) {
strbuf_sprintf ( debug , " ] " ) ;
2015-07-06 08:19:49 +00:00
_DEBUGF ( " %s " , strbuf_str ( debug ) ) ;
2014-06-26 07:17:23 +00:00
}
2012-12-04 04:17:57 +00:00
2013-09-11 01:43:33 +00:00
overlay_broadcast_ensemble ( packet - > destination , packet - > buffer ) ;
2013-08-13 05:46:17 +00:00
ret = 1 ;
2012-11-20 06:11:06 +00:00
}
2013-08-13 05:46:17 +00:00
if ( packet - > destination )
release_destination_ref ( packet - > destination ) ;
RETURN ( ret ) ;
2013-02-16 17:47:24 +00:00
OUT ( ) ;
2012-11-20 06:11:06 +00:00
}
// when the queue timer elapses, send a packet
2013-12-09 07:52:18 +00:00
static void overlay_send_packet ( struct sched_ent * UNUSED ( alarm ) )
{
2012-11-20 06:11:06 +00:00
struct outgoing_packet packet ;
bzero ( & packet , sizeof ( struct outgoing_packet ) ) ;
2013-05-22 03:57:41 +00:00
packet . seq = - 1 ;
2015-07-06 08:19:49 +00:00
strbuf debug = IF_DEBUG ( packets_sent ) ? strbuf_alloca ( 256 ) : NULL ;
2014-06-26 07:17:23 +00:00
overlay_fill_send_packet ( & packet , gettime_ms ( ) , debug ) ;
2012-11-20 06:11:06 +00:00
}
2013-04-30 07:05:45 +00:00
2013-11-25 06:13:32 +00:00
int overlay_send_tick_packet ( struct network_destination * destination )
{
2013-04-30 07:05:45 +00:00
struct outgoing_packet packet ;
bzero ( & packet , sizeof ( struct outgoing_packet ) ) ;
2014-06-26 07:17:23 +00:00
if ( overlay_init_packet ( & packet , 0 , destination ) ! = - 1 ) {
strbuf debug = NULL ;
2015-07-06 08:19:49 +00:00
if ( IF_DEBUG ( packets_sent ) ) {
2014-06-26 07:17:23 +00:00
debug = strbuf_alloca ( 256 ) ;
strbuf_sprintf ( debug , " building packet %s %s %d [ " ,
packet . destination - > interface - > name ,
alloca_socket_address ( & packet . destination - > address ) ,
packet . seq ) ;
}
overlay_fill_send_packet ( & packet , gettime_ms ( ) , debug ) ;
2016-09-06 05:30:21 +00:00
// This debug statement is used for testing; do not remove or alter.
DEBUGF ( overlaytick , " TICK name=%s destination=%s seq=%d " ,
packet . destination - > interface - > name ,
alloca_socket_address ( & packet . destination - > address ) ,
packet . seq ) ;
2014-06-26 07:17:23 +00:00
}
2013-04-30 07:05:45 +00:00
return 0 ;
}
2013-05-13 02:53:44 +00:00
2013-05-15 02:03:43 +00:00
// de-queue all packets that have been sent to this subscriber & have arrived.
2013-08-08 05:50:31 +00:00
int overlay_queue_ack ( struct subscriber * neighbour , struct network_destination * destination , uint32_t ack_mask , int ack_seq )
2013-05-13 02:53:44 +00:00
{
2013-08-08 05:50:31 +00:00
int i , j ;
2013-05-20 03:53:35 +00:00
time_ms_t now = gettime_ms ( ) ;
2014-05-12 04:09:46 +00:00
int rtt = 0 ;
2013-05-15 02:03:43 +00:00
for ( i = 0 ; i < OQ_MAX ; i + + ) {
struct overlay_frame * frame = overlay_tx [ i ] . first ;
2013-05-13 02:53:44 +00:00
2013-05-15 02:03:43 +00:00
while ( frame ) {
2013-08-12 04:51:31 +00:00
for ( j = frame - > destination_count - 1 ; j > = 0 ; j - - )
if ( frame - > destinations [ j ] . destination = = destination )
break ;
if ( j > = 0 ) {
int frame_seq = frame - > destinations [ j ] . sent_sequence ;
2014-09-23 04:17:48 +00:00
if ( frame_seq > = 0 & & ( frame - > destinations [ j ] . next_hop = = neighbour | | ! frame - > destination ) ) {
2013-08-12 04:51:31 +00:00
int seq_delta = ( ack_seq - frame_seq ) & 0xFF ;
2016-01-25 06:32:21 +00:00
char acked = ( seq_delta = = 0 | | ( seq_delta < = 32 & & ack_mask & ( ( uint32_t ) 1 < < ( seq_delta - 1 ) ) ) ) ? 1 : 0 ;
2013-08-12 04:51:31 +00:00
if ( acked ) {
2014-05-12 04:09:46 +00:00
int this_rtt = now - frame - > destinations [ j ] . transmit_time ;
2013-12-16 04:24:30 +00:00
// if we're on a fake network, the actual rtt can be unrealistic
2014-05-12 04:09:46 +00:00
if ( this_rtt < 10 )
this_rtt = 10 ;
if ( ! rtt | | this_rtt < rtt )
rtt = this_rtt ;
2013-08-29 05:35:32 +00:00
2015-07-06 08:19:49 +00:00
DEBUGF ( ack , " DROPPED DUE TO ACK: Packet %p to %s sent by seq %d, acked with seq %d " ,
frame , alloca_tohex_sid_t ( neighbour - > sid ) , frame_seq , ack_seq ) ;
2013-08-12 04:51:31 +00:00
// drop packets that don't need to be retransmitted
if ( frame - > destination | | frame - > destination_count < = 1 ) {
frame = overlay_queue_remove ( & overlay_tx [ i ] , frame ) ;
continue ;
2013-05-20 03:53:35 +00:00
}
2015-03-30 00:57:37 +00:00
frame_remove_destination ( frame , j ) ;
2013-08-12 04:51:31 +00:00
} else if ( seq_delta < 128 & & frame - > destination & & frame - > delay_until > now ) {
// retransmit asap
2015-07-06 08:19:49 +00:00
DEBUGF ( ack , " RE-TX DUE TO NACK: Requeue packet %p to %s sent by seq %d due to ack of seq %d " , frame , alloca_tohex_sid_t ( neighbour - > sid ) , frame_seq , ack_seq ) ;
2013-08-12 04:51:31 +00:00
frame - > delay_until = now ;
2013-12-09 07:52:18 +00:00
overlay_calc_queue_time ( frame ) ;
2013-05-20 03:53:35 +00:00
}
2013-05-15 02:03:43 +00:00
}
}
2013-08-08 05:50:31 +00:00
2013-08-12 04:51:31 +00:00
frame = frame - > next ;
2013-05-15 02:03:43 +00:00
}
}
2014-05-12 04:09:46 +00:00
if ( rtt ) {
if ( ! destination - > min_rtt | | rtt < destination - > min_rtt ) {
destination - > min_rtt = rtt ;
int delay = rtt * 2 + 40 ;
if ( delay < destination - > resend_delay ) {
destination - > resend_delay = delay ;
2015-07-06 08:19:49 +00:00
DEBUGF ( linkstate , " Adjusting resend delay to %d " , destination - > resend_delay ) ;
2014-05-12 04:09:46 +00:00
}
}
if ( ! destination - > max_rtt | | rtt > destination - > max_rtt )
destination - > max_rtt = rtt ;
}
2013-05-13 02:53:44 +00:00
return 0 ;
}