diff options
Diffstat (limited to 'libpod/networking_linux.go')
-rw-r--r-- | libpod/networking_linux.go | 126 |
1 files changed, 85 insertions, 41 deletions
diff --git a/libpod/networking_linux.go b/libpod/networking_linux.go index 035fb5832..fc91155fa 100644 --- a/libpod/networking_linux.go +++ b/libpod/networking_linux.go @@ -11,6 +11,7 @@ import ( "os/exec" "path/filepath" "regexp" + "sort" "strconv" "strings" "syscall" @@ -91,10 +92,7 @@ func (c *Container) getNetworkOptions() (types.NetworkOptions, error) { ContainerID: c.config.ID, ContainerName: getCNIPodName(c), } - // TODO remove ocicni PortMappings from container config and store as types PortMappings - if len(c.config.PortMappings) > 0 { - opts.PortMappings = ocicniPortsToNetTypesPorts(c.config.PortMappings) - } + opts.PortMappings = c.config.PortMappings networks, _, err := c.networks() if err != nil { return opts, err @@ -653,6 +651,9 @@ func getCNIPodName(c *Container) string { // Create and configure a new network namespace for a container func (r *Runtime) configureNetNS(ctr *Container, ctrNS ns.NetNS) (map[string]types.StatusBlock, error) { + if ctr.config.NetMode.IsSlirp4netns() { + return nil, r.setupSlirp4netns(ctr, ctrNS) + } networks, _, err := ctr.networks() if err != nil { return nil, err @@ -667,7 +668,24 @@ func (r *Runtime) configureNetNS(ctr *Container, ctrNS ns.NetNS) (map[string]typ if err != nil { return nil, err } - return r.setUpNetwork(ctrNS.Path(), netOpts) + netStatus, err := r.setUpNetwork(ctrNS.Path(), netOpts) + if err != nil { + return nil, err + } + + // setup rootless port forwarder when rootless with ports and the network status is empty, + // if this is called from network reload the network status will not be empty and we should + // not setup port because they are still active + if rootless.IsRootless() && len(ctr.config.PortMappings) > 0 && ctr.getNetworkStatus() == nil { + // set up port forwarder for rootless netns + netnsPath := ctrNS.Path() + // TODO: support slirp4netns port forwarder as well + // make sure to fix this in container.handleRestartPolicy() as well + // Important we have to call this after r.setUpNetwork() so that + // we can use the proper netStatus + err = r.setupRootlessPortMappingViaRLK(ctr, netnsPath, netStatus) + } + return netStatus, err } // Create and configure a new network namespace for a container @@ -690,31 +708,10 @@ func (r *Runtime) createNetNS(ctr *Container) (n ns.NetNS, q map[string]types.St logrus.Debugf("Made network namespace at %s for container %s", ctrNS.Path(), ctr.ID()) var networkStatus map[string]types.StatusBlock - if !ctr.config.NetMode.IsSlirp4netns() { - networkStatus, err = r.configureNetNS(ctr, ctrNS) - } + networkStatus, err = r.configureNetNS(ctr, ctrNS) return ctrNS, networkStatus, err } -// Configure the network namespace for a rootless container -func (r *Runtime) setupRootlessNetNS(ctr *Container) error { - if ctr.config.NetMode.IsSlirp4netns() { - return r.setupSlirp4netns(ctr) - } - networks, _, err := ctr.networks() - if err != nil { - return err - } - if len(networks) > 0 && len(ctr.config.PortMappings) > 0 { - // set up port forwarder for rootless netns - netnsPath := ctr.state.NetNS.Path() - // TODO: support slirp4netns port forwarder as well - // make sure to fix this in container.handleRestartPolicy() as well - return r.setupRootlessPortMappingViaRLK(ctr, netnsPath) - } - return nil -} - // Configure the network namespace using the container process func (r *Runtime) setupNetNS(ctr *Container) error { nsProcess := fmt.Sprintf("/proc/%d/ns/net", ctr.state.PID) @@ -1209,9 +1206,7 @@ func (c *Container) NetworkDisconnect(nameOrID, netName string, force bool) erro ContainerID: c.config.ID, ContainerName: getCNIPodName(c), } - if len(c.config.PortMappings) > 0 { - opts.PortMappings = ocicniPortsToNetTypesPorts(c.config.PortMappings) - } + opts.PortMappings = c.config.PortMappings eth, exists := c.state.NetInterfaceDescriptions.getInterfaceByName(netName) if !exists { return errors.Errorf("no network interface name for container %s on network %s", c.config.ID, netName) @@ -1303,9 +1298,7 @@ func (c *Container) NetworkConnect(nameOrID, netName string, aliases []string) e ContainerID: c.config.ID, ContainerName: getCNIPodName(c), } - if len(c.config.PortMappings) > 0 { - opts.PortMappings = ocicniPortsToNetTypesPorts(c.config.PortMappings) - } + opts.PortMappings = c.config.PortMappings eth, exists := c.state.NetInterfaceDescriptions.getInterfaceByName(netName) if !exists { return errors.Errorf("no network interface name for container %s on network %s", c.config.ID, netName) @@ -1373,16 +1366,67 @@ func (r *Runtime) normalizeNetworkName(nameOrID string) (string, error) { return net.Name, nil } +// ocicniPortsToNetTypesPorts convert the old port format to the new one +// while deduplicating ports into ranges func ocicniPortsToNetTypesPorts(ports []types.OCICNIPortMapping) []types.PortMapping { + if len(ports) == 0 { + return nil + } + newPorts := make([]types.PortMapping, 0, len(ports)) - for _, port := range ports { - newPorts = append(newPorts, types.PortMapping{ - HostIP: port.HostIP, - HostPort: uint16(port.HostPort), - ContainerPort: uint16(port.ContainerPort), - Protocol: port.Protocol, - Range: 1, - }) + + // first sort the ports + sort.Slice(ports, func(i, j int) bool { + return compareOCICNIPorts(ports[i], ports[j]) + }) + + // we already check if the slice is empty so we can use the first element + currentPort := types.PortMapping{ + HostIP: ports[0].HostIP, + HostPort: uint16(ports[0].HostPort), + ContainerPort: uint16(ports[0].ContainerPort), + Protocol: ports[0].Protocol, + Range: 1, + } + + for i := 1; i < len(ports); i++ { + if ports[i].HostIP == currentPort.HostIP && + ports[i].Protocol == currentPort.Protocol && + ports[i].HostPort-int32(currentPort.Range) == int32(currentPort.HostPort) && + ports[i].ContainerPort-int32(currentPort.Range) == int32(currentPort.ContainerPort) { + currentPort.Range = currentPort.Range + 1 + } else { + newPorts = append(newPorts, currentPort) + currentPort = types.PortMapping{ + HostIP: ports[i].HostIP, + HostPort: uint16(ports[i].HostPort), + ContainerPort: uint16(ports[i].ContainerPort), + Protocol: ports[i].Protocol, + Range: 1, + } + } } + newPorts = append(newPorts, currentPort) return newPorts } + +// compareOCICNIPorts will sort the ocicni ports by +// 1) host ip +// 2) protocol +// 3) hostPort +// 4) container port +func compareOCICNIPorts(i, j types.OCICNIPortMapping) bool { + if i.HostIP != j.HostIP { + return i.HostIP < j.HostIP + } + + if i.Protocol != j.Protocol { + return i.Protocol < j.Protocol + } + + if i.HostPort != j.HostPort { + return i.HostPort < j.HostPort + } + + return i.ContainerPort < j.ContainerPort +} |