[WIP] Refactor AMT
This commit is contained in:
parent
7d7fa3a753
commit
5f7e07157e
2 changed files with 50 additions and 18 deletions
46
amt.go
Normal file
46
amt.go
Normal 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
22
main.go
|
@ -34,7 +34,6 @@ import (
|
||||||
"gitea.drjosh.dev/josh/jrouter/aurp"
|
"gitea.drjosh.dev/josh/jrouter/aurp"
|
||||||
"github.com/sfiera/multitalk/pkg/aarp"
|
"github.com/sfiera/multitalk/pkg/aarp"
|
||||||
"github.com/sfiera/multitalk/pkg/ddp"
|
"github.com/sfiera/multitalk/pkg/ddp"
|
||||||
"github.com/sfiera/multitalk/pkg/ethernet"
|
|
||||||
"github.com/sfiera/multitalk/pkg/ethertalk"
|
"github.com/sfiera/multitalk/pkg/ethertalk"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -140,11 +139,7 @@ func main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// AppleTalk packet loop
|
// AppleTalk packet loop
|
||||||
type amtEntry struct {
|
var amt AMT
|
||||||
hwAddr ethernet.Addr
|
|
||||||
last time.Time
|
|
||||||
}
|
|
||||||
amt := make(map[ddp.Addr]amtEntry)
|
|
||||||
go func() {
|
go func() {
|
||||||
iface, err := net.InterfaceByName(cfg.EtherTalk.Device)
|
iface, err := net.InterfaceByName(cfg.EtherTalk.Device)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -186,18 +181,12 @@ func main() {
|
||||||
case aarp.RequestOp:
|
case aarp.RequestOp:
|
||||||
log.Printf("AARP: Who has %v? Tell %v", aapkt.Dst.Proto, aapkt.Src.Proto)
|
log.Printf("AARP: Who has %v? Tell %v", aapkt.Dst.Proto, aapkt.Src.Proto)
|
||||||
// Glean that aapkt.Src.Proto -> aapkt.Src.Hardware
|
// Glean that aapkt.Src.Proto -> aapkt.Src.Hardware
|
||||||
amt[aapkt.Src.Proto] = amtEntry{
|
amt.Learn(aapkt.Src.Proto, aapkt.Src.Hardware)
|
||||||
hwAddr: aapkt.Src.Hardware,
|
|
||||||
last: time.Now(),
|
|
||||||
}
|
|
||||||
log.Printf("AARP: Gleaned that %v -> %v", aapkt.Src.Proto, aapkt.Src.Hardware)
|
log.Printf("AARP: Gleaned that %v -> %v", aapkt.Src.Proto, aapkt.Src.Hardware)
|
||||||
|
|
||||||
case aarp.ResponseOp:
|
case aarp.ResponseOp:
|
||||||
log.Printf("AARP: %v is at %v", aapkt.Dst.Proto, aapkt.Dst.Hardware)
|
log.Printf("AARP: %v is at %v", aapkt.Dst.Proto, aapkt.Dst.Hardware)
|
||||||
amt[aapkt.Dst.Proto] = amtEntry{
|
amt.Learn(aapkt.Dst.Proto, aapkt.Dst.Hardware)
|
||||||
hwAddr: aapkt.Dst.Hardware,
|
|
||||||
last: time.Now(),
|
|
||||||
}
|
|
||||||
|
|
||||||
case aarp.ProbeOp:
|
case aarp.ProbeOp:
|
||||||
log.Printf("AARP: %v probing to see if %v is available", aapkt.Src.Hardware, aapkt.Src.Proto)
|
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))
|
ddpkt.Proto, len(ddpkt.Data))
|
||||||
// Glean address info for AMT
|
// Glean address info for AMT
|
||||||
srcAddr := ddp.Addr{Network: ddpkt.SrcNet, Node: ddpkt.SrcNode}
|
srcAddr := ddp.Addr{Network: ddpkt.SrcNet, Node: ddpkt.SrcNode}
|
||||||
amt[srcAddr] = amtEntry{
|
amt.Learn(srcAddr, ethFrame.Src)
|
||||||
hwAddr: ethFrame.Src,
|
|
||||||
last: time.Now(),
|
|
||||||
}
|
|
||||||
log.Printf("DDP: Gleaned that %v -> %v", srcAddr, ethFrame.Src)
|
log.Printf("DDP: Gleaned that %v -> %v", srcAddr, ethFrame.Src)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
Loading…
Reference in a new issue