Merge branch 'master' of ssh://gerrit.onlab.us:29418/onos-next
diff --git a/openflow/api/src/main/java/org/onlab/onos/openflow/controller/OpenFlowPacketContext.java b/openflow/api/src/main/java/org/onlab/onos/openflow/controller/OpenFlowPacketContext.java
index 9d07c2f..85ea70a 100644
--- a/openflow/api/src/main/java/org/onlab/onos/openflow/controller/OpenFlowPacketContext.java
+++ b/openflow/api/src/main/java/org/onlab/onos/openflow/controller/OpenFlowPacketContext.java
@@ -5,8 +5,9 @@
/**
* 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 {
diff --git a/providers/openflow/packet/src/main/java/org/onlab/onos/provider/of/packet/impl/OpenFlowPacketProvider.java b/providers/openflow/packet/src/main/java/org/onlab/onos/provider/of/packet/impl/OpenFlowPacketProvider.java
index bc5b892..2403a72 100644
--- a/providers/openflow/packet/src/main/java/org/onlab/onos/provider/of/packet/impl/OpenFlowPacketProvider.java
+++ b/providers/openflow/packet/src/main/java/org/onlab/onos/provider/of/packet/impl/OpenFlowPacketProvider.java
@@ -3,6 +3,7 @@
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.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.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 @@
@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.