Routing table simplifications

This commit is contained in:
Josh Deprez 2024-04-14 17:13:12 +10:00
parent abbe8c542b
commit c7d5ecec49
Signed by: josh
SSH key fingerprint: SHA256:zZji7w1Ilh2RuUpbQcqkLPrqmRwpiCSycbF2EfKm6Kw
4 changed files with 68 additions and 64 deletions

11
main.go
View file

@ -131,10 +131,7 @@ func main() {
} }
// ----------------------------- Routing table ---------------------------- // ----------------------------- Routing table ----------------------------
routing := &routingTable{ routing := NewRoutingTable()
table: make(map[ddp.Network][]*route),
allRoutes: make(map[*route]struct{}),
}
// ------------------------- Configured peer setup ------------------------ // ------------------------- Configured peer setup ------------------------
for _, peerStr := range cfg.Peers { for _, peerStr := range cfg.Peers {
@ -250,15 +247,15 @@ func main() {
// addressed to a node on the local network." // addressed to a node on the local network."
if ddpkt.DstNet != 0 && (ddpkt.DstNet < cfg.EtherTalk.NetStart || ddpkt.DstNet > cfg.EtherTalk.NetEnd) { if ddpkt.DstNet != 0 && (ddpkt.DstNet < cfg.EtherTalk.NetStart || ddpkt.DstNet > cfg.EtherTalk.NetEnd) {
// Is it for a network in the routing table? // Is it for a network in the routing table?
rt := routing.lookupRoute(ddpkt.DstNet) rt := routing.LookupRoute(ddpkt.DstNet)
if rt == nil { if rt == nil {
log.Printf("DDP: no route for network %d", ddpkt.DstNet) log.Printf("DDP: no route for network %d", ddpkt.DstNet)
continue continue
} }
// Encap ethPacket.Payload into an AURP packet // Encap ethPacket.Payload into an AURP packet
log.Printf("DDP: forwarding to AURP peer %v", rt.peer.tr.RemoteDI) log.Printf("DDP: forwarding to AURP peer %v", rt.Peer.tr.RemoteDI)
if _, err := rt.peer.send(rt.peer.tr.NewAppleTalkPacket(ethFrame.Payload)); err != nil { 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) log.Printf("DDP: Couldn't forward packet to AURP peer: %v", err)
} }

View file

@ -82,7 +82,7 @@ type peer struct {
raddr *net.UDPAddr raddr *net.UDPAddr
recv chan aurp.Packet recv chan aurp.Packet
routingTable *routingTable routingTable *RoutingTable
} }
// send encodes and sends pkt to the remote host. // send encodes and sends pkt to the remote host.
@ -279,7 +279,7 @@ func (p *peer) handle(ctx context.Context) error {
log.Printf("Learned about these networks: %v", pkt.Networks) log.Printf("Learned about these networks: %v", pkt.Networks)
for _, nt := range pkt.Networks { for _, nt := range pkt.Networks {
p.routingTable.upsertRoutes( p.routingTable.UpsertRoute(
nt.Extended, nt.Extended,
ddp.Network(nt.RangeStart), ddp.Network(nt.RangeStart),
ddp.Network(nt.RangeEnd), ddp.Network(nt.RangeEnd),

105
route.go
View file

@ -1,9 +1,7 @@
package main package main
import ( import (
"cmp"
"fmt" "fmt"
"slices"
"sync" "sync"
"time" "time"
@ -12,74 +10,83 @@ import (
const maxRouteAge = 10 * time.Minute // TODO: confirm const maxRouteAge = 10 * time.Minute // TODO: confirm
type route struct { type Route struct {
extended bool Extended bool
netStart ddp.Network NetStart ddp.Network
netEnd ddp.Network NetEnd ddp.Network
peer *peer Peer *peer
metric uint8 Distance uint8
last time.Time LastSeen time.Time
} }
type routingTable struct { type RoutingTable struct {
tableMu sync.Mutex mu sync.Mutex
table map[ddp.Network][]*route routes map[*Route]struct{}
allRoutesMu sync.Mutex
allRoutes map[*route]struct{}
} }
func (rt *routingTable) lookupRoute(network ddp.Network) *route { func NewRoutingTable() *RoutingTable {
rt.tableMu.Lock() return &RoutingTable{
defer rt.tableMu.Unlock() routes: make(map[*Route]struct{}),
}
}
for _, rs := range rt.table[network] { func (rt *RoutingTable) LookupRoute(network ddp.Network) *Route {
if time.Since(rs.last) > maxRouteAge { rt.mu.Lock()
defer rt.mu.Unlock()
var bestRoute *Route
for r := range rt.routes {
if r.Peer == nil {
continue continue
} }
return rs if network < r.NetStart || network > r.NetEnd {
continue
} }
return nil if time.Since(r.LastSeen) > maxRouteAge {
continue
}
if bestRoute == nil {
bestRoute = r
continue
}
if r.Distance < bestRoute.Distance {
bestRoute = r
}
}
return bestRoute
} }
func (rt *routingTable) upsertRoutes(extended bool, netStart, netEnd ddp.Network, peer *peer, metric uint8) error { func (rt *RoutingTable) UpsertRoute(extended bool, netStart, netEnd ddp.Network, peer *peer, metric uint8) error {
if netStart > netEnd { if netStart > netEnd {
return fmt.Errorf("invalid network range [%d, %d]", netStart, netEnd) return fmt.Errorf("invalid network range [%d, %d]", netStart, netEnd)
} }
r := &route{ // TODO: handle the Update part of "Upsert"
extended: extended,
netStart: netStart, r := &Route{
netEnd: netEnd, Extended: extended,
peer: peer, NetStart: netStart,
metric: metric, NetEnd: netEnd,
last: time.Now(), Peer: peer,
Distance: metric,
LastSeen: time.Now(),
} }
rt.allRoutesMu.Lock() rt.mu.Lock()
rt.allRoutes[r] = struct{}{} defer rt.mu.Unlock()
rt.allRoutesMu.Unlock() rt.routes[r] = struct{}{}
rt.tableMu.Lock()
defer rt.tableMu.Unlock()
for n := netStart; n <= netEnd; n++ {
rt.table[n] = append(rt.table[n], r)
slices.SortFunc(rt.table[n], func(r, s *route) int {
return cmp.Compare(r.metric, s.metric)
})
}
return nil return nil
} }
func (rt *routingTable) validRoutes() []*route { func (rt *RoutingTable) ValidRoutes() []*Route {
rt.allRoutesMu.Lock() rt.mu.Lock()
defer rt.allRoutesMu.Unlock() defer rt.mu.Unlock()
valid := make([]*route, 0, len(rt.allRoutes)) valid := make([]*Route, 0, len(rt.routes))
for r := range rt.allRoutes { for r := range rt.routes {
if r.peer == nil { if r.Peer == nil {
continue continue
} }
if time.Since(r.last) > maxRouteAge { if time.Since(r.LastSeen) > maxRouteAge {
continue continue
} }
valid = append(valid, r) valid = append(valid, r)

12
rtmp.go
View file

@ -35,7 +35,7 @@ type RTMPMachine struct {
aarp *AARPMachine aarp *AARPMachine
cfg *config cfg *config
pcapHandle *pcap.Handle pcapHandle *pcap.Handle
routingTable *routingTable routingTable *RoutingTable
} }
// Run executes the machine. // Run executes the machine.
@ -214,12 +214,12 @@ func (m *RTMPMachine) dataPacket(myAddr ddp.Addr) *rtmp.DataPacket {
}, },
}, },
} }
for _, rt := range m.routingTable.validRoutes() { for _, rt := range m.routingTable.ValidRoutes() {
p.NetworkTuples = append(p.NetworkTuples, rtmp.NetworkTuple{ p.NetworkTuples = append(p.NetworkTuples, rtmp.NetworkTuple{
Extended: rt.extended, Extended: rt.Extended,
RangeStart: rt.netStart, RangeStart: rt.NetStart,
RangeEnd: rt.netEnd, RangeEnd: rt.NetEnd,
Distance: rt.metric + 1, Distance: rt.Distance + 1,
}) })
} }
return p return p