@@ -77,72 +77,103 @@ std::string ToString(DiagnosticFailureReason reason) {
7777#ifndef _WIN32
7878namespace {
7979
80- bool CanConnectTcp (std::string const & host, std::uint16_t port,
81- std::chrono::milliseconds timeout) {
82- int const sock = socket (AF_INET , SOCK_STREAM , 0 );
83- if (sock < 0 ) return false ;
84-
85- std::int64_t const total_usec =
86- std::chrono::duration_cast<std::chrono::microseconds>(timeout).count ();
87- struct timeval tv;
88- tv.tv_sec = static_cast <time_t >(total_usec / 1000000 );
89- tv.tv_usec = static_cast <suseconds_t >(total_usec % 1000000 );
90- setsockopt (sock, SOL_SOCKET , SO_RCVTIMEO , &tv, sizeof (tv));
91- setsockopt (sock, SOL_SOCKET , SO_SNDTIMEO , &tv, sizeof (tv));
92-
93- struct sockaddr_in addr;
94- std::memset (&addr, 0 , sizeof (addr));
95- addr.sin_family = AF_INET ;
96- addr.sin_port = htons (port);
97- inet_pton (AF_INET , host.c_str (), &addr.sin_addr );
98-
99- int const res =
100- connect (sock, reinterpret_cast <struct sockaddr *>(&addr), sizeof (addr));
101- close (sock);
102- return res == 0 ;
103- }
104-
105- DiagnosticFailureReason CheckLoopbackConfiguration () {
106- struct ifaddrs * ifaddr = nullptr ;
107- if (getifaddrs (&ifaddr) == -1 ) return DiagnosticFailureReason::kUnknown ;
108-
109- bool has_ipv4_lo = false ;
110- bool has_ipv6_lo = false ;
80+ class DefaultDirectPathNetworkSystem : public DirectPathNetworkSystem {
81+ public:
82+ bool CanConnectTcp (std::string const & host, std::uint16_t port,
83+ std::chrono::milliseconds timeout) override {
84+ int const sock = socket (AF_INET , SOCK_STREAM , 0 );
85+ if (sock < 0 ) return false ;
86+
87+ std::int64_t const total_usec =
88+ std::chrono::duration_cast<std::chrono::microseconds>(timeout).count ();
89+ struct timeval tv;
90+ tv.tv_sec = static_cast <time_t >(total_usec / 1000000 );
91+ tv.tv_usec = static_cast <suseconds_t >(total_usec % 1000000 );
92+ setsockopt (sock, SOL_SOCKET , SO_RCVTIMEO , &tv, sizeof (tv));
93+ setsockopt (sock, SOL_SOCKET , SO_SNDTIMEO , &tv, sizeof (tv));
94+
95+ struct sockaddr_in addr;
96+ std::memset (&addr, 0 , sizeof (addr));
97+ addr.sin_family = AF_INET ;
98+ addr.sin_port = htons (port);
99+ inet_pton (AF_INET , host.c_str (), &addr.sin_addr );
100+
101+ int const res =
102+ connect (sock, reinterpret_cast <struct sockaddr *>(&addr), sizeof (addr));
103+ close (sock);
104+ return res == 0 ;
105+ }
111106
112- for (struct ifaddrs * ifa = ifaddr; ifa != nullptr ; ifa = ifa->ifa_next ) {
113- if (ifa->ifa_addr == nullptr ) continue ;
114- if (std::string (ifa->ifa_name ) == " lo" ) {
115- if (ifa->ifa_addr ->sa_family == AF_INET ) {
116- has_ipv4_lo = true ;
117- } else if (ifa->ifa_addr ->sa_family == AF_INET6 ) {
118- has_ipv6_lo = true ;
107+ DiagnosticFailureReason CheckLoopbackConfiguration () override {
108+ struct ifaddrs * ifaddr = nullptr ;
109+ if (getifaddrs (&ifaddr) == -1 ) return DiagnosticFailureReason::kUnknown ;
110+
111+ bool has_ipv4_lo = false ;
112+ bool has_ipv6_lo = false ;
113+
114+ for (struct ifaddrs * ifa = ifaddr; ifa != nullptr ; ifa = ifa->ifa_next ) {
115+ if (ifa->ifa_addr == nullptr ) continue ;
116+ if (std::string (ifa->ifa_name ) == " lo" ) {
117+ if (ifa->ifa_addr ->sa_family == AF_INET ) {
118+ has_ipv4_lo = true ;
119+ } else if (ifa->ifa_addr ->sa_family == AF_INET6 ) {
120+ has_ipv6_lo = true ;
121+ }
119122 }
120123 }
121- }
122- freeifaddrs (ifaddr);
124+ freeifaddrs (ifaddr);
123125
124- if (!has_ipv4_lo && !has_ipv6_lo) {
125- return DiagnosticFailureReason::kLoopbackMisconfigured ;
126+ if (!has_ipv4_lo && !has_ipv6_lo) {
127+ return DiagnosticFailureReason::kLoopbackMisconfigured ;
128+ }
129+ if (!has_ipv4_lo) {
130+ return DiagnosticFailureReason::kLoopbackMisconfiguredIpv4 ;
131+ }
132+ if (!has_ipv6_lo) {
133+ return DiagnosticFailureReason::kLoopbackMisconfiguredIpv6 ;
134+ }
135+ return DiagnosticFailureReason::kUnknown ;
126136 }
127- if (!has_ipv4_lo) {
128- return DiagnosticFailureReason::kLoopbackMisconfiguredIpv4 ;
137+ };
138+
139+ } // namespace
140+
141+ std::shared_ptr<DirectPathNetworkSystem> MakeDefaultDirectPathNetworkSystem () {
142+ return std::make_shared<DefaultDirectPathNetworkSystem>();
143+ }
144+
145+ #else
146+
147+ namespace {
148+
149+ class DefaultDirectPathNetworkSystem : public DirectPathNetworkSystem {
150+ public:
151+ bool CanConnectTcp (std::string const &, std::uint16_t ,
152+ std::chrono::milliseconds) override {
153+ return false ;
129154 }
130- if (!has_ipv6_lo) {
131- return DiagnosticFailureReason::kLoopbackMisconfiguredIpv6 ;
155+ DiagnosticFailureReason CheckLoopbackConfiguration () override {
156+ return DiagnosticFailureReason::kUnknown ;
132157 }
133- return DiagnosticFailureReason::kUnknown ;
134- }
158+ };
135159
136160} // namespace
161+
162+ std::shared_ptr<DirectPathNetworkSystem> MakeDefaultDirectPathNetworkSystem () {
163+ return std::make_shared<DefaultDirectPathNetworkSystem>();
164+ }
137165#endif
138166
139167DiagnosticFailureReason DirectPathDiagnostics::RunDiagnostics (
140168 Options const & options) {
141- return RunDiagnostics (options, internal::MakeGcpDetector ());
169+ return RunDiagnostics (options, internal::MakeGcpDetector (),
170+ MakeDefaultDirectPathNetworkSystem (), " 169.254.169.254" ,
171+ 80 );
142172}
143173
144174DiagnosticFailureReason DirectPathDiagnostics::RunDiagnostics (
145175 Options const & options, std::shared_ptr<internal::GcpDetector> detector,
176+ std::shared_ptr<DirectPathNetworkSystem> network_system,
146177 std::string const & metadata_host, std::uint16_t metadata_port) {
147178 // Step 1: Check platform (GCP VM)
148179 if (detector == nullptr ) {
@@ -152,43 +183,46 @@ DiagnosticFailureReason DirectPathDiagnostics::RunDiagnostics(
152183 return DiagnosticFailureReason::kNotInGcp ;
153184 }
154185
155- #ifdef _WIN32
156- return DiagnosticFailureReason::kUnknown ;
157- #else
186+ if (network_system == nullptr ) {
187+ network_system = MakeDefaultDirectPathNetworkSystem ();
188+ }
189+
158190 // Step 2: Metadata server reachability
159191 std::chrono::milliseconds timeout =
160192 options.get <bigtable::experimental::DirectPathDiagnosticsTimeoutOption>();
161193 if (timeout <= std::chrono::milliseconds::zero ()) {
162194 timeout = std::chrono::milliseconds (500 );
163195 }
164196
165- if (!CanConnectTcp (metadata_host, metadata_port, timeout)) {
197+ if (!network_system-> CanConnectTcp (metadata_host, metadata_port, timeout)) {
166198 return DiagnosticFailureReason::kMetadataUnreachable ;
167199 }
168200
169201 // Step 3 & 4: Loopback configuration check
170- DiagnosticFailureReason const lo_result = CheckLoopbackConfiguration ();
202+ DiagnosticFailureReason const lo_result =
203+ network_system->CheckLoopbackConfiguration ();
171204 if (lo_result != DiagnosticFailureReason::kUnknown ) {
172205 return lo_result;
173206 }
174207
175208 // Step 5: Route resolution or fallback
176209 return DiagnosticFailureReason::kUnknown ;
177- #endif
178210}
179211
180212#ifdef GOOGLE_CLOUD_CPP_BIGTABLE_WITH_OTEL_METRICS
181213void DirectPathDiagnostics::RunAsync (
182214 CompletionQueue cq, Options const & options,
183215 std::shared_ptr<DirectAccessCompatibility> direct_access_compatibility) {
184216 RunAsync (std::move (cq), options, std::move (direct_access_compatibility),
185- internal::MakeGcpDetector ());
217+ internal::MakeGcpDetector (), MakeDefaultDirectPathNetworkSystem (),
218+ " 169.254.169.254" , 80 );
186219}
187220
188221void DirectPathDiagnostics::RunAsync (
189222 CompletionQueue cq, Options const & options,
190223 std::shared_ptr<DirectAccessCompatibility> direct_access_compatibility,
191224 std::shared_ptr<internal::GcpDetector> detector,
225+ std::shared_ptr<DirectPathNetworkSystem> network_system,
192226 std::string const & metadata_host, std::uint16_t metadata_port) {
193227 std::chrono::milliseconds timeout =
194228 options.get <bigtable::experimental::DirectPathDiagnosticsTimeoutOption>();
@@ -199,10 +233,12 @@ void DirectPathDiagnostics::RunAsync(
199233 cq.RunAsync ([options,
200234 direct_access_compatibility =
201235 std::move (direct_access_compatibility),
202- detector = std::move (detector), metadata_host, metadata_port]() {
236+ detector = std::move (detector),
237+ network_system = std::move (network_system), metadata_host,
238+ metadata_port]() {
203239 DiagnosticFailureReason const reason =
204- DirectPathDiagnostics::RunDiagnostics (options, detector, metadata_host ,
205- metadata_port);
240+ DirectPathDiagnostics::RunDiagnostics (options, detector, network_system ,
241+ metadata_host, metadata_port);
206242 if (direct_access_compatibility != nullptr ) {
207243 direct_access_compatibility->Record (
208244 opentelemetry::context::RuntimeContext::GetCurrent (), 0 ,
0 commit comments