Addressed some checkstyle, PMD and findbugs violations in the ARP module
Change-Id: I194533ba5f96a7631ea662a93cbcbd8a2c84dea9
diff --git a/src/main/java/net/onrc/onos/ofcontroller/proxyarp/ArpCache.java b/src/main/java/net/onrc/onos/ofcontroller/proxyarp/ArpCache.java
index 83a3b55..0e965ff 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/proxyarp/ArpCache.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/proxyarp/ArpCache.java
@@ -11,89 +11,133 @@
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
- * 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.
+ * try and refresh the mapping before the entry times out because as a
+ * controller we don't know if the mapping is still needed.
*/
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;
+ private static final Logger log = LoggerFactory.getLogger(ArpCache.class);
- public ArpCacheEntry(MACAddress macAddress) {
- this.macAddress = macAddress;
- this.timeLastSeen = System.currentTimeMillis();
- }
+ private static final long ARP_ENTRY_TIMEOUT = 60000; // ms (1 min)
- public MACAddress getMacAddress() {
- return macAddress;
- }
-
- public void setTimeLastSeen(long time){
- timeLastSeen = time;
- }
-
- public boolean isExpired() {
- return System.currentTimeMillis() - timeLastSeen > ARP_ENTRY_TIMEOUT;
- }
- }
+ // Protected by locking on the ArpCache object (this)
+ private final Map<InetAddress, ArpCacheEntry> arpCache;
- ArpCache() {
- arpCache = new HashMap<InetAddress, ArpCacheEntry>();
- }
+ /**
+ * Represents a MAC address entry with a timestamp in the ARP cache.
+ * ARP cache entries are considered invalid if their timestamp is older
+ * than a timeout value.
+ */
+ private static class ArpCacheEntry {
+ private final MACAddress macAddress;
+ private long timeLastSeen;
- 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();
- }
+ /**
+ * Class constructor, specifying the MAC address for the entry.
+ * @param macAddress MAC address for the entry
+ */
+ public ArpCacheEntry(MACAddress macAddress) {
+ this.macAddress = macAddress;
+ this.timeLastSeen = System.currentTimeMillis();
+ }
- 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;
- }
+ /**
+ * Returns the MAC address this entry represents.
+ * @return this entry's MAC address
+ */
+ public MACAddress getMacAddress() {
+ return macAddress;
+ }
+
+ /**
+ * Update the timestamp for this entry.
+ * @param time the new timestamp to update the entry with
+ */
+ public void setTimeLastSeen(long time) {
+ timeLastSeen = time;
+ }
+
+ /**
+ * Returns whether the entry has timed out or not.
+ * @return true if the entry has timed out.
+ */
+ public boolean isExpired() {
+ return System.currentTimeMillis() - timeLastSeen > ARP_ENTRY_TIMEOUT;
+ }
+ }
+
+ /**
+ * Class constructor.
+ */
+ ArpCache() {
+ arpCache = new HashMap<InetAddress, ArpCacheEntry>();
+ }
+
+ /**
+ * Get the MAC address that is mapped to an IP address in the ARP cache.
+ * @param ipAddress the IP address to look up
+ * @return the MAC address if found in the cache, null if not
+ */
+ 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();
+ }
+
+ /**
+ * Update an entry in the ARP cache. If the IP to MAC mapping is already
+ * in the cache, its timestamp will be updated. If not, the entry will
+ * be added with a new timestamp of the current time.
+ * @param ipAddress the IP address that will be mapped in the cache
+ * @param macAddress the MAC address that maps to {@code ipAddress}
+ */
+ 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));
+ }
+ }
+
+ /**
+ * Retrieve a list of all mappings in the ARP cache.
+ * @return list of all ARP mappings, formatted as a human-readable string
+ *
+ */
+ 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
index 252e66e..242543c 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/proxyarp/ArpCacheResource.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/proxyarp/ArpCacheResource.java
@@ -5,14 +5,22 @@
import org.restlet.resource.Get;
import org.restlet.resource.ServerResource;
+/**
+ * REST resource to view the IP to MAC mappings in the ARP cache.
+ *
+ */
public class ArpCacheResource extends ServerResource {
- @Get("json")
- public List<String> getArpCache() {
- IProxyArpService arp = (IProxyArpService) getContext().getAttributes().
- get(IProxyArpService.class.getCanonicalName());
-
- return arp.getMappings();
- }
+ /**
+ * Handler for a REST call to retrieve the ARP cache.
+ * @return list of mappings formatted as a human-readable string.
+ */
+ @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/ArpReplyNotification.java b/src/main/java/net/onrc/onos/ofcontroller/proxyarp/ArpReplyNotification.java
index a8afc55..48d04e0 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/proxyarp/ArpReplyNotification.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/proxyarp/ArpReplyNotification.java
@@ -5,24 +5,42 @@
import net.floodlightcontroller.util.MACAddress;
+/**
+ * Inter-instance notification that an ARP reply has been received. The
+ * notification contains both the IP address and the MAC address.
+ */
public class ArpReplyNotification implements Serializable {
- private static final long serialVersionUID = 1L;
-
- private InetAddress targetAddress;
- private MACAddress targetMacAddress;
-
- public ArpReplyNotification(InetAddress targetAddress, MACAddress targetMacAddress) {
- this.targetAddress = targetAddress;
- this.targetMacAddress = targetMacAddress;
- }
+ private static final long serialVersionUID = 1L;
- public InetAddress getTargetAddress() {
- return targetAddress;
- }
+ private InetAddress targetAddress;
+ private MACAddress targetMacAddress;
- public MACAddress getTargetMacAddress() {
- return targetMacAddress;
- }
+ /**
+ * Class constructor.
+ * @param targetAddress IP address received from the ARP reply
+ * @param targetMacAddress MAC address received from the ARP reply
+ */
+ public ArpReplyNotification(InetAddress targetAddress,
+ MACAddress targetMacAddress) {
+ this.targetAddress = targetAddress;
+ this.targetMacAddress = targetMacAddress;
+ }
+
+ /**
+ * Returns the IP address of the ARP reply.
+ * @return the IP address
+ */
+ public InetAddress getTargetAddress() {
+ return targetAddress;
+ }
+
+ /**
+ * Returns the MAC address of the ARP reply.
+ * @return the MAC address
+ */
+ public MACAddress getTargetMacAddress() {
+ return targetMacAddress;
+ }
}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/proxyarp/ArpWebRoutable.java b/src/main/java/net/onrc/onos/ofcontroller/proxyarp/ArpWebRoutable.java
index eefa2db..606fb29 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/proxyarp/ArpWebRoutable.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/proxyarp/ArpWebRoutable.java
@@ -6,17 +6,31 @@
import org.restlet.Restlet;
import org.restlet.routing.Router;
+/**
+ * Routing class for ARP module REST URLs.
+ */
public class ArpWebRoutable implements RestletRoutable {
- @Override
- public Restlet getRestlet(Context context) {
- Router router = new Router(context);
- router.attach("/cache/json", ArpCacheResource.class);
- return router;
- }
+ /**
+ * Get a router configured with ARP module REST URLs.
+ *
+ * @param context the restlet context to build a router with
+ * @return the router
+ */
+ @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";
- }
+ /**
+ * Get the base path of the ARP module URLs.
+ *
+ * @return the string base path
+ */
+ @Override
+ public String basePath() {
+ return "/wm/arp";
+ }
}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/proxyarp/BroadcastPacketOutNotification.java b/src/main/java/net/onrc/onos/ofcontroller/proxyarp/BroadcastPacketOutNotification.java
index 135c061..22fe965 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/proxyarp/BroadcastPacketOutNotification.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/proxyarp/BroadcastPacketOutNotification.java
@@ -2,7 +2,9 @@
import java.net.InetAddress;
-//TODO This class is too generic to be handled by ProxyArpService.
+// TODO This class is too generic to be handled by ProxyArpService.
+// TODO The generic broadcast packet shouldn't contain an IP address which is
+// only for ARP packets.
/**
* Notification to all ONOS instances to broadcast this packet out the edge of
* the network. The edge is defined as any port that doesn't have a link to
@@ -10,33 +12,60 @@
* on.
*
*/
-public class BroadcastPacketOutNotification extends
- PacketOutNotification {
-
- private static final long serialVersionUID = 1L;
-
- private final InetAddress address;
- private final long inSwitch;
- private final short inPort;
+public class BroadcastPacketOutNotification extends PacketOutNotification {
- public BroadcastPacketOutNotification(byte[] packet, InetAddress address,
- long inSwitch, short inPort) {
- super(packet);
-
- this.address = address;
- this.inSwitch = inSwitch;
- this.inPort = inPort;
- }
+ private static final long serialVersionUID = 1L;
- public long getInSwitch() {
- return inSwitch;
- }
+ private final InetAddress address;
+ private final long inSwitch;
+ private final short inPort;
- public short getInPort() {
- return inPort;
- }
+ /**
+ * Class constructor.
+ *
+ * @param packet
+ * packet data to send in the packet-out
+ * @param address
+ * target IP address if the packet is an ARP packet
+ * @param inSwitch
+ * dpid of the switch the packet was received on
+ * @param inPort
+ * port number of the receiving port
+ */
+ public BroadcastPacketOutNotification(byte[] packet, InetAddress address,
+ long inSwitch, short inPort) {
+ super(packet);
- public InetAddress getTargetAddress() {
- return address;
- }
+ this.address = address;
+ this.inSwitch = inSwitch;
+ this.inPort = inPort;
+ }
+
+ /**
+ * Get the dpid of the switch the packet was received on.
+ *
+ * @return receiving switch dpid
+ */
+ public long getInSwitch() {
+ return inSwitch;
+ }
+
+ /**
+ * Get the port number of the port the packet was received on.
+ *
+ * @return receiving port number
+ */
+ public short getInPort() {
+ return inPort;
+ }
+
+ /**
+ * Get the target IP address if the packet is an ARP packet.
+ *
+ * @return the target IP address for ARP packets, or null if the packet is
+ * not an ARP packet
+ */
+ public InetAddress getTargetAddress() {
+ return address;
+ }
}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/proxyarp/IArpReplyEventHandler.java b/src/main/java/net/onrc/onos/ofcontroller/proxyarp/IArpReplyEventHandler.java
index 75f1d5d..98fcf0c 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/proxyarp/IArpReplyEventHandler.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/proxyarp/IArpReplyEventHandler.java
@@ -1,5 +1,12 @@
package net.onrc.onos.ofcontroller.proxyarp;
+/**
+ * Listener interface for ARP reply event callbacks.
+ */
public interface IArpReplyEventHandler {
- public void arpReplyEvent(ArpReplyNotification arpReply);
+ /**
+ * An ARP reply has been received.
+ * @param arpReply data about the received ARP reply
+ */
+ public void arpReplyEvent(ArpReplyNotification arpReply);
}
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 66a17a2..51a6295 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/proxyarp/IArpRequester.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/proxyarp/IArpRequester.java
@@ -5,17 +5,20 @@
import net.floodlightcontroller.util.MACAddress;
/**
- * Callback interface for modules using the {@link IProxyArpService} to
- * send ARP requests.
+ * Callback interface for modules using the {@link IProxyArpService} to send ARP
+ * requests.
*
*/
public interface IArpRequester {
- /**
- * 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);
+ /**
+ * 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/IPacketOutEventHandler.java b/src/main/java/net/onrc/onos/ofcontroller/proxyarp/IPacketOutEventHandler.java
index 86b3728..ce98703 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/proxyarp/IPacketOutEventHandler.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/proxyarp/IPacketOutEventHandler.java
@@ -1,18 +1,20 @@
package net.onrc.onos.ofcontroller.proxyarp;
/**
- * Classes may implement this interface if they wish to subscribe to
- * packet out notifications from the datagrid service. Packet out notifications
- * are used to direct other ONOS instances to send packets out particular
- * ports under their control.
+ * Classes may implement this interface if they wish to subscribe to packet out
+ * notifications from the datagrid service. Packet out notifications are used to
+ * direct other ONOS instances to send packets out particular ports under their
+ * control.
*
*/
public interface IPacketOutEventHandler {
- /**
- * Notify the packet out event handler that an packet out notification has
- * been received.
- * @param packetOutNotification An object describing the notification
- */
- public void packetOutNotification(PacketOutNotification packetOutNotification);
+ /**
+ * Notify the packet out event handler that an packet out notification has
+ * been received.
+ *
+ * @param packetOutNotification An object describing the notification
+ */
+ public void packetOutNotification(
+ PacketOutNotification packetOutNotification);
}
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 2029513..57993e5 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/proxyarp/IProxyArpService.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/proxyarp/IProxyArpService.java
@@ -6,29 +6,37 @@
import net.floodlightcontroller.core.module.IFloodlightService;
import net.floodlightcontroller.util.MACAddress;
-//Extends IFloodlightService so we can access it from REST API resources
+// Extends IFloodlightService so we can access it from REST API resources
+/**
+ * Provides ARP services to other modules.
+ */
public interface IProxyArpService extends IFloodlightService {
- /**
- * Returns the MAC address if there is a valid entry in the cache.
- * Otherwise returns null.
- * @param ipAddress
- * @return
- */
- public MACAddress getMacAddress(InetAddress ipAddress);
-
- /**
- * Tell the IProxyArpService to send an ARP request for the IP address.
- * The request will be broadcast out all edge ports in the network.
- * @param ipAddress
- * @param requester
- * @param retry Whether to keep sending requests until the MAC is learnt
- */
- public void sendArpRequest(InetAddress ipAddress, IArpRequester requester,
- boolean retry);
-
- /**
- * Returns a snapshot of the entire ARP cache.
- * @return
- */
- public List<String> getMappings();
+ /**
+ * Returns the MAC address if there is a valid entry in the cache. Otherwise
+ * returns null.
+ *
+ * @param ipAddress the IP address to request the ARP mapping for
+ * @return the MACAddress that maps to the specified IP address, or null if
+ * no mapping is found
+ */
+ public MACAddress getMacAddress(InetAddress ipAddress);
+
+ /**
+ * Tell the IProxyArpService to send an ARP request for the IP address. The
+ * request will be broadcast out all edge ports in the network.
+ *
+ * @param ipAddress the IP address to send an ARP request for
+ * @param requester the {@link IArpRequester} object that will be called if
+ * a reply is received
+ * @param retry whether to keep sending requests until the MAC is learnt
+ */
+ public void sendArpRequest(InetAddress ipAddress, IArpRequester requester,
+ boolean retry);
+
+ /**
+ * Returns a snapshot of the entire ARP cache.
+ *
+ * @return a list of mappings formatted as a human-readable string
+ */
+ public List<String> getMappings();
}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/proxyarp/PacketOutNotification.java b/src/main/java/net/onrc/onos/ofcontroller/proxyarp/PacketOutNotification.java
index 3d37d25..a201939 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/proxyarp/PacketOutNotification.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/proxyarp/PacketOutNotification.java
@@ -4,18 +4,21 @@
/**
* A PacketOutNotification contains data sent between ONOS instances that
- * directs other instances to send a packet out a set of ports.
- * This is an abstract base class that will be subclassed by specific
- * types of notifications.
- *
+ * directs other instances to send a packet out a set of ports. This is an
+ * abstract base class that will be subclassed by specific types of
+ * notifications.
*/
public abstract class PacketOutNotification implements Serializable {
- private static final long serialVersionUID = 1L;
-
- protected final byte[] packet;
+ private static final long serialVersionUID = 1L;
- public PacketOutNotification(byte[] packet) {
- this.packet = packet;
- }
+ protected final byte[] packet;
+
+ /**
+ * Class constructor.
+ * @param packet the packet data to send in the packet-out
+ */
+ public PacketOutNotification(byte[] packet) {
+ this.packet = packet;
+ }
}
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 2294a60..33d4d7d 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/proxyarp/ProxyArpManager.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/proxyarp/ProxyArpManager.java
@@ -46,780 +46,798 @@
import com.google.common.collect.SetMultimap;
public class ProxyArpManager implements IProxyArpService, IOFMessageListener,
- IPacketOutEventHandler, IArpReplyEventHandler,
- IFloodlightModule {
- private final static Logger log = LoggerFactory.getLogger(ProxyArpManager.class);
-
- private final long ARP_TIMER_PERIOD = 100; //ms
+ IPacketOutEventHandler, IArpReplyEventHandler, IFloodlightModule {
+ private static final Logger log = LoggerFactory
+ .getLogger(ProxyArpManager.class);
- private static final int ARP_REQUEST_TIMEOUT = 2000; //ms
-
- private IFloodlightProviderService floodlightProvider;
- private IDatagridService datagrid;
- private IConfigInfoService configService;
- private IRestApiService restApi;
- private IFlowPusherService flowPusher;
-
- private short vlan;
- private static final short NO_VLAN = 0;
-
- //private ArpCache arpCache;
+ private static final long ARP_TIMER_PERIOD = 100; // ms
- private SetMultimap<InetAddress, ArpRequest> arpRequests;
-
- private static class ArpRequest {
- private final IArpRequester requester;
- private final boolean retry;
- private boolean sent = false;
- private long requestTime;
-
- public ArpRequest(IArpRequester requester, boolean retry){
- this.requester = requester;
- this.retry = retry;
- }
-
- public ArpRequest(ArpRequest old) {
- this.requester = old.requester;
- this.retry = old.retry;
- }
-
- public boolean isExpired() {
- return sent && ((System.currentTimeMillis() - requestTime) > ARP_REQUEST_TIMEOUT);
- }
-
- public boolean shouldRetry() {
- return retry;
- }
-
- public void dispatchReply(InetAddress ipAddress, MACAddress replyMacAddress) {
- requester.arpResponse(ipAddress, replyMacAddress);
- }
-
- public void setRequestTime() {
- this.requestTime = System.currentTimeMillis();
- this.sent = true;
- }
- }
-
- 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;
- }
+ private static final int ARP_REQUEST_TIMEOUT = 2000; // ms
- @Override
- public void arpResponse(InetAddress ipAddress, MACAddress macAddress) {
- ProxyArpManager.this.sendArpReply(arpRequest, dpid, port, macAddress);
- }
- }
-
- @Override
- public Collection<Class<? extends IFloodlightService>> getModuleServices() {
- Collection<Class<? extends IFloodlightService>> l
- = new ArrayList<Class<? extends IFloodlightService>>();
- l.add(IProxyArpService.class);
- return l;
- }
+ private IFloodlightProviderService floodlightProvider;
+ private IDatagridService datagrid;
+ private IConfigInfoService configService;
+ private IRestApiService restApi;
+ private IFlowPusherService flowPusher;
- @Override
- public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() {
- Map<Class<? extends IFloodlightService>, IFloodlightService> m
- = new HashMap<Class<? extends IFloodlightService>, IFloodlightService>();
- m.put(IProxyArpService.class, this);
- return m;
- }
+ private short vlan;
+ private static final short NO_VLAN = 0;
- @Override
- public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
- Collection<Class<? extends IFloodlightService>> dependencies
- = new ArrayList<Class<? extends IFloodlightService>>();
- dependencies.add(IFloodlightProviderService.class);
- dependencies.add(IRestApiService.class);
- dependencies.add(IDatagridService.class);
- dependencies.add(IConfigInfoService.class);
- dependencies.add(IFlowPusherService.class);
- return dependencies;
- }
-
- @Override
- public void init(FloodlightModuleContext context){
- this.floodlightProvider =
- context.getServiceImpl(IFloodlightProviderService.class);
- this.datagrid = context.getServiceImpl(IDatagridService.class);
- this.configService = context.getServiceImpl(IConfigInfoService.class);
- this.restApi = context.getServiceImpl(IRestApiService.class);
- this.flowPusher = context.getServiceImpl(IFlowPusherService.class);
-
- //arpCache = new ArpCache();
+ private SetMultimap<InetAddress, ArpRequest> arpRequests;
- arpRequests = Multimaps.synchronizedSetMultimap(
- HashMultimap.<InetAddress, ArpRequest>create());
-
- }
-
- @Override
- public void startUp(FloodlightModuleContext context) {
- this.vlan = configService.getVlan();
- log.info("vlan set to {}", this.vlan);
-
- restApi.addRestletRoutable(new ArpWebRoutable());
- floodlightProvider.addOFMessageListener(OFType.PACKET_IN, this);
-
- datagrid.registerPacketOutEventHandler(this);
- datagrid.registerArpReplyEventHandler(this);
-
- Timer arpTimer = new Timer("arp-processing");
- arpTimer.scheduleAtFixedRate(new TimerTask() {
- @Override
- public void run() {
- doPeriodicArpProcessing();
- }
- }, 0, ARP_TIMER_PERIOD);
- }
-
- /*
- * Function that runs periodically to manage the asynchronous request mechanism.
- * It basically cleans up old ARP requests if we don't get a response for them.
- * The caller can designate that a request should be retried indefinitely, and
- * this task will handle that as well.
- */
- private void doPeriodicArpProcessing() {
- SetMultimap<InetAddress, ArpRequest> retryList
- = HashMultimap.<InetAddress, ArpRequest>create();
+ private static class ArpRequest {
+ private final IArpRequester requester;
+ private final boolean retry;
+ private boolean sent = false;
+ private long requestTime;
- //Have to synchronize externally on the Multimap while using an iterator,
- //even though it's a synchronizedMultimap
- synchronized (arpRequests) {
- Iterator<Map.Entry<InetAddress, ArpRequest>> it
- = arpRequests.entries().iterator();
-
- while (it.hasNext()) {
- Map.Entry<InetAddress, ArpRequest> entry
- = it.next();
- ArpRequest request = entry.getValue();
- if (request.isExpired()) {
- log.debug("Cleaning expired ARP request for {}",
- entry.getKey().getHostAddress());
-
- // If the ARP request is expired and then delete the device
- // TODO check whether this is OK from this thread
- // TODO: Fix the code below after deviceStorage was removed
- /*
- IDeviceObject targetDevice =
- deviceStorage.getDeviceByIP(InetAddresses.coerceToInteger(entry.getKey()));
- if (targetDevice != null) {
- deviceStorage.removeDevice(targetDevice);
- if (log.isDebugEnabled()) {
- log.debug("RemoveDevice: {} due to no have not recieve the ARP reply", targetDevice);
- }
- }
- */
-
- it.remove();
-
- if (request.shouldRetry()) {
- retryList.put(entry.getKey(), request);
- }
- }
- }
- }
-
- for (Map.Entry<InetAddress, Collection<ArpRequest>> entry
- : retryList.asMap().entrySet()) {
-
- InetAddress address = entry.getKey();
-
- log.debug("Resending ARP request for {}", address.getHostAddress());
-
- // Only ARP requests sent by the controller will have the retry flag
- // set, so for now we can just send a new ARP request for that address.
- sendArpRequestForAddress(address);
-
- for (ArpRequest request : entry.getValue()) {
- arpRequests.put(address, new ArpRequest(request));
- }
- }
- }
-
- @Override
- public String getName() {
- return "proxyarpmanager";
- }
+ public ArpRequest(IArpRequester requester, boolean retry) {
+ this.requester = requester;
+ this.retry = retry;
+ }
- @Override
- public boolean isCallbackOrderingPrereq(OFType type, String name) {
- if (type == OFType.PACKET_IN) {
- return "devicemanager".equals(name) || "onosdevicemanager".equals(name);
- }
- else {
- return false;
- }
- }
+ public ArpRequest(ArpRequest old) {
+ this.requester = old.requester;
+ this.retry = old.retry;
+ }
- @Override
- public boolean isCallbackOrderingPostreq(OFType type, String name) {
- return type == OFType.PACKET_IN && "onosforwarding".equals(name);
- }
+ public boolean isExpired() {
+ return sent
+ && ((System.currentTimeMillis() - requestTime) > ARP_REQUEST_TIMEOUT);
+ }
- @Override
- public Command receive(
- IOFSwitch sw, OFMessage msg, FloodlightContext cntx) {
-
- OFPacketIn pi = (OFPacketIn) msg;
-
- Ethernet eth = IFloodlightProviderService.bcStore.get(cntx,
+ public boolean shouldRetry() {
+ return retry;
+ }
+
+ public void dispatchReply(InetAddress ipAddress,
+ MACAddress replyMacAddress) {
+ requester.arpResponse(ipAddress, replyMacAddress);
+ }
+
+ public void setRequestTime() {
+ this.requestTime = System.currentTimeMillis();
+ this.sent = true;
+ }
+ }
+
+ 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);
+ }
+ }
+
+ @Override
+ public Collection<Class<? extends IFloodlightService>> getModuleServices() {
+ Collection<Class<? extends IFloodlightService>> l =
+ new ArrayList<Class<? extends IFloodlightService>>();
+ l.add(IProxyArpService.class);
+ return l;
+ }
+
+ @Override
+ public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() {
+ Map<Class<? extends IFloodlightService>, IFloodlightService> m =
+ new HashMap<Class<? extends IFloodlightService>, IFloodlightService>();
+ m.put(IProxyArpService.class, this);
+ return m;
+ }
+
+ @Override
+ public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
+ Collection<Class<? extends IFloodlightService>> dependencies =
+ new ArrayList<Class<? extends IFloodlightService>>();
+ dependencies.add(IFloodlightProviderService.class);
+ dependencies.add(IRestApiService.class);
+ dependencies.add(IDatagridService.class);
+ dependencies.add(IConfigInfoService.class);
+ dependencies.add(IFlowPusherService.class);
+ return dependencies;
+ }
+
+ @Override
+ public void init(FloodlightModuleContext context) {
+ this.floodlightProvider = context
+ .getServiceImpl(IFloodlightProviderService.class);
+ this.datagrid = context.getServiceImpl(IDatagridService.class);
+ this.configService = context.getServiceImpl(IConfigInfoService.class);
+ this.restApi = context.getServiceImpl(IRestApiService.class);
+ this.flowPusher = context.getServiceImpl(IFlowPusherService.class);
+
+ // arpCache = new ArpCache();
+
+ arpRequests = Multimaps.synchronizedSetMultimap(HashMultimap
+ .<InetAddress, ArpRequest>create());
+
+ }
+
+ @Override
+ public void startUp(FloodlightModuleContext context) {
+ this.vlan = configService.getVlan();
+ log.info("vlan set to {}", this.vlan);
+
+ restApi.addRestletRoutable(new ArpWebRoutable());
+ floodlightProvider.addOFMessageListener(OFType.PACKET_IN, this);
+
+ datagrid.registerPacketOutEventHandler(this);
+ datagrid.registerArpReplyEventHandler(this);
+
+ Timer arpTimer = new Timer("arp-processing");
+ arpTimer.scheduleAtFixedRate(new TimerTask() {
+ @Override
+ public void run() {
+ doPeriodicArpProcessing();
+ }
+ }, 0, ARP_TIMER_PERIOD);
+ }
+
+ /*
+ * Function that runs periodically to manage the asynchronous request mechanism.
+ * It basically cleans up old ARP requests if we don't get a response for them.
+ * The caller can designate that a request should be retried indefinitely, and
+ * this task will handle that as well.
+ */
+ private void doPeriodicArpProcessing() {
+ SetMultimap<InetAddress, ArpRequest> retryList = HashMultimap
+ .<InetAddress, ArpRequest>create();
+
+ // Have to synchronize externally on the Multimap while using an
+ // iterator,
+ // even though it's a synchronizedMultimap
+ synchronized (arpRequests) {
+ Iterator<Map.Entry<InetAddress, ArpRequest>> it = arpRequests
+ .entries().iterator();
+
+ while (it.hasNext()) {
+ Map.Entry<InetAddress, ArpRequest> entry = it.next();
+ ArpRequest request = entry.getValue();
+ if (request.isExpired()) {
+ log.debug("Cleaning expired ARP request for {}", entry
+ .getKey().getHostAddress());
+
+ // If the ARP request is expired and then delete the device
+ // TODO check whether this is OK from this thread
+ // TODO: Fix the code below after deviceStorage was removed
+ /*
+ IDeviceObject targetDevice =
+ deviceStorage.getDeviceByIP(InetAddresses.coerceToInteger(entry.getKey()));
+ if (targetDevice != null) {
+ deviceStorage.removeDevice(targetDevice);
+ if (log.isDebugEnabled()) {
+ log.debug("RemoveDevice: {} due to no have not recieve the ARP reply", targetDevice);
+ }
+ }
+ */
+
+ it.remove();
+
+ if (request.shouldRetry()) {
+ retryList.put(entry.getKey(), request);
+ }
+ }
+ }
+ }
+
+ for (Map.Entry<InetAddress, Collection<ArpRequest>> entry : retryList
+ .asMap().entrySet()) {
+
+ InetAddress address = entry.getKey();
+
+ log.debug("Resending ARP request for {}", address.getHostAddress());
+
+ // Only ARP requests sent by the controller will have the retry flag
+ // set, so for now we can just send a new ARP request for that
+ // address.
+ sendArpRequestForAddress(address);
+
+ for (ArpRequest request : entry.getValue()) {
+ arpRequests.put(address, new ArpRequest(request));
+ }
+ }
+ }
+
+ @Override
+ public String getName() {
+ return "proxyarpmanager";
+ }
+
+ @Override
+ public boolean isCallbackOrderingPrereq(OFType type, String name) {
+ if (type == OFType.PACKET_IN) {
+ return "devicemanager".equals(name)
+ || "onosdevicemanager".equals(name);
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public boolean isCallbackOrderingPostreq(OFType type, String name) {
+ return type == OFType.PACKET_IN && "onosforwarding".equals(name);
+ }
+
+ @Override
+ public Command receive(IOFSwitch sw, OFMessage msg, FloodlightContext cntx) {
+
+ OFPacketIn pi = (OFPacketIn) msg;
+
+ Ethernet eth = IFloodlightProviderService.bcStore.get(cntx,
IFloodlightProviderService.CONTEXT_PI_PAYLOAD);
-
- if (eth.getEtherType() == Ethernet.TYPE_ARP){
- ARP arp = (ARP) eth.getPayload();
- if (arp.getOpCode() == ARP.OP_REQUEST) {
- handleArpRequest(sw, pi, arp, eth);
- }
- else if (arp.getOpCode() == ARP.OP_REPLY) {
- // For replies we simply send a notification via Hazelcast
- sendArpReplyNotification(eth, pi);
-
- //handleArpReply(sw, pi, arp);
- }
-
- // Stop ARP packets here
- return Command.STOP;
- }
-
- // Propagate everything else
- return Command.CONTINUE;
- }
-
- private void handleArpRequest(IOFSwitch sw, OFPacketIn pi, ARP arp, Ethernet eth) {
- if (log.isTraceEnabled()) {
- log.trace("ARP request received for {}",
- inetAddressToString(arp.getTargetProtocolAddress()));
- }
- InetAddress target;
- try {
- target = InetAddress.getByAddress(arp.getTargetProtocolAddress());
- } catch (UnknownHostException e) {
- log.debug("Invalid address in ARP request", e);
- return;
- }
+ if (eth.getEtherType() == Ethernet.TYPE_ARP) {
+ ARP arp = (ARP) eth.getPayload();
+ if (arp.getOpCode() == ARP.OP_REQUEST) {
+ handleArpRequest(sw, pi, arp, eth);
+ } else if (arp.getOpCode() == ARP.OP_REPLY) {
+ // For replies we simply send a notification via Hazelcast
+ sendArpReplyNotification(eth, pi);
- if (configService.fromExternalNetwork(sw.getId(), pi.getInPort())) {
- //If the request came from outside our network, we only care if
- //it was a request for one of our interfaces.
- if (configService.isInterfaceAddress(target)) {
- log.trace("ARP request for our interface. Sending reply {} => {}",
- target.getHostAddress(), configService.getRouterMacAddress());
+ // handleArpReply(sw, pi, arp);
+ }
- sendArpReply(arp, sw.getId(), pi.getInPort(),
- configService.getRouterMacAddress());
- }
+ // Stop ARP packets here
+ return Command.STOP;
+ }
- return;
- }
-
- //MACAddress macAddress = arpCache.lookup(target);
+ // Propagate everything else
+ return Command.CONTINUE;
+ }
- arpRequests.put(target, new ArpRequest(
- new HostArpRequester(arp, sw.getId(), pi.getInPort()), false));
+ private void handleArpRequest(IOFSwitch sw, OFPacketIn pi, ARP arp,
+ Ethernet eth) {
+ if (log.isTraceEnabled()) {
+ log.trace("ARP request received for {}",
+ inetAddressToString(arp.getTargetProtocolAddress()));
+ }
- // TODO: Fix the code below after deviceStorage was removed
- /*
- IDeviceObject targetDevice =
- deviceStorage.getDeviceByIP(InetAddresses.coerceToInteger(target));
- */
+ InetAddress target;
+ try {
+ target = InetAddress.getByAddress(arp.getTargetProtocolAddress());
+ } catch (UnknownHostException e) {
+ log.debug("Invalid address in ARP request", e);
+ return;
+ }
- // TODO: Fix the code below after deviceStorage was removed
- /*
- if (targetDevice == null) {
- if (log.isTraceEnabled()) {
- log.trace("No device info found for {} - broadcasting",
- target.getHostAddress());
- }
-
- // We don't know the device so broadcast the request out
- datagrid.sendPacketOutNotification(
- new BroadcastPacketOutNotification(eth.serialize(),
- target, sw.getId(), pi.getInPort()));
- }
- else {
- // Even if the device exists in our database, we do not reply to
- // the request directly, but check whether the device is still valid
- MACAddress macAddress = MACAddress.valueOf(targetDevice.getMACAddress());
+ if (configService.fromExternalNetwork(sw.getId(), pi.getInPort())) {
+ // If the request came from outside our network, we only care if
+ // it was a request for one of our interfaces.
+ if (configService.isInterfaceAddress(target)) {
+ log.trace(
+ "ARP request for our interface. Sending reply {} => {}",
+ target.getHostAddress(),
+ configService.getRouterMacAddress());
- if (log.isTraceEnabled()) {
- log.trace("The target Device Record in DB is: {} => {} from ARP request host at {}/{}",
- new Object [] {
- inetAddressToString(arp.getTargetProtocolAddress()),
- macAddress,
- HexString.toHexString(sw.getId()), pi.getInPort()});
- }
+ sendArpReply(arp, sw.getId(), pi.getInPort(),
+ configService.getRouterMacAddress());
+ }
- // sendArpReply(arp, sw.getId(), pi.getInPort(), macAddress);
+ return;
+ }
- Iterable<IPortObject> outPorts = targetDevice.getAttachedPorts();
+ // MACAddress macAddress = arpCache.lookup(target);
- if (!outPorts.iterator().hasNext()){
- if (log.isTraceEnabled()) {
- log.trace("Device {} exists but is not connected to any ports" +
- " - broadcasting", macAddress);
- }
-
- datagrid.sendPacketOutNotification(
- new BroadcastPacketOutNotification(eth.serialize(),
- target, sw.getId(), pi.getInPort()));
- }
- else {
- for (IPortObject portObject : outPorts) {
- //long outSwitch = 0;
- //short outPort = 0;
+ arpRequests.put(
+ target,
+ new ArpRequest(new HostArpRequester(arp, sw.getId(), pi
+ .getInPort()), false));
- // if (!portObject.getLinkedPorts().iterator().hasNext()) {
- // outPort = portObject.getNumber();
- // }
- if (portObject.getLinkedPorts().iterator().hasNext()) {
- continue;
- }
+ // TODO: Fix the code below after deviceStorage was removed
+ /*
+ IDeviceObject targetDevice =
+ deviceStorage.getDeviceByIP(InetAddresses.coerceToInteger(target));
+ */
- short outPort = portObject.getNumber();
- ISwitchObject outSwitchObject = portObject.getSwitch();
- long outSwitch = HexString.toLong(outSwitchObject.getDPID());
+ // TODO: Fix the code below after deviceStorage was removed
+ /*
+ if (targetDevice == null) {
+ if (log.isTraceEnabled()) {
+ log.trace("No device info found for {} - broadcasting",
+ target.getHostAddress());
+ }
- if (log.isTraceEnabled()) {
- log.trace("Probing device {} on port {}/{}",
- new Object[] {macAddress,
- HexString.toHexString(outSwitch), outPort});
- }
-
- datagrid.sendPacketOutNotification(
- new SinglePacketOutNotification(eth.serialize(),
- target, outSwitch, outPort));
- }
- }
- }
- */
- }
-
- private void handleArpReply(IOFSwitch sw, OFPacketIn pi, ARP arp){
- if (log.isTraceEnabled()) {
- log.trace("ARP reply recieved: {} => {}, on {}/{}", new Object[] {
- inetAddressToString(arp.getSenderProtocolAddress()),
- HexString.toHexString(arp.getSenderHardwareAddress()),
- HexString.toHexString(sw.getId()), pi.getInPort()});
- }
-
- InetAddress senderIpAddress;
- try {
- senderIpAddress = InetAddress.getByAddress(arp.getSenderProtocolAddress());
- } catch (UnknownHostException e) {
- log.debug("Invalid address in ARP reply", e);
- return;
- }
-
- MACAddress senderMacAddress = MACAddress.valueOf(arp.getSenderHardwareAddress());
-
- //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());
- synchronized (arpRequests) {
- Iterator<ArpRequest> it = requests.iterator();
- while (it.hasNext()) {
- ArpRequest request = it.next();
- it.remove();
- requestsToSend.add(request);
- }
- }
-
- //Don't hold an ARP lock while dispatching requests
- for (ArpRequest request : requestsToSend) {
- request.dispatchReply(senderIpAddress, senderMacAddress);
- }
- }
-
- private void sendArpRequestForAddress(InetAddress ipAddress) {
- //TODO what should the sender IP address and MAC address be if no
- //IP addresses are configured? Will there ever be a need to send
- //ARP requests from the controller in that case?
- //All-zero MAC address doesn't seem to work - hosts don't respond to it
-
- byte[] zeroIpv4 = {0x0, 0x0, 0x0, 0x0};
- byte[] zeroMac = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
- byte[] genericNonZeroMac = {0x0, 0x0, 0x0, 0x0, 0x0, 0x01};
- byte[] broadcastMac = {(byte)0xff, (byte)0xff, (byte)0xff,
- (byte)0xff, (byte)0xff, (byte)0xff};
-
- ARP arpRequest = new ARP();
-
- arpRequest.setHardwareType(ARP.HW_TYPE_ETHERNET)
- .setProtocolType(ARP.PROTO_TYPE_IP)
- .setHardwareAddressLength((byte)Ethernet.DATALAYER_ADDRESS_LENGTH)
- .setProtocolAddressLength((byte)IPv4.ADDRESS_LENGTH)
- .setOpCode(ARP.OP_REQUEST)
- .setTargetHardwareAddress(zeroMac)
- .setTargetProtocolAddress(ipAddress.getAddress());
+ // We don't know the device so broadcast the request out
+ datagrid.sendPacketOutNotification(
+ new BroadcastPacketOutNotification(eth.serialize(),
+ target, sw.getId(), pi.getInPort()));
+ }
+ else {
+ // Even if the device exists in our database, we do not reply to
+ // the request directly, but check whether the device is still valid
+ MACAddress macAddress = MACAddress.valueOf(targetDevice.getMACAddress());
- MACAddress routerMacAddress = configService.getRouterMacAddress();
- //TODO hack for now as it's unclear what the MAC address should be
- byte[] senderMacAddress = genericNonZeroMac;
- if (routerMacAddress != null) {
- senderMacAddress = routerMacAddress.toBytes();
- }
- arpRequest.setSenderHardwareAddress(senderMacAddress);
-
- byte[] senderIPAddress = zeroIpv4;
- Interface intf = configService.getOutgoingInterface(ipAddress);
- if (intf != null) {
- senderIPAddress = intf.getIpAddress().getAddress();
- }
-
- arpRequest.setSenderProtocolAddress(senderIPAddress);
-
- Ethernet eth = new Ethernet();
- eth.setSourceMACAddress(senderMacAddress)
- .setDestinationMACAddress(broadcastMac)
- .setEtherType(Ethernet.TYPE_ARP)
- .setPayload(arpRequest);
-
- if (vlan != NO_VLAN) {
- eth.setVlanID(vlan)
- .setPriorityCode((byte)0);
- }
-
- //sendArpRequestToSwitches(ipAddress, eth.serialize());
- datagrid.sendPacketOutNotification(new SinglePacketOutNotification(eth.serialize(),
- ipAddress, intf.getDpid(),intf.getPort()));
- }
-
- private void sendArpRequestToSwitches(InetAddress dstAddress, byte[] arpRequest) {
- sendArpRequestToSwitches(dstAddress, arpRequest,
- 0, OFPort.OFPP_NONE.getValue());
- }
-
- private void sendArpRequestToSwitches(InetAddress dstAddress, byte[] arpRequest,
- long inSwitch, short inPort) {
+ if (log.isTraceEnabled()) {
+ log.trace("The target Device Record in DB is: {} => {} from ARP request host at {}/{}",
+ new Object [] {
+ inetAddressToString(arp.getTargetProtocolAddress()),
+ macAddress,
+ HexString.toHexString(sw.getId()), pi.getInPort()});
+ }
- if (configService.hasLayer3Configuration()) {
- Interface intf = configService.getOutgoingInterface(dstAddress);
- if (intf != null) {
- sendArpRequestOutPort(arpRequest, intf.getDpid(), intf.getPort());
- }
- else {
- //TODO here it should be broadcast out all non-interface edge ports.
- //I think we can assume that if it's not a request for an external
- //network, it's an ARP for a host in our own network. So we want to
- //send it out all edge ports that don't have an interface configured
- //to ensure it reaches all hosts in our network.
- log.debug("No interface found to send ARP request for {}",
- dstAddress.getHostAddress());
- }
- }
- else {
- //broadcastArpRequestOutEdge(arpRequest, inSwitch, inPort);
- broadcastArpRequestOutMyEdge(arpRequest, inSwitch, inPort);
- }
- }
-
- private void sendArpReplyNotification(Ethernet eth, OFPacketIn pi) {
- ARP arp = (ARP) eth.getPayload();
-
- if (log.isTraceEnabled()) {
- log.trace("Sending ARP reply for {} to other ONOS instances",
- inetAddressToString(arp.getSenderProtocolAddress()));
- }
-
- InetAddress targetAddress;
- MACAddress mac = new MACAddress(arp.getSenderHardwareAddress());
-
- try {
- targetAddress = InetAddress.getByAddress(arp.getSenderProtocolAddress());
- } catch (UnknownHostException e) {
- log.error("Unknown host", e);
- return;
- }
+ // sendArpReply(arp, sw.getId(), pi.getInPort(), macAddress);
- datagrid.sendArpReplyNotification(new ArpReplyNotification(targetAddress, mac));
- }
-
- private void broadcastArpRequestOutMyEdge(byte[] arpRequest,
- long inSwitch, short inPort) {
- List<SwitchPort> switchPorts = new ArrayList<SwitchPort>();
-
- for (IOFSwitch sw : floodlightProvider.getSwitches().values()) {
-
- OFPacketOut po = new OFPacketOut();
- po.setInPort(OFPort.OFPP_NONE)
- .setBufferId(-1)
- .setPacketData(arpRequest);
-
- List<OFAction> actions = new ArrayList<OFAction>();
+ Iterable<IPortObject> outPorts = targetDevice.getAttachedPorts();
- // TODO: Fix the code below after topoSwitchService was removed
- /*
- Iterable<IPortObject> ports
- = topoSwitchService.getPortsOnSwitch(sw.getStringId());
- if (ports == null) {
- continue;
- }
-
- for (IPortObject portObject : ports) {
- if (!portObject.getLinkedPorts().iterator().hasNext()) {
- short portNumber = portObject.getNumber();
-
- if (sw.getId() == inSwitch && portNumber == inPort) {
- // This is the port that the ARP message came in,
- // so don't broadcast out this port
- continue;
- }
-
- switchPorts.add(new SwitchPort(new Dpid(sw.getId()),
- new Port(portNumber)));
- actions.add(new OFActionOutput(portNumber));
- }
- }
- */
-
- po.setActions(actions);
- short actionsLength = (short)
- (actions.size() * OFActionOutput.MINIMUM_LENGTH);
- po.setActionsLength(actionsLength);
- po.setLengthU(OFPacketOut.MINIMUM_LENGTH + actionsLength
- + arpRequest.length);
-
- flowPusher.add(sw, po);
- }
-
- if (log.isTraceEnabled()) {
- log.trace("Broadcast ARP request to: {}", switchPorts);
- }
- }
-
- private void sendArpRequestOutPort(byte[] arpRequest, long dpid, short port) {
- if (log.isTraceEnabled()) {
- log.trace("Sending ARP request out {}/{}",
- HexString.toHexString(dpid), port);
- }
-
- OFPacketOut po = new OFPacketOut();
- po.setInPort(OFPort.OFPP_NONE)
- .setBufferId(-1)
- .setPacketData(arpRequest);
-
- List<OFAction> actions = new ArrayList<OFAction>();
- actions.add(new OFActionOutput(port));
- po.setActions(actions);
- short actionsLength = (short) (actions.size() * OFActionOutput.MINIMUM_LENGTH);
- po.setActionsLength(actionsLength);
- po.setLengthU(OFPacketOut.MINIMUM_LENGTH + actionsLength
- + arpRequest.length);
-
- IOFSwitch sw = floodlightProvider.getSwitches().get(dpid);
-
- if (sw == null) {
- log.warn("Switch not found when sending ARP request");
- return;
- }
-
- flowPusher.add(sw, po);
- }
-
- private void sendArpReply(ARP arpRequest, long dpid, short port, MACAddress targetMac) {
- if (log.isTraceEnabled()) {
- log.trace("Sending reply {} => {} to {}", new Object[] {
- inetAddressToString(arpRequest.getTargetProtocolAddress()),
- targetMac,
- inetAddressToString(arpRequest.getSenderProtocolAddress())});
- }
-
- ARP arpReply = new ARP();
- arpReply.setHardwareType(ARP.HW_TYPE_ETHERNET)
- .setProtocolType(ARP.PROTO_TYPE_IP)
- .setHardwareAddressLength((byte)Ethernet.DATALAYER_ADDRESS_LENGTH)
- .setProtocolAddressLength((byte)IPv4.ADDRESS_LENGTH)
- .setOpCode(ARP.OP_REPLY)
- .setSenderHardwareAddress(targetMac.toBytes())
- .setSenderProtocolAddress(arpRequest.getTargetProtocolAddress())
- .setTargetHardwareAddress(arpRequest.getSenderHardwareAddress())
- .setTargetProtocolAddress(arpRequest.getSenderProtocolAddress());
-
+ if (!outPorts.iterator().hasNext()){
+ if (log.isTraceEnabled()) {
+ log.trace("Device {} exists but is not connected to any ports" +
+ " - broadcasting", macAddress);
+ }
- Ethernet eth = new Ethernet();
- eth.setDestinationMACAddress(arpRequest.getSenderHardwareAddress())
- .setSourceMACAddress(targetMac.toBytes())
- .setEtherType(Ethernet.TYPE_ARP)
- .setPayload(arpReply);
-
- if (vlan != NO_VLAN) {
- eth.setVlanID(vlan)
- .setPriorityCode((byte)0);
- }
-
- List<OFAction> actions = new ArrayList<OFAction>();
- actions.add(new OFActionOutput(port));
-
- OFPacketOut po = new OFPacketOut();
- po.setInPort(OFPort.OFPP_NONE)
- .setBufferId(-1)
- .setPacketData(eth.serialize())
- .setActions(actions)
- .setActionsLength((short)OFActionOutput.MINIMUM_LENGTH)
- .setLengthU(OFPacketOut.MINIMUM_LENGTH + OFActionOutput.MINIMUM_LENGTH
- + po.getPacketData().length);
-
- List<OFMessage> msgList = new ArrayList<OFMessage>();
- msgList.add(po);
+ datagrid.sendPacketOutNotification(
+ new BroadcastPacketOutNotification(eth.serialize(),
+ target, sw.getId(), pi.getInPort()));
+ }
+ else {
+ for (IPortObject portObject : outPorts) {
+ //long outSwitch = 0;
+ //short outPort = 0;
- IOFSwitch sw = floodlightProvider.getSwitches().get(dpid);
-
- if (sw == null) {
- log.warn("Switch {} not found when sending ARP reply",
- HexString.toHexString(dpid));
- return;
- }
-
- flowPusher.add(sw, po);
- }
-
- private String inetAddressToString(byte[] bytes) {
- try {
- return InetAddress.getByAddress(bytes).getHostAddress();
- } catch (UnknownHostException e) {
- log.debug("Invalid IP address", e);
- return "";
- }
- }
-
- /*
- * IProxyArpService methods
- */
+ // if (!portObject.getLinkedPorts().iterator().hasNext()) {
+ // outPort = portObject.getNumber();
+ // }
+ if (portObject.getLinkedPorts().iterator().hasNext()) {
+ continue;
+ }
- @Override
- public MACAddress getMacAddress(InetAddress ipAddress) {
- //return arpCache.lookup(ipAddress);
- return null;
- }
+ short outPort = portObject.getNumber();
+ ISwitchObject outSwitchObject = portObject.getSwitch();
+ long outSwitch = HexString.toLong(outSwitchObject.getDPID());
- @Override
- public void sendArpRequest(InetAddress ipAddress, IArpRequester requester,
- boolean retry) {
- arpRequests.put(ipAddress, new ArpRequest(requester, retry));
-
- //Sanity check to make sure we don't send a request for our own address
- if (!configService.isInterfaceAddress(ipAddress)) {
- sendArpRequestForAddress(ipAddress);
- }
- }
-
- @Override
- public List<String> getMappings() {
- //return arpCache.getMappings();
- return new ArrayList<String>();
- }
+ if (log.isTraceEnabled()) {
+ log.trace("Probing device {} on port {}/{}",
+ new Object[] {macAddress,
+ HexString.toHexString(outSwitch), outPort});
+ }
- /*
- @Override
- public void arpRequestNotification(ArpMessage arpMessage) {
- log.debug("Received ARP notification from other instances");
+ datagrid.sendPacketOutNotification(
+ new SinglePacketOutNotification(eth.serialize(),
+ target, outSwitch, outPort));
+ }
+ }
+ }
+ */
+ }
- switch (arpMessage.getType()){
- case REQUEST:
- if(arpMessage.getOutSwitch() == -1 || arpMessage.getOutPort() == -1){
- broadcastArpRequestOutMyEdge(arpMessage.getPacket(),
- arpMessage.getInSwitch(), arpMessage.getInPort());
- }else{
- sendArpRequestOutPort(arpMessage.getPacket(),arpMessage.getOutSwitch(),arpMessage.getOutPort());
- log.debug("OutSwitch in ARP request message is: {}; OutPort in ARP request message is: {}",arpMessage.getOutSwitch(),arpMessage.getOutPort());
- }
- break;
- case REPLY:
- log.debug("Received ARP reply notification for {}",
- arpMessage.getAddress());
- sendArpReplyToWaitingRequesters(arpMessage.getAddress(),arpMessage.getMAC());
- break;
- }
- }
- */
-
- private void sendArpReplyToWaitingRequesters(InetAddress address, MACAddress mac) {
- log.debug("Sending ARP reply for {} to requesters",
- address.getHostAddress());
-
- //See if anyone's waiting for this ARP reply
- Set<ArpRequest> requests = arpRequests.get(address);
-
- //Synchronize on the Multimap while using an iterator for one of the sets
- List<ArpRequest> requestsToSend = new ArrayList<ArpRequest>(requests.size());
- synchronized (arpRequests) {
- Iterator<ArpRequest> it = requests.iterator();
- while (it.hasNext()) {
- ArpRequest request = it.next();
- it.remove();
- requestsToSend.add(request);
- }
- }
-
- /*IDeviceObject deviceObject = deviceStorage.getDeviceByIP(
- InetAddresses.coerceToInteger(address));
-
- MACAddress mac = MACAddress.valueOf(deviceObject.getMACAddress());
-
- log.debug("Found {} at {} in network map",
- address.getHostAddress(), mac);*/
-
- //Don't hold an ARP lock while dispatching requests
- for (ArpRequest request : requestsToSend) {
- request.dispatchReply(address, mac);
- }
- }
+ // Not used because device manager currently updates the database
+ // for ARP replies. May be useful in the future.
+ private void handleArpReply(IOFSwitch sw, OFPacketIn pi, ARP arp) {
+ if (log.isTraceEnabled()) {
+ log.trace("ARP reply recieved: {} => {}, on {}/{}", new Object[] {
+ inetAddressToString(arp.getSenderProtocolAddress()),
+ HexString.toHexString(arp.getSenderHardwareAddress()),
+ HexString.toHexString(sw.getId()), pi.getInPort()});
+ }
- @Override
- public void arpReplyEvent(ArpReplyNotification arpReply) {
- log.debug("Received ARP reply notification for {}",
- arpReply.getTargetAddress());
- sendArpReplyToWaitingRequesters(arpReply.getTargetAddress(),
- arpReply.getTargetMacAddress());
- }
+ InetAddress senderIpAddress;
+ try {
+ senderIpAddress = InetAddress.getByAddress(arp
+ .getSenderProtocolAddress());
+ } catch (UnknownHostException e) {
+ log.debug("Invalid address in ARP reply", e);
+ return;
+ }
- @Override
- public void packetOutNotification(
- PacketOutNotification packetOutNotification) {
-
- if (packetOutNotification instanceof SinglePacketOutNotification) {
- SinglePacketOutNotification notification =
- (SinglePacketOutNotification) packetOutNotification;
- sendArpRequestOutPort(notification.packet, notification.getOutSwitch(),
- notification.getOutPort());
-
- // set timestamp
- InetAddress addr = notification.getTargetAddress();
- if (addr != null) {
- for (ArpRequest request : arpRequests.get(addr)) {
- request.setRequestTime();
- }
- }
- }
- else if (packetOutNotification instanceof BroadcastPacketOutNotification) {
- BroadcastPacketOutNotification notification =
- (BroadcastPacketOutNotification) packetOutNotification;
- broadcastArpRequestOutMyEdge(notification.packet,
- notification.getInSwitch(), notification.getInPort());
-
- // set timestamp
- InetAddress addr = notification.getTargetAddress();
- if (addr != null) {
- for (ArpRequest request : arpRequests.get(addr)) {
- request.setRequestTime();
- }
- }
- }
- else {
- log.warn("Unknown packet out notification received");
- }
- }
+ MACAddress senderMacAddress = MACAddress.valueOf(arp
+ .getSenderHardwareAddress());
+
+ // 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());
+ synchronized (arpRequests) {
+ Iterator<ArpRequest> it = requests.iterator();
+ while (it.hasNext()) {
+ ArpRequest request = it.next();
+ it.remove();
+ requestsToSend.add(request);
+ }
+ }
+
+ // Don't hold an ARP lock while dispatching requests
+ for (ArpRequest request : requestsToSend) {
+ request.dispatchReply(senderIpAddress, senderMacAddress);
+ }
+ }
+
+ private void sendArpRequestForAddress(InetAddress ipAddress) {
+ // TODO what should the sender IP address and MAC address be if no
+ // IP addresses are configured? Will there ever be a need to send
+ // ARP requests from the controller in that case?
+ // All-zero MAC address doesn't seem to work - hosts don't respond to it
+
+ byte[] zeroIpv4 = {0x0, 0x0, 0x0, 0x0};
+ byte[] zeroMac = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
+ byte[] genericNonZeroMac = {0x0, 0x0, 0x0, 0x0, 0x0, 0x01};
+ byte[] broadcastMac = {(byte) 0xff, (byte) 0xff, (byte) 0xff,
+ (byte) 0xff, (byte) 0xff, (byte) 0xff};
+
+ ARP arpRequest = new ARP();
+
+ arpRequest
+ .setHardwareType(ARP.HW_TYPE_ETHERNET)
+ .setProtocolType(ARP.PROTO_TYPE_IP)
+ .setHardwareAddressLength(
+ (byte) Ethernet.DATALAYER_ADDRESS_LENGTH)
+ .setProtocolAddressLength((byte) IPv4.ADDRESS_LENGTH)
+ .setOpCode(ARP.OP_REQUEST).setTargetHardwareAddress(zeroMac)
+ .setTargetProtocolAddress(ipAddress.getAddress());
+
+ MACAddress routerMacAddress = configService.getRouterMacAddress();
+ // TODO hack for now as it's unclear what the MAC address should be
+ byte[] senderMacAddress = genericNonZeroMac;
+ if (routerMacAddress != null) {
+ senderMacAddress = routerMacAddress.toBytes();
+ }
+ arpRequest.setSenderHardwareAddress(senderMacAddress);
+
+ byte[] senderIPAddress = zeroIpv4;
+ Interface intf = configService.getOutgoingInterface(ipAddress);
+ if (intf != null) {
+ senderIPAddress = intf.getIpAddress().getAddress();
+ }
+
+ arpRequest.setSenderProtocolAddress(senderIPAddress);
+
+ Ethernet eth = new Ethernet();
+ eth.setSourceMACAddress(senderMacAddress)
+ .setDestinationMACAddress(broadcastMac)
+ .setEtherType(Ethernet.TYPE_ARP).setPayload(arpRequest);
+
+ if (vlan != NO_VLAN) {
+ eth.setVlanID(vlan).setPriorityCode((byte) 0);
+ }
+
+ // sendArpRequestToSwitches(ipAddress, eth.serialize());
+ datagrid.sendPacketOutNotification(new SinglePacketOutNotification(eth
+ .serialize(), ipAddress, intf.getDpid(), intf.getPort()));
+ }
+
+ private void sendArpRequestToSwitches(InetAddress dstAddress,
+ byte[] arpRequest) {
+ sendArpRequestToSwitches(dstAddress, arpRequest, 0,
+ OFPort.OFPP_NONE.getValue());
+ }
+
+ private void sendArpRequestToSwitches(InetAddress dstAddress,
+ byte[] arpRequest, long inSwitch, short inPort) {
+
+ if (configService.hasLayer3Configuration()) {
+ Interface intf = configService.getOutgoingInterface(dstAddress);
+ if (intf == null) {
+ // TODO here it should be broadcast out all non-interface edge
+ // ports.
+ // I think we can assume that if it's not a request for an
+ // external
+ // network, it's an ARP for a host in our own network. So we
+ // want to
+ // send it out all edge ports that don't have an interface
+ // configured
+ // to ensure it reaches all hosts in our network.
+ log.debug("No interface found to send ARP request for {}",
+ dstAddress.getHostAddress());
+ } else {
+ sendArpRequestOutPort(arpRequest, intf.getDpid(),
+ intf.getPort());
+ }
+ } else {
+ // broadcastArpRequestOutEdge(arpRequest, inSwitch, inPort);
+ broadcastArpRequestOutMyEdge(arpRequest, inSwitch, inPort);
+ }
+ }
+
+ private void sendArpReplyNotification(Ethernet eth, OFPacketIn pi) {
+ ARP arp = (ARP) eth.getPayload();
+
+ if (log.isTraceEnabled()) {
+ log.trace("Sending ARP reply for {} to other ONOS instances",
+ inetAddressToString(arp.getSenderProtocolAddress()));
+ }
+
+ InetAddress targetAddress;
+
+ try {
+ targetAddress = InetAddress.getByAddress(arp
+ .getSenderProtocolAddress());
+ } catch (UnknownHostException e) {
+ log.error("Unknown host", e);
+ return;
+ }
+
+ MACAddress mac = new MACAddress(arp.getSenderHardwareAddress());
+
+ datagrid.sendArpReplyNotification(new ArpReplyNotification(
+ targetAddress, mac));
+ }
+
+ private void broadcastArpRequestOutMyEdge(byte[] arpRequest, long inSwitch,
+ short inPort) {
+ List<SwitchPort> switchPorts = new ArrayList<SwitchPort>();
+
+ for (IOFSwitch sw : floodlightProvider.getSwitches().values()) {
+
+ OFPacketOut po = new OFPacketOut();
+ po.setInPort(OFPort.OFPP_NONE).setBufferId(-1)
+ .setPacketData(arpRequest);
+
+ List<OFAction> actions = new ArrayList<OFAction>();
+
+ // TODO: Fix the code below after topoSwitchService was removed
+ /*
+ Iterable<IPortObject> ports
+ = topoSwitchService.getPortsOnSwitch(sw.getStringId());
+ if (ports == null) {
+ continue;
+ }
+
+ for (IPortObject portObject : ports) {
+ if (!portObject.getLinkedPorts().iterator().hasNext()) {
+ short portNumber = portObject.getNumber();
+
+ if (sw.getId() == inSwitch && portNumber == inPort) {
+ // This is the port that the ARP message came in,
+ // so don't broadcast out this port
+ continue;
+ }
+
+ switchPorts.add(new SwitchPort(new Dpid(sw.getId()),
+ new Port(portNumber)));
+ actions.add(new OFActionOutput(portNumber));
+ }
+ }
+ */
+
+ po.setActions(actions);
+ short actionsLength = (short) (actions.size() * OFActionOutput.MINIMUM_LENGTH);
+ po.setActionsLength(actionsLength);
+ po.setLengthU(OFPacketOut.MINIMUM_LENGTH + actionsLength
+ + arpRequest.length);
+
+ flowPusher.add(sw, po);
+ }
+
+ if (log.isTraceEnabled()) {
+ log.trace("Broadcast ARP request to: {}", switchPorts);
+ }
+ }
+
+ private void sendArpRequestOutPort(byte[] arpRequest, long dpid, short port) {
+ if (log.isTraceEnabled()) {
+ log.trace("Sending ARP request out {}/{}",
+ HexString.toHexString(dpid), port);
+ }
+
+ OFPacketOut po = new OFPacketOut();
+ po.setInPort(OFPort.OFPP_NONE).setBufferId(-1)
+ .setPacketData(arpRequest);
+
+ List<OFAction> actions = new ArrayList<OFAction>();
+ actions.add(new OFActionOutput(port));
+ po.setActions(actions);
+ short actionsLength = (short) (actions.size() * OFActionOutput.MINIMUM_LENGTH);
+ po.setActionsLength(actionsLength);
+ po.setLengthU(OFPacketOut.MINIMUM_LENGTH + actionsLength
+ + arpRequest.length);
+
+ IOFSwitch sw = floodlightProvider.getSwitches().get(dpid);
+
+ if (sw == null) {
+ log.warn("Switch not found when sending ARP request");
+ return;
+ }
+
+ flowPusher.add(sw, po);
+ }
+
+ private void sendArpReply(ARP arpRequest, long dpid, short port,
+ MACAddress targetMac) {
+ if (log.isTraceEnabled()) {
+ log.trace(
+ "Sending reply {} => {} to {}",
+ new Object[] {
+ inetAddressToString(arpRequest
+ .getTargetProtocolAddress()),
+ targetMac,
+ inetAddressToString(arpRequest
+ .getSenderProtocolAddress())});
+ }
+
+ ARP arpReply = new ARP();
+ arpReply.setHardwareType(ARP.HW_TYPE_ETHERNET)
+ .setProtocolType(ARP.PROTO_TYPE_IP)
+ .setHardwareAddressLength(
+ (byte) Ethernet.DATALAYER_ADDRESS_LENGTH)
+ .setProtocolAddressLength((byte) IPv4.ADDRESS_LENGTH)
+ .setOpCode(ARP.OP_REPLY)
+ .setSenderHardwareAddress(targetMac.toBytes())
+ .setSenderProtocolAddress(arpRequest.getTargetProtocolAddress())
+ .setTargetHardwareAddress(arpRequest.getSenderHardwareAddress())
+ .setTargetProtocolAddress(arpRequest.getSenderProtocolAddress());
+
+ Ethernet eth = new Ethernet();
+ eth.setDestinationMACAddress(arpRequest.getSenderHardwareAddress())
+ .setSourceMACAddress(targetMac.toBytes())
+ .setEtherType(Ethernet.TYPE_ARP).setPayload(arpReply);
+
+ if (vlan != NO_VLAN) {
+ eth.setVlanID(vlan).setPriorityCode((byte) 0);
+ }
+
+ List<OFAction> actions = new ArrayList<OFAction>();
+ actions.add(new OFActionOutput(port));
+
+ OFPacketOut po = new OFPacketOut();
+ po.setInPort(OFPort.OFPP_NONE)
+ .setBufferId(-1)
+ .setPacketData(eth.serialize())
+ .setActions(actions)
+ .setActionsLength((short) OFActionOutput.MINIMUM_LENGTH)
+ .setLengthU(
+ OFPacketOut.MINIMUM_LENGTH
+ + OFActionOutput.MINIMUM_LENGTH
+ + po.getPacketData().length);
+
+ List<OFMessage> msgList = new ArrayList<OFMessage>();
+ msgList.add(po);
+
+ IOFSwitch sw = floodlightProvider.getSwitches().get(dpid);
+
+ if (sw == null) {
+ log.warn("Switch {} not found when sending ARP reply",
+ HexString.toHexString(dpid));
+ return;
+ }
+
+ flowPusher.add(sw, po);
+ }
+
+ 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 MACAddress getMacAddress(InetAddress ipAddress) {
+ // return arpCache.lookup(ipAddress);
+ return null;
+ }
+
+ @Override
+ public void sendArpRequest(InetAddress ipAddress, IArpRequester requester,
+ boolean retry) {
+ arpRequests.put(ipAddress, new ArpRequest(requester, retry));
+
+ // Sanity check to make sure we don't send a request for our own address
+ if (!configService.isInterfaceAddress(ipAddress)) {
+ sendArpRequestForAddress(ipAddress);
+ }
+ }
+
+ @Override
+ public List<String> getMappings() {
+ return new ArrayList<String>();
+ }
+
+ /*
+ @Override
+ public void arpRequestNotification(ArpMessage arpMessage) {
+ log.debug("Received ARP notification from other instances");
+
+ switch (arpMessage.getType()){
+ case REQUEST:
+ if(arpMessage.getOutSwitch() == -1 || arpMessage.getOutPort() == -1){
+ broadcastArpRequestOutMyEdge(arpMessage.getPacket(),
+ arpMessage.getInSwitch(), arpMessage.getInPort());
+ }else{
+ sendArpRequestOutPort(arpMessage.getPacket(),arpMessage.getOutSwitch(),arpMessage.getOutPort());
+ log.debug("OutSwitch in ARP request message is: {}; " +
+ "OutPort in ARP request message is: {}",arpMessage.getOutSwitch(),arpMessage.getOutPort());
+ }
+ break;
+ case REPLY:
+ log.debug("Received ARP reply notification for {}",
+ arpMessage.getAddress());
+ sendArpReplyToWaitingRequesters(arpMessage.getAddress(),arpMessage.getMAC());
+ break;
+ }
+ }
+ */
+
+ private void sendArpReplyToWaitingRequesters(InetAddress address,
+ MACAddress mac) {
+ log.debug("Sending ARP reply for {} to requesters",
+ address.getHostAddress());
+
+ // See if anyone's waiting for this ARP reply
+ Set<ArpRequest> requests = arpRequests.get(address);
+
+ // Synchronize on the Multimap while using an iterator for one of the
+ // sets
+ List<ArpRequest> requestsToSend = new ArrayList<ArpRequest>(
+ requests.size());
+ synchronized (arpRequests) {
+ Iterator<ArpRequest> it = requests.iterator();
+ while (it.hasNext()) {
+ ArpRequest request = it.next();
+ it.remove();
+ requestsToSend.add(request);
+ }
+ }
+
+ /*IDeviceObject deviceObject = deviceStorage.getDeviceByIP(
+ InetAddresses.coerceToInteger(address));
+
+ MACAddress mac = MACAddress.valueOf(deviceObject.getMACAddress());
+
+ log.debug("Found {} at {} in network map",
+ address.getHostAddress(), mac);*/
+
+ // Don't hold an ARP lock while dispatching requests
+ for (ArpRequest request : requestsToSend) {
+ request.dispatchReply(address, mac);
+ }
+ }
+
+ @Override
+ public void arpReplyEvent(ArpReplyNotification arpReply) {
+ log.debug("Received ARP reply notification for {}",
+ arpReply.getTargetAddress());
+ sendArpReplyToWaitingRequesters(arpReply.getTargetAddress(),
+ arpReply.getTargetMacAddress());
+ }
+
+ @Override
+ public void packetOutNotification(
+ PacketOutNotification packetOutNotification) {
+
+ if (packetOutNotification instanceof SinglePacketOutNotification) {
+ SinglePacketOutNotification notification = (SinglePacketOutNotification) packetOutNotification;
+ sendArpRequestOutPort(notification.packet,
+ notification.getOutSwitch(), notification.getOutPort());
+
+ // set timestamp
+ InetAddress addr = notification.getTargetAddress();
+ if (addr != null) {
+ for (ArpRequest request : arpRequests.get(addr)) {
+ request.setRequestTime();
+ }
+ }
+ } else if (packetOutNotification instanceof BroadcastPacketOutNotification) {
+ BroadcastPacketOutNotification notification = (BroadcastPacketOutNotification) packetOutNotification;
+ broadcastArpRequestOutMyEdge(notification.packet,
+ notification.getInSwitch(), notification.getInPort());
+
+ // set timestamp
+ InetAddress addr = notification.getTargetAddress();
+ if (addr != null) {
+ for (ArpRequest request : arpRequests.get(addr)) {
+ request.setRequestTime();
+ }
+ }
+ } else {
+ log.warn("Unknown packet out notification received");
+ }
+ }
}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/proxyarp/SinglePacketOutNotification.java b/src/main/java/net/onrc/onos/ofcontroller/proxyarp/SinglePacketOutNotification.java
index d654f67..ab9a9b5 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/proxyarp/SinglePacketOutNotification.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/proxyarp/SinglePacketOutNotification.java
@@ -5,34 +5,53 @@
// TODO This class is too generic to be handled by ProxyArpService.
/**
* Notification to another ONOS instance to send a packet out a single port.
- *
*/
public class SinglePacketOutNotification extends PacketOutNotification {
- private static final long serialVersionUID = 1L;
-
- private final InetAddress address;
- private final long outSwitch;
- private final short outPort;
-
- public SinglePacketOutNotification(byte[] packet, InetAddress address,
- long outSwitch, short outPort) {
- super(packet);
-
- this.address = address;
- this.outSwitch = outSwitch;
- this.outPort = outPort;
- }
+ private static final long serialVersionUID = 1L;
- public long getOutSwitch() {
- return outSwitch;
- }
+ private final InetAddress address;
+ private final long outSwitch;
+ private final short outPort;
- public short getOutPort() {
- return outPort;
- }
+ /**
+ * Class constructor.
+ * @param packet the packet data to send in the packet-out
+ * @param address target IP address if the packet is an ARP packet
+ * @param outSwitch the dpid of the switch to send the packet on
+ * @param outPort the port number of the port to send the packet out
+ */
+ public SinglePacketOutNotification(byte[] packet, InetAddress address,
+ long outSwitch, short outPort) {
+ super(packet);
- public InetAddress getTargetAddress() {
- return address;
- }
+ this.address = address;
+ this.outSwitch = outSwitch;
+ this.outPort = outPort;
+ }
+
+ /**
+ * Get the dpid of the switch the packet will be sent out.
+ * @return the switch's dpid
+ */
+ public long getOutSwitch() {
+ return outSwitch;
+ }
+
+ /**
+ * Get the port number of the port the packet will be sent out.
+ * @return the port number
+ */
+ public short getOutPort() {
+ return outPort;
+ }
+
+ /**
+ * Get the target IP address if the packet is an ARP packet.
+ * @return the target IP address for ARP packets, or null if the packet is
+ * not an ARP packet
+ */
+ public InetAddress getTargetAddress() {
+ return address;
+ }
}