/** * Pushes a packet-out to a switch. The assumption here is that the packet-in was also generated * from the same switch. Thus, if the input port of the packet-in and the outport are the same, * the function will not push the packet-out. * * @param sw switch that generated the packet-in, and from which packet-out is sent * @param pi packet-in * @param useBufferId if true, use the bufferId from the packet in and do not add the packetIn's * payload. If false set bufferId to BUFFER_ID_NONE and use the packetIn's payload * @param outport output port * @param cntx context of the packet */ protected void pushPacket( IOFSwitch sw, OFPacketIn pi, boolean useBufferId, short outport, FloodlightContext cntx) { if (pi == null) { return; } // The assumption here is (sw) is the switch that generated the // packet-in. If the input port is the same as output port, then // the packet-out should be ignored. if (pi.getInPort() == outport) { if (log.isDebugEnabled()) { log.debug( "Attempting to do packet-out to the same " + "interface as packet-in. Dropping packet. " + " SrcSwitch={}, pi={}", new Object[] {sw, pi}); return; } } if (log.isTraceEnabled()) { log.trace("PacketOut srcSwitch={} pi={}", new Object[] {sw, pi}); } OFPacketOut po = (OFPacketOut) floodlightProvider.getOFMessageFactory().getMessage(OFType.PACKET_OUT); // set actions List<OFAction> actions = new ArrayList<OFAction>(); actions.add(new OFActionOutput(outport, (short) 0xffff)); po.setActions(actions).setActionsLength((short) OFActionOutput.MINIMUM_LENGTH); short poLength = (short) (po.getActionsLength() + OFPacketOut.MINIMUM_LENGTH); if (useBufferId) { po.setBufferId(pi.getBufferId()); } else { po.setBufferId(OFPacketOut.BUFFER_ID_NONE); } if (po.getBufferId() == OFPacketOut.BUFFER_ID_NONE) { byte[] packetData = pi.getPacketData(); poLength += packetData.length; po.setPacketData(packetData); } po.setInPort(pi.getInPort()); po.setLength(poLength); try { counterStore.updatePktOutFMCounterStoreLocal(sw, po); messageDamper.write(sw, po, cntx); } catch (IOException e) { log.error("Failure writing packet out", e); } }
/** * 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; }
/** * TODO This method must be moved to a layer below forwarding so that anyone can use it. * * @param packetData * @param sw * @param ports * @param cntx */ @LogMessageDoc( level = "ERROR", message = "Failed to clear all flows on switch {switch}", explanation = "An I/O error occured while trying send " + "topology discovery packet", recommendation = LogMessageDoc.CHECK_SWITCH) public void doMultiActionPacketOut( byte[] packetData, IOFSwitch sw, Set<Short> ports, FloodlightContext cntx) { if (ports == null) return; if (packetData == null || packetData.length <= 0) return; OFPacketOut po = (OFPacketOut) floodlightProvider.getOFMessageFactory().getMessage(OFType.PACKET_OUT); List<OFAction> actions = new ArrayList<OFAction>(); for (short p : ports) { actions.add(new OFActionOutput(p, (short) 0)); } // set actions po.setActions(actions); // set action length po.setActionsLength((short) (OFActionOutput.MINIMUM_LENGTH * ports.size())); // set buffer-id to BUFFER_ID_NONE po.setBufferId(OFPacketOut.BUFFER_ID_NONE); // set in-port to OFPP_NONE po.setInPort(OFPort.OFPP_NONE.getValue()); // set packet data po.setPacketData(packetData); // compute and set packet length. short poLength = (short) (OFPacketOut.MINIMUM_LENGTH + po.getActionsLength() + packetData.length); po.setLength(poLength); try { // counterStore.updatePktOutFMCounterStore(sw, po); if (log.isTraceEnabled()) { log.trace( "write broadcast packet on switch-id={} " + "interaces={} packet-data={} packet-out={}", new Object[] {sw.getId(), ports, packetData, po}); } sw.write(po, cntx); } catch (IOException e) { log.error("Failure writing packet out", e); } }
@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); }
/** * Write packetout message to sw with output actions to one or more output ports with * inPort/outPorts passed in. * * @param packetData * @param sw * @param inPort * @param ports * @param cntx */ public void packetOutMultiPort( byte[] packetData, IOFSwitch sw, short inPort, Set<Integer> outPorts, FloodlightContext cntx) { // setting actions List<OFAction> actions = new ArrayList<OFAction>(); Iterator<Integer> j = outPorts.iterator(); while (j.hasNext()) { actions.add(new OFActionOutput(j.next().shortValue(), (short) 0)); } OFPacketOut po = (OFPacketOut) floodlightProvider.getOFMessageFactory().getMessage(OFType.PACKET_OUT); po.setActions(actions); po.setActionsLength((short) (OFActionOutput.MINIMUM_LENGTH * outPorts.size())); // set buffer-id to BUFFER_ID_NONE, and set in-port to OFPP_NONE po.setBufferId(OFPacketOut.BUFFER_ID_NONE); po.setInPort(inPort); // data (note buffer_id is always BUFFER_ID_NONE) and length short poLength = (short) (po.getActionsLength() + OFPacketOut.MINIMUM_LENGTH); poLength += packetData.length; po.setPacketData(packetData); po.setLength(poLength); try { counterStore.updatePktOutFMCounterStoreLocal(sw, po); if (log.isTraceEnabled()) { log.trace( "write broadcast packet on switch-id={} " + "interfaces={} packet-out={}", new Object[] {sw.getId(), outPorts, po}); } messageDamper.write(sw, po, cntx); } catch (IOException e) { log.error("Failure writing packet out", e); } }
protected void pushPacket( IOFSwitch sw, OFMatch match, OFPacketIn pi, short outport, FloodlightContext cntx) { if (pi == null) { return; } else if (pi.getInPort() == outport) { log.warn("Packet out not sent as the outport matches inport. {}", pi); return; } // The assumption here is (sw) is the switch that generated the // packet-in. If the input port is the same as output port, then // the packet-out should be ignored. if (pi.getInPort() == outport) { if (log.isDebugEnabled()) { log.debug( "Attempting to do packet-out to the same " + "interface as packet-in. Dropping packet. " + " SrcSwitch={}, match = {}, pi={}", new Object[] {sw, match, pi}); return; } } if (log.isTraceEnabled()) { log.trace("PacketOut srcSwitch={} match={} pi={}", new Object[] {sw, match, pi}); } OFPacketOut po = (OFPacketOut) floodlightProvider.getOFMessageFactory().getMessage(OFType.PACKET_OUT); // set actions List<OFAction> actions = new ArrayList<OFAction>(); actions.add(new OFActionOutput(outport, (short) 0xffff)); po.setActions(actions).setActionsLength((short) OFActionOutput.MINIMUM_LENGTH); short poLength = (short) (po.getActionsLength() + OFPacketOut.MINIMUM_LENGTH); // If the switch doens't support buffering set the buffer id to be none // otherwise it'll be the the buffer id of the PacketIn if (sw.getBuffers() == 0) { // We set the PI buffer id here so we don't have to check again // below pi.setBufferId(OFPacketOut.BUFFER_ID_NONE); po.setBufferId(OFPacketOut.BUFFER_ID_NONE); } else { po.setBufferId(pi.getBufferId()); } po.setInPort(pi.getInPort()); // If the buffer id is none or the switch doesn's support buffering // we send the data with the packet out if (pi.getBufferId() == OFPacketOut.BUFFER_ID_NONE) { byte[] packetData = pi.getPacketData(); poLength += packetData.length; po.setPacketData(packetData); } po.setLength(poLength); try { counterStore.updatePktOutFMCounterStoreLocal(sw, po); messageDamper.write(sw, po, cntx); } catch (IOException e) { log.error("Failure writing packet out", e); } }
/** * Pushes a packet-out to a switch. If bufferId != BUFFER_ID_NONE we assume that the packetOut * switch is the same as the packetIn switch and we will use the bufferId. In this case the packet * can be null Caller needs to make sure that inPort and outPort differs * * @param packet packet data to send. * @param sw switch from which packet-out is sent * @param bufferId bufferId * @param inPort input port * @param outPort output port * @param cntx context of the packet * @param flush force to flush the packet. */ @LogMessageDocs({ @LogMessageDoc( level = "ERROR", message = "BufferId is not and packet data is null. " + "Cannot send packetOut. " + "srcSwitch={dpid} inPort={port} outPort={port}", explanation = "The switch send a malformed packet-in." + "The packet will be dropped", recommendation = LogMessageDoc.REPORT_SWITCH_BUG), @LogMessageDoc( level = "ERROR", message = "Failure writing packet out", explanation = "An I/O error occurred while writing a " + "packet out to a switch", recommendation = LogMessageDoc.CHECK_SWITCH) }) public void pushPacket( IPacket packet, IOFSwitch sw, int bufferId, short inPort, short outPort, FloodlightContext cntx, boolean flush) { if (log.isTraceEnabled()) { log.trace("PacketOut srcSwitch={} inPort={} outPort={}", new Object[] {sw, inPort, outPort}); } OFPacketOut po = (OFPacketOut) floodlightProvider.getOFMessageFactory().getMessage(OFType.PACKET_OUT); // set actions List<OFAction> actions = new ArrayList<OFAction>(); actions.add(new OFActionOutput(outPort, (short) 0xffff)); po.setActions(actions).setActionsLength((short) OFActionOutput.MINIMUM_LENGTH); short poLength = (short) (po.getActionsLength() + OFPacketOut.MINIMUM_LENGTH); // set buffer_id, in_port po.setBufferId(bufferId); po.setInPort(inPort); // set data - only if buffer_id == -1 if (po.getBufferId() == OFPacketOut.BUFFER_ID_NONE) { if (packet == null) { log.error( "BufferId is not set and packet data is null. " + "Cannot send packetOut. " + "srcSwitch={} inPort={} outPort={}", new Object[] {sw, inPort, outPort}); return; } byte[] packetData = packet.serialize(); poLength += packetData.length; po.setPacketData(packetData); } po.setLength(poLength); try { counterStore.updatePktOutFMCounterStoreLocal(sw, po); messageDamper.write(sw, po, cntx, flush); } catch (IOException e) { log.error("Failure writing packet out", e); } }