/** * Creates a OFPacketOut with the OFPacketIn data that is flooded on all ports unless the port is * blocked, in which case the packet will be dropped. * * @param sw The switch that receives the OFPacketIn * @param pi The OFPacketIn that came to the switch * @param cntx The FloodlightContext associated with this OFPacketIn */ @LogMessageDoc( level = "ERROR", message = "Failure writing PacketOut " + "switch={switch} packet-in={packet-in} " + "packet-out={packet-out}", explanation = "An I/O error occured while writing a packet " + "out message to the switch", recommendation = LogMessageDoc.CHECK_SWITCH) protected void doFlood(IOFSwitch sw, OFPacketIn pi, FloodlightContext cntx) { if (topology.isIncomingBroadcastAllowed(sw.getId(), pi.getInPort()) == false) { if (log.isTraceEnabled()) { log.trace( "doFlood, drop broadcast packet, pi={}, " + "from a blocked port, srcSwitch=[{},{}], linkInfo={}", new Object[] {pi, sw.getId(), pi.getInPort()}); } return; } // Set Action to flood OFPacketOut po = (OFPacketOut) floodlightProvider.getOFMessageFactory().getMessage(OFType.PACKET_OUT); List<OFAction> actions = new ArrayList<OFAction>(); if (sw.hasAttribute(IOFSwitch.PROP_SUPPORTS_OFPP_FLOOD)) { actions.add(new OFActionOutput(OFPort.OFPP_FLOOD.getValue(), (short) 0xFFFF)); } else { actions.add(new OFActionOutput(OFPort.OFPP_ALL.getValue(), (short) 0xFFFF)); } po.setActions(actions); po.setActionsLength((short) OFActionOutput.MINIMUM_LENGTH); // set buffer-id, in-port and packet-data based on packet-in short poLength = (short) (po.getActionsLength() + OFPacketOut.MINIMUM_LENGTH); po.setBufferId(pi.getBufferId()); po.setInPort(pi.getInPort()); if (pi.getBufferId() == OFPacketOut.BUFFER_ID_NONE) { byte[] packetData = pi.getPacketData(); poLength += packetData.length; po.setPacketData(packetData); } po.setLength(poLength); try { if (log.isTraceEnabled()) { log.trace( "Writing flood PacketOut switch={} packet-in={} packet-out={}", new Object[] {sw, pi, po}); } messageDamper.write(sw, po, cntx); } catch (IOException e) { log.error( "Failure writing PacketOut switch={} packet-in={} packet-out={}", new Object[] {sw, pi, po}, e); } return; }
@Test public void testFloodNoBufferId() throws Exception { // build our expected flooded packetOut OFPacketOut po = ((OFPacketOut) mockFloodlightProvider.getOFMessageFactory().getMessage(OFType.PACKET_OUT)) .setActions( Arrays.asList( new OFAction[] {new OFActionOutput().setPort(OFPort.OFPP_FLOOD.getValue())})) .setActionsLength((short) OFActionOutput.MINIMUM_LENGTH) .setBufferId(-1) .setInPort((short) 1) .setPacketData(this.testPacketSerialized); po.setLengthU( OFPacketOut.MINIMUM_LENGTH + po.getActionsLengthU() + this.testPacketSerialized.length); // Mock up our expected behavior IOFSwitch mockSwitch = createMock(IOFSwitch.class); Capture<OFMessage> wc1 = new Capture<OFMessage>(CaptureType.ALL); Capture<FloodlightContext> bc1 = new Capture<FloodlightContext>(CaptureType.ALL); mockSwitch.write(capture(wc1), capture(bc1)); // Start recording the replay on the mocks replay(mockSwitch); // Get the listener and trigger the packet in IOFMessageListener listener = mockFloodlightProvider.getListeners().get(OFType.PACKET_IN).get(0); listener.receive(mockSwitch, this.packetIn, parseAndAnnotate(this.packetIn)); // Verify the replay matched our expectations verify(mockSwitch); assertTrue(wc1.hasCaptured()); OFMessage m = wc1.getValue(); assertEquals(po, m); }