summaryrefslogtreecommitdiff
path: root/libpod/networking_linux.go
diff options
context:
space:
mode:
authorMatthew Heon <matthew.heon@pm.me>2020-02-20 13:34:51 -0500
committerMatthew Heon <matthew.heon@pm.me>2020-02-25 13:20:25 -0500
commitf9fc9a7b7b0e5633cf279273b614a5d3e4c68906 (patch)
tree3e089830787caf5276424aec748326b7fe569c3e /libpod/networking_linux.go
parent3d37dc639d87e4469a6457cf4592ff5b773d0777 (diff)
downloadpodman-f9fc9a7b7b0e5633cf279273b614a5d3e4c68906.tar.gz
podman-f9fc9a7b7b0e5633cf279273b614a5d3e4c68906.tar.bz2
podman-f9fc9a7b7b0e5633cf279273b614a5d3e4c68906.zip
Add support for multiple CNI networks in podman inspect
When inspecting containers, info on CNI networks added to the container by name (e.g. --net=name1) should be displayed separately from the configuration of the default network, in a separate map called Networks. This patch adds this separation, improving our Docker compatibility and also adding the ability to see if a container has more than one IPv4 and IPv6 address and more than one MAC address. Fixes #4907 Signed-off-by: Matthew Heon <matthew.heon@pm.me>
Diffstat (limited to 'libpod/networking_linux.go')
-rw-r--r--libpod/networking_linux.go118
1 files changed, 93 insertions, 25 deletions
diff --git a/libpod/networking_linux.go b/libpod/networking_linux.go
index fa8593f20..d57b1a8eb 100644
--- a/libpod/networking_linux.go
+++ b/libpod/networking_linux.go
@@ -12,13 +12,13 @@ import (
"os"
"os/exec"
"path/filepath"
- "strconv"
"strings"
"syscall"
"time"
cnitypes "github.com/containernetworking/cni/pkg/types/current"
"github.com/containernetworking/plugins/pkg/ns"
+ "github.com/containers/libpod/libpod/define"
"github.com/containers/libpod/pkg/errorhandling"
"github.com/containers/libpod/pkg/netns"
"github.com/containers/libpod/pkg/rootless"
@@ -556,37 +556,105 @@ func getContainerNetIO(ctr *Container) (*netlink.LinkStatistics, error) {
return netStats, err
}
-func (c *Container) getContainerNetworkInfo(data *InspectContainerData) *InspectContainerData {
- if c.state.NetNS != nil && len(c.state.NetworkStatus) > 0 {
- // Report network settings from the first pod network
- result := c.state.NetworkStatus[0]
- // Go through our IP addresses
- for _, ctrIP := range result.IPs {
- ipWithMask := ctrIP.Address.String()
- splitIP := strings.Split(ipWithMask, "/")
- mask, _ := strconv.Atoi(splitIP[1])
- if ctrIP.Version == "4" {
- data.NetworkSettings.IPAddress = splitIP[0]
- data.NetworkSettings.IPPrefixLen = mask
- data.NetworkSettings.Gateway = ctrIP.Gateway.String()
- } else {
- data.NetworkSettings.GlobalIPv6Address = splitIP[0]
- data.NetworkSettings.GlobalIPv6PrefixLen = mask
- data.NetworkSettings.IPv6Gateway = ctrIP.Gateway.String()
+// Produce an InspectNetworkSettings containing information on the container
+// network.
+func (c *Container) getContainerNetworkInfo() (*InspectNetworkSettings, error) {
+ settings := new(InspectNetworkSettings)
+ settings.Ports = []ocicni.PortMapping{}
+ if c.config.PortMappings != nil {
+ // TODO: This may not be safe.
+ settings.Ports = c.config.PortMappings
+ }
+
+ // We can't do more if the network is down.
+ if c.state.NetNS == nil {
+ return settings, nil
+ }
+
+ // Set network namespace path
+ settings.SandboxKey = c.state.NetNS.Path()
+
+ // If this is empty, we're probably slirp4netns
+ if len(c.state.NetworkStatus) == 0 {
+ return settings, nil
+ }
+
+ // If we have CNI networks - handle that here
+ if len(c.config.Networks) > 0 {
+ if len(c.config.Networks) != len(c.state.NetworkStatus) {
+ return nil, errors.Wrapf(define.ErrInternal, "network inspection mismatch: asked to join %d CNI networks but have information on %d networks", len(c.config.Networks), len(c.state.NetworkStatus))
+ }
+
+ settings.Networks = make(map[string]*InspectAdditionalNetwork)
+
+ // CNI results should be in the same order as the list of
+ // networks we pass into CNI.
+ for index, name := range c.config.Networks {
+ cniResult := c.state.NetworkStatus[index]
+ addedNet := new(InspectAdditionalNetwork)
+ addedNet.NetworkID = name
+
+ basicConfig, err := resultToBasicNetworkConfig(cniResult)
+ if err != nil {
+ return nil, err
}
+ addedNet.InspectBasicNetworkConfig = basicConfig
+
+ settings.Networks[name] = addedNet
}
- // Set network namespace path
- data.NetworkSettings.SandboxKey = c.state.NetNS.Path()
+ return settings, nil
+ }
+
+ // If not joining networks, we should have at most 1 result
+ if len(c.state.NetworkStatus) > 1 {
+ return nil, errors.Wrapf(define.ErrInternal, "should have at most 1 CNI result if not joining networks, instead got %d", len(c.state.NetworkStatus))
+ }
+
+ if len(c.state.NetworkStatus) == 1 {
+ basicConfig, err := resultToBasicNetworkConfig(c.state.NetworkStatus[0])
+ if err != nil {
+ return nil, err
+ }
- // Set MAC address of interface linked with network namespace path
- for _, i := range result.Interfaces {
- if i.Sandbox == data.NetworkSettings.SandboxKey {
- data.NetworkSettings.MacAddress = i.Mac
+ settings.InspectBasicNetworkConfig = basicConfig
+ }
+
+ return settings, nil
+}
+
+// resultToBasicNetworkConfig produces an InspectBasicNetworkConfig from a CNI
+// result
+func resultToBasicNetworkConfig(result *cnitypes.Result) (InspectBasicNetworkConfig, error) {
+ config := InspectBasicNetworkConfig{}
+
+ for _, ctrIP := range result.IPs {
+ size, _ := ctrIP.Address.Mask.Size()
+ switch {
+ case ctrIP.Version == "4" && config.IPAddress == "":
+ config.IPAddress = ctrIP.Address.IP.String()
+ config.IPPrefixLen = size
+ config.Gateway = ctrIP.Gateway.String()
+ if ctrIP.Interface != nil && *ctrIP.Interface < len(result.Interfaces) && *ctrIP.Interface > 0 {
+ config.MacAddress = result.Interfaces[*ctrIP.Interface].Mac
+ }
+ case ctrIP.Version == "4" && config.IPAddress != "":
+ config.SecondaryIPAddresses = append(config.SecondaryIPAddresses, ctrIP.Address.String())
+ if ctrIP.Interface != nil && *ctrIP.Interface < len(result.Interfaces) && *ctrIP.Interface > 0 {
+ config.AdditionalMacAddresses = append(config.AdditionalMacAddresses, result.Interfaces[*ctrIP.Interface].Mac)
}
+ case ctrIP.Version == "6" && config.IPAddress == "":
+ config.GlobalIPv6Address = ctrIP.Address.IP.String()
+ config.GlobalIPv6PrefixLen = size
+ config.IPv6Gateway = ctrIP.Gateway.String()
+ case ctrIP.Version == "6" && config.IPAddress != "":
+ config.SecondaryIPv6Addresses = append(config.SecondaryIPv6Addresses, ctrIP.Address.String())
+ default:
+ return config, errors.Wrapf(define.ErrInternal, "unrecognized IP version %q", ctrIP.Version)
}
}
- return data
+
+ return config, nil
}
type logrusDebugWriter struct {