Skip to content

Commit 857b7b3

Browse files
nybidarigvisor-bot
authored andcommitted
Move connection termination from beforeSave() to restore.
Previously, external connections were terminated in beforeSave(), which required re-connection establishment after performing resume operation. By moving the termination logic to the restore, connections are now only closed when a full restore is required, keeping them active for resumes as intended. PiperOrigin-RevId: 856267199
1 parent 9bd108f commit 857b7b3

File tree

4 files changed

+53
-11
lines changed

4 files changed

+53
-11
lines changed

pkg/tcpip/stack/addressable_endpoint_state.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -738,6 +738,8 @@ func (a *AddressableEndpointState) Cleanup() {
738738
var _ AddressEndpoint = (*addressState)(nil)
739739

740740
// addressState holds state for an address.
741+
//
742+
// +stateify savable
741743
type addressState struct {
742744
addressableEndpointState *AddressableEndpointState
743745
addr tcpip.AddressWithPrefix
@@ -748,7 +750,7 @@ type addressState struct {
748750
//
749751
// AddressableEndpointState.mu
750752
// addressState.mu
751-
mu addressStateRWMutex
753+
mu addressStateRWMutex `state:"nosave"`
752754
refs addressStateRefs
753755
// checklocks:mu
754756
kind AddressKind

pkg/tcpip/stack/route.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ import (
2424
// Route represents a route through the networking stack to a given destination.
2525
//
2626
// It is safe to call Route's methods from multiple goroutines.
27+
//
28+
// +stateify savable
2729
type Route struct {
2830
routeInfo routeInfo
2931

@@ -33,7 +35,7 @@ type Route struct {
3335
localAddressNIC *nic
3436

3537
// mu protects annotated fields below.
36-
mu routeRWMutex
38+
mu routeRWMutex `state:"nosave"`
3739

3840
// localAddressEndpoint is the local address this route is associated with.
3941
// +checklocks:mu

pkg/tcpip/transport/tcp/endpoint.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -418,7 +418,8 @@ type Endpoint struct {
418418
isPortReserved bool
419419
isRegistered bool
420420
boundNICID tcpip.NICID
421-
route *stack.Route `state:"nosave"`
421+
route *stack.Route
422+
restoreConn bool
422423
ipv4TTL uint8
423424
ipv6HopLimit int16
424425
isConnectNotified bool

pkg/tcpip/transport/tcp/endpoint_state.go

Lines changed: 45 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ var logDisconnectOnce sync.Once
3333

3434
func logDisconnect() {
3535
logDisconnectOnce.Do(func() {
36-
log.Infof("One or more TCP connections terminated during save")
36+
log.Infof("One or more TCP connections terminated during restore")
3737
})
3838
}
3939

@@ -49,13 +49,7 @@ func (e *Endpoint) beforeSave() {
4949
switch {
5050
case epState == StateInitial || epState == StateBound:
5151
case epState.connected() || epState.handshake():
52-
if !e.route.HasSaveRestoreCapability() {
53-
logDisconnect()
54-
e.resetConnectionLocked(&tcpip.ErrConnectionAborted{})
55-
e.mu.Unlock()
56-
e.Close()
57-
e.mu.Lock()
58-
}
52+
e.restoreConn = e.route.HasSaveRestoreCapability()
5953
fallthrough
6054
case epState == StateListen:
6155
// Nothing to do.
@@ -133,6 +127,28 @@ func (e *Endpoint) afterLoad(ctx context.Context) {
133127
}
134128
}
135129

130+
func (e *Endpoint) releaseOldRoute() {
131+
e.mu.Lock()
132+
defer e.mu.Unlock()
133+
134+
if e.route != nil {
135+
e.route.Release()
136+
e.route = nil
137+
}
138+
}
139+
140+
func (e *Endpoint) closeAtRestore() {
141+
e.mu.Lock()
142+
logDisconnect()
143+
e.resetConnectionLocked(&tcpip.ErrConnectionAborted{})
144+
// Update the origEndpointState to error as it will be used during restore.
145+
e.origEndpointState = uint32(StateError)
146+
e.mu.Unlock()
147+
e.Close()
148+
e.stack.CompleteTransportEndpointCleanup(e)
149+
tcpip.DeleteDanglingEndpoint(e)
150+
}
151+
136152
// Restore implements tcpip.RestoredEndpoint.Restore.
137153
func (e *Endpoint) Restore(s *stack.Stack) {
138154
if !e.EndpointState().closed() {
@@ -154,6 +170,7 @@ func (e *Endpoint) Restore(s *stack.Stack) {
154170

155171
e.mu.Lock()
156172
id := e.ID
173+
restoreConn := e.restoreConn
157174
e.mu.Unlock()
158175

159176
bind := func() {
@@ -186,6 +203,13 @@ func (e *Endpoint) Restore(s *stack.Stack) {
186203
epState := EndpointState(e.origEndpointState)
187204
switch {
188205
case epState.connected():
206+
if !restoreConn {
207+
e.closeAtRestore()
208+
connectedLoading.Done()
209+
return
210+
}
211+
e.releaseOldRoute()
212+
189213
bind()
190214
if e.connectingAddress.BitLen() == 0 {
191215
e.connectingAddress = e.TransportEndpointInfo.ID.RemoteAddress
@@ -254,6 +278,7 @@ func (e *Endpoint) Restore(s *stack.Stack) {
254278
tcpip.AsyncLoading.Done()
255279
}()
256280
} else {
281+
e.releaseOldRoute()
257282
go func() {
258283
connectedLoading.Wait()
259284
e.LockUser()
@@ -269,6 +294,7 @@ func (e *Endpoint) Restore(s *stack.Stack) {
269294
}()
270295
}
271296
case epState == StateConnecting:
297+
e.releaseOldRoute()
272298
// Initial SYN hasn't been sent yet so initiate a connect.
273299
tcpip.AsyncLoading.Add(1)
274300
go func() {
@@ -288,6 +314,16 @@ func (e *Endpoint) Restore(s *stack.Stack) {
288314
go func() {
289315
connectedLoading.Wait()
290316
listenLoading.Wait()
317+
318+
// Handshake phase.
319+
if !restoreConn {
320+
e.closeAtRestore()
321+
connectingLoading.Done()
322+
tcpip.AsyncLoading.Done()
323+
return
324+
}
325+
e.releaseOldRoute()
326+
291327
// Initial SYN has been sent/received so we should bind the
292328
// ports start the retransmit timer for the SYNs and let it
293329
// naturally complete the connection.
@@ -314,6 +350,7 @@ func (e *Endpoint) Restore(s *stack.Stack) {
314350
e.mu.Unlock()
315351
}()
316352
case epState == StateBound:
353+
e.releaseOldRoute()
317354
tcpip.AsyncLoading.Add(1)
318355
go func() {
319356
connectedLoading.Wait()

0 commit comments

Comments
 (0)