Change for the way to learn IP and MAC binding.
ProxyArpManager has not done unit tests because the codes will be changed soon by another Jono's fix.
Change-Id: I0cf45aa328871497db522c531dcef999156c2d55
diff --git a/src/main/java/net/onrc/onos/apps/proxyarp/ArpCache.java b/src/main/java/net/onrc/onos/apps/proxyarp/ArpCache.java
index f8c1589..38cd41f 100644
--- a/src/main/java/net/onrc/onos/apps/proxyarp/ArpCache.java
+++ b/src/main/java/net/onrc/onos/apps/proxyarp/ArpCache.java
@@ -2,22 +2,18 @@
import java.net.InetAddress;
import java.util.ArrayList;
-import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Map.Entry;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
import net.floodlightcontroller.util.MACAddress;
+import net.onrc.onos.core.datastore.KVArpCache;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-/*
- * TODO clean out old ARP entries out of the cache periodically. We currently
- * don't do this which means the cache memory size will never decrease. We
- * already have a periodic thread that can be used to do this in
- * ProxyArpManager.
- */
-
/**
* Implements a basic ARP cache which maps IPv4 addresses to MAC addresses.
* Mappings time out after a short period of time (currently 1 min). We don't
@@ -26,11 +22,11 @@
*/
class ArpCache {
private static final Logger log = LoggerFactory.getLogger(ArpCache.class);
-
- private static final long ARP_ENTRY_TIMEOUT = 60000; // ms (1 min)
+ private static long arpEntryTimeoutConfig = 60000; // ms (1 min)
+ private final KVArpCache kvArpCache;
// Protected by locking on the ArpCache object (this)
- private final Map<InetAddress, ArpCacheEntry> arpCache;
+ private final ConcurrentMap<InetAddress, ArpCacheEntry> arpCache;
/**
* Represents a MAC address entry with a timestamp in the ARP cache.
@@ -75,17 +71,30 @@
* @return true if the entry has timed out.
*/
public boolean isExpired() {
- return System.currentTimeMillis() - timeLastSeen > ARP_ENTRY_TIMEOUT;
+ return System.currentTimeMillis() - timeLastSeen > arpEntryTimeoutConfig;
}
}
/**
- * Class constructor.
+ * Class constructors.
*/
- ArpCache() {
- arpCache = new HashMap<InetAddress, ArpCacheEntry>();
+ public ArpCache() {
+ arpCache = new ConcurrentHashMap<InetAddress, ArpCacheEntry>();
+ kvArpCache = new KVArpCache();
}
+ public void setArpEntryTimeoutConfig(long arpEntryTimeout) {
+ if (arpEntryTimeout <= 0) {
+ throw new IllegalArgumentException(Long.toString(arpEntryTimeout));
+ }
+ arpEntryTimeoutConfig(arpEntryTimeout);
+ }
+
+ private static void arpEntryTimeoutConfig(long arpEntryTimeout) {
+ ArpCache.arpEntryTimeoutConfig = arpEntryTimeout;
+ log.debug("Set arpEntryTimeoutConfig {}", ArpCache.arpEntryTimeoutConfig);
+ }
+
/**
* Get the MAC address that is mapped to an IP address in the ARP cache.
*
@@ -124,8 +133,27 @@
if (arpEntry != null && arpEntry.getMacAddress().equals(macAddress)) {
arpEntry.setTimeLastSeen(System.currentTimeMillis());
+ log.debug("The same ArpCache, ip {}, mac {}. Update local cache last seen time only.", ipAddress, macAddress);
} else {
arpCache.put(ipAddress, new ArpCacheEntry(macAddress));
+ kvArpCache.forceCreate(ipAddress, macAddress.toBytes());
+ log.debug("Create/Update ip {}, mac {} in ArpCache.", ipAddress, macAddress);
+ }
+ }
+
+ /**
+ * Remove an entry in the ARP cache.
+ *
+ * @param ipAddress the IP address that will be mapped in the cache
+ */
+ synchronized void remove(InetAddress ipAddress) {
+ ArpCacheEntry entry = arpCache.remove(ipAddress);
+
+ if (entry == null) {
+ log.debug("ArpCache doesn't have the ip key {}.", ipAddress);
+ } else {
+ kvArpCache.forceDelete(ipAddress);
+ log.debug("Remove it in ArpCache and DB, ip {}", ipAddress);
}
}
@@ -134,7 +162,7 @@
*
* @return list of all ARP mappings, formatted as a human-readable string
*/
- synchronized List<String> getMappings() {
+ List<String> getMappings() {
List<String> result = new ArrayList<String>(arpCache.size());
for (Map.Entry<InetAddress, ArpCacheEntry> entry : arpCache.entrySet()) {
@@ -146,4 +174,22 @@
return result;
}
+
+ /**
+ * Retrieve a list of all expired IPs in the ARP cache.
+ *
+ * @return list of all expired IPs
+ */
+ List<InetAddress> getExpiredArpCacheIps() {
+ List<InetAddress> result = new ArrayList<InetAddress>();
+
+ for (Entry<InetAddress, ArpCacheEntry> entry : arpCache.entrySet()) {
+ if (entry.getValue().isExpired()) {
+ log.debug("add to the expired ip list, ip {}", entry.getKey());
+ result.add(entry.getKey());
+ }
+ }
+
+ return result;
+ }
}