Skip to content

Commit

Permalink
refactor
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 715454790
  • Loading branch information
nybidari authored and gvisor-bot committed Jan 22, 2025
1 parent 50731e5 commit 628c553
Show file tree
Hide file tree
Showing 18 changed files with 572 additions and 166 deletions.
8 changes: 0 additions & 8 deletions pkg/sentry/inet/inet.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,14 +100,6 @@ type Stack interface {
// Restore restarts the network stack after restore.
Restore()

// ReplaceConfig replaces the new network stack configuration to the
// loaded or saved network stack after restore.
// TODO(b/379115439): This method is a workaround to update netstack config
// during restore. It should be removed after a new method is added to
// extract the complete config from the spec and update it in the loaded
// stack during restore.
ReplaceConfig(st Stack)

// Destroy the network stack.
Destroy()

Expand Down
2 changes: 1 addition & 1 deletion pkg/sentry/inet/namespace.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ type Namespace struct {
//
// At afterLoad(), creator will be used to create network stack. Stateify
// needs to wait for this field to be loaded before calling afterLoad().
creator NetworkStackCreator `state:"wait"`
creator NetworkStackCreator `state:"nosave"`

// isRoot indicates whether this is the root network namespace.
isRoot bool
Expand Down
8 changes: 0 additions & 8 deletions pkg/sentry/kernel/kernel.go
Original file line number Diff line number Diff line change
Expand Up @@ -836,14 +836,6 @@ func (k *Kernel) LoadFrom(ctx context.Context, r, pagesMetadata io.Reader, pages

if saveRestoreNet {
log.Infof("netstack save restore is enabled")
s := k.rootNetworkNamespace.Stack()
if s == nil {
panic("inet.Stack cannot be nil when netstack s/r is enabled")
}
if net != nil {
s.ReplaceConfig(net)
}
s.Restore()
} else if net != nil {
net.Restore()
}
Expand Down
3 changes: 0 additions & 3 deletions pkg/sentry/socket/hostinet/stack.go
Original file line number Diff line number Diff line change
Expand Up @@ -398,9 +398,6 @@ func (*Stack) Pause() {}
// Restore implements inet.Stack.Restore.
func (*Stack) Restore() {}

// ReplaceConfig implements inet.Stack.ReplaceConfig.
func (s *Stack) ReplaceConfig(_ inet.Stack) {}

// Resume implements inet.Stack.Resume.
func (*Stack) Resume() {}

Expand Down
12 changes: 3 additions & 9 deletions pkg/sentry/socket/netstack/stack.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"gvisor.dev/gvisor/pkg/log"
"gvisor.dev/gvisor/pkg/refs"
"gvisor.dev/gvisor/pkg/sentry/inet"
"gvisor.dev/gvisor/pkg/sentry/socket/netfilter"
"gvisor.dev/gvisor/pkg/sentry/socket/netlink/nlmsg"
"gvisor.dev/gvisor/pkg/syserr"
"gvisor.dev/gvisor/pkg/tcpip"
Expand Down Expand Up @@ -922,15 +923,8 @@ func (s *Stack) Pause() {

// Restore implements inet.Stack.Restore.
func (s *Stack) Restore() {
s.Stack.Restore()
}

// ReplaceConfig implements inet.Stack.ReplaceConfig.
func (s *Stack) ReplaceConfig(st inet.Stack) {
if _, ok := st.(*Stack); !ok {
panic("netstack.Stack cannot be nil when netstack s/r is enabled")
}
s.Stack.ReplaceConfig(st.(*Stack).Stack)
defaultIPTables := netfilter.DefaultLinuxTables
s.Stack.Restore(defaultIPTables)
}

// Resume implements inet.Stack.Resume.
Expand Down
4 changes: 4 additions & 0 deletions pkg/tcpip/stack/save_restore.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,14 @@ import (
"time"

cryptorand "gvisor.dev/gvisor/pkg/rand"
"gvisor.dev/gvisor/pkg/tcpip"
)

// afterLoad is invoked by stateify.
func (s *Stack) afterLoad(context.Context) {
s.insecureRNG = rand.New(rand.NewSource(time.Now().UnixNano()))
s.secureRNG = cryptorand.RNGFrom(cryptorand.Reader)
s.mu.Lock()
s.nics = make(map[tcpip.NICID]*nic)
s.mu.Unlock()
}
34 changes: 3 additions & 31 deletions pkg/tcpip/stack/stack.go
Original file line number Diff line number Diff line change
Expand Up @@ -1966,45 +1966,17 @@ func (s *Stack) Pause() {
}
}

func (s *Stack) getNICs() map[tcpip.NICID]*nic {
s.mu.RLock()
defer s.mu.RUnlock()

nics := s.nics
return nics
}

// ReplaceConfig replaces config in the loaded stack.
func (s *Stack) ReplaceConfig(st *Stack) {
if st == nil {
panic("stack.Stack cannot be nil when netstack s/r is enabled")
}

// Update route table.
s.SetRouteTable(st.GetRouteTable())

// Update NICs.
nics := st.getNICs()
s.mu.Lock()
defer s.mu.Unlock()
s.nics = make(map[tcpip.NICID]*nic)
for id, nic := range nics {
nic.stack = s
s.nics[id] = nic
_ = s.NextNICID()
}
s.tables = st.tables
}

// Restore restarts the stack after a restore. This must be called after the
// entire system has been restored.
func (s *Stack) Restore() {
func (s *Stack) Restore(defaultIPTables func(clock tcpip.Clock, rand *rand.Rand) *IPTables) {
// RestoredEndpoint.Restore() may call other methods on s, so we can't hold
// s.mu while restoring the endpoints.
s.mu.Lock()
eps := s.restoredEndpoints
s.restoredEndpoints = nil
saveRestoreEnabled := s.saveRestoreEnabled
s.icmpRateLimiter = NewICMPRateLimiter(s.clock)
s.tables = defaultIPTables(s.clock, s.insecureRNG)
s.mu.Unlock()
for _, e := range eps {
e.Restore(s)
Expand Down
8 changes: 8 additions & 0 deletions runsc/boot/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,13 @@ go_library(
"loader.go",
"mount_hints.go",
"network.go",
"no_xdp.go",
"restore.go",
"restore_impl.go",
"seccheck.go",
"strace.go",
"vfs.go",
"xdp.go",
],
visibility = [
"//pkg/test:__subpackages__",
Expand Down Expand Up @@ -125,17 +127,23 @@ go_library(
"//pkg/tcpip/transport/tcp",
"//pkg/tcpip/transport/udp",
"//pkg/urpc",
"//pkg/xdp",
"//runsc/boot/filter",
"//runsc/boot/portforward",
"//runsc/boot/pprof",
"//runsc/boot/procfs",
"//runsc/config",
"//runsc/profile",
"//runsc/sandbox/bpf",
"//runsc/specutils",
"//runsc/specutils/seccomp",
"//runsc/version",
"//tools/xdp/cmd",
"@com_github_cilium_ebpf//:go_default_library",
"@com_github_cilium_ebpf//link:go_default_library",
"@com_github_opencontainers_runtime_spec//specs-go:go_default_library",
"@com_github_syndtr_gocapability//capability:go_default_library",
"@com_github_vishvananda_netlink//:go_default_library",
"@org_golang_google_protobuf//proto:go_default_library",
"@org_golang_x_sys//unix:go_default_library",
],
Expand Down
13 changes: 13 additions & 0 deletions runsc/boot/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,10 @@ const (

// ContMgrContainerRuntimeState returns the runtime state of a container.
ContMgrContainerRuntimeState = "containerManager.ContainerRuntimeState"

// ContMgrStoreNetworkConfig stores the network config which are required
// during restore in the loader.
ContMgrStoreNetworkConfig = "containerManager.StoreNetworkConfig"
)

const (
Expand All @@ -131,6 +135,9 @@ const (

// DebugStacks collects sandbox stacks for debugging.
DebugStacks = "debug.Stacks"

// NetworkSetupNetwork sets up network stack.
NetworkSetupNetwork = "Network.SetupNetwork"
)

// Profiling related commands (see pprof.go for more details).
Expand Down Expand Up @@ -943,3 +950,9 @@ func (cm *containerManager) ContainerRuntimeState(cid *string, state *ContainerR
*state = cm.l.containerRuntimeState(*cid)
return nil
}

// StoreNetworkConfig stores the network config in the loader.
func (cm *containerManager) StoreNetworkConfig(netConf *NetworkConfig, _ *struct{}) error {
cm.l.netConf = netConf
return nil
}
13 changes: 13 additions & 0 deletions runsc/boot/loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"encoding/json"
"errors"
"fmt"
"net"
"os"
"runtime"
"strconv"
Expand Down Expand Up @@ -255,6 +256,18 @@ type Loader struct {
// saveRestoreNet indicates if the saved network stack should be used
// during restore.
saveRestoreNet bool

// netConf contains the network configuration required during restore.
netConf *NetworkConfig
}

// NetworkConfig contains the network config.
type NetworkConfig struct {
Args *CreateLinksAndRoutesArgs
InitArgs *InitPluginStackArgs
Iface net.Interface
Network config.NetworkType
XDPMode config.XDPMode
}

// execID uniquely identifies a sentry process that is executed in a container.
Expand Down
36 changes: 36 additions & 0 deletions runsc/boot/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -605,3 +605,39 @@ func ipMaskToAddressMask(ipMask net.IPMask) tcpip.AddressMask {
addr := ipToAddress(net.IP(ipMask))
return tcpip.MaskFromBytes(addr.AsSlice())
}

func (n *Network) SetupNetworkSandbox(netConf *NetworkConfig, _ *struct{}) error {
switch netConf.XDPMode {
case config.XDPModeOff:
case config.XDPModeNS:
case config.XDPModeRedirect:
if err := n.SetupXDPModeRedirect(netConf, nil); err != nil {
return fmt.Errorf("failed to create XDP tunnel interface: %w", err)
}
return nil
case config.XDPModeTunnel:
if err := n.SetupXDPModeTunnel(netConf, nil); err != nil {
return fmt.Errorf("failed to create XDP tunnel interface: %w", err)
}
return nil
default:
return fmt.Errorf("unknown XDP mode: %v", netConf.XDPMode)
}
return n.CreateLinksAndRoutes(netConf.Args, nil)
}

func (n *Network) SetupNetwork(netConf *NetworkConfig, _ *struct{}) error {
switch netConf.Network {
case config.NetworkNone:
return n.CreateLinksAndRoutes(netConf.Args, nil)
case config.NetworkHost:
/* nothing to do */
return nil
case config.NetworkPlugin:
return n.InitPluginStack(netConf.InitArgs, nil)
case config.NetworkSandbox:
return n.SetupNetworkSandbox(netConf, nil)
default:
return fmt.Errorf("unknown network type")
}
}
42 changes: 42 additions & 0 deletions runsc/boot/no_xdp.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Copyright 2025 The gVisor Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//go:build !xdp
// +build !xdp

package boot

import (
"errors"
"net"
"os"
)

// This file holds placeholders for XDP support, which is not compiled in by default.
//
// To enable XDP support, build gVisor with `--define=gotags=xdp`.

const noXDPMsg = "XDP support was not built into this release -- rebuild with --define=gotags=xdp"

func (n *Network) SetupXDPModeRedirect(netConf *NetworkConfig, _ *struct{}) error {
return errors.New(noXDPMsg)
}

func createSocketXDP(iface net.Interface) ([]*os.File, error) {
return nil, errors.New(noXDPMsg)
}

func (n *Network) SetupXDPModeTunnel(netConf *NetworkConfig, _ *struct{}) error {
return errors.New(noXDPMsg)
}
20 changes: 20 additions & 0 deletions runsc/boot/restore.go
Original file line number Diff line number Diff line change
Expand Up @@ -708,12 +708,32 @@ func (r *restorer) restore(l *Loader, unsafeSkipRestoreSpecValidation bool) erro

l.kernelInitExtra()

if eps, ok := l.k.RootNetworkNamespace().Stack().(*netstack.Stack); ok {
// The network stack will be loaded from the state file, we do
// not need this network stack anymore.
oldInetStack.Destroy()

n := &Network{
Stack: eps.Stack,
}
log.Infof("network config: %+v", l.netConf)
if err := n.SetupNetwork(l.netConf, nil); err != nil {
return fmt.Errorf("restore network error: %w", err)
}
} else {
l.k.RootNetworkNamespace().RestoreRootStack(hostinet.NewStack())
}

// Refresh the control server with the newly created kernel.
l.ctrl.refreshHandlers()

// Release `l.mu` before calling into callbacks.
cu.Clean()

if _, ok := l.k.RootNetworkNamespace().Stack().(*netstack.Stack); ok {
l.k.RootNetworkNamespace().Stack().Restore()
}

// r.restoreDone() signals and waits for the sandbox to start.
if err := r.restoreDone(); err != nil {
return fmt.Errorf("restorer.restoreDone callback failed: %w", err)
Expand Down
Loading

0 comments on commit 628c553

Please sign in to comment.