fixed ARP returns wrong MAC && ARP reply uses hazelcast && handle ARP request in two steps
diff --git a/src/main/java/net/floodlightcontroller/util/MACAddress.java b/src/main/java/net/floodlightcontroller/util/MACAddress.java
index b77d4cc..b143bda 100644
--- a/src/main/java/net/floodlightcontroller/util/MACAddress.java
+++ b/src/main/java/net/floodlightcontroller/util/MACAddress.java
@@ -1,5 +1,6 @@
package net.floodlightcontroller.util;
+import java.io.Serializable;
import java.util.Arrays;
import net.onrc.onos.ofcontroller.util.serializers.MACAddressDeserializer;
@@ -15,7 +16,8 @@
*/
@JsonDeserialize(using=MACAddressDeserializer.class)
@JsonSerialize(using=MACAddressSerializer.class)
-public class MACAddress {
+public class MACAddress implements Serializable{
+ private static final long serialVersionUID = 10000L;
public static final int MAC_ADDRESS_LENGTH = 6;
private byte[] address = new byte[MAC_ADDRESS_LENGTH];
diff --git a/src/main/java/net/onrc/onos/datagrid/IDatagridService.java b/src/main/java/net/onrc/onos/datagrid/IDatagridService.java
index 034fe25..0f03d77 100644
--- a/src/main/java/net/onrc/onos/datagrid/IDatagridService.java
+++ b/src/main/java/net/onrc/onos/datagrid/IDatagridService.java
@@ -170,5 +170,5 @@
* Send an ARP request to other ONOS instances
* @param arpRequest The request packet to send
*/
- public void sendArpRequest(ArpMessage arpMessage);
+ public void sendArpRequest(ArpMessage arpMessage);
}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/core/IDeviceStorage.java b/src/main/java/net/onrc/onos/ofcontroller/core/IDeviceStorage.java
index be495b9..13b9182 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/core/IDeviceStorage.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/core/IDeviceStorage.java
@@ -8,6 +8,7 @@
public IDeviceObject addDevice(IDevice device);
public IDeviceObject updateDevice(IDevice device);
public void removeDevice(IDevice device);
+ public void removeDevice(IDeviceObject deviceObject);
public IDeviceObject getDeviceByMac(String mac);
public IDeviceObject getDeviceByIP(int ipv4Address);
public void changeDeviceAttachments(IDevice device);
diff --git a/src/main/java/net/onrc/onos/ofcontroller/core/INetMapTopologyObjects.java b/src/main/java/net/onrc/onos/ofcontroller/core/INetMapTopologyObjects.java
index 49ffd4e..da19ba1 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/core/INetMapTopologyObjects.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/core/INetMapTopologyObjects.java
@@ -1,6 +1,7 @@
package net.onrc.onos.ofcontroller.core;
import net.onrc.onos.ofcontroller.flowmanager.web.DatapathSummarySerializer;
+import net.onrc.onos.ofcontroller.util.SwitchPort;
import org.codehaus.jackson.annotate.JsonIgnore;
import org.codehaus.jackson.annotate.JsonProperty;
diff --git a/src/main/java/net/onrc/onos/ofcontroller/proxyarp/ArpMessage.java b/src/main/java/net/onrc/onos/ofcontroller/proxyarp/ArpMessage.java
index 53891ef..dd159fe 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/proxyarp/ArpMessage.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/proxyarp/ArpMessage.java
@@ -5,6 +5,7 @@
import java.util.ArrayList;
import java.util.List;
+import net.floodlightcontroller.util.MACAddress;
import net.onrc.onos.ofcontroller.util.SwitchPort;
public class ArpMessage implements Serializable {
@@ -18,6 +19,13 @@
private final InetAddress forAddress;
private final byte[] packetData;
+ //ARP reply message needs MAC info
+ private MACAddress mac;
+ //only send the ARP request message to the device attachment needs the attachement swith and port.
+ private long outSwitch=-1;
+ private short outPort=-1;
+
+
private final List<SwitchPort> switchPorts = new ArrayList<SwitchPort>();
public enum Type {
@@ -37,7 +45,24 @@
this.forAddress = address;
this.packetData = null;
}
+ // the ARP reply message with MAC
+ private ArpMessage(Type type, InetAddress address, MACAddress mac) {
+ this.type = type;
+ this.forAddress = address;
+ this.packetData = null;
+ this.mac=mac;
+ }
+ // construct ARP request message with attachment switch and port
+ private ArpMessage(Type type, InetAddress address, byte[] arpRequest,
+ long outSwitch, short outPort) {
+ this.type = type;
+ this.forAddress = address;
+ this.packetData = arpRequest;
+ this.setOutSwitch(outSwitch);
+ this.setOutPort(outPort);
+ }
+
public static ArpMessage newRequest(InetAddress forAddress, byte[] arpRequest) {
return new ArpMessage(Type.REQUEST, forAddress, arpRequest);
}
@@ -45,6 +70,16 @@
public static ArpMessage newReply(InetAddress forAddress) {
return new ArpMessage(Type.REPLY, forAddress);
}
+ //ARP reply message with MAC
+ public static ArpMessage newReply(InetAddress forAddress, MACAddress mac) {
+ return new ArpMessage(Type.REPLY, forAddress, mac);
+
+ }
+ //ARP reqsuest message with attachment switch and port
+ public static ArpMessage newRequest(InetAddress forAddress, byte[] arpRequest, long outSwitch, short outPort ) {
+ return new ArpMessage(Type.REQUEST, forAddress, arpRequest, outSwitch, outPort);
+
+ }
public Type getType() {
return type;
@@ -57,4 +92,23 @@
public byte[] getPacket() {
return packetData;
}
+ public MACAddress getMAC() {
+ return mac;
+ }
+
+ public long getOutSwitch() {
+ return outSwitch;
+ }
+
+ public void setOutSwitch(long outSwitch) {
+ this.outSwitch = outSwitch;
+ }
+
+ public short getOutPort() {
+ return outPort;
+ }
+
+ public void setOutPort(short outPort) {
+ this.outPort = outPort;
+ }
}
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 0b46778..a0aaf2a 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/proxyarp/ProxyArpManager.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/proxyarp/ProxyArpManager.java
@@ -32,6 +32,7 @@
import net.onrc.onos.ofcontroller.core.IDeviceStorage;
import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IDeviceObject;
import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IPortObject;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.ISwitchObject;
import net.onrc.onos.ofcontroller.core.INetMapTopologyService.ITopoSwitchService;
import net.onrc.onos.ofcontroller.core.config.IConfigInfoService;
import net.onrc.onos.ofcontroller.core.internal.DeviceStorageImpl;
@@ -60,9 +61,9 @@
IArpEventHandler, IFloodlightModule {
private final static Logger log = LoggerFactory.getLogger(ProxyArpManager.class);
- private final long ARP_TIMER_PERIOD = 60000; //ms (== 1 min)
-
- private static final int ARP_REQUEST_TIMEOUT = 2000; //ms
+ private final long ARP_TIMER_PERIOD = 100; //ms
+
+ private static final int ARP_REQUEST_TIMEOUT = 500; //ms
private IFloodlightProviderService floodlightProvider;
private ITopologyService topology;
@@ -221,6 +222,15 @@
log.debug("Cleaning expired ARP request for {}",
entry.getKey().getHostAddress());
+ //if he ARP Request is expired and then delete the device
+ IDeviceObject targetDevice =
+ deviceStorage.getDeviceByIP(InetAddresses.coerceToInteger(entry.getKey()));
+
+ if(targetDevice!=null)
+ {deviceStorage.removeDevice(targetDevice);
+ log.debug("RemoveDevice: {} due to no have not recieve the ARP reply", targetDevice.toString());
+ }
+
it.remove();
if (request.shouldRetry()) {
@@ -277,6 +287,7 @@
if (eth.getEtherType() == Ethernet.TYPE_ARP){
ARP arp = (ARP) eth.getPayload();
if (arp.getOpCode() == ARP.OP_REQUEST) {
+ log.debug("receive ARP request");
//TODO check what the DeviceManager does about propagating
//or swallowing ARPs. We want to go after DeviceManager in the
//chain but we really need it to CONTINUE ARP packets so we can
@@ -284,7 +295,9 @@
handleArpRequest(sw, pi, arp, eth);
}
else if (arp.getOpCode() == ARP.OP_REPLY) {
- //handleArpReply(sw, pi, arp);
+ log.debug("receive ARP reply");
+ handleArpReply(sw, pi, arp);
+ sendToOtherNodesReply(eth, pi);
}
}
@@ -322,57 +335,68 @@
}
//MACAddress macAddress = arpCache.lookup(target);
-
+
IDeviceObject targetDevice =
deviceStorage.getDeviceByIP(InetAddresses.coerceToInteger(target));
-
log.debug("targetDevice: {}", targetDevice);
+ arpRequests.put(target, new ArpRequest(
+ new HostArpRequester(arp, sw.getId(), pi.getInPort()), false));
+
if (targetDevice != null) {
- // We have the device in our database, so send a reply
+ // Even the device in our database is not null, we do not reply to the request directly, but to check whether the device is still valid
MACAddress macAddress = MACAddress.valueOf(targetDevice.getMACAddress());
if (log.isTraceEnabled()) {
- log.trace("Sending reply: {} => {} to host at {}/{}", new Object [] {
- inetAddressToString(arp.getTargetProtocolAddress()),
- macAddress.toString(),
- HexString.toHexString(sw.getId()), pi.getInPort()});
+ log.trace("The target Device Record in DB is: {} => {} from ARP request host at {}/{}", new Object [] {
+ inetAddressToString(arp.getTargetProtocolAddress()),
+ macAddress.toString(),
+ HexString.toHexString(sw.getId()), pi.getInPort()});
}
- sendArpReply(arp, sw.getId(), pi.getInPort(), macAddress);
- }
- else {
- // We don't know the device so broadcast the request out
- // the edge of the network
+ // sendArpReply(arp, sw.getId(), pi.getInPort(), macAddress);
+ try {
+ log.trace("Checking the device info from DB is still valid or not");
+ Iterable<IPortObject> outPorts=targetDevice.getAttachedPorts();
- //Record where the request came from so we know where to send the reply
- arpRequests.put(target, new ArpRequest(
- new HostArpRequester(arp, sw.getId(), pi.getInPort()), false));
-
- sendToOtherNodes(eth, pi);
- }
-
- /*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(arp, sw.getId(), pi.getInPort()), false));
-
- //Flood the request out edge ports
- //sendArpRequestToSwitches(target, pi.getPacketData(), sw.getId(), pi.getInPort());
- }
- else {
- //We know the address, so send a reply
- if (log.isTraceEnabled()) {
- log.trace("Sending reply: {} => {} to host at {}/{}", new Object [] {
- inetAddressToString(arp.getTargetProtocolAddress()),
- macAddress.toString(),
- HexString.toHexString(sw.getId()), pi.getInPort()});
+ if(!outPorts.iterator().hasNext())
+ {
+ log.debug("outPort : null");
+ sendToOtherNodes(eth, pi);
+ }
+ else{
+
+ for (IPortObject portObject : outPorts) {
+ long outSwitch=0;
+ short outPort=0;
+
+
+ if (!portObject.getLinkedPorts().iterator().hasNext()) {
+ outPort=portObject.getNumber();
+ log.debug("outPort:{} ", outPort);
+ }
+
+ Iterable<ISwitchObject> outSwitches= targetDevice.getSwitch();
+
+ for (ISwitchObject outswitch : outSwitches) {
+
+ outSwitch= HexString.toLong(outswitch.getDPID());
+ log.debug("outSwitch.DPID:{}; outPort: {}", outswitch.getDPID(), outPort );
+ sendToOtherNodes( eth, pi, outSwitch, outPort);
+ }
+
+ }
+ }
+ }catch (Exception e) {
+ log.error("Get attach outSwitche and outPort exception", e);
}
+ } else {
+ log.debug("The Device info in DB is {} for IP {}", targetDevice, inetAddressToString(arp.getTargetProtocolAddress()));
- sendArpReply(arp, sw.getId(), pi.getInPort(), macAddress);
- }*/
+ // We don't know the device so broadcast the request out
+ sendToOtherNodes(eth, pi);
+ }
+
}
private void handleArpReply(IOFSwitch sw, OFPacketIn pi, ARP arp){
@@ -393,7 +417,7 @@
MACAddress senderMacAddress = MACAddress.valueOf(arp.getSenderHardwareAddress());
- arpCache.update(senderIpAddress, senderMacAddress);
+ //arpCache.update(senderIpAddress, senderMacAddress);
//See if anyone's waiting for this ARP reply
Set<ArpRequest> requests = arpRequests.get(senderIpAddress);
@@ -513,6 +537,51 @@
datagrid.sendArpRequest(ArpMessage.newRequest(targetAddress, eth.serialize()));
}
+ //hazelcast to other ONOS instances to send the ARP packet out on outPort of outSwitch
+ private void sendToOtherNodes(Ethernet eth, OFPacketIn pi, long outSwitch, short outPort) {
+ ARP arp = (ARP) eth.getPayload();
+
+ if (log.isTraceEnabled()) {
+ log.trace("Sending ARP request for {} to other ONOS instances with outSwitch {} ",
+ inetAddressToString(arp.getTargetProtocolAddress()), String.valueOf(outSwitch));
+
+ }
+
+ InetAddress targetAddress;
+ try {
+ targetAddress = InetAddress.getByAddress(arp.getTargetProtocolAddress());
+ } catch (UnknownHostException e) {
+ log.error("Unknown host", e);
+ return;
+ }
+
+ datagrid.sendArpRequest(ArpMessage.newRequest(targetAddress, eth.serialize(), outSwitch, outPort));
+ //datagrid.sendArpRequest(ArpMessage.newRequest(targetAddress, eth.serialize()));
+
+
+ }
+ private void sendToOtherNodesReply(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;
+ }
+
+ datagrid.sendArpRequest(ArpMessage.newReply(targetAddress,mac));
+ //datagrid.sendArpReply(ArpMessage.newRequest(targetAddress, eth.serialize()));
+
+ }
private void broadcastArpRequestOutEdge(byte[] arpRequest, long inSwitch, short inPort) {
for (IOFSwitch sw : floodlightProvider.getSwitches().values()){
@@ -603,7 +672,7 @@
}
}
- log.debug("Broadcast ARP request for to: {}", switchPorts);
+ log.debug("Broadcast ARP request to: {}", switchPorts);
}
private void sendArpRequestOutPort(byte[] arpRequest, long dpid, short port) {
@@ -743,23 +812,35 @@
@Override
public void arpRequestNotification(ArpMessage arpMessage) {
- //log.debug("Received ARP notification from other instances");
+ log.debug("Received ARP notification from other instances");
switch (arpMessage.getType()){
case REQUEST:
- log.debug("Received ARP request notification for {}",
- arpMessage.getAddress());
- broadcastArpRequestOutMyEdge(arpMessage.getPacket());
+ if (arpMessage.getOutSwitch()==-1)
+ { log.debug("OutSwitch in ARP request Message is null");
+ }
+ if (arpMessage.getOutPort()==-1)
+ { log.debug("OutPort in ARP request Message is null");
+ }
+
+ if(arpMessage.getOutSwitch() ==-1 || arpMessage.getOutPort()==-1){
+ broadcastArpRequestOutMyEdge(arpMessage.getPacket());
+ }else if (arpMessage.getOutSwitch() >0 && arpMessage.getOutPort()>0 ){
+ log.debug("OutSwitch in ARP request message is: {}; OutPort in ARP request message is: {}",arpMessage.getOutSwitch(),arpMessage.getOutPort());
+ sendArpRequestOutPort(arpMessage.getPacket(),arpMessage.getOutSwitch(),arpMessage.getOutPort());
+
+ }else{
+ broadcastArpRequestOutMyEdge(arpMessage.getPacket());}
break;
case REPLY:
log.debug("Received ARP reply notification for {}",
arpMessage.getAddress());
- sendArpReplyToWaitingRequesters(arpMessage.getAddress());
+ sendArpReplyToWaitingRequesters(arpMessage.getAddress(),arpMessage.getMAC());
break;
}
}
- private void sendArpReplyToWaitingRequesters(InetAddress address) {
+ private void sendArpReplyToWaitingRequesters(InetAddress address, MACAddress mac) {
log.debug("Sending ARP reply for {} to requesters",
address.getHostAddress());
@@ -777,13 +858,13 @@
}
}
- IDeviceObject deviceObject = deviceStorage.getDeviceByIP(
+ /*IDeviceObject deviceObject = deviceStorage.getDeviceByIP(
InetAddresses.coerceToInteger(address));
MACAddress mac = MACAddress.valueOf(deviceObject.getMACAddress());
log.debug("Found {} at {} in network map",
- address.getHostAddress(), mac);
+ address.getHostAddress(), mac);*/
//Don't hold an ARP lock while dispatching requests
for (ArpRequest request : requestsToSend) {