From c20f61148cfc7c51f72bf266e154d1903db68c6a Mon Sep 17 00:00:00 2001 From: Paul Holzinger Date: Thu, 16 Sep 2021 14:03:49 +0200 Subject: CNI: network create support macvlan modes Support setting the macvlan mode with `podman network create -d macvlan --opt mode=bridge`. This will correctly set the specified macvlan mode in the cni conflist file. Signed-off-by: Paul Holzinger --- docs/source/markdown/podman-network-create.1.md | 11 ++++++--- libpod/network/cni/cni_conversion.go | 13 +++++++++- libpod/network/cni/cni_types.go | 10 +++++--- libpod/network/cni/config_test.go | 33 +++++++++++++++++++++++++ 4 files changed, 60 insertions(+), 7 deletions(-) diff --git a/docs/source/markdown/podman-network-create.1.md b/docs/source/markdown/podman-network-create.1.md index 816dd53ea..1eb96be11 100644 --- a/docs/source/markdown/podman-network-create.1.md +++ b/docs/source/markdown/podman-network-create.1.md @@ -32,9 +32,14 @@ As rootless the `macvlan` driver has no access to the host network interfaces be Set driver specific options. -For the `bridge` driver the following options are supported: `mtu` and `vlan`. -The `mtu` option sets the Maximum Transmission Unit (MTU) and takes an integer value. -The `vlan` option assign VLAN tag and enables vlan\_filtering. Defaults to none. +All drivers accept the `mtu` option. The `mtu` option sets the Maximum Transmission Unit (MTU) and takes an integer value. + +Additionally the `bridge` driver supports the following option: +- `vlan`: This option assign VLAN tag and enables vlan\_filtering. Defaults to none. + +The `macvlan` driver supports the following options: +- `parent`: The host device which should be used for the macvlan interface. Defaults to the default route interface. +- `mode`: This options sets the specified macvlan mode on the interface. Supported values are `bridge`, `private`, `vepa`, `passthru`. Defaults to `bridge`. #### **--gateway** diff --git a/libpod/network/cni/cni_conversion.go b/libpod/network/cni/cni_conversion.go index 060794ebe..32dcc62de 100644 --- a/libpod/network/cni/cni_conversion.go +++ b/libpod/network/cni/cni_conversion.go @@ -94,6 +94,10 @@ func createNetworkFromCNIConfigList(conf *libcni.NetworkConfigList, confPath str network.Options["mtu"] = strconv.Itoa(macvlan.MTU) } + if macvlan.Mode != "" { + network.Options["mode"] = macvlan.Mode + } + err = convertIPAMConfToNetwork(&network, macvlan.IPAM, confPath) if err != nil { return nil, err @@ -237,6 +241,7 @@ func (n *cniNetwork) createCNIConfigListFromNetwork(network *types.Network, writ vlan := 0 mtu := 0 + macvlanMode := "" for k, v := range network.Options { switch k { case "mtu": @@ -251,6 +256,12 @@ func (n *cniNetwork) createCNIConfigListFromNetwork(network *types.Network, writ return nil, "", err } + case "mode": + if !pkgutil.StringInSlice(v, []string{"", "bridge", "private", "vepa", "passthru"}) { + return nil, "", errors.Errorf("unknown macvlan mode %q", v) + } + macvlanMode = v + default: return nil, "", errors.Errorf("unsupported network option %s", k) } @@ -281,7 +292,7 @@ func (n *cniNetwork) createCNIConfigListFromNetwork(network *types.Network, writ } case types.MacVLANNetworkDriver: - plugins = append(plugins, newMacVLANPlugin(network.NetworkInterface, mtu, ipamConf)) + plugins = append(plugins, newMacVLANPlugin(network.NetworkInterface, macvlanMode, mtu, ipamConf)) default: return nil, "", errors.Errorf("driver %q is not supported by cni", network.Driver) diff --git a/libpod/network/cni/cni_types.go b/libpod/network/cni/cni_types.go index 91fd1c27b..0a7bb066e 100644 --- a/libpod/network/cni/cni_types.go +++ b/libpod/network/cni/cni_types.go @@ -50,7 +50,7 @@ type hostLocalBridge struct { PromiscMode bool `json:"promiscMode,omitempty"` Vlan int `json:"vlan,omitempty"` IPAM ipamConfig `json:"ipam"` - Capabilities map[string]bool `json:"capabilities"` + Capabilities map[string]bool `json:"capabilities,omitempty"` } // ipamConfig describes an IPAM configuration @@ -88,7 +88,8 @@ type macVLANConfig struct { Master string `json:"master"` IPAM ipamConfig `json:"ipam"` MTU int `json:"mtu,omitempty"` - Capabilities map[string]bool `json:"capabilities"` + Mode string `json:"mode,omitempty"` + Capabilities map[string]bool `json:"capabilities,omitempty"` } // firewallConfig describes the firewall plugin @@ -260,7 +261,7 @@ func hasDNSNamePlugin(paths []string) bool { } // newMacVLANPlugin creates a macvlanconfig with a given device name -func newMacVLANPlugin(device string, mtu int, ipam ipamConfig) macVLANConfig { +func newMacVLANPlugin(device, mode string, mtu int, ipam ipamConfig) macVLANConfig { m := macVLANConfig{ PluginType: "macvlan", IPAM: ipam, @@ -268,6 +269,9 @@ func newMacVLANPlugin(device string, mtu int, ipam ipamConfig) macVLANConfig { if mtu > 0 { m.MTU = mtu } + if len(mode) > 0 { + m.Mode = mode + } // CNI is supposed to use the default route if a // parent device is not provided if len(device) > 0 { diff --git a/libpod/network/cni/config_test.go b/libpod/network/cni/config_test.go index 11ad71870..62b6ef837 100644 --- a/libpod/network/cni/config_test.go +++ b/libpod/network/cni/config_test.go @@ -250,6 +250,39 @@ var _ = Describe("Config", func() { grepInFile(path, `"type": "host-local"`) }) + It("create macvlan config with mode", func() { + for _, mode := range []string{"bridge", "private", "vepa", "passthru"} { + network := types.Network{ + Driver: "macvlan", + Options: map[string]string{ + "mode": mode, + }, + } + network1, err := libpodNet.NetworkCreate(network) + Expect(err).To(BeNil()) + Expect(network1.Name).ToNot(BeEmpty()) + path := filepath.Join(cniConfDir, network1.Name+".conflist") + Expect(path).To(BeARegularFile()) + Expect(network1.Driver).To(Equal("macvlan")) + Expect(network1.Options).To(HaveKeyWithValue("mode", mode)) + Expect(network1.IPAMOptions).ToNot(BeEmpty()) + Expect(network1.IPAMOptions).To(HaveKeyWithValue("driver", "dhcp")) + grepInFile(path, `"mode": "`+mode+`"`) + } + }) + + It("create macvlan config with invalid mode", func() { + network := types.Network{ + Driver: "macvlan", + Options: map[string]string{ + "mode": "test", + }, + } + _, err := libpodNet.NetworkCreate(network) + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring(`unknown macvlan mode "test"`)) + }) + It("create macvlan config with invalid device", func() { network := types.Network{ Driver: "macvlan", -- cgit v1.2.3-54-g00ecf