mirror of
https://github.com/soypat/lneto.git
synced 2026-09-03 05:19:04 +00:00
add gvisor-mwe and add binary sizes to README
This commit is contained in:
@@ -15,6 +15,7 @@ vendor/
|
|||||||
*.so
|
*.so
|
||||||
*.dylib
|
*.dylib
|
||||||
*.hex
|
*.hex
|
||||||
|
*.wasm
|
||||||
|
|
||||||
# Profiling
|
# Profiling
|
||||||
*.pprof
|
*.pprof
|
||||||
|
|||||||
@@ -27,6 +27,14 @@ Userspace networking primitives.
|
|||||||
## [`min-working-example`](./examples/min-working-example/) - Quick lneto showcase
|
## [`min-working-example`](./examples/min-working-example/) - Quick lneto showcase
|
||||||
Get a quick showcase of how lneto can be configured and how to get a TCP listening server up and running.
|
Get a quick showcase of how lneto can be configured and how to get a TCP listening server up and running.
|
||||||
|
|
||||||
|
### Binary size comparisons
|
||||||
|
All examples include IPv4, ARP, ICMP, TCP and UDP functionality. Go and TinyGo default build flags used. **DNC**= Does Not Compile.
|
||||||
|
|
||||||
|
|
||||||
|
| Program | Extra Protocols | amd64 Go | WASM Go | amd64 TinyGo | WASM TinyGo | Pico TinyGo |
|
||||||
|
|---|---|---|---|---|---|---|
|
||||||
|
| [Lneto MWE](./examples/min-working-example/) | DNS,NTP,DHCP | 3.8MB | 4.3MB | 1.3MB | 934kB | 181kB |
|
||||||
|
| [Gvisor MWE w/ go-net](./examples/_import_examples/gvisor-mwe/)| None | 6.6MB | 7.5MB | DNC | DNC | DNC |
|
||||||
## `xcurl` example
|
## `xcurl` example
|
||||||
You may try lneto out on linux with the [xcurl example](./examples/xcurl/) which gets an HTTP page by doing all the low-level networking part using absolutely no standard library.
|
You may try lneto out on linux with the [xcurl example](./examples/xcurl/) which gets an HTTP page by doing all the low-level networking part using absolutely no standard library.
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
# import-examples
|
||||||
|
This folder contains examples that need external imports to work.
|
||||||
|
|
||||||
|
This is done to avoid adding dependencies to lneto's go.mod file.
|
||||||
|
- Trivial Auditing
|
||||||
|
- No dependency analysis needed for vulnerability scanning
|
||||||
|
- Eliminate a whole set of attack vectors for lneto importers
|
||||||
|
- Ensures nothing outside Lneto gets compiled maintaining binary sizes small
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
module gvisormwe
|
||||||
|
|
||||||
|
go 1.25.7
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/google/btree v1.1.2 // indirect
|
||||||
|
github.com/usbarmory/go-net v0.0.0-20260416163630-1078311e0956 // indirect
|
||||||
|
golang.org/x/sys v0.26.0 // indirect
|
||||||
|
golang.org/x/time v0.7.0 // indirect
|
||||||
|
gvisor.dev/gvisor v0.0.0-20250911055229-61a46406f068 // indirect
|
||||||
|
)
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU=
|
||||||
|
github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
|
||||||
|
github.com/usbarmory/go-net v0.0.0-20260416163630-1078311e0956 h1:ZjhVXLMT/Ogxs1GIy1g8UJk7yi9G8kt90D0ElAPbaCc=
|
||||||
|
github.com/usbarmory/go-net v0.0.0-20260416163630-1078311e0956/go.mod h1:+6WiKCFJtJQZdNM2VpwQsYGo/aBJ39pN7nWx6Td3Z8s=
|
||||||
|
golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
|
||||||
|
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
|
golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ=
|
||||||
|
golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||||
|
gvisor.dev/gvisor v0.0.0-20250911055229-61a46406f068 h1:95kdltF/maTDk/Wulj7V81cSLgjB/Mg/6eJmOKsey4U=
|
||||||
|
gvisor.dev/gvisor v0.0.0-20250911055229-61a46406f068/go.mod h1:K16uJjZ+hSqDVsXhU2Rg2FpMN7kBvjZp/Ibt5BYZJjw=
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"net/netip"
|
||||||
|
"os"
|
||||||
|
"syscall"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
gnet "github.com/usbarmory/go-net"
|
||||||
|
)
|
||||||
|
|
||||||
|
const pollTime = 5 * time.Millisecond
|
||||||
|
|
||||||
|
var networkDevice NetworkDevice
|
||||||
|
|
||||||
|
// NetworkDevice implements gnet.NetworkDevice for bridging with raw Ethernet I/O.
|
||||||
|
type NetworkDevice struct {
|
||||||
|
send func([]byte) error
|
||||||
|
recv func([]byte) (int, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *NetworkDevice) Transmit(buf []byte) error { return d.send(buf) }
|
||||||
|
func (d *NetworkDevice) Receive(buf []byte) (int, error) { return d.recv(buf) }
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
ctx := context.Background()
|
||||||
|
if err := run(ctx); err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func run(ctx context.Context) error {
|
||||||
|
// Create gVisor-based networking stack.
|
||||||
|
stack := gnet.NewGVisorStack(1)
|
||||||
|
|
||||||
|
// Configure stack with MAC, IP prefix, and gateway.
|
||||||
|
err := stack.Configure(
|
||||||
|
"aa:bb:cc:dd:ee:ff",
|
||||||
|
netip.MustParsePrefix("192.168.1.10/24"),
|
||||||
|
netip.MustParseAddr("192.168.1.1"),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("configuring stack: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = stack.EnableICMP()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("enabling ICMP: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bridge the stack with a network device for packet I/O.
|
||||||
|
iface := &gnet.Interface{
|
||||||
|
Stack: stack,
|
||||||
|
NetworkDevice: &networkDevice,
|
||||||
|
HandleStackErr: func(err error, tx bool) {
|
||||||
|
dir := "rx"
|
||||||
|
if tx {
|
||||||
|
dir = "tx"
|
||||||
|
}
|
||||||
|
fmt.Printf("stack %s err: %v\n", dir, err)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
// Start the packet processing loop in a goroutine.
|
||||||
|
go iface.Start()
|
||||||
|
|
||||||
|
// Create a TCP listener on port 80 using the gVisor stack.
|
||||||
|
const sockStream = 0x1
|
||||||
|
laddr := net.TCPAddrFromAddrPort(netip.AddrPortFrom(netip.MustParseAddr("192.168.1.10"), 80))
|
||||||
|
c, err := stack.Socket(ctx, "tcp", syscall.AF_INET, sockStream, laddr, nil)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("creating AF_INET stream socket: %w", err)
|
||||||
|
}
|
||||||
|
listener := c.(net.Listener)
|
||||||
|
for ctx.Err() == nil {
|
||||||
|
time.Sleep(pollTime)
|
||||||
|
conn, err := listener.Accept()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("conn failed:", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
go handleConn(conn)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleConn(conn net.Conn) {
|
||||||
|
defer conn.Close()
|
||||||
|
conn.Write([]byte("Hello from gVisor stack!"))
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user