mirror of
https://github.com/soypat/lneto.git
synced 2026-09-10 08:39:30 +00:00
Lay out device/stack interfaces - Netdev/Netlink (#92)
* good code today * add netdev.Runner * round off APIs more * better interface method documentation * improve DHCP netstack API * add pico w netdev example * remove temp file * keep thinking about this. this is hard :/ * fix ci * small fixer * working dhcp * fix rebase API mismatches * begin adding espradio example * keep working on espradio, icmp not working * fix icmp by fixing dhcp
This commit is contained in:
@@ -0,0 +1,111 @@
|
||||
package xnet
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/netip"
|
||||
"time"
|
||||
|
||||
"github.com/soypat/lneto"
|
||||
"github.com/soypat/lneto/x/netdev"
|
||||
)
|
||||
|
||||
// Netstack is a more modern outward facing API wrapper on StackAsync.
|
||||
type Netstack struct {
|
||||
stack StackAsync
|
||||
//gstack references stack above.
|
||||
gstack StackGo
|
||||
awaitDHCP bool
|
||||
}
|
||||
|
||||
var _ netdev.Stack = (*Netstack)(nil)
|
||||
|
||||
// Configure configures this Stack with the argument mac, ip and gateway addresses.
|
||||
// The Stack must resolve the gateway hardware address if set.
|
||||
func (netstack *Netstack) Reset(cfg StackConfig, stackBackoff lneto.BackoffStrategy, poolcfg TCPPoolConfig) error {
|
||||
err := netstack.stack.Reset(cfg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
netstack.gstack = netstack.stack.StackGo(stackBackoff, StackGoConfig{
|
||||
ListenerPoolConfig: poolcfg,
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
func (netstack *Netstack) IPAddr4() [4]byte {
|
||||
return netstack.stack.Addr4()
|
||||
}
|
||||
|
||||
// EnableICMP enables responding/sending ICMP echo frames.
|
||||
func (netstack *Netstack) EnableICMP(enabled bool) error {
|
||||
return netstack.stack.EnableICMP(enabled)
|
||||
}
|
||||
|
||||
// EnableDHCP performs a DHCPv4 request, writes the assigned address into the
|
||||
// stack, and resolves the gateway hardware address via ARP.
|
||||
func (netstack *Netstack) EnableDHCP(ctx context.Context, enabled bool, requestAddr netip.Addr) (assigned netip.Addr, routerGW netip.Addr, subnetBits int, err error) {
|
||||
var addr [4]byte
|
||||
if !enabled {
|
||||
netstack.stack.dhcp.Reset()
|
||||
return netip.Addr{}, netip.Addr{}, 0, nil
|
||||
} else if requestAddr.Is4() {
|
||||
addr = requestAddr.As4()
|
||||
} else if requestAddr.IsValid() {
|
||||
return netip.Addr{}, netip.Addr{}, 0, lneto.ErrUnsupported
|
||||
}
|
||||
timeout := 4 * time.Second
|
||||
deadline, ok := ctx.Deadline()
|
||||
if ok {
|
||||
timeout = time.Until(deadline)
|
||||
}
|
||||
results, err := netstack.gstack.blk.DoDHCPv4(addr, timeout)
|
||||
if err != nil {
|
||||
return netip.Addr{}, netip.Addr{}, 0, err
|
||||
}
|
||||
// Write IP, subnet and DNS into the stack.
|
||||
if err = netstack.stack.AssimilateDHCPResults(results); err != nil {
|
||||
return netip.AddrFrom4(results.AssignedAddr4), results.Router, results.Subnet.Bits(), err
|
||||
}
|
||||
// Resolve gateway hardware address so egress packets are unicasted to the
|
||||
// router rather than broadcast. Failure is non-fatal.
|
||||
if results.Router.IsValid() {
|
||||
gwHW, gwErr := netstack.gstack.blk.DoResolveHardwareAddress6(results.Router, 2*time.Second)
|
||||
if gwErr == nil {
|
||||
netstack.stack.SetGatewayHardwareAddr(gwHW)
|
||||
}
|
||||
}
|
||||
return netip.AddrFrom4(results.AssignedAddr4), results.Router, results.Subnet.Bits(), nil
|
||||
}
|
||||
|
||||
// Socket is a berkeley socket abstraction. Returns an [net.Listener] or [net.Conn] depending on laddr/raddr combination.
|
||||
func (netstack *Netstack) Socket(ctx context.Context, network string, family, sotype int, laddr, raddr netip.AddrPort) (c any, err error) {
|
||||
return netstack.gstack.SocketNetip(ctx, network, family, sotype, laddr, raddr)
|
||||
}
|
||||
|
||||
// EgressPackets instructs Stack to write outgoing packets into bufs and writing the sizes into sizes not including initial offset.
|
||||
// offset can be used to tell the stack to start writing after an offset for each buffer.
|
||||
func (netstack *Netstack) EgressPackets(bufs [][]byte, sizes []int, offset int) (err error) {
|
||||
var err0 error
|
||||
for i := range bufs {
|
||||
sizes[i], err0 = netstack.stack.EgressEthernet(bufs[i][offset:])
|
||||
if sizes[i] == 0 {
|
||||
return err
|
||||
} else if err0 != nil {
|
||||
err = err0
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// IngressPackets is called on incoming packets so the Stack can direct packets to
|
||||
// their respective node/connection and update internal state.
|
||||
// offset instructs the Stack to start reading packets at an offset.
|
||||
func (netstack *Netstack) IngressPackets(bufs [][]byte, offset int) (err error) {
|
||||
for _, buf := range bufs {
|
||||
err0 := netstack.stack.IngressEthernet(buf[offset:])
|
||||
if err0 != nil {
|
||||
err = err0
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
Reference in New Issue
Block a user