@@ -39,6 +39,7 @@ struct ReachConfig {
3939 bool PrintStatistics {false };
4040 bool RequireAll {false };
4141 std::vector<const char *> HostNames;
42+ QuicAddr Address;
4243 uint32_t Parallel {1 };
4344 uint16_t Port {443 };
4445 MsQuicAlpn Alpn {" h3" };
@@ -124,6 +125,7 @@ bool ParseConfig(int argc, char **argv) {
124125 " -b, --built-in-val Use built-in TLS validation logic\n "
125126 " -c, --csv <file> Writes CSV results to the given file\n "
126127 " -h, --help Prints this help text\n "
128+ " -i, --ip <address> The IP address to use\n "
127129 " -l, --parallel <num> The numer of parallel hosts to test at once (def=1)\n "
128130 " -m, --mtu <mtu> The initial (IPv6) MTU to use (def=1288)\n "
129131 " -p, --port <port> The UDP port to use (def=443)\n "
@@ -154,14 +156,20 @@ bool ParseConfig(int argc, char **argv) {
154156 if (++i >= argc) { printf (" Missing MTU value\n " ); return false ; }
155157 Config.Settings .SetMinimumMtu ((uint16_t )atoi (argv[i]));
156158
157- } else if (!strcmp (argv[i], " --port" ) || !strcmp (argv[i], " -p" )) {
158- if (++i >= argc) { printf (" Missing port number\n " ); return false ; }
159- Config.Port = (uint16_t )atoi (argv[i]);
159+ } else if (!strcmp (argv[i], " --ip" ) || !strcmp (argv[i], " -i" )) {
160+ if (++i >= argc) { printf (" Missing IP address\n " ); return false ; }
161+ if (!QuicAddrFromString (argv[i], 0 , &Config.Address .SockAddr )) {
162+ printf (" Invalid address arg passed in\n " ); return false ;
163+ }
160164
161165 } else if (!strcmp (argv[i], " --parallel" ) || !strcmp (argv[i], " -l" )) {
162166 if (++i >= argc) { printf (" Missing parallel number\n " ); return false ; }
163167 Config.Parallel = (uint32_t )atoi (argv[i]);
164168
169+ } else if (!strcmp (argv[i], " --port" ) || !strcmp (argv[i], " -p" )) {
170+ if (++i >= argc) { printf (" Missing port number\n " ); return false ; }
171+ Config.Port = (uint16_t )atoi (argv[i]);
172+
165173 } else if (!strcmp (argv[i], " --stats" ) || !strcmp (argv[i], " -s" )) {
166174 Config.PrintStatistics = true ;
167175
@@ -190,6 +198,9 @@ struct ReachConnection : public MsQuicConnection {
190198 ) : MsQuicConnection(Registration, CleanUpAutoDelete, Callback), HostName(HostName) {
191199 IncStat (Results.TotalCount );
192200 Results.IncActive ();
201+ if (IsValid () && Config.Address .GetFamily () != QUIC_ADDRESS_FAMILY_UNSPEC) {
202+ InitStatus = SetRemoteAddr (Config.Address );
203+ }
193204 if (IsValid ()) {
194205 InitStatus = Start (Configuration, HostName, Config.Port );
195206 }
@@ -249,8 +260,10 @@ struct ReachConnection : public MsQuicConnection {
249260 TooMuch ? ' !' : (MultiRtt ? ' *' : ' ' ),
250261 Retry ? ' R' : ' ' ,
251262 ' \0 ' };
263+ QUIC_ADDR_STR AddrStr;
264+ QuicAddrToString (&RemoteAddr.SockAddr , &AddrStr);
252265 unique_lock<mutex> lock (Results.Mutex );
253- printf (" %30s %3u.%03u ms %3u.%03u ms %3u.%03u ms %u:%u %u:%u (%2.1fx) %4u %4u %s %s %s\n " ,
266+ printf (" %30s %3u.%03u ms %3u.%03u ms %3u.%03u ms %u:%u %u:%u (%2.1fx) %4u %4u %s %20s %s\n " ,
254267 HostName,
255268 Stats.Rtt / 1000 , Stats.Rtt % 1000 ,
256269 InitialTime / 1000 , InitialTime % 1000 ,
@@ -262,8 +275,8 @@ struct ReachConnection : public MsQuicConnection {
262275 Amplification,
263276 Stats.HandshakeClientFlight1Bytes ,
264277 Stats.HandshakeServerFlight1Bytes ,
265- RemoteAddr.GetFamily () == QUIC_ADDRESS_FAMILY_INET6 ? " IPv6" : " IPv4" ,
266278 Version == QUIC_VERSION_1 ? " v1" : " v2" ,
279+ AddrStr.Address ,
267280 HandshakeTags);
268281 }
269282 }
@@ -308,7 +321,7 @@ bool TestReachability() {
308321 Configuration.SetVersionNegotiationExtEnabled ();
309322
310323 if (Config.PrintStatistics )
311- printf (" %30s RTT TIME_I TIME_H SEND:RECV C1 S1 FAM VER \n " , " SERVER" );
324+ printf (" %30s RTT TIME_I TIME_H SEND:RECV C1 S1 VER IP \n " , " SERVER" );
312325
313326 for (auto HostName : Config.HostNames ) {
314327 new ReachConnection (Registration, Configuration, HostName);
0 commit comments