blob: 83a3b551d8321fd0cde598c143dffd5759bec494 [file] [log] [blame]
Jonathan Hartabad6a52013-09-30 18:17:21 +13001package net.onrc.onos.ofcontroller.proxyarp;
2
3import java.net.InetAddress;
Jonathan Hart5afde492013-10-01 12:30:53 +13004import java.util.ArrayList;
Jonathan Hartabad6a52013-09-30 18:17:21 +13005import java.util.HashMap;
Jonathan Hart5afde492013-10-01 12:30:53 +13006import java.util.List;
Jonathan Hartabad6a52013-09-30 18:17:21 +13007import java.util.Map;
8
9import net.floodlightcontroller.util.MACAddress;
10
11import org.slf4j.Logger;
12import org.slf4j.LoggerFactory;
13
14/**
15 * Implements a basic ARP cache which maps IPv4 addresses to MAC addresses.
16 * Mappings time out after a short period of time (currently 1 min). We don't
17 * try and refresh the mapping before the entry times out because as a controller
18 * we don't know if the mapping is still needed.
Jonathan Hartabad6a52013-09-30 18:17:21 +130019 */
20
21/* TODO clean out old ARP entries out of the cache periodically. We currently
22 * don't do this which means the cache memory size will never decrease. We already
23 * have a periodic thread that can be used to do this in ProxyArpManager.
24 */
Jonathan Hart5afde492013-10-01 12:30:53 +130025class ArpCache {
Jonathan Hartabad6a52013-09-30 18:17:21 +130026 private final static Logger log = LoggerFactory.getLogger(ArpCache.class);
27
Jonathan Hart5afde492013-10-01 12:30:53 +130028 private final static long ARP_ENTRY_TIMEOUT = 60000; //ms (1 min)
Jonathan Hartabad6a52013-09-30 18:17:21 +130029
30 //Protected by locking on the ArpCache object
31 private final Map<InetAddress, ArpCacheEntry> arpCache;
32
33 private static class ArpCacheEntry {
34 private final MACAddress macAddress;
35 private long timeLastSeen;
36
37 public ArpCacheEntry(MACAddress macAddress) {
38 this.macAddress = macAddress;
39 this.timeLastSeen = System.currentTimeMillis();
40 }
41
42 public MACAddress getMacAddress() {
43 return macAddress;
44 }
Jonathan Hartabad6a52013-09-30 18:17:21 +130045
46 public void setTimeLastSeen(long time){
47 timeLastSeen = time;
48 }
Jonathan Hart5afde492013-10-01 12:30:53 +130049
50 public boolean isExpired() {
51 return System.currentTimeMillis() - timeLastSeen > ARP_ENTRY_TIMEOUT;
52 }
Jonathan Hartabad6a52013-09-30 18:17:21 +130053 }
54
Jonathan Hart5afde492013-10-01 12:30:53 +130055 ArpCache() {
Jonathan Hartabad6a52013-09-30 18:17:21 +130056 arpCache = new HashMap<InetAddress, ArpCacheEntry>();
57 }
58
Jonathan Hart5afde492013-10-01 12:30:53 +130059 synchronized MACAddress lookup(InetAddress ipAddress){
Jonathan Hartabad6a52013-09-30 18:17:21 +130060 ArpCacheEntry arpEntry = arpCache.get(ipAddress);
61
62 if (arpEntry == null){
63 return null;
64 }
65
Jonathan Hart5afde492013-10-01 12:30:53 +130066 if (arpEntry.isExpired()) {
Jonathan Hartabad6a52013-09-30 18:17:21 +130067 //Entry has timed out so we'll remove it and return null
68 log.trace("Removing expired ARP entry for {}", ipAddress.getHostAddress());
69
70 arpCache.remove(ipAddress);
71 return null;
72 }
73
74 return arpEntry.getMacAddress();
75 }
76
Jonathan Hart5afde492013-10-01 12:30:53 +130077 synchronized void update(InetAddress ipAddress, MACAddress macAddress){
Jonathan Hartabad6a52013-09-30 18:17:21 +130078 ArpCacheEntry arpEntry = arpCache.get(ipAddress);
79
80 if (arpEntry != null && arpEntry.getMacAddress().equals(macAddress)){
81 arpEntry.setTimeLastSeen(System.currentTimeMillis());
82 }
83 else {
84 arpCache.put(ipAddress, new ArpCacheEntry(macAddress));
85 }
86 }
Jonathan Hart5afde492013-10-01 12:30:53 +130087
88 synchronized List<String> getMappings() {
89 List<String> result = new ArrayList<String>(arpCache.size());
90
91 for (Map.Entry<InetAddress, ArpCacheEntry> entry : arpCache.entrySet()) {
92 result.add(entry.getKey().getHostAddress() + " => " +
93 entry.getValue().getMacAddress().toString() +
94 (entry.getValue().isExpired()?" : EXPIRED":" : VALID"));
95 }
96
97 return result;
98 }
Jonathan Hartabad6a52013-09-30 18:17:21 +130099}