@Override @LogMessageDoc( level = "ERROR", message = "Unexpected decision made for this packet-in={}", explanation = "An unsupported PacketIn decision has been " + "passed to the flow programming component", recommendation = LogMessageDoc.REPORT_CONTROLLER_BUG) public Command processPacketInMessage( IOFSwitch sw, OFPacketIn pi, IRoutingDecision decision, FloodlightContext cntx) { Ethernet eth = IFloodlightProviderService.bcStore.get(cntx, IFloodlightProviderService.CONTEXT_PI_PAYLOAD); // If a decision has been made we obey it // otherwise we just forward if (decision != null) { if (log.isTraceEnabled()) { log.trace( "Forwaring decision={} was made for PacketIn={}", decision.getRoutingAction().toString(), pi); } switch (decision.getRoutingAction()) { case NONE: // don't do anything return Command.CONTINUE; case FORWARD_OR_FLOOD: case FORWARD: doForwardFlow(sw, pi, cntx, false); return Command.CONTINUE; case MULTICAST: // treat as broadcast doFlood(sw, pi, cntx); return Command.CONTINUE; case DROP: doDropFlow(sw, pi, decision, cntx); return Command.CONTINUE; default: log.error( "Unexpected decision made for this packet-in={}", pi, decision.getRoutingAction()); return Command.CONTINUE; } } else { if (log.isTraceEnabled()) { log.trace("No decision was made for PacketIn={}, forwarding", pi); } if (eth.isBroadcast() || eth.isMulticast()) { // For now we treat multicast as broadcast doFlood(sw, pi, cntx); } else { doForwardFlow(sw, pi, cntx, false); } } return Command.CONTINUE; }
@LogMessageDoc( level = "ERROR", message = "Failure writing drop flow mod", explanation = "An I/O error occured while trying to write a " + "drop flow mod to a switch", recommendation = LogMessageDoc.CHECK_SWITCH) protected void doDropFlow( IOFSwitch sw, OFPacketIn pi, IRoutingDecision decision, FloodlightContext cntx) { // initialize match structure and populate it using the packet OFMatch match = new OFMatch(); match.loadFromPacket(pi.getPacketData(), pi.getInPort()); if (decision.getWildcards() != null) { match.setWildcards(decision.getWildcards()); } // Create flow-mod based on packet-in and src-switch OFFlowMod fm = (OFFlowMod) floodlightProvider.getOFMessageFactory().getMessage(OFType.FLOW_MOD); List<OFAction> actions = new ArrayList<OFAction>(); // Set no action to // drop long cookie = AppCookie.makeCookie(FORWARDING_APP_ID, 0); fm.setCookie(cookie) .setHardTimeout((short) 0) .setIdleTimeout((short) 5) .setBufferId(OFPacketOut.BUFFER_ID_NONE) .setMatch(match) .setActions(actions) .setLengthU(OFFlowMod.MINIMUM_LENGTH); // +OFActionOutput.MINIMUM_LENGTH); try { if (log.isDebugEnabled()) { log.debug("write drop flow-mod sw={} match={} flow-mod={}", new Object[] {sw, match, fm}); } messageDamper.write(sw, fm, cntx); } catch (IOException e) { log.error("Failure writing drop flow mod", e); } }
protected void doForwardFlow(IOFSwitch sw, OFPacketIn pi, FloodlightContext cntx) { // Setup fields for our packets OFMatch match = new OFMatch(); match.loadFromPacket(pi.getPacketData(), pi.getInPort()); // Check if we have the location of the destination IDevice dstDevice = IDeviceService.fcStore.get(cntx, IDeviceService.CONTEXT_DST_DEVICE); if (dstDevice != null) { IDevice srcDevice = IDeviceService.fcStore.get(cntx, IDeviceService.CONTEXT_SRC_DEVICE); Long srcIsland = topology.getL2DomainId(sw.getId()); if (srcDevice == null) { log.debug("No device entry found for source device"); return; } if (srcIsland == null) { log.debug("No openflow island found for source {}/{}", sw.getStringId(), pi.getInPort()); return; } // Validate that we have a destination known on the same // island // Validate that the source and destination are not on // the same switchport boolean on_same_island = false; boolean on_same_if = false; for (SwitchPort dstDap : dstDevice.getAttachmentPoints()) { long dstSwDpid = dstDap.getSwitchDPID(); Long dstIsland = topology.getL2DomainId(dstSwDpid); if ((dstIsland != null) && dstIsland.equals(srcIsland)) { on_same_island = true; if ((sw.getId() == dstSwDpid) && (pi.getInPort() == dstDap.getPort())) { on_same_if = true; } break; } } if (!on_same_island) { // Flood since we don't know the dst device if (log.isTraceEnabled()) { log.trace( "No first hop island found for destination " + "device {}, Action = flooding", dstDevice); } doFlood(sw, pi, cntx); return; } if (on_same_if) { if (log.isTraceEnabled()) { log.trace( "Both source and destination are on the same " + "switch/port {}/{}, Action = NOP", sw.toString(), pi.getInPort()); } return; } // Install all the routes where both src and dst have // attachment // points. Since the lists are stored in sorted order we // can // traverse the attachment points in O(m+n) time SwitchPort[] srcDaps = srcDevice.getAttachmentPoints(); Arrays.sort(srcDaps, clusterIdComparator); SwitchPort[] dstDaps = dstDevice.getAttachmentPoints(); Arrays.sort(dstDaps, clusterIdComparator); int iSrcDaps = 0, iDstDaps = 0; while ((iSrcDaps < srcDaps.length) && (iDstDaps < dstDaps.length)) { SwitchPort srcDap = srcDaps[iSrcDaps]; SwitchPort dstDap = dstDaps[iDstDaps]; Long srcCluster = topology.getL2DomainId(srcDap.getSwitchDPID()); Long dstCluster = topology.getL2DomainId(dstDap.getSwitchDPID()); int srcVsDest = srcCluster.compareTo(dstCluster); if (srcVsDest == 0) { if (!srcDap.equals(dstDap) && (srcCluster != null) && (dstCluster != null)) { // TODO: INSERT DIJKSTRA HERE FOR OUR VIDEO FLOWS // AND CALCULATE FLOWS // Call getroute also with weights!! Route route = getRoute( srcDap.getSwitchDPID(), (short) srcDap.getPort(), dstDap.getSwitchDPID(), (short) dstDap.getPort()); if (route != null) { if (log.isTraceEnabled()) { log.trace( "pushRoute match={} route={} " + "destination={}:{}", new Object[] {match, route, dstDap.getSwitchDPID(), dstDap.getPort()}); } long cookie = AppCookie.makeCookie(FORWARDING_APP_ID, 0); // if there is prior routing decision // use wildcard Integer wildcard_hints = null; IRoutingDecision decision = null; if (cntx != null) { decision = IRoutingDecision.rtStore.get(cntx, IRoutingDecision.CONTEXT_DECISION); } if (decision != null) { wildcard_hints = decision.getWildcards(); } else { // L2 only wildcard if there is no // prior route decision wildcard_hints = ((Integer) sw.getAttribute(IOFSwitch.PROP_FASTWILDCARDS)).intValue() & ~OFMatch.OFPFW_IN_PORT & ~OFMatch.OFPFW_DL_VLAN & ~OFMatch.OFPFW_DL_SRC & ~OFMatch.OFPFW_DL_DST & ~OFMatch.OFPFW_NW_SRC_MASK & ~OFMatch.OFPFW_NW_DST_MASK; } pushRoute( route, match, wildcard_hints, pi, sw.getId(), cookie, cntx, false, false, OFFlowMod.OFPFC_ADD); } } iSrcDaps++; iDstDaps++; } else if (srcVsDest < 0) { iSrcDaps++; } else { iDstDaps++; } } } else { // Flood since we don't know the dst device doFlood(sw, pi, cntx); } }