Start routing table

This commit is contained in:
Josh Deprez 2024-04-12 16:14:27 +10:00
parent 10c447c78d
commit 1a83e4d543
No known key found for this signature in database
5 changed files with 98 additions and 9 deletions

View file

@ -79,6 +79,14 @@ func Unmarshal(data []byte) (*Packet, error) {
NBPID: data[1],
}
tupleCount := data[0] & 0x0F
if tupleCount == 0 {
return nil, fmt.Errorf("no tuples")
}
// Only LkUp-Reply can have more than 1 tuple
if tupleCount > 1 && p.Function != FunctionLkUpReply {
return nil, fmt.Errorf("wrong number of tuples %d for function %s", tupleCount, p.Function)
}
data = data[2:]
for range tupleCount {
if len(data) < 8 {
@ -144,7 +152,7 @@ func (t *Tuple) writeTo(b *bytes.Buffer) error {
return nil
}
func (t *Tuple) String() string {
func (t Tuple) String() string {
return fmt.Sprintf("%d.%d.%d (enum %d) <-> %s:%s@%s",
t.Network, t.Node, t.Socket, t.Enumerator, t.Object, t.Type, t.Zone,
)

View file

@ -102,6 +102,14 @@ func (tr *Transport) sequenced(connID, seq uint16) TrHeader {
}
}
// NewAppleTalkPacket returns a new AppleTalkPacket.
func (tr *Transport) NewAppleTalkPacket(data []byte) *AppleTalkPacket {
return &AppleTalkPacket{
DomainHeader: tr.domainHeader(PacketTypeAppleTalk),
Data: data,
}
}
// NewOpenReqPacket returns a new Open-Req packet structure. By default it sets
// all SUI flags and uses version 1.
func (tr *Transport) NewOpenReqPacket(opts Options) *OpenReqPacket {

30
main.go
View file

@ -128,7 +128,7 @@ func main() {
}()
}
// --------------- Configured peer setup ---------------
// ------------------------- Configured peer setup ------------------------
for _, peerStr := range cfg.Peers {
if !hasPortRE.MatchString(peerStr) {
peerStr += ":387"
@ -156,12 +156,12 @@ func main() {
goPeerHandler(peer)
}
// -------------------- AARP --------------------
// --------------------------------- AARP ---------------------------------
aarpMachine := NewAARPMachine(cfg, pcapHandle, myHWAddr)
aarpCh := make(chan *ethertalk.Packet, 1024)
go aarpMachine.Run(ctx, aarpCh)
// -------------------- RTMP --------------------
// --------------------------------- RTMP ---------------------------------
rtmpMachine := &RTMPMachine{
aarp: aarpMachine,
cfg: cfg,
@ -170,7 +170,7 @@ func main() {
rtmpCh := make(chan *ddp.ExtPacket, 1024)
go rtmpMachine.Run(ctx, rtmpCh)
// --------------------- NBP --------------------
// ---------------------------------- NBP ---------------------------------
nbpMachine := &NBPMachine{
aarp: aarpMachine,
pcapHandle: pcapHandle,
@ -178,7 +178,7 @@ func main() {
nbpCh := make(chan *ddp.ExtPacket, 1024)
go nbpMachine.Run(ctx, nbpCh)
// ---------- Raw AppleTalk/AARP inbound ----------
// ---------------------- Raw AppleTalk/AARP inbound ----------------------
go func() {
for {
if ctx.Err() != nil {
@ -235,12 +235,28 @@ func main() {
continue
}
// TODO: If the packet is NBP BrRq and for a zone we have in
// our zone info table, convert it to a FwdReq and send that
// out to the peer
// TODO: implement the zone information table
// Our network?
// "The network number 0 is reserved to mean unknown; by default
// it specifies the local network to which the node is
// connected. Packets whose destination network number is 0 are
// addressed to a node on the local network."
if ddpkt.DstNet != 0 && ddpkt.DstNet != myAddr.Proto.Network {
if ddpkt.DstNet != 0 && (ddpkt.DstNet < cfg.EtherTalk.NetStart || ddpkt.DstNet > cfg.EtherTalk.NetEnd) {
// Is it for a network in the routing table?
rt := lookupRoute(ddpkt.DstNet)
if rt == nil {
continue
}
// Encap ethPacket.Payload into an AURP packet
if _, err := rt.peer.send(rt.peer.tr.NewAppleTalkPacket(ethFrame.Payload)); err != nil {
log.Printf("DDP: Couldn't forward packet to AURP peer: %v", err)
}
continue
}
@ -275,7 +291,7 @@ func main() {
}
}()
// ---------- AURP inbound ----------
// ----------------------------- AURP inbound -----------------------------
for {
if ctx.Err() != nil {
return

View file

@ -24,6 +24,7 @@ import (
"time"
"gitea.drjosh.dev/josh/jrouter/aurp"
"github.com/sfiera/multitalk/pkg/ddp"
)
const (
@ -275,7 +276,9 @@ func (p *peer) handle(ctx context.Context) error {
log.Printf("Learned about these networks: %v", pkt.Networks)
// TODO: Integrate info into route table
for _, nt := range pkt.Networks {
upsertRoutes(ddp.Network(nt.RangeStart), ddp.Network(nt.RangeEnd), p, nt.Distance)
}
// TODO: track which networks we don't have zone info for, and
// only set SZI for those ?

54
route.go Normal file
View file

@ -0,0 +1,54 @@
package main
import (
"cmp"
"fmt"
"slices"
"sync"
"time"
"github.com/sfiera/multitalk/pkg/ddp"
)
type route struct {
peer *peer
metric uint8
last time.Time
}
var (
routingTableMu sync.Mutex
routingTable = make(map[ddp.Network][]*route)
)
func lookupRoute(network ddp.Network) *route {
routingTableMu.Lock()
defer routingTableMu.Unlock()
rs := routingTable[network]
if len(rs) == 0 {
return nil
}
return rs[0]
}
func upsertRoutes(netStart, netEnd ddp.Network, peer *peer, metric uint8) error {
if netStart > netEnd {
return fmt.Errorf("invalid network range [%d, %d]", netStart, netEnd)
}
r := &route{
peer: peer,
metric: metric,
last: time.Now(),
}
routingTableMu.Lock()
defer routingTableMu.Unlock()
for n := netStart; n <= netEnd; n++ {
routingTable[n] = append(routingTable[n], r)
slices.SortFunc(routingTable[n], func(r, s *route) int {
return cmp.Compare(r.metric, s.metric)
})
}
return nil
}