Skip to content

Commit 25b137d

Browse files
authored
Merge pull request #1279 from balajiv113/host_vm
support socket_vmnet for vz driver
2 parents 13fe50e + 714be8e commit 25b137d

File tree

5 files changed

+161
-7
lines changed

5 files changed

+161
-7
lines changed

docs/network.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,11 @@ If `useHostResolver` is false, then DNS servers can be configured manually in `l
4646

4747
VMNet assigns a "real" IP address that is reachable from the host.
4848

49-
The configuration steps are different across QEMU and VZ:
50-
- [QEMU](#qemu)
51-
- [VZ](#vz)
49+
The configuration steps are different for each network type:
50+
- [socket_vmnet](#socket_vmnet)
51+
- [vzNAT](#vzNAT)
5252

53-
### QEMU
53+
### socket_vmnet
5454
#### Managed (192.168.105.0/24)
5555

5656
[`socket_vmnet`](https://github.com/lima-vm/socket_vmnet) is required for adding another guest IP that is accessible from the host and other guests.
@@ -176,7 +176,7 @@ networks:
176176

177177
</details>
178178

179-
### VZ
179+
### vzNAT
180180

181181
> **Warning**
182182
> "vz" mode is experimental

examples/vmnet.yaml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
# Example to enable vmnet.framework for QEMU.
2-
# VZ users should refer to experimental/vz.yaml
1+
# Example to enable vmnet.framework.
32

43
# Usage:
54
# brew install socket_vmnet

pkg/vz/network_darwin.go

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
//go:build darwin && !no_vz
2+
// +build darwin,!no_vz
3+
4+
package vz
5+
6+
import (
7+
"context"
8+
"encoding/binary"
9+
"io"
10+
"net"
11+
"os"
12+
"time"
13+
14+
"github.com/sirupsen/logrus"
15+
"inet.af/tcpproxy"
16+
)
17+
18+
// DialQemu support connecting to QEMU supported network stack via unix socket
19+
// Returns os.File, connected dgram connection to be used for vz
20+
func DialQemu(unixSock string) (*os.File, error) {
21+
unixConn, err := net.Dial("unix", unixSock)
22+
if err != nil {
23+
return nil, err
24+
}
25+
qemuConn := &QEMUPacketConn{unixConn: unixConn}
26+
27+
server, client, err := createSockPair()
28+
if err != nil {
29+
return nil, err
30+
}
31+
dgramConn, err := net.FileConn(server)
32+
if err != nil {
33+
return nil, err
34+
}
35+
36+
remote := tcpproxy.DialProxy{
37+
DialContext: func(ctx context.Context, network, address string) (net.Conn, error) {
38+
return dgramConn, nil
39+
},
40+
}
41+
go remote.HandleConn(qemuConn)
42+
43+
return client, nil
44+
}
45+
46+
// QEMUPacketConn converts raw network packet to a QEMU supported network packet.
47+
type QEMUPacketConn struct {
48+
unixConn net.Conn
49+
}
50+
51+
var _ net.Conn = (*QEMUPacketConn)(nil)
52+
53+
// Read gets rid of the QEMU header packet and returns the raw packet as response
54+
func (v *QEMUPacketConn) Read(b []byte) (n int, err error) {
55+
header := make([]byte, 4)
56+
_, err = io.ReadFull(v.unixConn, header)
57+
if err != nil {
58+
logrus.Errorln("Failed to read header", err)
59+
}
60+
61+
size := binary.BigEndian.Uint32(header)
62+
reader := io.LimitReader(v.unixConn, int64(size))
63+
_, err = reader.Read(b)
64+
65+
if err != nil {
66+
logrus.Errorln("Failed to read packet", err)
67+
}
68+
return int(size), nil
69+
}
70+
71+
// Write puts QEMU header packet first and then writes the raw packet
72+
func (v *QEMUPacketConn) Write(b []byte) (n int, err error) {
73+
header := make([]byte, 4)
74+
binary.BigEndian.PutUint32(header, uint32(len(b)))
75+
_, err = v.unixConn.Write(header)
76+
if err != nil {
77+
logrus.Errorln("Failed to write header", err)
78+
}
79+
80+
write, err := v.unixConn.Write(b)
81+
if err != nil {
82+
logrus.Errorln("Failed to write packet", err)
83+
}
84+
return write, nil
85+
}
86+
func (v *QEMUPacketConn) Close() error {
87+
return v.unixConn.Close()
88+
}
89+
func (v *QEMUPacketConn) LocalAddr() net.Addr {
90+
return v.unixConn.LocalAddr()
91+
}
92+
93+
func (v *QEMUPacketConn) RemoteAddr() net.Addr {
94+
return v.unixConn.RemoteAddr()
95+
}
96+
97+
func (v *QEMUPacketConn) SetDeadline(t time.Time) error {
98+
return v.unixConn.SetDeadline(t)
99+
}
100+
101+
func (v *QEMUPacketConn) SetReadDeadline(t time.Time) error {
102+
return v.unixConn.SetReadDeadline(t)
103+
}
104+
105+
func (v *QEMUPacketConn) SetWriteDeadline(t time.Time) error {
106+
return v.unixConn.SetWriteDeadline(t)
107+
}

pkg/vz/vm_darwin.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,52 @@ func attachNetwork(driver *driver.BaseDriver, vmConfig *vz.VirtualMachineConfigu
234234
}
235235
configurations = append(configurations, networkConfig)
236236
}
237+
238+
if nw.Lima != "" {
239+
nwCfg, err := networks.Config()
240+
if err != nil {
241+
return err
242+
}
243+
socketVMNetOk, err := nwCfg.IsDaemonInstalled(networks.SocketVMNet)
244+
if err != nil {
245+
return err
246+
}
247+
if socketVMNetOk {
248+
logrus.Debugf("Using socketVMNet (%q)", nwCfg.Paths.SocketVMNet)
249+
sock, err := networks.Sock(nw.Lima)
250+
if err != nil {
251+
return err
252+
}
253+
254+
clientFile, err := DialQemu(sock)
255+
if err != nil {
256+
return err
257+
}
258+
attachment, err := vz.NewFileHandleNetworkDeviceAttachment(clientFile)
259+
if err != nil {
260+
return err
261+
}
262+
networkConfig, err = newVirtioNetworkDeviceConfiguration(attachment, nw.MACAddress)
263+
if err != nil {
264+
return err
265+
}
266+
configurations = append(configurations, networkConfig)
267+
}
268+
} else if nw.Socket != "" {
269+
clientFile, err := DialQemu(nw.Socket)
270+
if err != nil {
271+
return err
272+
}
273+
attachment, err := vz.NewFileHandleNetworkDeviceAttachment(clientFile)
274+
if err != nil {
275+
return err
276+
}
277+
networkConfig, err = newVirtioNetworkDeviceConfiguration(attachment, nw.MACAddress)
278+
if err != nil {
279+
return err
280+
}
281+
configurations = append(configurations, networkConfig)
282+
}
237283
}
238284
vmConfig.SetNetworkDevicesVirtualMachineConfiguration(configurations)
239285
return nil

pkg/vz/vz_driver_darwin.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,8 @@ func (l *LimaVzDriver) Validate() error {
8686

8787
for i, network := range l.Yaml.Networks {
8888
if unknown := reflectutil.UnknownNonEmptyFields(network, "VZNAT",
89+
"Lima",
90+
"Socket",
8991
"MACAddress",
9092
"Interface",
9193
); len(unknown) > 0 {

0 commit comments

Comments
 (0)