From 5376ed199622117403c51d1aef1733b1f3c5b7d8 Mon Sep 17 00:00:00 2001 From: Keith Winstein Date: Mon, 13 Aug 2012 16:48:25 +0300 Subject: [PATCH] Use end-to-end-to-end connectivity (in transport layer) to control port hop. Avoid playing games with network-layer timestamps. --- src/network/network.cc | 36 +++++++++++++++++++++++++-------- src/network/network.h | 11 +++++++++- src/network/networktransport.cc | 3 +++ 3 files changed, 41 insertions(+), 9 deletions(-) diff --git a/src/network/network.cc b/src/network/network.cc index 72af284..907b1d3 100644 --- a/src/network/network.cc +++ b/src/network/network.cc @@ -107,17 +107,15 @@ Packet Connection::new_packet( string &s_payload ) return p; } -void Connection::reset( void ) +void Connection::hop_port( void ) { - if ( server ) { - has_remote_addr = false; - } else { /* client */ - if ( close( sock ) < 0 ) { - throw NetworkException( "close", errno ); - } + assert( !server ); - setup(); + if ( close( sock ) < 0 ) { + throw NetworkException( "close", errno ); } + + setup(); } void Connection::setup( void ) @@ -128,6 +126,8 @@ void Connection::setup( void ) throw NetworkException( "socket", errno ); } + last_port_choice = timestamp(); + /* Disable path MTU discovery */ #ifdef HAVE_IP_MTU_DISCOVER char flag = IP_PMTUDISC_DONT; @@ -157,6 +157,9 @@ Connection::Connection( const char *desired_ip, const char *desired_port ) /* se saved_timestamp( -1 ), saved_timestamp_received_at( 0 ), expected_receiver_seq( 0 ), + last_heard( -1 ), + last_port_choice( -1 ), + last_roundtrip_success( -1 ), RTT_hit( false ), SRTT( 1000 ), RTTVAR( 500 ), @@ -266,6 +269,9 @@ Connection::Connection( const char *key_str, const char *ip, int port ) /* clien saved_timestamp( -1 ), saved_timestamp_received_at( 0 ), expected_receiver_seq( 0 ), + last_heard( -1 ), + last_port_choice( -1 ), + last_roundtrip_success( -1 ), RTT_hit( false ), SRTT( 1000 ), RTTVAR( 500 ), @@ -307,6 +313,19 @@ void Connection::send( string s ) have_send_exception = true; send_exception = NetworkException( "sendto", errno ); } + + uint64_t now = timestamp(); + if ( server ) { + if ( now - last_heard > SERVER_ASSOCIATION_TIMEOUT ) { + has_remote_addr = false; + fprintf( stderr, "Server now detached from client.\n" ); + } + } else { /* client */ + if ( ( now - last_port_choice > PORT_HOP_INTERVAL ) + && ( now - last_roundtrip_success > PORT_HOP_INTERVAL ) ) { + hop_port(); + } + } } string Connection::recv( void ) @@ -364,6 +383,7 @@ string Connection::recv( void ) /* auto-adjust to remote host */ has_remote_addr = true; + last_heard = timestamp(); if ( server ) { /* only client can roam */ if ( (remote_addr.sin_addr.s_addr != packet_remote_addr.sin_addr.s_addr) diff --git a/src/network/network.h b/src/network/network.h index 4c42967..765990b 100644 --- a/src/network/network.h +++ b/src/network/network.h @@ -91,6 +91,9 @@ namespace Network { static const int PORT_RANGE_LOW = 60001; static const int PORT_RANGE_HIGH = 60999; + static const unsigned int SERVER_ASSOCIATION_TIMEOUT = 20000; + static const unsigned int PORT_HOP_INTERVAL = 20000; + static bool try_bind( int socket, uint32_t addr, int port ); int sock; @@ -112,6 +115,10 @@ namespace Network { uint64_t saved_timestamp_received_at; uint64_t expected_receiver_seq; + uint64_t last_heard; + uint64_t last_port_choice; + uint64_t last_roundtrip_success; /* transport layer needs to tell us this */ + bool RTT_hit; double SRTT; double RTTVAR; @@ -123,6 +130,8 @@ namespace Network { Packet new_packet( string &s_payload ); + void hop_port( void ); + public: Connection( const char *desired_ip, const char *desired_port ); /* server */ Connection( const char *key_str, const char *ip, int port ); /* client */ @@ -147,7 +156,7 @@ namespace Network { return have_send_exception ? &send_exception : NULL; } - void reset( void ); + void set_last_roundtrip_success( uint64_t s_success ) { last_roundtrip_success = s_success; } }; } diff --git a/src/network/networktransport.cc b/src/network/networktransport.cc index 7db4ef6..150f444 100644 --- a/src/network/networktransport.cc +++ b/src/network/networktransport.cc @@ -80,6 +80,9 @@ void Transport::recv( void ) sender.process_acknowledgment_through( inst.ack_num() ); + /* inform network layer of roundtrip (end-to-end-to-end) connectivity */ + connection.set_last_roundtrip_success( sender.get_sent_state_acked_timestamp() ); + /* first, make sure we don't already have the new state */ for ( typename list< TimestampedState >::iterator i = received_states.begin(); i != received_states.end();