1 /* 2 * Copyright 2011 The WebRTC Project Authors. All rights reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #include <algorithm> 12 #include <vector> 13 14 #include "webrtc/p2p/base/pseudotcp.h" 15 #include "webrtc/base/gunit.h" 16 #include "webrtc/base/helpers.h" 17 #include "webrtc/base/messagehandler.h" 18 #include "webrtc/base/stream.h" 19 #include "webrtc/base/thread.h" 20 #include "webrtc/base/timeutils.h" 21 22 using cricket::PseudoTcp; 23 24 static const int kConnectTimeoutMs = 10000; // ~3 * default RTO of 3000ms 25 static const int kTransferTimeoutMs = 15000; 26 static const int kBlockSize = 4096; 27 28 class PseudoTcpForTest : public cricket::PseudoTcp { 29 public: 30 PseudoTcpForTest(cricket::IPseudoTcpNotify* notify, uint32_t conv) 31 : PseudoTcp(notify, conv) {} 32 33 bool isReceiveBufferFull() const { 34 return PseudoTcp::isReceiveBufferFull(); 35 } 36 37 void disableWindowScale() { 38 PseudoTcp::disableWindowScale(); 39 } 40 }; 41 42 class PseudoTcpTestBase : public testing::Test, 43 public rtc::MessageHandler, 44 public cricket::IPseudoTcpNotify { 45 public: 46 PseudoTcpTestBase() 47 : local_(this, 1), 48 remote_(this, 1), 49 have_connected_(false), 50 have_disconnected_(false), 51 local_mtu_(65535), 52 remote_mtu_(65535), 53 delay_(0), 54 loss_(0) { 55 // Set use of the test RNG to get predictable loss patterns. 56 rtc::SetRandomTestMode(true); 57 } 58 ~PseudoTcpTestBase() { 59 // Put it back for the next test. 60 rtc::SetRandomTestMode(false); 61 } 62 void SetLocalMtu(int mtu) { 63 local_.NotifyMTU(mtu); 64 local_mtu_ = mtu; 65 } 66 void SetRemoteMtu(int mtu) { 67 remote_.NotifyMTU(mtu); 68 remote_mtu_ = mtu; 69 } 70 void SetDelay(int delay) { 71 delay_ = delay; 72 } 73 void SetLoss(int percent) { 74 loss_ = percent; 75 } 76 void SetOptNagling(bool enable_nagles) { 77 local_.SetOption(PseudoTcp::OPT_NODELAY, !enable_nagles); 78 remote_.SetOption(PseudoTcp::OPT_NODELAY, !enable_nagles); 79 } 80 void SetOptAckDelay(int ack_delay) { 81 local_.SetOption(PseudoTcp::OPT_ACKDELAY, ack_delay); 82 remote_.SetOption(PseudoTcp::OPT_ACKDELAY, ack_delay); 83 } 84 void SetOptSndBuf(int size) { 85 local_.SetOption(PseudoTcp::OPT_SNDBUF, size); 86 remote_.SetOption(PseudoTcp::OPT_SNDBUF, size); 87 } 88 void SetRemoteOptRcvBuf(int size) { 89 remote_.SetOption(PseudoTcp::OPT_RCVBUF, size); 90 } 91 void SetLocalOptRcvBuf(int size) { 92 local_.SetOption(PseudoTcp::OPT_RCVBUF, size); 93 } 94 void DisableRemoteWindowScale() { 95 remote_.disableWindowScale(); 96 } 97 void DisableLocalWindowScale() { 98 local_.disableWindowScale(); 99 } 100 101 protected: 102 int Connect() { 103 int ret = local_.Connect(); 104 if (ret == 0) { 105 UpdateLocalClock(); 106 } 107 return ret; 108 } 109 void Close() { 110 local_.Close(false); 111 UpdateLocalClock(); 112 } 113 114 enum { MSG_LPACKET, MSG_RPACKET, MSG_LCLOCK, MSG_RCLOCK, MSG_IOCOMPLETE, 115 MSG_WRITE}; 116 virtual void OnTcpOpen(PseudoTcp* tcp) { 117 // Consider ourselves connected when the local side gets OnTcpOpen. 118 // OnTcpWriteable isn't fired at open, so we trigger it now. 119 LOG(LS_VERBOSE) << "Opened"; 120 if (tcp == &local_) { 121 have_connected_ = true; 122 OnTcpWriteable(tcp); 123 } 124 } 125 // Test derived from the base should override 126 // virtual void OnTcpReadable(PseudoTcp* tcp) 127 // and 128 // virtual void OnTcpWritable(PseudoTcp* tcp) 129 virtual void OnTcpClosed(PseudoTcp* tcp, uint32_t error) { 130 // Consider ourselves closed when the remote side gets OnTcpClosed. 131 // TODO: OnTcpClosed is only ever notified in case of error in 132 // the current implementation. Solicited close is not (yet) supported. 133 LOG(LS_VERBOSE) << "Closed"; 134 EXPECT_EQ(0U, error); 135 if (tcp == &remote_) { 136 have_disconnected_ = true; 137 } 138 } 139 virtual WriteResult TcpWritePacket(PseudoTcp* tcp, 140 const char* buffer, size_t len) { 141 // Randomly drop the desired percentage of packets. 142 // Also drop packets that are larger than the configured MTU. 143 if (rtc::CreateRandomId() % 100 < static_cast<uint32_t>(loss_)) { 144 LOG(LS_VERBOSE) << "Randomly dropping packet, size=" << len; 145 } else if (len > static_cast<size_t>(std::min(local_mtu_, remote_mtu_))) { 146 LOG(LS_VERBOSE) << "Dropping packet that exceeds path MTU, size=" << len; 147 } else { 148 int id = (tcp == &local_) ? MSG_RPACKET : MSG_LPACKET; 149 std::string packet(buffer, len); 150 rtc::Thread::Current()->PostDelayed(delay_, this, id, 151 rtc::WrapMessageData(packet)); 152 } 153 return WR_SUCCESS; 154 } 155 156 void UpdateLocalClock() { UpdateClock(&local_, MSG_LCLOCK); } 157 void UpdateRemoteClock() { UpdateClock(&remote_, MSG_RCLOCK); } 158 void UpdateClock(PseudoTcp* tcp, uint32_t message) { 159 long interval = 0; // NOLINT 160 tcp->GetNextClock(PseudoTcp::Now(), interval); 161 interval = std::max<int>(interval, 0L); // sometimes interval is < 0 162 rtc::Thread::Current()->Clear(this, message); 163 rtc::Thread::Current()->PostDelayed(interval, this, message); 164 } 165 166 virtual void OnMessage(rtc::Message* message) { 167 switch (message->message_id) { 168 case MSG_LPACKET: { 169 const std::string& s( 170 rtc::UseMessageData<std::string>(message->pdata)); 171 local_.NotifyPacket(s.c_str(), s.size()); 172 UpdateLocalClock(); 173 break; 174 } 175 case MSG_RPACKET: { 176 const std::string& s( 177 rtc::UseMessageData<std::string>(message->pdata)); 178 remote_.NotifyPacket(s.c_str(), s.size()); 179 UpdateRemoteClock(); 180 break; 181 } 182 case MSG_LCLOCK: 183 local_.NotifyClock(PseudoTcp::Now()); 184 UpdateLocalClock(); 185 break; 186 case MSG_RCLOCK: 187 remote_.NotifyClock(PseudoTcp::Now()); 188 UpdateRemoteClock(); 189 break; 190 default: 191 break; 192 } 193 delete message->pdata; 194 } 195 196 PseudoTcpForTest local_; 197 PseudoTcpForTest remote_; 198 rtc::MemoryStream send_stream_; 199 rtc::MemoryStream recv_stream_; 200 bool have_connected_; 201 bool have_disconnected_; 202 int local_mtu_; 203 int remote_mtu_; 204 int delay_; 205 int loss_; 206 }; 207 208 class PseudoTcpTest : public PseudoTcpTestBase { 209 public: 210 void TestTransfer(int size) { 211 uint32_t start, elapsed; 212 size_t received; 213 // Create some dummy data to send. 214 send_stream_.ReserveSize(size); 215 for (int i = 0; i < size; ++i) { 216 char ch = static_cast<char>(i); 217 send_stream_.Write(&ch, 1, NULL, NULL); 218 } 219 send_stream_.Rewind(); 220 // Prepare the receive stream. 221 recv_stream_.ReserveSize(size); 222 // Connect and wait until connected. 223 start = rtc::Time(); 224 EXPECT_EQ(0, Connect()); 225 EXPECT_TRUE_WAIT(have_connected_, kConnectTimeoutMs); 226 // Sending will start from OnTcpWriteable and complete when all data has 227 // been received. 228 EXPECT_TRUE_WAIT(have_disconnected_, kTransferTimeoutMs); 229 elapsed = rtc::TimeSince(start); 230 recv_stream_.GetSize(&received); 231 // Ensure we closed down OK and we got the right data. 232 // TODO: Ensure the errors are cleared properly. 233 //EXPECT_EQ(0, local_.GetError()); 234 //EXPECT_EQ(0, remote_.GetError()); 235 EXPECT_EQ(static_cast<size_t>(size), received); 236 EXPECT_EQ(0, memcmp(send_stream_.GetBuffer(), 237 recv_stream_.GetBuffer(), size)); 238 LOG(LS_INFO) << "Transferred " << received << " bytes in " << elapsed 239 << " ms (" << size * 8 / elapsed << " Kbps)"; 240 } 241 242 private: 243 // IPseudoTcpNotify interface 244 245 virtual void OnTcpReadable(PseudoTcp* tcp) { 246 // Stream bytes to the recv stream as they arrive. 247 if (tcp == &remote_) { 248 ReadData(); 249 250 // TODO: OnTcpClosed() is currently only notified on error - 251 // there is no on-the-wire equivalent of TCP FIN. 252 // So we fake the notification when all the data has been read. 253 size_t received, required; 254 recv_stream_.GetPosition(&received); 255 send_stream_.GetSize(&required); 256 if (received == required) 257 OnTcpClosed(&remote_, 0); 258 } 259 } 260 virtual void OnTcpWriteable(PseudoTcp* tcp) { 261 // Write bytes from the send stream when we can. 262 // Shut down when we've sent everything. 263 if (tcp == &local_) { 264 LOG(LS_VERBOSE) << "Flow Control Lifted"; 265 bool done; 266 WriteData(&done); 267 if (done) { 268 Close(); 269 } 270 } 271 } 272 273 void ReadData() { 274 char block[kBlockSize]; 275 size_t position; 276 int rcvd; 277 do { 278 rcvd = remote_.Recv(block, sizeof(block)); 279 if (rcvd != -1) { 280 recv_stream_.Write(block, rcvd, NULL, NULL); 281 recv_stream_.GetPosition(&position); 282 LOG(LS_VERBOSE) << "Received: " << position; 283 } 284 } while (rcvd > 0); 285 } 286 void WriteData(bool* done) { 287 size_t position, tosend; 288 int sent; 289 char block[kBlockSize]; 290 do { 291 send_stream_.GetPosition(&position); 292 if (send_stream_.Read(block, sizeof(block), &tosend, NULL) != 293 rtc::SR_EOS) { 294 sent = local_.Send(block, tosend); 295 UpdateLocalClock(); 296 if (sent != -1) { 297 send_stream_.SetPosition(position + sent); 298 LOG(LS_VERBOSE) << "Sent: " << position + sent; 299 } else { 300 send_stream_.SetPosition(position); 301 LOG(LS_VERBOSE) << "Flow Controlled"; 302 } 303 } else { 304 sent = static_cast<int>(tosend = 0); 305 } 306 } while (sent > 0); 307 *done = (tosend == 0); 308 } 309 310 private: 311 rtc::MemoryStream send_stream_; 312 rtc::MemoryStream recv_stream_; 313 }; 314 315 316 class PseudoTcpTestPingPong : public PseudoTcpTestBase { 317 public: 318 PseudoTcpTestPingPong() 319 : iterations_remaining_(0), 320 sender_(NULL), 321 receiver_(NULL), 322 bytes_per_send_(0) { 323 } 324 void SetBytesPerSend(int bytes) { 325 bytes_per_send_ = bytes; 326 } 327 void TestPingPong(int size, int iterations) { 328 uint32_t start, elapsed; 329 iterations_remaining_ = iterations; 330 receiver_ = &remote_; 331 sender_ = &local_; 332 // Create some dummy data to send. 333 send_stream_.ReserveSize(size); 334 for (int i = 0; i < size; ++i) { 335 char ch = static_cast<char>(i); 336 send_stream_.Write(&ch, 1, NULL, NULL); 337 } 338 send_stream_.Rewind(); 339 // Prepare the receive stream. 340 recv_stream_.ReserveSize(size); 341 // Connect and wait until connected. 342 start = rtc::Time(); 343 EXPECT_EQ(0, Connect()); 344 EXPECT_TRUE_WAIT(have_connected_, kConnectTimeoutMs); 345 // Sending will start from OnTcpWriteable and stop when the required 346 // number of iterations have completed. 347 EXPECT_TRUE_WAIT(have_disconnected_, kTransferTimeoutMs); 348 elapsed = rtc::TimeSince(start); 349 LOG(LS_INFO) << "Performed " << iterations << " pings in " 350 << elapsed << " ms"; 351 } 352 353 private: 354 // IPseudoTcpNotify interface 355 356 virtual void OnTcpReadable(PseudoTcp* tcp) { 357 if (tcp != receiver_) { 358 LOG_F(LS_ERROR) << "unexpected OnTcpReadable"; 359 return; 360 } 361 // Stream bytes to the recv stream as they arrive. 362 ReadData(); 363 // If we've received the desired amount of data, rewind things 364 // and send it back the other way! 365 size_t position, desired; 366 recv_stream_.GetPosition(&position); 367 send_stream_.GetSize(&desired); 368 if (position == desired) { 369 if (receiver_ == &local_ && --iterations_remaining_ == 0) { 370 Close(); 371 // TODO: Fake OnTcpClosed() on the receiver for now. 372 OnTcpClosed(&remote_, 0); 373 return; 374 } 375 PseudoTcp* tmp = receiver_; 376 receiver_ = sender_; 377 sender_ = tmp; 378 recv_stream_.Rewind(); 379 send_stream_.Rewind(); 380 OnTcpWriteable(sender_); 381 } 382 } 383 virtual void OnTcpWriteable(PseudoTcp* tcp) { 384 if (tcp != sender_) 385 return; 386 // Write bytes from the send stream when we can. 387 // Shut down when we've sent everything. 388 LOG(LS_VERBOSE) << "Flow Control Lifted"; 389 WriteData(); 390 } 391 392 void ReadData() { 393 char block[kBlockSize]; 394 size_t position; 395 int rcvd; 396 do { 397 rcvd = receiver_->Recv(block, sizeof(block)); 398 if (rcvd != -1) { 399 recv_stream_.Write(block, rcvd, NULL, NULL); 400 recv_stream_.GetPosition(&position); 401 LOG(LS_VERBOSE) << "Received: " << position; 402 } 403 } while (rcvd > 0); 404 } 405 void WriteData() { 406 size_t position, tosend; 407 int sent; 408 char block[kBlockSize]; 409 do { 410 send_stream_.GetPosition(&position); 411 tosend = bytes_per_send_ ? bytes_per_send_ : sizeof(block); 412 if (send_stream_.Read(block, tosend, &tosend, NULL) != 413 rtc::SR_EOS) { 414 sent = sender_->Send(block, tosend); 415 UpdateLocalClock(); 416 if (sent != -1) { 417 send_stream_.SetPosition(position + sent); 418 LOG(LS_VERBOSE) << "Sent: " << position + sent; 419 } else { 420 send_stream_.SetPosition(position); 421 LOG(LS_VERBOSE) << "Flow Controlled"; 422 } 423 } else { 424 sent = static_cast<int>(tosend = 0); 425 } 426 } while (sent > 0); 427 } 428 429 private: 430 int iterations_remaining_; 431 PseudoTcp* sender_; 432 PseudoTcp* receiver_; 433 int bytes_per_send_; 434 }; 435 436 // Fill the receiver window until it is full, drain it and then 437 // fill it with the same amount. This is to test that receiver window 438 // contracts and enlarges correctly. 439 class PseudoTcpTestReceiveWindow : public PseudoTcpTestBase { 440 public: 441 // Not all the data are transfered, |size| just need to be big enough 442 // to fill up the receiver window twice. 443 void TestTransfer(int size) { 444 // Create some dummy data to send. 445 send_stream_.ReserveSize(size); 446 for (int i = 0; i < size; ++i) { 447 char ch = static_cast<char>(i); 448 send_stream_.Write(&ch, 1, NULL, NULL); 449 } 450 send_stream_.Rewind(); 451 452 // Prepare the receive stream. 453 recv_stream_.ReserveSize(size); 454 455 // Connect and wait until connected. 456 EXPECT_EQ(0, Connect()); 457 EXPECT_TRUE_WAIT(have_connected_, kConnectTimeoutMs); 458 459 rtc::Thread::Current()->Post(this, MSG_WRITE); 460 EXPECT_TRUE_WAIT(have_disconnected_, kTransferTimeoutMs); 461 462 ASSERT_EQ(2u, send_position_.size()); 463 ASSERT_EQ(2u, recv_position_.size()); 464 465 const size_t estimated_recv_window = EstimateReceiveWindowSize(); 466 467 // The difference in consecutive send positions should equal the 468 // receive window size or match very closely. This verifies that receive 469 // window is open after receiver drained all the data. 470 const size_t send_position_diff = send_position_[1] - send_position_[0]; 471 EXPECT_GE(1024u, estimated_recv_window - send_position_diff); 472 473 // Receiver drained the receive window twice. 474 EXPECT_EQ(2 * estimated_recv_window, recv_position_[1]); 475 } 476 477 virtual void OnMessage(rtc::Message* message) { 478 int message_id = message->message_id; 479 PseudoTcpTestBase::OnMessage(message); 480 481 switch (message_id) { 482 case MSG_WRITE: { 483 WriteData(); 484 break; 485 } 486 default: 487 break; 488 } 489 } 490 491 uint32_t EstimateReceiveWindowSize() const { 492 return static_cast<uint32_t>(recv_position_[0]); 493 } 494 495 uint32_t EstimateSendWindowSize() const { 496 return static_cast<uint32_t>(send_position_[0] - recv_position_[0]); 497 } 498 499 private: 500 // IPseudoTcpNotify interface 501 virtual void OnTcpReadable(PseudoTcp* tcp) { 502 } 503 504 virtual void OnTcpWriteable(PseudoTcp* tcp) { 505 } 506 507 void ReadUntilIOPending() { 508 char block[kBlockSize]; 509 size_t position; 510 int rcvd; 511 512 do { 513 rcvd = remote_.Recv(block, sizeof(block)); 514 if (rcvd != -1) { 515 recv_stream_.Write(block, rcvd, NULL, NULL); 516 recv_stream_.GetPosition(&position); 517 LOG(LS_VERBOSE) << "Received: " << position; 518 } 519 } while (rcvd > 0); 520 521 recv_stream_.GetPosition(&position); 522 recv_position_.push_back(position); 523 524 // Disconnect if we have done two transfers. 525 if (recv_position_.size() == 2u) { 526 Close(); 527 OnTcpClosed(&remote_, 0); 528 } else { 529 WriteData(); 530 } 531 } 532 533 void WriteData() { 534 size_t position, tosend; 535 int sent; 536 char block[kBlockSize]; 537 do { 538 send_stream_.GetPosition(&position); 539 if (send_stream_.Read(block, sizeof(block), &tosend, NULL) != 540 rtc::SR_EOS) { 541 sent = local_.Send(block, tosend); 542 UpdateLocalClock(); 543 if (sent != -1) { 544 send_stream_.SetPosition(position + sent); 545 LOG(LS_VERBOSE) << "Sent: " << position + sent; 546 } else { 547 send_stream_.SetPosition(position); 548 LOG(LS_VERBOSE) << "Flow Controlled"; 549 } 550 } else { 551 sent = static_cast<int>(tosend = 0); 552 } 553 } while (sent > 0); 554 // At this point, we've filled up the available space in the send queue. 555 556 int message_queue_size = 557 static_cast<int>(rtc::Thread::Current()->size()); 558 // The message queue will always have at least 2 messages, an RCLOCK and 559 // an LCLOCK, since they are added back on the delay queue at the same time 560 // they are pulled off and therefore are never really removed. 561 if (message_queue_size > 2) { 562 // If there are non-clock messages remaining, attempt to continue sending 563 // after giving those messages time to process, which should free up the 564 // send buffer. 565 rtc::Thread::Current()->PostDelayed(10, this, MSG_WRITE); 566 } else { 567 if (!remote_.isReceiveBufferFull()) { 568 LOG(LS_ERROR) << "This shouldn't happen - the send buffer is full, " 569 << "the receive buffer is not, and there are no " 570 << "remaining messages to process."; 571 } 572 send_stream_.GetPosition(&position); 573 send_position_.push_back(position); 574 575 // Drain the receiver buffer. 576 ReadUntilIOPending(); 577 } 578 } 579 580 private: 581 rtc::MemoryStream send_stream_; 582 rtc::MemoryStream recv_stream_; 583 584 std::vector<size_t> send_position_; 585 std::vector<size_t> recv_position_; 586 }; 587 588 // Basic end-to-end data transfer tests 589 590 // Test the normal case of sending data from one side to the other. 591 TEST_F(PseudoTcpTest, TestSend) { 592 SetLocalMtu(1500); 593 SetRemoteMtu(1500); 594 TestTransfer(1000000); 595 } 596 597 // Test sending data with a 50 ms RTT. Transmission should take longer due 598 // to a slower ramp-up in send rate. 599 TEST_F(PseudoTcpTest, TestSendWithDelay) { 600 SetLocalMtu(1500); 601 SetRemoteMtu(1500); 602 SetDelay(50); 603 TestTransfer(1000000); 604 } 605 606 // Test sending data with packet loss. Transmission should take much longer due 607 // to send back-off when loss occurs. 608 TEST_F(PseudoTcpTest, TestSendWithLoss) { 609 SetLocalMtu(1500); 610 SetRemoteMtu(1500); 611 SetLoss(10); 612 TestTransfer(100000); // less data so test runs faster 613 } 614 615 // Test sending data with a 50 ms RTT and 10% packet loss. Transmission should 616 // take much longer due to send back-off and slower detection of loss. 617 TEST_F(PseudoTcpTest, TestSendWithDelayAndLoss) { 618 SetLocalMtu(1500); 619 SetRemoteMtu(1500); 620 SetDelay(50); 621 SetLoss(10); 622 TestTransfer(100000); // less data so test runs faster 623 } 624 625 // Test sending data with 10% packet loss and Nagling disabled. Transmission 626 // should take about the same time as with Nagling enabled. 627 TEST_F(PseudoTcpTest, TestSendWithLossAndOptNaglingOff) { 628 SetLocalMtu(1500); 629 SetRemoteMtu(1500); 630 SetLoss(10); 631 SetOptNagling(false); 632 TestTransfer(100000); // less data so test runs faster 633 } 634 635 // Test sending data with 10% packet loss and Delayed ACK disabled. 636 // Transmission should be slightly faster than with it enabled. 637 TEST_F(PseudoTcpTest, TestSendWithLossAndOptAckDelayOff) { 638 SetLocalMtu(1500); 639 SetRemoteMtu(1500); 640 SetLoss(10); 641 SetOptAckDelay(0); 642 TestTransfer(100000); 643 } 644 645 // Test sending data with 50ms delay and Nagling disabled. 646 TEST_F(PseudoTcpTest, TestSendWithDelayAndOptNaglingOff) { 647 SetLocalMtu(1500); 648 SetRemoteMtu(1500); 649 SetDelay(50); 650 SetOptNagling(false); 651 TestTransfer(100000); // less data so test runs faster 652 } 653 654 // Test sending data with 50ms delay and Delayed ACK disabled. 655 TEST_F(PseudoTcpTest, TestSendWithDelayAndOptAckDelayOff) { 656 SetLocalMtu(1500); 657 SetRemoteMtu(1500); 658 SetDelay(50); 659 SetOptAckDelay(0); 660 TestTransfer(100000); // less data so test runs faster 661 } 662 663 // Test a large receive buffer with a sender that doesn't support scaling. 664 TEST_F(PseudoTcpTest, TestSendRemoteNoWindowScale) { 665 SetLocalMtu(1500); 666 SetRemoteMtu(1500); 667 SetLocalOptRcvBuf(100000); 668 DisableRemoteWindowScale(); 669 TestTransfer(1000000); 670 } 671 672 // Test a large sender-side receive buffer with a receiver that doesn't support 673 // scaling. 674 TEST_F(PseudoTcpTest, TestSendLocalNoWindowScale) { 675 SetLocalMtu(1500); 676 SetRemoteMtu(1500); 677 SetRemoteOptRcvBuf(100000); 678 DisableLocalWindowScale(); 679 TestTransfer(1000000); 680 } 681 682 // Test when both sides use window scaling. 683 TEST_F(PseudoTcpTest, TestSendBothUseWindowScale) { 684 SetLocalMtu(1500); 685 SetRemoteMtu(1500); 686 SetRemoteOptRcvBuf(100000); 687 SetLocalOptRcvBuf(100000); 688 TestTransfer(1000000); 689 } 690 691 // Test using a large window scale value. 692 TEST_F(PseudoTcpTest, TestSendLargeInFlight) { 693 SetLocalMtu(1500); 694 SetRemoteMtu(1500); 695 SetRemoteOptRcvBuf(100000); 696 SetLocalOptRcvBuf(100000); 697 SetOptSndBuf(150000); 698 TestTransfer(1000000); 699 } 700 701 TEST_F(PseudoTcpTest, TestSendBothUseLargeWindowScale) { 702 SetLocalMtu(1500); 703 SetRemoteMtu(1500); 704 SetRemoteOptRcvBuf(1000000); 705 SetLocalOptRcvBuf(1000000); 706 TestTransfer(10000000); 707 } 708 709 // Test using a small receive buffer. 710 TEST_F(PseudoTcpTest, TestSendSmallReceiveBuffer) { 711 SetLocalMtu(1500); 712 SetRemoteMtu(1500); 713 SetRemoteOptRcvBuf(10000); 714 SetLocalOptRcvBuf(10000); 715 TestTransfer(1000000); 716 } 717 718 // Test using a very small receive buffer. 719 TEST_F(PseudoTcpTest, TestSendVerySmallReceiveBuffer) { 720 SetLocalMtu(1500); 721 SetRemoteMtu(1500); 722 SetRemoteOptRcvBuf(100); 723 SetLocalOptRcvBuf(100); 724 TestTransfer(100000); 725 } 726 727 // Ping-pong (request/response) tests 728 729 // Test sending <= 1x MTU of data in each ping/pong. Should take <10ms. 730 TEST_F(PseudoTcpTestPingPong, TestPingPong1xMtu) { 731 SetLocalMtu(1500); 732 SetRemoteMtu(1500); 733 TestPingPong(100, 100); 734 } 735 736 // Test sending 2x-3x MTU of data in each ping/pong. Should take <10ms. 737 TEST_F(PseudoTcpTestPingPong, TestPingPong3xMtu) { 738 SetLocalMtu(1500); 739 SetRemoteMtu(1500); 740 TestPingPong(400, 100); 741 } 742 743 // Test sending 1x-2x MTU of data in each ping/pong. 744 // Should take ~1s, due to interaction between Nagling and Delayed ACK. 745 TEST_F(PseudoTcpTestPingPong, TestPingPong2xMtu) { 746 SetLocalMtu(1500); 747 SetRemoteMtu(1500); 748 TestPingPong(2000, 5); 749 } 750 751 // Test sending 1x-2x MTU of data in each ping/pong with Delayed ACK off. 752 // Should take <10ms. 753 TEST_F(PseudoTcpTestPingPong, TestPingPong2xMtuWithAckDelayOff) { 754 SetLocalMtu(1500); 755 SetRemoteMtu(1500); 756 SetOptAckDelay(0); 757 TestPingPong(2000, 100); 758 } 759 760 // Test sending 1x-2x MTU of data in each ping/pong with Nagling off. 761 // Should take <10ms. 762 TEST_F(PseudoTcpTestPingPong, TestPingPong2xMtuWithNaglingOff) { 763 SetLocalMtu(1500); 764 SetRemoteMtu(1500); 765 SetOptNagling(false); 766 TestPingPong(2000, 5); 767 } 768 769 // Test sending a ping as pair of short (non-full) segments. 770 // Should take ~1s, due to Delayed ACK interaction with Nagling. 771 TEST_F(PseudoTcpTestPingPong, TestPingPongShortSegments) { 772 SetLocalMtu(1500); 773 SetRemoteMtu(1500); 774 SetOptAckDelay(5000); 775 SetBytesPerSend(50); // i.e. two Send calls per payload 776 TestPingPong(100, 5); 777 } 778 779 // Test sending ping as a pair of short (non-full) segments, with Nagling off. 780 // Should take <10ms. 781 TEST_F(PseudoTcpTestPingPong, TestPingPongShortSegmentsWithNaglingOff) { 782 SetLocalMtu(1500); 783 SetRemoteMtu(1500); 784 SetOptNagling(false); 785 SetBytesPerSend(50); // i.e. two Send calls per payload 786 TestPingPong(100, 5); 787 } 788 789 // Test sending <= 1x MTU of data ping/pong, in two segments, no Delayed ACK. 790 // Should take ~1s. 791 TEST_F(PseudoTcpTestPingPong, TestPingPongShortSegmentsWithAckDelayOff) { 792 SetLocalMtu(1500); 793 SetRemoteMtu(1500); 794 SetBytesPerSend(50); // i.e. two Send calls per payload 795 SetOptAckDelay(0); 796 TestPingPong(100, 5); 797 } 798 799 // Test that receive window expands and contract correctly. 800 TEST_F(PseudoTcpTestReceiveWindow, TestReceiveWindow) { 801 SetLocalMtu(1500); 802 SetRemoteMtu(1500); 803 SetOptNagling(false); 804 SetOptAckDelay(0); 805 TestTransfer(1024 * 1000); 806 } 807 808 // Test setting send window size to a very small value. 809 TEST_F(PseudoTcpTestReceiveWindow, TestSetVerySmallSendWindowSize) { 810 SetLocalMtu(1500); 811 SetRemoteMtu(1500); 812 SetOptNagling(false); 813 SetOptAckDelay(0); 814 SetOptSndBuf(900); 815 TestTransfer(1024 * 1000); 816 EXPECT_EQ(900u, EstimateSendWindowSize()); 817 } 818 819 // Test setting receive window size to a value other than default. 820 TEST_F(PseudoTcpTestReceiveWindow, TestSetReceiveWindowSize) { 821 SetLocalMtu(1500); 822 SetRemoteMtu(1500); 823 SetOptNagling(false); 824 SetOptAckDelay(0); 825 SetRemoteOptRcvBuf(100000); 826 SetLocalOptRcvBuf(100000); 827 TestTransfer(1024 * 1000); 828 EXPECT_EQ(100000u, EstimateReceiveWindowSize()); 829 } 830 831 /* Test sending data with mismatched MTUs. We should detect this and reduce 832 // our packet size accordingly. 833 // TODO: This doesn't actually work right now. The current code 834 // doesn't detect if the MTU is set too high on either side. 835 TEST_F(PseudoTcpTest, TestSendWithMismatchedMtus) { 836 SetLocalMtu(1500); 837 SetRemoteMtu(1280); 838 TestTransfer(1000000); 839 } 840 */ 841