blob: 8be1feca191ebb5eafd10e102b48180aa608bc56 [file] [log] [blame]
alshabibae857582014-09-12 23:53:10 -07001package org.onlab.onos.provider.of.packet.impl;
2
3import static org.slf4j.LoggerFactory.getLogger;
4
alshabibd58d3522014-09-13 17:14:53 -07005import java.nio.ByteBuffer;
Ayaka Koshibeab3374b2014-09-19 11:41:25 -07006import java.util.Collections;
alshabibd58d3522014-09-13 17:14:53 -07007
alshabibae857582014-09-12 23:53:10 -07008import org.apache.felix.scr.annotations.Activate;
9import org.apache.felix.scr.annotations.Component;
10import org.apache.felix.scr.annotations.Deactivate;
11import org.apache.felix.scr.annotations.Reference;
12import org.apache.felix.scr.annotations.ReferenceCardinality;
alshabibd58d3522014-09-13 17:14:53 -070013import org.onlab.onos.net.ConnectPoint;
14import org.onlab.onos.net.DeviceId;
15import org.onlab.onos.net.PortNumber;
Ayaka Koshibeab3374b2014-09-19 11:41:25 -070016import org.onlab.onos.net.flow.instructions.Instruction;
17import org.onlab.onos.net.flow.instructions.Instructions.OutputInstruction;
alshabibd58d3522014-09-13 17:14:53 -070018import org.onlab.onos.net.packet.DefaultInboundPacket;
alshabibe9d3a322014-09-23 15:18:33 -070019import org.onlab.onos.net.packet.DefaultOutboundPacket;
alshabibae857582014-09-12 23:53:10 -070020import org.onlab.onos.net.packet.OutboundPacket;
21import org.onlab.onos.net.packet.PacketProvider;
22import org.onlab.onos.net.packet.PacketProviderRegistry;
23import org.onlab.onos.net.packet.PacketProviderService;
24import org.onlab.onos.net.provider.AbstractProvider;
25import org.onlab.onos.net.provider.ProviderId;
tom9c94c5b2014-09-17 13:14:42 -070026import org.onlab.onos.openflow.controller.Dpid;
27import org.onlab.onos.openflow.controller.OpenFlowController;
28import org.onlab.onos.openflow.controller.OpenFlowPacketContext;
Ayaka Koshibeab3374b2014-09-19 11:41:25 -070029import org.onlab.onos.openflow.controller.OpenFlowSwitch;
tom9c94c5b2014-09-17 13:14:42 -070030import org.onlab.onos.openflow.controller.PacketListener;
Ayaka Koshibeab3374b2014-09-19 11:41:25 -070031import org.projectfloodlight.openflow.protocol.OFPacketOut;
32import org.projectfloodlight.openflow.protocol.OFPortDesc;
33import org.projectfloodlight.openflow.protocol.action.OFAction;
34import org.projectfloodlight.openflow.protocol.ver10.OFFactoryVer10;
35import org.projectfloodlight.openflow.types.OFBufferId;
36import org.projectfloodlight.openflow.types.OFPort;
alshabibae857582014-09-12 23:53:10 -070037import org.slf4j.Logger;
38
Ayaka Koshibeab3374b2014-09-19 11:41:25 -070039
alshabibae857582014-09-12 23:53:10 -070040/**
41 * Provider which uses an OpenFlow controller to detect network
42 * infrastructure links.
43 */
44@Component(immediate = true)
45public class OpenFlowPacketProvider extends AbstractProvider implements PacketProvider {
46
47 private final Logger log = getLogger(getClass());
48
49 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
50 protected PacketProviderRegistry providerRegistry;
51
52 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
53 protected OpenFlowController controller;
54
55 private PacketProviderService providerService;
56
alshabibae857582014-09-12 23:53:10 -070057 private final InternalPacketProvider listener = new InternalPacketProvider();
58
alshabibae857582014-09-12 23:53:10 -070059 /**
60 * Creates an OpenFlow link provider.
61 */
62 public OpenFlowPacketProvider() {
tom7e02cda2014-09-18 12:05:46 -070063 super(new ProviderId("of", "org.onlab.onos.provider.openflow"));
alshabibae857582014-09-12 23:53:10 -070064 }
65
66 @Activate
67 public void activate() {
68 providerService = providerRegistry.register(this);
alshabib8aef1ad2014-09-15 17:47:31 -070069 controller.addPacketListener(20, listener);
alshabibae857582014-09-12 23:53:10 -070070 log.info("Started");
71 }
72
73 @Deactivate
74 public void deactivate() {
75 providerRegistry.unregister(this);
76 controller.removePacketListener(listener);
77 providerService = null;
78 log.info("Stopped");
79 }
80
81 @Override
82 public void emit(OutboundPacket packet) {
Ayaka Koshibeab3374b2014-09-19 11:41:25 -070083 DeviceId devId = packet.sendThrough();
84 String scheme = devId.toString().split(":")[0];
85
86 if (!scheme.equals(this.id().scheme())) {
87 throw new IllegalArgumentException(
88 "Don't know how to handle Device with scheme " + scheme);
89 }
90
91 Dpid dpid = Dpid.dpid(devId.uri());
92 OpenFlowSwitch sw = controller.getSwitch(dpid);
93 if (sw == null) {
94 log.warn("Device {} isn't available?", devId);
95 return;
Ayaka Koshibeab3374b2014-09-19 11:41:25 -070096 }
97
alshabib7911a052014-10-16 17:49:37 -070098 //Ethernet eth = new Ethernet();
99 //eth.deserialize(packet.data().array(), 0, packet.data().array().length);
Ayaka Koshibeab3374b2014-09-19 11:41:25 -0700100 OFPortDesc p = null;
101 for (Instruction inst : packet.treatment().instructions()) {
102 if (inst.type().equals(Instruction.Type.OUTPUT)) {
103 p = portDesc(((OutputInstruction) inst).port());
alshabib7911a052014-10-16 17:49:37 -0700104 OFPacketOut po = packetOut(sw, packet.data().array(), p.getPortNo());
Ayaka Koshibeab3374b2014-09-19 11:41:25 -0700105 sw.sendMsg(po);
106 }
107 }
alshabibae857582014-09-12 23:53:10 -0700108
109 }
110
Ayaka Koshibeab3374b2014-09-19 11:41:25 -0700111 private OFPortDesc portDesc(PortNumber port) {
112 OFPortDesc.Builder builder = OFFactoryVer10.INSTANCE.buildPortDesc();
113 builder.setPortNo(OFPort.of((int) port.toLong()));
114
115 return builder.build();
116 }
117
alshabib7911a052014-10-16 17:49:37 -0700118 private OFPacketOut packetOut(OpenFlowSwitch sw, byte[] eth, OFPort out) {
Ayaka Koshibeab3374b2014-09-19 11:41:25 -0700119 OFPacketOut.Builder builder = sw.factory().buildPacketOut();
120 OFAction act = sw.factory().actions()
121 .buildOutput()
122 .setPort(out)
123 .build();
124 return builder
125 .setBufferId(OFBufferId.NO_BUFFER)
126 .setInPort(OFPort.NO_MASK)
127 .setActions(Collections.singletonList(act))
alshabib7911a052014-10-16 17:49:37 -0700128 .setData(eth)
Ayaka Koshibeab3374b2014-09-19 11:41:25 -0700129 .build();
130 }
alshabibae857582014-09-12 23:53:10 -0700131
alshabibd58d3522014-09-13 17:14:53 -0700132 /**
133 * Internal Packet Provider implementation.
134 *
135 */
alshabibae857582014-09-12 23:53:10 -0700136 private class InternalPacketProvider implements PacketListener {
137
alshabibae857582014-09-12 23:53:10 -0700138 @Override
139 public void handlePacket(OpenFlowPacketContext pktCtx) {
alshabibd58d3522014-09-13 17:14:53 -0700140 DeviceId id = DeviceId.deviceId(Dpid.uri(pktCtx.dpid().value()));
alshabibae857582014-09-12 23:53:10 -0700141
alshabibd58d3522014-09-13 17:14:53 -0700142 DefaultInboundPacket inPkt = new DefaultInboundPacket(
143 new ConnectPoint(id, PortNumber.portNumber(pktCtx.inPort())),
144 pktCtx.parsed(), ByteBuffer.wrap(pktCtx.unparsed()));
alshabibae857582014-09-12 23:53:10 -0700145
alshabibe9d3a322014-09-23 15:18:33 -0700146 DefaultOutboundPacket outPkt = null;
147 if (!pktCtx.isBuffered()) {
148 outPkt = new DefaultOutboundPacket(id, null,
149 ByteBuffer.wrap(pktCtx.unparsed()));
150 }
151
alshabibd58d3522014-09-13 17:14:53 -0700152 OpenFlowCorePacketContext corePktCtx =
alshabib9842a4e2014-09-16 21:42:35 -0700153 new OpenFlowCorePacketContext(System.currentTimeMillis(),
alshabibe9d3a322014-09-23 15:18:33 -0700154 inPkt, outPkt, pktCtx.isHandled(), pktCtx);
alshabibd58d3522014-09-13 17:14:53 -0700155 providerService.processPacket(corePktCtx);
alshabibae857582014-09-12 23:53:10 -0700156 }
157
158 }
159
160
161}