Skip to content

Commit

Permalink
Introduce VSOCK link type
Browse files Browse the repository at this point in the history
This address family is used in communication between virtual machines
and their hosts. Advantages include that no virtual ethernet adapter
and their respective address configuration and routing need to be
setup. Rather, with this new link type, only a single yggdrasil
interface can exist inside of the virtual machine.

It can also be used inside of containers. There, the advantage over
existing link types like unix sockets include, that no mount point
need to be shared with the host and container. This provides more
isolation.

More information:

https://man7.org/linux/man-pages/man7/vsock.7.html

https://gist.github.com/nrdmn/7971be650919b112343b1cb2757a3fe6
  • Loading branch information
nagy committed Jan 3, 2025
1 parent d252278 commit b19e574
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 0 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,13 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- in case of vulnerabilities.
-->

## [0.5.xx] - 2025-xx-xx

### Added

* VSOCK support for peerings, by using the new `vsock://` scheme in `Listen` and `Peers`.
* Use e.g. `vsock://local:1234`.

## [0.5.12] - 2024-12-18

* Go 1.22 is now required to build Yggdrasil
Expand Down
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ require (
github.com/hashicorp/go-syslog v1.0.0
github.com/hjson/hjson-go/v4 v4.4.0
github.com/kardianos/minwinsvc v1.0.2
github.com/mdlayher/vsock v1.2.1
github.com/quic-go/quic-go v0.48.2
github.com/vishvananda/netlink v1.3.0
github.com/wlynxg/anet v0.0.5
Expand All @@ -29,6 +30,7 @@ require (
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mdlayher/socket v0.4.1 // indirect
github.com/onsi/ginkgo/v2 v2.9.5 // indirect
github.com/rivo/uniseg v0.2.0 // indirect
go.uber.org/mock v0.4.0 // indirect
Expand Down
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mdlayher/socket v0.4.1 h1:eM9y2/jlbs1M615oshPQOHZzj6R6wMT7bX5NPiQvn2U=
github.com/mdlayher/socket v0.4.1/go.mod h1:cAqeGjoufqdxWkD7DkpyS+wcefOtmu5OQ8KuoJGIReA=
github.com/mdlayher/vsock v1.2.1 h1:pC1mTJTvjo1r9n9fbm7S1j04rCgCzhCOS5DY0zqHlnQ=
github.com/mdlayher/vsock v1.2.1/go.mod h1:NRfCibel++DgeMD8z/hP+PPTjlNJsdPOmxcnENvE+SE=
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
github.com/onsi/ginkgo/v2 v2.9.5 h1:+6Hr4uxzP4XIUyAkg61dWBw8lb/gc4/X5luuxN/EC+Q=
Expand Down
6 changes: 6 additions & 0 deletions src/core/link.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ type links struct {
quic *linkQUIC // QUIC interface support
ws *linkWS // WS interface support
wss *linkWSS // WSS interface support
vsock *linkVSOCK // VSOCK interface support
// _links can only be modified safely from within the links actor
_links map[linkInfo]*link // *link is nil if connection in progress
_listeners map[*Listener]context.CancelFunc
Expand Down Expand Up @@ -96,6 +97,7 @@ func (l *links) init(c *Core) error {
l.quic = l.newLinkQUIC()
l.ws = l.newLinkWS()
l.wss = l.newLinkWSS()
l.vsock = l.newLinkVSOCK()
l._links = make(map[linkInfo]*link)
l._listeners = make(map[*Listener]context.CancelFunc)

Expand Down Expand Up @@ -444,6 +446,8 @@ func (l *links) listen(u *url.URL, sintf string, local bool) (*Listener, error)
protocol = l.ws
case "wss":
protocol = l.wss
case "vsock":
protocol = l.vsock
default:
ctxcancel()
return nil, ErrLinkUnrecognisedSchema
Expand Down Expand Up @@ -595,6 +599,8 @@ func (l *links) connect(ctx context.Context, u *url.URL, info linkInfo, options
dialer = l.ws
case "wss":
dialer = l.wss
case "vsock":
dialer = l.vsock
default:
return nil, ErrLinkUnrecognisedSchema
}
Expand Down
69 changes: 69 additions & 0 deletions src/core/link_vsock.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package core

import (
"context"
"fmt"
"net"
"net/url"
"strconv"
"strings"

"github.com/Arceliar/phony"
"github.com/mdlayher/vsock"
)

type linkVSOCK struct {
phony.Inbox
*links
}

func (l *links) newLinkVSOCK() *linkVSOCK {
lt := &linkVSOCK{
links: l,
}
return lt
}

func (l *linkVSOCK) dial(ctx context.Context, url *url.URL, info linkInfo, options linkOptions) (net.Conn, error) {
localPort, err := strconv.Atoi(url.Port())
if err != nil {
return nil, fmt.Errorf("no VSOCK port specified: %w", err)
}
contextId, err := urlParseContextId(url)
if err != nil {
return nil, fmt.Errorf("Unknown VSOCK host and cannot parse as numerical contextID: %w", err)
}
return vsock.Dial(contextId, uint32(localPort), nil)

Check failure

Code scanning / CodeQL

Incorrect conversion between integer types High

Incorrect conversion of an integer with architecture-dependent bit size from
strconv.Atoi
to a lower bit size type uint32 without an upper bound check.
}

func (l *linkVSOCK) listen(ctx context.Context, url *url.URL, _ string) (net.Listener, error) {
localPort, err := strconv.Atoi(url.Port())
if err != nil {
return nil, fmt.Errorf("no VSOCK port specified: %w", err)
}
contextId, err := urlParseContextId(url)
if err != nil {
return nil, fmt.Errorf("Unknown VSOCK host and cannot parse as numerical contextID: %w", err)
}
return vsock.ListenContextID(contextId, uint32(localPort), nil)

Check failure

Code scanning / CodeQL

Incorrect conversion between integer types High

Incorrect conversion of an integer with architecture-dependent bit size from
strconv.Atoi
to a lower bit size type uint32 without an upper bound check.
}

func urlParseContextId(u *url.URL) (uint32, error) {
var contextId uint32

switch strings.ToLower(u.Hostname()) {
case "hypervisor":
contextId = vsock.Hypervisor
case "local":
contextId = vsock.Local
case "host":
contextId = vsock.Host
default:
parsedHost, err := strconv.Atoi(u.Hostname())
if err != nil {
return 0, err
}
contextId = uint32(parsedHost)

Check failure

Code scanning / CodeQL

Incorrect conversion between integer types High

Incorrect conversion of an integer with architecture-dependent bit size from
strconv.Atoi
to a lower bit size type uint32 without an upper bound check.
}
return contextId, nil
}

0 comments on commit b19e574

Please sign in to comment.