Merge release-20200323.0-187-gdb2a60b (automated)

This commit is contained in:
gVisor bot 2020-04-20 05:18:38 +00:00
commit f9519276e4
6 changed files with 40 additions and 43 deletions

View File

@ -46,11 +46,6 @@ func (v Value) InWindow(first Value, size Size) bool {
return v.InRange(first, first.Add(size))
}
// Overlap checks if the window [a,a+b) overlaps with the window [x, x+y).
func Overlap(a Value, b Size, x Value, y Size) bool {
return a.LessThan(x.Add(y)) && x.LessThan(a.Add(b))
}
// Add calculates the sequence number following the [v, v+s) window.
func (v Value) Add(s Size) Value {
return v + Value(s)

View File

@ -101,7 +101,7 @@ type listenContext struct {
// v6Only is true if listenEP is a dual stack socket and has the
// IPV6_V6ONLY option set.
v6only bool
v6Only bool
// netProto indicates the network protocol(IPv4/v6) for the listening
// endpoint.
@ -126,12 +126,12 @@ func timeStamp() uint32 {
}
// newListenContext creates a new listen context.
func newListenContext(stk *stack.Stack, listenEP *endpoint, rcvWnd seqnum.Size, v6only bool, netProto tcpip.NetworkProtocolNumber) *listenContext {
func newListenContext(stk *stack.Stack, listenEP *endpoint, rcvWnd seqnum.Size, v6Only bool, netProto tcpip.NetworkProtocolNumber) *listenContext {
l := &listenContext{
stack: stk,
rcvWnd: rcvWnd,
hasher: sha1.New(),
v6only: v6only,
v6Only: v6Only,
netProto: netProto,
listenEP: listenEP,
pendingEndpoints: make(map[stack.TransportEndpointID]*endpoint),
@ -207,7 +207,7 @@ func (l *listenContext) createConnectingEndpoint(s *segment, iss seqnum.Value, i
netProto = s.route.NetProto
}
n := newEndpoint(l.stack, netProto, queue)
n.v6only = l.v6only
n.v6only = l.v6Only
n.ID = s.id
n.boundNICID = s.route.NICID()
n.route = s.route.Clone()
@ -293,7 +293,7 @@ func (l *listenContext) createEndpointAndPerformHandshake(s *segment, opts *head
}
// Perform the 3-way handshake.
h := newPassiveHandshake(ep, seqnum.Size(ep.initialReceiveWindow()), isn, irs, opts, deferAccept)
h := newPassiveHandshake(ep, ep.rcv.rcvWnd, isn, irs, opts, deferAccept)
if err := h.execute(); err != nil {
ep.mu.Unlock()
ep.Close()
@ -613,8 +613,8 @@ func (e *endpoint) handleListenSegment(ctx *listenContext, s *segment) {
// its own goroutine and is responsible for handling connection requests.
func (e *endpoint) protocolListenLoop(rcvWnd seqnum.Size) *tcpip.Error {
e.mu.Lock()
v6only := e.v6only
ctx := newListenContext(e.stack, e, rcvWnd, v6only, e.NetProto)
v6Only := e.v6only
ctx := newListenContext(e.stack, e, rcvWnd, v6Only, e.NetProto)
defer func() {
// Mark endpoint as closed. This will prevent goroutines running

View File

@ -105,24 +105,11 @@ type handshake struct {
}
func newHandshake(ep *endpoint, rcvWnd seqnum.Size) handshake {
rcvWndScale := ep.rcvWndScaleForHandshake()
// Round-down the rcvWnd to a multiple of wndScale. This ensures that the
// window offered in SYN won't be reduced due to the loss of precision if
// window scaling is enabled after the handshake.
rcvWnd = (rcvWnd >> uint8(rcvWndScale)) << uint8(rcvWndScale)
// Ensure we can always accept at least 1 byte if the scale specified
// was too high for the provided rcvWnd.
if rcvWnd == 0 {
rcvWnd = 1
}
h := handshake{
ep: ep,
active: true,
rcvWnd: rcvWnd,
rcvWndScale: int(rcvWndScale),
rcvWndScale: ep.rcvWndScaleForHandshake(),
}
h.resetState()
return h

View File

@ -1062,6 +1062,19 @@ func (e *endpoint) initialReceiveWindow() int {
if rcvWnd > routeWnd {
rcvWnd = routeWnd
}
rcvWndScale := e.rcvWndScaleForHandshake()
// Round-down the rcvWnd to a multiple of wndScale. This ensures that the
// window offered in SYN won't be reduced due to the loss of precision if
// window scaling is enabled after the handshake.
rcvWnd = (rcvWnd >> uint8(rcvWndScale)) << uint8(rcvWndScale)
// Ensure we can always accept at least 1 byte if the scale specified
// was too high for the provided rcvWnd.
if rcvWnd == 0 {
rcvWnd = 1
}
return rcvWnd
}

View File

@ -70,13 +70,24 @@ func newReceiver(ep *endpoint, irs seqnum.Value, rcvWnd seqnum.Size, rcvWndScale
// acceptable checks if the segment sequence number range is acceptable
// according to the table on page 26 of RFC 793.
func (r *receiver) acceptable(segSeq seqnum.Value, segLen seqnum.Size) bool {
rcvWnd := r.rcvNxt.Size(r.rcvAcc)
if rcvWnd == 0 {
return segLen == 0 && segSeq == r.rcvNxt
}
return Acceptable(segSeq, segLen, r.rcvNxt, r.rcvAcc)
}
return segSeq.InWindow(r.rcvNxt, rcvWnd) ||
seqnum.Overlap(r.rcvNxt, rcvWnd, segSeq, segLen)
// Acceptable checks if a segment that starts at segSeq and has length segLen is
// "acceptable" for arriving in a receive window that starts at rcvNxt and ends
// before rcvAcc, according to the table on page 26 and 69 of RFC 793.
func Acceptable(segSeq seqnum.Value, segLen seqnum.Size, rcvNxt, rcvAcc seqnum.Value) bool {
if rcvNxt == rcvAcc {
return segLen == 0 && segSeq == rcvNxt
}
if segLen == 0 {
// rcvWnd is incremented by 1 because that is Linux's behavior despite the
// RFC.
return segSeq.InRange(rcvNxt, rcvAcc.Add(1))
}
// Page 70 of RFC 793 allows packets that can be made "acceptable" by trimming
// the payload, so we'll accept any payload that overlaps the receieve window.
return rcvNxt.LessThan(segSeq.Add(segLen)) && segSeq.LessThan(rcvAcc)
}
// getSendParams returns the parameters needed by the sender when building

View File

@ -20,6 +20,7 @@ package tcpconntrack
import (
"gvisor.dev/gvisor/pkg/tcpip/header"
"gvisor.dev/gvisor/pkg/tcpip/seqnum"
"gvisor.dev/gvisor/pkg/tcpip/transport/tcp"
)
// Result is returned when the state of a TCB is updated in response to an
@ -311,17 +312,7 @@ type stream struct {
// the window is zero, if it's a packet with no payload and sequence number
// equal to una.
func (s *stream) acceptable(segSeq seqnum.Value, segLen seqnum.Size) bool {
wnd := s.una.Size(s.end)
if wnd == 0 {
return segLen == 0 && segSeq == s.una
}
// Make sure [segSeq, seqSeq+segLen) is non-empty.
if segLen == 0 {
segLen = 1
}
return seqnum.Overlap(s.una, wnd, segSeq, segLen)
return tcp.Acceptable(segSeq, segLen, s.una, s.end)
}
// closed determines if the stream has already been closed. This happens when