diff options
Diffstat (limited to 'pkg')
-rw-r--r-- | pkg/tcpip/link/loopback/loopback.go | 2 | ||||
-rw-r--r-- | pkg/tcpip/stack/registration.go | 1 | ||||
-rw-r--r-- | pkg/tcpip/transport/tcp/endpoint_state.go | 9 |
3 files changed, 9 insertions, 3 deletions
diff --git a/pkg/tcpip/link/loopback/loopback.go b/pkg/tcpip/link/loopback/loopback.go index aede1b4a2..b4dc4833c 100644 --- a/pkg/tcpip/link/loopback/loopback.go +++ b/pkg/tcpip/link/loopback/loopback.go @@ -56,7 +56,7 @@ func (*endpoint) MTU() uint32 { // Capabilities implements stack.LinkEndpoint.Capabilities. Loopback advertises // itself as supporting checksum offload, but in reality it's just omitted. func (*endpoint) Capabilities() stack.LinkEndpointCapabilities { - return stack.CapabilityChecksumOffload + return stack.CapabilityChecksumOffload | stack.CapabilitySaveRestore } // MaxHeaderLength implements stack.LinkEndpoint.MaxHeaderLength. Given that the diff --git a/pkg/tcpip/stack/registration.go b/pkg/tcpip/stack/registration.go index 70a123bbd..e9550a062 100644 --- a/pkg/tcpip/stack/registration.go +++ b/pkg/tcpip/stack/registration.go @@ -201,6 +201,7 @@ type LinkEndpointCapabilities uint const ( CapabilityChecksumOffload LinkEndpointCapabilities = 1 << iota CapabilityResolutionRequired + CapabilitySaveRestore ) // LinkEndpoint is the interface implemented by data link layer protocols (e.g., diff --git a/pkg/tcpip/transport/tcp/endpoint_state.go b/pkg/tcpip/transport/tcp/endpoint_state.go index 43765d425..ad20407fa 100644 --- a/pkg/tcpip/transport/tcp/endpoint_state.go +++ b/pkg/tcpip/transport/tcp/endpoint_state.go @@ -50,11 +50,16 @@ func (e *endpoint) beforeSave() { switch e.state { case stateInitial, stateBound: - case stateListen, stateConnecting, stateConnected: - if e.state == stateConnected && !e.workerRunning { + case stateConnected: + if e.route.Capabilities()&stack.CapabilitySaveRestore == 0 { + panic(tcpip.ErrSaveRejection{fmt.Errorf("endpoint cannot be saved in connected state: local %v:%d, remote %v:%d", e.id.LocalAddress, e.id.LocalPort, e.id.RemoteAddress, e.id.RemotePort)}) + } + if !e.workerRunning { // The endpoint must be in acceptedChan. break } + fallthrough + case stateListen, stateConnecting: e.drainSegmentLocked() if e.state != stateClosed && e.state != stateError { if !e.workerRunning { |