blob: 2403a724e3087b25fd1e4c256545052da9707e93 [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;
alshabibae857582014-09-12 23:53:10 -070019import org.onlab.onos.net.packet.OutboundPacket;
20import org.onlab.onos.net.packet.PacketProvider;
21import org.onlab.onos.net.packet.PacketProviderRegistry;
22import org.onlab.onos.net.packet.PacketProviderService;
23import org.onlab.onos.net.provider.AbstractProvider;
24import org.onlab.onos.net.provider.ProviderId;
Ayaka Koshibeab3374b2014-09-19 11:41:25 -070025import org.onlab.onos.openflow.controller.DefaultOpenFlowPacketContext;
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.onlab.packet.Ethernet;
32import org.projectfloodlight.openflow.protocol.OFPacketOut;
33import org.projectfloodlight.openflow.protocol.OFPortDesc;
34import org.projectfloodlight.openflow.protocol.action.OFAction;
35import org.projectfloodlight.openflow.protocol.ver10.OFFactoryVer10;
36import org.projectfloodlight.openflow.types.OFBufferId;
37import org.projectfloodlight.openflow.types.OFPort;
alshabibae857582014-09-12 23:53:10 -070038import org.slf4j.Logger;
39
Ayaka Koshibeab3374b2014-09-19 11:41:25 -070040import static org.onlab.onos.openflow.controller.RoleState.*;
41
42
alshabibae857582014-09-12 23:53:10 -070043/**
44 * Provider which uses an OpenFlow controller to detect network
45 * infrastructure links.
46 */
47@Component(immediate = true)
48public class OpenFlowPacketProvider extends AbstractProvider implements PacketProvider {
49
50 private final Logger log = getLogger(getClass());
51
52 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
53 protected PacketProviderRegistry providerRegistry;
54
55 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
56 protected OpenFlowController controller;
57
58 private PacketProviderService providerService;
59
alshabibae857582014-09-12 23:53:10 -070060 private final InternalPacketProvider listener = new InternalPacketProvider();
61
alshabibae857582014-09-12 23:53:10 -070062 /**
63 * Creates an OpenFlow link provider.
64 */
65 public OpenFlowPacketProvider() {
tom7e02cda2014-09-18 12:05:46 -070066 super(new ProviderId("of", "org.onlab.onos.provider.openflow"));
alshabibae857582014-09-12 23:53:10 -070067 }
68
69 @Activate
70 public void activate() {
71 providerService = providerRegistry.register(this);
alshabib8aef1ad2014-09-15 17:47:31 -070072 controller.addPacketListener(20, listener);
alshabibae857582014-09-12 23:53:10 -070073 log.info("Started");
74 }
75
76 @Deactivate
77 public void deactivate() {
78 providerRegistry.unregister(this);
79 controller.removePacketListener(listener);
80 providerService = null;
81 log.info("Stopped");
82 }
83
84 @Override
85 public void emit(OutboundPacket packet) {
Ayaka Koshibeab3374b2014-09-19 11:41:25 -070086 DeviceId devId = packet.sendThrough();
87 String scheme = devId.toString().split(":")[0];
88
89 if (!scheme.equals(this.id().scheme())) {
90 throw new IllegalArgumentException(
91 "Don't know how to handle Device with scheme " + scheme);
92 }
93
94 Dpid dpid = Dpid.dpid(devId.uri());
95 OpenFlowSwitch sw = controller.getSwitch(dpid);
96 if (sw == null) {
97 log.warn("Device {} isn't available?", devId);
98 return;
99 } else if (sw.getRole().equals(SLAVE)) {
100 log.warn("Can't write to Device {} as slave", devId);
101 return;
102 }
103
104 Ethernet eth = new Ethernet();
105 eth.deserialize(packet.data().array(), 0, packet.data().array().length);
106 OFPortDesc p = null;
107 for (Instruction inst : packet.treatment().instructions()) {
108 if (inst.type().equals(Instruction.Type.OUTPUT)) {
109 p = portDesc(((OutputInstruction) inst).port());
110 if (!sw.getPorts().contains(p)) {
111 log.warn("Tried to write out non-existint port {}", p.getPortNo());
112 continue;
113 }
114 OFPacketOut po = packetOut(sw, eth, p.getPortNo());
115 sw.sendMsg(po);
116 }
117 }
alshabibae857582014-09-12 23:53:10 -0700118
119 }
120
Ayaka Koshibeab3374b2014-09-19 11:41:25 -0700121 private OFPortDesc portDesc(PortNumber port) {
122 OFPortDesc.Builder builder = OFFactoryVer10.INSTANCE.buildPortDesc();
123 builder.setPortNo(OFPort.of((int) port.toLong()));
124
125 return builder.build();
126 }
127
128 private OFPacketOut packetOut(OpenFlowSwitch sw, Ethernet eth, OFPort out) {
129 OFPacketOut.Builder builder = sw.factory().buildPacketOut();
130 OFAction act = sw.factory().actions()
131 .buildOutput()
132 .setPort(out)
133 .build();
134 return builder
135 .setBufferId(OFBufferId.NO_BUFFER)
136 .setInPort(OFPort.NO_MASK)
137 .setActions(Collections.singletonList(act))
138 .setData(eth.serialize())
139 .build();
140 }
alshabibae857582014-09-12 23:53:10 -0700141
alshabibd58d3522014-09-13 17:14:53 -0700142 /**
143 * Internal Packet Provider implementation.
144 *
145 */
alshabibae857582014-09-12 23:53:10 -0700146 private class InternalPacketProvider implements PacketListener {
147
alshabibae857582014-09-12 23:53:10 -0700148 @Override
149 public void handlePacket(OpenFlowPacketContext pktCtx) {
alshabibd58d3522014-09-13 17:14:53 -0700150 DeviceId id = DeviceId.deviceId(Dpid.uri(pktCtx.dpid().value()));
alshabibae857582014-09-12 23:53:10 -0700151
alshabibd58d3522014-09-13 17:14:53 -0700152 DefaultInboundPacket inPkt = new DefaultInboundPacket(
153 new ConnectPoint(id, PortNumber.portNumber(pktCtx.inPort())),
154 pktCtx.parsed(), ByteBuffer.wrap(pktCtx.unparsed()));
alshabibae857582014-09-12 23:53:10 -0700155
alshabibd58d3522014-09-13 17:14:53 -0700156 OpenFlowCorePacketContext corePktCtx =
alshabib9842a4e2014-09-16 21:42:35 -0700157 new OpenFlowCorePacketContext(System.currentTimeMillis(),
158 inPkt, null, pktCtx.isHandled(), pktCtx);
alshabibd58d3522014-09-13 17:14:53 -0700159 providerService.processPacket(corePktCtx);
alshabibae857582014-09-12 23:53:10 -0700160 }
161
162 }
163
164
165}