allow switching of port-forward approaches in rootless/using slirp4netns

As of podman 1.8.0, because of commit da7595a, the default approach of providing
port-forwarding in rootless mode has switched (and been hard-coded) to rootlessport,
for the purpose of providing super performance. The side-effect of this switch is
source within the container to the port-forwarded service always appears to originate
from 127.0.0.1 (see issue #5138).

This commit allows a user to specify if they want to revert to the previous approach
of leveraging slirp4netns add_hostfwd() api which, although not as stellar performance,
restores usefulness of seeing incoming traffic origin IP addresses.

The change should be transparent; when not specified, rootlessport will continue to be
used, however if specifying --net slirp4netns:slirplisten the old approach will be used.

Note: the above may imply the restored port-forwarding via slirp4netns is not as
performant as the new rootlessport approach, however the figures shared in the original
commit that introduced rootlessport are as follows:
slirp4netns: 8.3 Gbps,
RootlessKit: 27.3 Gbps,
which are more than sufficient for many use cases where the origin of traffic is more
important than limits that cannot be reached due to bottlenecks elsewhere.

Signed-off-by: Aleks Mariusz <m.k@alek.cx>
Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
This commit is contained in:
aleks-mariusz
2020-06-16 11:36:33 +01:00
committed by Giuseppe Scrivano
parent c4843d4e9c
commit 8d12f19371
4 changed files with 160 additions and 8 deletions

View File

@ -108,7 +108,19 @@ func validateNetNS(n *Namespace) error {
return nil
}
switch n.NSMode {
case "", Default, Host, Path, FromContainer, FromPod, Private, NoNetwork, Bridge, Slirp:
case Slirp:
if n.Value != "" {
parts := strings.Split(n.Value, ",")
for _, p := range parts {
switch p {
case "port_handler=slirp4netns", "port_handler=rootlesskit":
default:
return errors.Errorf("invalid value for slirp %q", n.Value)
}
}
}
break
case "", Default, Host, Path, FromContainer, FromPod, Private, NoNetwork, Bridge:
break
default:
return errors.Errorf("invalid network %q", n.NSMode)
@ -119,8 +131,8 @@ func validateNetNS(n *Namespace) error {
if len(n.Value) < 1 {
return errors.Errorf("namespace mode %s requires a value", n.NSMode)
}
} else {
// All others must NOT set a string value
} else if n.NSMode != Slirp {
// All others except must NOT set a string value
if len(n.Value) > 0 {
return errors.Errorf("namespace value %s cannot be provided with namespace mode %s", n.Value, n.NSMode)
}
@ -250,8 +262,12 @@ func ParseNetworkNamespace(ns string) (Namespace, []string, error) {
var cniNetworks []string
// Net defaults to Slirp on rootless
switch {
case ns == "slirp4netns":
case ns == "slirp4netns", strings.HasPrefix(ns, "slirp4netns:"):
split := strings.SplitN(ns, ":", 2)
toReturn.NSMode = Slirp
if len(split) > 1 {
toReturn.Value = split[1]
}
case ns == "pod":
toReturn.NSMode = FromPod
case ns == "":