Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion pkg/network/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ const (

var netlog = logrus.WithField("subsystem", "network")

// ErrNoContainerNetwork is returned when the current network namespace has no
// suitable container interface (e.g. ctr without networking, or --network none).
// Callers may treat this as a non-fatal condition and continue without guest networking.
var ErrNoContainerNetwork = errors.New("no suitable network interface found in namespace")

type UnikernelNetworkInfo struct {
TapDevice string
EthDevice Interface
Expand Down Expand Up @@ -403,7 +408,7 @@ func discoverContainerIface() (netlink.Link, error) {
}
netlog.Debugf("skipping interface %s: no default route found", attrs.Name)
}
return nil, errors.New("no suitable network interface found in namespace")
return nil, ErrNoContainerNetwork
}

func deleteAllQDiscs(device netlink.Link) error {
Expand Down
3 changes: 1 addition & 2 deletions pkg/network/network_static.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,7 @@ func (n StaticNetwork) NetworkSetup(uid uint32, gid uint32) (*UnikernelNetworkIn
addTCRules := false
redirectLink, err := discoverContainerIface()
if err != nil {
netlog.Errorf("failed to find container interface, (unikernel may have been spawned using ctr): %v", err)
return nil, err
return nil, fmt.Errorf("failed to find container interface, (unikernel may have been spawned using ctr): %w", err)
}
newTapDevice, err := networkSetup(newTapName, StaticIPAddr, redirectLink, addTCRules, uid, gid)
if err != nil {
Expand Down
12 changes: 12 additions & 0 deletions pkg/network/network_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
package network

import (
"errors"
"fmt"
"testing"

"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -56,3 +58,13 @@ func TestNewNetworkManager(t *testing.T) {
})
}
}

func TestErrNoContainerNetworkIsDetectableWhenWrapped(t *testing.T) {
t.Parallel()

wrapped := fmt.Errorf("failed to find container interface, (unikernel may have been spawned using ctr): %w", ErrNoContainerNetwork)
assert.True(t, errors.Is(wrapped, ErrNoContainerNetwork))

other := fmt.Errorf("createTapDevice(tap0_urunc) failed: %w", errors.New("permission denied"))
assert.False(t, errors.Is(other, ErrNoContainerNetwork))
}
34 changes: 17 additions & 17 deletions pkg/unikontainers/unikontainers.go
Original file line number Diff line number Diff line change
Expand Up @@ -266,23 +266,23 @@ func (u *Unikontainer) SetupNet() (types.NetDevParams, error) {

networkInfo, err := netManager.NetworkSetup(u.Spec.Process.User.UID, u.Spec.Process.User.GID)
if err != nil {
// TODO: Handle this case better. We do not need to show an error
// since there was no network in the container. Therefore, we
// need better error handling and specifically check if the container
// di not have any network.
uniklog.Errorf("Failed to setup network :%v. Possibly due to ctr", err)
}
// if network info is nil, we didn't find eth0, so we are running with ctr
if networkInfo != nil {
netArgs.TapDev = networkInfo.TapDevice
netArgs.IP = networkInfo.EthDevice.IP
netArgs.Mask = networkInfo.EthDevice.Mask
netArgs.Gateway = networkInfo.EthDevice.DefaultGateway
// The MAC address for the guest network device is the same as the
// virtual ethernet interface inside the namespace
netArgs.MAC = networkInfo.EthDevice.MAC
netArgs.MTU = networkInfo.EthDevice.MTU
}
// No container interface means there is no network to set up (e.g. ctr
// without CNI, or --network none). Continue without guest networking.
// Any other failure (TAP creation, TC rules, etc.) is fatal.
if errors.Is(err, network.ErrNoContainerNetwork) {
uniklog.Debugf("no container network interface found, continuing without network: %v", err)
return netArgs, nil
}
return netArgs, fmt.Errorf("failed to setup network: %w", err)
}
netArgs.TapDev = networkInfo.TapDevice
netArgs.IP = networkInfo.EthDevice.IP
netArgs.Mask = networkInfo.EthDevice.Mask
netArgs.Gateway = networkInfo.EthDevice.DefaultGateway
// The MAC address for the guest network device is the same as the
// virtual ethernet interface inside the namespace
netArgs.MAC = networkInfo.EthDevice.MAC
netArgs.MTU = networkInfo.EthDevice.MTU

return netArgs, nil
}
Expand Down