Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,8 @@ require (
github.com/NYTimes/gziphandler v1.1.1 // indirect
github.com/Rican7/retry v0.1.0 // indirect
github.com/RoaringBitmap/roaring v1.2.1 // indirect
github.com/adrg/xdg v0.5.3 // indirect
github.com/anatol/vmtest v0.0.0-20250318022921-2f32244e2f0f // indirect
github.com/andybalholm/brotli v1.1.0 // indirect
github.com/antlr4-go/antlr/v4 v4.13.0 // indirect
github.com/apache/thrift v0.20.0 // indirect
Expand All @@ -128,6 +130,7 @@ require (
github.com/beorn7/perks v1.0.1 // indirect
github.com/bits-and-blooms/bitset v1.2.0 // indirect
github.com/blang/semver/v4 v4.0.0 // indirect
github.com/bramvdbogaerde/go-scp v1.5.0 // indirect
github.com/buraksezer/consistent v0.10.0 // indirect
github.com/cactus/go-statsd-client/statsd v0.0.0-20200423205355-cb0885a1018c // indirect
github.com/cactus/go-statsd-client/v5 v5.1.0 // indirect
Expand Down Expand Up @@ -231,8 +234,10 @@ require (
github.com/joyent/triton-go v0.0.0-20180628001255-830d2b111e62 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
github.com/kdomanski/iso9660 v0.4.0 // indirect
github.com/kelseyhightower/envconfig v1.4.0 // indirect
github.com/klauspost/compress v1.18.0 // indirect
github.com/klauspost/cpuid/v2 v2.2.10 // indirect
github.com/kylelemons/godebug v1.1.0 // indirect
github.com/labstack/echo/v4 v4.10.0 // indirect
github.com/labstack/gommon v0.4.0 // indirect
Expand Down
10 changes: 10 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -90,13 +90,17 @@ github.com/RoaringBitmap/roaring v1.2.1 h1:58/LJlg/81wfEHd5L9qsHduznOIhyv4qb1yWc
github.com/RoaringBitmap/roaring v1.2.1/go.mod h1:icnadbWcNyfEHlYdr+tDlOTih1Bf/h+rzPpv4sbomAA=
github.com/abdullin/seq v0.0.0-20160510034733-d5467c17e7af h1:DBNMBMuMiWYu0b+8KMJuWmfCkcxl09JwdlqwDZZ6U14=
github.com/abdullin/seq v0.0.0-20160510034733-d5467c17e7af/go.mod h1:5Jv4cbFiHJMsVxt52+i0Ha45fjshj6wxYr1r19tB9bw=
github.com/adrg/xdg v0.5.3 h1:xRnxJXne7+oWDatRhR1JLnvuccuIeCoBu2rtuLqQB78=
github.com/adrg/xdg v0.5.3/go.mod h1:nlTsY+NNiCBGCK2tpm09vRqfVzrc2fLmXGpBLF0zlTQ=
github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM=
github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alessio/shellescape v1.2.2/go.mod h1:PZAiSCk0LJaZkiCSkPv8qIobYglO3FPpyFjDCtHLS30=
github.com/alphadose/haxmap v1.4.1 h1:VtD6VCxUkjNIfJk/aWdYFfOzrRddDFjmvmRmILg7x8Q=
github.com/alphadose/haxmap v1.4.1/go.mod h1:rjHw1IAqbxm0S3U5tD16GoKsiAd8FWx5BJ2IYqXwgmM=
github.com/anatol/vmtest v0.0.0-20250318022921-2f32244e2f0f h1:k3vr4NtQzqEak4d+pBcyZ/NJuzOMPuJftLx1Fx1M2uo=
github.com/anatol/vmtest v0.0.0-20250318022921-2f32244e2f0f/go.mod h1:m5pN88x7ZnEDGXZldwg7RCX+EikR9qz/iSI2GzXq++Y=
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M=
github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY=
Expand Down Expand Up @@ -145,6 +149,8 @@ github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4Yn
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
github.com/bmizerany/perks v0.0.0-20141205001514-d9a9656a3a4b h1:AP/Y7sqYicnjGDfD5VcY4CIfh1hRXBUavxrvELjTiOE=
github.com/bmizerany/perks v0.0.0-20141205001514-d9a9656a3a4b/go.mod h1:ac9efd0D1fsDb3EJvhqgXRbFx7bs2wqZ10HQPeU8U/Q=
github.com/bramvdbogaerde/go-scp v1.5.0 h1:a9BinAjTfQh273eh7vd3qUgmBC+bx+3TRDtkZWmIpzM=
github.com/bramvdbogaerde/go-scp v1.5.0/go.mod h1:on2aH5AxaFb2G0N5Vsdy6B0Ml7k9HuHSwfo1y0QzAbQ=
github.com/brianvoe/gofakeit/v6 v6.22.0 h1:BzOsDot1o3cufTfOk+fWKE9nFYojyDV+XHdCWL2+uyE=
github.com/brianvoe/gofakeit/v6 v6.22.0/go.mod h1:Ow6qC71xtwm79anlwKRlWZW6zVq9D2XHE4QSSMP/rU8=
github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs=
Expand Down Expand Up @@ -663,6 +669,8 @@ github.com/k3s-io/kine v0.13.2 h1:l++g2KY/3UaPJiGpgYuGoqaaYKeMpVj9fP/yfnSxHxo=
github.com/k3s-io/kine v0.13.2/go.mod h1:Zi9F142tmeXVqhPjL6KHVnwOBs8wc/V5r3avKSpIHn0=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
github.com/kdomanski/iso9660 v0.4.0 h1:BPKKdcINz3m0MdjIMwS0wx1nofsOjxOq8TOr45WGHFg=
github.com/kdomanski/iso9660 v0.4.0/go.mod h1:OxUSupHsO9ceI8lBLPJKWBTphLemjrCQY8LPXM7qSzU=
github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8=
github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
Expand All @@ -673,6 +681,8 @@ github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47e
github.com/klauspost/compress v1.14.4/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
github.com/klauspost/cpuid/v2 v2.2.10 h1:tBs3QSyvjDyFTq3uoc/9xFpCuOsJQFNPiAhYdw2skhE=
github.com/klauspost/cpuid/v2 v2.2.10/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
Expand Down
2 changes: 1 addition & 1 deletion pkg/tunnel/connection/splice.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ func Splice(tun tun.Device, conn Connection) error {
for {
_, err := tun.Read([][]byte{pkt[:]}, sizes, 0)
if err != nil {
if strings.Contains(err.Error(), "file already closed") {
if strings.Contains(err.Error(), "closed") {
slog.Debug("TUN device closed")
return nil
}
Expand Down
151 changes: 0 additions & 151 deletions pkg/tunnel/router/mock_router.go

This file was deleted.

22 changes: 11 additions & 11 deletions pkg/tunnel/router/netlink_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,38 +87,38 @@ func extPrefixes(link netlink.Link) (netip.Addr, []netip.Prefix, error) {
}

// NewNetlinkRouter creates a new netlink-based tunnel router.
// Option represents a router configuration option.
type Option func(*routerOptions)
// NetlinkRouterOption represents a router configuration option.
type NetlinkRouterOption func(*netlinkRouterOptions)

type routerOptions struct {
type netlinkRouterOptions struct {
extIfaceName string
tunIfaceName string
}

func defaultOptions() *routerOptions {
return &routerOptions{
func defaultNetlinkOptions() *netlinkRouterOptions {
return &netlinkRouterOptions{
extIfaceName: "eth0",
tunIfaceName: "tun0",
}
}

// WithExternalInterface sets the external interface name.
func WithExternalInterface(name string) Option {
return func(o *routerOptions) {
func WithExternalInterface(name string) NetlinkRouterOption {
return func(o *netlinkRouterOptions) {
o.extIfaceName = name
}
}

// WithTunnelInterface sets the tunnel interface name.
func WithTunnelInterface(name string) Option {
return func(o *routerOptions) {
func WithTunnelInterface(name string) NetlinkRouterOption {
return func(o *netlinkRouterOptions) {
o.tunIfaceName = name
}
}

// NewNetlinkRouter creates a new netlink-based tunnel router.
func NewNetlinkRouter(opts ...Option) (*NetlinkRouter, error) {
options := defaultOptions()
func NewNetlinkRouter(opts ...NetlinkRouterOption) (*NetlinkRouter, error) {
options := defaultNetlinkOptions()
for _, opt := range opts {
opt(options)
}
Expand Down
55 changes: 31 additions & 24 deletions pkg/tunnel/router/netlink_linux_test.go
Original file line number Diff line number Diff line change
@@ -1,53 +1,60 @@
//go:build linux

package router
package router_test

import (
"context"
"net/netip"
"reflect"
"testing"
"time"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"golang.org/x/sync/errgroup"

"github.com/apoxy-dev/apoxy-cli/pkg/tunnel/connection"
"github.com/apoxy-dev/apoxy-cli/pkg/tunnel/router"
"github.com/apoxy-dev/apoxy-cli/pkg/utils/vm"
)

func TestNetlinkRouterMock(t *testing.T) {
// This is a mock test that doesn't actually create routes
// but validates the struct and interface implementation
func TestNetlinkRouter(t *testing.T) {
// Run the test in a linux VM
child := vm.RunTestInVM(t)
if !child {
return
}

r := &NetlinkRouter{}
r, err := router.NewNetlinkRouter()
require.NoError(t, err)

ctx, cancel := context.WithCancel(context.Background())
t.Cleanup(cancel)

// Test that it implements the Router interface
var _ Router = r
// Start the router
var g errgroup.Group

// Test Start method existence
assert.NotPanics(t, func() {
startMethod := reflect.ValueOf(r).MethodByName("Start")
assert.True(t, startMethod.IsValid(), "Start method should exist")
g.Go(func() error {
return r.Start(ctx)
})

// Test GetTunnelDevice method existence
assert.NotPanics(t, func() {
getTunnelDeviceMethod := reflect.ValueOf(r).MethodByName("GetTunnelDevice")
assert.True(t, getTunnelDeviceMethod.IsValid(), "GetTunnelDevice method should exist")
t.Cleanup(func() {
require.NoError(t, r.Close())
})

conn := connection.NewMuxedConnection()
time.Sleep(100 * time.Millisecond) // Give some time for the router to start

// Test AddPeer
prefix := netip.MustParsePrefix("fd00::1/128")
_, _, err := r.AddPeer(prefix, conn)
// Should fail since we didn't initialize the link
assert.Error(t, err)
conn := connection.NewMuxedConnection()
_, _, err = r.AddPeer(prefix, conn)
require.NoError(t, err)

// Test RemovePeer
err = r.RemovePeer(prefix)
// Should fail since we didn't initialize the link
assert.Error(t, err)
require.NoError(t, err)

// Test Close
err = r.Close()
cancel()

err = g.Wait()
require.NoError(t, err)
}
16 changes: 16 additions & 0 deletions pkg/tunnel/router/netlink_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
//go:build !linux

package router_test

import (
"testing"

"github.com/apoxy-dev/apoxy-cli/pkg/utils/vm"
)

// A stub for non-linux operating systems, when the test is compiled for the VM
// it will use the linux version of this test.
func TestNetlinkRouter(t *testing.T) {
// Run the test in a linux VM.
vm.RunTestInVM(t)
}
Loading