[WIP] Refactor AMT

This commit is contained in:
Josh Deprez 2024-04-06 15:19:42 +11:00
parent 7d7fa3a753
commit 5f7e07157e
Signed by: josh
SSH key fingerprint: SHA256:zZji7w1Ilh2RuUpbQcqkLPrqmRwpiCSycbF2EfKm6Kw
2 changed files with 50 additions and 18 deletions

46
amt.go Normal file
View file

@ -0,0 +1,46 @@
package main
import (
"sync"
"time"
"github.com/sfiera/multitalk/pkg/ddp"
"github.com/sfiera/multitalk/pkg/ethernet"
)
// TODO: verify this parameter
const maxAMTEntryAge = 30 * time.Second
type amtEntry struct {
hwAddr ethernet.Addr
last time.Time
}
// AMT implements a concurrent-safe Address Mapping Table for AppleTalk (DDP)
// addresses to Ethernet hardware addresses.
type AMT struct {
mu sync.RWMutex
table map[ddp.Addr]amtEntry
}
// Learn adds or updates an AMT entry.
func (t *AMT) Learn(ddpAddr ddp.Addr, hwAddr ethernet.Addr) {
t.mu.Lock()
defer t.mu.Unlock()
if t.table == nil {
t.table = make(map[ddp.Addr]amtEntry)
}
t.table[ddpAddr] = amtEntry{
hwAddr: hwAddr,
last: time.Now(),
}
}
// Lookup searches for a non-expired entry in the table only. It does not send
// any packets.
func (t *AMT) Lookup(ddpAddr ddp.Addr) (ethernet.Addr, bool) {
t.mu.RLock()
defer t.mu.RUnlock()
ent, ok := t.table[ddpAddr]
return ent.hwAddr, ok && time.Since(ent.last) < maxAMTEntryAge
}

22
main.go
View file

@ -34,7 +34,6 @@ import (
"gitea.drjosh.dev/josh/jrouter/aurp"
"github.com/sfiera/multitalk/pkg/aarp"
"github.com/sfiera/multitalk/pkg/ddp"
"github.com/sfiera/multitalk/pkg/ethernet"
"github.com/sfiera/multitalk/pkg/ethertalk"
)
@ -140,11 +139,7 @@ func main() {
}
// AppleTalk packet loop
type amtEntry struct {
hwAddr ethernet.Addr
last time.Time
}
amt := make(map[ddp.Addr]amtEntry)
var amt AMT
go func() {
iface, err := net.InterfaceByName(cfg.EtherTalk.Device)
if err != nil {
@ -186,18 +181,12 @@ func main() {
case aarp.RequestOp:
log.Printf("AARP: Who has %v? Tell %v", aapkt.Dst.Proto, aapkt.Src.Proto)
// Glean that aapkt.Src.Proto -> aapkt.Src.Hardware
amt[aapkt.Src.Proto] = amtEntry{
hwAddr: aapkt.Src.Hardware,
last: time.Now(),
}
amt.Learn(aapkt.Src.Proto, aapkt.Src.Hardware)
log.Printf("AARP: Gleaned that %v -> %v", aapkt.Src.Proto, aapkt.Src.Hardware)
case aarp.ResponseOp:
log.Printf("AARP: %v is at %v", aapkt.Dst.Proto, aapkt.Dst.Hardware)
amt[aapkt.Dst.Proto] = amtEntry{
hwAddr: aapkt.Dst.Hardware,
last: time.Now(),
}
amt.Learn(aapkt.Dst.Proto, aapkt.Dst.Hardware)
case aarp.ProbeOp:
log.Printf("AARP: %v probing to see if %v is available", aapkt.Src.Hardware, aapkt.Src.Proto)
@ -216,10 +205,7 @@ func main() {
ddpkt.Proto, len(ddpkt.Data))
// Glean address info for AMT
srcAddr := ddp.Addr{Network: ddpkt.SrcNet, Node: ddpkt.SrcNode}
amt[srcAddr] = amtEntry{
hwAddr: ethFrame.Src,
last: time.Now(),
}
amt.Learn(srcAddr, ethFrame.Src)
log.Printf("DDP: Gleaned that %v -> %v", srcAddr, ethFrame.Src)
default: