Ayaka Koshibe

emit + tests for OFPacketProvider

Change-Id: I9d6a2a641f857742fa68597189a9047dd16989d1
......@@ -5,8 +5,9 @@ import org.projectfloodlight.openflow.types.OFPort;
/**
* A representation of a packet context which allows any provider
* to view the packet in event but may block the response to the
* event if blocked has been called.
* to view a packet in event, but may block the response to the
* event if blocked has been called. This packet context can be used
* to react to the packet in event with a packet out.
*/
public interface OpenFlowPacketContext {
......
......@@ -3,6 +3,7 @@ package org.onlab.onos.provider.of.packet.impl;
import static org.slf4j.LoggerFactory.getLogger;
import java.nio.ByteBuffer;
import java.util.Collections;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
......@@ -12,6 +13,8 @@ import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.onlab.onos.net.ConnectPoint;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.PortNumber;
import org.onlab.onos.net.flow.instructions.Instruction;
import org.onlab.onos.net.flow.instructions.Instructions.OutputInstruction;
import org.onlab.onos.net.packet.DefaultInboundPacket;
import org.onlab.onos.net.packet.OutboundPacket;
import org.onlab.onos.net.packet.PacketProvider;
......@@ -19,12 +22,24 @@ import org.onlab.onos.net.packet.PacketProviderRegistry;
import org.onlab.onos.net.packet.PacketProviderService;
import org.onlab.onos.net.provider.AbstractProvider;
import org.onlab.onos.net.provider.ProviderId;
import org.onlab.onos.openflow.controller.DefaultOpenFlowPacketContext;
import org.onlab.onos.openflow.controller.Dpid;
import org.onlab.onos.openflow.controller.OpenFlowController;
import org.onlab.onos.openflow.controller.OpenFlowPacketContext;
import org.onlab.onos.openflow.controller.OpenFlowSwitch;
import org.onlab.onos.openflow.controller.PacketListener;
import org.onlab.packet.Ethernet;
import org.projectfloodlight.openflow.protocol.OFPacketOut;
import org.projectfloodlight.openflow.protocol.OFPortDesc;
import org.projectfloodlight.openflow.protocol.action.OFAction;
import org.projectfloodlight.openflow.protocol.ver10.OFFactoryVer10;
import org.projectfloodlight.openflow.types.OFBufferId;
import org.projectfloodlight.openflow.types.OFPort;
import org.slf4j.Logger;
import static org.onlab.onos.openflow.controller.RoleState.*;
/**
* Provider which uses an OpenFlow controller to detect network
* infrastructure links.
......@@ -68,9 +83,61 @@ public class OpenFlowPacketProvider extends AbstractProvider implements PacketPr
@Override
public void emit(OutboundPacket packet) {
DeviceId devId = packet.sendThrough();
String scheme = devId.toString().split(":")[0];
if (!scheme.equals(this.id().scheme())) {
throw new IllegalArgumentException(
"Don't know how to handle Device with scheme " + scheme);
}
Dpid dpid = Dpid.dpid(devId.uri());
OpenFlowSwitch sw = controller.getSwitch(dpid);
if (sw == null) {
log.warn("Device {} isn't available?", devId);
return;
} else if (sw.getRole().equals(SLAVE)) {
log.warn("Can't write to Device {} as slave", devId);
return;
}
Ethernet eth = new Ethernet();
eth.deserialize(packet.data().array(), 0, packet.data().array().length);
OFPortDesc p = null;
for (Instruction inst : packet.treatment().instructions()) {
if (inst.type().equals(Instruction.Type.OUTPUT)) {
p = portDesc(((OutputInstruction) inst).port());
if (!sw.getPorts().contains(p)) {
log.warn("Tried to write out non-existint port {}", p.getPortNo());
continue;
}
OFPacketOut po = packetOut(sw, eth, p.getPortNo());
sw.sendMsg(po);
}
}
}
private OFPortDesc portDesc(PortNumber port) {
OFPortDesc.Builder builder = OFFactoryVer10.INSTANCE.buildPortDesc();
builder.setPortNo(OFPort.of((int) port.toLong()));
return builder.build();
}
private OFPacketOut packetOut(OpenFlowSwitch sw, Ethernet eth, OFPort out) {
OFPacketOut.Builder builder = sw.factory().buildPacketOut();
OFAction act = sw.factory().actions()
.buildOutput()
.setPort(out)
.build();
return builder
.setBufferId(OFBufferId.NO_BUFFER)
.setInPort(OFPort.NO_MASK)
.setActions(Collections.singletonList(act))
.setData(eth.serialize())
.build();
}
/**
* Internal Packet Provider implementation.
......