Skip to content

Commit 156fcce

Browse files
committed
Support for lima usernet network
Signed-off-by: Balaji Vijayakumar <[email protected]>
1 parent 7443f96 commit 156fcce

File tree

22 files changed

+933
-154
lines changed

22 files changed

+933
-154
lines changed

cmd/limactl/main.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ func newApp() *cobra.Command {
100100
newEditCommand(),
101101
newFactoryResetCommand(),
102102
newDiskCommand(),
103+
newUsernetCommand(),
103104
)
104105
return rootCmd
105106
}

cmd/limactl/usernet.go

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
package main
2+
3+
import (
4+
"errors"
5+
"fmt"
6+
"os"
7+
"strconv"
8+
9+
"github.com/lima-vm/lima/pkg/usernet"
10+
"github.com/spf13/cobra"
11+
)
12+
13+
func newUsernetCommand() *cobra.Command {
14+
var hostagentCommand = &cobra.Command{
15+
Use: "usernet",
16+
Short: "run usernet",
17+
Args: cobra.ExactArgs(0),
18+
RunE: usernetAction,
19+
Hidden: true,
20+
}
21+
hostagentCommand.Flags().StringP("pidfile", "p", "", "write pid to file")
22+
hostagentCommand.Flags().StringP("endpoint", "e", "", "exposes usernet api(s) on this endpoint")
23+
hostagentCommand.Flags().String("listen-qemu", "", "listen for qemu connections")
24+
hostagentCommand.Flags().String("listen-fd", "", "listen for fd connections")
25+
hostagentCommand.Flags().Int("mtu", 1500, "mtu")
26+
return hostagentCommand
27+
}
28+
29+
func usernetAction(cmd *cobra.Command, args []string) error {
30+
31+
pidfile, err := cmd.Flags().GetString("pidfile")
32+
if err != nil {
33+
return err
34+
}
35+
if pidfile != "" {
36+
if _, err := os.Stat(pidfile); !errors.Is(err, os.ErrNotExist) {
37+
return fmt.Errorf("pidfile %q already exists", pidfile)
38+
}
39+
if err := os.WriteFile(pidfile, []byte(strconv.Itoa(os.Getpid())+"\n"), 0644); err != nil {
40+
return err
41+
}
42+
defer os.RemoveAll(pidfile)
43+
}
44+
endpoint, err := cmd.Flags().GetString("endpoint")
45+
if err != nil {
46+
return err
47+
}
48+
qemuSocket, err := cmd.Flags().GetString("listen-qemu")
49+
if err != nil {
50+
return err
51+
}
52+
fdSocket, err := cmd.Flags().GetString("listen-fd")
53+
if err != nil {
54+
return err
55+
}
56+
57+
mtu, err := cmd.Flags().GetInt("mtu")
58+
if err != nil {
59+
return err
60+
}
61+
62+
os.RemoveAll(endpoint)
63+
os.RemoveAll(qemuSocket)
64+
os.RemoveAll(fdSocket)
65+
66+
return usernet.StartGVisorNetstack(cmd.Context(), &usernet.GVisorNetstackOpts{
67+
MTU: mtu,
68+
Endpoint: endpoint,
69+
QemuSocket: qemuSocket,
70+
FdSocket: fdSocket,
71+
})
72+
}

examples/experimental/usernet.yaml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Example to run vz instance with lima usernet enabled
2+
vmType: "vz"
3+
images:
4+
- location: "https://cloud-images.ubuntu.com/releases/22.04/release/ubuntu-22.04-server-cloudimg-amd64.img"
5+
arch: "x86_64"
6+
- location: "https://cloud-images.ubuntu.com/releases/22.04/release/ubuntu-22.04-server-cloudimg-arm64.img"
7+
arch: "aarch64"
8+
9+
mounts:
10+
- location: "~"
11+
- location: "/tmp/lima"
12+
writable: true
13+
mountType: "virtiofs"
14+
usernet:
15+
enabled: true

go.mod

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ require (
99
github.com/cheggaaa/pb/v3 v3.1.0
1010
github.com/containerd/containerd v1.6.18
1111
github.com/containerd/continuity v0.3.0
12-
github.com/containers/gvisor-tap-vsock v0.5.0
12+
github.com/containers/gvisor-tap-vsock v0.5.1-0.20230220110902-2732d3a55dc7
1313
github.com/coreos/go-semver v0.3.1
1414
github.com/cyphar/filepath-securejoin v0.2.3
1515
github.com/digitalocean/go-qemu v0.0.0-20210326154740-ac9e0b687001
@@ -78,10 +78,13 @@ require (
7878
github.com/json-iterator/go v1.1.12 // indirect
7979
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
8080
github.com/kr/fs v0.1.0 // indirect
81+
github.com/linuxkit/virtsock v0.0.0-20220523201153-1a23e78aa7a2 // indirect
8182
github.com/magiconair/properties v1.8.7 // indirect
8283
github.com/mailru/easyjson v0.7.6 // indirect
8384
github.com/mattn/go-colorable v0.1.13 // indirect
8485
github.com/mattn/go-runewidth v0.0.12 // indirect
86+
github.com/mdlayher/socket v0.4.0 // indirect
87+
github.com/mdlayher/vsock v1.2.0 // indirect
8588
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect
8689
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
8790
github.com/modern-go/reflect2 v1.0.2 // indirect
@@ -95,10 +98,10 @@ require (
9598
go.uber.org/multierr v1.7.0 // indirect
9699
golang.org/x/crypto v0.4.0 // indirect
97100
golang.org/x/mod v0.6.0 // indirect
98-
golang.org/x/net v0.4.0 // indirect
101+
golang.org/x/net v0.7.0 // indirect
99102
golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b // indirect
100-
golang.org/x/term v0.3.0 // indirect
101-
golang.org/x/text v0.5.0 // indirect
103+
golang.org/x/term v0.5.0 // indirect
104+
golang.org/x/text v0.7.0 // indirect
102105
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 // indirect
103106
golang.org/x/tools v0.2.0 // indirect
104107
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect

go.sum

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,8 @@ github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDG
111111
github.com/containerd/ttrpc v1.0.2/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y=
112112
github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc=
113113
github.com/containerd/typeurl v0.0.0-20200205145503-b45ef1f1f737/go.mod h1:TB1hUtrpaiO88KEK56ijojHS1+NeF0izUACaJW2mdXg=
114-
github.com/containers/gvisor-tap-vsock v0.5.0 h1:hoCkrfQ96tjek2BtiW1BHy50zAQCzkqeiAQY96y6NLk=
115-
github.com/containers/gvisor-tap-vsock v0.5.0/go.mod h1:jrnI5plQtmys5LEKpXcCCrLqZlrHsozQg0V2Jw1UG74=
114+
github.com/containers/gvisor-tap-vsock v0.5.1-0.20230220110902-2732d3a55dc7 h1:Ej2OTGLHMjcpnGApet9gmEfboe9aTT2eU/civ1Imm6g=
115+
github.com/containers/gvisor-tap-vsock v0.5.1-0.20230220110902-2732d3a55dc7/go.mod h1:RfDVvmr+DHvp6whJVEwrMn+hfTYIPLWlUPJhWXNUsCM=
116116
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
117117
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
118118
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
@@ -376,6 +376,8 @@ github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
376376
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
377377
github.com/lima-vm/sshocker v0.3.2 h1:o0WqVzcpt6mzVCuqtS3N3O8kwTx6X4SLr4h7YaRISuE=
378378
github.com/lima-vm/sshocker v0.3.2/go.mod h1:9SWN6wob210VM6oJkkzvWQOlHSp/rQLB+0fSEc92zig=
379+
github.com/linuxkit/virtsock v0.0.0-20220523201153-1a23e78aa7a2 h1:DZMFueDbfz6PNc1GwDRA8+6lBx1TB9UnxDQliCqR73Y=
380+
github.com/linuxkit/virtsock v0.0.0-20220523201153-1a23e78aa7a2/go.mod h1:SWzULI85WerrFt3u+nIm5F9l7EvxZTKQvd0InF3nmgM=
379381
github.com/lithammer/dedent v1.1.0 h1:VNzHMVCBNG1j0fh3OrsFRkVUwStdDArbgBWoPAffktY=
380382
github.com/lithammer/dedent v1.1.0/go.mod h1:jrXYCQtgg0nJiN+StA2KgR7w6CiQNv9Fd/Z9BP0jIOc=
381383
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
@@ -409,6 +411,10 @@ github.com/mdlayher/netlink v1.1.1/go.mod h1:WTYpFb/WTvlRJAyKhZL5/uy69TDDpHHu2VZ
409411
github.com/mdlayher/raw v0.0.0-20190606142536-fef19f00fc18/go.mod h1:7EpbotpCmVZcu+KCX4g9WaRNuu11uyhiW7+Le1dKawg=
410412
github.com/mdlayher/raw v0.0.0-20191009151244-50f2db8cc065 h1:aFkJ6lx4FPip+S+Uw4aTegFMct9shDvP+79PsSxpm3w=
411413
github.com/mdlayher/raw v0.0.0-20191009151244-50f2db8cc065/go.mod h1:7EpbotpCmVZcu+KCX4g9WaRNuu11uyhiW7+Le1dKawg=
414+
github.com/mdlayher/socket v0.4.0 h1:280wsy40IC9M9q1uPGcLBwXpcTQDtoGwVt+BNoITxIw=
415+
github.com/mdlayher/socket v0.4.0/go.mod h1:xxFqz5GRCUN3UEOm9CZqEJsAbe1C8OwSK46NlmWuVoc=
416+
github.com/mdlayher/vsock v1.2.0 h1:klRY9lndjmg6k/QWbX/ucQ3e2JFRm1M7vfG9hijbQ0A=
417+
github.com/mdlayher/vsock v1.2.0/go.mod h1:w4kdSTQB9p1l/WwGmAs0V62qQ869qRYoongwgN+Y1HE=
412418
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4=
413419
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
414420
github.com/miekg/dns v1.1.25/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso=
@@ -444,7 +450,7 @@ github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
444450
github.com/onsi/ginkgo/v2 v2.4.0 h1:+Ig9nvqgS5OBSACXNk15PLdp0U9XPYROt9CFzVdFGIs=
445451
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
446452
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
447-
github.com/onsi/gomega v1.24.2 h1:J/tulyYK6JwBldPViHJReihxxZ+22FHs0piGjQAvoUE=
453+
github.com/onsi/gomega v1.27.1 h1:rfztXRbg6nv/5f+Raen9RcGoSecHIFgBBLQK3Wdj754=
448454
github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
449455
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
450456
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
@@ -639,8 +645,8 @@ golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96b
639645
golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
640646
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
641647
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
642-
golang.org/x/net v0.4.0 h1:Q5QPcMlvfxFTAPV0+07Xz/MpK9NTXu2VDUuy0FeMfaU=
643-
golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
648+
golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g=
649+
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
644650
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
645651
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
646652
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -742,8 +748,8 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
742748
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
743749
golang.org/x/term v0.0.0-20210503060354-a79de5458b56/go.mod h1:tfny5GFUkzUvx4ps4ajbZsCe5lw1metzhBm9T3x7oIY=
744750
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
745-
golang.org/x/term v0.3.0 h1:qoo4akIqOcDME5bhc/NgxUdovd6BSS2uMsVjB56q1xI=
746-
golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA=
751+
golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY=
752+
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
747753
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
748754
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
749755
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -754,8 +760,8 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
754760
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
755761
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
756762
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
757-
golang.org/x/text v0.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM=
758-
golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
763+
golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo=
764+
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
759765
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
760766
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
761767
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=

pkg/fd/fd.go

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
// This file has been adapted from https://github.com/ftrvxmtrx/fd/blob/master/fd.go
2+
3+
// Package fd provides a simple API to pass file descriptors
4+
// between different OS processes.
5+
//
6+
// It can be useful if you want to inherit network connections
7+
// from another process without closing them.
8+
//
9+
// Example scenario:
10+
//
11+
// 1. Running server receives a "let's upgrade" message
12+
// 2. Server opens a Unix domain socket for the "upgrade"
13+
// 3. Server starts a new copy of itself and passes Unix domain socket name
14+
// 4. New copy starts reading for the socket
15+
// 5. Server sends its state over the socket, also sending the number
16+
// of network connections to inherit, then it sends those connections
17+
// using fd.Put()
18+
// 6. New copy reads the state and inherits connections using fd.Get(),
19+
// checks that everything is OK and sends the "OK" message to the socket
20+
// 7. Server receives "OK" message and kills itself
21+
package fd
22+
23+
import (
24+
"net"
25+
"os"
26+
"syscall"
27+
)
28+
29+
// Get receives single file descriptors from a Unix domain socket.
30+
//
31+
// Num specifies the expected number of file descriptors in one message.
32+
// Internal files' names to be assigned are specified via optional filenames
33+
// argument.
34+
//
35+
// You need to close all files in the returned slice. The slice can be
36+
// non-empty even if this function returns an error.
37+
//
38+
// Use net.FileConn() if you're receiving a network connection.
39+
func Get(via *net.UnixConn, num int, filenames []string) ([]*os.File, error) {
40+
if num < 1 {
41+
return nil, nil
42+
}
43+
44+
// get the underlying socket
45+
viaf, err := via.File()
46+
if err != nil {
47+
return nil, err
48+
}
49+
socket := int(viaf.Fd())
50+
defer viaf.Close()
51+
52+
// recvmsg
53+
buf := make([]byte, syscall.CmsgSpace(num*4))
54+
_, _, _, _, err = syscall.Recvmsg(socket, nil, buf, 0)
55+
if err != nil {
56+
return nil, err
57+
}
58+
59+
// parse control msgs
60+
var msgs []syscall.SocketControlMessage
61+
msgs, err = syscall.ParseSocketControlMessage(buf)
62+
63+
// convert fds to files
64+
res := make([]*os.File, 0, len(msgs))
65+
for i := 0; i < len(msgs) && err == nil; i++ {
66+
var fds []int
67+
fds, err = syscall.ParseUnixRights(&msgs[i])
68+
69+
for fi, fd := range fds {
70+
var filename string
71+
if fi < len(filenames) {
72+
filename = filenames[fi]
73+
}
74+
75+
res = append(res, os.NewFile(uintptr(fd), filename))
76+
}
77+
}
78+
79+
return res, err
80+
}
81+
82+
// Put sends file descriptors to Unix domain socket.
83+
//
84+
// Please note that the number of descriptors in one message is limited
85+
// and is rather small.
86+
// Use conn.File() to get a file if you want to put a network connection.
87+
func Put(via *net.UnixConn, files ...*os.File) error {
88+
if len(files) == 0 {
89+
return nil
90+
}
91+
92+
viaf, err := via.File()
93+
if err != nil {
94+
return err
95+
}
96+
socket := int(viaf.Fd())
97+
defer viaf.Close()
98+
99+
fds := make([]int, len(files))
100+
for i := range files {
101+
fds[i] = int(files[i].Fd())
102+
}
103+
104+
rights := syscall.UnixRights(fds...)
105+
return syscall.Sendmsg(socket, nil, rights, nil, 0)
106+
}

0 commit comments

Comments
 (0)