aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd/podman/cliconfig/config.go1
-rw-r--r--cmd/podman/network_create.go11
-rw-r--r--completions/bash/podman1
-rw-r--r--docs/source/markdown/podman-network-create.1.md17
-rw-r--r--pkg/adapter/network.go51
-rw-r--r--pkg/network/config.go16
-rw-r--r--pkg/network/netconflist.go12
7 files changed, 104 insertions, 5 deletions
diff --git a/cmd/podman/cliconfig/config.go b/cmd/podman/cliconfig/config.go
index c15ce8829..431d5e087 100644
--- a/cmd/podman/cliconfig/config.go
+++ b/cmd/podman/cliconfig/config.go
@@ -278,6 +278,7 @@ type NetworkCreateValues struct {
IPRange net.IPNet
IPV6 bool
Network net.IPNet
+ MacVLAN string
}
type NetworkListValues struct {
diff --git a/cmd/podman/network_create.go b/cmd/podman/network_create.go
index 6710883ae..886607885 100644
--- a/cmd/podman/network_create.go
+++ b/cmd/podman/network_create.go
@@ -41,6 +41,7 @@ func init() {
flags.IPVar(&networkCreateCommand.Gateway, "gateway", nil, "IPv4 or IPv6 gateway for the subnet")
flags.BoolVar(&networkCreateCommand.Internal, "internal", false, "restrict external access from this network")
flags.IPNetVar(&networkCreateCommand.IPRange, "ip-range", net.IPNet{}, "allocate container IP from range")
+ flags.StringVar(&networkCreateCommand.MacVLAN, "macvlan", "", "create a Macvlan connection based on this device")
// TODO not supported yet
//flags.StringVar(&networkCreateCommand.IPamDriver, "ipam-driver", "", "IP Address Management Driver")
// TODO enable when IPv6 is working
@@ -50,6 +51,10 @@ func init() {
}
func networkcreateCmd(c *cliconfig.NetworkCreateValues) error {
+ var (
+ fileName string
+ err error
+ )
if err := network.IsSupportedDriver(c.Driver); err != nil {
return err
}
@@ -66,7 +71,11 @@ func networkcreateCmd(c *cliconfig.NetworkCreateValues) error {
if err != nil {
return err
}
- fileName, err := runtime.NetworkCreate(c)
+ if len(c.MacVLAN) > 0 {
+ fileName, err = runtime.NetworkCreateMacVLAN(c)
+ } else {
+ fileName, err = runtime.NetworkCreateBridge(c)
+ }
if err == nil {
fmt.Println(fileName)
}
diff --git a/completions/bash/podman b/completions/bash/podman
index 18e2460ec..f37b45837 100644
--- a/completions/bash/podman
+++ b/completions/bash/podman
@@ -980,6 +980,7 @@ _podman_network_create() {
--driver
--gateway
--ip-range
+ --macvlan
--subnet
"
local boolean_options="
diff --git a/docs/source/markdown/podman-network-create.1.md b/docs/source/markdown/podman-network-create.1.md
index c281d50d9..2eca93adb 100644
--- a/docs/source/markdown/podman-network-create.1.md
+++ b/docs/source/markdown/podman-network-create.1.md
@@ -7,8 +7,10 @@ podman\-network-create - Create a Podman CNI network
**podman network create** [*options*] name
## DESCRIPTION
-Create a CNI-network configuration for use with Podman. At the time of this writing, the only network
-type that can be created is a *bridge* network.
+Create a CNI-network configuration for use with Podman. By default, Podman creates a bridge connection. A
+*Macvlan* connection can be created with the *macvlan* option. In the case of *Macvlan* connections, the
+CNI *dhcp* plugin needs to be activated or the container image must have a DHCP client to interact
+with the host network's DHCP server.
If no options are provided, Podman will assign a free subnet and name for your network.
@@ -38,6 +40,11 @@ Restrict external access of this network
Allocate container IP from a range. The range must be a complete subnet and in CIDR notation. The *ip-range* option
must be used with a *subnet* option.
+**--macvlan**
+
+Create a *Macvlan* based connection rather than a classic bridge. You must pass an interface name from the host for the
+Macvlan connection.
+
**--subnet**
The subnet in CIDR notation.
@@ -68,6 +75,12 @@ Create a network that uses a *192.168.55.0/24** subnet and has an IP address ran
/etc/cni/net.d/cni-podman-5.conflist
```
+Create a Macvlan based network using the host interface eth0
+```
+# podman network create --macvlan eth0 newnet
+/etc/cni/net.d/newnet.conflist
+```
+
## SEE ALSO
podman(1), podman-network(1), podman-network-inspect(1)
diff --git a/pkg/adapter/network.go b/pkg/adapter/network.go
index 9659ae339..160e334e9 100644
--- a/pkg/adapter/network.go
+++ b/pkg/adapter/network.go
@@ -153,8 +153,8 @@ func (r *LocalRuntime) removeNetwork(ctx context.Context, name string, container
return nil
}
-// NetworkCreate creates a CNI network
-func (r *LocalRuntime) NetworkCreate(cli *cliconfig.NetworkCreateValues) (string, error) {
+// NetworkCreateBridge creates a CNI network
+func (r *LocalRuntime) NetworkCreateBridge(cli *cliconfig.NetworkCreateValues) (string, error) {
isGateway := true
ipMasq := true
subnet := &cli.Network
@@ -262,3 +262,50 @@ func (r *LocalRuntime) NetworkCreate(cli *cliconfig.NetworkCreateValues) (string
err = ioutil.WriteFile(cniPathName, b, 0644)
return cniPathName, err
}
+
+// NetworkCreateMacVLAN creates a CNI network
+func (r *LocalRuntime) NetworkCreateMacVLAN(cli *cliconfig.NetworkCreateValues) (string, error) {
+ var (
+ name string
+ plugins []network.CNIPlugins
+ )
+ liveNetNames, err := network.GetLiveNetworkNames()
+ if err != nil {
+ return "", err
+ }
+ // Make sure the host-device exists
+ if !util.StringInSlice(cli.MacVLAN, liveNetNames) {
+ return "", errors.Errorf("failed to find network interface %q", cli.MacVLAN)
+ }
+ if len(cli.InputArgs) > 0 {
+ name = cli.InputArgs[0]
+ netNames, err := network.GetNetworkNamesFromFileSystem()
+ if err != nil {
+ return "", err
+ }
+ if util.StringInSlice(name, netNames) {
+ return "", errors.Errorf("the network name %s is already used", name)
+ }
+ }
+ if len(name) < 1 {
+ name, err = network.GetFreeDeviceName()
+ if err != nil {
+ return "", err
+ }
+ }
+ ncList := network.NewNcList(name, cniversion.Current())
+ macvlan := network.NewMacVLANPlugin(cli.MacVLAN)
+ plugins = append(plugins, macvlan)
+ ncList["plugins"] = plugins
+ b, err := json.MarshalIndent(ncList, "", " ")
+ if err != nil {
+ return "", err
+ }
+ cniConfigPath, err := getCNIConfDir(r)
+ if err != nil {
+ return "", err
+ }
+ cniPathName := filepath.Join(cniConfigPath, fmt.Sprintf("%s.conflist", name))
+ err = ioutil.WriteFile(cniPathName, b, 0644)
+ return cniPathName, err
+}
diff --git a/pkg/network/config.go b/pkg/network/config.go
index 37eb0dd64..e47b16143 100644
--- a/pkg/network/config.go
+++ b/pkg/network/config.go
@@ -90,6 +90,22 @@ func (p PortMapConfig) Bytes() ([]byte, error) {
return json.MarshalIndent(p, "", "\t")
}
+type IPAMDHCP struct {
+ DHCP string `json:"type"`
+}
+
+// MacVLANConfig describes the macvlan config
+type MacVLANConfig struct {
+ PluginType string `json:"type"`
+ Master string `json:"master"`
+ IPAM IPAMDHCP `json:"ipam"`
+}
+
+// Bytes outputs the configuration as []byte
+func (p MacVLANConfig) Bytes() ([]byte, error) {
+ return json.MarshalIndent(p, "", "\t")
+}
+
// FirewallConfig describes the firewall plugin
type FirewallConfig struct {
PluginType string `json:"type"`
diff --git a/pkg/network/netconflist.go b/pkg/network/netconflist.go
index e19051b88..a8217097a 100644
--- a/pkg/network/netconflist.go
+++ b/pkg/network/netconflist.go
@@ -132,3 +132,15 @@ func HasDNSNamePlugin(paths []string) bool {
}
return false
}
+
+// NewMacVLANPlugin creates a macvlanconfig with a given device name
+func NewMacVLANPlugin(device string) MacVLANConfig {
+ i := IPAMDHCP{DHCP: "dhcp"}
+
+ m := MacVLANConfig{
+ PluginType: "macvlan",
+ Master: device,
+ IPAM: i,
+ }
+ return m
+}