blob: feedd886e12e377dfb0c2529563d5e0f4d2621ad [file] [log] [blame]
alshabibae857582014-09-12 23:53:10 -07001package org.onlab.onos.provider.of.packet.impl;
2
alshabibe9d3a322014-09-23 15:18:33 -07003import static org.onlab.onos.openflow.controller.RoleState.SLAVE;
alshabibae857582014-09-12 23:53:10 -07004import static org.slf4j.LoggerFactory.getLogger;
5
alshabibd58d3522014-09-13 17:14:53 -07006import java.nio.ByteBuffer;
Ayaka Koshibeab3374b2014-09-19 11:41:25 -07007import java.util.Collections;
alshabibd58d3522014-09-13 17:14:53 -07008
alshabibae857582014-09-12 23:53:10 -07009import org.apache.felix.scr.annotations.Activate;
10import org.apache.felix.scr.annotations.Component;
11import org.apache.felix.scr.annotations.Deactivate;
12import org.apache.felix.scr.annotations.Reference;
13import org.apache.felix.scr.annotations.ReferenceCardinality;
alshabibd58d3522014-09-13 17:14:53 -070014import org.onlab.onos.net.ConnectPoint;
15import org.onlab.onos.net.DeviceId;
16import org.onlab.onos.net.PortNumber;
Ayaka Koshibeab3374b2014-09-19 11:41:25 -070017import org.onlab.onos.net.flow.instructions.Instruction;
18import org.onlab.onos.net.flow.instructions.Instructions.OutputInstruction;
alshabibd58d3522014-09-13 17:14:53 -070019import org.onlab.onos.net.packet.DefaultInboundPacket;
alshabibe9d3a322014-09-23 15:18:33 -070020import org.onlab.onos.net.packet.DefaultOutboundPacket;
alshabibae857582014-09-12 23:53:10 -070021import org.onlab.onos.net.packet.OutboundPacket;
22import org.onlab.onos.net.packet.PacketProvider;
23import org.onlab.onos.net.packet.PacketProviderRegistry;
24import org.onlab.onos.net.packet.PacketProviderService;
25import org.onlab.onos.net.provider.AbstractProvider;
26import org.onlab.onos.net.provider.ProviderId;
tom9c94c5b2014-09-17 13:14:42 -070027import org.onlab.onos.openflow.controller.Dpid;
28import org.onlab.onos.openflow.controller.OpenFlowController;
29import org.onlab.onos.openflow.controller.OpenFlowPacketContext;
Ayaka Koshibeab3374b2014-09-19 11:41:25 -070030import org.onlab.onos.openflow.controller.OpenFlowSwitch;
tom9c94c5b2014-09-17 13:14:42 -070031import org.onlab.onos.openflow.controller.PacketListener;
Ayaka Koshibeab3374b2014-09-19 11:41:25 -070032import org.onlab.packet.Ethernet;
33import org.projectfloodlight.openflow.protocol.OFPacketOut;
34import org.projectfloodlight.openflow.protocol.OFPortDesc;
35import org.projectfloodlight.openflow.protocol.action.OFAction;
36import org.projectfloodlight.openflow.protocol.ver10.OFFactoryVer10;
37import org.projectfloodlight.openflow.types.OFBufferId;
38import org.projectfloodlight.openflow.types.OFPort;
alshabibae857582014-09-12 23:53:10 -070039import org.slf4j.Logger;
40
Ayaka Koshibeab3374b2014-09-19 11:41:25 -070041
alshabibae857582014-09-12 23:53:10 -070042/**
43 * Provider which uses an OpenFlow controller to detect network
44 * infrastructure links.
45 */
46@Component(immediate = true)
47public class OpenFlowPacketProvider extends AbstractProvider implements PacketProvider {
48
49 private final Logger log = getLogger(getClass());
50
51 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
52 protected PacketProviderRegistry providerRegistry;
53
54 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
55 protected OpenFlowController controller;
56
57 private PacketProviderService providerService;
58
alshabibae857582014-09-12 23:53:10 -070059 private final InternalPacketProvider listener = new InternalPacketProvider();
60
alshabibae857582014-09-12 23:53:10 -070061 /**
62 * Creates an OpenFlow link provider.
63 */
64 public OpenFlowPacketProvider() {
tom7e02cda2014-09-18 12:05:46 -070065 super(new ProviderId("of", "org.onlab.onos.provider.openflow"));
alshabibae857582014-09-12 23:53:10 -070066 }
67
68 @Activate
69 public void activate() {
70 providerService = providerRegistry.register(this);
alshabib8aef1ad2014-09-15 17:47:31 -070071 controller.addPacketListener(20, listener);
alshabibae857582014-09-12 23:53:10 -070072 log.info("Started");
73 }
74
75 @Deactivate
76 public void deactivate() {
77 providerRegistry.unregister(this);
78 controller.removePacketListener(listener);
79 providerService = null;
80 log.info("Stopped");
81 }
82
83 @Override
84 public void emit(OutboundPacket packet) {
Ayaka Koshibeab3374b2014-09-19 11:41:25 -070085 DeviceId devId = packet.sendThrough();
86 String scheme = devId.toString().split(":")[0];
87
88 if (!scheme.equals(this.id().scheme())) {
89 throw new IllegalArgumentException(
90 "Don't know how to handle Device with scheme " + scheme);
91 }
92
93 Dpid dpid = Dpid.dpid(devId.uri());
94 OpenFlowSwitch sw = controller.getSwitch(dpid);
95 if (sw == null) {
96 log.warn("Device {} isn't available?", devId);
97 return;
98 } else if (sw.getRole().equals(SLAVE)) {
99 log.warn("Can't write to Device {} as slave", devId);
100 return;
101 }
102
103 Ethernet eth = new Ethernet();
104 eth.deserialize(packet.data().array(), 0, packet.data().array().length);
105 OFPortDesc p = null;
106 for (Instruction inst : packet.treatment().instructions()) {
107 if (inst.type().equals(Instruction.Type.OUTPUT)) {
108 p = portDesc(((OutputInstruction) inst).port());
109 if (!sw.getPorts().contains(p)) {
110 log.warn("Tried to write out non-existint port {}", p.getPortNo());
111 continue;
112 }
113 OFPacketOut po = packetOut(sw, eth, p.getPortNo());
114 sw.sendMsg(po);
115 }
116 }
alshabibae857582014-09-12 23:53:10 -0700117
118 }
119
Ayaka Koshibeab3374b2014-09-19 11:41:25 -0700120 private OFPortDesc portDesc(PortNumber port) {
121 OFPortDesc.Builder builder = OFFactoryVer10.INSTANCE.buildPortDesc();
122 builder.setPortNo(OFPort.of((int) port.toLong()));
123
124 return builder.build();
125 }
126
127 private OFPacketOut packetOut(OpenFlowSwitch sw, Ethernet eth, OFPort out) {
128 OFPacketOut.Builder builder = sw.factory().buildPacketOut();
129 OFAction act = sw.factory().actions()
130 .buildOutput()
131 .setPort(out)
132 .build();
133 return builder
134 .setBufferId(OFBufferId.NO_BUFFER)
135 .setInPort(OFPort.NO_MASK)
136 .setActions(Collections.singletonList(act))
137 .setData(eth.serialize())
138 .build();
139 }
alshabibae857582014-09-12 23:53:10 -0700140
alshabibd58d3522014-09-13 17:14:53 -0700141 /**
142 * Internal Packet Provider implementation.
143 *
144 */
alshabibae857582014-09-12 23:53:10 -0700145 private class InternalPacketProvider implements PacketListener {
146
alshabibae857582014-09-12 23:53:10 -0700147 @Override
148 public void handlePacket(OpenFlowPacketContext pktCtx) {
alshabibd58d3522014-09-13 17:14:53 -0700149 DeviceId id = DeviceId.deviceId(Dpid.uri(pktCtx.dpid().value()));
alshabibae857582014-09-12 23:53:10 -0700150
alshabibd58d3522014-09-13 17:14:53 -0700151 DefaultInboundPacket inPkt = new DefaultInboundPacket(
152 new ConnectPoint(id, PortNumber.portNumber(pktCtx.inPort())),
153 pktCtx.parsed(), ByteBuffer.wrap(pktCtx.unparsed()));
alshabibae857582014-09-12 23:53:10 -0700154
alshabibe9d3a322014-09-23 15:18:33 -0700155 DefaultOutboundPacket outPkt = null;
156 if (!pktCtx.isBuffered()) {
157 outPkt = new DefaultOutboundPacket(id, null,
158 ByteBuffer.wrap(pktCtx.unparsed()));
159 }
160
alshabibd58d3522014-09-13 17:14:53 -0700161 OpenFlowCorePacketContext corePktCtx =
alshabib9842a4e2014-09-16 21:42:35 -0700162 new OpenFlowCorePacketContext(System.currentTimeMillis(),
alshabibe9d3a322014-09-23 15:18:33 -0700163 inPkt, outPkt, pktCtx.isHandled(), pktCtx);
alshabibd58d3522014-09-13 17:14:53 -0700164 providerService.processPacket(corePktCtx);
alshabibae857582014-09-12 23:53:10 -0700165 }
166
167 }
168
169
170}