Skip to content

Commit

Permalink
Merge pull request #231 from cfergeau/vfkit
Browse files Browse the repository at this point in the history
Add vfkit support
  • Loading branch information
openshift-merge-robot authored Jun 22, 2023
2 parents 9bfaf52 + d2db521 commit 9b06a04
Show file tree
Hide file tree
Showing 9 changed files with 166 additions and 0 deletions.
40 changes: 40 additions & 0 deletions cmd/gvproxy/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ var (
qemuSocket string
bessSocket string
stdioSocket string
vfkitSocket string
forwardSocket arrayFlags
forwardDest arrayFlags
forwardUser arrayFlags
Expand All @@ -59,6 +60,7 @@ func main() {
flag.StringVar(&qemuSocket, "listen-qemu", "", "Socket to be used by Qemu")
flag.StringVar(&bessSocket, "listen-bess", "", "unixpacket socket to be used by Bess-compatible applications")
flag.StringVar(&stdioSocket, "listen-stdio", "", "accept stdio pipe")
flag.StringVar(&vfkitSocket, "listen-vfkit", "", "unixgram socket to be used by vfkit-compatible applications")
flag.Var(&forwardSocket, "forward-sock", "Forwards a unix socket to the guest virtual machine over SSH")
flag.Var(&forwardDest, "forward-dest", "Forwards a unix socket to the guest virtual machine over SSH")
flag.Var(&forwardUser, "forward-user", "SSH user to use for unix socket forward")
Expand Down Expand Up @@ -101,6 +103,18 @@ func main() {
exitWithError(errors.Errorf("%q already exists", uri.Path))
}
}
if len(vfkitSocket) > 0 {
uri, err := url.Parse(vfkitSocket)
if err != nil || uri == nil {
exitWithError(errors.Wrapf(err, "invalid value for listen-vfkit"))
}
if uri.Scheme != "unixgram" {
exitWithError(errors.New("listen-vfkit must be unixgram:// address"))
}
if _, err := os.Stat(uri.Path); err == nil {
exitWithError(errors.Errorf("%q already exists", uri.Path))
}
}

if vpnkitSocket != "" && qemuSocket != "" {
exitWithError(errors.New("cannot use qemu and vpnkit protocol at the same time"))
Expand All @@ -124,6 +138,9 @@ func main() {
if bessSocket != "" {
protocol = types.BessProtocol
}
if vfkitSocket != "" {
protocol = types.VfkitProtocol
}

if c := len(forwardSocket); c != len(forwardDest) || c != len(forwardUser) || c != len(forwardIdentify) {
exitWithError(errors.New("-forward-sock, --forward-dest, --forward-user, and --forward-identity must all be specified together, " +
Expand Down Expand Up @@ -363,6 +380,29 @@ func run(ctx context.Context, g *errgroup.Group, configuration *types.Configurat
})
}

if vfkitSocket != "" {
conn, err := transport.ListenUnixgram(vfkitSocket)
if err != nil {
return err
}

g.Go(func() error {
<-ctx.Done()
if err := conn.Close(); err != nil {
log.Errorf("error closing %s: %q", vfkitSocket, err)
}
return os.Remove(vfkitSocket)
})

g.Go(func() error {
vfkitConn, err := transport.AcceptVfkit(conn)
if err != nil {
return err
}
return vn.AcceptVfkit(ctx, vfkitConn)
})
}

if stdioSocket != "" {
g.Go(func() error {
conn := stdio.GetStdioConn()
Expand Down
7 changes: 7 additions & 0 deletions pkg/tap/protocol.go → pkg/tap/protocols.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,10 @@ type bessProtocol struct {
func (s *bessProtocol) Stream() bool {
return false
}

type vfkitProtocol struct {
}

func (s *vfkitProtocol) Stream() bool {
return false
}
2 changes: 2 additions & 0 deletions pkg/tap/switch.go
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,8 @@ func protocolImplementation(protocol types.Protocol) protocol {
return &qemuProtocol{}
case types.BessProtocol:
return &bessProtocol{}
case types.VfkitProtocol:
return &vfkitProtocol{}
default:
return &hyperkitProtocol{}
}
Expand Down
14 changes: 14 additions & 0 deletions pkg/transport/listen_darwin.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,17 @@ func Listen(endpoint string) (net.Listener, error) {
return nil, errors.New("unexpected scheme")
}
}

func ListenUnixgram(endpoint string) (*net.UnixConn, error) {
parsed, err := url.Parse(endpoint)
if err != nil {
return nil, err
}
if parsed.Scheme != "unixgram" {
return nil, errors.New("unexpected scheme")
}
return net.ListenUnixgram("unixgram", &net.UnixAddr{
Name: parsed.Path,
Net: "unixgram",
})
}
14 changes: 14 additions & 0 deletions pkg/transport/listen_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,17 @@ func Listen(endpoint string) (net.Listener, error) {
return nil, errors.New("unexpected scheme")
}
}

func ListenUnixgram(endpoint string) (*net.UnixConn, error) {
parsed, err := url.Parse(endpoint)
if err != nil {
return nil, err
}
if parsed.Scheme != "unixgram" {
return nil, errors.New("unexpected scheme")
}
return net.ListenUnixgram("unixgram", &net.UnixAddr{
Name: parsed.Path,
Net: "unixgram",
})
}
8 changes: 8 additions & 0 deletions pkg/transport/listen_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,11 @@ func Listen(endpoint string) (net.Listener, error) {
return nil, errors.New("unexpected scheme")
}
}

func ListenUnixgram(endpoint string) (net.Conn, error) {
return nil, errors.New("unsupported 'unixgram' scheme")
}

func AcceptVfkit(listeningConn net.Conn) (net.Conn, error) {
return nil, errors.New("vfkit is unsupported on Windows")
}
67 changes: 67 additions & 0 deletions pkg/transport/unixgram_unix.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
//go:build !windows
// +build !windows

package transport

import (
"bytes"
"encoding/hex"
"fmt"
"net"
"syscall"
)

type connectedUnixgramConn struct {
*net.UnixConn
remoteAddr *net.UnixAddr
}

func connectListeningUnixgramConn(conn *net.UnixConn, remoteAddr *net.UnixAddr) (*connectedUnixgramConn, error) {
rawConn, err := conn.SyscallConn()
if err != nil {
return nil, err
}
err = rawConn.Control(func(fd uintptr) {
if err = syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_SNDBUF, 1*1024*1024); err != nil {
return
}
if err = syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_RCVBUF, 4*1024*1024); err != nil {
return
}
})
if err != nil {
return nil, err
}

return &connectedUnixgramConn{
UnixConn: conn,
remoteAddr: remoteAddr,
}, nil
}

func (conn *connectedUnixgramConn) RemoteAddr() net.Addr {
return conn.remoteAddr
}

func (conn *connectedUnixgramConn) Write(b []byte) (int, error) {
return conn.WriteTo(b, conn.remoteAddr)
}

func AcceptVfkit(listeningConn *net.UnixConn) (net.Conn, error) {
vfkitMagic := make([]byte, 4)
// the main reason for this magic check is to get the address to use to send data to the vfkit VM
bytesRead, vfkitAddr, err := listeningConn.ReadFrom(vfkitMagic)
if bytesRead != len(vfkitMagic) {
return nil, fmt.Errorf("invalid magic length: %d", len(vfkitMagic))
}
if err != nil {
return nil, err
}
if _, ok := vfkitAddr.(*net.UnixAddr); !ok {
return nil, fmt.Errorf("unexpected type for vfkit unix sockaddr: %t", vfkitAddr)
}
if !bytes.Equal(vfkitMagic, []byte("VFKT")) {
return nil, fmt.Errorf("invalid magic from the vfkit process: %s", hex.EncodeToString(vfkitMagic))
}
return connectListeningUnixgramConn(listeningConn, vfkitAddr.(*net.UnixAddr))
}
2 changes: 2 additions & 0 deletions pkg/types/configuration.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ const (
BessProtocol Protocol = "bess"
// StdioProtocol is HyperKitProtocol without the handshake
StdioProtocol Protocol = "stdio"
// VfkitProtocol transfers bare L2 packets as SOCK_DGRAM.
VfkitProtocol Protocol = "vfkit"
)

type Zone struct {
Expand Down
12 changes: 12 additions & 0 deletions pkg/virtualnetwork/vfkit.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package virtualnetwork

import (
"context"
"net"

"github.com/containers/gvisor-tap-vsock/pkg/types"
)

func (n *VirtualNetwork) AcceptVfkit(ctx context.Context, conn net.Conn) error {
return n.networkSwitch.Accept(ctx, conn, types.VfkitProtocol)
}

0 comments on commit 9b06a04

Please sign in to comment.