Merge pull request #499 from jonohart/fw
Improvements to device handling and reactive forwarding
diff --git a/conf/onos-embedded.properties b/conf/onos-embedded.properties
index 8ae143e..dddacdb 100644
--- a/conf/onos-embedded.properties
+++ b/conf/onos-embedded.properties
@@ -1,7 +1,6 @@
floodlight.modules = net.floodlightcontroller.core.FloodlightProvider,\
net.floodlightcontroller.threadpool.ThreadPool,\
net.onrc.onos.ofcontroller.floodlightlistener.NetworkGraphPublisher, \
-net.floodlightcontroller.devicemanager.internal.DeviceManagerImpl,\
net.floodlightcontroller.ui.web.StaticWebRoutable,\
net.onrc.onos.datagrid.HazelcastDatagrid,\
net.onrc.onos.ofcontroller.flowmanager.FlowManager,\
diff --git a/conf/onos.properties b/conf/onos.properties
index b748b40..e77e6e0 100644
--- a/conf/onos.properties
+++ b/conf/onos.properties
@@ -1,7 +1,6 @@
floodlight.modules = net.floodlightcontroller.core.FloodlightProvider,\
net.floodlightcontroller.threadpool.ThreadPool,\
net.onrc.onos.ofcontroller.floodlightlistener.NetworkGraphPublisher, \
-net.floodlightcontroller.devicemanager.internal.DeviceManagerImpl,\
net.floodlightcontroller.ui.web.StaticWebRoutable,\
net.onrc.onos.datagrid.HazelcastDatagrid,\
net.onrc.onos.ofcontroller.flowmanager.FlowManager,\
diff --git a/src/main/java/net/floodlightcontroller/util/MACAddress.java b/src/main/java/net/floodlightcontroller/util/MACAddress.java
index b143bda..fc144bb 100644
--- a/src/main/java/net/floodlightcontroller/util/MACAddress.java
+++ b/src/main/java/net/floodlightcontroller/util/MACAddress.java
@@ -8,6 +8,7 @@
import org.codehaus.jackson.map.annotate.JsonDeserialize;
import org.codehaus.jackson.map.annotate.JsonSerialize;
+import org.openflow.util.HexString;
/**
* The class representing MAC address.
@@ -167,13 +168,6 @@
@Override
public String toString() {
- StringBuilder builder = new StringBuilder();
- for (byte b: address) {
- if (builder.length() > 0) {
- builder.append(":");
- }
- builder.append(String.format("%02X", b & 0xFF));
- }
- return builder.toString();
+ return HexString.toHexString(address);
}
}
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 13b9182..2eddadf 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/core/IDeviceStorage.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/core/IDeviceStorage.java
@@ -2,6 +2,7 @@
import net.floodlightcontroller.devicemanager.IDevice;
import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IDeviceObject;
+import net.onrc.onos.ofcontroller.devicemanager.OnosDevice;
public interface IDeviceStorage extends INetMapStorage {
@@ -12,5 +13,7 @@
public IDeviceObject getDeviceByMac(String mac);
public IDeviceObject getDeviceByIP(int ipv4Address);
public void changeDeviceAttachments(IDevice device);
- public void changeDeviceIPv4Address(IDevice device);
+ public void changeDeviceIPv4Address(IDevice device);
+
+ public void addOnosDevice(OnosDevice onosDevice);
}
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 4bbc054..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;
@@ -11,6 +12,8 @@
import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IDeviceObject;
import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IIpv4Address;
import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IPortObject;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.ISwitchObject;
+import net.onrc.onos.ofcontroller.devicemanager.OnosDevice;
import org.openflow.util.HexString;
import org.slf4j.Logger;
@@ -314,5 +317,92 @@
}
}
}
+
+ /**
+ * Takes an {@link OnosDevice} and adds it into the database. There is no
+ * checking of the database data and removing old data - an
+ * {@link OnosDevice} basically corresponds to a packet we've just seen,
+ * and we need to add that information into the database.
+ */
+ @Override
+ public void addOnosDevice(OnosDevice onosDevice) {
+ String macAddress = HexString.toHexString(onosDevice.getMacAddress().toBytes());
+
+ log.debug("addOnosDevice: {}", onosDevice);
+
+ try {
+ IDeviceObject device = ope.searchDevice(macAddress);
+
+ if (device == null) {
+ device = ope.newDevice();
+ device.setType("device");
+ device.setState("ACTIVE");
+ device.setMACAddress(macAddress);
+ }
+
+ // Check if the device has the IP address, add it if it doesn't
+ if (onosDevice.getIpv4Address() != null) {
+ boolean hasIpAddress = false;
+ for (IIpv4Address ipv4Address : device.getIpv4Addresses()) {
+ if (ipv4Address.getIpv4Address() == onosDevice.getIpv4Address().intValue()) {
+ hasIpAddress = true;
+ break;
+ }
+ }
+
+ if (!hasIpAddress) {
+ IIpv4Address ipv4Address = ope.ensureIpv4Address(onosDevice.getIpv4Address().intValue());
+ IDeviceObject oldDevice = ipv4Address.getDevice();
+ if (oldDevice != null && oldDevice.getMACAddress() != macAddress) {
+ oldDevice.removeIpv4Address(ipv4Address);
+ }
+ device.addIpv4Address(ipv4Address);
+ }
+ }
+
+ // 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)
+ && portObject.getNumber() == onosDevice.getSwitchPort()) {
+ hasAttachmentPoint = true;
+ break;
+ }
+ }
+ */
+
+ if (!hasAttachmentPoint) {
+ IPortObject portObject = ope.searchPort(switchDpid, onosDevice.getSwitchPort());
+ if (portObject != null) {
+ portObject.setDevice(device);
+ }
+ }
+
+ ope.commit();
+ }
+ catch (TitanException e) {
+ log.error("addOnosDevice {} failed:", macAddress, e);
+ ope.rollback();
+ }
+ }
}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/devicemanager/IOnosDeviceService.java b/src/main/java/net/onrc/onos/ofcontroller/devicemanager/IOnosDeviceService.java
new file mode 100644
index 0000000..1e40aa5
--- /dev/null
+++ b/src/main/java/net/onrc/onos/ofcontroller/devicemanager/IOnosDeviceService.java
@@ -0,0 +1,14 @@
+package net.onrc.onos.ofcontroller.devicemanager;
+
+import net.floodlightcontroller.core.module.IFloodlightService;
+
+/**
+ * {@link OnosDeviceManager} doesn't yet provide any API to fellow modules,
+ * however making it export a dummy service means we can specify it as
+ * a dependency of Forwarding
+ * @author jono
+ *
+ */
+public interface IOnosDeviceService extends IFloodlightService {
+
+}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/devicemanager/OnosDevice.java b/src/main/java/net/onrc/onos/ofcontroller/devicemanager/OnosDevice.java
new file mode 100644
index 0000000..34d2c38
--- /dev/null
+++ b/src/main/java/net/onrc/onos/ofcontroller/devicemanager/OnosDevice.java
@@ -0,0 +1,274 @@
+/**
+* Copyright 2011,2012, Big Switch Networks, Inc.
+* Originally created by David Erickson, Stanford University
+*
+* Licensed under the Apache License, Version 2.0 (the "License"); you may
+* not use this file except in compliance with the License. You may obtain
+* a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+* License for the specific language governing permissions and limitations
+* under the License.
+**/
+
+package net.onrc.onos.ofcontroller.devicemanager;
+
+import java.util.Date;
+
+import net.floodlightcontroller.devicemanager.internal.Entity;
+import net.floodlightcontroller.packet.IPv4;
+import net.floodlightcontroller.util.MACAddress;
+
+/**
+ * An entity on the network is a visible trace of a device that corresponds
+ * to a packet received from a particular interface on the edge of a network,
+ * with a particular VLAN tag, and a particular MAC address, along with any
+ * other packet characteristics we might want to consider as helpful for
+ * disambiguating devices.
+ *
+ * Entities are the most basic element of devices; devices consist of one or
+ * more entities. Entities are immutable once created, except for the last
+ * seen timestamp.
+ *
+ * @author readams
+ *
+ */
+public class OnosDevice { //implements Comparable<OnosDevice> {
+ /**
+ * Timeout for computing {@link Entity#activeSince}.
+ * @see {@link Entity#activeSince}
+ */
+ private static int ACTIVITY_TIMEOUT = 30000;
+
+ /**
+ * The MAC address associated with this entity
+ */
+ private MACAddress macAddress;
+
+ /**
+ * The IP address associated with this entity, or null if no IP learned
+ * from the network observation associated with this entity
+ */
+ private Integer ipv4Address;
+
+ /**
+ * The VLAN tag on this entity, or null if untagged
+ */
+ private Short vlan;
+
+ /**
+ * The DPID of the switch for the ingress point for this entity,
+ * or null if not present
+ */
+ private long switchDPID;
+
+ /**
+ * The port number of the switch for the ingress point for this entity,
+ * or null if not present
+ */
+ private short switchPort;
+
+ /**
+ * The last time we observed this entity on the network
+ */
+ private Date lastSeenTimestamp;
+
+ /**
+ * The time between {@link Entity#activeSince} and
+ * {@link Entity#lastSeenTimestamp} is a period of activity for this
+ * entity where it was observed repeatedly. If, when the entity is
+ * observed, the is longer ago than the activity timeout,
+ * {@link Entity#lastSeenTimestamp} and {@link Entity#activeSince} will
+ * be set to the current time.
+ */
+ private Date activeSince;
+
+ private int hashCode = 0;
+
+ // ************
+ // Constructors
+ // ************
+
+ /**
+ * Create a new entity
+ *
+ * @param macAddress
+ * @param vlan
+ * @param ipv4Address
+ * @param switchDPID
+ * @param switchPort
+ * @param lastSeenTimestamp
+ */
+ public OnosDevice(MACAddress macAddress, Short vlan,
+ Integer ipv4Address, Long switchDPID, short switchPort,
+ Date lastSeenTimestamp) {
+ this.macAddress = macAddress;
+ this.ipv4Address = ipv4Address;
+ this.vlan = vlan;
+ this.switchDPID = switchDPID;
+ this.switchPort = switchPort;
+ this.lastSeenTimestamp = lastSeenTimestamp;
+ this.activeSince = lastSeenTimestamp;
+ }
+
+ // ***************
+ // Getters/Setters
+ // ***************
+
+ public MACAddress getMacAddress() {
+ return macAddress;
+ }
+
+ public Integer getIpv4Address() {
+ return ipv4Address;
+ }
+
+ public Short getVlan() {
+ return vlan;
+ }
+
+ public Long getSwitchDPID() {
+ return switchDPID;
+ }
+
+ public short getSwitchPort() {
+ return switchPort;
+ }
+
+ public Date getLastSeenTimestamp() {
+ return lastSeenTimestamp;
+ }
+
+ /**
+ * Set the last seen timestamp and also update {@link Entity#activeSince}
+ * if appropriate
+ * @param lastSeenTimestamp the new last seen timestamp
+ * @see {@link Entity#activeSince}
+ */
+ public void setLastSeenTimestamp(Date lastSeenTimestamp) {
+ if (activeSince == null ||
+ (activeSince.getTime() + ACTIVITY_TIMEOUT) <
+ lastSeenTimestamp.getTime())
+ this.activeSince = lastSeenTimestamp;
+ this.lastSeenTimestamp = lastSeenTimestamp;
+ }
+
+ public Date getActiveSince() {
+ return activeSince;
+ }
+
+ public void setActiveSince(Date activeSince) {
+ this.activeSince = activeSince;
+ }
+
+ /*
+ @Override
+ public int hashCode() {
+ if (hashCode != 0) return hashCode;
+ final int prime = 31;
+ hashCode = 1;
+ hashCode = prime * hashCode
+ + ((ipv4Address == null) ? 0 : ipv4Address.hashCode());
+ //hashCode = prime * hashCode + (int) (macAddress ^ (macAddress >>> 32));
+ hashCode = prime * macAddress.hashCode();
+ hashCode = prime * hashCode + (int) (switchDPID ^ (switchDPID >>> 32));
+ hashCode = prime * hashCode + switchPort;
+ hashCode = prime * hashCode + ((vlan == null) ? 0 : vlan.hashCode());
+ return hashCode;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) return true;
+ if (obj == null) return false;
+ if (getClass() != obj.getClass()) return false;
+ Entity other = (Entity) obj;
+ if (hashCode() != other.hashCode()) return false;
+ if (ipv4Address == null) {
+ if (other.ipv4Address != null) return false;
+ } else if (!ipv4Address.equals(other.ipv4Address)) return false;
+ if (macAddress != other.macAddress) return false;
+ if (switchDPID == null) {
+ if (other.switchDPID != null) return false;
+ } else if (!switchDPID.equals(other.switchDPID)) return false;
+ if (switchPort == null) {
+ if (other.switchPort != null) return false;
+ } else if (!switchPort.equals(other.switchPort)) return false;
+ if (vlan == null) {
+ if (other.vlan != null) return false;
+ } else if (!vlan.equals(other.vlan)) return false;
+ return true;
+ }
+ */
+
+
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append("Entity [macAddress=");
+ builder.append(macAddress.toString());
+ builder.append(", ipv4Address=");
+ builder.append(IPv4.fromIPv4Address(ipv4Address==null ?
+ 0 : ipv4Address.intValue()));
+ builder.append(", vlan=");
+ builder.append(vlan);
+ builder.append(", switchDPID=");
+ builder.append(switchDPID);
+ builder.append(", switchPort=");
+ builder.append(switchPort);
+ builder.append(", lastSeenTimestamp=");
+ builder.append(lastSeenTimestamp == null? "null" : lastSeenTimestamp.getTime());
+ builder.append(", activeSince=");
+ builder.append(activeSince == null? "null" : activeSince.getTime());
+ builder.append("]");
+ return builder.toString();
+ }
+
+ /*
+ @Override
+ public int compareTo(OnosDevice o) {
+ if (macAddress < o.macAddress) return -1;
+ if (macAddress > o.macAddress) return 1;
+
+ int r;
+ if (switchDPID == null)
+ r = o.switchDPID == null ? 0 : -1;
+ else if (o.switchDPID == null)
+ r = 1;
+ else
+ r = switchDPID.compareTo(o.switchDPID);
+ if (r != 0) return r;
+
+ if (switchPort == null)
+ r = o.switchPort == null ? 0 : -1;
+ else if (o.switchPort == null)
+ r = 1;
+ else
+ r = switchPort.compareTo(o.switchPort);
+ if (r != 0) return r;
+
+ if (ipv4Address == null)
+ r = o.ipv4Address == null ? 0 : -1;
+ else if (o.ipv4Address == null)
+ r = 1;
+ else
+ r = ipv4Address.compareTo(o.ipv4Address);
+ if (r != 0) return r;
+
+ if (vlan == null)
+ r = o.vlan == null ? 0 : -1;
+ else if (o.vlan == null)
+ r = 1;
+ else
+ r = vlan.compareTo(o.vlan);
+ if (r != 0) return r;
+
+ return 0;
+ }*/
+
+}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/devicemanager/OnosDeviceManager.java b/src/main/java/net/onrc/onos/ofcontroller/devicemanager/OnosDeviceManager.java
new file mode 100644
index 0000000..f75a2b0
--- /dev/null
+++ b/src/main/java/net/onrc/onos/ofcontroller/devicemanager/OnosDeviceManager.java
@@ -0,0 +1,190 @@
+package net.onrc.onos.ofcontroller.devicemanager;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import net.floodlightcontroller.core.FloodlightContext;
+import net.floodlightcontroller.core.IFloodlightProviderService;
+import net.floodlightcontroller.core.IOFMessageListener;
+import net.floodlightcontroller.core.IOFSwitch;
+import net.floodlightcontroller.core.IUpdate;
+import net.floodlightcontroller.core.module.FloodlightModuleContext;
+import net.floodlightcontroller.core.module.FloodlightModuleException;
+import net.floodlightcontroller.core.module.IFloodlightModule;
+import net.floodlightcontroller.core.module.IFloodlightService;
+import net.floodlightcontroller.packet.ARP;
+import net.floodlightcontroller.packet.DHCP;
+import net.floodlightcontroller.packet.Ethernet;
+import net.floodlightcontroller.packet.IPv4;
+import net.floodlightcontroller.packet.UDP;
+import net.floodlightcontroller.util.MACAddress;
+import net.onrc.onos.ofcontroller.core.IDeviceStorage;
+import net.onrc.onos.ofcontroller.core.internal.DeviceStorageImpl;
+
+import org.openflow.protocol.OFMessage;
+import org.openflow.protocol.OFPacketIn;
+import org.openflow.protocol.OFType;
+
+public class OnosDeviceManager implements IFloodlightModule, IOFMessageListener,
+ IOnosDeviceService {
+ private IDeviceStorage deviceStorage;
+
+ private IFloodlightProviderService floodlightProvider;
+
+ private class OnosDeviceUpdate implements IUpdate {
+ private OnosDevice device;
+
+ public OnosDeviceUpdate(OnosDevice device) {
+ this.device = device;
+ }
+
+ @Override
+ public void dispatch() {
+ deviceStorage.addOnosDevice(device);
+ }
+ }
+
+ @Override
+ public String getName() {
+ return "onosdevicemanager";
+ }
+
+ @Override
+ public boolean isCallbackOrderingPrereq(OFType type, String name) {
+ // 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
+ public boolean isCallbackOrderingPostreq(OFType type, String name) {
+ return type == OFType.PACKET_IN &&
+ ("proxyarpmanager".equals(name) || "onosforwarding".equals(name));
+ }
+
+ @Override
+ public Command receive(IOFSwitch sw, OFMessage msg, FloodlightContext cntx) {
+ if (msg.getType().equals(OFType.PACKET_IN)) {
+ OFPacketIn pi = (OFPacketIn) msg;
+
+ Ethernet eth = IFloodlightProviderService.bcStore.
+ get(cntx, IFloodlightProviderService.CONTEXT_PI_PAYLOAD);
+
+ return processPacketIn(sw, pi, eth);
+ }
+
+ return Command.CONTINUE;
+ }
+
+ private Command processPacketIn(IOFSwitch sw, OFPacketIn pi, Ethernet eth) {
+
+ // Extract source entity information
+ OnosDevice srcDevice =
+ getSourceDeviceFromPacket(eth, sw.getId(), pi.getInPort());
+ if (srcDevice == null)
+ return Command.STOP;
+
+ floodlightProvider.publishUpdate(new OnosDeviceUpdate(srcDevice));
+
+ return Command.CONTINUE;
+ }
+
+ /**
+ * Get IP address from packet if the packet is either an ARP
+ * or a DHCP packet
+ * @param eth
+ * @param dlAddr
+ * @return
+ */
+ private int getSrcNwAddr(Ethernet eth, long dlAddr) {
+ if (eth.getPayload() instanceof ARP) {
+ ARP arp = (ARP) eth.getPayload();
+ if ((arp.getProtocolType() == ARP.PROTO_TYPE_IP) &&
+ (Ethernet.toLong(arp.getSenderHardwareAddress()) == dlAddr)) {
+ return IPv4.toIPv4Address(arp.getSenderProtocolAddress());
+ }
+ } else if (eth.getPayload() instanceof IPv4) {
+ IPv4 ipv4 = (IPv4) eth.getPayload();
+ if (ipv4.getPayload() instanceof UDP) {
+ UDP udp = (UDP)ipv4.getPayload();
+ if (udp.getPayload() instanceof DHCP) {
+ DHCP dhcp = (DHCP)udp.getPayload();
+ if (dhcp.getOpCode() == DHCP.OPCODE_REPLY) {
+ return ipv4.getSourceAddress();
+ }
+ }
+ }
+ }
+ return 0;
+ }
+
+ /**
+ * Parse an entity from an {@link Ethernet} packet.
+ * @param eth the packet to parse
+ * @param sw the switch on which the packet arrived
+ * @param pi the original packetin
+ * @return the entity from the packet
+ */
+ private OnosDevice getSourceDeviceFromPacket(Ethernet eth,
+ long swdpid,
+ short port) {
+ byte[] dlAddrArr = eth.getSourceMACAddress();
+ long dlAddr = Ethernet.toLong(dlAddrArr);
+
+ // Ignore broadcast/multicast source
+ if ((dlAddrArr[0] & 0x1) != 0)
+ return null;
+
+ short vlan = eth.getVlanID();
+ int nwSrc = getSrcNwAddr(eth, dlAddr);
+ return new OnosDevice(MACAddress.valueOf(dlAddr),
+ ((vlan >= 0) ? vlan : null),
+ ((nwSrc != 0) ? nwSrc : null),
+ swdpid,
+ port,
+ new Date());
+ }
+
+ @Override
+ public Collection<Class<? extends IFloodlightService>> getModuleServices() {
+ List<Class<? extends IFloodlightService>> services =
+ new ArrayList<Class<? extends IFloodlightService>>();
+ services.add(IOnosDeviceService.class);
+ return services;
+ }
+
+ @Override
+ public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() {
+ Map<Class<? extends IFloodlightService>, IFloodlightService> impls =
+ new HashMap<Class<? extends IFloodlightService>, IFloodlightService>();
+ impls.put(IOnosDeviceService.class, this);
+ return impls;
+ }
+
+ @Override
+ public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
+ List<Class<? extends IFloodlightService>> dependencies =
+ new ArrayList<Class<? extends IFloodlightService>>();
+ dependencies.add(IFloodlightProviderService.class);
+ return dependencies;
+ }
+
+ @Override
+ public void init(FloodlightModuleContext context)
+ throws FloodlightModuleException {
+ floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
+
+ deviceStorage = new DeviceStorageImpl();
+ deviceStorage.init("");
+ }
+
+ @Override
+ public void startUp(FloodlightModuleContext context) {
+ floodlightProvider.addOFMessageListener(OFType.PACKET_IN, this);
+ }
+
+}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/floodlightlistener/NetworkGraphPublisher.java b/src/main/java/net/onrc/onos/ofcontroller/floodlightlistener/NetworkGraphPublisher.java
index 4b31667..da5a6f4 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/floodlightlistener/NetworkGraphPublisher.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/floodlightlistener/NetworkGraphPublisher.java
@@ -8,13 +8,6 @@
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
-import org.openflow.protocol.OFPhysicalPort;
-import org.openflow.util.HexString;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.net.InetAddresses;
-
import net.floodlightcontroller.core.IFloodlightProviderService;
import net.floodlightcontroller.core.IOFSwitch;
import net.floodlightcontroller.core.IOFSwitchListener;
@@ -25,7 +18,6 @@
import net.floodlightcontroller.core.util.SingletonTask;
import net.floodlightcontroller.devicemanager.IDevice;
import net.floodlightcontroller.devicemanager.IDeviceListener;
-import net.floodlightcontroller.devicemanager.IDeviceService;
import net.floodlightcontroller.routing.Link;
import net.floodlightcontroller.threadpool.IThreadPoolService;
import net.onrc.onos.datagrid.IDatagridService;
@@ -35,10 +27,10 @@
import net.onrc.onos.graph.LocalTopologyEventListener;
import net.onrc.onos.ofcontroller.core.IDeviceStorage;
import net.onrc.onos.ofcontroller.core.ILinkStorage;
-import net.onrc.onos.ofcontroller.core.IOFSwitchPortListener;
-import net.onrc.onos.ofcontroller.core.ISwitchStorage;
import net.onrc.onos.ofcontroller.core.INetMapStorage.DM_OPERATION;
import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.ISwitchObject;
+import net.onrc.onos.ofcontroller.core.IOFSwitchPortListener;
+import net.onrc.onos.ofcontroller.core.ISwitchStorage;
import net.onrc.onos.ofcontroller.core.internal.DeviceStorageImpl;
import net.onrc.onos.ofcontroller.core.internal.LinkStorageImpl;
import net.onrc.onos.ofcontroller.core.internal.SwitchStorageImpl;
@@ -51,6 +43,13 @@
import net.onrc.onos.registry.controller.IControllerRegistryService.ControlChangeCallback;
import net.onrc.onos.registry.controller.RegistryException;
+import org.openflow.protocol.OFPhysicalPort;
+import org.openflow.util.HexString;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.net.InetAddresses;
+
public class NetworkGraphPublisher implements IDeviceListener,
IOFSwitchListener,
IOFSwitchPortListener,
@@ -62,7 +61,7 @@
protected ISwitchStorage swStore;
protected ILinkStorage linkStore;
protected final static Logger log = LoggerFactory.getLogger(NetworkGraphPublisher.class);
- protected IDeviceService deviceService;
+ //protected IDeviceService deviceService;
protected IControllerRegistryService registryService;
protected GraphDBOperation op;
@@ -431,7 +430,7 @@
Collection<Class<? extends IFloodlightService>> l =
new ArrayList<Class<? extends IFloodlightService>>();
l.add(IFloodlightProviderService.class);
- l.add(IDeviceService.class);
+ //l.add(IDeviceService.class);
l.add(IDatagridService.class);
l.add(IThreadPoolService.class);
return l;
@@ -446,7 +445,7 @@
floodlightProvider =
context.getServiceImpl(IFloodlightProviderService.class);
- deviceService = context.getServiceImpl(IDeviceService.class);
+ //deviceService = context.getServiceImpl(IDeviceService.class);
linkDiscovery = context.getServiceImpl(ILinkDiscoveryService.class);
threadPool = context.getServiceImpl(IThreadPoolService.class);
registryService = context.getServiceImpl(IControllerRegistryService.class);
@@ -470,7 +469,7 @@
Map<String, String> configMap = context.getConfigParams(this);
String cleanupNeeded = configMap.get(CleanupEnabled);
- deviceService.addListener(this);
+ //deviceService.addListener(this);
floodlightProvider.addOFSwitchListener(this);
linkDiscovery.addListener(this);
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 bd51fdc..02972e2 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/forwarding/Forwarding.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/forwarding/Forwarding.java
@@ -25,6 +25,7 @@
import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IPortObject;
import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.ISwitchObject;
import net.onrc.onos.ofcontroller.core.internal.DeviceStorageImpl;
+import net.onrc.onos.ofcontroller.devicemanager.IOnosDeviceService;
import net.onrc.onos.ofcontroller.flowmanager.IFlowService;
import net.onrc.onos.ofcontroller.flowprogrammer.IFlowPusherService;
import net.onrc.onos.ofcontroller.proxyarp.ArpMessage;
@@ -51,8 +52,8 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.common.collect.HashMultimap;
-import com.google.common.collect.Multimap;
+import com.google.common.collect.LinkedListMultimap;
+import com.google.common.collect.ListMultimap;
import com.google.common.net.InetAddresses;
public class Forwarding implements IOFMessageListener, IFloodlightModule,
@@ -71,7 +72,7 @@
private TopologyManager topologyService;
private Map<Path, Long> pendingFlows;
- private Multimap<Long, PacketToPush> waitingPackets;
+ private ListMultimap<Long, PacketToPush> waitingPackets;
private final Object lock = new Object();
@@ -139,6 +140,7 @@
dependencies.add(IFloodlightProviderService.class);
dependencies.add(IFlowService.class);
dependencies.add(IFlowPusherService.class);
+ dependencies.add(IOnosDeviceService.class);
return dependencies;
}
@@ -155,7 +157,8 @@
pendingFlows = new ConcurrentHashMap<Path, Long>();
//waitingPackets = Multimaps.synchronizedSetMultimap(
//HashMultimap.<Long, PacketToPush>create());
- waitingPackets = HashMultimap.create();
+ //waitingPackets = HashMultimap.create();
+ waitingPackets = LinkedListMultimap.create();
deviceStorage = new DeviceStorageImpl();
deviceStorage.init("");
@@ -176,7 +179,8 @@
@Override
public boolean isCallbackOrderingPrereq(OFType type, String name) {
return (type == OFType.PACKET_IN) &&
- (name.equals("devicemanager") || name.equals("proxyarpmanager"));
+ (name.equals("devicemanager") || name.equals("proxyarpmanager")
+ || name.equals("onosdevicemanager"));
}
@Override
@@ -234,7 +238,7 @@
// our non-ARP packets.
// TODO This should be refactored later to account for the new use case.
datagrid.sendArpRequest(ArpMessage.newRequest(targetAddress, eth.serialize(),
- sw.getId(), pi.getInPort()));
+ -1L, (short)-1, sw.getId(), pi.getInPort()));
}
private void handlePacketIn(IOFSwitch sw, OFPacketIn pi, Ethernet eth) {
@@ -245,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 3962efb..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,14 +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();
@@ -263,7 +261,7 @@
@Override
public boolean isCallbackOrderingPrereq(OFType type, String name) {
if (type == OFType.PACKET_IN) {
- return "devicemanager".equals(name);
+ return "devicemanager".equals(name) || "onosdevicemanager".equals(name);
}
else {
return false;
@@ -272,7 +270,7 @@
@Override
public boolean isCallbackOrderingPostreq(OFType type, String name) {
- return false;
+ return type == OFType.PACKET_IN && "onosforwarding".equals(name);
}
@Override
@@ -287,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
@@ -337,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()});
@@ -359,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){
@@ -532,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));
@@ -555,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()));
}
@@ -676,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) {
@@ -791,7 +796,8 @@
@Override
public MACAddress getMacAddress(InetAddress ipAddress) {
- return arpCache.lookup(ipAddress);
+ //return arpCache.lookup(ipAddress);
+ return null;
}
@Override
@@ -807,7 +813,8 @@
@Override
public List<String> getMappings() {
- return arpCache.getMappings();
+ //return arpCache.getMappings();
+ return new ArrayList<String>();
}
/*
diff --git a/src/main/resources/META-INF/services/net.floodlightcontroller.core.module.IFloodlightModule b/src/main/resources/META-INF/services/net.floodlightcontroller.core.module.IFloodlightModule
index a842665..dfd31ab 100644
--- a/src/main/resources/META-INF/services/net.floodlightcontroller.core.module.IFloodlightModule
+++ b/src/main/resources/META-INF/services/net.floodlightcontroller.core.module.IFloodlightModule
@@ -1,6 +1,5 @@
net.floodlightcontroller.core.FloodlightProvider
net.onrc.onos.ofcontroller.floodlightlistener.NetworkGraphPublisher
-net.floodlightcontroller.devicemanager.internal.DeviceManagerImpl
net.onrc.onos.ofcontroller.linkdiscovery.internal.LinkDiscoveryManager
net.floodlightcontroller.topology.TopologyManager
net.floodlightcontroller.forwarding.Forwarding
@@ -21,3 +20,4 @@
net.onrc.onos.ofcontroller.forwarding.Forwarding
net.onrc.onos.ofcontroller.proxyarp.ProxyArpManager
net.onrc.onos.ofcontroller.core.config.DefaultConfiguration
+net.onrc.onos.ofcontroller.devicemanager.OnosDeviceManager