From a9e2bfab0477d9f73026a14b4b53ab8fb5b8eb72 Mon Sep 17 00:00:00 2001 From: Michal Simon Date: Wed, 17 Jan 2018 17:13:14 +0100 Subject: [PATCH] [XrdCl] Try all IP addresses in case posix connect fails. --- docs/man/xrdcp.1 | 5 +++++ src/XrdCl/XrdClConstants.hh | 1 + src/XrdCl/XrdClDefaultEnv.cc | 1 + src/XrdCl/XrdClStream.cc | 37 ++++++++++++++++++++++++++---------- 4 files changed, 34 insertions(+), 10 deletions(-) diff --git a/docs/man/xrdcp.1 b/docs/man/xrdcp.1 index e65a0209dbe..92d041e11cc 100644 --- a/docs/man/xrdcp.1 +++ b/docs/man/xrdcp.1 @@ -456,6 +456,11 @@ XRD_NODELAY Disables the Nagle algorithm if set to 1 (default), enables it if set to 0. .RE +XRD_PREFERIPV4 +.RS 5 +If set the client tries first IPv4 address (turned off by default). +.RE + .SH NOTES Documentation for all components associated with \fBxrdcp\fR can be found at http://xrootd.org/docs.html diff --git a/src/XrdCl/XrdClConstants.hh b/src/XrdCl/XrdClConstants.hh index 3cb6c9daaea..9fa5b8cef78 100644 --- a/src/XrdCl/XrdClConstants.hh +++ b/src/XrdCl/XrdClConstants.hh @@ -69,6 +69,7 @@ namespace XrdCl const int DefaultXCpBlockSize = 134217728; // DefaultCPChunkSize * DefaultCPParallelChunks * 2 const int DefaultNoDelay = 1; const int DefaultAioSignal = 1; + const int DefaultPreferIPv4 = 0; const char * const DefaultPollerPreference = "built-in"; const char * const DefaultNetworkStack = "IPAuto"; diff --git a/src/XrdCl/XrdClDefaultEnv.cc b/src/XrdCl/XrdClDefaultEnv.cc index 0e91c1ebc79..298c37fee1b 100644 --- a/src/XrdCl/XrdClDefaultEnv.cc +++ b/src/XrdCl/XrdClDefaultEnv.cc @@ -289,6 +289,7 @@ namespace XrdCl REGISTER_VAR_INT( varsInt, "XCpBlockSize", DefaultXCpBlockSize ); REGISTER_VAR_INT( varsInt, "NoDelay", DefaultNoDelay ); REGISTER_VAR_INT( varsInt, "AioSignal", DefaultAioSignal ); + REGISTER_VAR_INT( varsInt, "PreferIPv4", DefaultPreferIPv4 ); REGISTER_VAR_STR( varsStr, "PollerPreference", DefaultPollerPreference ); REGISTER_VAR_STR( varsStr, "ClientMonitor", DefaultClientMonitor ); diff --git a/src/XrdCl/XrdClStream.cc b/src/XrdCl/XrdClStream.cc index 979f9aa006c..0f67643832f 100644 --- a/src/XrdCl/XrdClStream.cc +++ b/src/XrdCl/XrdClStream.cc @@ -240,7 +240,6 @@ namespace XrdCl return pLastFatalError; gettimeofday( &pConnectionStarted, 0 ); - pConnectionInitTime = now; ++pConnectionCount; //-------------------------------------------------------------------------- @@ -265,12 +264,23 @@ namespace XrdCl // It's more efficient to remove addresses from the back of a vector // so we reverse the it. //-------------------------------------------------------------------------- - std::reverse( pAddresses.begin(), pAddresses.end() ); - pSubStreams[0]->socket->SetAddress( pAddresses.back() ); - pAddresses.pop_back(); - st = pSubStreams[0]->socket->Connect( pConnectionWindow ); - if( st.IsOK() ) - pSubStreams[0]->status = Socket::Connecting; + int preferIPv4 = DefaultPreferIPv4; + DefaultEnv::GetEnv()->GetInt( "PreferIPv4", preferIPv4 ); + if( !preferIPv4 ) + std::reverse( pAddresses.begin(), pAddresses.end() ); + + while( !pAddresses.empty() ) + { + pSubStreams[0]->socket->SetAddress( pAddresses.back() ); + pAddresses.pop_back(); + pConnectionInitTime = ::time( 0 ); + st = pSubStreams[0]->socket->Connect( pConnectionWindow ); + if( st.IsOK() ) + { + pSubStreams[0]->status = Socket::Connecting; + break; + } + } return st; } @@ -676,12 +686,19 @@ namespace XrdCl //------------------------------------------------------------------------ if( !pAddresses.empty() ) { - pSubStreams[0]->socket->SetAddress( pAddresses.back() ); - pAddresses.pop_back(); + Status st; + do + { + pSubStreams[0]->socket->SetAddress( pAddresses.back() ); + pAddresses.pop_back(); + pConnectionInitTime = ::time( 0 ); + st = pSubStreams[0]->socket->Connect( pConnectionWindow ); + } + while( !pAddresses.empty() && !st.IsOK() ); - Status st = pSubStreams[0]->socket->Connect( pConnectionWindow-elapsed ); if( !st.IsOK() ) OnFatalError( subStream, st, scopedLock ); + return; } //------------------------------------------------------------------------