Merge branch 'master' of https://github.com/OPENNETWORKINGLAB/ONOS
diff --git a/conf/cassandra-repair.sh b/conf/cassandra-repair.sh
new file mode 100755
index 0000000..2c2638e
--- /dev/null
+++ b/conf/cassandra-repair.sh
@@ -0,0 +1 @@
+<cassandra_dir>/bin/nodetool repair
diff --git a/conf/logback-deployment.xml b/conf/logback-deployment.xml
new file mode 100644
index 0000000..3877f65
--- /dev/null
+++ b/conf/logback-deployment.xml
@@ -0,0 +1,37 @@
+<configuration scan="true" debug="true">
+ <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+ <encoder>
+ <pattern>%level [%logger:%thread] %msg%n</pattern>
+ </encoder>
+ </appender>
+
+ <appender name="FILE" class="ch.qos.logback.core.FileAppender">
+ <file>./onos-logs/onos.ubuntu.log</file>
+ <encoder>
+ <pattern>%date %level [%thread] %logger{10} [%file:%line] %msg%n</pattern>
+ </encoder>
+ </appender>
+
+ <appender name="ROLLINGFILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <file>./onos-logs/onos.ubuntu.log</file>
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <!-- Roll over to a new log file every day -->
+ <fileNamePattern>./onos-logs/onos.ubuntu.%d{yyyy-MM-dd}.log</fileNamePattern>
+ <!-- Keep 10 days worth of logs -->
+ <maxHistory>10</maxHistory>
+ </rollingPolicy>
+
+ <encoder>
+ <pattern>%date %level [%thread] %logger{10} [%file:%line] %msg%n</pattern>
+ </encoder>
+
+ </appender>
+
+ <logger name="org" level="WARN"/>
+ <logger name="LogService" level="WARN"/> <!-- Restlet access logging -->
+ <logger name="net.floodlightcontroller.logging" level="WARN"/>
+
+ <root level="DEBUG">
+ <appender-ref ref="ROLLINGFILE" />
+ </root>
+</configuration>
diff --git a/src/main/java/net/onrc/onos/ofcontroller/bgproute/BgpRoute.java b/src/main/java/net/onrc/onos/ofcontroller/bgproute/BgpRoute.java
index 960d001..a698fd5 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/bgproute/BgpRoute.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/bgproute/BgpRoute.java
@@ -40,6 +40,7 @@
import net.onrc.onos.ofcontroller.linkdiscovery.ILinkDiscovery.LDUpdate;
import net.onrc.onos.ofcontroller.linkdiscovery.ILinkDiscoveryService;
import net.onrc.onos.ofcontroller.proxyarp.IArpRequester;
+import net.onrc.onos.ofcontroller.proxyarp.IProxyArpService;
import net.onrc.onos.ofcontroller.proxyarp.ProxyArpManager;
import net.onrc.onos.ofcontroller.routing.TopoRouteService;
import net.onrc.onos.ofcontroller.util.DataPath;
@@ -76,7 +77,8 @@
public class BgpRoute implements IFloodlightModule, IBgpRouteService,
ITopologyListener, IArpRequester,
- IOFSwitchListener, ILayer3InfoService {
+ IOFSwitchListener, ILayer3InfoService,
+ IProxyArpService {
protected static Logger log = LoggerFactory.getLogger(BgpRoute.class);
@@ -232,6 +234,7 @@
Map<Class<? extends IFloodlightService>, IFloodlightService> m
= new HashMap<Class<? extends IFloodlightService>, IFloodlightService>();
m.put(IBgpRouteService.class, this);
+ m.put(IProxyArpService.class, this);
return m;
}
@@ -262,7 +265,7 @@
//TODO We'll initialise this here for now, but it should really be done as
//part of the controller core
- proxyArp = new ProxyArpManager(floodlightProvider, topology, this);
+ proxyArp = new ProxyArpManager(floodlightProvider, topology, this, restApi);
linkUpdates = new ArrayList<LDUpdate>();
ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
@@ -429,7 +432,7 @@
InetAddress dstIpAddress = rib.getNextHop();
//See if we know the MAC address of the next hop
- byte[] nextHopMacAddress = proxyArp.getMacAddress(rib.getNextHop());
+ MACAddress nextHopMacAddress = proxyArp.getMacAddress(rib.getNextHop());
//Find the attachment point (egress interface) of the next hop
Interface egressInterface = null;
@@ -463,7 +466,7 @@
Path path = pushedPaths.get(dstIpAddress);
if (path == null) {
path = new Path(egressInterface, dstIpAddress);
- calculateAndPushPath(path, MACAddress.valueOf(nextHopMacAddress));
+ calculateAndPushPath(path, nextHopMacAddress);
pushedPaths.put(dstIpAddress, path);
}
@@ -476,9 +479,9 @@
}
}
- private void addPrefixFlows(Prefix prefix, Interface egressInterface, byte[] nextHopMacAddress) {
+ private void addPrefixFlows(Prefix prefix, Interface egressInterface, MACAddress nextHopMacAddress) {
log.debug("Adding flows for prefix {} added, next hop mac {}",
- prefix, HexString.toHexString(nextHopMacAddress));
+ prefix, nextHopMacAddress);
//We only need one flow mod per switch, so pick one interface on each switch
Map<Long, Interface> srcInterfaces = new HashMap<Long, Interface>();
@@ -533,7 +536,7 @@
//Set up MAC rewrite action
OFActionDataLayerDestination macRewriteAction = new OFActionDataLayerDestination();
- macRewriteAction.setDataLayerAddress(nextHopMacAddress);
+ macRewriteAction.setDataLayerAddress(nextHopMacAddress.toBytes());
//Set up output action
OFActionOutput outputAction = new OFActionOutput();
@@ -694,8 +697,8 @@
//See if we know the MAC address of the peer. If not we can't
//do anything until we learn it
- byte[] mac = proxyArp.getMacAddress(peer.getIpAddress());
- if (mac == null) {
+ MACAddress macAddress = proxyArp.getMacAddress(peer.getIpAddress());
+ if (macAddress == null) {
log.debug("Don't know MAC for {}", peer.getIpAddress().getHostAddress());
//Put in the pending paths list first
pathsWaitingOnArp.put(peer.getIpAddress(), path);
@@ -705,7 +708,7 @@
}
//If we know the MAC, lets go ahead and push the paths to this peer
- calculateAndPushPath(path, MACAddress.valueOf(mac));
+ calculateAndPushPath(path, macAddress);
}
}
@@ -959,9 +962,9 @@
}
@Override
- public void arpResponse(InetAddress ipAddress, byte[] macAddress) {
- log.debug("Received ARP response: {} => {}", ipAddress.getHostAddress(),
- MACAddress.valueOf(macAddress).toString());
+ public void arpResponse(InetAddress ipAddress, MACAddress macAddress) {
+ log.debug("Received ARP response: {} => {}",
+ ipAddress.getHostAddress(), macAddress);
/*
* We synchronize on this to prevent changes to the ptree while we're pushing
@@ -973,8 +976,7 @@
if (path != null) {
log.debug("Pushing path to {} at {} on {}", new Object[] {
- path.getDstIpAddress().getHostAddress(),
- MACAddress.valueOf(macAddress),
+ path.getDstIpAddress().getHostAddress(), macAddress,
path.getDstInterface().getSwitchPort()});
//These paths should always be to BGP peers. Paths to non-peers are
//handled once the first prefix is ready to push
@@ -986,7 +988,7 @@
}
}
else {
- calculateAndPushPath(path, MACAddress.valueOf(macAddress));
+ calculateAndPushPath(path, macAddress);
pushedPaths.put(path.getDstIpAddress(), path);
}
}
@@ -1299,4 +1301,27 @@
public MACAddress getRouterMacAddress() {
return bgpdMacAddress;
}
+
+ /*
+ * TODO This is a hack to get the REST API to work for ProxyArpManager.
+ * The REST API is currently tied to the Floodlight module system and we
+ * need to separate it to allow ONOS modules to use it. For now we will
+ * proxy calls through to the ProxyArpManager (which is not a Floodlight
+ * module) through this class which is a module.
+ */
+ @Override
+ public MACAddress getMacAddress(InetAddress ipAddress) {
+ return proxyArp.getMacAddress(ipAddress);
+ }
+
+ @Override
+ public void sendArpRequest(InetAddress ipAddress, IArpRequester requester,
+ boolean retry) {
+ proxyArp.sendArpRequest(ipAddress, requester, retry);
+ }
+
+ @Override
+ public List<String> getMappings() {
+ return proxyArp.getMappings();
+ }
}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/proxyarp/ArpCache.java b/src/main/java/net/onrc/onos/ofcontroller/proxyarp/ArpCache.java
new file mode 100644
index 0000000..83a3b55
--- /dev/null
+++ b/src/main/java/net/onrc/onos/ofcontroller/proxyarp/ArpCache.java
@@ -0,0 +1,99 @@
+package net.onrc.onos.ofcontroller.proxyarp;
+
+import java.net.InetAddress;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import net.floodlightcontroller.util.MACAddress;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * 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
+ * try and refresh the mapping before the entry times out because as a controller
+ * we don't know if the mapping is still needed.
+ */
+
+/* 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.
+ */
+class ArpCache {
+ private final static Logger log = LoggerFactory.getLogger(ArpCache.class);
+
+ private final static long ARP_ENTRY_TIMEOUT = 60000; //ms (1 min)
+
+ //Protected by locking on the ArpCache object
+ private final Map<InetAddress, ArpCacheEntry> arpCache;
+
+ private static class ArpCacheEntry {
+ private final MACAddress macAddress;
+ private long timeLastSeen;
+
+ public ArpCacheEntry(MACAddress macAddress) {
+ this.macAddress = macAddress;
+ this.timeLastSeen = System.currentTimeMillis();
+ }
+
+ public MACAddress getMacAddress() {
+ return macAddress;
+ }
+
+ public void setTimeLastSeen(long time){
+ timeLastSeen = time;
+ }
+
+ public boolean isExpired() {
+ return System.currentTimeMillis() - timeLastSeen > ARP_ENTRY_TIMEOUT;
+ }
+ }
+
+ ArpCache() {
+ arpCache = new HashMap<InetAddress, ArpCacheEntry>();
+ }
+
+ synchronized MACAddress lookup(InetAddress ipAddress){
+ ArpCacheEntry arpEntry = arpCache.get(ipAddress);
+
+ if (arpEntry == null){
+ return null;
+ }
+
+ if (arpEntry.isExpired()) {
+ //Entry has timed out so we'll remove it and return null
+ log.trace("Removing expired ARP entry for {}", ipAddress.getHostAddress());
+
+ arpCache.remove(ipAddress);
+ return null;
+ }
+
+ return arpEntry.getMacAddress();
+ }
+
+ synchronized void update(InetAddress ipAddress, MACAddress macAddress){
+ ArpCacheEntry arpEntry = arpCache.get(ipAddress);
+
+ if (arpEntry != null && arpEntry.getMacAddress().equals(macAddress)){
+ arpEntry.setTimeLastSeen(System.currentTimeMillis());
+ }
+ else {
+ arpCache.put(ipAddress, new ArpCacheEntry(macAddress));
+ }
+ }
+
+ synchronized List<String> getMappings() {
+ List<String> result = new ArrayList<String>(arpCache.size());
+
+ for (Map.Entry<InetAddress, ArpCacheEntry> entry : arpCache.entrySet()) {
+ result.add(entry.getKey().getHostAddress() + " => " +
+ entry.getValue().getMacAddress().toString() +
+ (entry.getValue().isExpired()?" : EXPIRED":" : VALID"));
+ }
+
+ return result;
+ }
+}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/proxyarp/ArpCacheResource.java b/src/main/java/net/onrc/onos/ofcontroller/proxyarp/ArpCacheResource.java
new file mode 100644
index 0000000..252e66e
--- /dev/null
+++ b/src/main/java/net/onrc/onos/ofcontroller/proxyarp/ArpCacheResource.java
@@ -0,0 +1,18 @@
+package net.onrc.onos.ofcontroller.proxyarp;
+
+import java.util.List;
+
+import org.restlet.resource.Get;
+import org.restlet.resource.ServerResource;
+
+public class ArpCacheResource extends ServerResource {
+
+ @Get("json")
+ public List<String> getArpCache() {
+ IProxyArpService arp = (IProxyArpService) getContext().getAttributes().
+ get(IProxyArpService.class.getCanonicalName());
+
+ return arp.getMappings();
+ }
+
+}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/proxyarp/ArpTableEntry.java b/src/main/java/net/onrc/onos/ofcontroller/proxyarp/ArpTableEntry.java
deleted file mode 100644
index 5830cfd..0000000
--- a/src/main/java/net/onrc/onos/ofcontroller/proxyarp/ArpTableEntry.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package net.onrc.onos.ofcontroller.proxyarp;
-
-
-public class ArpTableEntry {
-
- private byte[] macAddress;
- private long timeLastSeen;
-
- public ArpTableEntry(byte[] macAddress, long timeLastSeen) {
- this.macAddress = macAddress;
- this.timeLastSeen = timeLastSeen;
- }
-
- public byte[] getMacAddress() {
- return macAddress;
- }
-
- public long getTimeLastSeen() {
- return timeLastSeen;
- }
-
- public void setTimeLastSeen(long time){
- //TODO thread safety issues?
- timeLastSeen = time;
- }
-
-}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/proxyarp/ArpWebRoutable.java b/src/main/java/net/onrc/onos/ofcontroller/proxyarp/ArpWebRoutable.java
new file mode 100644
index 0000000..eefa2db
--- /dev/null
+++ b/src/main/java/net/onrc/onos/ofcontroller/proxyarp/ArpWebRoutable.java
@@ -0,0 +1,22 @@
+package net.onrc.onos.ofcontroller.proxyarp;
+
+import net.floodlightcontroller.restserver.RestletRoutable;
+
+import org.restlet.Context;
+import org.restlet.Restlet;
+import org.restlet.routing.Router;
+
+public class ArpWebRoutable implements RestletRoutable {
+
+ @Override
+ public Restlet getRestlet(Context context) {
+ Router router = new Router(context);
+ router.attach("/cache/json", ArpCacheResource.class);
+ return router;
+ }
+
+ @Override
+ public String basePath() {
+ return "/wm/arp";
+ }
+}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/proxyarp/HostArpRequester.java b/src/main/java/net/onrc/onos/ofcontroller/proxyarp/HostArpRequester.java
deleted file mode 100644
index 1474d02..0000000
--- a/src/main/java/net/onrc/onos/ofcontroller/proxyarp/HostArpRequester.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package net.onrc.onos.ofcontroller.proxyarp;
-
-import java.net.InetAddress;
-
-import net.floodlightcontroller.packet.ARP;
-
-public class HostArpRequester implements IArpRequester {
-
- private IProxyArpService arpService;
- private ARP arpRequest;
- private long dpid;
- private short port;
-
- public HostArpRequester(IProxyArpService arpService, ARP arpRequest,
- long dpid, short port) {
-
- this.arpService = arpService;
- this.arpRequest = arpRequest;
- this.dpid = dpid;
- this.port = port;
- }
-
- @Override
- public void arpResponse(InetAddress ipAddress, byte[] macAddress) {
- arpService.sendArpReply(arpRequest, dpid, port, macAddress);
- }
-
-}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/proxyarp/IArpRequester.java b/src/main/java/net/onrc/onos/ofcontroller/proxyarp/IArpRequester.java
index 90da2ba..66a17a2 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/proxyarp/IArpRequester.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/proxyarp/IArpRequester.java
@@ -2,6 +2,20 @@
import java.net.InetAddress;
+import net.floodlightcontroller.util.MACAddress;
+
+/**
+ * Callback interface for modules using the {@link IProxyArpService} to
+ * send ARP requests.
+ *
+ */
public interface IArpRequester {
- public void arpResponse(InetAddress ipAddress, byte[] macAddress);
+ /**
+ * Callback method that will be called by the {@link IProxyArpService}
+ * when it receives a reply for a request previously submitted by this
+ * {@code IArpRequester}.
+ * @param ipAddress The IP address than an ARP request was sent for
+ * @param macAddress The MAC address mapped to the requested IP address
+ */
+ public void arpResponse(InetAddress ipAddress, MACAddress macAddress);
}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/proxyarp/IProxyArpService.java b/src/main/java/net/onrc/onos/ofcontroller/proxyarp/IProxyArpService.java
index 2bb32f4..97844d3 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/proxyarp/IProxyArpService.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/proxyarp/IProxyArpService.java
@@ -1,30 +1,20 @@
package net.onrc.onos.ofcontroller.proxyarp;
import java.net.InetAddress;
+import java.util.List;
-import net.floodlightcontroller.packet.ARP;
+import net.floodlightcontroller.core.module.IFloodlightService;
+import net.floodlightcontroller.util.MACAddress;
-public interface IProxyArpService {
-
- public final int ARP_REQUEST_TIMEOUT = 2000; //ms
-
+//Extends IFloodlightService so we can access it from REST API resources
+public interface IProxyArpService extends IFloodlightService{
/**
- * Tell the IProxyArpService to send an ARP reply with the targetMac to
- * the host on the specified switchport.
- * @param arpRequest
- * @param dpid
- * @param port
- * @param targetMac
- */
- public void sendArpReply(ARP arpRequest, long dpid, short port, byte[] targetMac);
-
- /**
- * Returns the mac address if there is a valid entry in the cache.
+ * Returns the MAC address if there is a valid entry in the cache.
* Otherwise returns null.
* @param ipAddress
* @return
*/
- public byte[] getMacAddress(InetAddress ipAddress);
+ public MACAddress getMacAddress(InetAddress ipAddress);
/**
* Tell the IProxyArpService to send an ARP request for the IP address.
@@ -32,8 +22,13 @@
* @param ipAddress
* @param requester
* @param retry Whether to keep sending requests until the MAC is learnt
- * @return
*/
public void sendArpRequest(InetAddress ipAddress, IArpRequester requester,
boolean retry);
+
+ /**
+ * Returns a snapshot of the entire ARP cache.
+ * @return
+ */
+ public List<String> getMappings();
}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/proxyarp/ProxyArpManager.java b/src/main/java/net/onrc/onos/ofcontroller/proxyarp/ProxyArpManager.java
index 6e12f28..31cc4fc 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/proxyarp/ProxyArpManager.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/proxyarp/ProxyArpManager.java
@@ -5,7 +5,6 @@
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Collection;
-import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@@ -20,6 +19,7 @@
import net.floodlightcontroller.packet.ARP;
import net.floodlightcontroller.packet.Ethernet;
import net.floodlightcontroller.packet.IPv4;
+import net.floodlightcontroller.restserver.IRestApiService;
import net.floodlightcontroller.topology.ITopologyService;
import net.floodlightcontroller.util.MACAddress;
import net.onrc.onos.ofcontroller.bgproute.ILayer3InfoService;
@@ -40,25 +40,25 @@
import com.google.common.collect.Multimaps;
import com.google.common.collect.SetMultimap;
-//TODO REST API to inspect ARP table
public class ProxyArpManager implements IProxyArpService, IOFMessageListener {
private final static Logger log = LoggerFactory.getLogger(ProxyArpManager.class);
- private final long ARP_ENTRY_TIMEOUT = 600000; //ms (== 10 mins)
-
private final long ARP_TIMER_PERIOD = 60000; //ms (== 1 min)
+
+ private static final int ARP_REQUEST_TIMEOUT = 2000; //ms
- private IFloodlightProviderService floodlightProvider;
- private ITopologyService topology;
- private ILayer3InfoService layer3;
+ private final IFloodlightProviderService floodlightProvider;
+ private final ITopologyService topology;
+ private final ILayer3InfoService layer3;
+ private final IRestApiService restApi;
- private Map<InetAddress, ArpTableEntry> arpTable;
+ private final ArpCache arpCache;
- private SetMultimap<InetAddress, ArpRequest> arpRequests;
+ private final SetMultimap<InetAddress, ArpRequest> arpRequests;
- private class ArpRequest {
+ private static class ArpRequest {
private final IArpRequester requester;
- private boolean retry;
+ private final boolean retry;
private long requestTime;
public ArpRequest(IArpRequester requester, boolean retry){
@@ -74,32 +74,52 @@
}
public boolean isExpired() {
- return (System.currentTimeMillis() - requestTime)
- > IProxyArpService.ARP_REQUEST_TIMEOUT;
+ return (System.currentTimeMillis() - requestTime) > ARP_REQUEST_TIMEOUT;
}
public boolean shouldRetry() {
return retry;
}
- public void dispatchReply(InetAddress ipAddress, byte[] replyMacAddress) {
+ public void dispatchReply(InetAddress ipAddress, MACAddress replyMacAddress) {
requester.arpResponse(ipAddress, replyMacAddress);
}
}
+ private class HostArpRequester implements IArpRequester {
+ private final ARP arpRequest;
+ private final long dpid;
+ private final short port;
+
+ public HostArpRequester(ARP arpRequest, long dpid, short port) {
+ this.arpRequest = arpRequest;
+ this.dpid = dpid;
+ this.port = port;
+ }
+
+ @Override
+ public void arpResponse(InetAddress ipAddress, MACAddress macAddress) {
+ ProxyArpManager.this.sendArpReply(arpRequest, dpid, port, macAddress);
+ }
+ }
+
public ProxyArpManager(IFloodlightProviderService floodlightProvider,
- ITopologyService topology, ILayer3InfoService layer3){
+ ITopologyService topology, ILayer3InfoService layer3,
+ IRestApiService restApi){
this.floodlightProvider = floodlightProvider;
this.topology = topology;
this.layer3 = layer3;
+ this.restApi = restApi;
- arpTable = new HashMap<InetAddress, ArpTableEntry>();
+ arpCache = new ArpCache();
arpRequests = Multimaps.synchronizedSetMultimap(
HashMultimap.<InetAddress, ArpRequest>create());
}
public void startUp() {
+ restApi.addRestletRoutable(new ArpWebRoutable());
+
Timer arpTimer = new Timer("arp-processing");
arpTimer.scheduleAtFixedRate(new TimerTask() {
@Override
@@ -226,20 +246,20 @@
target.getHostAddress(), layer3.getRouterMacAddress());
sendArpReply(arp, sw.getId(), pi.getInPort(),
- layer3.getRouterMacAddress().toBytes());
+ layer3.getRouterMacAddress());
}
return;
}
- byte[] mac = lookupArpTable(arp.getTargetProtocolAddress());
+ MACAddress macAddress = arpCache.lookup(target);
- if (mac == null){
- //Mac address is not in our arp table.
+ if (macAddress == null){
+ //MAC address is not in our ARP cache.
//Record where the request came from so we know where to send the reply
arpRequests.put(target, new ArpRequest(
- new HostArpRequester(this, arp, sw.getId(), pi.getInPort()), false));
+ new HostArpRequester(arp, sw.getId(), pi.getInPort()), false));
//Flood the request out edge ports
sendArpRequestToSwitches(target, pi.getPacketData(), sw.getId(), pi.getInPort());
@@ -249,11 +269,11 @@
if (log.isTraceEnabled()) {
log.trace("Sending reply: {} => {} to host at {}/{}", new Object [] {
inetAddressToString(arp.getTargetProtocolAddress()),
- MACAddress.valueOf(mac).toString(),
+ macAddress.toString(),
HexString.toHexString(sw.getId()), pi.getInPort()});
}
- sendArpReply(arp, sw.getId(), pi.getInPort(), mac);
+ sendArpReply(arp, sw.getId(), pi.getInPort(), macAddress);
}
}
@@ -265,18 +285,20 @@
HexString.toHexString(sw.getId()), pi.getInPort()});
}
- updateArpTable(arp);
-
- //See if anyone's waiting for this ARP reply
- InetAddress addr;
+ InetAddress senderIpAddress;
try {
- addr = InetAddress.getByAddress(arp.getSenderProtocolAddress());
+ senderIpAddress = InetAddress.getByAddress(arp.getSenderProtocolAddress());
} catch (UnknownHostException e) {
log.debug("Invalid address in ARP reply", e);
return;
}
- Set<ArpRequest> requests = arpRequests.get(addr);
+ MACAddress senderMacAddress = MACAddress.valueOf(arp.getSenderHardwareAddress());
+
+ arpCache.update(senderIpAddress, senderMacAddress);
+
+ //See if anyone's waiting for this ARP reply
+ Set<ArpRequest> requests = arpRequests.get(senderIpAddress);
//Synchronize on the Multimap while using an iterator for one of the sets
List<ArpRequest> requestsToSend = new ArrayList<ArpRequest>(requests.size());
@@ -291,57 +313,7 @@
//Don't hold an ARP lock while dispatching requests
for (ArpRequest request : requestsToSend) {
- request.dispatchReply(addr, arp.getSenderHardwareAddress());
- }
- }
-
- private synchronized byte[] lookupArpTable(byte[] ipAddress){
- InetAddress addr;
- try {
- addr = InetAddress.getByAddress(ipAddress);
- } catch (UnknownHostException e) {
- log.debug("Unable to create InetAddress", e);
- return null;
- }
-
- ArpTableEntry arpEntry = arpTable.get(addr);
-
- if (arpEntry == null){
- return null;
- }
-
- if (System.currentTimeMillis() - arpEntry.getTimeLastSeen()
- > ARP_ENTRY_TIMEOUT){
- //Entry has timed out so we'll remove it and return null
- log.trace("Removing expired ARP entry for {}",
- inetAddressToString(ipAddress));
-
- arpTable.remove(addr);
- return null;
- }
-
- return arpEntry.getMacAddress();
- }
-
- private synchronized void updateArpTable(ARP arp){
- InetAddress addr;
- try {
- addr = InetAddress.getByAddress(arp.getSenderProtocolAddress());
- } catch (UnknownHostException e) {
- log.debug("Unable to create InetAddress", e);
- return;
- }
-
- ArpTableEntry arpEntry = arpTable.get(addr);
-
- if (arpEntry != null
- && arpEntry.getMacAddress() == arp.getSenderHardwareAddress()){
- arpEntry.setTimeLastSeen(System.currentTimeMillis());
- }
- else {
- arpTable.put(addr,
- new ArpTableEntry(arp.getSenderHardwareAddress(),
- System.currentTimeMillis()));
+ request.dispatchReply(senderIpAddress, senderMacAddress);
}
}
@@ -501,24 +473,11 @@
}
}
- private String inetAddressToString(byte[] bytes) {
- try {
- return InetAddress.getByAddress(bytes).getHostAddress();
- } catch (UnknownHostException e) {
- log.debug("Invalid IP address", e);
- return "";
- }
- }
-
- /*
- * IProxyArpService methods
- */
-
- public void sendArpReply(ARP arpRequest, long dpid, short port, byte[] targetMac) {
+ private void sendArpReply(ARP arpRequest, long dpid, short port, MACAddress targetMac) {
if (log.isTraceEnabled()) {
log.trace("Sending reply {} => {} to {}", new Object[] {
inetAddressToString(arpRequest.getTargetProtocolAddress()),
- HexString.toHexString(targetMac),
+ targetMac,
inetAddressToString(arpRequest.getSenderProtocolAddress())});
}
@@ -528,14 +487,14 @@
.setHardwareAddressLength((byte)Ethernet.DATALAYER_ADDRESS_LENGTH)
.setProtocolAddressLength((byte)IPv4.ADDRESS_LENGTH)
.setOpCode(ARP.OP_REPLY)
- .setSenderHardwareAddress(targetMac)
+ .setSenderHardwareAddress(targetMac.toBytes())
.setSenderProtocolAddress(arpRequest.getTargetProtocolAddress())
.setTargetHardwareAddress(arpRequest.getSenderHardwareAddress())
.setTargetProtocolAddress(arpRequest.getSenderProtocolAddress());
Ethernet eth = new Ethernet();
eth.setDestinationMACAddress(arpRequest.getSenderHardwareAddress())
- .setSourceMACAddress(targetMac)
+ .setSourceMACAddress(targetMac.toBytes())
.setEtherType(Ethernet.TYPE_ARP)
.setPayload(arpReply);
@@ -569,10 +528,23 @@
log.error("Failure writing packet out to switch", e);
}
}
+
+ private String inetAddressToString(byte[] bytes) {
+ try {
+ return InetAddress.getByAddress(bytes).getHostAddress();
+ } catch (UnknownHostException e) {
+ log.debug("Invalid IP address", e);
+ return "";
+ }
+ }
+
+ /*
+ * IProxyArpService methods
+ */
@Override
- public byte[] getMacAddress(InetAddress ipAddress) {
- return lookupArpTable(ipAddress.getAddress());
+ public MACAddress getMacAddress(InetAddress ipAddress) {
+ return arpCache.lookup(ipAddress);
}
@Override
@@ -585,4 +557,9 @@
sendArpRequestForAddress(ipAddress);
}
}
+
+ @Override
+ public List<String> getMappings() {
+ return arpCache.getMappings();
+ }
}
diff --git a/start-onos.sh b/start-onos.sh
index a35d181..14adfb0 100755
--- a/start-onos.sh
+++ b/start-onos.sh
@@ -71,7 +71,8 @@
done
# Create a logback file if required
- cat <<EOF_LOGBACK >${ONOS_LOGBACK}
+ if [ ! -f ${ONOS_LOGBACK} ]; then
+ cat <<EOF_LOGBACK >${ONOS_LOGBACK}
<configuration scan="true" debug="true">
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
@@ -95,6 +96,7 @@
</root>
</configuration>
EOF_LOGBACK
+ fi
# Run floodlight
echo "Starting ONOS controller ..."