Skip to content

Commit

Permalink
slirp configurator: Support ifaces with network binding plugin
Browse files Browse the repository at this point in the history
Signed-off-by: Or Mergi <ormergi@redhat.com>
  • Loading branch information
ormergi committed Aug 17, 2023
1 parent e27a7ea commit 487446e
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 23 deletions.
40 changes: 40 additions & 0 deletions cmd/network-slirp-binding/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,43 @@ It will be used by Kubevirt to offload slirp networking configuration.

> _NOTE_:
> Slirp network binding is supported for pod network interfaces only.
# How to use

Register the `slirp` binding plugin with its sidecar image:

```yaml
apiVersion: kubevirt.io/v1
kind: KubeVirt
metadata:
name: kubevirt
namespace: kubevirt
spec:
configuration:
network:
binding:
slirp:
sidecarImage: registry:5000/kubevirt/network-slirp-binding:devel
...
```

In the VM spec, set interface to use `slirp` binding plugin:

```yaml
apiVersion: kubevirt.io/v1
kind: VirtualMachineInstance
metadata:
name: vmi-slirp
spec:
domain:
devices:
interfaces:
- name: slirp
binding:
name: slirp
...
networks:
- name: slirp-net
pod: {}
...
```
14 changes: 12 additions & 2 deletions cmd/network-slirp-binding/domain/domain.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ import (
"kubevirt.io/kubevirt/pkg/network/vmispec"
)

// SlirpPluginName slirp binding plugin name should be registered to Kubevirt through Kubevirt CR
const SlirpPluginName = "slirp"

type SlirpNetworkConfigurator struct {
vmiSpecIface *vmschema.Interface
vmiSpecNetwork *vmschema.Network
Expand All @@ -44,9 +47,16 @@ func NewSlirpNetworkConfigurator(ifaces []vmschema.Interface, networks []vmschem
if network == nil {
return nil, fmt.Errorf("pod network not found")
}

iface := vmispec.LookupInterfaceByName(ifaces, network.Name)
if iface == nil || iface.Slirp == nil {
return nil, fmt.Errorf("no slirp iface found")
if iface == nil {
return nil, fmt.Errorf("iface %q not found", network.Name)
}
if iface.Binding == nil && iface.Slirp == nil {
return nil, fmt.Errorf("iface %q is not set with slirp network binding plugin or slirp binding method", network.Name)
}
if iface.Binding != nil && iface.Binding.Name != SlirpPluginName {
return nil, fmt.Errorf("iface %q is not set with slirp network binding plugin", network.Name)
}

return &SlirpNetworkConfigurator{
Expand Down
58 changes: 37 additions & 21 deletions cmd/network-slirp-binding/domain/domain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,20 +34,36 @@ var _ = Describe("QEMU slirp networking", func() {
Context("configure domain spec slirp interface QMEU command line", func() {
var testSearchDomain = []string{"dns.com"}

It("should fail given no pod network", func() {
network := vmschema.Network{Name: "secondary", NetworkSource: vmschema.NetworkSource{Multus: &vmschema.MultusNetwork{}}}

_, err := domain.NewSlirpNetworkConfigurator(nil, []vmschema.Network{network}, nil)
Expect(err).To(HaveOccurred())
})

It("should fail given no slirp iface", func() {
network := vmschema.Network{Name: "secondary", NetworkSource: vmschema.NetworkSource{Multus: &vmschema.MultusNetwork{}}}
iface := vmschema.Interface{Name: "secondary", InterfaceBindingMethod: vmschema.InterfaceBindingMethod{Bridge: &vmschema.InterfaceBridge{}}}

_, err := domain.NewSlirpNetworkConfigurator([]vmschema.Interface{iface}, []vmschema.Network{network}, nil)
Expect(err).To(HaveOccurred())
})
DescribeTable("should fail, given",
func(iface vmschema.Interface, network vmschema.Network) {
_, err := domain.NewSlirpNetworkConfigurator(nil, []vmschema.Network{network}, nil)
Expect(err).To(HaveOccurred())
},
Entry("no pod network",
vmschema.Interface{},
vmschema.Network{Name: "secondary", NetworkSource: vmschema.NetworkSource{Multus: &vmschema.MultusNetwork{}}},
),
Entry("no iface",
vmschema.Interface{Name: "other", InterfaceBindingMethod: vmschema.InterfaceBindingMethod{Bridge: &vmschema.InterfaceBridge{}}},
vmschema.Network{Name: "secondary", NetworkSource: vmschema.NetworkSource{Pod: &vmschema.PodNetwork{}}},
),
Entry("iface with no binding method or network binding plugin",
vmschema.Interface{Name: "secondary"},
vmschema.Network{Name: "secondary", NetworkSource: vmschema.NetworkSource{Pod: &vmschema.PodNetwork{}}},
),
Entry("iface with no slirp binding method",
vmschema.Interface{Name: "secondary",
InterfaceBindingMethod: vmschema.InterfaceBindingMethod{Bridge: &vmschema.InterfaceBridge{}},
},
vmschema.Network{Name: "secondary", NetworkSource: vmschema.NetworkSource{Pod: &vmschema.PodNetwork{}}},
),
Entry("iface with no slirp network binding plugin",
vmschema.Interface{Name: "secondary",
Binding: &vmschema.PluginBinding{Name: "sriov"},
},
vmschema.Network{Name: "secondary", NetworkSource: vmschema.NetworkSource{Pod: &vmschema.PodNetwork{}}},
),
)

DescribeTable("should succeed, given",
func(iface vmschema.Interface, network vmschema.Network, expectedQEMUCmdArgs []domainschema.Arg) {
Expand All @@ -60,7 +76,7 @@ var _ = Describe("QEMU slirp networking", func() {
Expect(err).ToNot(HaveOccurred())
Expect(testMutator.Mutate(testDomainSpec)).To(Equal(expectedDomainSpec))
},
Entry("default slirp interface",
Entry("interface with slirp binding method",
*vmschema.DefaultSlirpNetworkInterface(),
*vmschema.DefaultPodNetwork(),
[]domainschema.Arg{
Expand All @@ -71,7 +87,7 @@ var _ = Describe("QEMU slirp networking", func() {
},
),
Entry("custom CIDR",
vmschema.Interface{Name: "slirpTest", InterfaceBindingMethod: vmschema.InterfaceBindingMethod{Slirp: &vmschema.InterfaceSlirp{}}},
vmschema.Interface{Name: "slirpTest", Binding: &vmschema.PluginBinding{Name: domain.SlirpPluginName}},
vmschema.Network{Name: "slirpTest", NetworkSource: vmschema.NetworkSource{Pod: &vmschema.PodNetwork{
VMNetworkCIDR: "192.168.100.0/24",
}}},
Expand All @@ -81,7 +97,7 @@ var _ = Describe("QEMU slirp networking", func() {
},
),
Entry("ports",
vmschema.Interface{Name: "slirpTest", InterfaceBindingMethod: vmschema.InterfaceBindingMethod{Slirp: &vmschema.InterfaceSlirp{}},
vmschema.Interface{Name: "slirpTest", Binding: &vmschema.PluginBinding{Name: domain.SlirpPluginName},
Ports: []vmschema.Port{
{Name: "http", Protocol: "TCP", Port: 80},
{Port: 8080},
Expand All @@ -94,7 +110,7 @@ var _ = Describe("QEMU slirp networking", func() {
},
),
Entry("slirp interface with virtio model type - should be changed to e1000",
vmschema.Interface{Name: "slirpTest", InterfaceBindingMethod: vmschema.InterfaceBindingMethod{Slirp: &vmschema.InterfaceSlirp{}},
vmschema.Interface{Name: "slirpTest", Binding: &vmschema.PluginBinding{Name: domain.SlirpPluginName},
Model: "virtio",
},
vmschema.Network{Name: "slirpTest", NetworkSource: vmschema.NetworkSource{Pod: &vmschema.PodNetwork{}}},
Expand All @@ -104,7 +120,7 @@ var _ = Describe("QEMU slirp networking", func() {
},
),
Entry("custom MAC address",
vmschema.Interface{Name: "slirpTest", InterfaceBindingMethod: vmschema.InterfaceBindingMethod{Slirp: &vmschema.InterfaceSlirp{}},
vmschema.Interface{Name: "slirpTest", Binding: &vmschema.PluginBinding{Name: domain.SlirpPluginName},
MacAddress: "02:02:02:02:02:02",
},
vmschema.Network{Name: "slirpTest", NetworkSource: vmschema.NetworkSource{Pod: &vmschema.PodNetwork{}}},
Expand Down Expand Up @@ -153,7 +169,7 @@ var _ = Describe("QEMU slirp networking", func() {
network := vmschema.Network{Name: "slirpTest", NetworkSource: vmschema.NetworkSource{Pod: &vmschema.PodNetwork{
VMNetworkCIDR: "592.468.300.0/24",
}}}
iface := vmschema.Interface{Name: "slirpTest", InterfaceBindingMethod: vmschema.InterfaceBindingMethod{Slirp: &vmschema.InterfaceSlirp{}}}
iface := vmschema.Interface{Name: "slirpTest", Binding: &vmschema.PluginBinding{Name: domain.SlirpPluginName}}

testMutator, err := domain.NewSlirpNetworkConfigurator([]vmschema.Interface{iface}, []vmschema.Network{network}, testSearchDomain)
Expect(err).ToNot(HaveOccurred())
Expand All @@ -163,7 +179,7 @@ var _ = Describe("QEMU slirp networking", func() {

DescribeTable("should fail given invalid port",
func(port int32) {
iface := vmschema.Interface{Name: "slirpTest", InterfaceBindingMethod: vmschema.InterfaceBindingMethod{Slirp: &vmschema.InterfaceSlirp{}},
iface := vmschema.Interface{Name: "slirpTest", Binding: &vmschema.PluginBinding{Name: domain.SlirpPluginName},
Ports: []vmschema.Port{{Port: port}},
}
network := vmschema.Network{Name: "slirpTest", NetworkSource: vmschema.NetworkSource{Pod: &vmschema.PodNetwork{}}}
Expand Down

0 comments on commit 487446e

Please sign in to comment.