runtime: delete netmon

Netmon is not used anymore.

Fixes: #3112

Signed-off-by: bin <bin@hyper.sh>
This commit is contained in:
bin 2021-11-24 15:08:18 +08:00
parent ac058b3897
commit ddc68131df
24 changed files with 2 additions and 1895 deletions

View File

@ -11,7 +11,6 @@ config-generated.go
/pkg/containerd-shim-v2/monitor_address
/data/kata-collect-data.sh
/kata-monitor
/kata-netmon
/kata-runtime
/pkg/katautils/config-settings.go
/virtcontainers/hack/virtc/virtc

View File

@ -55,11 +55,6 @@ RUNTIME_OUTPUT = $(CURDIR)/$(TARGET)
RUNTIME_DIR = $(CLI_DIR)/$(TARGET)
BINLIST += $(TARGET)
NETMON_DIR = $(CLI_DIR)/netmon
NETMON_TARGET = $(PROJECT_TYPE)-netmon
NETMON_RUNTIME_OUTPUT = $(CURDIR)/$(NETMON_TARGET)
BINLIBEXECLIST += $(NETMON_TARGET)
DESTDIR ?= /
ifeq ($(PREFIX),)
@ -142,9 +137,6 @@ ACRNVALIDHYPERVISORPATHS := [\"$(ACRNPATH)\"]
ACRNCTLPATH := $(ACRNBINDIR)/$(ACRNCTLCMD)
ACRNVALIDCTLPATHS := [\"$(ACRNCTLPATH)\"]
NETMONCMD := $(BIN_PREFIX)-netmon
NETMONPATH := $(PKGLIBEXECDIR)/$(NETMONCMD)
# Default number of vCPUs
DEFVCPUS := 1
# Default maximum number of vCPUs
@ -416,7 +408,6 @@ USER_VARS += PROJECT_PREFIX
USER_VARS += PROJECT_TAG
USER_VARS += PROJECT_TYPE
USER_VARS += PROJECT_URL
USER_VARS += NETMONPATH
USER_VARS += QEMUBINDIR
USER_VARS += QEMUCMD
USER_VARS += QEMUPATH
@ -509,7 +500,7 @@ define SHOW_ARCH
$(shell printf "\\t%s%s\\\n" "$(1)" $(if $(filter $(ARCH),$(1))," (default)",""))
endef
all: runtime containerd-shim-v2 netmon monitor
all: runtime containerd-shim-v2 monitor
# Targets that depend on .git-commit can use $(shell cat .git-commit) to get a
# git revision string. They will only be rebuilt if the revision string
@ -525,11 +516,6 @@ containerd-shim-v2: $(SHIMV2_OUTPUT)
monitor: $(MONITOR_OUTPUT)
netmon: $(NETMON_RUNTIME_OUTPUT)
$(NETMON_RUNTIME_OUTPUT): $(SOURCES) VERSION
$(QUIET_BUILD)(cd $(NETMON_DIR) && go build $(BUILDFLAGS) -o $@ -ldflags "-X main.version=$(VERSION)" $(KATA_LDFLAGS))
runtime: $(RUNTIME_OUTPUT) $(CONFIGS)
.DEFAULT: default
@ -638,15 +624,13 @@ coverage:
go test -v -mod=vendor -covermode=atomic -coverprofile=coverage.txt ./...
go tool cover -html=coverage.txt -o coverage.html
install: all install-runtime install-containerd-shim-v2 install-monitor install-netmon
install: all install-runtime install-containerd-shim-v2 install-monitor
install-bin: $(BINLIST)
$(QUIET_INST)$(foreach f,$(BINLIST),$(call INSTALL_EXEC,$f,$(BINDIR)))
install-runtime: runtime install-scripts install-completions install-configs install-bin
install-netmon: install-bin-libexec
install-containerd-shim-v2: $(SHIMV2)
$(QUIET_INST)$(call INSTALL_EXEC,$<,$(BINDIR))
@ -678,7 +662,6 @@ clean:
$(QUIET_CLEAN)rm -f \
$(CONFIGS) \
$(GENERATED_FILES) \
$(NETMON_TARGET) \
$(MONITOR) \
$(SHIMV2) \
$(TARGET) \
@ -706,9 +689,7 @@ show-usage: show-header
@printf "\tgenerate-config : create configuration file.\n"
@printf "\tinstall : install everything.\n"
@printf "\tinstall-containerd-shim-v2 : only install containerd shim v2 files.\n"
@printf "\tinstall-netmon : only install netmon files.\n"
@printf "\tinstall-runtime : only install runtime files.\n"
@printf "\tnetmon : only build netmon.\n"
@printf "\truntime : only build runtime.\n"
@printf "\tshow-arches : show supported architectures (ARCH variable values).\n"
@printf "\tshow-summary : show install locations.\n"

View File

@ -140,14 +140,6 @@ type HostInfo struct {
SupportVSocks bool
}
// NetmonInfo stores netmon details
type NetmonInfo struct {
Path string
Version VersionInfo
Debug bool
Enable bool
}
// EnvInfo collects all information that will be displayed by the
// env command.
//
@ -159,7 +151,6 @@ type EnvInfo struct {
Initrd InitrdInfo
Hypervisor HypervisorInfo
Runtime RuntimeInfo
Netmon NetmonInfo
Host HostInfo
Agent AgentInfo
}
@ -276,26 +267,6 @@ func getMemoryInfo() MemoryInfo {
}
}
func getNetmonInfo(config oci.RuntimeConfig) NetmonInfo {
netmonConfig := config.NetmonConfig
var netmonVersionInfo VersionInfo
if version, err := getCommandVersion(netmonConfig.Path); err != nil {
netmonVersionInfo = unknownVersionInfo
} else {
netmonVersionInfo = constructVersionInfo(version)
}
netmon := NetmonInfo{
Version: netmonVersionInfo,
Path: netmonConfig.Path,
Debug: netmonConfig.Debug,
Enable: netmonConfig.Enable,
}
return netmon
}
func getCommandVersion(cmd string) (string, error) {
return utils.RunCommand([]string{cmd, "--version"})
}
@ -364,8 +335,6 @@ func getEnvInfo(configFile string, config oci.RuntimeConfig) (env EnvInfo, err e
return EnvInfo{}, err
}
netmon := getNetmonInfo(config)
agent, err := getAgentInfo(config)
if err != nil {
return EnvInfo{}, err
@ -398,7 +367,6 @@ func getEnvInfo(configFile string, config oci.RuntimeConfig) (env EnvInfo, err e
Initrd: initrd,
Agent: agent,
Host: host,
Netmon: netmon,
}
return env, nil

View File

@ -32,7 +32,6 @@ import (
)
var (
testNetmonVersion = "netmon version 0.1"
testHypervisorVersion = "QEMU emulator version 2.7.0+git.741f430a96-6.1, Copyright (c) 2003-2016 Fabrice Bellard and the QEMU Project developers"
)
@ -41,7 +40,6 @@ var (
enableVirtioFS = false
runtimeDebug = false
runtimeTrace = false
netmonDebug = false
agentDebug = false
agentTrace = false
)
@ -83,7 +81,6 @@ func makeRuntimeConfig(prefixDir string) (configFile string, config oci.RuntimeC
imagePath := filepath.Join(prefixDir, "image")
kernelParams := "foo=bar xyz"
machineType := "machineType"
netmonPath := filepath.Join(prefixDir, "netmon")
disableBlock := true
blockStorageDriver := "virtio-scsi"
enableIOThreads := true
@ -107,11 +104,6 @@ func makeRuntimeConfig(prefixDir string) (configFile string, config oci.RuntimeC
}
}
err = makeVersionBinary(netmonPath, testNetmonVersion)
if err != nil {
return "", oci.RuntimeConfig{}, err
}
err = makeVersionBinary(hypervisorPath, testHypervisorVersion)
if err != nil {
return "", oci.RuntimeConfig{}, err
@ -130,7 +122,6 @@ func makeRuntimeConfig(prefixDir string) (configFile string, config oci.RuntimeC
ImagePath: imagePath,
KernelParams: kernelParams,
MachineType: machineType,
NetmonPath: netmonPath,
LogPath: logPath,
DefaultGuestHookPath: hypConfig.GuestHookPath,
DisableBlock: disableBlock,
@ -146,7 +137,6 @@ func makeRuntimeConfig(prefixDir string) (configFile string, config oci.RuntimeC
HypervisorDebug: hypervisorDebug,
RuntimeDebug: runtimeDebug,
RuntimeTrace: runtimeTrace,
NetmonDebug: netmonDebug,
AgentDebug: agentDebug,
AgentTrace: agentTrace,
SharedFS: sharedFS,
@ -169,15 +159,6 @@ func makeRuntimeConfig(prefixDir string) (configFile string, config oci.RuntimeC
return configFile, config, nil
}
func getExpectedNetmonDetails(config oci.RuntimeConfig) (NetmonInfo, error) {
return NetmonInfo{
Version: constructVersionInfo(testNetmonVersion),
Path: config.NetmonConfig.Path,
Debug: config.NetmonConfig.Debug,
Enable: config.NetmonConfig.Enable,
}, nil
}
func getExpectedAgentDetails(config oci.RuntimeConfig) (AgentInfo, error) {
agentConfig := config.AgentConfig
@ -352,11 +333,6 @@ func getExpectedSettings(config oci.RuntimeConfig, tmpdir, configFile string) (E
return EnvInfo{}, err
}
netmon, err := getExpectedNetmonDetails(config)
if err != nil {
return EnvInfo{}, err
}
hypervisor := getExpectedHypervisor(config)
kernel := getExpectedKernel(config)
image := getExpectedImage(config)
@ -369,7 +345,6 @@ func getExpectedSettings(config oci.RuntimeConfig, tmpdir, configFile string) (E
Kernel: kernel,
Agent: agent,
Host: host,
Netmon: netmon,
}
return env, nil
@ -612,50 +587,6 @@ func TestEnvGetRuntimeInfo(t *testing.T) {
assert.Equal(t, expectedRuntime, runtime)
}
func TestEnvGetNetmonInfo(t *testing.T) {
tmpdir, err := ioutil.TempDir("", "")
if err != nil {
panic(err)
}
defer os.RemoveAll(tmpdir)
_, config, err := makeRuntimeConfig(tmpdir)
assert.NoError(t, err)
expectedNetmon, err := getExpectedNetmonDetails(config)
assert.NoError(t, err)
netmon := getNetmonInfo(config)
assert.NoError(t, err)
assert.Equal(t, expectedNetmon, netmon)
}
func TestEnvGetNetmonInfoNoVersion(t *testing.T) {
tmpdir, err := ioutil.TempDir("", "")
if err != nil {
panic(err)
}
defer os.RemoveAll(tmpdir)
_, config, err := makeRuntimeConfig(tmpdir)
assert.NoError(t, err)
expectedNetmon, err := getExpectedNetmonDetails(config)
assert.NoError(t, err)
// remove the netmon ensuring its version cannot be queried
err = os.Remove(config.NetmonConfig.Path)
assert.NoError(t, err)
expectedNetmon.Version = unknownVersionInfo
netmon := getNetmonInfo(config)
assert.NoError(t, err)
assert.Equal(t, expectedNetmon, netmon)
}
func TestEnvGetAgentInfo(t *testing.T) {
tmpdir, err := ioutil.TempDir("", "")
if err != nil {

View File

@ -1,683 +0,0 @@
// Copyright (c) 2018 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0
//
package main
import (
"encoding/json"
"errors"
"flag"
"fmt"
"io/ioutil"
"log/syslog"
"net"
"os"
"os/exec"
"os/signal"
"path/filepath"
"strings"
"syscall"
"time"
"github.com/kata-containers/kata-containers/src/runtime/pkg/signals"
pbTypes "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/agent/protocols"
"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/utils"
"github.com/sirupsen/logrus"
lSyslog "github.com/sirupsen/logrus/hooks/syslog"
"github.com/vishvananda/netlink"
"golang.org/x/sys/unix"
)
const (
netmonName = "kata-netmon"
kataCmd = "kata-network"
kataCLIAddIfaceCmd = "add-iface"
kataCLIDelIfaceCmd = "del-iface"
kataCLIUpdtRoutesCmd = "update-routes"
kataSuffix = "kata"
// sharedFile is the name of the file that will be used to share
// the data between this process and the kata-runtime process
// responsible for updating the network.
sharedFile = "shared.json"
storageFilePerm = os.FileMode(0640)
storageDirPerm = os.FileMode(0750)
)
var (
// version is the netmon version. This variable is populated at build time.
version = "unknown"
// For simplicity the code will only focus on IPv4 addresses for now.
netlinkFamily = netlink.FAMILY_ALL
storageParentPath = "/var/run/kata-containers/netmon/sbs"
)
type netmonParams struct {
sandboxID string
runtimePath string
logLevel string
debug bool
}
type netmon struct {
netIfaces map[int]pbTypes.Interface
linkUpdateCh chan netlink.LinkUpdate
linkDoneCh chan struct{}
rtUpdateCh chan netlink.RouteUpdate
rtDoneCh chan struct{}
netHandler *netlink.Handle
storagePath string
sharedFile string
netmonParams
}
var netmonLog = logrus.New()
func printVersion() {
fmt.Printf("%s version %s\n", netmonName, version)
}
const componentDescription = `is a network monitoring process that is intended to be started in the
appropriate network namespace so that it can listen to any event related to
link and routes. Whenever a new interface or route is created/updated, it is
responsible for calling into the kata-runtime CLI to ask for the actual
creation/update of the given interface or route.
`
func printComponentDescription() {
fmt.Printf("\n%s %s\n", netmonName, componentDescription)
}
func parseOptions() netmonParams {
var version, help bool
params := netmonParams{}
flag.BoolVar(&help, "h", false, "describe component usage")
flag.BoolVar(&help, "help", false, "")
flag.BoolVar(&params.debug, "d", false, "enable debug mode")
flag.BoolVar(&version, "v", false, "display program version and exit")
flag.BoolVar(&version, "version", false, "")
flag.StringVar(&params.sandboxID, "s", "", "sandbox id (required)")
flag.StringVar(&params.runtimePath, "r", "", "runtime path (required)")
flag.StringVar(&params.logLevel, "log", "warn",
"log messages above specified level: debug, warn, error, fatal or panic")
flag.Parse()
if help {
printComponentDescription()
flag.PrintDefaults()
os.Exit(0)
}
if version {
printVersion()
os.Exit(0)
}
if params.sandboxID == "" {
fmt.Fprintf(os.Stderr, "Error: sandbox id is empty, one must be provided\n")
flag.PrintDefaults()
os.Exit(1)
}
if params.runtimePath == "" {
fmt.Fprintf(os.Stderr, "Error: runtime path is empty, one must be provided\n")
flag.PrintDefaults()
os.Exit(1)
}
return params
}
func newNetmon(params netmonParams) (*netmon, error) {
handler, err := netlink.NewHandle(netlinkFamily)
if err != nil {
return nil, err
}
n := &netmon{
netmonParams: params,
storagePath: filepath.Join(storageParentPath, params.sandboxID),
sharedFile: filepath.Join(storageParentPath, params.sandboxID, sharedFile),
netIfaces: make(map[int]pbTypes.Interface),
linkUpdateCh: make(chan netlink.LinkUpdate),
linkDoneCh: make(chan struct{}),
rtUpdateCh: make(chan netlink.RouteUpdate),
rtDoneCh: make(chan struct{}),
netHandler: handler,
}
if err := os.MkdirAll(n.storagePath, storageDirPerm); err != nil {
return nil, err
}
return n, nil
}
func (n *netmon) cleanup() {
os.RemoveAll(n.storagePath)
n.netHandler.Close()
close(n.linkDoneCh)
close(n.rtDoneCh)
}
// setupSignalHandler sets up signal handling, starting a go routine to deal
// with signals as they arrive.
func (n *netmon) setupSignalHandler() {
signals.SetLogger(n.logger())
sigCh := make(chan os.Signal, 8)
for _, sig := range signals.HandledSignals() {
signal.Notify(sigCh, sig)
}
go func() {
for {
sig := <-sigCh
nativeSignal, ok := sig.(syscall.Signal)
if !ok {
err := errors.New("unknown signal")
netmonLog.WithError(err).WithField("signal", sig.String()).Error()
continue
}
if signals.FatalSignal(nativeSignal) {
netmonLog.WithField("signal", sig).Error("received fatal signal")
signals.Die(nil)
} else if n.debug && signals.NonFatalSignal(nativeSignal) {
netmonLog.WithField("signal", sig).Debug("handling signal")
signals.Backtrace()
}
}
}()
}
func (n *netmon) logger() *logrus.Entry {
fields := logrus.Fields{
"name": netmonName,
"pid": os.Getpid(),
"source": "netmon",
}
if n.sandboxID != "" {
fields["sandbox"] = n.sandboxID
}
return netmonLog.WithFields(fields)
}
func (n *netmon) setupLogger() error {
level, err := logrus.ParseLevel(n.logLevel)
if err != nil {
return err
}
netmonLog.SetLevel(level)
netmonLog.Formatter = &logrus.TextFormatter{TimestampFormat: time.RFC3339Nano}
hook, err := lSyslog.NewSyslogHook("", "", syslog.LOG_INFO|syslog.LOG_USER, netmonName)
if err != nil {
return err
}
netmonLog.AddHook(hook)
announceFields := logrus.Fields{
"runtime-path": n.runtimePath,
"debug": n.debug,
"log-level": n.logLevel,
}
n.logger().WithFields(announceFields).Info("announce")
return nil
}
func (n *netmon) listenNetlinkEvents() error {
if err := netlink.LinkSubscribe(n.linkUpdateCh, n.linkDoneCh); err != nil {
return err
}
return netlink.RouteSubscribe(n.rtUpdateCh, n.rtDoneCh)
}
// convertInterface converts a link and its IP addresses as defined by netlink
// package, into the Interface structure format expected by kata-runtime to
// describe an interface and its associated IP addresses.
func convertInterface(linkAttrs *netlink.LinkAttrs, linkType string, addrs []netlink.Addr) pbTypes.Interface {
if linkAttrs == nil {
netmonLog.Warn("Link attributes are nil")
return pbTypes.Interface{}
}
var ipAddrs []*pbTypes.IPAddress
for _, addr := range addrs {
if addr.IPNet == nil {
continue
}
netMask, _ := addr.Mask.Size()
ipAddr := &pbTypes.IPAddress{
Address: addr.IP.String(),
Mask: fmt.Sprintf("%d", netMask),
}
if addr.IP.To4() != nil {
ipAddr.Family = utils.ConvertNetlinkFamily(netlink.FAMILY_V4)
} else {
ipAddr.Family = utils.ConvertNetlinkFamily(netlink.FAMILY_V6)
}
ipAddrs = append(ipAddrs, ipAddr)
}
iface := pbTypes.Interface{
Device: linkAttrs.Name,
Name: linkAttrs.Name,
IPAddresses: ipAddrs,
Mtu: uint64(linkAttrs.MTU),
HwAddr: linkAttrs.HardwareAddr.String(),
Type: linkType,
}
netmonLog.WithField("interface", iface).Debug("Interface converted")
return iface
}
// convertRoutes converts a list of routes as defined by netlink package,
// into a list of Route structure format expected by kata-runtime to
// describe a set of routes.
func convertRoutes(netRoutes []netlink.Route) []pbTypes.Route {
var routes []pbTypes.Route
for _, netRoute := range netRoutes {
dst := ""
if netRoute.Protocol == unix.RTPROT_KERNEL {
continue
}
if netRoute.Dst != nil {
dst = netRoute.Dst.String()
if netRoute.Dst.IP.To4() != nil || netRoute.Dst.IP.To16() != nil {
dst = netRoute.Dst.String()
} else {
netmonLog.WithField("destination", netRoute.Dst.IP.String()).Warn("Unexpected network address format")
}
}
src := ""
if netRoute.Src != nil {
if netRoute.Src.To4() != nil || netRoute.Src.To16() != nil {
src = netRoute.Src.String()
} else {
netmonLog.WithField("source", netRoute.Src.String()).Warn("Unexpected network address format")
}
}
gw := ""
if netRoute.Gw != nil {
if netRoute.Gw.To4() != nil || netRoute.Gw.To16() != nil {
gw = netRoute.Gw.String()
} else {
netmonLog.WithField("gateway", netRoute.Gw.String()).Warn("Unexpected network address format")
}
}
dev := ""
iface, err := net.InterfaceByIndex(netRoute.LinkIndex)
if err == nil {
dev = iface.Name
}
route := pbTypes.Route{
Dest: dst,
Gateway: gw,
Device: dev,
Source: src,
Scope: uint32(netRoute.Scope),
}
routes = append(routes, route)
}
netmonLog.WithField("routes", routes).Debug("Routes converted")
return routes
}
// scanNetwork lists all the interfaces it can find inside the current
// network namespace, and store them in-memory to keep track of them.
func (n *netmon) scanNetwork() error {
links, err := n.netHandler.LinkList()
if err != nil {
return err
}
for _, link := range links {
addrs, err := n.netHandler.AddrList(link, netlinkFamily)
if err != nil {
return err
}
linkAttrs := link.Attrs()
if linkAttrs == nil {
continue
}
iface := convertInterface(linkAttrs, link.Type(), addrs)
n.netIfaces[linkAttrs.Index] = iface
}
n.logger().Debug("Network scanned")
return nil
}
func (n *netmon) storeDataToSend(data interface{}) error {
// Marshal the data structure into a JSON bytes array.
jsonArray, err := json.Marshal(data)
if err != nil {
return err
}
// Store the JSON bytes array at the specified path.
return ioutil.WriteFile(n.sharedFile, jsonArray, storageFilePerm)
}
func (n *netmon) execKataCmd(subCmd string) error {
execCmd := exec.Command(n.runtimePath, kataCmd, subCmd, n.sandboxID, n.sharedFile)
n.logger().WithField("command", execCmd).Debug("Running runtime command")
// Make use of Run() to ensure the kata-runtime process has correctly
// terminated before to go further.
if err := execCmd.Run(); err != nil {
return err
}
// Remove the shared file after the command returned. At this point
// we know the content of the file is not going to be used anymore,
// and the file path can be reused for further commands.
return os.Remove(n.sharedFile)
}
func (n *netmon) addInterfaceCLI(iface pbTypes.Interface) error {
if err := n.storeDataToSend(iface); err != nil {
return err
}
return n.execKataCmd(kataCLIAddIfaceCmd)
}
func (n *netmon) delInterfaceCLI(iface pbTypes.Interface) error {
if err := n.storeDataToSend(iface); err != nil {
return err
}
return n.execKataCmd(kataCLIDelIfaceCmd)
}
func (n *netmon) updateRoutesCLI(routes []pbTypes.Route) error {
if err := n.storeDataToSend(routes); err != nil {
return err
}
return n.execKataCmd(kataCLIUpdtRoutesCmd)
}
func (n *netmon) updateRoutes() error {
// Get all the routes.
netlinkRoutes, err := n.netHandler.RouteList(nil, netlinkFamily)
if err != nil {
return err
}
// Translate them into Route structures.
routes := convertRoutes(netlinkRoutes)
// Update the routes through the Kata CLI.
return n.updateRoutesCLI(routes)
}
func (n *netmon) handleRTMNewAddr(ev netlink.LinkUpdate) error {
n.logger().Debug("Interface update not supported")
return nil
}
func (n *netmon) handleRTMDelAddr(ev netlink.LinkUpdate) error {
n.logger().Debug("Interface update not supported")
return nil
}
func (n *netmon) handleRTMNewLink(ev netlink.LinkUpdate) error {
// NEWLINK might be a lot of different things. We're interested in
// adding the interface (both to our list and by calling into the
// Kata CLI API) only if this has the flags UP and RUNNING, meaning
// we don't expect any further change on the interface, and that we
// are ready to add it.
linkAttrs := ev.Link.Attrs()
if linkAttrs == nil {
n.logger().Warn("The link attributes are nil")
return nil
}
// First, ignore if the interface name contains "kata". This way we
// are preventing from adding interfaces created by Kata Containers.
if strings.HasSuffix(linkAttrs.Name, kataSuffix) {
n.logger().Debugf("Ignore the interface %s because found %q",
linkAttrs.Name, kataSuffix)
return nil
}
// Check if the interface exist in the internal list.
if _, exist := n.netIfaces[int(ev.Index)]; exist {
n.logger().Debugf("Ignoring interface %s because already exist",
linkAttrs.Name)
return nil
}
// Now, check if the interface has been enabled to UP and RUNNING.
if (ev.Flags&unix.IFF_UP) != unix.IFF_UP ||
(ev.Flags&unix.IFF_RUNNING) != unix.IFF_RUNNING {
n.logger().Debugf("Ignore the interface %s because not UP and RUNNING",
linkAttrs.Name)
return nil
}
// Get the list of IP addresses associated with this interface.
addrs, err := n.netHandler.AddrList(ev.Link, netlinkFamily)
if err != nil {
return err
}
// Convert the interfaces in the appropriate structure format.
iface := convertInterface(linkAttrs, ev.Link.Type(), addrs)
// Add the interface through the Kata CLI.
if err := n.addInterfaceCLI(iface); err != nil {
return err
}
// Add the interface to the internal list.
n.netIfaces[linkAttrs.Index] = iface
// Complete by updating the routes.
return n.updateRoutes()
}
func (n *netmon) handleRTMDelLink(ev netlink.LinkUpdate) error {
// It can only delete if identical interface is found in the internal
// list of interfaces. Otherwise, the deletion will be ignored.
linkAttrs := ev.Link.Attrs()
if linkAttrs == nil {
n.logger().Warn("Link attributes are nil")
return nil
}
// First, ignore if the interface name contains "kata". This way we
// are preventing from deleting interfaces created by Kata Containers.
if strings.Contains(linkAttrs.Name, kataSuffix) {
n.logger().Debugf("Ignore the interface %s because found %q",
linkAttrs.Name, kataSuffix)
return nil
}
// Check if the interface exist in the internal list.
iface, exist := n.netIfaces[int(ev.Index)]
if !exist {
n.logger().Debugf("Ignoring interface %s because not found",
linkAttrs.Name)
return nil
}
if err := n.delInterfaceCLI(iface); err != nil {
return err
}
// Delete the interface from the internal list.
delete(n.netIfaces, linkAttrs.Index)
// Complete by updating the routes.
return n.updateRoutes()
}
func (n *netmon) handleRTMNewRoute(ev netlink.RouteUpdate) error {
// Add the route through updateRoutes(), only if the route refer to an
// interface that already exists in the internal list of interfaces.
if _, exist := n.netIfaces[ev.Route.LinkIndex]; !exist {
n.logger().Debugf("Ignoring route %+v since interface %d not found",
ev.Route, ev.Route.LinkIndex)
return nil
}
return n.updateRoutes()
}
func (n *netmon) handleRTMDelRoute(ev netlink.RouteUpdate) error {
// Remove the route through updateRoutes(), only if the route refer to
// an interface that already exists in the internal list of interfaces.
return n.updateRoutes()
}
func (n *netmon) handleLinkEvent(ev netlink.LinkUpdate) error {
n.logger().Debug("handleLinkEvent: netlink event received")
switch ev.Header.Type {
case unix.NLMSG_DONE:
n.logger().Debug("NLMSG_DONE")
return nil
case unix.NLMSG_ERROR:
n.logger().Error("NLMSG_ERROR")
return fmt.Errorf("Error while listening on netlink socket")
case unix.RTM_NEWADDR:
n.logger().Debug("RTM_NEWADDR")
return n.handleRTMNewAddr(ev)
case unix.RTM_DELADDR:
n.logger().Debug("RTM_DELADDR")
return n.handleRTMDelAddr(ev)
case unix.RTM_NEWLINK:
n.logger().Debug("RTM_NEWLINK")
return n.handleRTMNewLink(ev)
case unix.RTM_DELLINK:
n.logger().Debug("RTM_DELLINK")
return n.handleRTMDelLink(ev)
default:
n.logger().Warnf("Unknown msg type %v", ev.Header.Type)
}
return nil
}
func (n *netmon) handleRouteEvent(ev netlink.RouteUpdate) error {
n.logger().Debug("handleRouteEvent: netlink event received")
switch ev.Type {
case unix.RTM_NEWROUTE:
n.logger().Debug("RTM_NEWROUTE")
return n.handleRTMNewRoute(ev)
case unix.RTM_DELROUTE:
n.logger().Debug("RTM_DELROUTE")
return n.handleRTMDelRoute(ev)
default:
n.logger().Warnf("Unknown msg type %v", ev.Type)
}
return nil
}
func (n *netmon) handleEvents() (err error) {
for {
select {
case ev := <-n.linkUpdateCh:
if err = n.handleLinkEvent(ev); err != nil {
return err
}
case ev := <-n.rtUpdateCh:
if err = n.handleRouteEvent(ev); err != nil {
return err
}
}
}
}
func main() {
// Parse parameters.
params := parseOptions()
// Create netmon handler.
n, err := newNetmon(params)
if err != nil {
netmonLog.WithError(err).Fatal("newNetmon()")
os.Exit(1)
}
defer n.cleanup()
// Init logger.
if err := n.setupLogger(); err != nil {
netmonLog.WithError(err).Fatal("setupLogger()")
os.Exit(1)
}
// Setup signal handlers
n.setupSignalHandler()
// Scan the current interfaces.
if err := n.scanNetwork(); err != nil {
n.logger().WithError(err).Fatal("scanNetwork()")
os.Exit(1)
}
// Subscribe to the link listener.
if err := n.listenNetlinkEvents(); err != nil {
n.logger().WithError(err).Fatal("listenNetlinkEvents()")
os.Exit(1)
}
// Go into the main loop.
if err := n.handleEvents(); err != nil {
n.logger().WithError(err).Fatal("handleEvents()")
os.Exit(1)
}
}

View File

@ -1,701 +0,0 @@
// Copyright (c) 2018 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0
//
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"net"
"os"
"os/exec"
"path/filepath"
"reflect"
"runtime"
"testing"
ktu "github.com/kata-containers/kata-containers/src/runtime/pkg/katatestutils"
pbTypes "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/agent/protocols"
"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/utils"
"github.com/sirupsen/logrus"
"github.com/stretchr/testify/assert"
"github.com/vishvananda/netlink"
"github.com/vishvananda/netns"
"golang.org/x/sys/unix"
)
const (
testSandboxID = "123456789"
testRuntimePath = "/foo/bar/test-runtime"
testLogLevel = "info"
testStorageParentPath = "/tmp/netmon"
testSharedFile = "foo-shared.json"
testWrongNetlinkFamily = -1
testIfaceName = "test_eth0"
testMTU = 12345
testHwAddr = "02:00:ca:fe:00:48"
testIPAddress = "192.168.0.15"
testIPAddressWithMask = "192.168.0.15/32"
testIP6Address = "2001:db8:1::242:ac11:2"
testIP6AddressWithMask = "2001:db8:1::/64"
testScope = 1
testTxQLen = -1
testIfaceIndex = 5
)
func skipUnlessRoot(t *testing.T) {
tc := ktu.NewTestConstraint(false)
if tc.NotValid(ktu.NeedRoot()) {
t.Skip("Test disabled as requires root user")
}
}
func TestNewNetmon(t *testing.T) {
skipUnlessRoot(t)
// Override storageParentPath
savedStorageParentPath := storageParentPath
storageParentPath = testStorageParentPath
defer func() {
storageParentPath = savedStorageParentPath
}()
params := netmonParams{
sandboxID: testSandboxID,
runtimePath: testRuntimePath,
debug: true,
logLevel: testLogLevel,
}
expected := &netmon{
netmonParams: params,
storagePath: filepath.Join(storageParentPath, params.sandboxID),
sharedFile: filepath.Join(storageParentPath, params.sandboxID, sharedFile),
}
os.RemoveAll(expected.storagePath)
got, err := newNetmon(params)
assert.Nil(t, err)
assert.True(t, reflect.DeepEqual(expected.netmonParams, got.netmonParams),
"Got %+v\nExpected %+v", got.netmonParams, expected.netmonParams)
assert.True(t, reflect.DeepEqual(expected.storagePath, got.storagePath),
"Got %+v\nExpected %+v", got.storagePath, expected.storagePath)
assert.True(t, reflect.DeepEqual(expected.sharedFile, got.sharedFile),
"Got %+v\nExpected %+v", got.sharedFile, expected.sharedFile)
_, err = os.Stat(got.storagePath)
assert.Nil(t, err)
os.RemoveAll(got.storagePath)
}
func TestNewNetmonErrorWrongFamilyType(t *testing.T) {
// Override netlinkFamily
savedNetlinkFamily := netlinkFamily
netlinkFamily = testWrongNetlinkFamily
defer func() {
netlinkFamily = savedNetlinkFamily
}()
n, err := newNetmon(netmonParams{})
assert.NotNil(t, err)
assert.Nil(t, n)
}
func TestCleanup(t *testing.T) {
skipUnlessRoot(t)
// Override storageParentPath
savedStorageParentPath := storageParentPath
storageParentPath = testStorageParentPath
defer func() {
storageParentPath = savedStorageParentPath
}()
handler, err := netlink.NewHandle(netlinkFamily)
assert.Nil(t, err)
n := &netmon{
storagePath: filepath.Join(storageParentPath, testSandboxID),
linkDoneCh: make(chan struct{}),
rtDoneCh: make(chan struct{}),
netHandler: handler,
}
err = os.MkdirAll(n.storagePath, storageDirPerm)
assert.Nil(t, err)
_, err = os.Stat(n.storagePath)
assert.Nil(t, err)
n.cleanup()
_, err = os.Stat(n.storagePath)
assert.NotNil(t, err)
_, ok := (<-n.linkDoneCh)
assert.False(t, ok)
_, ok = (<-n.rtDoneCh)
assert.False(t, ok)
}
func TestLogger(t *testing.T) {
fields := logrus.Fields{
"name": netmonName,
"pid": os.Getpid(),
"source": "netmon",
"sandbox": testSandboxID,
}
expected := netmonLog.WithFields(fields)
n := &netmon{
netmonParams: netmonParams{
sandboxID: testSandboxID,
},
}
got := n.logger()
assert.True(t, reflect.DeepEqual(*expected, *got),
"Got %+v\nExpected %+v", *got, *expected)
}
func TestConvertInterface(t *testing.T) {
hwAddr, err := net.ParseMAC(testHwAddr)
assert.Nil(t, err)
addrs := []netlink.Addr{
{
IPNet: &net.IPNet{
IP: net.ParseIP(testIPAddress),
},
},
{
IPNet: &net.IPNet{
IP: net.ParseIP(testIP6Address),
},
},
}
linkAttrs := &netlink.LinkAttrs{
Name: testIfaceName,
MTU: testMTU,
HardwareAddr: hwAddr,
}
linkType := "link_type_test"
expected := pbTypes.Interface{
Device: testIfaceName,
Name: testIfaceName,
Mtu: uint64(testMTU),
HwAddr: testHwAddr,
IPAddresses: []*pbTypes.IPAddress{
{
Family: utils.ConvertNetlinkFamily(netlink.FAMILY_V4),
Address: testIPAddress,
Mask: "0",
},
{
Family: utils.ConvertNetlinkFamily(netlink.FAMILY_V6),
Address: testIP6Address,
Mask: "0",
},
},
Type: linkType,
}
got := convertInterface(linkAttrs, linkType, addrs)
assert.True(t, reflect.DeepEqual(expected, got),
"Got %+v\nExpected %+v", got, expected)
}
func TestConvertRoutes(t *testing.T) {
ip, ipNet, err := net.ParseCIDR(testIPAddressWithMask)
assert.Nil(t, err)
assert.NotNil(t, ipNet)
_, ip6Net, err := net.ParseCIDR(testIP6AddressWithMask)
assert.Nil(t, err)
assert.NotNil(t, ipNet)
routes := []netlink.Route{
{
Dst: ipNet,
Src: ip,
Gw: ip,
LinkIndex: -1,
Scope: testScope,
},
{
Dst: ip6Net,
Src: nil,
Gw: nil,
LinkIndex: -1,
Scope: testScope,
},
}
expected := []pbTypes.Route{
{
Dest: testIPAddressWithMask,
Gateway: testIPAddress,
Source: testIPAddress,
Scope: uint32(testScope),
},
{
Dest: testIP6AddressWithMask,
Gateway: "",
Source: "",
Scope: uint32(testScope),
},
}
got := convertRoutes(routes)
assert.True(t, reflect.DeepEqual(expected, got),
"Got %+v\nExpected %+v", got, expected)
}
type testTeardownNetwork func()
func testSetupNetwork(t *testing.T) testTeardownNetwork {
skipUnlessRoot(t)
// new temporary namespace so we don't pollute the host
// lock thread since the namespace is thread local
runtime.LockOSThread()
var err error
ns, err := netns.New()
if err != nil {
t.Fatal("Failed to create newns", ns)
}
return func() {
ns.Close()
runtime.UnlockOSThread()
}
}
func testCreateDummyNetwork(t *testing.T, handler *netlink.Handle) (int, pbTypes.Interface) {
hwAddr, err := net.ParseMAC(testHwAddr)
assert.Nil(t, err)
link := &netlink.Dummy{
LinkAttrs: netlink.LinkAttrs{
MTU: testMTU,
TxQLen: testTxQLen,
Name: testIfaceName,
HardwareAddr: hwAddr,
},
}
err = handler.LinkAdd(link)
assert.Nil(t, err)
err = handler.LinkSetUp(link)
assert.Nil(t, err)
attrs := link.Attrs()
assert.NotNil(t, attrs)
addrs, err := handler.AddrList(link, netlinkFamily)
assert.Nil(t, err)
var ipAddrs []*pbTypes.IPAddress
// Scan addresses for ipv6 link local address which is automatically assigned
for _, addr := range addrs {
if addr.IPNet == nil {
continue
}
netMask, _ := addr.Mask.Size()
ipAddr := &pbTypes.IPAddress{
Address: addr.IP.String(),
Mask: fmt.Sprintf("%d", netMask),
}
if addr.IP.To4() != nil {
ipAddr.Family = utils.ConvertNetlinkFamily(netlink.FAMILY_V4)
} else {
ipAddr.Family = utils.ConvertNetlinkFamily(netlink.FAMILY_V6)
}
ipAddrs = append(ipAddrs, ipAddr)
}
iface := pbTypes.Interface{
Device: testIfaceName,
Name: testIfaceName,
Mtu: uint64(testMTU),
HwAddr: testHwAddr,
Type: link.Type(),
IPAddresses: ipAddrs,
}
return attrs.Index, iface
}
func TestScanNetwork(t *testing.T) {
tearDownNetworkCb := testSetupNetwork(t)
defer tearDownNetworkCb()
handler, err := netlink.NewHandle(netlinkFamily)
assert.Nil(t, err)
assert.NotNil(t, handler)
defer handler.Close()
idx, expected := testCreateDummyNetwork(t, handler)
n := &netmon{
netIfaces: make(map[int]pbTypes.Interface),
netHandler: handler,
}
err = n.scanNetwork()
assert.Nil(t, err)
assert.True(t, reflect.DeepEqual(expected, n.netIfaces[idx]),
"Got %+v\nExpected %+v", n.netIfaces[idx], expected)
}
func TestStoreDataToSend(t *testing.T) {
var got pbTypes.Interface
expected := pbTypes.Interface{
Device: testIfaceName,
Name: testIfaceName,
Mtu: uint64(testMTU),
HwAddr: testHwAddr,
}
n := &netmon{
sharedFile: filepath.Join(testStorageParentPath, testSharedFile),
}
err := os.MkdirAll(testStorageParentPath, storageDirPerm)
defer os.RemoveAll(testStorageParentPath)
assert.Nil(t, err)
err = n.storeDataToSend(expected)
assert.Nil(t, err)
// Check the file has been created, check the content, and delete it.
_, err = os.Stat(n.sharedFile)
assert.Nil(t, err)
byteArray, err := ioutil.ReadFile(n.sharedFile)
assert.Nil(t, err)
err = json.Unmarshal(byteArray, &got)
assert.Nil(t, err)
assert.True(t, reflect.DeepEqual(expected, got),
"Got %+v\nExpected %+v", got, expected)
}
func TestExecKataCmdSuccess(t *testing.T) {
trueBinPath, err := exec.LookPath("true")
assert.Nil(t, err)
assert.NotEmpty(t, trueBinPath)
params := netmonParams{
runtimePath: trueBinPath,
}
n := &netmon{
netmonParams: params,
sharedFile: filepath.Join(testStorageParentPath, testSharedFile),
}
err = os.MkdirAll(testStorageParentPath, storageDirPerm)
assert.Nil(t, err)
defer os.RemoveAll(testStorageParentPath)
file, err := os.Create(n.sharedFile)
assert.Nil(t, err)
assert.NotNil(t, file)
file.Close()
_, err = os.Stat(n.sharedFile)
assert.Nil(t, err)
err = n.execKataCmd("")
assert.Nil(t, err)
_, err = os.Stat(n.sharedFile)
assert.NotNil(t, err)
}
func TestExecKataCmdFailure(t *testing.T) {
falseBinPath, err := exec.LookPath("false")
assert.Nil(t, err)
assert.NotEmpty(t, falseBinPath)
params := netmonParams{
runtimePath: falseBinPath,
}
n := &netmon{
netmonParams: params,
}
err = n.execKataCmd("")
assert.NotNil(t, err)
}
func TestActionsCLI(t *testing.T) {
trueBinPath, err := exec.LookPath("true")
assert.Nil(t, err)
assert.NotEmpty(t, trueBinPath)
params := netmonParams{
runtimePath: trueBinPath,
}
n := &netmon{
netmonParams: params,
sharedFile: filepath.Join(testStorageParentPath, testSharedFile),
}
err = os.MkdirAll(testStorageParentPath, storageDirPerm)
assert.Nil(t, err)
defer os.RemoveAll(testStorageParentPath)
// Test addInterfaceCLI
err = n.addInterfaceCLI(pbTypes.Interface{})
assert.Nil(t, err)
// Test delInterfaceCLI
err = n.delInterfaceCLI(pbTypes.Interface{})
assert.Nil(t, err)
// Test updateRoutesCLI
err = n.updateRoutesCLI([]pbTypes.Route{})
assert.Nil(t, err)
tearDownNetworkCb := testSetupNetwork(t)
defer tearDownNetworkCb()
handler, err := netlink.NewHandle(netlinkFamily)
assert.Nil(t, err)
assert.NotNil(t, handler)
defer handler.Close()
n.netHandler = handler
// Test updateRoutes
err = n.updateRoutes()
assert.Nil(t, err)
// Test handleRTMDelRoute
err = n.handleRTMDelRoute(netlink.RouteUpdate{})
assert.Nil(t, err)
}
func TestHandleRTMNewAddr(t *testing.T) {
n := &netmon{}
err := n.handleRTMNewAddr(netlink.LinkUpdate{})
assert.Nil(t, err)
}
func TestHandleRTMDelAddr(t *testing.T) {
n := &netmon{}
err := n.handleRTMDelAddr(netlink.LinkUpdate{})
assert.Nil(t, err)
}
func TestHandleRTMNewLink(t *testing.T) {
n := &netmon{}
ev := netlink.LinkUpdate{
Link: &netlink.Dummy{},
}
// LinkAttrs is nil
err := n.handleRTMNewLink(ev)
assert.Nil(t, err)
// Link name contains "kata" suffix
ev = netlink.LinkUpdate{
Link: &netlink.Dummy{
LinkAttrs: netlink.LinkAttrs{
Name: "foo_kata",
},
},
}
err = n.handleRTMNewLink(ev)
assert.Nil(t, err)
// Interface already exist in list
n.netIfaces = make(map[int]pbTypes.Interface)
n.netIfaces[testIfaceIndex] = pbTypes.Interface{}
ev = netlink.LinkUpdate{
Link: &netlink.Dummy{
LinkAttrs: netlink.LinkAttrs{
Name: "foo0",
},
},
}
ev.Index = testIfaceIndex
err = n.handleRTMNewLink(ev)
assert.Nil(t, err)
// Flags are not up and running
n.netIfaces = make(map[int]pbTypes.Interface)
ev = netlink.LinkUpdate{
Link: &netlink.Dummy{
LinkAttrs: netlink.LinkAttrs{
Name: "foo0",
},
},
}
ev.Index = testIfaceIndex
err = n.handleRTMNewLink(ev)
assert.Nil(t, err)
// Invalid link
n.netIfaces = make(map[int]pbTypes.Interface)
ev = netlink.LinkUpdate{
Link: &netlink.Dummy{
LinkAttrs: netlink.LinkAttrs{
Name: "foo0",
},
},
}
ev.Index = testIfaceIndex
ev.Flags = unix.IFF_UP | unix.IFF_RUNNING
handler, err := netlink.NewHandle(netlinkFamily)
assert.Nil(t, err)
assert.NotNil(t, handler)
defer handler.Close()
n.netHandler = handler
err = n.handleRTMNewLink(ev)
assert.NotNil(t, err)
}
func TestHandleRTMDelLink(t *testing.T) {
n := &netmon{}
ev := netlink.LinkUpdate{
Link: &netlink.Dummy{},
}
// LinkAttrs is nil
err := n.handleRTMDelLink(ev)
assert.Nil(t, err)
// Link name contains "kata" suffix
ev = netlink.LinkUpdate{
Link: &netlink.Dummy{
LinkAttrs: netlink.LinkAttrs{
Name: "foo_kata",
},
},
}
err = n.handleRTMDelLink(ev)
assert.Nil(t, err)
// Interface does not exist in list
n.netIfaces = make(map[int]pbTypes.Interface)
ev = netlink.LinkUpdate{
Link: &netlink.Dummy{
LinkAttrs: netlink.LinkAttrs{
Name: "foo0",
},
},
}
ev.Index = testIfaceIndex
err = n.handleRTMDelLink(ev)
assert.Nil(t, err)
}
func TestHandleRTMNewRouteIfaceNotFound(t *testing.T) {
n := &netmon{
netIfaces: make(map[int]pbTypes.Interface),
}
err := n.handleRTMNewRoute(netlink.RouteUpdate{})
assert.Nil(t, err)
}
func TestHandleLinkEvent(t *testing.T) {
n := &netmon{}
ev := netlink.LinkUpdate{}
// Unknown event
err := n.handleLinkEvent(ev)
assert.Nil(t, err)
// DONE event
ev.Header.Type = unix.NLMSG_DONE
err = n.handleLinkEvent(ev)
assert.Nil(t, err)
// ERROR event
ev.Header.Type = unix.NLMSG_ERROR
err = n.handleLinkEvent(ev)
assert.NotNil(t, err)
// NEWADDR event
ev.Header.Type = unix.RTM_NEWADDR
err = n.handleLinkEvent(ev)
assert.Nil(t, err)
// DELADDR event
ev.Header.Type = unix.RTM_DELADDR
err = n.handleLinkEvent(ev)
assert.Nil(t, err)
// NEWLINK event
ev.Header.Type = unix.RTM_NEWLINK
ev.Link = &netlink.Dummy{}
err = n.handleLinkEvent(ev)
assert.Nil(t, err)
// DELLINK event
ev.Header.Type = unix.RTM_DELLINK
ev.Link = &netlink.Dummy{}
err = n.handleLinkEvent(ev)
assert.Nil(t, err)
}
func TestHandleRouteEvent(t *testing.T) {
n := &netmon{}
ev := netlink.RouteUpdate{}
// Unknown event
err := n.handleRouteEvent(ev)
assert.Nil(t, err)
// RTM_NEWROUTE event
ev.Type = unix.RTM_NEWROUTE
err = n.handleRouteEvent(ev)
assert.Nil(t, err)
trueBinPath, err := exec.LookPath("true")
assert.Nil(t, err)
assert.NotEmpty(t, trueBinPath)
n.runtimePath = trueBinPath
n.sharedFile = filepath.Join(testStorageParentPath, testSharedFile)
err = os.MkdirAll(testStorageParentPath, storageDirPerm)
assert.Nil(t, err)
defer os.RemoveAll(testStorageParentPath)
tearDownNetworkCb := testSetupNetwork(t)
defer tearDownNetworkCb()
handler, err := netlink.NewHandle(netlinkFamily)
assert.Nil(t, err)
assert.NotNil(t, handler)
defer handler.Close()
n.netHandler = handler
// RTM_DELROUTE event
ev.Type = unix.RTM_DELROUTE
err = n.handleRouteEvent(ev)
assert.Nil(t, err)
}

View File

@ -147,21 +147,6 @@ block_device_driver = "@DEFBLOCKSTORAGEDRIVER_ACRN@"
# (default: 30)
#dial_timeout = 30
[netmon]
# If enabled, the network monitoring process gets started when the
# sandbox is created. This allows for the detection of some additional
# network being added to the existing network namespace, after the
# sandbox has been created.
# (default: disabled)
#enable_netmon = true
# Specify the path to the netmon binary.
path = "@NETMONPATH@"
# If enabled, netmon messages will be sent to the system log
# (default: disabled)
#enable_debug = true
[runtime]
# If enabled, the runtime will log additional debug messages to the
# system log
@ -217,7 +202,6 @@ disable_guest_seccomp=@DEFDISABLEGUESTSECCOMP@
# If enabled, the runtime will not create a network namespace for shim and hypervisor processes.
# This option may have some potential impacts to your host. It should only be used when you know what you're doing.
# `disable_new_netns` conflicts with `enable_netmon`
# `disable_new_netns` conflicts with `internetworking_model=bridged` and `internetworking_model=macvtap`. It works only
# with `internetworking_model=none`. The tap device will be in the host network namespace and can connect to a bridge
# (like OVS) directly.

View File

@ -169,22 +169,6 @@ block_device_driver = "virtio-blk"
# (default: 30)
#dial_timeout = 30
[netmon]
# If enabled, the network monitoring process gets started when the
# sandbox is created. This allows for the detection of some additional
# network being added to the existing network namespace, after the
# sandbox has been created.
# (default: disabled)
#enable_netmon = true
# Specify the path to the netmon binary.
path = "@NETMONPATH@"
# If enabled, netmon messages will be sent to the system log
# (default: disabled)
#enable_debug = true
[runtime]
# If enabled, the runtime will log additional debug messages to the
# system log
@ -240,7 +224,6 @@ disable_guest_seccomp=@DEFDISABLEGUESTSECCOMP@
# If enabled, the runtime will not create a network namespace for shim and hypervisor processes.
# This option may have some potential impacts to your host. It should only be used when you know what you're doing.
# `disable_new_netns` conflicts with `enable_netmon`
# `disable_new_netns` conflicts with `internetworking_model=bridged` and `internetworking_model=macvtap`. It works only
# with `internetworking_model=none`. The tap device will be in the host network namespace and can connect to a bridge
# (like OVS) directly.

View File

@ -282,21 +282,6 @@ kernel_modules=[]
# (default: 30)
#dial_timeout = 30
[netmon]
# If enabled, the network monitoring process gets started when the
# sandbox is created. This allows for the detection of some additional
# network being added to the existing network namespace, after the
# sandbox has been created.
# (default: disabled)
#enable_netmon = true
# Specify the path to the netmon binary.
path = "@NETMONPATH@"
# If enabled, netmon messages will be sent to the system log
# (default: disabled)
#enable_debug = true
[runtime]
# If enabled, the runtime will log additional debug messages to the
# system log
@ -345,7 +330,6 @@ disable_guest_seccomp=@DEFDISABLEGUESTSECCOMP@
# If enabled, the runtime will not create a network namespace for shim and hypervisor processes.
# This option may have some potential impacts to your host. It should only be used when you know what you're doing.
# `disable_new_netns` conflicts with `enable_netmon`
# `disable_new_netns` conflicts with `internetworking_model=tcfilter` and `internetworking_model=macvtap`. It works only
# with `internetworking_model=none`. The tap device will be in the host network namespace and can connect to a bridge
# (like OVS) directly.

View File

@ -458,21 +458,6 @@ kernel_modules=[]
# (default: 30)
#dial_timeout = 30
[netmon]
# If enabled, the network monitoring process gets started when the
# sandbox is created. This allows for the detection of some additional
# network being added to the existing network namespace, after the
# sandbox has been created.
# (default: disabled)
#enable_netmon = true
# Specify the path to the netmon binary.
path = "@NETMONPATH@"
# If enabled, netmon messages will be sent to the system log
# (default: disabled)
#enable_debug = true
[runtime]
# If enabled, the runtime will log additional debug messages to the
# system log
@ -521,7 +506,6 @@ disable_guest_seccomp=@DEFDISABLEGUESTSECCOMP@
# If enabled, the runtime will not create a network namespace for shim and hypervisor processes.
# This option may have some potential impacts to your host. It should only be used when you know what you're doing.
# `disable_new_netns` conflicts with `enable_netmon`
# `disable_new_netns` conflicts with `internetworking_model=tcfilter` and `internetworking_model=macvtap`. It works only
# with `internetworking_model=none`. The tap device will be in the host network namespace and can connect to a bridge
# (like OVS) directly.

View File

@ -328,7 +328,6 @@ func createAllRuntimeConfigFiles(dir, hypervisor string) (config string, err err
kernelParams := "foo=bar xyz"
imagePath := path.Join(dir, "image")
shimPath := path.Join(dir, "shim")
netmonPath := path.Join(dir, "netmon")
logDir := path.Join(dir, "logs")
logPath := path.Join(logDir, "runtime.log")
machineType := "machineType"
@ -349,7 +348,6 @@ func createAllRuntimeConfigFiles(dir, hypervisor string) (config string, err err
KernelParams: kernelParams,
MachineType: machineType,
ShimPath: shimPath,
NetmonPath: netmonPath,
LogPath: logPath,
DisableBlock: disableBlockDevice,
BlockDeviceDriver: blockDeviceDriver,

View File

@ -215,7 +215,6 @@ type RuntimeConfigOptions struct {
KernelParams string
MachineType string
ShimPath string
NetmonPath string
LogPath string
BlockDeviceDriver string
SharedFS string
@ -237,7 +236,6 @@ type RuntimeConfigOptions struct {
RuntimeDebug bool
RuntimeTrace bool
ShimDebug bool
NetmonDebug bool
AgentDebug bool
AgentTrace bool
EnablePprof bool
@ -331,10 +329,6 @@ func MakeRuntimeConfigFileData(config RuntimeConfigOptions) string {
enable_debug = ` + strconv.FormatBool(config.AgentDebug) + `
enable_tracing = ` + strconv.FormatBool(config.AgentTrace) + `
[netmon]
path = "` + config.NetmonPath + `"
enable_debug = ` + strconv.FormatBool(config.NetmonDebug) + `
[runtime]
enable_debug = ` + strconv.FormatBool(config.RuntimeDebug) + `
enable_tracing = ` + strconv.FormatBool(config.RuntimeTrace) + `

View File

@ -97,5 +97,3 @@ const defaultVMCacheEndpoint string = "/var/run/kata-containers/cache.sock"
// Default config file used by stateless systems.
var defaultRuntimeConfiguration = "@CONFIG_PATH@"
var defaultNetmonPath = "/usr/libexec/kata-containers/kata-netmon"

View File

@ -56,7 +56,6 @@ type tomlConfig struct {
Agent map[string]agent
Runtime runtime
Image image
Netmon netmon
Factory factory
}
@ -162,12 +161,6 @@ type agent struct {
DialTimeout uint32 `toml:"dial_timeout"`
}
type netmon struct {
Path string `toml:"path"`
Debug bool `toml:"enable_debug"`
Enable bool `toml:"enable_netmon"`
}
func (h hypervisor) path() (string, error) {
p := h.Path
@ -506,22 +499,6 @@ func (a agent) kernelModules() []string {
return a.KernelModules
}
func (n netmon) enable() bool {
return n.Enable
}
func (n netmon) path() string {
if n.Path == "" {
return defaultNetmonPath
}
return n.Path
}
func (n netmon) debug() bool {
return n.Debug
}
func newFirecrackerHypervisorConfig(h hypervisor) (vc.HypervisorConfig, error) {
hypervisor, err := h.path()
if err != nil {
@ -1014,12 +991,6 @@ func updateRuntimeConfig(configPath string, tomlConf tomlConfig, config *oci.Run
}
config.FactoryConfig = fConfig
config.NetmonConfig = vc.NetmonConfig{
Path: tomlConf.Netmon.path(),
Debug: tomlConf.Netmon.debug(),
Enable: tomlConf.Netmon.enable(),
}
err = SetKernelParams(config)
if err != nil {
return err
@ -1262,9 +1233,6 @@ func checkConfig(config oci.RuntimeConfig) error {
// Because it is an expert option and conflicts with some other common configs.
func checkNetNsConfig(config oci.RuntimeConfig) error {
if config.DisableNewNetNs {
if config.NetmonConfig.Enable {
return fmt.Errorf("config disable_new_netns conflicts with enable_netmon")
}
if config.InterNetworkModel != vc.NetXConnectNoneModel {
return fmt.Errorf("config disable_new_netns only works with 'none' internetworking_model")
}

View File

@ -29,7 +29,6 @@ var (
hypervisorDebug = false
runtimeDebug = false
runtimeTrace = false
netmonDebug = false
agentDebug = false
agentTrace = false
enablePprof = true
@ -74,7 +73,6 @@ func createAllRuntimeConfigFiles(dir, hypervisor string) (config testRuntimeConf
kernelPath := path.Join(dir, "kernel")
kernelParams := "foo=bar xyz"
imagePath := path.Join(dir, "image")
netmonPath := path.Join(dir, "netmon")
logDir := path.Join(dir, "logs")
logPath := path.Join(logDir, "runtime.log")
machineType := "machineType"
@ -95,7 +93,6 @@ func createAllRuntimeConfigFiles(dir, hypervisor string) (config testRuntimeConf
ImagePath: imagePath,
KernelParams: kernelParams,
MachineType: machineType,
NetmonPath: netmonPath,
LogPath: logPath,
DefaultGuestHookPath: defaultGuestHookPath,
DisableBlock: disableBlockDevice,
@ -111,7 +108,6 @@ func createAllRuntimeConfigFiles(dir, hypervisor string) (config testRuntimeConf
HypervisorDebug: hypervisorDebug,
RuntimeDebug: runtimeDebug,
RuntimeTrace: runtimeTrace,
NetmonDebug: netmonDebug,
AgentDebug: agentDebug,
AgentTrace: agentTrace,
SharedFS: sharedFS,
@ -180,12 +176,6 @@ func createAllRuntimeConfigFiles(dir, hypervisor string) (config testRuntimeConf
LongLiveConn: true,
}
netmonConfig := vc.NetmonConfig{
Path: netmonPath,
Debug: false,
Enable: false,
}
factoryConfig := oci.FactoryConfig{
TemplatePath: defaultTemplatePath,
VMCacheEndpoint: defaultVMCacheEndpoint,
@ -197,7 +187,6 @@ func createAllRuntimeConfigFiles(dir, hypervisor string) (config testRuntimeConf
AgentConfig: agentConfig,
NetmonConfig: netmonConfig,
DisableNewNetNs: disableNewNetNs,
EnablePprof: enablePprof,
JaegerEndpoint: jaegerEndpoint,
@ -493,7 +482,6 @@ func TestMinimalRuntimeConfig(t *testing.T) {
defaultHypervisorPath = hypervisorPath
jailerPath := path.Join(dir, "jailer")
defaultJailerPath = jailerPath
netmonPath := path.Join(dir, "netmon")
imagePath := path.Join(dir, "image.img")
initrdPath := path.Join(dir, "initrd.img")
@ -535,8 +523,6 @@ func TestMinimalRuntimeConfig(t *testing.T) {
[agent.kata]
debug_console_enabled=true
kernel_modules=["a", "b", "c"]
[netmon]
path = "` + netmonPath + `"
`
orgVHostVSockDevicePath := utils.VHostVSockDevicePath
@ -561,11 +547,6 @@ func TestMinimalRuntimeConfig(t *testing.T) {
t.Error(err)
}
err = createEmptyFile(netmonPath)
if err != nil {
t.Error(err)
}
_, config, err := LoadConfiguration(configPath, false)
if err != nil {
t.Fatal(err)
@ -597,12 +578,6 @@ func TestMinimalRuntimeConfig(t *testing.T) {
KernelModules: []string{"a", "b", "c"},
}
expectedNetmonConfig := vc.NetmonConfig{
Path: netmonPath,
Debug: false,
Enable: false,
}
expectedFactoryConfig := oci.FactoryConfig{
TemplatePath: defaultTemplatePath,
VMCacheEndpoint: defaultVMCacheEndpoint,
@ -614,8 +589,6 @@ func TestMinimalRuntimeConfig(t *testing.T) {
AgentConfig: expectedAgentConfig,
NetmonConfig: expectedNetmonConfig,
FactoryConfig: expectedFactoryConfig,
}
err = SetKernelParams(&expectedConfig)
@ -1553,9 +1526,6 @@ func TestCheckNetNsConfig(t *testing.T) {
config := oci.RuntimeConfig{
DisableNewNetNs: true,
NetmonConfig: vc.NetmonConfig{
Enable: true,
},
}
err := checkNetNsConfig(config)
assert.Error(err)

View File

@ -109,7 +109,6 @@ type RuntimeConfig struct {
FactoryConfig FactoryConfig
HypervisorConfig vc.HypervisorConfig
NetmonConfig vc.NetmonConfig
AgentConfig vc.KataAgentConfig
//Determines how the VM should be connected to the
@ -314,12 +313,6 @@ func networkConfig(ocispec specs.Spec, config RuntimeConfig) (vc.NetworkConfig,
netConf.InterworkingModel = config.InterNetworkModel
netConf.DisableNewNetNs = config.DisableNewNetNs
netConf.NetmonConfig = vc.NetmonConfig{
Path: config.NetmonConfig.Path,
Debug: config.NetmonConfig.Debug,
Enable: config.NetmonConfig.Enable,
}
return netConf, nil
}

View File

@ -366,7 +366,6 @@ type NetworkConfig struct {
NetNSPath string
NetNsCreated bool
DisableNewNetNs bool
NetmonConfig NetmonConfig
InterworkingModel NetInterworkingModel
}
```

View File

@ -1,96 +0,0 @@
// Copyright (c) 2018 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0
//
package virtcontainers
import (
"fmt"
"os/exec"
"syscall"
"github.com/sirupsen/logrus"
)
// NetmonConfig is the structure providing specific configuration
// for the network monitor.
type NetmonConfig struct {
Path string
Debug bool
Enable bool
}
// netmonParams is the structure providing specific parameters needed
// for the execution of the network monitor binary.
type netmonParams struct {
netmonPath string
logLevel string
runtime string
sandboxID string
debug bool
}
func netmonLogger() *logrus.Entry {
return virtLog.WithField("subsystem", "netmon")
}
func prepareNetMonParams(params netmonParams) ([]string, error) {
if params.netmonPath == "" {
return []string{}, fmt.Errorf("Netmon path is empty")
}
if params.runtime == "" {
return []string{}, fmt.Errorf("Netmon runtime path is empty")
}
if params.sandboxID == "" {
return []string{}, fmt.Errorf("Netmon sandbox ID is empty")
}
args := []string{params.netmonPath,
"-r", params.runtime,
"-s", params.sandboxID,
}
if params.debug {
args = append(args, "-d")
}
if params.logLevel != "" {
args = append(args, []string{"-log", params.logLevel}...)
}
return args, nil
}
func startNetmon(params netmonParams) (int, error) {
args, err := prepareNetMonParams(params)
if err != nil {
return -1, err
}
cmd := exec.Command(args[0], args[1:]...)
if err := cmd.Start(); err != nil {
return -1, err
}
return cmd.Process.Pid, nil
}
func stopNetmon(pid int) error {
if pid <= 0 {
return nil
}
sig := syscall.SIGKILL
netmonLogger().WithFields(
logrus.Fields{
"netmon-pid": pid,
"netmon-signal": sig,
}).Info("Stopping netmon")
if err := syscall.Kill(pid, sig); err != nil && err != syscall.ESRCH {
return err
}
return nil
}

View File

@ -1,61 +0,0 @@
// Copyright (c) 2018 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0
//
package virtcontainers
import (
"reflect"
"testing"
"github.com/stretchr/testify/assert"
)
const (
testNetmonPath = "/foo/bar/netmon"
testRuntimePath = "/foo/bar/runtime"
)
func TestNetmonLogger(t *testing.T) {
got := netmonLogger()
expected := virtLog.WithField("subsystem", "netmon")
assert.True(t, reflect.DeepEqual(expected, got),
"Got %+v\nExpected %+v", got, expected)
}
func TestPrepareNetMonParams(t *testing.T) {
// Empty netmon path
params := netmonParams{}
got, err := prepareNetMonParams(params)
assert.NotNil(t, err)
assert.Equal(t, got, []string{})
// Empty runtime path
params.netmonPath = testNetmonPath
got, err = prepareNetMonParams(params)
assert.NotNil(t, err)
assert.Equal(t, got, []string{})
// Empty sandbox ID
params.runtime = testRuntimePath
got, err = prepareNetMonParams(params)
assert.NotNil(t, err)
assert.Equal(t, got, []string{})
// Successful case
params.sandboxID = testSandboxID
got, err = prepareNetMonParams(params)
assert.Nil(t, err)
expected := []string{testNetmonPath,
"-r", testRuntimePath,
"-s", testSandboxID}
assert.True(t, reflect.DeepEqual(expected, got),
"Got %+v\nExpected %+v", got, expected)
}
func TestStopNetmon(t *testing.T) {
pid := -1
err := stopNetmon(pid)
assert.Nil(t, err)
}

View File

@ -178,7 +178,6 @@ type NetworkInterfacePair struct {
// NetworkConfig is the network configuration related to a network.
type NetworkConfig struct {
NetNSPath string
NetmonConfig NetmonConfig
InterworkingModel NetInterworkingModel
NetNsCreated bool
DisableNewNetNs bool
@ -193,7 +192,6 @@ type NetworkNamespace struct {
NetNsPath string
Endpoints []Endpoint
NetNsCreated bool
NetmonPID int
}
func createLink(netHandle *netlink.Handle, name string, expectedLink netlink.Link, queues int) (netlink.Link, []*os.File, error) {

View File

@ -164,7 +164,6 @@ func (s *Sandbox) dumpAgent(ss *persistapi.SandboxState) {
func (s *Sandbox) dumpNetwork(ss *persistapi.SandboxState) {
ss.Network = persistapi.NetworkInfo{
NetNsPath: s.networkNS.NetNsPath,
NetmonPID: s.networkNS.NetmonPID,
NetNsCreated: s.networkNS.NetNsCreated,
}
for _, e := range s.networkNS.Endpoints {
@ -367,7 +366,6 @@ func (c *Container) loadContProcess(cs persistapi.ContainerState) {
func (s *Sandbox) loadNetwork(netInfo persistapi.NetworkInfo) {
s.networkNS = NetworkNamespace{
NetNsPath: netInfo.NetNsPath,
NetmonPID: netInfo.NetmonPID,
NetNsCreated: netInfo.NetNsCreated,
}

View File

@ -98,6 +98,5 @@ type NetworkEndpoint struct {
type NetworkInfo struct {
NetNsPath string
Endpoints []NetworkEndpoint
NetmonPID int
NetNsCreated bool
}

View File

@ -778,40 +778,6 @@ func (s *Sandbox) Delete(ctx context.Context) error {
return s.store.Destroy(s.id)
}
func (s *Sandbox) startNetworkMonitor(ctx context.Context) error {
span, ctx := katatrace.Trace(ctx, s.Logger(), "startNetworkMonitor", sandboxTracingTags, map[string]string{"sandbox_id": s.id})
defer span.End()
binPath, err := os.Executable()
if err != nil {
return err
}
logLevel := "info"
if s.config.NetworkConfig.NetmonConfig.Debug {
logLevel = "debug"
}
params := netmonParams{
netmonPath: s.config.NetworkConfig.NetmonConfig.Path,
debug: s.config.NetworkConfig.NetmonConfig.Debug,
logLevel: logLevel,
runtime: binPath,
sandboxID: s.id,
}
return s.network.Run(ctx, s.networkNS.NetNsPath, func() error {
pid, err := startNetmon(params)
if err != nil {
return err
}
s.networkNS.NetmonPID = pid
return nil
})
}
func (s *Sandbox) createNetwork(ctx context.Context) error {
if s.config.NetworkConfig.DisableNewNetNs ||
s.config.NetworkConfig.NetNSPath == "" {
@ -838,18 +804,11 @@ func (s *Sandbox) createNetwork(ctx context.Context) error {
}
s.networkNS.Endpoints = endpoints
if s.config.NetworkConfig.NetmonConfig.Enable {
if err := s.startNetworkMonitor(ctx); err != nil {
return err
}
}
}
return nil
}
func (s *Sandbox) postCreatedNetwork(ctx context.Context) error {
return s.network.PostAdd(ctx, &s.networkNS, s.factory != nil)
}
@ -857,12 +816,6 @@ func (s *Sandbox) removeNetwork(ctx context.Context) error {
span, ctx := katatrace.Trace(ctx, s.Logger(), "removeNetwork", sandboxTracingTags, map[string]string{"sandbox_id": s.id})
defer span.End()
if s.config.NetworkConfig.NetmonConfig.Enable {
if err := stopNetmon(s.networkNS.NetmonPID); err != nil {
return err
}
}
return s.network.Remove(ctx, &s.networkNS, s.hypervisor)
}
@ -1218,12 +1171,6 @@ func (s *Sandbox) startVM(ctx context.Context) (err error) {
}
s.networkNS.Endpoints = endpoints
if s.config.NetworkConfig.NetmonConfig.Enable {
if err := s.startNetworkMonitor(ctx); err != nil {
return err
}
}
}
s.Logger().Info("VM started")

View File

@ -10,7 +10,6 @@ import (
"fmt"
"io/ioutil"
"os"
"os/exec"
"path"
"path/filepath"
"strings"
@ -1300,33 +1299,6 @@ func TestGetNetNs(t *testing.T) {
assert.Equal(t, netNs, expected)
}
func TestStartNetworkMonitor(t *testing.T) {
if os.Getuid() != 0 {
t.Skip("Test disabled as requires root user")
}
trueBinPath, err := exec.LookPath("true")
assert.Nil(t, err)
assert.NotEmpty(t, trueBinPath)
s := &Sandbox{
id: testSandboxID,
config: &SandboxConfig{
NetworkConfig: NetworkConfig{
NetmonConfig: NetmonConfig{
Path: trueBinPath,
},
},
},
networkNS: NetworkNamespace{
NetNsPath: fmt.Sprintf("/proc/%d/task/%d/ns/net", os.Getpid(), unix.Gettid()),
},
ctx: context.Background(),
}
err = s.startNetworkMonitor(context.Background())
assert.Nil(t, err)
}
func TestSandboxStopStopped(t *testing.T) {
s := &Sandbox{
ctx: context.Background(),