Skip to content

Commit e51dca4

Browse files
nybidarigvisor-bot
authored andcommitted
Remove old NICs and routes during save/restore.
During restore there will be new NICs and routes created based on the network config. Close these old NICs and routes in beforeSave() only for save/restore. For save/resume, do not close them. As new link endpoints are created during restore, there is no need to start the associated old processor goroutines in afterLoad. Start them only for save/resume. PiperOrigin-RevId: 804994281
1 parent d6ba994 commit e51dca4

File tree

9 files changed

+78
-3
lines changed

9 files changed

+78
-3
lines changed

pkg/sentry/inet/inet.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,10 @@ type Stack interface {
140140

141141
// Stats returns the network stats.
142142
Stats() tcpip.Stats
143+
144+
// SetRemoveNICs sets removeNICs in stack to true. This should only be
145+
// called during save/restore.
146+
SetRemoveNICs()
143147
}
144148

145149
// Interface contains information about a network interface.

pkg/sentry/inet/test_stack.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,3 +241,8 @@ func (*TestStack) Stats() tcpip.Stats {
241241
// No-op.
242242
return tcpip.Stats{}
243243
}
244+
245+
// SetRemoveNICs implements Stack.
246+
func (*TestStack) SetRemoveNICs() {
247+
// No-op.
248+
}

pkg/sentry/kernel/kernel.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ import (
8080
"gvisor.dev/gvisor/pkg/sentry/vfs"
8181
"gvisor.dev/gvisor/pkg/state"
8282
"gvisor.dev/gvisor/pkg/sync"
83+
"gvisor.dev/gvisor/pkg/tcpip/stack"
8384
)
8485

8586
// IOUringEnabled is set to true when IO_URING is enabled. Added as a global to
@@ -613,7 +614,7 @@ func savePrivateMFs(ctx context.Context, w io.Writer, pw io.Writer, mfsToSave ma
613614
// SaveTo saves the state of k to w.
614615
//
615616
// Preconditions: The kernel must be paused throughout the call to SaveTo.
616-
func (k *Kernel) SaveTo(ctx context.Context, w, pagesMetadata io.Writer, pagesFile *fd.FD, mfOpts pgalloc.SaveOpts) error {
617+
func (k *Kernel) SaveTo(ctx context.Context, w, pagesMetadata io.Writer, pagesFile *fd.FD, mfOpts pgalloc.SaveOpts, resume bool) error {
617618
saveStart := time.Now()
618619

619620
// Do not allow other Kernel methods to affect it while it's being saved.
@@ -681,6 +682,11 @@ func (k *Kernel) SaveTo(ctx context.Context, w, pagesMetadata io.Writer, pagesFi
681682
if rootNS := k.rootNetworkNamespace; rootNS != nil && rootNS.Stack() != nil {
682683
// Pause the network stack.
683684
netstackPauseStart := time.Now()
685+
if resume {
686+
ctx = context.WithValue(ctx, stack.CtxResumeStack, resume)
687+
} else {
688+
k.rootNetworkNamespace.Stack().SetRemoveNICs()
689+
}
684690
log.Infof("Pausing root network namespace")
685691
k.rootNetworkNamespace.Stack().Pause()
686692
defer k.rootNetworkNamespace.Stack().Resume()

pkg/sentry/socket/hostinet/stack.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -443,3 +443,8 @@ func (s *Stack) IsSaveRestoreEnabled() bool {
443443
func (s *Stack) Stats() tcpip.Stats {
444444
return tcpip.Stats{}
445445
}
446+
447+
// SetRemoveNICs implements inet.Stack.SetRemoveNICs.
448+
func (*Stack) SetRemoveNICs() {
449+
// No-op.
450+
}

pkg/sentry/socket/netstack/stack.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -970,3 +970,8 @@ func (s *Stack) PortRange() (uint16, uint16) {
970970
func (s *Stack) SetPortRange(start uint16, end uint16) error {
971971
return syserr.TranslateNetstackError(s.Stack.SetPortRange(start, end)).ToError()
972972
}
973+
974+
// SetRemoveNICs implements inet.Stack.SetRemoveNICs.
975+
func (s *Stack) SetRemoveNICs() {
976+
s.Stack.SetRemoveNICs()
977+
}

pkg/sentry/state/state.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ func (opts SaveOpts) Save(ctx context.Context, k *kernel.Kernel, w *watchdog.Wat
110110
}
111111

112112
// Save the kernel.
113-
err = k.SaveTo(ctx, wc, pagesMetadata, opts.PagesFile, opts.MemoryFileSaveOpts)
113+
err = k.SaveTo(ctx, wc, pagesMetadata, opts.PagesFile, opts.MemoryFileSaveOpts, opts.Resume)
114114

115115
// ENOSPC is a state file error. This error can only come from
116116
// writing the state file, and not from fs.FileOperations.Fsync

pkg/tcpip/link/fdbased/processors.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,13 @@ func (m *processorManager) start() {
127127
}
128128

129129
// afterLoad is invoked by stateify.
130-
func (m *processorManager) afterLoad(context.Context) {
130+
func (m *processorManager) afterLoad(ctx context.Context) {
131+
// Do not start the processors for save/restore. New NICs and
132+
// processors will be created during restore.
133+
resume := stack.ResumeStackFromContext(ctx)
134+
if !resume {
135+
return
136+
}
131137
m.wg.Add(len(m.processors))
132138
m.start()
133139
}
@@ -276,6 +282,7 @@ func (m *processorManager) wakeReady() {
276282
}
277283
}
278284

285+
// beforeSave is invoked by stateify.
279286
func (m *processorManager) beforeSave() {
280287
m.close()
281288
m.wg.Wait()

pkg/tcpip/stack/save_restore.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,31 @@ import (
2222
cryptorand "gvisor.dev/gvisor/pkg/rand"
2323
)
2424

25+
// beforeSave is invoked by stateify.
26+
func (s *Stack) beforeSave() {
27+
// removeNICs will be set only in case of save/restore.
28+
s.mu.Lock()
29+
if !s.removeNICs {
30+
s.mu.Unlock()
31+
return
32+
}
33+
34+
// Remove all the NICs and routes from the stack as they will be
35+
// created again during restore based on the new network config.
36+
deferActs := make([]func(), 0)
37+
for id := range s.nics {
38+
act, _ := s.removeNICLocked(id)
39+
if act != nil {
40+
deferActs = append(deferActs, act)
41+
}
42+
}
43+
s.mu.Unlock()
44+
45+
for _, act := range deferActs {
46+
act()
47+
}
48+
}
49+
2550
// afterLoad is invoked by stateify.
2651
func (s *Stack) afterLoad(context.Context) {
2752
s.insecureRNG = rand.New(rand.NewSource(time.Now().UnixNano()))

pkg/tcpip/stack/stack.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,9 @@ type Stack struct {
185185

186186
// saveRestoreEnabled indicates whether the stack is saved and restored.
187187
saveRestoreEnabled bool
188+
189+
// removeNICs indicates if the NICs and routes should be removed before saving.
190+
removeNICs bool `state:"nosave"`
188191
}
189192

190193
// NetworkProtocolFactory instantiates a network protocol.
@@ -2518,9 +2521,24 @@ type contextID int
25182521
const (
25192522
// CtxRestoreStack is a Context.Value key for the stack to be used in restore.
25202523
CtxRestoreStack contextID = iota
2524+
2525+
// CtxResumeStack is a Context.Value key for the stack to be used in resume.
2526+
CtxResumeStack contextID = iota
25212527
)
25222528

25232529
// RestoreStackFromContext returns the stack to be used during restore.
25242530
func RestoreStackFromContext(ctx context.Context) *Stack {
25252531
return ctx.Value(CtxRestoreStack).(*Stack)
25262532
}
2533+
2534+
// ResumeStackFromContext returns the stack to be used during restore.
2535+
func ResumeStackFromContext(ctx context.Context) bool {
2536+
return ctx.Value(CtxResumeStack).(bool)
2537+
}
2538+
2539+
// SetRemoveNICs sets the removeNICs in stack to true during save/restore.
2540+
func (s *Stack) SetRemoveNICs() {
2541+
s.mu.Lock()
2542+
defer s.mu.Unlock()
2543+
s.removeNICs = true
2544+
}

0 commit comments

Comments
 (0)