summaryrefslogtreecommitdiffhomepage
path: root/pkg/tcpip
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/tcpip')
-rw-r--r--pkg/tcpip/link/loopback/loopback.go2
-rw-r--r--pkg/tcpip/stack/registration.go1
-rw-r--r--pkg/tcpip/transport/tcp/endpoint_state.go9
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 {