github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/tcpip/transport/tcp/tcp_rack_test.go (about) 1 // Copyright 2020 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package tcp_test 16 17 import ( 18 "bytes" 19 "fmt" 20 "testing" 21 "time" 22 23 "github.com/SagerNet/gvisor/pkg/tcpip" 24 "github.com/SagerNet/gvisor/pkg/tcpip/header" 25 "github.com/SagerNet/gvisor/pkg/tcpip/seqnum" 26 "github.com/SagerNet/gvisor/pkg/tcpip/stack" 27 "github.com/SagerNet/gvisor/pkg/tcpip/transport/tcp/testing/context" 28 "github.com/SagerNet/gvisor/pkg/test/testutil" 29 ) 30 31 const ( 32 maxPayload = 10 33 tsOptionSize = 12 34 maxTCPOptionSize = 40 35 mtu = header.TCPMinimumSize + header.IPv4MinimumSize + maxTCPOptionSize + maxPayload 36 latency = 5 * time.Millisecond 37 ) 38 39 func setStackRACKPermitted(t *testing.T, c *context.Context) { 40 t.Helper() 41 opt := tcpip.TCPRACKLossDetection 42 if err := c.Stack().SetTransportProtocolOption(header.TCPProtocolNumber, &opt); err != nil { 43 t.Fatalf("c.s.SetTransportProtocolOption(%d, &%v(%v)): %s", header.TCPProtocolNumber, opt, opt, err) 44 } 45 } 46 47 // TestRACKUpdate tests the RACK related fields are updated when an ACK is 48 // received on a SACK enabled connection. 49 func TestRACKUpdate(t *testing.T) { 50 c := context.New(t, uint32(mtu)) 51 defer c.Cleanup() 52 53 var xmitTime tcpip.MonotonicTime 54 probeDone := make(chan struct{}) 55 c.Stack().AddTCPProbe(func(state stack.TCPEndpointState) { 56 // Validate that the endpoint Sender.RACKState is what we expect. 57 if state.Sender.RACKState.XmitTime.Before(xmitTime) { 58 t.Fatalf("RACK transmit time failed to update when an ACK is received") 59 } 60 61 gotSeq := state.Sender.RACKState.EndSequence 62 wantSeq := state.Sender.SndNxt 63 if !gotSeq.LessThanEq(wantSeq) || gotSeq.LessThan(wantSeq) { 64 t.Fatalf("RACK sequence number failed to update, got: %v, but want: %v", gotSeq, wantSeq) 65 } 66 67 if state.Sender.RACKState.RTT == 0 { 68 t.Fatalf("RACK RTT failed to update when an ACK is received, got RACKState.RTT == 0 want != 0") 69 } 70 close(probeDone) 71 }) 72 setStackSACKPermitted(t, c, true) 73 setStackRACKPermitted(t, c) 74 createConnectedWithSACKAndTS(c) 75 76 data := make([]byte, maxPayload) 77 for i := range data { 78 data[i] = byte(i) 79 } 80 81 // Write the data. 82 xmitTime = c.Stack().Clock().NowMonotonic() 83 var r bytes.Reader 84 r.Reset(data) 85 if _, err := c.EP.Write(&r, tcpip.WriteOptions{}); err != nil { 86 t.Fatalf("Write failed: %s", err) 87 } 88 89 bytesRead := 0 90 c.ReceiveAndCheckPacketWithOptions(data, bytesRead, maxPayload, tsOptionSize) 91 bytesRead += maxPayload 92 c.SendAck(seqnum.Value(context.TestInitialSequenceNumber).Add(1), bytesRead) 93 94 // Wait for the probe function to finish processing the ACK before the 95 // test completes. 96 <-probeDone 97 } 98 99 // TestRACKDetectReorder tests that RACK detects packet reordering. 100 func TestRACKDetectReorder(t *testing.T) { 101 c := context.New(t, uint32(mtu)) 102 defer c.Cleanup() 103 104 t.Skipf("Skipping this test as reorder detection does not consider DSACK.") 105 106 var n int 107 const ackNumToVerify = 2 108 probeDone := make(chan struct{}) 109 c.Stack().AddTCPProbe(func(state stack.TCPEndpointState) { 110 gotSeq := state.Sender.RACKState.FACK 111 wantSeq := state.Sender.SndNxt 112 // FACK should be updated to the highest ending sequence number of the 113 // segment acknowledged most recently. 114 if !gotSeq.LessThanEq(wantSeq) || gotSeq.LessThan(wantSeq) { 115 t.Fatalf("RACK FACK failed to update, got: %v, but want: %v", gotSeq, wantSeq) 116 } 117 118 n++ 119 if n < ackNumToVerify { 120 if state.Sender.RACKState.Reord { 121 t.Fatalf("RACK reorder detected when there is no reordering") 122 } 123 return 124 } 125 126 if state.Sender.RACKState.Reord == false { 127 t.Fatalf("RACK reorder detection failed") 128 } 129 close(probeDone) 130 }) 131 setStackSACKPermitted(t, c, true) 132 setStackRACKPermitted(t, c) 133 createConnectedWithSACKAndTS(c) 134 data := make([]byte, ackNumToVerify*maxPayload) 135 for i := range data { 136 data[i] = byte(i) 137 } 138 139 // Write the data. 140 var r bytes.Reader 141 r.Reset(data) 142 if _, err := c.EP.Write(&r, tcpip.WriteOptions{}); err != nil { 143 t.Fatalf("Write failed: %s", err) 144 } 145 146 bytesRead := 0 147 for i := 0; i < ackNumToVerify; i++ { 148 c.ReceiveAndCheckPacketWithOptions(data, bytesRead, maxPayload, tsOptionSize) 149 bytesRead += maxPayload 150 } 151 152 start := c.IRS.Add(maxPayload + 1) 153 end := start.Add(maxPayload) 154 seq := seqnum.Value(context.TestInitialSequenceNumber).Add(1) 155 c.SendAckWithSACK(seq, 0, []header.SACKBlock{{start, end}}) 156 c.SendAck(seq, bytesRead) 157 158 // Wait for the probe function to finish processing the ACK before the 159 // test completes. 160 <-probeDone 161 } 162 163 func sendAndReceiveWithSACK(t *testing.T, c *context.Context, numPackets int, enableRACK bool) []byte { 164 setStackSACKPermitted(t, c, true) 165 if enableRACK { 166 setStackRACKPermitted(t, c) 167 } 168 createConnectedWithSACKAndTS(c) 169 170 data := make([]byte, numPackets*maxPayload) 171 for i := range data { 172 data[i] = byte(i) 173 } 174 175 // Write the data. 176 var r bytes.Reader 177 r.Reset(data) 178 if _, err := c.EP.Write(&r, tcpip.WriteOptions{}); err != nil { 179 t.Fatalf("Write failed: %s", err) 180 } 181 182 bytesRead := 0 183 for i := 0; i < numPackets; i++ { 184 c.ReceiveAndCheckPacketWithOptions(data, bytesRead, maxPayload, tsOptionSize) 185 bytesRead += maxPayload 186 // This delay is added to increase RTT as low RTT can cause TLP 187 // before sending ACK. 188 time.Sleep(latency) 189 } 190 191 return data 192 } 193 194 const ( 195 validDSACKDetected = 1 196 failedToDetectDSACK = 2 197 invalidDSACKDetected = 3 198 ) 199 200 func addDSACKSeenCheckerProbe(t *testing.T, c *context.Context, numACK int, probeDone chan int) { 201 var n int 202 c.Stack().AddTCPProbe(func(state stack.TCPEndpointState) { 203 // Validate that RACK detects DSACK. 204 n++ 205 if n < numACK { 206 if state.Sender.RACKState.DSACKSeen { 207 probeDone <- invalidDSACKDetected 208 } 209 return 210 } 211 212 if !state.Sender.RACKState.DSACKSeen { 213 probeDone <- failedToDetectDSACK 214 return 215 } 216 probeDone <- validDSACKDetected 217 }) 218 } 219 220 // TestRACKTLPRecovery tests that RACK sends a tail loss probe (TLP) in the 221 // case of a tail loss. This simulates a situation where the TLP is able to 222 // insinuate the SACK holes and sender is able to retransmit the rest. 223 func TestRACKTLPRecovery(t *testing.T) { 224 c := context.New(t, uint32(mtu)) 225 defer c.Cleanup() 226 227 // Send 8 packets. 228 numPackets := 8 229 data := sendAndReceiveWithSACK(t, c, numPackets, true /* enableRACK */) 230 231 // Packets [6-8] are lost. Send cumulative ACK for [1-5]. 232 seq := seqnum.Value(context.TestInitialSequenceNumber).Add(1) 233 bytesRead := 5 * maxPayload 234 c.SendAck(seq, bytesRead) 235 236 // PTO should fire and send #8 packet as a TLP. 237 c.ReceiveAndCheckPacketWithOptions(data, 7*maxPayload, maxPayload, tsOptionSize) 238 var info tcpip.TCPInfoOption 239 if err := c.EP.GetSockOpt(&info); err != nil { 240 t.Fatalf("GetSockOpt failed: %v", err) 241 } 242 243 // Send the SACK after RTT because RACK RFC states that if the ACK for a 244 // retransmission arrives before the smoothed RTT then the sender should not 245 // update RACK state as it could be a spurious inference. 246 time.Sleep(info.RTT) 247 248 // Okay, let the sender know we got #8 using a SACK block. 249 eighthPStart := c.IRS.Add(1 + seqnum.Size(7*maxPayload)) 250 eighthPEnd := eighthPStart.Add(maxPayload) 251 c.SendAckWithSACK(seq, bytesRead, []header.SACKBlock{{eighthPStart, eighthPEnd}}) 252 253 // The sender should be entering RACK based loss-recovery and sending #6 and 254 // #7 one after another. 255 c.ReceiveAndCheckPacketWithOptions(data, bytesRead, maxPayload, tsOptionSize) 256 bytesRead += maxPayload 257 c.ReceiveAndCheckPacketWithOptions(data, bytesRead, maxPayload, tsOptionSize) 258 bytesRead += 2 * maxPayload 259 c.SendAck(seq, bytesRead) 260 261 metricPollFn := func() error { 262 tcpStats := c.Stack().Stats().TCP 263 stats := []struct { 264 stat *tcpip.StatCounter 265 name string 266 want uint64 267 }{ 268 // One fast retransmit after the SACK. 269 {tcpStats.FastRetransmit, "stats.TCP.FastRetransmit", 1}, 270 // Recovery should be SACK recovery. 271 {tcpStats.SACKRecovery, "stats.TCP.SACKRecovery", 1}, 272 // Packets 6, 7 and 8 were retransmitted. 273 {tcpStats.Retransmits, "stats.TCP.Retransmits", 3}, 274 // TLP recovery should have been detected. 275 {tcpStats.TLPRecovery, "stats.TCP.TLPRecovery", 1}, 276 // No RTOs should have occurred. 277 {tcpStats.Timeouts, "stats.TCP.Timeouts", 0}, 278 } 279 for _, s := range stats { 280 if got, want := s.stat.Value(), s.want; got != want { 281 return fmt.Errorf("got %s.Value() = %d, want = %d", s.name, got, want) 282 } 283 } 284 return nil 285 } 286 if err := testutil.Poll(metricPollFn, 1*time.Second); err != nil { 287 t.Error(err) 288 } 289 } 290 291 // TestRACKTLPFallbackRTO tests that RACK sends a tail loss probe (TLP) in the 292 // case of a tail loss. This simulates a situation where either the TLP or its 293 // ACK is lost. The sender should retransmit when RTO fires. 294 func TestRACKTLPFallbackRTO(t *testing.T) { 295 c := context.New(t, uint32(mtu)) 296 defer c.Cleanup() 297 298 // Send 8 packets. 299 numPackets := 8 300 data := sendAndReceiveWithSACK(t, c, numPackets, true /* enableRACK */) 301 302 // Packets [6-8] are lost. Send cumulative ACK for [1-5]. 303 seq := seqnum.Value(context.TestInitialSequenceNumber).Add(1) 304 bytesRead := 5 * maxPayload 305 c.SendAck(seq, bytesRead) 306 307 // PTO should fire and send #8 packet as a TLP. 308 c.ReceiveAndCheckPacketWithOptions(data, 7*maxPayload, maxPayload, tsOptionSize) 309 310 // Either the TLP or the ACK the receiver sent with SACK blocks was lost. 311 312 // Confirm that RTO fires and retransmits packet #6. 313 c.ReceiveAndCheckPacketWithOptions(data, bytesRead, maxPayload, tsOptionSize) 314 315 metricPollFn := func() error { 316 tcpStats := c.Stack().Stats().TCP 317 stats := []struct { 318 stat *tcpip.StatCounter 319 name string 320 want uint64 321 }{ 322 // No fast retransmits happened. 323 {tcpStats.FastRetransmit, "stats.TCP.FastRetransmit", 0}, 324 // No SACK recovery happened. 325 {tcpStats.SACKRecovery, "stats.TCP.SACKRecovery", 0}, 326 // TLP was unsuccessful. 327 {tcpStats.TLPRecovery, "stats.TCP.TLPRecovery", 0}, 328 // RTO should have fired. 329 {tcpStats.Timeouts, "stats.TCP.Timeouts", 1}, 330 } 331 for _, s := range stats { 332 if got, want := s.stat.Value(), s.want; got != want { 333 return fmt.Errorf("got %s.Value() = %d, want = %d", s.name, got, want) 334 } 335 } 336 return nil 337 } 338 if err := testutil.Poll(metricPollFn, 1*time.Second); err != nil { 339 t.Error(err) 340 } 341 } 342 343 // TestNoTLPRecoveryOnDSACK tests the scenario where the sender speculates a 344 // tail loss and sends a TLP. Everything is received and acked. The probe 345 // segment is DSACKed. No fast recovery should be triggered in this case. 346 func TestNoTLPRecoveryOnDSACK(t *testing.T) { 347 c := context.New(t, uint32(mtu)) 348 defer c.Cleanup() 349 350 // Send 8 packets. 351 numPackets := 8 352 data := sendAndReceiveWithSACK(t, c, numPackets, true /* enableRACK */) 353 354 // Packets [1-5] are received first. [6-8] took a detour and will take a 355 // while to arrive. Ack [1-5]. 356 seq := seqnum.Value(context.TestInitialSequenceNumber).Add(1) 357 bytesRead := 5 * maxPayload 358 c.SendAck(seq, bytesRead) 359 360 // The tail loss probe (#8 packet) is received. 361 c.ReceiveAndCheckPacketWithOptions(data, 7*maxPayload, maxPayload, tsOptionSize) 362 363 // Now that all 8 packets are received + duplicate 8th packet, send ack. 364 bytesRead += 3 * maxPayload 365 eighthPStart := c.IRS.Add(1 + seqnum.Size(7*maxPayload)) 366 eighthPEnd := eighthPStart.Add(maxPayload) 367 c.SendAckWithSACK(seq, bytesRead, []header.SACKBlock{{eighthPStart, eighthPEnd}}) 368 369 // Wait for RTO and make sure that nothing else is received. 370 var info tcpip.TCPInfoOption 371 if err := c.EP.GetSockOpt(&info); err != nil { 372 t.Fatalf("GetSockOpt failed: %v", err) 373 } 374 if p := c.GetPacketWithTimeout(info.RTO); p != nil { 375 t.Errorf("received an unexpected packet: %v", p) 376 } 377 378 metricPollFn := func() error { 379 tcpStats := c.Stack().Stats().TCP 380 stats := []struct { 381 stat *tcpip.StatCounter 382 name string 383 want uint64 384 }{ 385 // Make sure no recovery was entered. 386 {tcpStats.FastRetransmit, "stats.TCP.FastRetransmit", 0}, 387 {tcpStats.SACKRecovery, "stats.TCP.SACKRecovery", 0}, 388 {tcpStats.TLPRecovery, "stats.TCP.TLPRecovery", 0}, 389 // RTO should not have fired. 390 {tcpStats.Timeouts, "stats.TCP.Timeouts", 0}, 391 // Only #8 was retransmitted. 392 {tcpStats.Retransmits, "stats.TCP.Retransmits", 1}, 393 } 394 for _, s := range stats { 395 if got, want := s.stat.Value(), s.want; got != want { 396 return fmt.Errorf("got %s.Value() = %d, want = %d", s.name, got, want) 397 } 398 } 399 return nil 400 } 401 if err := testutil.Poll(metricPollFn, 1*time.Second); err != nil { 402 t.Error(err) 403 } 404 } 405 406 // TestNoTLPOnSACK tests the scenario where there is not exactly a tail loss 407 // due to the presence of multiple SACK holes. In such a scenario, TLP should 408 // not be sent. 409 func TestNoTLPOnSACK(t *testing.T) { 410 c := context.New(t, uint32(mtu)) 411 defer c.Cleanup() 412 413 // Send 8 packets. 414 numPackets := 8 415 data := sendAndReceiveWithSACK(t, c, numPackets, true /* enableRACK */) 416 417 // Packets [1-5] and #7 were received. #6 and #8 were dropped. 418 seq := seqnum.Value(context.TestInitialSequenceNumber).Add(1) 419 bytesRead := 5 * maxPayload 420 seventhStart := c.IRS.Add(1 + seqnum.Size(6*maxPayload)) 421 seventhEnd := seventhStart.Add(maxPayload) 422 c.SendAckWithSACK(seq, bytesRead, []header.SACKBlock{{seventhStart, seventhEnd}}) 423 424 // The sender should retransmit #6. If the sender sends a TLP, then #8 will 425 // received and fail this test. 426 c.ReceiveAndCheckPacketWithOptions(data, 5*maxPayload, maxPayload, tsOptionSize) 427 428 metricPollFn := func() error { 429 tcpStats := c.Stack().Stats().TCP 430 stats := []struct { 431 stat *tcpip.StatCounter 432 name string 433 want uint64 434 }{ 435 // #6 was retransmitted due to SACK recovery. 436 {tcpStats.FastRetransmit, "stats.TCP.FastRetransmit", 1}, 437 {tcpStats.SACKRecovery, "stats.TCP.SACKRecovery", 1}, 438 {tcpStats.TLPRecovery, "stats.TCP.TLPRecovery", 0}, 439 // RTO should not have fired. 440 {tcpStats.Timeouts, "stats.TCP.Timeouts", 0}, 441 // Only #6 was retransmitted. 442 {tcpStats.Retransmits, "stats.TCP.Retransmits", 1}, 443 } 444 for _, s := range stats { 445 if got, want := s.stat.Value(), s.want; got != want { 446 return fmt.Errorf("got %s.Value() = %d, want = %d", s.name, got, want) 447 } 448 } 449 return nil 450 } 451 if err := testutil.Poll(metricPollFn, 1*time.Second); err != nil { 452 t.Error(err) 453 } 454 } 455 456 // TestRACKOnePacketTailLoss tests the trivial case of a tail loss of only one 457 // packet. The probe should itself repairs the loss instead of having to go 458 // into any recovery. 459 func TestRACKOnePacketTailLoss(t *testing.T) { 460 c := context.New(t, uint32(mtu)) 461 defer c.Cleanup() 462 463 // Send 3 packets. 464 numPackets := 3 465 data := sendAndReceiveWithSACK(t, c, numPackets, true /* enableRACK */) 466 467 // Packets [1-2] are received. #3 is lost. 468 seq := seqnum.Value(context.TestInitialSequenceNumber).Add(1) 469 bytesRead := 2 * maxPayload 470 c.SendAck(seq, bytesRead) 471 472 // PTO should fire and send #3 packet as a TLP. 473 c.ReceiveAndCheckPacketWithOptions(data, 2*maxPayload, maxPayload, tsOptionSize) 474 bytesRead += maxPayload 475 c.SendAck(seq, bytesRead) 476 477 metricPollFn := func() error { 478 tcpStats := c.Stack().Stats().TCP 479 stats := []struct { 480 stat *tcpip.StatCounter 481 name string 482 want uint64 483 }{ 484 // #3 was retransmitted as TLP. 485 {tcpStats.FastRetransmit, "stats.TCP.FastRetransmit", 0}, 486 {tcpStats.SACKRecovery, "stats.TCP.SACKRecovery", 1}, 487 {tcpStats.TLPRecovery, "stats.TCP.TLPRecovery", 0}, 488 // RTO should not have fired. 489 {tcpStats.Timeouts, "stats.TCP.Timeouts", 0}, 490 // Only #3 was retransmitted. 491 {tcpStats.Retransmits, "stats.TCP.Retransmits", 1}, 492 } 493 for _, s := range stats { 494 if got, want := s.stat.Value(), s.want; got != want { 495 return fmt.Errorf("got %s.Value() = %d, want = %d", s.name, got, want) 496 } 497 } 498 return nil 499 } 500 if err := testutil.Poll(metricPollFn, 1*time.Second); err != nil { 501 t.Error(err) 502 } 503 } 504 505 // TestRACKDetectDSACK tests that RACK detects DSACK with duplicate segments. 506 // See: https://tools.ietf.org/html/rfc2883#section-4.1.1. 507 func TestRACKDetectDSACK(t *testing.T) { 508 c := context.New(t, uint32(mtu)) 509 defer c.Cleanup() 510 511 probeDone := make(chan int) 512 const ackNumToVerify = 2 513 addDSACKSeenCheckerProbe(t, c, ackNumToVerify, probeDone) 514 515 numPackets := 8 516 data := sendAndReceiveWithSACK(t, c, numPackets, true /* enableRACK */) 517 518 // Cumulative ACK for [1-5] packets and SACK #8 packet (to prevent TLP). 519 seq := seqnum.Value(context.TestInitialSequenceNumber).Add(1) 520 bytesRead := 5 * maxPayload 521 eighthPStart := c.IRS.Add(1 + seqnum.Size(7*maxPayload)) 522 eighthPEnd := eighthPStart.Add(maxPayload) 523 c.SendAckWithSACK(seq, bytesRead, []header.SACKBlock{{eighthPStart, eighthPEnd}}) 524 525 // Expect retransmission of #6 packet after RTO expires. 526 c.ReceiveAndCheckPacketWithOptions(data, bytesRead, maxPayload, tsOptionSize) 527 528 // Send DSACK block for #6 packet indicating both 529 // initial and retransmitted packet are received and 530 // packets [1-8] are received. 531 start := c.IRS.Add(1 + seqnum.Size(bytesRead)) 532 end := start.Add(maxPayload) 533 bytesRead += 3 * maxPayload 534 c.SendAckWithSACK(seq, bytesRead, []header.SACKBlock{{start, end}}) 535 536 // Wait for the probe function to finish processing the 537 // ACK before the test completes. 538 err := <-probeDone 539 switch err { 540 case failedToDetectDSACK: 541 t.Fatalf("RACK DSACK detection failed") 542 case invalidDSACKDetected: 543 t.Fatalf("RACK DSACK detected when there is no duplicate SACK") 544 } 545 } 546 547 // TestRACKDetectDSACKWithOutOfOrder tests that RACK detects DSACK with out of 548 // order segments. 549 // See: https://tools.ietf.org/html/rfc2883#section-4.1.2. 550 func TestRACKDetectDSACKWithOutOfOrder(t *testing.T) { 551 c := context.New(t, uint32(mtu)) 552 defer c.Cleanup() 553 554 probeDone := make(chan int) 555 const ackNumToVerify = 2 556 addDSACKSeenCheckerProbe(t, c, ackNumToVerify, probeDone) 557 558 numPackets := 10 559 data := sendAndReceiveWithSACK(t, c, numPackets, true /* enableRACK */) 560 561 // Cumulative ACK for [1-5] packets and SACK for #7 packet (to prevent TLP). 562 seq := seqnum.Value(context.TestInitialSequenceNumber).Add(1) 563 bytesRead := 5 * maxPayload 564 seventhPStart := c.IRS.Add(1 + seqnum.Size(6*maxPayload)) 565 seventhPEnd := seventhPStart.Add(maxPayload) 566 c.SendAckWithSACK(seq, bytesRead, []header.SACKBlock{{seventhPStart, seventhPEnd}}) 567 568 // Expect retransmission of #6 packet. 569 c.ReceiveAndCheckPacketWithOptions(data, bytesRead, maxPayload, tsOptionSize) 570 571 // Send DSACK block for #6 packet indicating both 572 // initial and retransmitted packet are received and 573 // packets [1-7] are received. 574 start := c.IRS.Add(1 + seqnum.Size(bytesRead)) 575 end := start.Add(maxPayload) 576 bytesRead += 2 * maxPayload 577 // Send DSACK block for #6 along with SACK for out of 578 // order #9 packet. 579 start1 := c.IRS.Add(1 + seqnum.Size(bytesRead) + maxPayload) 580 end1 := start1.Add(maxPayload) 581 c.SendAckWithSACK(seq, bytesRead, []header.SACKBlock{{start, end}, {start1, end1}}) 582 583 // Wait for the probe function to finish processing the 584 // ACK before the test completes. 585 err := <-probeDone 586 switch err { 587 case failedToDetectDSACK: 588 t.Fatalf("RACK DSACK detection failed") 589 case invalidDSACKDetected: 590 t.Fatalf("RACK DSACK detected when there is no duplicate SACK") 591 } 592 } 593 594 // TestRACKDetectDSACKWithOutOfOrderDup tests that DSACK is detected on a 595 // duplicate of out of order packet. 596 // See: https://tools.ietf.org/html/rfc2883#section-4.1.3 597 func TestRACKDetectDSACKWithOutOfOrderDup(t *testing.T) { 598 c := context.New(t, uint32(mtu)) 599 defer c.Cleanup() 600 601 probeDone := make(chan int) 602 const ackNumToVerify = 4 603 addDSACKSeenCheckerProbe(t, c, ackNumToVerify, probeDone) 604 605 numPackets := 10 606 sendAndReceiveWithSACK(t, c, numPackets, true /* enableRACK */) 607 608 // ACK [1-5] packets. 609 seq := seqnum.Value(context.TestInitialSequenceNumber).Add(1) 610 bytesRead := 5 * maxPayload 611 c.SendAck(seq, bytesRead) 612 613 // Send SACK indicating #6 packet is missing and received #7 packet. 614 offset := seqnum.Size(bytesRead + maxPayload) 615 start := c.IRS.Add(1 + offset) 616 end := start.Add(maxPayload) 617 c.SendAckWithSACK(seq, bytesRead, []header.SACKBlock{{start, end}}) 618 619 // Send SACK with #6 packet is missing and received [7-8] packets. 620 end = start.Add(2 * maxPayload) 621 c.SendAckWithSACK(seq, bytesRead, []header.SACKBlock{{start, end}}) 622 623 // Consider #8 packet is duplicated on the network and send DSACK. 624 dsackStart := c.IRS.Add(1 + offset + maxPayload) 625 dsackEnd := dsackStart.Add(maxPayload) 626 c.SendAckWithSACK(seq, bytesRead, []header.SACKBlock{{dsackStart, dsackEnd}, {start, end}}) 627 628 // Wait for the probe function to finish processing the ACK before the 629 // test completes. 630 err := <-probeDone 631 switch err { 632 case failedToDetectDSACK: 633 t.Fatalf("RACK DSACK detection failed") 634 case invalidDSACKDetected: 635 t.Fatalf("RACK DSACK detected when there is no duplicate SACK") 636 } 637 } 638 639 // TestRACKDetectDSACKSingleDup tests DSACK for a single duplicate subsegment. 640 // See: https://tools.ietf.org/html/rfc2883#section-4.2.1. 641 func TestRACKDetectDSACKSingleDup(t *testing.T) { 642 c := context.New(t, uint32(mtu)) 643 defer c.Cleanup() 644 645 probeDone := make(chan int) 646 const ackNumToVerify = 4 647 addDSACKSeenCheckerProbe(t, c, ackNumToVerify, probeDone) 648 649 numPackets := 4 650 data := sendAndReceiveWithSACK(t, c, numPackets, true /* enableRACK */) 651 652 // Send ACK for #1 packet. 653 bytesRead := maxPayload 654 seq := seqnum.Value(context.TestInitialSequenceNumber).Add(1) 655 c.SendAck(seq, bytesRead) 656 657 // Missing [2-3] packets and received #4 packet. 658 seq = seqnum.Value(context.TestInitialSequenceNumber).Add(1) 659 start := c.IRS.Add(1 + seqnum.Size(3*maxPayload)) 660 end := start.Add(seqnum.Size(maxPayload)) 661 c.SendAckWithSACK(seq, bytesRead, []header.SACKBlock{{start, end}}) 662 663 // Expect retransmission of #2 packet. 664 c.ReceiveAndCheckPacketWithOptions(data, bytesRead, maxPayload, tsOptionSize) 665 666 // ACK for retransmitted #2 packet. 667 bytesRead += maxPayload 668 c.SendAckWithSACK(seq, bytesRead, []header.SACKBlock{{start, end}}) 669 670 // Simulate receving delayed subsegment of #2 packet and delayed #3 packet by 671 // sending DSACK block for the subsegment. 672 dsackStart := c.IRS.Add(1 + seqnum.Size(bytesRead)) 673 dsackEnd := dsackStart.Add(seqnum.Size(maxPayload / 2)) 674 c.SendAckWithSACK(seq, numPackets*maxPayload, []header.SACKBlock{{dsackStart, dsackEnd}}) 675 676 // Wait for the probe function to finish processing the ACK before the 677 // test completes. 678 err := <-probeDone 679 switch err { 680 case failedToDetectDSACK: 681 t.Fatalf("RACK DSACK detection failed") 682 case invalidDSACKDetected: 683 t.Fatalf("RACK DSACK detected when there is no duplicate SACK") 684 } 685 } 686 687 // TestRACKDetectDSACKDupWithCumulativeACK tests DSACK for two non-contiguous 688 // duplicate subsegments covered by the cumulative acknowledgement. 689 // See: https://tools.ietf.org/html/rfc2883#section-4.2.2. 690 func TestRACKDetectDSACKDupWithCumulativeACK(t *testing.T) { 691 c := context.New(t, uint32(mtu)) 692 defer c.Cleanup() 693 694 probeDone := make(chan int) 695 const ackNumToVerify = 5 696 addDSACKSeenCheckerProbe(t, c, ackNumToVerify, probeDone) 697 698 numPackets := 6 699 data := sendAndReceiveWithSACK(t, c, numPackets, true /* enableRACK */) 700 701 // Send ACK for #1 packet. 702 bytesRead := maxPayload 703 seq := seqnum.Value(context.TestInitialSequenceNumber).Add(1) 704 c.SendAck(seq, bytesRead) 705 706 // Missing [2-5] packets and received #6 packet. 707 seq = seqnum.Value(context.TestInitialSequenceNumber).Add(1) 708 start := c.IRS.Add(1 + seqnum.Size(5*maxPayload)) 709 end := start.Add(seqnum.Size(maxPayload)) 710 c.SendAckWithSACK(seq, bytesRead, []header.SACKBlock{{start, end}}) 711 712 // Expect retransmission of #2 packet. 713 c.ReceiveAndCheckPacketWithOptions(data, bytesRead, maxPayload, tsOptionSize) 714 715 // Received delayed #2 packet. 716 bytesRead += maxPayload 717 c.SendAckWithSACK(seq, bytesRead, []header.SACKBlock{{start, end}}) 718 719 // Received delayed #4 packet. 720 start1 := c.IRS.Add(1 + seqnum.Size(3*maxPayload)) 721 end1 := start1.Add(seqnum.Size(maxPayload)) 722 c.SendAckWithSACK(seq, bytesRead, []header.SACKBlock{{start1, end1}, {start, end}}) 723 724 // Simulate receiving retransmitted subsegment for #2 packet and delayed #3 725 // packet by sending DSACK block for #2 packet. 726 dsackStart := c.IRS.Add(1 + seqnum.Size(maxPayload)) 727 dsackEnd := dsackStart.Add(seqnum.Size(maxPayload / 2)) 728 c.SendAckWithSACK(seq, 4*maxPayload, []header.SACKBlock{{dsackStart, dsackEnd}, {start, end}}) 729 730 // Wait for the probe function to finish processing the ACK before the 731 // test completes. 732 err := <-probeDone 733 switch err { 734 case failedToDetectDSACK: 735 t.Fatalf("RACK DSACK detection failed") 736 case invalidDSACKDetected: 737 t.Fatalf("RACK DSACK detected when there is no duplicate SACK") 738 } 739 } 740 741 // TestRACKDetectDSACKDup tests two non-contiguous duplicate subsegments not 742 // covered by the cumulative acknowledgement. 743 // See: https://tools.ietf.org/html/rfc2883#section-4.2.3. 744 func TestRACKDetectDSACKDup(t *testing.T) { 745 c := context.New(t, uint32(mtu)) 746 defer c.Cleanup() 747 748 probeDone := make(chan int) 749 const ackNumToVerify = 5 750 addDSACKSeenCheckerProbe(t, c, ackNumToVerify, probeDone) 751 752 numPackets := 7 753 data := sendAndReceiveWithSACK(t, c, numPackets, true /* enableRACK */) 754 755 // Send ACK for #1 packet. 756 bytesRead := maxPayload 757 seq := seqnum.Value(context.TestInitialSequenceNumber).Add(1) 758 c.SendAck(seq, bytesRead) 759 760 // Missing [2-6] packets and SACK #7 packet. 761 seq = seqnum.Value(context.TestInitialSequenceNumber).Add(1) 762 start := c.IRS.Add(1 + seqnum.Size(6*maxPayload)) 763 end := start.Add(seqnum.Size(maxPayload)) 764 c.SendAckWithSACK(seq, bytesRead, []header.SACKBlock{{start, end}}) 765 766 // Received delayed #3 packet. 767 start1 := c.IRS.Add(1 + seqnum.Size(2*maxPayload)) 768 end1 := start1.Add(seqnum.Size(maxPayload)) 769 c.SendAckWithSACK(seq, bytesRead, []header.SACKBlock{{start1, end1}, {start, end}}) 770 771 // Expect retransmission of #2 packet. 772 c.ReceiveAndCheckPacketWithOptions(data, bytesRead, maxPayload, tsOptionSize) 773 774 // Consider #2 packet has been dropped and SACK #4 packet. 775 start2 := c.IRS.Add(1 + seqnum.Size(3*maxPayload)) 776 end2 := start2.Add(seqnum.Size(maxPayload)) 777 c.SendAckWithSACK(seq, bytesRead, []header.SACKBlock{{start2, end2}, {start1, end1}, {start, end}}) 778 779 // Simulate receiving retransmitted subsegment for #3 packet and delayed #5 780 // packet by sending DSACK block for the subsegment. 781 dsackStart := c.IRS.Add(1 + seqnum.Size(2*maxPayload)) 782 dsackEnd := dsackStart.Add(seqnum.Size(maxPayload / 2)) 783 end1 = end1.Add(seqnum.Size(2 * maxPayload)) 784 c.SendAckWithSACK(seq, bytesRead, []header.SACKBlock{{dsackStart, dsackEnd}, {start1, end1}}) 785 786 // Wait for the probe function to finish processing the ACK before the 787 // test completes. 788 err := <-probeDone 789 switch err { 790 case failedToDetectDSACK: 791 t.Fatalf("RACK DSACK detection failed") 792 case invalidDSACKDetected: 793 t.Fatalf("RACK DSACK detected when there is no duplicate SACK") 794 } 795 } 796 797 // TestRACKWithInvalidDSACKBlock tests that DSACK is not detected when DSACK 798 // is not the first SACK block. 799 func TestRACKWithInvalidDSACKBlock(t *testing.T) { 800 c := context.New(t, uint32(mtu)) 801 defer c.Cleanup() 802 803 probeDone := make(chan struct{}) 804 const ackNumToVerify = 2 805 var n int 806 c.Stack().AddTCPProbe(func(state stack.TCPEndpointState) { 807 // Validate that RACK does not detect DSACK when DSACK block is 808 // not the first SACK block. 809 n++ 810 t.Helper() 811 if state.Sender.RACKState.DSACKSeen { 812 t.Fatalf("RACK DSACK detected when there is no duplicate SACK") 813 } 814 815 if n == ackNumToVerify { 816 close(probeDone) 817 } 818 }) 819 820 numPackets := 10 821 data := sendAndReceiveWithSACK(t, c, numPackets, true /* enableRACK */) 822 823 // Cumulative ACK for [1-5] packets and SACK for #7 packet (to prevent TLP). 824 seq := seqnum.Value(context.TestInitialSequenceNumber).Add(1) 825 bytesRead := 5 * maxPayload 826 seventhPStart := c.IRS.Add(1 + seqnum.Size(6*maxPayload)) 827 seventhPEnd := seventhPStart.Add(maxPayload) 828 c.SendAckWithSACK(seq, bytesRead, []header.SACKBlock{{seventhPStart, seventhPEnd}}) 829 830 // Expect retransmission of #6 packet. 831 c.ReceiveAndCheckPacketWithOptions(data, bytesRead, maxPayload, tsOptionSize) 832 833 // Send DSACK block for #6 packet indicating both 834 // initial and retransmitted packet are received and 835 // packets [1-7] are received. 836 start := c.IRS.Add(1 + seqnum.Size(bytesRead)) 837 end := start.Add(maxPayload) 838 bytesRead += 2 * maxPayload 839 840 // Send DSACK block as second block. The first block is a SACK for #9 packet. 841 start1 := c.IRS.Add(1 + seqnum.Size(bytesRead) + maxPayload) 842 end1 := start1.Add(maxPayload) 843 c.SendAckWithSACK(seq, bytesRead, []header.SACKBlock{{start1, end1}, {start, end}}) 844 845 // Wait for the probe function to finish processing the 846 // ACK before the test completes. 847 <-probeDone 848 } 849 850 func addReorderWindowCheckerProbe(c *context.Context, numACK int, probeDone chan error) { 851 var n int 852 c.Stack().AddTCPProbe(func(state stack.TCPEndpointState) { 853 // Validate that RACK detects DSACK. 854 n++ 855 if n < numACK { 856 return 857 } 858 859 if state.Sender.RACKState.ReoWnd == 0 || state.Sender.RACKState.ReoWnd > state.Sender.RTTState.SRTT { 860 probeDone <- fmt.Errorf("got RACKState.ReoWnd: %d, expected it to be greater than 0 and less than %d", state.Sender.RACKState.ReoWnd, state.Sender.RTTState.SRTT) 861 return 862 } 863 864 if state.Sender.RACKState.ReoWndIncr != 1 { 865 probeDone <- fmt.Errorf("got RACKState.ReoWndIncr: %v, want: 1", state.Sender.RACKState.ReoWndIncr) 866 return 867 } 868 869 if state.Sender.RACKState.ReoWndPersist > 0 { 870 probeDone <- fmt.Errorf("got RACKState.ReoWndPersist: %v, want: greater than 0", state.Sender.RACKState.ReoWndPersist) 871 return 872 } 873 probeDone <- nil 874 }) 875 } 876 877 func TestRACKCheckReorderWindow(t *testing.T) { 878 c := context.New(t, uint32(mtu)) 879 defer c.Cleanup() 880 881 probeDone := make(chan error) 882 const ackNumToVerify = 3 883 addReorderWindowCheckerProbe(c, ackNumToVerify, probeDone) 884 885 const numPackets = 7 886 sendAndReceiveWithSACK(t, c, numPackets, true /* enableRACK */) 887 888 // Send ACK for #1 packet. 889 bytesRead := maxPayload 890 seq := seqnum.Value(context.TestInitialSequenceNumber).Add(1) 891 c.SendAck(seq, bytesRead) 892 893 // Missing [2-6] packets and SACK #7 packet. 894 start := c.IRS.Add(1 + seqnum.Size(6*maxPayload)) 895 end := start.Add(seqnum.Size(maxPayload)) 896 c.SendAckWithSACK(seq, bytesRead, []header.SACKBlock{{start, end}}) 897 898 // Received delayed packets [2-6] which indicates there is reordering 899 // in the connection. 900 bytesRead += 6 * maxPayload 901 c.SendAck(seq, bytesRead) 902 903 // Wait for the probe function to finish processing the ACK before the 904 // test completes. 905 if err := <-probeDone; err != nil { 906 t.Fatalf("unexpected values for RACK variables: %v", err) 907 } 908 } 909 910 func TestRACKWithDuplicateACK(t *testing.T) { 911 c := context.New(t, uint32(mtu)) 912 defer c.Cleanup() 913 914 const numPackets = 4 915 data := sendAndReceiveWithSACK(t, c, numPackets, true /* enableRACK */) 916 917 // Send three duplicate ACKs to trigger fast recovery. The first 918 // segment is considered as lost and will be retransmitted after 919 // receiving the duplicate ACKs. 920 seq := seqnum.Value(context.TestInitialSequenceNumber).Add(1) 921 start := c.IRS.Add(1 + seqnum.Size(maxPayload)) 922 end := start.Add(seqnum.Size(maxPayload)) 923 for i := 0; i < 3; i++ { 924 c.SendAckWithSACK(seq, 0, []header.SACKBlock{{start, end}}) 925 end = end.Add(seqnum.Size(maxPayload)) 926 } 927 928 // Receive the retransmitted packet. 929 c.ReceiveAndCheckPacketWithOptions(data, 0, maxPayload, tsOptionSize) 930 931 metricPollFn := func() error { 932 tcpStats := c.Stack().Stats().TCP 933 stats := []struct { 934 stat *tcpip.StatCounter 935 name string 936 want uint64 937 }{ 938 {tcpStats.FastRetransmit, "stats.TCP.FastRetransmit", 1}, 939 {tcpStats.SACKRecovery, "stats.TCP.SACKRecovery", 1}, 940 {tcpStats.FastRecovery, "stats.TCP.FastRecovery", 0}, 941 } 942 for _, s := range stats { 943 if got, want := s.stat.Value(), s.want; got != want { 944 return fmt.Errorf("got %s.Value() = %d, want = %d", s.name, got, want) 945 } 946 } 947 return nil 948 } 949 950 if err := testutil.Poll(metricPollFn, 1*time.Second); err != nil { 951 t.Error(err) 952 } 953 } 954 955 // TestRACKUpdateSackedOut tests the sacked out field is updated when a SACK 956 // is received. 957 func TestRACKUpdateSackedOut(t *testing.T) { 958 c := context.New(t, uint32(mtu)) 959 defer c.Cleanup() 960 961 probeDone := make(chan struct{}) 962 ackNum := 0 963 c.Stack().AddTCPProbe(func(state stack.TCPEndpointState) { 964 // Validate that the endpoint Sender.SackedOut is what we expect. 965 if state.Sender.SackedOut != 2 && ackNum == 0 { 966 t.Fatalf("SackedOut got updated to wrong value got: %v want: 2", state.Sender.SackedOut) 967 } 968 969 if state.Sender.SackedOut != 0 && ackNum == 1 { 970 t.Fatalf("SackedOut got updated to wrong value got: %v want: 0", state.Sender.SackedOut) 971 } 972 if ackNum > 0 { 973 close(probeDone) 974 } 975 ackNum++ 976 }) 977 978 sendAndReceiveWithSACK(t, c, 8, true /* enableRACK */) 979 980 // ACK for [3-5] packets. 981 seq := seqnum.Value(context.TestInitialSequenceNumber).Add(1) 982 start := c.IRS.Add(seqnum.Size(1 + 3*maxPayload)) 983 bytesRead := 2 * maxPayload 984 end := start.Add(seqnum.Size(bytesRead)) 985 c.SendAckWithSACK(seq, bytesRead, []header.SACKBlock{{start, end}}) 986 987 bytesRead += 3 * maxPayload 988 c.SendAck(seq, bytesRead) 989 990 // Wait for the probe function to finish processing the ACK before the 991 // test completes. 992 <-probeDone 993 } 994 995 // TestRACKWithWindowFull tests that RACK honors the receive window size. 996 func TestRACKWithWindowFull(t *testing.T) { 997 c := context.New(t, uint32(mtu)) 998 defer c.Cleanup() 999 1000 setStackSACKPermitted(t, c, true) 1001 setStackRACKPermitted(t, c) 1002 createConnectedWithSACKAndTS(c) 1003 1004 seq := seqnum.Value(context.TestInitialSequenceNumber).Add(1) 1005 const numPkts = 10 1006 data := make([]byte, numPkts*maxPayload) 1007 for i := range data { 1008 data[i] = byte(i) 1009 } 1010 1011 // Write the data. 1012 var r bytes.Reader 1013 r.Reset(data) 1014 if _, err := c.EP.Write(&r, tcpip.WriteOptions{}); err != nil { 1015 t.Fatalf("Write failed: %s", err) 1016 } 1017 1018 bytesRead := 0 1019 for i := 0; i < numPkts; i++ { 1020 c.ReceiveAndCheckPacketWithOptions(data, bytesRead, maxPayload, tsOptionSize) 1021 bytesRead += maxPayload 1022 if i == 0 { 1023 // Send ACK for the first packet to establish RTT. 1024 c.SendAck(seq, maxPayload) 1025 } 1026 } 1027 1028 // SACK for #10 packet. 1029 start := c.IRS.Add(seqnum.Size(1 + (numPkts-1)*maxPayload)) 1030 end := start.Add(seqnum.Size(maxPayload)) 1031 c.SendAckWithSACK(seq, 2*maxPayload, []header.SACKBlock{{start, end}}) 1032 1033 var info tcpip.TCPInfoOption 1034 if err := c.EP.GetSockOpt(&info); err != nil { 1035 t.Fatalf("GetSockOpt failed: %v", err) 1036 } 1037 // Wait for RTT to trigger recovery. 1038 time.Sleep(info.RTT) 1039 1040 // Expect retransmission of #2 packet. 1041 c.ReceiveAndCheckPacketWithOptions(data, 2*maxPayload, maxPayload, tsOptionSize) 1042 1043 // Send ACK for #2 packet. 1044 c.SendAck(seq, 3*maxPayload) 1045 1046 // Expect retransmission of #3 packet. 1047 c.ReceiveAndCheckPacketWithOptions(data, 3*maxPayload, maxPayload, tsOptionSize) 1048 1049 // Send ACK with zero window size. 1050 c.SendPacket(nil, &context.Headers{ 1051 SrcPort: context.TestPort, 1052 DstPort: c.Port, 1053 Flags: header.TCPFlagAck, 1054 SeqNum: seq, 1055 AckNum: c.IRS.Add(1 + 4*maxPayload), 1056 RcvWnd: 0, 1057 }) 1058 1059 // No packet should be received as the receive window size is zero. 1060 c.CheckNoPacket("unexpected packet received after userTimeout has expired") 1061 }