Changes to ARP, Forwarding, and OnosDeviceManager to make reactive forwarding more reliable
diff --git a/src/main/java/net/onrc/onos/ofcontroller/core/internal/DeviceStorageImpl.java b/src/main/java/net/onrc/onos/ofcontroller/core/internal/DeviceStorageImpl.java
index a71b762..ba4a3b5 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/core/internal/DeviceStorageImpl.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/core/internal/DeviceStorageImpl.java
@@ -2,6 +2,7 @@
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Iterator;
import java.util.List;
import net.floodlightcontroller.devicemanager.IDevice;
@@ -325,9 +326,10 @@
*/
@Override
public void addOnosDevice(OnosDevice onosDevice) {
-
String macAddress = HexString.toHexString(onosDevice.getMacAddress().toBytes());
+ log.debug("addOnosDevice: {}", onosDevice);
+
try {
IDeviceObject device = ope.searchDevice(macAddress);
@@ -339,7 +341,6 @@
}
// Check if the device has the IP address, add it if it doesn't
- // TODO multiple IP addresses
if (onosDevice.getIpv4Address() != null) {
boolean hasIpAddress = false;
for (IIpv4Address ipv4Address : device.getIpv4Addresses()) {
@@ -360,8 +361,25 @@
}
// Check if the device has the attachment point, add it if not
+ // TODO single attachment point for now, extend to multiple later
String switchDpid = HexString.toHexString(onosDevice.getSwitchDPID());
boolean hasAttachmentPoint = false;
+ Iterator<IPortObject> it = device.getAttachedPorts().iterator();
+ if (it.hasNext()) {
+ IPortObject existingPort = it.next();
+ if (existingPort != null) {
+ ISwitchObject existingSwitch = existingPort.getSwitch();
+ if (!existingSwitch.getDPID().equals(switchDpid) ||
+ existingPort.getNumber() != onosDevice.getSwitchPort()) {
+ existingPort.removeDevice(device);
+ }
+ else {
+ hasAttachmentPoint = true;
+ }
+ }
+ }
+
+ /*
for (IPortObject portObject : device.getAttachedPorts()) {
ISwitchObject switchObject = portObject.getSwitch();
if (switchObject.getDPID().equals(switchDpid)
@@ -370,10 +388,13 @@
break;
}
}
+ */
if (!hasAttachmentPoint) {
IPortObject portObject = ope.searchPort(switchDpid, onosDevice.getSwitchPort());
- portObject.setDevice(device);
+ if (portObject != null) {
+ portObject.setDevice(device);
+ }
}
ope.commit();
diff --git a/src/main/java/net/onrc/onos/ofcontroller/devicemanager/OnosDeviceManager.java b/src/main/java/net/onrc/onos/ofcontroller/devicemanager/OnosDeviceManager.java
index a776eaa..f75a2b0 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/devicemanager/OnosDeviceManager.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/devicemanager/OnosDeviceManager.java
@@ -35,7 +35,7 @@
private IFloodlightProviderService floodlightProvider;
- public class OnosDeviceUpdate implements IUpdate {
+ private class OnosDeviceUpdate implements IUpdate {
private OnosDevice device;
public OnosDeviceUpdate(OnosDevice device) {
@@ -55,8 +55,9 @@
@Override
public boolean isCallbackOrderingPrereq(OFType type, String name) {
- // TODO Auto-generated method stub
- return false;
+ // We want link discovery to consume LLDP first otherwise we'll
+ // end up reading bad device info from LLDP packets
+ return type == OFType.PACKET_IN && "linkdiscovery".equals(name);
}
@Override
diff --git a/src/main/java/net/onrc/onos/ofcontroller/forwarding/Forwarding.java b/src/main/java/net/onrc/onos/ofcontroller/forwarding/Forwarding.java
index 4b2b087..02972e2 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/forwarding/Forwarding.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/forwarding/Forwarding.java
@@ -249,13 +249,17 @@
destinationMac);
if (deviceObject == null) {
- log.debug("No device entry found for {}", destinationMac);
+ log.debug("No device entry found for {} - broadcasting packet",
+ destinationMac);
+ handleBroadcast(sw, pi, eth);
return;
}
Iterator<IPortObject> ports = deviceObject.getAttachedPorts().iterator();
if (!ports.hasNext()) {
- log.debug("No attachment point found for device {}", destinationMac);
+ log.debug("No attachment point found for device {} - broadcasting packet",
+ destinationMac);
+ handleBroadcast(sw, pi, eth);
return;
}
IPortObject portObject = ports.next();
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 a63d2a8..32b2e9c 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/proxyarp/ProxyArpManager.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/proxyarp/ProxyArpManager.java
@@ -63,7 +63,7 @@
private final long ARP_TIMER_PERIOD = 100; //ms
- private static final int ARP_REQUEST_TIMEOUT = 500; //ms
+ private static final int ARP_REQUEST_TIMEOUT = 2000; //ms
private IFloodlightProviderService floodlightProvider;
private ITopologyService topology;
@@ -77,7 +77,7 @@
private short vlan;
private static final short NO_VLAN = 0;
- private ArpCache arpCache;
+ //private ArpCache arpCache;
private SetMultimap<InetAddress, ArpRequest> arpRequests;
@@ -165,7 +165,7 @@
this.configService = context.getServiceImpl(IConfigInfoService.class);
this.restApi = context.getServiceImpl(IRestApiService.class);
- arpCache = new ArpCache();
+ //arpCache = new ArpCache();
arpRequests = Multimaps.synchronizedSetMultimap(
HashMultimap.<InetAddress, ArpRequest>create());
@@ -207,10 +207,7 @@
//Have to synchronize externally on the Multimap while using an iterator,
//even though it's a synchronizedMultimap
- synchronized (arpRequests) {
- //log.debug("Current have {} outstanding requests",
- //arpRequests.size());
-
+ synchronized (arpRequests) {
Iterator<Map.Entry<InetAddress, ArpRequest>> it
= arpRequests.entries().iterator();
@@ -222,16 +219,15 @@
log.debug("Cleaning expired ARP request for {}",
entry.getKey().getHostAddress());
- //if he ARP Request is expired and then delete the device
- /*
+ // If the ARP request is expired and then delete the device
+ // TODO check whether this is OK from this thread
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());
+ if (targetDevice != null) {
+ deviceStorage.removeDevice(targetDevice);
+ log.debug("RemoveDevice: {} due to no have not recieve the ARP reply", targetDevice.toString());
}
- */
it.remove();
@@ -289,17 +285,11 @@
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
- //get them.
handleArpRequest(sw, pi, arp, eth);
}
else if (arp.getOpCode() == ARP.OP_REPLY) {
- log.debug("receive ARP reply");
- handleArpReply(sw, pi, arp);
- sendToOtherNodesReply(eth, pi);
+ handleArpReply(sw, pi, arp);
+ sendToOtherNodesReply(eth, pi);
}
// Stop ARP packets here
@@ -339,20 +329,30 @@
}
//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) {
- // 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
+ IDeviceObject targetDevice =
+ deviceStorage.getDeviceByIP(InetAddresses.coerceToInteger(target));
+
+ 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
+ sendToOtherNodes(eth, sw.getId(), pi);
+ }
+ 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 (log.isTraceEnabled()) {
- log.trace("The target Device Record in DB is: {} => {} from ARP request 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()});
@@ -361,38 +361,38 @@
// 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();
+ Iterable<IPortObject> outPorts = targetDevice.getAttachedPorts();
- if(!outPorts.iterator().hasNext()){
- log.debug("outPort : null");
+ if (!outPorts.iterator().hasNext()){
+ if (log.isTraceEnabled()) {
+ log.trace("Device {} exists but is not connected to any ports" +
+ " - broadcasting", macAddress);
+ }
+
sendToOtherNodes(eth, sw.getId(), pi);
- }else{
-
+ }
+ else {
for (IPortObject portObject : outPorts) {
- long outSwitch=0;
- short outPort=0;
-
+ long outSwitch = 0;
+ short outPort = 0;
if (!portObject.getLinkedPorts().iterator().hasNext()) {
- outPort=portObject.getNumber();
- log.debug("outPort:{} ", outPort);
- }
+ outPort = portObject.getNumber();
+ }
ISwitchObject outSwitchObject = portObject.getSwitch();
- outSwitch= HexString.toLong(outSwitchObject.getDPID());
- log.debug("outSwitch.DPID:{}; outPort: {}", outSwitchObject.getDPID(), outPort );
- sendToOtherNodes( eth, pi, outSwitch, outPort);
+ outSwitch = HexString.toLong(outSwitchObject.getDPID());
+
+ if (log.isTraceEnabled()) {
+ log.trace("Probing device {} on port {}/{}",
+ new Object[] {macAddress,
+ HexString.toHexString(outSwitch), 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
- sendToOtherNodes(eth, sw.getId(), pi);
}
-
}
private void handleArpReply(IOFSwitch sw, OFPacketIn pi, ARP arp){
@@ -534,22 +534,22 @@
datagrid.sendArpRequest(ArpMessage.newRequest(targetAddress, eth.serialize(),
-1L, (short)-1, inSwitchId, pi.getInPort()));
}
+
//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));
-
+ 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());
+ targetAddress = InetAddress.getByAddress(arp.getTargetProtocolAddress());
} catch (UnknownHostException e) {
- log.error("Unknown host", e);
- return;
+ log.error("Unknown host", e);
+ return;
}
datagrid.sendArpRequest(ArpMessage.newRequest(targetAddress, eth.serialize(), outSwitch, outPort));
@@ -557,25 +557,26 @@
}
+
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()));
+ 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());
+ targetAddress = InetAddress.getByAddress(arp.getSenderProtocolAddress());
} catch (UnknownHostException e) {
- log.error("Unknown host", e);
- return;
+ log.error("Unknown host", e);
+ return;
}
- datagrid.sendArpRequest(ArpMessage.newReply(targetAddress,mac));
+ datagrid.sendArpRequest(ArpMessage.newReply(targetAddress, mac));
//datagrid.sendArpReply(ArpMessage.newRequest(targetAddress, eth.serialize()));
}
@@ -678,7 +679,9 @@
}
}
- log.debug("Broadcast ARP request to: {}", switchPorts);
+ if (log.isTraceEnabled()) {
+ log.trace("Broadcast ARP request to: {}", switchPorts);
+ }
}
private void sendArpRequestOutPort(byte[] arpRequest, long dpid, short port) {
@@ -793,7 +796,8 @@
@Override
public MACAddress getMacAddress(InetAddress ipAddress) {
- return arpCache.lookup(ipAddress);
+ //return arpCache.lookup(ipAddress);
+ return null;
}
@Override
@@ -809,7 +813,8 @@
@Override
public List<String> getMappings() {
- return arpCache.getMappings();
+ //return arpCache.getMappings();
+ return new ArrayList<String>();
}
/*