Fix checkstyle whitespace issues - WHITESPACE ONLY
Change-Id: Ic205c1afd639c6008d61d9de95cb764eeb6238ca
diff --git a/src/main/java/net/onrc/onos/apps/forwarding/Forwarding.java b/src/main/java/net/onrc/onos/apps/forwarding/Forwarding.java
index bdafdcd..2ed8ba5 100644
--- a/src/main/java/net/onrc/onos/apps/forwarding/Forwarding.java
+++ b/src/main/java/net/onrc/onos/apps/forwarding/Forwarding.java
@@ -62,529 +62,526 @@
import com.google.common.collect.ListMultimap;
public class Forwarding implements IOFMessageListener, IFloodlightModule,
- IForwardingService, IEventChannelListener<Long, IntentStateList> {
- private final static Logger log = LoggerFactory.getLogger(Forwarding.class);
-
- private final int SLEEP_TIME_FOR_DB_DEVICE_INSTALLED = 100; // milliseconds
- private final static int NUMBER_OF_THREAD_FOR_EXECUTOR = 1;
-
- private final static ScheduledExecutorService executor = Executors.newScheduledThreadPool(NUMBER_OF_THREAD_FOR_EXECUTOR);
-
- private final String callerId = "Forwarding";
-
- private IFloodlightProviderService floodlightProvider;
- private IFlowPusherService flowPusher;
- private IDatagridService datagrid;
+ IForwardingService, IEventChannelListener<Long, IntentStateList> {
+ private final static Logger log = LoggerFactory.getLogger(Forwarding.class);
- private IEventChannel<Long, BroadcastPacketOutNotification> eventChannel;
- private static final String SINGLE_PACKET_OUT_CHANNEL_NAME = "onos.forwarding.packet_out";
+ private final int SLEEP_TIME_FOR_DB_DEVICE_INSTALLED = 100; // milliseconds
+ private final static int NUMBER_OF_THREAD_FOR_EXECUTOR = 1;
- private IControllerRegistryService controllerRegistryService;
-
- private INetworkGraphService networkGraphService;
- private NetworkGraph networkGraph;
- private IPathCalcRuntimeService pathRuntime;
- private IntentMap intentMap;
-
- // TODO it seems there is a Guava collection that will time out entries.
- // We should see if this will work here.
- private Map<Path, PushedFlow> pendingFlows;
- private ListMultimap<String, PacketToPush> waitingPackets;
-
- private final Object lock = new Object();
-
- private class PacketToPush {
- public final OFPacketOut packet;
- public final long dpid;
-
- public PacketToPush(OFPacketOut packet, long dpid) {
- this.packet = packet;
- this.dpid = dpid;
- }
- }
-
- private class PushedFlow {
- public final String intentId;
- public boolean installed = false;
- public short firstOutPort;
-
- public PushedFlow(String flowId) {
- this.intentId = flowId;
- }
- }
-
- private final class Path {
- public final MACAddress srcMac;
- public final MACAddress dstMac;
-
- public Path(MACAddress srcMac, MACAddress dstMac) {
- this.srcMac = srcMac;
- this.dstMac = dstMac;
- }
-
- @Override
- public boolean equals(Object other) {
- if (!(other instanceof Path)) {
- return false;
- }
-
- Path otherPath = (Path) other;
- return srcMac.equals(otherPath.srcMac) &&
- dstMac.equals(otherPath.dstMac);
- }
-
- @Override
- public int hashCode() {
- int hash = 17;
- hash = 31 * hash + srcMac.hashCode();
- hash = 31 * hash + dstMac.hashCode();
- return hash;
- }
-
- @Override
- public String toString() {
- return "(" + srcMac + ") => (" + dstMac + ")";
- }
- }
-
- @Override
- public Collection<Class<? extends IFloodlightService>> getModuleServices() {
- List<Class<? extends IFloodlightService>> services =
- new ArrayList<Class<? extends IFloodlightService>>(1);
- services.add(IForwardingService.class);
- return services;
- }
+ private final static ScheduledExecutorService executor = Executors.newScheduledThreadPool(NUMBER_OF_THREAD_FOR_EXECUTOR);
- @Override
- public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() {
- Map<Class<? extends IFloodlightService>, IFloodlightService> impls =
- new HashMap<Class<? extends IFloodlightService>, IFloodlightService>(1);
- impls.put(IForwardingService.class, this);
- return impls;
- }
+ private final String callerId = "Forwarding";
- @Override
- public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
- List<Class<? extends IFloodlightService>> dependencies =
- new ArrayList<Class<? extends IFloodlightService>>();
- dependencies.add(IFloodlightProviderService.class);
- dependencies.add(IFlowPusherService.class);
- dependencies.add(IControllerRegistryService.class);
- dependencies.add(IOnosDeviceService.class);
- dependencies.add(IDatagridService.class);
- dependencies.add(INetworkGraphService.class);
- dependencies.add(IPathCalcRuntimeService.class);
- // We don't use the IProxyArpService directly, but reactive forwarding
- // requires it to be loaded and answering ARP requests
- dependencies.add(IProxyArpService.class);
- return dependencies;
- }
-
- @Override
- public void init(FloodlightModuleContext context) {
- floodlightProvider =
- context.getServiceImpl(IFloodlightProviderService.class);
- flowPusher = context.getServiceImpl(IFlowPusherService.class);
- datagrid = context.getServiceImpl(IDatagridService.class);
- controllerRegistryService = context.getServiceImpl(IControllerRegistryService.class);
- networkGraphService = context.getServiceImpl(INetworkGraphService.class);
+ private IFloodlightProviderService floodlightProvider;
+ private IFlowPusherService flowPusher;
+ private IDatagridService datagrid;
+
+ private IEventChannel<Long, BroadcastPacketOutNotification> eventChannel;
+ private static final String SINGLE_PACKET_OUT_CHANNEL_NAME = "onos.forwarding.packet_out";
+
+ private IControllerRegistryService controllerRegistryService;
+
+ private INetworkGraphService networkGraphService;
+ private NetworkGraph networkGraph;
+ private IPathCalcRuntimeService pathRuntime;
+ private IntentMap intentMap;
+
+ // TODO it seems there is a Guava collection that will time out entries.
+ // We should see if this will work here.
+ private Map<Path, PushedFlow> pendingFlows;
+ private ListMultimap<String, PacketToPush> waitingPackets;
+
+ private final Object lock = new Object();
+
+ private class PacketToPush {
+ public final OFPacketOut packet;
+ public final long dpid;
+
+ public PacketToPush(OFPacketOut packet, long dpid) {
+ this.packet = packet;
+ this.dpid = dpid;
+ }
+ }
+
+ private class PushedFlow {
+ public final String intentId;
+ public boolean installed = false;
+ public short firstOutPort;
+
+ public PushedFlow(String flowId) {
+ this.intentId = flowId;
+ }
+ }
+
+ private final class Path {
+ public final MACAddress srcMac;
+ public final MACAddress dstMac;
+
+ public Path(MACAddress srcMac, MACAddress dstMac) {
+ this.srcMac = srcMac;
+ this.dstMac = dstMac;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (!(other instanceof Path)) {
+ return false;
+ }
+
+ Path otherPath = (Path) other;
+ return srcMac.equals(otherPath.srcMac) &&
+ dstMac.equals(otherPath.dstMac);
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 17;
+ hash = 31 * hash + srcMac.hashCode();
+ hash = 31 * hash + dstMac.hashCode();
+ return hash;
+ }
+
+ @Override
+ public String toString() {
+ return "(" + srcMac + ") => (" + dstMac + ")";
+ }
+ }
+
+ @Override
+ public Collection<Class<? extends IFloodlightService>> getModuleServices() {
+ List<Class<? extends IFloodlightService>> services =
+ new ArrayList<Class<? extends IFloodlightService>>(1);
+ services.add(IForwardingService.class);
+ return services;
+ }
+
+ @Override
+ public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() {
+ Map<Class<? extends IFloodlightService>, IFloodlightService> impls =
+ new HashMap<Class<? extends IFloodlightService>, IFloodlightService>(1);
+ impls.put(IForwardingService.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);
+ dependencies.add(IFlowPusherService.class);
+ dependencies.add(IControllerRegistryService.class);
+ dependencies.add(IOnosDeviceService.class);
+ dependencies.add(IDatagridService.class);
+ dependencies.add(INetworkGraphService.class);
+ dependencies.add(IPathCalcRuntimeService.class);
+ // We don't use the IProxyArpService directly, but reactive forwarding
+ // requires it to be loaded and answering ARP requests
+ dependencies.add(IProxyArpService.class);
+ return dependencies;
+ }
+
+ @Override
+ public void init(FloodlightModuleContext context) {
+ floodlightProvider =
+ context.getServiceImpl(IFloodlightProviderService.class);
+ flowPusher = context.getServiceImpl(IFlowPusherService.class);
+ datagrid = context.getServiceImpl(IDatagridService.class);
+ controllerRegistryService = context.getServiceImpl(IControllerRegistryService.class);
+ networkGraphService = context.getServiceImpl(INetworkGraphService.class);
pathRuntime = context.getServiceImpl(IPathCalcRuntimeService.class);
-
- floodlightProvider.addOFMessageListener(OFType.PACKET_IN, this);
- pendingFlows = new HashMap<Path, PushedFlow>();
- waitingPackets = LinkedListMultimap.create();
- }
-
- @Override
- public void startUp(FloodlightModuleContext context) {
+ floodlightProvider.addOFMessageListener(OFType.PACKET_IN, this);
- eventChannel = datagrid.createChannel(SINGLE_PACKET_OUT_CHANNEL_NAME,
- Long.class,
- BroadcastPacketOutNotification.class);
- networkGraph = networkGraphService.getNetworkGraph();
- intentMap = pathRuntime.getPathIntents();
- datagrid.addListener("onos.pathintent_state", this, Long.class, IntentStateList.class);
- }
+ pendingFlows = new HashMap<Path, PushedFlow>();
+ waitingPackets = LinkedListMultimap.create();
+ }
- @Override
- public String getName() {
- return "onosforwarding";
- }
+ @Override
+ public void startUp(FloodlightModuleContext context) {
- @Override
- public boolean isCallbackOrderingPrereq(OFType type, String name) {
- return (type == OFType.PACKET_IN) &&
- (name.equals("devicemanager") || name.equals("proxyarpmanager")
- || name.equals("onosdevicemanager"));
- }
+ eventChannel = datagrid.createChannel(SINGLE_PACKET_OUT_CHANNEL_NAME,
+ Long.class,
+ BroadcastPacketOutNotification.class);
+ networkGraph = networkGraphService.getNetworkGraph();
+ intentMap = pathRuntime.getPathIntents();
+ datagrid.addListener("onos.pathintent_state", this, Long.class, IntentStateList.class);
+ }
- @Override
- public boolean isCallbackOrderingPostreq(OFType type, String name) {
- return false;
- }
+ @Override
+ public String getName() {
+ return "onosforwarding";
+ }
- @Override
- public Command receive(
- IOFSwitch sw, OFMessage msg, FloodlightContext cntx) {
-
- if (msg.getType() != OFType.PACKET_IN) {
- return Command.CONTINUE;
- }
-
- OFPacketIn pi = (OFPacketIn) msg;
-
- Ethernet eth = IFloodlightProviderService.bcStore.
- get(cntx, IFloodlightProviderService.CONTEXT_PI_PAYLOAD);
-
- log.debug("Receive PACKET_IN swId {}, portId {}", sw.getId(), pi.getInPort());
-
- if (eth.getEtherType() != Ethernet.TYPE_IPv4) {
- return Command.CONTINUE;
- }
-
- if (eth.isBroadcast() || eth.isMulticast()) {
- handleBroadcast(sw, pi, eth);
- }
- else {
- // Unicast
- handlePacketIn(sw, pi, eth);
- }
-
- return Command.STOP;
- }
-
- private void handleBroadcast(IOFSwitch sw, OFPacketIn pi, Ethernet eth) {
- if (log.isTraceEnabled()) {
- log.trace("Sending broadcast packet to other ONOS instances");
- }
+ @Override
+ public boolean isCallbackOrderingPrereq(OFType type, String name) {
+ return (type == OFType.PACKET_IN) &&
+ (name.equals("devicemanager") || name.equals("proxyarpmanager")
+ || name.equals("onosdevicemanager"));
+ }
- //We don't use address information, so 0 is put into the third argument.
- BroadcastPacketOutNotification key =
- new BroadcastPacketOutNotification(
- eth.serialize(),
- 0, sw.getId(),
- pi.getInPort());
- eventChannel.addTransientEntry(eth.getDestinationMAC().toLong(), key);
- }
-
- private void handlePacketIn(IOFSwitch sw, OFPacketIn pi, Ethernet eth){
- log.debug("Start handlePacketIn swId {}, portId {}", sw.getId(), pi.getInPort());
+ @Override
+ public boolean isCallbackOrderingPostreq(OFType type, String name) {
+ return false;
+ }
- String destinationMac =
- HexString.toHexString(eth.getDestinationMACAddress());
-
- //FIXME getDeviceByMac() is a blocking call, so it may be better way to handle it to avoid the condition.
- Device deviceObject = networkGraph.getDeviceByMac(MACAddress.valueOf(destinationMac));
+ @Override
+ public Command receive(
+ IOFSwitch sw, OFMessage msg, FloodlightContext cntx) {
- if (deviceObject == null) {
- log.debug("No device entry found for {}",
- destinationMac);
+ if (msg.getType() != OFType.PACKET_IN) {
+ return Command.CONTINUE;
+ }
- //Device is not in the DB, so wait it until the device is added.
- executor.schedule(new WaitDeviceArp(sw, pi, eth), SLEEP_TIME_FOR_DB_DEVICE_INSTALLED, TimeUnit.MILLISECONDS);
- return;
- }
+ OFPacketIn pi = (OFPacketIn) msg;
- continueHandlePacketIn(sw, pi, eth, deviceObject);
- }
-
- private class WaitDeviceArp implements Runnable {
- IOFSwitch sw;
- OFPacketIn pi;
- Ethernet eth;
+ Ethernet eth = IFloodlightProviderService.bcStore.
+ get(cntx, IFloodlightProviderService.CONTEXT_PI_PAYLOAD);
- public WaitDeviceArp(IOFSwitch sw, OFPacketIn pi, Ethernet eth) {
- super();
- this.sw = sw;
- this.pi = pi;
- this.eth = eth;
- }
+ log.debug("Receive PACKET_IN swId {}, portId {}", sw.getId(), pi.getInPort());
- @Override
- public void run() {
- Device deviceObject = networkGraph.getDeviceByMac(MACAddress.valueOf(eth.getDestinationMACAddress()));
- if(deviceObject == null){
- log.debug("wait {}ms and device was not found. Send broadcast packet and the thread finish.", SLEEP_TIME_FOR_DB_DEVICE_INSTALLED);
- handleBroadcast(sw, pi, eth);
- return;
- }
- log.debug("wait {}ms and device {} was found, continue",SLEEP_TIME_FOR_DB_DEVICE_INSTALLED, deviceObject.getMacAddress());
- continueHandlePacketIn(sw, pi, eth, deviceObject);
- }
- }
+ if (eth.getEtherType() != Ethernet.TYPE_IPv4) {
+ return Command.CONTINUE;
+ }
- private void continueHandlePacketIn(IOFSwitch sw, OFPacketIn pi, Ethernet eth, Device deviceObject) {
+ if (eth.isBroadcast() || eth.isMulticast()) {
+ handleBroadcast(sw, pi, eth);
+ } else {
+ // Unicast
+ handlePacketIn(sw, pi, eth);
+ }
- log.debug("Start continuehandlePacketIn");
-
- //Iterator<IPortObject> ports = deviceObject.getAttachedPorts().iterator();
- Iterator<net.onrc.onos.core.topology.Port> ports = deviceObject.getAttachmentPoints().iterator();
- if (!ports.hasNext()) {
- log.debug("No attachment point found for device {} - broadcasting packet",
- deviceObject.getMacAddress());
- handleBroadcast(sw, pi, eth);
- return;
- }
+ return Command.STOP;
+ }
- //This code assumes the device has only one port. It should be problem.
- net.onrc.onos.core.topology.Port portObject = ports.next();
- short destinationPort = portObject.getNumber().shortValue();
- Switch switchObject = portObject.getSwitch();
- long destinationDpid = switchObject.getDpid();
-
- // TODO SwitchPort, Dpid and Port should probably be immutable
- SwitchPort srcSwitchPort = new SwitchPort(
- new Dpid(sw.getId()), new Port(pi.getInPort()));
- SwitchPort dstSwitchPort = new SwitchPort(
- new Dpid(destinationDpid), new Port(destinationPort));
-
- MACAddress srcMacAddress = MACAddress.valueOf(eth.getSourceMACAddress());
- MACAddress dstMacAddress = MACAddress.valueOf(eth.getDestinationMACAddress());
-
- synchronized (lock) {
- //TODO check concurrency
- Path pathspec = new Path(srcMacAddress, dstMacAddress);
- PushedFlow existingFlow = pendingFlows.get(pathspec);
+ private void handleBroadcast(IOFSwitch sw, OFPacketIn pi, Ethernet eth) {
+ if (log.isTraceEnabled()) {
+ log.trace("Sending broadcast packet to other ONOS instances");
+ }
- //A path is installed side by side to reduce a path timeout and a wrong state.
- if (existingFlow != null) {
- // We've already start to install a flow for this pair of MAC addresses
- if(log.isDebugEnabled()) {
- log.debug("Found existing the same pathspec {}, intent ID is {}",
- pathspec,
- existingFlow.intentId);
- }
-
- OFPacketOut po = constructPacketOut(pi, sw);
-
- // Find the correct port here. We just assume the PI is from
- // the first hop switch, but this is definitely not always
- // the case. We'll have to retrieve the flow from HZ every time
- // because it could change (be rerouted) sometimes.
- if (existingFlow.installed) {
- // Flow has been sent to the switches so it is safe to
- // send a packet out now
+ //We don't use address information, so 0 is put into the third argument.
+ BroadcastPacketOutNotification key =
+ new BroadcastPacketOutNotification(
+ eth.serialize(),
+ 0, sw.getId(),
+ pi.getInPort());
+ eventChannel.addTransientEntry(eth.getDestinationMAC().toLong(), key);
+ }
- Intent intent = intentMap.getIntent(existingFlow.intentId);
- PathIntent pathIntent = null;
- if(intent instanceof PathIntent) {
- pathIntent = (PathIntent)intent;
- } else {
- log.debug("Intent {} is not PathIntent. Return.", intent.getId());
- return;
- }
-
- Boolean isflowEntryForThisSwitch = false;
- net.onrc.onos.core.topology.Path path = pathIntent.getPath();
+ private void handlePacketIn(IOFSwitch sw, OFPacketIn pi, Ethernet eth) {
+ log.debug("Start handlePacketIn swId {}, portId {}", sw.getId(), pi.getInPort());
- for(Iterator<LinkEvent> i = path.iterator(); i.hasNext();) {
- LinkEvent le = (LinkEvent)i.next();
- if(le.getSrc().dpid == sw.getId()) {
- log.debug("src {} dst {}", le.getSrc(), le.getDst());
- isflowEntryForThisSwitch = true;
- break;
- }
- }
-
- if (isflowEntryForThisSwitch == false) {
- // If we don't find a flow entry for that switch, then we're
- // in the middle of a rerouting (or something's gone wrong).
- // This packet will be dropped as a victim of the rerouting.
- log.debug("Dropping packet on flow {} between {}-{}",
- existingFlow.intentId,
- srcMacAddress, dstMacAddress);
- } else {
- log.debug("Sending packet out from sw {}, outport{}", sw, existingFlow.firstOutPort);
- sendPacketOut(sw, po, existingFlow.firstOutPort);
- }
- }
- else {
- // Flow path has not yet been installed to switches so save the
- // packet out for later
- log.debug("Put a packet into the waitng list. flowId {}", existingFlow.intentId);
- waitingPackets.put(existingFlow.intentId, new PacketToPush(po, sw.getId()));
- }
- return;
- }
+ String destinationMac =
+ HexString.toHexString(eth.getDestinationMACAddress());
- log.debug("Adding new flow between {} at {} and {} at {}",
- new Object[]{srcMacAddress, srcSwitchPort, dstMacAddress, dstSwitchPort});
-
- String intentId = callerId + ":" + controllerRegistryService.getNextUniqueId();
- IntentOperationList operations = new IntentOperationList();
- ShortestPathIntent intent = new ShortestPathIntent(intentId,
- sw.getId(), pi.getInPort(), srcMacAddress.toLong(),
- destinationDpid, destinationPort, dstMacAddress.toLong());
- IntentOperation.Operator operator = IntentOperation.Operator.ADD;
- operations.add(operator, intent);
- pathRuntime.executeIntentOperations(operations);
+ //FIXME getDeviceByMac() is a blocking call, so it may be better way to handle it to avoid the condition.
+ Device deviceObject = networkGraph.getDeviceByMac(MACAddress.valueOf(destinationMac));
- OFPacketOut po = constructPacketOut(pi, sw);
-
- // Add to waiting lists
- pendingFlows.put(pathspec, new PushedFlow(intentId));
- log.debug("Put a Path {} in the pending flow, intent ID {}", pathspec, intentId);
- waitingPackets.put(intentId, new PacketToPush(po, sw.getId()));
- log.debug("Put a Packet in the wating list. related pathspec {}", pathspec);
-
- }
- }
+ if (deviceObject == null) {
+ log.debug("No device entry found for {}",
+ destinationMac);
- private OFPacketOut constructPacketOut(OFPacketIn pi, IOFSwitch sw) {
- OFPacketOut po = new OFPacketOut();
- po.setInPort(OFPort.OFPP_NONE)
- .setInPort(pi.getInPort())
- .setActions(new ArrayList<OFAction>())
- .setLengthU(OFPacketOut.MINIMUM_LENGTH);
-
- if (sw.getBuffers() == 0) {
- po.setBufferId(OFPacketOut.BUFFER_ID_NONE)
- .setPacketData(pi.getPacketData())
- .setLengthU(po.getLengthU() + po.getPacketData().length);
- }
- else {
- po.setBufferId(pi.getBufferId());
- }
-
- return po;
- }
+ //Device is not in the DB, so wait it until the device is added.
+ executor.schedule(new WaitDeviceArp(sw, pi, eth), SLEEP_TIME_FOR_DB_DEVICE_INSTALLED, TimeUnit.MILLISECONDS);
+ return;
+ }
- @Override
- public void flowsInstalled(Collection<FlowPath> installedFlowPaths) {
- }
-
- @Override
- public void flowRemoved(FlowPath removedFlowPath) {
- }
-
- public void flowRemoved(PathIntent removedIntent) {
- if(log.isTraceEnabled()){
- log.trace("Path {} was removed", removedIntent.getParentIntent().getId());
- }
+ continueHandlePacketIn(sw, pi, eth, deviceObject);
+ }
- ShortestPathIntent spfIntent = (ShortestPathIntent) removedIntent.getParentIntent();
- MACAddress srcMacAddress = MACAddress.valueOf(spfIntent.getSrcMac());
- MACAddress dstMacAddress = MACAddress.valueOf(spfIntent.getDstMac());
- Path removedPath = new Path(srcMacAddress, dstMacAddress);
-
- synchronized (lock) {
- // There *shouldn't* be any packets queued if the flow has
- // just been removed.
- List<PacketToPush> packets = waitingPackets.removeAll(spfIntent.getId());
- if (!packets.isEmpty()) {
- log.warn("Removed flow {} has packets queued.", spfIntent.getId());
- }
- pendingFlows.remove(removedPath);
- log.debug("Removed from the pendingFlow: Path {}, Flow ID {}", removedPath, spfIntent.getId());
- }
- }
-
- private void flowInstalled(PathIntent installedPath) {
- if(log.isTraceEnabled()){
- log.trace("Path {} was installed", installedPath.getParentIntent().getId());
- }
-
- ShortestPathIntent spfIntent = (ShortestPathIntent) installedPath.getParentIntent();
- MACAddress srcMacAddress = MACAddress.valueOf(spfIntent.getSrcMac());
- MACAddress dstMacAddress = MACAddress.valueOf(spfIntent.getDstMac());
- Path path = new Path(srcMacAddress, dstMacAddress);
- log.debug("Path spec {}", path);
-
- // TODO waiting packets should time out. We could request a path that
- // can't be installed right now because of a network partition. The path
- // may eventually be installed, but we may have received thousands of
- // packets in the meantime and probably don't want to send very old packets.
-
- List<PacketToPush> packets = null;
- net.onrc.onos.core.topology.Path graphPath = installedPath.getPath();
-
- log.debug("path{}", graphPath);
- Short outPort = graphPath.get(0).getSrc().getNumber().shortValue();
-
- PushedFlow existingFlow = null;
-
- synchronized (lock) {
- existingFlow = pendingFlows.get(path);
+ private class WaitDeviceArp implements Runnable {
+ IOFSwitch sw;
+ OFPacketIn pi;
+ Ethernet eth;
- if (existingFlow != null) {
- existingFlow.installed = true;
- existingFlow.firstOutPort = outPort;
- } else {
- log.debug("ExistingFlow {} is null", path);
- return;
- }
+ public WaitDeviceArp(IOFSwitch sw, OFPacketIn pi, Ethernet eth) {
+ super();
+ this.sw = sw;
+ this.pi = pi;
+ this.eth = eth;
+ }
- //Check both existing flow are installed status.
- if(existingFlow.installed){
- packets = waitingPackets.removeAll(existingFlow.intentId);
- if(log.isDebugEnabled()){
- log.debug("removed my packets {} to push from waitingPackets. outPort {} size {}",
- existingFlow.intentId, existingFlow.firstOutPort, packets.size());
- }
- }else{
- log.debug("Forward or reverse flows hasn't been pushed yet. return");
- return;
- }
- }
-
- for (PacketToPush packet : packets) {
- log.debug("Start packetToPush to sw {}, outPort {}, path {}", packet.dpid, existingFlow.firstOutPort, path);
- IOFSwitch sw = floodlightProvider.getSwitches().get(packet.dpid);
- sendPacketOut(sw, packet.packet, existingFlow.firstOutPort);
- }
- }
-
- private void sendPacketOut(IOFSwitch sw, OFPacketOut po, short outPort) {
- po.getActions().add(new OFActionOutput(outPort));
- po.setActionsLength((short)
- (po.getActionsLength() + OFActionOutput.MINIMUM_LENGTH));
- po.setLengthU(po.getLengthU() + OFActionOutput.MINIMUM_LENGTH);
-
- flowPusher.add(sw, po);
- }
+ @Override
+ public void run() {
+ Device deviceObject = networkGraph.getDeviceByMac(MACAddress.valueOf(eth.getDestinationMACAddress()));
+ if (deviceObject == null) {
+ log.debug("wait {}ms and device was not found. Send broadcast packet and the thread finish.", SLEEP_TIME_FOR_DB_DEVICE_INSTALLED);
+ handleBroadcast(sw, pi, eth);
+ return;
+ }
+ log.debug("wait {}ms and device {} was found, continue", SLEEP_TIME_FOR_DB_DEVICE_INSTALLED, deviceObject.getMacAddress());
+ continueHandlePacketIn(sw, pi, eth, deviceObject);
+ }
+ }
- @Override
- public void entryAdded(IntentStateList value) {
- entryUpdated(value);
-
- }
+ private void continueHandlePacketIn(IOFSwitch sw, OFPacketIn pi, Ethernet eth, Device deviceObject) {
- @Override
- public void entryRemoved(IntentStateList value) {
- //no-op
- }
+ log.debug("Start continuehandlePacketIn");
- @Override
- public void entryUpdated(IntentStateList value) {
- for (Entry<String, IntentState> entry: value.entrySet()) {
- log.debug("path intent key {}, value {}", entry.getKey(), entry.getValue());
- PathIntent pathIntent = (PathIntent) intentMap.getIntent(entry.getKey());
- if (pathIntent == null)
- continue;
-
- if (!(pathIntent.getParentIntent() instanceof ShortestPathIntent))
- continue;
+ //Iterator<IPortObject> ports = deviceObject.getAttachedPorts().iterator();
+ Iterator<net.onrc.onos.core.topology.Port> ports = deviceObject.getAttachmentPoints().iterator();
+ if (!ports.hasNext()) {
+ log.debug("No attachment point found for device {} - broadcasting packet",
+ deviceObject.getMacAddress());
+ handleBroadcast(sw, pi, eth);
+ return;
+ }
- IntentState state = entry.getValue();
- switch (state) {
- case INST_REQ:
- break;
- case INST_ACK:
- flowInstalled(pathIntent);
- break;
- case INST_NACK:
- break;
- case DEL_REQ:
- break;
- case DEL_ACK:
- flowRemoved(pathIntent);
- break;
- case DEL_PENDING:
- break;
- default:
- break;
- }
- }
- }
+ //This code assumes the device has only one port. It should be problem.
+ net.onrc.onos.core.topology.Port portObject = ports.next();
+ short destinationPort = portObject.getNumber().shortValue();
+ Switch switchObject = portObject.getSwitch();
+ long destinationDpid = switchObject.getDpid();
+
+ // TODO SwitchPort, Dpid and Port should probably be immutable
+ SwitchPort srcSwitchPort = new SwitchPort(
+ new Dpid(sw.getId()), new Port(pi.getInPort()));
+ SwitchPort dstSwitchPort = new SwitchPort(
+ new Dpid(destinationDpid), new Port(destinationPort));
+
+ MACAddress srcMacAddress = MACAddress.valueOf(eth.getSourceMACAddress());
+ MACAddress dstMacAddress = MACAddress.valueOf(eth.getDestinationMACAddress());
+
+ synchronized (lock) {
+ //TODO check concurrency
+ Path pathspec = new Path(srcMacAddress, dstMacAddress);
+ PushedFlow existingFlow = pendingFlows.get(pathspec);
+
+ //A path is installed side by side to reduce a path timeout and a wrong state.
+ if (existingFlow != null) {
+ // We've already start to install a flow for this pair of MAC addresses
+ if (log.isDebugEnabled()) {
+ log.debug("Found existing the same pathspec {}, intent ID is {}",
+ pathspec,
+ existingFlow.intentId);
+ }
+
+ OFPacketOut po = constructPacketOut(pi, sw);
+
+ // Find the correct port here. We just assume the PI is from
+ // the first hop switch, but this is definitely not always
+ // the case. We'll have to retrieve the flow from HZ every time
+ // because it could change (be rerouted) sometimes.
+ if (existingFlow.installed) {
+ // Flow has been sent to the switches so it is safe to
+ // send a packet out now
+
+ Intent intent = intentMap.getIntent(existingFlow.intentId);
+ PathIntent pathIntent = null;
+ if (intent instanceof PathIntent) {
+ pathIntent = (PathIntent) intent;
+ } else {
+ log.debug("Intent {} is not PathIntent. Return.", intent.getId());
+ return;
+ }
+
+ Boolean isflowEntryForThisSwitch = false;
+ net.onrc.onos.core.topology.Path path = pathIntent.getPath();
+
+ for (Iterator<LinkEvent> i = path.iterator(); i.hasNext(); ) {
+ LinkEvent le = (LinkEvent) i.next();
+ if (le.getSrc().dpid == sw.getId()) {
+ log.debug("src {} dst {}", le.getSrc(), le.getDst());
+ isflowEntryForThisSwitch = true;
+ break;
+ }
+ }
+
+ if (isflowEntryForThisSwitch == false) {
+ // If we don't find a flow entry for that switch, then we're
+ // in the middle of a rerouting (or something's gone wrong).
+ // This packet will be dropped as a victim of the rerouting.
+ log.debug("Dropping packet on flow {} between {}-{}",
+ existingFlow.intentId,
+ srcMacAddress, dstMacAddress);
+ } else {
+ log.debug("Sending packet out from sw {}, outport{}", sw, existingFlow.firstOutPort);
+ sendPacketOut(sw, po, existingFlow.firstOutPort);
+ }
+ } else {
+ // Flow path has not yet been installed to switches so save the
+ // packet out for later
+ log.debug("Put a packet into the waitng list. flowId {}", existingFlow.intentId);
+ waitingPackets.put(existingFlow.intentId, new PacketToPush(po, sw.getId()));
+ }
+ return;
+ }
+
+ log.debug("Adding new flow between {} at {} and {} at {}",
+ new Object[]{srcMacAddress, srcSwitchPort, dstMacAddress, dstSwitchPort});
+
+ String intentId = callerId + ":" + controllerRegistryService.getNextUniqueId();
+ IntentOperationList operations = new IntentOperationList();
+ ShortestPathIntent intent = new ShortestPathIntent(intentId,
+ sw.getId(), pi.getInPort(), srcMacAddress.toLong(),
+ destinationDpid, destinationPort, dstMacAddress.toLong());
+ IntentOperation.Operator operator = IntentOperation.Operator.ADD;
+ operations.add(operator, intent);
+ pathRuntime.executeIntentOperations(operations);
+
+ OFPacketOut po = constructPacketOut(pi, sw);
+
+ // Add to waiting lists
+ pendingFlows.put(pathspec, new PushedFlow(intentId));
+ log.debug("Put a Path {} in the pending flow, intent ID {}", pathspec, intentId);
+ waitingPackets.put(intentId, new PacketToPush(po, sw.getId()));
+ log.debug("Put a Packet in the wating list. related pathspec {}", pathspec);
+
+ }
+ }
+
+ private OFPacketOut constructPacketOut(OFPacketIn pi, IOFSwitch sw) {
+ OFPacketOut po = new OFPacketOut();
+ po.setInPort(OFPort.OFPP_NONE)
+ .setInPort(pi.getInPort())
+ .setActions(new ArrayList<OFAction>())
+ .setLengthU(OFPacketOut.MINIMUM_LENGTH);
+
+ if (sw.getBuffers() == 0) {
+ po.setBufferId(OFPacketOut.BUFFER_ID_NONE)
+ .setPacketData(pi.getPacketData())
+ .setLengthU(po.getLengthU() + po.getPacketData().length);
+ } else {
+ po.setBufferId(pi.getBufferId());
+ }
+
+ return po;
+ }
+
+ @Override
+ public void flowsInstalled(Collection<FlowPath> installedFlowPaths) {
+ }
+
+ @Override
+ public void flowRemoved(FlowPath removedFlowPath) {
+ }
+
+ public void flowRemoved(PathIntent removedIntent) {
+ if (log.isTraceEnabled()) {
+ log.trace("Path {} was removed", removedIntent.getParentIntent().getId());
+ }
+
+ ShortestPathIntent spfIntent = (ShortestPathIntent) removedIntent.getParentIntent();
+ MACAddress srcMacAddress = MACAddress.valueOf(spfIntent.getSrcMac());
+ MACAddress dstMacAddress = MACAddress.valueOf(spfIntent.getDstMac());
+ Path removedPath = new Path(srcMacAddress, dstMacAddress);
+
+ synchronized (lock) {
+ // There *shouldn't* be any packets queued if the flow has
+ // just been removed.
+ List<PacketToPush> packets = waitingPackets.removeAll(spfIntent.getId());
+ if (!packets.isEmpty()) {
+ log.warn("Removed flow {} has packets queued.", spfIntent.getId());
+ }
+ pendingFlows.remove(removedPath);
+ log.debug("Removed from the pendingFlow: Path {}, Flow ID {}", removedPath, spfIntent.getId());
+ }
+ }
+
+ private void flowInstalled(PathIntent installedPath) {
+ if (log.isTraceEnabled()) {
+ log.trace("Path {} was installed", installedPath.getParentIntent().getId());
+ }
+
+ ShortestPathIntent spfIntent = (ShortestPathIntent) installedPath.getParentIntent();
+ MACAddress srcMacAddress = MACAddress.valueOf(spfIntent.getSrcMac());
+ MACAddress dstMacAddress = MACAddress.valueOf(spfIntent.getDstMac());
+ Path path = new Path(srcMacAddress, dstMacAddress);
+ log.debug("Path spec {}", path);
+
+ // TODO waiting packets should time out. We could request a path that
+ // can't be installed right now because of a network partition. The path
+ // may eventually be installed, but we may have received thousands of
+ // packets in the meantime and probably don't want to send very old packets.
+
+ List<PacketToPush> packets = null;
+ net.onrc.onos.core.topology.Path graphPath = installedPath.getPath();
+
+ log.debug("path{}", graphPath);
+ Short outPort = graphPath.get(0).getSrc().getNumber().shortValue();
+
+ PushedFlow existingFlow = null;
+
+ synchronized (lock) {
+ existingFlow = pendingFlows.get(path);
+
+ if (existingFlow != null) {
+ existingFlow.installed = true;
+ existingFlow.firstOutPort = outPort;
+ } else {
+ log.debug("ExistingFlow {} is null", path);
+ return;
+ }
+
+ //Check both existing flow are installed status.
+ if (existingFlow.installed) {
+ packets = waitingPackets.removeAll(existingFlow.intentId);
+ if (log.isDebugEnabled()) {
+ log.debug("removed my packets {} to push from waitingPackets. outPort {} size {}",
+ existingFlow.intentId, existingFlow.firstOutPort, packets.size());
+ }
+ } else {
+ log.debug("Forward or reverse flows hasn't been pushed yet. return");
+ return;
+ }
+ }
+
+ for (PacketToPush packet : packets) {
+ log.debug("Start packetToPush to sw {}, outPort {}, path {}", packet.dpid, existingFlow.firstOutPort, path);
+ IOFSwitch sw = floodlightProvider.getSwitches().get(packet.dpid);
+ sendPacketOut(sw, packet.packet, existingFlow.firstOutPort);
+ }
+ }
+
+ private void sendPacketOut(IOFSwitch sw, OFPacketOut po, short outPort) {
+ po.getActions().add(new OFActionOutput(outPort));
+ po.setActionsLength((short)
+ (po.getActionsLength() + OFActionOutput.MINIMUM_LENGTH));
+ po.setLengthU(po.getLengthU() + OFActionOutput.MINIMUM_LENGTH);
+
+ flowPusher.add(sw, po);
+ }
+
+ @Override
+ public void entryAdded(IntentStateList value) {
+ entryUpdated(value);
+
+ }
+
+ @Override
+ public void entryRemoved(IntentStateList value) {
+ //no-op
+ }
+
+ @Override
+ public void entryUpdated(IntentStateList value) {
+ for (Entry<String, IntentState> entry : value.entrySet()) {
+ log.debug("path intent key {}, value {}", entry.getKey(), entry.getValue());
+ PathIntent pathIntent = (PathIntent) intentMap.getIntent(entry.getKey());
+ if (pathIntent == null)
+ continue;
+
+ if (!(pathIntent.getParentIntent() instanceof ShortestPathIntent))
+ continue;
+
+ IntentState state = entry.getValue();
+ switch (state) {
+ case INST_REQ:
+ break;
+ case INST_ACK:
+ flowInstalled(pathIntent);
+ break;
+ case INST_NACK:
+ break;
+ case DEL_REQ:
+ break;
+ case DEL_ACK:
+ flowRemoved(pathIntent);
+ break;
+ case DEL_PENDING:
+ break;
+ default:
+ break;
+ }
+ }
+ }
}
diff --git a/src/main/java/net/onrc/onos/apps/forwarding/IForwardingService.java b/src/main/java/net/onrc/onos/apps/forwarding/IForwardingService.java
index 375da88..6968999 100644
--- a/src/main/java/net/onrc/onos/apps/forwarding/IForwardingService.java
+++ b/src/main/java/net/onrc/onos/apps/forwarding/IForwardingService.java
@@ -8,26 +8,26 @@
/**
* Temporary interface that allows the Forwarding module to be
* notified when a flow has been installed.
- *
+ * <p/>
* This should be refactored to a listener framework in the future.
- * @author jono
*
+ * @author jono
*/
public interface IForwardingService extends IFloodlightService {
- /**
- * Notify the Forwarding module that a collection of flows has been
- * installed in the network.
- *
- * @param installedFlowPaths the collection of FlowPaths that have
- * been installed in the network.
- */
- public void flowsInstalled(Collection<FlowPath> installedFlowPaths);
-
- /**
- * Notify the Forwarding module that a flow has expired and been
- * removed from the network.
- *
- * @param removedFlowPath The FlowPath that was removed
- */
- public void flowRemoved(FlowPath removedFlowPath);
+ /**
+ * Notify the Forwarding module that a collection of flows has been
+ * installed in the network.
+ *
+ * @param installedFlowPaths the collection of FlowPaths that have
+ * been installed in the network.
+ */
+ public void flowsInstalled(Collection<FlowPath> installedFlowPaths);
+
+ /**
+ * Notify the Forwarding module that a flow has expired and been
+ * removed from the network.
+ *
+ * @param removedFlowPath The FlowPath that was removed
+ */
+ public void flowRemoved(FlowPath removedFlowPath);
}