From 5a0257d463fc31621d8cdb8664ebba95dc765ed6 Mon Sep 17 00:00:00 2001 From: Paul Holzinger Date: Thu, 20 May 2021 11:23:03 +0200 Subject: [PATCH] Fix network create macvlan with subnet option Creating a macvlan network with the subnet or ipRange option should set the ipam plugin type to `host-local`. We also have to insert the default route. Fixes #10283 Signed-off-by: Paul Holzinger --- libpod/network/config.go | 43 +++++++++++++++-------------------- libpod/network/netconflist.go | 18 +++++++++++---- test/e2e/network_test.go | 26 ++++++++++++++++++--- 3 files changed, 54 insertions(+), 33 deletions(-) diff --git a/libpod/network/config.go b/libpod/network/config.go index ac44786023..9a3bc47638 100644 --- a/libpod/network/config.go +++ b/libpod/network/config.go @@ -44,17 +44,17 @@ type CNIPlugins interface { // HostLocalBridge describes a configuration for a bridge plugin // https://github.com/containernetworking/plugins/tree/master/plugins/main/bridge#network-configuration-reference type HostLocalBridge struct { - PluginType string `json:"type"` - BrName string `json:"bridge,omitempty"` - IsGW bool `json:"isGateway"` - IsDefaultGW bool `json:"isDefaultGateway,omitempty"` - ForceAddress bool `json:"forceAddress,omitempty"` - IPMasq bool `json:"ipMasq,omitempty"` - MTU int `json:"mtu,omitempty"` - HairpinMode bool `json:"hairpinMode,omitempty"` - PromiscMode bool `json:"promiscMode,omitempty"` - Vlan int `json:"vlan,omitempty"` - IPAM IPAMHostLocalConf `json:"ipam"` + PluginType string `json:"type"` + BrName string `json:"bridge,omitempty"` + IsGW bool `json:"isGateway"` + IsDefaultGW bool `json:"isDefaultGateway,omitempty"` + ForceAddress bool `json:"forceAddress,omitempty"` + IPMasq bool `json:"ipMasq,omitempty"` + MTU int `json:"mtu,omitempty"` + HairpinMode bool `json:"hairpinMode,omitempty"` + PromiscMode bool `json:"promiscMode,omitempty"` + Vlan int `json:"vlan,omitempty"` + IPAM IPAMConfig `json:"ipam"` } // Bytes outputs []byte @@ -62,9 +62,9 @@ func (h *HostLocalBridge) Bytes() ([]byte, error) { return json.MarshalIndent(h, "", "\t") } -// IPAMHostLocalConf describes an IPAM configuration +// IPAMConfig describes an IPAM configuration // https://github.com/containernetworking/plugins/tree/master/plugins/ipam/host-local#network-configuration-reference -type IPAMHostLocalConf struct { +type IPAMConfig struct { PluginType string `json:"type"` Routes []IPAMRoute `json:"routes,omitempty"` ResolveConf string `json:"resolveConf,omitempty"` @@ -81,7 +81,7 @@ type IPAMLocalHostRangeConf struct { } // Bytes outputs the configuration as []byte -func (i IPAMHostLocalConf) Bytes() ([]byte, error) { +func (i IPAMConfig) Bytes() ([]byte, error) { return json.MarshalIndent(i, "", "\t") } @@ -101,19 +101,12 @@ func (p PortMapConfig) Bytes() ([]byte, error) { return json.MarshalIndent(p, "", "\t") } -// IPAMDHCP describes the ipamdhcp config -type IPAMDHCP struct { - DHCP string `json:"type"` - Routes []IPAMRoute `json:"routes,omitempty"` - Ranges [][]IPAMLocalHostRangeConf `json:"ranges,omitempty"` -} - // MacVLANConfig describes the macvlan config type MacVLANConfig struct { - PluginType string `json:"type"` - Master string `json:"master"` - IPAM IPAMDHCP `json:"ipam"` - MTU int `json:"mtu,omitempty"` + PluginType string `json:"type"` + Master string `json:"master"` + IPAM IPAMConfig `json:"ipam"` + MTU int `json:"mtu,omitempty"` } // Bytes outputs the configuration as []byte diff --git a/libpod/network/netconflist.go b/libpod/network/netconflist.go index d2031df6d1..d6c33740ea 100644 --- a/libpod/network/netconflist.go +++ b/libpod/network/netconflist.go @@ -45,7 +45,7 @@ func NewNcList(name, version string, labels NcLabels) NcList { } // NewHostLocalBridge creates a new LocalBridge for host-local -func NewHostLocalBridge(name string, isGateWay, isDefaultGW, ipMasq bool, mtu int, vlan int, ipamConf IPAMHostLocalConf) *HostLocalBridge { +func NewHostLocalBridge(name string, isGateWay, isDefaultGW, ipMasq bool, mtu int, vlan int, ipamConf IPAMConfig) *HostLocalBridge { hostLocalBridge := HostLocalBridge{ PluginType: "bridge", BrName: name, @@ -65,8 +65,8 @@ func NewHostLocalBridge(name string, isGateWay, isDefaultGW, ipMasq bool, mtu in } // NewIPAMHostLocalConf creates a new IPAMHostLocal configuration -func NewIPAMHostLocalConf(routes []IPAMRoute, ipamRanges [][]IPAMLocalHostRangeConf) (IPAMHostLocalConf, error) { - ipamConf := IPAMHostLocalConf{ +func NewIPAMHostLocalConf(routes []IPAMRoute, ipamRanges [][]IPAMLocalHostRangeConf) (IPAMConfig, error) { + ipamConf := IPAMConfig{ PluginType: "host-local", Routes: routes, // Possible future support ? Leaving for clues @@ -177,8 +177,10 @@ func HasDNSNamePlugin(paths []string) bool { // NewMacVLANPlugin creates a macvlanconfig with a given device name func NewMacVLANPlugin(device string, gateway net.IP, ipRange *net.IPNet, subnet *net.IPNet, mtu int) (MacVLANConfig, error) { - i := IPAMDHCP{DHCP: "dhcp"} - if gateway != nil || ipRange != nil || subnet != nil { + i := IPAMConfig{PluginType: "dhcp"} + if gateway != nil || + (ipRange != nil && ipRange.IP != nil && ipRange.Mask != nil) || + (subnet != nil && subnet.IP != nil && subnet.Mask != nil) { ipam, err := NewIPAMLocalHostRange(subnet, ipRange, gateway) if err != nil { return MacVLANConfig{}, err @@ -186,6 +188,12 @@ func NewMacVLANPlugin(device string, gateway net.IP, ipRange *net.IPNet, subnet ranges := make([][]IPAMLocalHostRangeConf, 0) ranges = append(ranges, ipam) i.Ranges = ranges + route, err := NewIPAMDefaultRoute(IsIPv6(subnet.IP)) + if err != nil { + return MacVLANConfig{}, err + } + i.Routes = []IPAMRoute{route} + i.PluginType = "host-local" } m := MacVLANConfig{ diff --git a/test/e2e/network_test.go b/test/e2e/network_test.go index 6f28d7e19f..a7e61932ed 100644 --- a/test/e2e/network_test.go +++ b/test/e2e/network_test.go @@ -533,7 +533,11 @@ var _ = Describe("Podman network", func() { out, err := inspect.jq(".[0].plugins[0].master") Expect(err).To(BeNil()) - Expect(out).To(Equal("\"lo\"")) + Expect(out).To(Equal(`"lo"`)) + + ipamType, err := inspect.jq(".[0].plugins[0].ipam.type") + Expect(err).To(BeNil()) + Expect(ipamType).To(Equal(`"dhcp"`)) nc = podmanTest.Podman([]string{"network", "rm", net}) nc.WaitWithDefaultTimeout() @@ -571,13 +575,29 @@ var _ = Describe("Podman network", func() { Expect(err).To(BeNil()) Expect(mtu).To(Equal("1500")) + name, err := inspect.jq(".[0].plugins[0].type") + Expect(err).To(BeNil()) + Expect(name).To(Equal(`"macvlan"`)) + + netInt, err := inspect.jq(".[0].plugins[0].master") + Expect(err).To(BeNil()) + Expect(netInt).To(Equal(`"lo"`)) + + ipamType, err := inspect.jq(".[0].plugins[0].ipam.type") + Expect(err).To(BeNil()) + Expect(ipamType).To(Equal(`"host-local"`)) + gw, err := inspect.jq(".[0].plugins[0].ipam.ranges[0][0].gateway") Expect(err).To(BeNil()) - Expect(gw).To(Equal("\"192.168.1.254\"")) + Expect(gw).To(Equal(`"192.168.1.254"`)) subnet, err := inspect.jq(".[0].plugins[0].ipam.ranges[0][0].subnet") Expect(err).To(BeNil()) - Expect(subnet).To(Equal("\"192.168.1.0/24\"")) + Expect(subnet).To(Equal(`"192.168.1.0/24"`)) + + routes, err := inspect.jq(".[0].plugins[0].ipam.routes[0].dst") + Expect(err).To(BeNil()) + Expect(routes).To(Equal(`"0.0.0.0/0"`)) nc = podmanTest.Podman([]string{"network", "rm", net}) nc.WaitWithDefaultTimeout()