package integration import ( "os" "path/filepath" . "github.com/containers/podman/v5/test/utils" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" ) func isDebianRunc(pTest *PodmanTestIntegration) bool { info := GetHostDistributionInfo() if info.Distribution == "debian" && pTest.OCIRuntime == "runc" { return true } return false } func createNetworkDevice(name string) { session := SystemExec("ip", []string{"link", "add", name, "type", "bridge"}) session.WaitWithDefaultTimeout() Expect(session).Should(ExitCleanly()) } func deleteNetworkDevice(name string) { session := SystemExec("ip", []string{"link", "delete", name}) session.WaitWithDefaultTimeout() Expect(session).Should(ExitCleanly()) } func createContainersConfFileWithDeviceIfaceName(pTest *PodmanTestIntegration) { configPath := filepath.Join(pTest.TempDir, "containers.conf") containersConf := []byte("[containers]\ninterface_name = \"device\"\n") err := os.WriteFile(configPath, containersConf, os.ModePerm) Expect(err).ToNot(HaveOccurred()) // Set custom containers.conf file os.Setenv("CONTAINERS_CONF_OVERRIDE", configPath) if IsRemote() { pTest.RestartRemoteService() } } var _ = Describe("Podman container interface name", func() { It("podman container interface name for bridge network", func() { // Assert that the network interface name inside container for // bridge network is ethX regardless of interface_name setting // in the containers.conf file. netName1 := createNetworkName("bridge") netName2 := createNetworkName("bridge") defer podmanTest.removeNetwork(netName1) nc1 := podmanTest.Podman([]string{"network", "create", netName1}) nc1.WaitWithDefaultTimeout() Expect(nc1).Should(ExitCleanly()) defer podmanTest.removeNetwork(netName2) nc2 := podmanTest.Podman([]string{"network", "create", netName2}) nc2.WaitWithDefaultTimeout() Expect(nc2).Should(ExitCleanly()) for _, override := range []bool{false, true} { if override { createContainersConfFileWithDeviceIfaceName(podmanTest) } ctr := podmanTest.Podman([]string{"run", "-d", "--network", netName1, "--name", "test", ALPINE, "top"}) ctr.WaitWithDefaultTimeout() Expect(ctr).Should(ExitCleanly()) exec1 := podmanTest.Podman([]string{"exec", "test", "ip", "addr", "show", "eth0"}) exec1.WaitWithDefaultTimeout() Expect(exec1).Should(ExitCleanly()) Expect(exec1.OutputToString()).Should(ContainSubstring("eth0")) conn := podmanTest.Podman([]string{"network", "connect", netName2, "test"}) conn.WaitWithDefaultTimeout() Expect(conn).Should(ExitCleanly()) exec2 := podmanTest.Podman([]string{"exec", "test", "ip", "addr", "show", "eth1"}) exec2.WaitWithDefaultTimeout() Expect(exec2).Should(ExitCleanly()) Expect(exec2.OutputToString()).Should(ContainSubstring("eth1")) rm := podmanTest.Podman([]string{"rm", "--time=0", "-f", "test"}) rm.WaitWithDefaultTimeout() Expect(rm).Should(ExitCleanly()) } }) It("podman container interface name for macvlan/ipvlan network with no parent", func() { // Assert that the network interface name inside container for // macvlan/ipvlan network with no parent interface is ethX // regardless of interface_name setting in the containers.conf // file. for _, override := range []bool{false, true} { if override { createContainersConfFileWithDeviceIfaceName(podmanTest) } for _, driverType := range []string{"macvlan", "ipvlan"} { if driverType == "ipvlan" && isDebianRunc(podmanTest) { GinkgoWriter.Println("FIXME: Fails with netavark < 1.10. Re-enable once Debian gets an update") continue } netName1 := createNetworkName(driverType) netName2 := createNetworkName(driverType) // There is no nic created by the macvlan/ipvlan driver. defer podmanTest.removeNetwork(netName1) nc1 := podmanTest.Podman([]string{"network", "create", "-d", driverType, "--subnet", "10.10.0.0/24", netName1}) nc1.WaitWithDefaultTimeout() Expect(nc1).Should(ExitCleanly()) ctr := podmanTest.Podman([]string{"run", "-d", "--network", netName1, "--name", "test", ALPINE, "top"}) ctr.WaitWithDefaultTimeout() Expect(ctr).Should(ExitCleanly()) exec1 := podmanTest.Podman([]string{"exec", "test", "ip", "addr", "show", "eth0"}) exec1.WaitWithDefaultTimeout() Expect(exec1).Should(ExitCleanly()) Expect(exec1.OutputToString()).Should(ContainSubstring("eth0")) defer podmanTest.removeNetwork(netName2) nc2 := podmanTest.Podman([]string{"network", "create", "-d", driverType, "--subnet", "10.25.40.0/24", netName2}) nc2.WaitWithDefaultTimeout() Expect(nc2).Should(ExitCleanly()) conn := podmanTest.Podman([]string{"network", "connect", netName2, "test"}) conn.WaitWithDefaultTimeout() Expect(conn).Should(ExitCleanly()) exec2 := podmanTest.Podman([]string{"exec", "test", "ip", "addr", "show", "eth1"}) exec2.WaitWithDefaultTimeout() Expect(exec2).Should(ExitCleanly()) Expect(exec2.OutputToString()).Should(ContainSubstring("eth1")) rm := podmanTest.Podman([]string{"rm", "--time=0", "-f", "test"}) rm.WaitWithDefaultTimeout() Expect(rm).Should(ExitCleanly()) } } }) It("podman container interface name with default scheme for macvlan/ipvlan network with parent", func() { // Assert that the network interface name inside container for // macvlan/ipvlan network, created with a specific parent // interface, continues to be ethX when interface_name in the // containers.conf file is set to default value, i.e., "". SkipIfRootless("cannot create network device in rootless mode.") for _, driverType := range []string{"macvlan", "ipvlan"} { if driverType == "ipvlan" && isDebianRunc(podmanTest) { GinkgoWriter.Println("FIXME: Fails with netavark < 1.10. Re-enable once Debian gets an update") continue } // Create a nic to be used as a parent for macvlan/ipvlan network. nicName1 := createNetworkName("nic")[:8] nicName2 := createNetworkName("nic")[:8] netName1 := createNetworkName(driverType) netName2 := createNetworkName(driverType) parent1 := "parent=" + nicName1 parent2 := "parent=" + nicName2 defer deleteNetworkDevice(nicName1) createNetworkDevice(nicName1) defer podmanTest.removeNetwork(netName1) nc1 := podmanTest.Podman([]string{"network", "create", "-d", driverType, "-o", parent1, "--subnet", "10.10.0.0/24", netName1}) nc1.WaitWithDefaultTimeout() Expect(nc1).Should(ExitCleanly()) ctr := podmanTest.Podman([]string{"run", "-d", "--network", netName1, "--name", "test", ALPINE, "top"}) ctr.WaitWithDefaultTimeout() Expect(ctr).Should(ExitCleanly()) exec1 := podmanTest.Podman([]string{"exec", "test", "ip", "addr", "show", "eth0"}) exec1.WaitWithDefaultTimeout() Expect(exec1).Should(ExitCleanly()) Expect(exec1.OutputToString()).Should(ContainSubstring("eth0")) defer deleteNetworkDevice(nicName2) createNetworkDevice(nicName2) defer podmanTest.removeNetwork(netName2) nc2 := podmanTest.Podman([]string{"network", "create", "-d", driverType, "-o", parent2, "--subnet", "10.25.40.0/24", netName2}) nc2.WaitWithDefaultTimeout() Expect(nc2).Should(ExitCleanly()) conn := podmanTest.Podman([]string{"network", "connect", netName2, "test"}) conn.WaitWithDefaultTimeout() Expect(conn).Should(ExitCleanly()) exec2 := podmanTest.Podman([]string{"exec", "test", "ip", "addr", "show", "eth1"}) exec2.WaitWithDefaultTimeout() Expect(exec2).Should(ExitCleanly()) Expect(exec2.OutputToString()).Should(ContainSubstring("eth1")) rm := podmanTest.Podman([]string{"rm", "--time=0", "-f", "test"}) rm.WaitWithDefaultTimeout() Expect(rm).Should(ExitCleanly()) } }) It("podman container interface name with device scheme for macvlan/ipvlan network with parent", func() { // Assert that the network interface name inside container for // macvlan/ipvlan network, created with a specific parent // interface, is the parent interface name ethX when // interface_name in the containers.conf file is set to "device" SkipIfRootless("cannot create network device in rootless mode.") createContainersConfFileWithDeviceIfaceName(podmanTest) for _, driverType := range []string{"macvlan", "ipvlan"} { if driverType == "ipvlan" && isDebianRunc(podmanTest) { GinkgoWriter.Println("FIXME: Fails with netavark < 1.10. Re-enable once Debian gets an update") continue } // Create a nic to be used as a parent for the network. nicName1 := createNetworkName("nic")[:8] nicName2 := createNetworkName("nic")[:8] netName1 := createNetworkName(driverType) netName2 := createNetworkName(driverType) parent1 := "parent=" + nicName1 parent2 := "parent=" + nicName2 defer deleteNetworkDevice(nicName1) createNetworkDevice(nicName1) defer podmanTest.removeNetwork(netName1) nc1 := podmanTest.Podman([]string{"network", "create", "-d", driverType, "-o", parent1, "--subnet", "10.10.0.0/24", netName1}) nc1.WaitWithDefaultTimeout() Expect(nc1).Should(ExitCleanly()) ctr := podmanTest.Podman([]string{"run", "-d", "--network", netName1, "--name", "test", ALPINE, "top"}) ctr.WaitWithDefaultTimeout() Expect(ctr).Should(ExitCleanly()) exec1 := podmanTest.Podman([]string{"exec", "test", "ip", "addr", "show", nicName1}) exec1.WaitWithDefaultTimeout() Expect(exec1).Should(ExitCleanly()) Expect(exec1.OutputToString()).Should(ContainSubstring(nicName1)) defer deleteNetworkDevice(nicName2) createNetworkDevice(nicName2) defer podmanTest.removeNetwork(netName2) nc2 := podmanTest.Podman([]string{"network", "create", "-d", driverType, "-o", parent2, "--subnet", "10.25.40.0/24", netName2}) nc2.WaitWithDefaultTimeout() Expect(nc2).Should(ExitCleanly()) conn := podmanTest.Podman([]string{"network", "connect", netName2, "test"}) conn.WaitWithDefaultTimeout() Expect(conn).Should(ExitCleanly()) exec2 := podmanTest.Podman([]string{"exec", "test", "ip", "addr", "show", nicName2}) exec2.WaitWithDefaultTimeout() Expect(exec2).Should(ExitCleanly()) Expect(exec2.OutputToString()).Should(ContainSubstring(nicName2)) rm := podmanTest.Podman([]string{"rm", "--time=0", "-f", "test"}) rm.WaitWithDefaultTimeout() Expect(rm).Should(ExitCleanly()) } }) })