Skip to content

Commit ce6c350

Browse files
authored
Merge pull request #691 from darinkes/arp_timeout
packet/neigh: add optional timeout
2 parents 7ff09bf + 119c73f commit ce6c350

File tree

1 file changed

+55
-3
lines changed

1 file changed

+55
-3
lines changed

packet/neigh.go

Lines changed: 55 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515

1616
const (
1717
arpRequestsRepeatInterval = 1 * time.Second
18+
arpEntryCleanup = 60 * time.Second
1819
)
1920

2021
type NeighboursLookupTable struct {
@@ -30,15 +31,58 @@ type NeighboursLookupTable struct {
3031
checkv6 func(ipv6 types.IPv6Address) bool
3132
}
3233

34+
type neighboursLookupTableEntry struct {
35+
MAC types.MACAddress
36+
LastUsed time.Time
37+
}
38+
3339
func NewNeighbourTable(index uint16, mac types.MACAddress,
3440
checkv4 func(ipv4 types.IPv4Address) bool,
3541
checkv6 func(ipv6 types.IPv6Address) bool) *NeighboursLookupTable {
36-
return &NeighboursLookupTable{
42+
43+
return NewTimeoutNeighbourTable(index, mac, checkv4, checkv6, 0)
44+
}
45+
46+
func NewTimeoutNeighbourTable(index uint16, mac types.MACAddress,
47+
checkv4 func(ipv4 types.IPv4Address) bool,
48+
checkv6 func(ipv6 types.IPv6Address) bool,
49+
cleanupInterval time.Duration) *NeighboursLookupTable {
50+
51+
nlt := &NeighboursLookupTable{
3752
portIndex: index,
3853
interfaceMAC: mac,
3954
checkv4: checkv4,
4055
checkv6: checkv6,
4156
}
57+
58+
if cleanupInterval <= 0 {
59+
return nlt
60+
}
61+
62+
go func() {
63+
ticker := time.NewTicker(cleanupInterval)
64+
65+
for {
66+
select {
67+
case <-ticker.C:
68+
nlt.cleanup()
69+
}
70+
}
71+
}()
72+
73+
return nlt
74+
}
75+
76+
func (table *NeighboursLookupTable) cleanup() {
77+
table.ipv4Table.Range(func(k interface{}, v interface{}) bool {
78+
entry := v.(neighboursLookupTableEntry)
79+
if time.Since(entry.LastUsed) >= arpEntryCleanup {
80+
ipv4 := k.(types.IPv4Address)
81+
table.ipv4Table.Delete(ipv4)
82+
common.LogDebug(common.Debug, "Removed ARP Entry for", ipv4, ":", entry.MAC)
83+
}
84+
return true
85+
})
4286
}
4387

4488
// HandleIPv4ARPRequest processes IPv4 ARP request and reply packets
@@ -52,7 +96,12 @@ func (table *NeighboursLookupTable) HandleIPv4ARPPacket(pkt *Packet) error {
5296
// Handle ARP reply and record information in lookup table
5397
if SwapBytesUint16(arp.Operation) == ARPReply {
5498
ipv4 := types.ArrayToIPv4(arp.SPA)
55-
table.ipv4Table.Store(ipv4, arp.SHA)
99+
entry := neighboursLookupTableEntry {
100+
MAC: arp.SHA,
101+
LastUsed: time.Now(),
102+
}
103+
table.ipv4Table.Store(ipv4, entry)
104+
common.LogDebug(common.Debug, "Added ARP Entry for", ipv4, ":", entry.MAC)
56105
}
57106
return nil
58107
}
@@ -85,7 +134,10 @@ func (table *NeighboursLookupTable) HandleIPv4ARPPacket(pkt *Packet) error {
85134
func (table *NeighboursLookupTable) LookupMACForIPv4(ipv4 types.IPv4Address) (types.MACAddress, bool) {
86135
v, found := table.ipv4Table.Load(ipv4)
87136
if found {
88-
return v.(types.MACAddress), true
137+
entry := v.(neighboursLookupTableEntry)
138+
entry.LastUsed = time.Now()
139+
table.ipv4Table.Store(ipv4, entry)
140+
return entry.MAC, true
89141
}
90142
return [types.EtherAddrLen]byte{}, false
91143
}

0 commit comments

Comments
 (0)