Merge pull request #480 from pingping-lin/master
ARP improvements
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/proxyarp/ArpMessage.java b/src/main/java/net/onrc/onos/ofcontroller/proxyarp/ArpMessage.java
index 5f22ca2..ee8f23d 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/proxyarp/ArpMessage.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/proxyarp/ArpMessage.java
@@ -2,6 +2,7 @@
import java.io.Serializable;
import java.net.InetAddress;
+import net.floodlightcontroller.util.MACAddress;
public class ArpMessage implements Serializable {
@@ -14,6 +15,14 @@
private final InetAddress forAddress;
private final byte[] packetData;
+ //ARP reply message needs MAC info
+ private final MACAddress mac;
+ //only send the ARP request message to the device attachment needs the attachment switch and port.
+ private final long outSwitch;
+ private final short outPort;
+
+
+
public enum Type {
REQUEST,
REPLY
@@ -24,14 +33,41 @@
this.type = type;
this.forAddress = address;
this.packetData = eth;
+ this.mac = null;
+ this.outSwitch = -1;
+ this.outPort = -1;
}
private ArpMessage(Type type, InetAddress address) {
this.type = type;
this.forAddress = address;
this.packetData = null;
+ this.mac = null;
+ this.outSwitch = -1;
+ this.outPort = -1;
+
+ }
+ // 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;
+ this.outSwitch = -1;
+ this.outPort = -1;
}
+ // 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.mac = null;
+ this.outSwitch = outSwitch;
+ this.outPort = outPort;
+ }
+
public static ArpMessage newRequest(InetAddress forAddress, byte[] arpRequest) {
return new ArpMessage(Type.REQUEST, forAddress, arpRequest);
}
@@ -39,6 +75,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;
@@ -51,4 +97,16 @@
public byte[] getPacket() {
return packetData;
}
+ public MACAddress getMAC() {
+ return mac;
+ }
+
+ public long getOutSwitch() {
+ return outSwitch;
+ }
+
+ public short getOutPort() {
+ return 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 415d697..c53e8e1 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);
}
}
@@ -301,7 +314,7 @@
InetAddress target;
try {
- target = InetAddress.getByAddress(arp.getTargetProtocolAddress());
+ target = InetAddress.getByAddress(arp.getTargetProtocolAddress());
} catch (UnknownHostException e) {
log.debug("Invalid address in ARP request", e);
return;
@@ -313,66 +326,72 @@
if (configService.isInterfaceAddress(target)) {
log.trace("ARP request for our interface. Sending reply {} => {}",
target.getHostAddress(), configService.getRouterMacAddress());
-
+
sendArpReply(arp, sw.getId(), pi.getInPort(),
configService.getRouterMacAddress());
}
-
+
return;
}
//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 [] {
+ 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 {
+
+ // sendArpReply(arp, sw.getId(), pi.getInPort(), macAddress);
+
+ log.trace("Checking the device info from DB is still valid or not");
+ Iterable<IPortObject> outPorts=targetDevice.getAttachedPorts();
+
+ 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);
+ }
+ }
+ }
+
+ }else {
+ log.debug("The Device info in DB is {} for IP {}", targetDevice, inetAddressToString(arp.getTargetProtocolAddress()));
+
// We don't know the device so broadcast the request out
- // the edge of the network
-
- //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()});
- }
-
- sendArpReply(arp, sw.getId(), pi.getInPort(), macAddress);
- }*/
+
}
@SuppressWarnings("unused")
@@ -394,7 +413,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);
@@ -514,6 +533,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()){
@@ -604,7 +668,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) {
@@ -744,23 +808,26 @@
@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 || arpMessage.getOutPort() == -1){
+ broadcastArpRequestOutMyEdge(arpMessage.getPacket());
+ }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());
+ 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());
@@ -778,13 +845,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) {