mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Fix data race in tcp_test.
This change makes SynRcvdCountThreshold and the global synRcvdCount into a stack configurable value. This is required because in cases like mod_proxy which create multiple Stack instances the count will be a global value that impacts all Stack instances. Further the tests relied on modifying the global threshold to simulate tests where we want to verify SYN cookie based behaviour. This lead to data races due to the global being modified/read without locks or atomics. PiperOrigin-RevId: 306947723
This commit is contained in:
committed by
gVisor bot
parent
75e864fc75
commit
0eda0104a5
@@ -685,6 +685,11 @@ type TCPDeferAcceptOption time.Duration
|
||||
// default MinRTO used by the Stack.
|
||||
type TCPMinRTOOption time.Duration
|
||||
|
||||
// TCPSynRcvdCountThresholdOption is used by SetSockOpt/GetSockOpt to specify
|
||||
// the number of endpoints that can be in SYN-RCVD state before the stack
|
||||
// switches to using SYN cookies.
|
||||
type TCPSynRcvdCountThresholdOption uint64
|
||||
|
||||
// MulticastInterfaceOption is used by SetSockOpt/GetSockOpt to specify a
|
||||
// default interface for multicast.
|
||||
type MulticastInterfaceOption struct {
|
||||
|
||||
@@ -17,6 +17,7 @@ package tcp
|
||||
import (
|
||||
"crypto/sha1"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"hash"
|
||||
"io"
|
||||
"time"
|
||||
@@ -49,17 +50,14 @@ const (
|
||||
// timestamp and the current timestamp. If the difference is greater
|
||||
// than maxTSDiff, the cookie is expired.
|
||||
maxTSDiff = 2
|
||||
|
||||
// SynRcvdCountThreshold is the default global maximum number of
|
||||
// connections that are allowed to be in SYN-RCVD state before TCP
|
||||
// starts using SYN cookies to accept connections.
|
||||
SynRcvdCountThreshold uint64 = 1000
|
||||
)
|
||||
|
||||
var (
|
||||
// SynRcvdCountThreshold is the global maximum number of connections
|
||||
// that are allowed to be in SYN-RCVD state before TCP starts using SYN
|
||||
// cookies to accept connections.
|
||||
//
|
||||
// It is an exported variable only for testing, and should not otherwise
|
||||
// be used by importers of this package.
|
||||
SynRcvdCountThreshold uint64 = 1000
|
||||
|
||||
// mssTable is a slice containing the possible MSS values that we
|
||||
// encode in the SYN cookie with two bits.
|
||||
mssTable = []uint16{536, 1300, 1440, 1460}
|
||||
@@ -74,29 +72,42 @@ func encodeMSS(mss uint16) uint32 {
|
||||
return 0
|
||||
}
|
||||
|
||||
// syncRcvdCount is the number of endpoints in the SYN-RCVD state. The value is
|
||||
// protected by a mutex so that we can increment only when it's guaranteed not
|
||||
// to go above a threshold.
|
||||
var synRcvdCount struct {
|
||||
sync.Mutex
|
||||
value uint64
|
||||
pending sync.WaitGroup
|
||||
}
|
||||
|
||||
// listenContext is used by a listening endpoint to store state used while
|
||||
// listening for connections. This struct is allocated by the listen goroutine
|
||||
// and must not be accessed or have its methods called concurrently as they
|
||||
// may mutate the stored objects.
|
||||
type listenContext struct {
|
||||
stack *stack.Stack
|
||||
rcvWnd seqnum.Size
|
||||
nonce [2][sha1.BlockSize]byte
|
||||
stack *stack.Stack
|
||||
|
||||
// synRcvdCount is a reference to the stack level synRcvdCount.
|
||||
synRcvdCount *synRcvdCounter
|
||||
|
||||
// rcvWnd is the receive window that is sent by this listening context
|
||||
// in the initial SYN-ACK.
|
||||
rcvWnd seqnum.Size
|
||||
|
||||
// nonce are random bytes that are initialized once when the context
|
||||
// is created and used to seed the hash function when generating
|
||||
// the SYN cookie.
|
||||
nonce [2][sha1.BlockSize]byte
|
||||
|
||||
// listenEP is a reference to the listening endpoint associated with
|
||||
// this context. Can be nil if the context is created by the forwarder.
|
||||
listenEP *endpoint
|
||||
|
||||
// hasherMu protects hasher.
|
||||
hasherMu sync.Mutex
|
||||
hasher hash.Hash
|
||||
v6only bool
|
||||
// hasher is the hash function used to generate a SYN cookie.
|
||||
hasher hash.Hash
|
||||
|
||||
// v6Only is true if listenEP is a dual stack socket and has the
|
||||
// IPV6_V6ONLY option set.
|
||||
v6only bool
|
||||
|
||||
// netProto indicates the network protocol(IPv4/v6) for the listening
|
||||
// endpoint.
|
||||
netProto tcpip.NetworkProtocolNumber
|
||||
|
||||
// pendingMu protects pendingEndpoints. This should only be accessed
|
||||
// by the listening endpoint's worker goroutine.
|
||||
//
|
||||
@@ -115,44 +126,6 @@ func timeStamp() uint32 {
|
||||
return uint32(time.Now().Unix()>>6) & tsMask
|
||||
}
|
||||
|
||||
// incSynRcvdCount tries to increment the global number of endpoints in SYN-RCVD
|
||||
// state. It succeeds if the increment doesn't make the count go beyond the
|
||||
// threshold, and fails otherwise.
|
||||
func incSynRcvdCount() bool {
|
||||
synRcvdCount.Lock()
|
||||
|
||||
if synRcvdCount.value >= SynRcvdCountThreshold {
|
||||
synRcvdCount.Unlock()
|
||||
return false
|
||||
}
|
||||
|
||||
synRcvdCount.pending.Add(1)
|
||||
synRcvdCount.value++
|
||||
|
||||
synRcvdCount.Unlock()
|
||||
return true
|
||||
}
|
||||
|
||||
// decSynRcvdCount atomically decrements the global number of endpoints in
|
||||
// SYN-RCVD state. It must only be called if a previous call to incSynRcvdCount
|
||||
// succeeded.
|
||||
func decSynRcvdCount() {
|
||||
synRcvdCount.Lock()
|
||||
|
||||
synRcvdCount.value--
|
||||
synRcvdCount.pending.Done()
|
||||
synRcvdCount.Unlock()
|
||||
}
|
||||
|
||||
// synCookiesInUse() returns true if the synRcvdCount is greater than
|
||||
// SynRcvdCountThreshold.
|
||||
func synCookiesInUse() bool {
|
||||
synRcvdCount.Lock()
|
||||
v := synRcvdCount.value
|
||||
synRcvdCount.Unlock()
|
||||
return v >= SynRcvdCountThreshold
|
||||
}
|
||||
|
||||
// newListenContext creates a new listen context.
|
||||
func newListenContext(stk *stack.Stack, listenEP *endpoint, rcvWnd seqnum.Size, v6only bool, netProto tcpip.NetworkProtocolNumber) *listenContext {
|
||||
l := &listenContext{
|
||||
@@ -164,6 +137,11 @@ func newListenContext(stk *stack.Stack, listenEP *endpoint, rcvWnd seqnum.Size,
|
||||
listenEP: listenEP,
|
||||
pendingEndpoints: make(map[stack.TransportEndpointID]*endpoint),
|
||||
}
|
||||
p, ok := stk.TransportProtocolInstance(ProtocolNumber).(*protocol)
|
||||
if !ok {
|
||||
panic(fmt.Sprintf("unable to get TCP protocol instance from stack: %+v", stk))
|
||||
}
|
||||
l.synRcvdCount = p.SynRcvdCounter()
|
||||
|
||||
rand.Read(l.nonce[0][:])
|
||||
rand.Read(l.nonce[1][:])
|
||||
@@ -410,7 +388,7 @@ func (e *endpoint) propagateInheritableOptionsLocked(n *endpoint) {
|
||||
// A limited number of these goroutines are allowed before TCP starts using SYN
|
||||
// cookies to accept connections.
|
||||
func (e *endpoint) handleSynSegment(ctx *listenContext, s *segment, opts *header.TCPSynOptions) {
|
||||
defer decSynRcvdCount()
|
||||
defer ctx.synRcvdCount.dec()
|
||||
defer func() {
|
||||
e.mu.Lock()
|
||||
e.decSynRcvdCount()
|
||||
@@ -477,7 +455,7 @@ func (e *endpoint) handleListenSegment(ctx *listenContext, s *segment) {
|
||||
switch {
|
||||
case s.flags == header.TCPFlagSyn:
|
||||
opts := parseSynSegmentOptions(s)
|
||||
if incSynRcvdCount() {
|
||||
if ctx.synRcvdCount.inc() {
|
||||
// Only handle the syn if the following conditions hold
|
||||
// - accept queue is not full.
|
||||
// - number of connections in synRcvd state is less than the
|
||||
@@ -487,7 +465,7 @@ func (e *endpoint) handleListenSegment(ctx *listenContext, s *segment) {
|
||||
go e.handleSynSegment(ctx, s, &opts) // S/R-SAFE: synRcvdCount is the barrier.
|
||||
return
|
||||
}
|
||||
decSynRcvdCount()
|
||||
ctx.synRcvdCount.dec()
|
||||
e.stack.Stats().TCP.ListenOverflowSynDrop.Increment()
|
||||
e.stats.ReceiveErrors.ListenOverflowSynDrop.Increment()
|
||||
e.stack.Stats().DroppedPackets.Increment()
|
||||
@@ -540,7 +518,7 @@ func (e *endpoint) handleListenSegment(ctx *listenContext, s *segment) {
|
||||
return
|
||||
}
|
||||
|
||||
if !synCookiesInUse() {
|
||||
if !ctx.synRcvdCount.synCookiesInUse() {
|
||||
// When not using SYN cookies, as per RFC 793, section 3.9, page 64:
|
||||
// Any acknowledgment is bad if it arrives on a connection still in
|
||||
// the LISTEN state. An acceptable reset segment should be formed
|
||||
|
||||
@@ -568,11 +568,10 @@ func TestV4AcceptOnV4(t *testing.T) {
|
||||
func testV4ListenClose(t *testing.T, c *context.Context) {
|
||||
// Set the SynRcvd threshold to zero to force a syn cookie based accept
|
||||
// to happen.
|
||||
saved := tcp.SynRcvdCountThreshold
|
||||
defer func() {
|
||||
tcp.SynRcvdCountThreshold = saved
|
||||
}()
|
||||
tcp.SynRcvdCountThreshold = 0
|
||||
if err := c.Stack().SetTransportProtocolOption(tcp.ProtocolNumber, tcpip.TCPSynRcvdCountThresholdOption(0)); err != nil {
|
||||
t.Fatalf("setting TCPSynRcvdCountThresholdOption failed: %s", err)
|
||||
}
|
||||
|
||||
const n = uint16(32)
|
||||
|
||||
// Start listening.
|
||||
|
||||
@@ -94,6 +94,63 @@ const (
|
||||
ccCubic = "cubic"
|
||||
)
|
||||
|
||||
// syncRcvdCounter tracks the number of endpoints in the SYN-RCVD state. The
|
||||
// value is protected by a mutex so that we can increment only when it's
|
||||
// guaranteed not to go above a threshold.
|
||||
type synRcvdCounter struct {
|
||||
sync.Mutex
|
||||
value uint64
|
||||
pending sync.WaitGroup
|
||||
threshold uint64
|
||||
}
|
||||
|
||||
// inc tries to increment the global number of endpoints in SYN-RCVD state. It
|
||||
// succeeds if the increment doesn't make the count go beyond the threshold, and
|
||||
// fails otherwise.
|
||||
func (s *synRcvdCounter) inc() bool {
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
if s.value >= s.threshold {
|
||||
return false
|
||||
}
|
||||
|
||||
s.pending.Add(1)
|
||||
s.value++
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// dec atomically decrements the global number of endpoints in SYN-RCVD
|
||||
// state. It must only be called if a previous call to inc succeeded.
|
||||
func (s *synRcvdCounter) dec() {
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
s.value--
|
||||
s.pending.Done()
|
||||
}
|
||||
|
||||
// synCookiesInUse returns true if the synRcvdCount is greater than
|
||||
// SynRcvdCountThreshold.
|
||||
func (s *synRcvdCounter) synCookiesInUse() bool {
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
return s.value >= s.threshold
|
||||
}
|
||||
|
||||
// SetThreshold sets synRcvdCounter.Threshold to ths new threshold.
|
||||
func (s *synRcvdCounter) SetThreshold(threshold uint64) {
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
s.threshold = threshold
|
||||
}
|
||||
|
||||
// Threshold returns the current value of synRcvdCounter.Threhsold.
|
||||
func (s *synRcvdCounter) Threshold() uint64 {
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
return s.threshold
|
||||
}
|
||||
|
||||
type protocol struct {
|
||||
mu sync.RWMutex
|
||||
sackEnabled bool
|
||||
@@ -106,6 +163,7 @@ type protocol struct {
|
||||
tcpLingerTimeout time.Duration
|
||||
tcpTimeWaitTimeout time.Duration
|
||||
minRTO time.Duration
|
||||
synRcvdCount synRcvdCounter
|
||||
dispatcher *dispatcher
|
||||
}
|
||||
|
||||
@@ -282,6 +340,12 @@ func (p *protocol) SetOption(option interface{}) *tcpip.Error {
|
||||
p.mu.Unlock()
|
||||
return nil
|
||||
|
||||
case tcpip.TCPSynRcvdCountThresholdOption:
|
||||
p.mu.Lock()
|
||||
p.synRcvdCount.SetThreshold(uint64(v))
|
||||
p.mu.Unlock()
|
||||
return nil
|
||||
|
||||
default:
|
||||
return tcpip.ErrUnknownProtocolOption
|
||||
}
|
||||
@@ -350,6 +414,12 @@ func (p *protocol) Option(option interface{}) *tcpip.Error {
|
||||
p.mu.RUnlock()
|
||||
return nil
|
||||
|
||||
case *tcpip.TCPSynRcvdCountThresholdOption:
|
||||
p.mu.RLock()
|
||||
*v = tcpip.TCPSynRcvdCountThresholdOption(p.synRcvdCount.Threshold())
|
||||
p.mu.RUnlock()
|
||||
return nil
|
||||
|
||||
default:
|
||||
return tcpip.ErrUnknownProtocolOption
|
||||
}
|
||||
@@ -365,6 +435,12 @@ func (p *protocol) Wait() {
|
||||
p.dispatcher.wait()
|
||||
}
|
||||
|
||||
// SynRcvdCounter returns a reference to the synRcvdCount for this protocol
|
||||
// instance.
|
||||
func (p *protocol) SynRcvdCounter() *synRcvdCounter {
|
||||
return &p.synRcvdCount
|
||||
}
|
||||
|
||||
// NewProtocol returns a TCP transport protocol.
|
||||
func NewProtocol() stack.TransportProtocol {
|
||||
return &protocol{
|
||||
@@ -374,6 +450,7 @@ func NewProtocol() stack.TransportProtocol {
|
||||
availableCongestionControl: []string{ccReno, ccCubic},
|
||||
tcpLingerTimeout: DefaultTCPLingerTimeout,
|
||||
tcpTimeWaitTimeout: DefaultTCPTimeWaitTimeout,
|
||||
synRcvdCount: synRcvdCounter{threshold: SynRcvdCountThreshold},
|
||||
dispatcher: newDispatcher(runtime.GOMAXPROCS(0)),
|
||||
minRTO: MinRTO,
|
||||
}
|
||||
|
||||
@@ -149,21 +149,22 @@ func TestSackPermittedAccept(t *testing.T) {
|
||||
{true, false, -1, 0xffff}, // When cookie is used window scaling is disabled.
|
||||
{false, true, 5, 0x8000}, // 0x8000 * 2^5 = 1<<20 = 1MB window (the default).
|
||||
}
|
||||
savedSynCountThreshold := tcp.SynRcvdCountThreshold
|
||||
defer func() {
|
||||
tcp.SynRcvdCountThreshold = savedSynCountThreshold
|
||||
}()
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(fmt.Sprintf("test: %#v", tc), func(t *testing.T) {
|
||||
if tc.cookieEnabled {
|
||||
tcp.SynRcvdCountThreshold = 0
|
||||
} else {
|
||||
tcp.SynRcvdCountThreshold = savedSynCountThreshold
|
||||
}
|
||||
for _, sackEnabled := range []bool{false, true} {
|
||||
t.Run(fmt.Sprintf("test stack.sackEnabled: %v", sackEnabled), func(t *testing.T) {
|
||||
c := context.New(t, defaultMTU)
|
||||
defer c.Cleanup()
|
||||
|
||||
if tc.cookieEnabled {
|
||||
// Set the SynRcvd threshold to
|
||||
// zero to force a syn cookie
|
||||
// based accept to happen.
|
||||
if err := c.Stack().SetTransportProtocolOption(tcp.ProtocolNumber, tcpip.TCPSynRcvdCountThresholdOption(0)); err != nil {
|
||||
t.Fatalf("setting TCPSynRcvdCountThresholdOption to 0 failed: %s", err)
|
||||
}
|
||||
}
|
||||
setStackSACKPermitted(t, c, sackEnabled)
|
||||
|
||||
rep := c.AcceptWithOptions(tc.wndScale, header.TCPSynOptions{MSS: defaultIPv4MSS, SACKPermitted: tc.sackPermitted})
|
||||
@@ -222,21 +223,23 @@ func TestSackDisabledAccept(t *testing.T) {
|
||||
{true, -1, 0xffff}, // When cookie is used window scaling is disabled.
|
||||
{false, 5, 0x8000}, // 0x8000 * 2^5 = 1<<20 = 1MB window (the default).
|
||||
}
|
||||
savedSynCountThreshold := tcp.SynRcvdCountThreshold
|
||||
defer func() {
|
||||
tcp.SynRcvdCountThreshold = savedSynCountThreshold
|
||||
}()
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(fmt.Sprintf("test: %#v", tc), func(t *testing.T) {
|
||||
if tc.cookieEnabled {
|
||||
tcp.SynRcvdCountThreshold = 0
|
||||
} else {
|
||||
tcp.SynRcvdCountThreshold = savedSynCountThreshold
|
||||
}
|
||||
for _, sackEnabled := range []bool{false, true} {
|
||||
t.Run(fmt.Sprintf("test: sackEnabled: %v", sackEnabled), func(t *testing.T) {
|
||||
c := context.New(t, defaultMTU)
|
||||
defer c.Cleanup()
|
||||
|
||||
if tc.cookieEnabled {
|
||||
// Set the SynRcvd threshold to
|
||||
// zero to force a syn cookie
|
||||
// based accept to happen.
|
||||
if err := c.Stack().SetTransportProtocolOption(tcp.ProtocolNumber, tcpip.TCPSynRcvdCountThresholdOption(0)); err != nil {
|
||||
t.Fatalf("setting TCPSynRcvdCountThresholdOption to 0 failed: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
setStackSACKPermitted(t, c, sackEnabled)
|
||||
|
||||
rep := c.AcceptWithOptions(tc.wndScale, header.TCPSynOptions{MSS: defaultIPv4MSS})
|
||||
|
||||
@@ -2706,26 +2706,24 @@ func TestSynCookiePassiveSendMSSLessThanMTU(t *testing.T) {
|
||||
|
||||
// Set the SynRcvd threshold to zero to force a syn cookie based accept
|
||||
// to happen.
|
||||
saved := tcp.SynRcvdCountThreshold
|
||||
defer func() {
|
||||
tcp.SynRcvdCountThreshold = saved
|
||||
}()
|
||||
tcp.SynRcvdCountThreshold = 0
|
||||
if err := c.Stack().SetTransportProtocolOption(tcp.ProtocolNumber, tcpip.TCPSynRcvdCountThresholdOption(0)); err != nil {
|
||||
t.Fatalf("setting TCPSynRcvdCountThresholdOption to 0 failed: %s", err)
|
||||
}
|
||||
|
||||
// Create EP and start listening.
|
||||
wq := &waiter.Queue{}
|
||||
ep, err := c.Stack().NewEndpoint(tcp.ProtocolNumber, ipv4.ProtocolNumber, wq)
|
||||
if err != nil {
|
||||
t.Fatalf("NewEndpoint failed: %v", err)
|
||||
t.Fatalf("NewEndpoint failed: %s", err)
|
||||
}
|
||||
defer ep.Close()
|
||||
|
||||
if err := ep.Bind(tcpip.FullAddress{Port: context.StackPort}); err != nil {
|
||||
t.Fatalf("Bind failed: %v", err)
|
||||
t.Fatalf("Bind failed: %s", err)
|
||||
}
|
||||
|
||||
if err := ep.Listen(10); err != nil {
|
||||
t.Fatalf("Listen failed: %v", err)
|
||||
t.Fatalf("Listen failed: %s", err)
|
||||
}
|
||||
|
||||
// Do 3-way handshake.
|
||||
@@ -2743,7 +2741,7 @@ func TestSynCookiePassiveSendMSSLessThanMTU(t *testing.T) {
|
||||
case <-ch:
|
||||
c.EP, _, err = ep.Accept()
|
||||
if err != nil {
|
||||
t.Fatalf("Accept failed: %v", err)
|
||||
t.Fatalf("Accept failed: %s", err)
|
||||
}
|
||||
|
||||
case <-time.After(1 * time.Second):
|
||||
@@ -5143,25 +5141,23 @@ func TestListenSynRcvdQueueFull(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestListenBacklogFullSynCookieInUse(t *testing.T) {
|
||||
saved := tcp.SynRcvdCountThreshold
|
||||
defer func() {
|
||||
tcp.SynRcvdCountThreshold = saved
|
||||
}()
|
||||
tcp.SynRcvdCountThreshold = 1
|
||||
|
||||
c := context.New(t, defaultMTU)
|
||||
defer c.Cleanup()
|
||||
|
||||
if err := c.Stack().SetTransportProtocolOption(tcp.ProtocolNumber, tcpip.TCPSynRcvdCountThresholdOption(1)); err != nil {
|
||||
t.Fatalf("setting TCPSynRcvdCountThresholdOption to 1 failed: %s", err)
|
||||
}
|
||||
|
||||
// Create TCP endpoint.
|
||||
var err *tcpip.Error
|
||||
c.EP, err = c.Stack().NewEndpoint(tcp.ProtocolNumber, ipv4.ProtocolNumber, &c.WQ)
|
||||
if err != nil {
|
||||
t.Fatalf("NewEndpoint failed: %v", err)
|
||||
t.Fatalf("NewEndpoint failed: %s", err)
|
||||
}
|
||||
|
||||
// Bind to wildcard.
|
||||
if err := c.EP.Bind(tcpip.FullAddress{Port: context.StackPort}); err != nil {
|
||||
t.Fatalf("Bind failed: %v", err)
|
||||
t.Fatalf("Bind failed: %s", err)
|
||||
}
|
||||
|
||||
// Test acceptance.
|
||||
@@ -5169,7 +5165,7 @@ func TestListenBacklogFullSynCookieInUse(t *testing.T) {
|
||||
listenBacklog := 1
|
||||
portOffset := uint16(0)
|
||||
if err := c.EP.Listen(listenBacklog); err != nil {
|
||||
t.Fatalf("Listen failed: %v", err)
|
||||
t.Fatalf("Listen failed: %s", err)
|
||||
}
|
||||
|
||||
executeHandshake(t, c, context.TestPort+portOffset, false)
|
||||
|
||||
@@ -127,17 +127,15 @@ func TestTimeStampDisabledConnect(t *testing.T) {
|
||||
}
|
||||
|
||||
func timeStampEnabledAccept(t *testing.T, cookieEnabled bool, wndScale int, wndSize uint16) {
|
||||
savedSynCountThreshold := tcp.SynRcvdCountThreshold
|
||||
defer func() {
|
||||
tcp.SynRcvdCountThreshold = savedSynCountThreshold
|
||||
}()
|
||||
|
||||
if cookieEnabled {
|
||||
tcp.SynRcvdCountThreshold = 0
|
||||
}
|
||||
c := context.New(t, defaultMTU)
|
||||
defer c.Cleanup()
|
||||
|
||||
if cookieEnabled {
|
||||
if err := c.Stack().SetTransportProtocolOption(tcp.ProtocolNumber, tcpip.TCPSynRcvdCountThresholdOption(0)); err != nil {
|
||||
t.Fatalf("setting TCPSynRcvdCountThresholdOption to 0 failed: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
t.Logf("Test w/ CookieEnabled = %v", cookieEnabled)
|
||||
tsVal := rand.Uint32()
|
||||
c.AcceptWithOptions(wndScale, header.TCPSynOptions{MSS: defaultIPv4MSS, TS: true, TSVal: tsVal})
|
||||
@@ -148,7 +146,7 @@ func timeStampEnabledAccept(t *testing.T, cookieEnabled bool, wndScale int, wndS
|
||||
copy(view, data)
|
||||
|
||||
if _, _, err := c.EP.Write(tcpip.SlicePayload(view), tcpip.WriteOptions{}); err != nil {
|
||||
t.Fatalf("Unexpected error from Write: %v", err)
|
||||
t.Fatalf("Unexpected error from Write: %s", err)
|
||||
}
|
||||
|
||||
// Check that data is received and that the timestamp option TSEcr field
|
||||
@@ -190,17 +188,15 @@ func TestTimeStampEnabledAccept(t *testing.T) {
|
||||
}
|
||||
|
||||
func timeStampDisabledAccept(t *testing.T, cookieEnabled bool, wndScale int, wndSize uint16) {
|
||||
savedSynCountThreshold := tcp.SynRcvdCountThreshold
|
||||
defer func() {
|
||||
tcp.SynRcvdCountThreshold = savedSynCountThreshold
|
||||
}()
|
||||
if cookieEnabled {
|
||||
tcp.SynRcvdCountThreshold = 0
|
||||
}
|
||||
|
||||
c := context.New(t, defaultMTU)
|
||||
defer c.Cleanup()
|
||||
|
||||
if cookieEnabled {
|
||||
if err := c.Stack().SetTransportProtocolOption(tcp.ProtocolNumber, tcpip.TCPSynRcvdCountThresholdOption(0)); err != nil {
|
||||
t.Fatalf("setting TCPSynRcvdCountThresholdOption to 0 failed: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
t.Logf("Test w/ CookieEnabled = %v", cookieEnabled)
|
||||
c.AcceptWithOptions(wndScale, header.TCPSynOptions{MSS: defaultIPv4MSS})
|
||||
|
||||
@@ -211,7 +207,7 @@ func timeStampDisabledAccept(t *testing.T, cookieEnabled bool, wndScale int, wnd
|
||||
copy(view, data)
|
||||
|
||||
if _, _, err := c.EP.Write(tcpip.SlicePayload(view), tcpip.WriteOptions{}); err != nil {
|
||||
t.Fatalf("Unexpected error from Write: %v", err)
|
||||
t.Fatalf("Unexpected error from Write: %s", err)
|
||||
}
|
||||
|
||||
// Check that data is received and that the timestamp option is disabled
|
||||
|
||||
Reference in New Issue
Block a user