blob: 901217bd56f982438838dd1e1cfa706270cabeb9 [file] [log] [blame]
Thomas Vachuska781d18b2014-10-27 10:31:25 -07001/*
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07002 * Copyright 2014 Open Networking Laboratory
Thomas Vachuska781d18b2014-10-27 10:31:25 -07003 *
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07004 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
Thomas Vachuska781d18b2014-10-27 10:31:25 -07007 *
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07008 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
Thomas Vachuska781d18b2014-10-27 10:31:25 -070015 */
alshabibae857582014-09-12 23:53:10 -070016package org.onlab.onos.provider.of.packet.impl;
17
18import static org.slf4j.LoggerFactory.getLogger;
19
alshabibd58d3522014-09-13 17:14:53 -070020import java.nio.ByteBuffer;
Ayaka Koshibeab3374b2014-09-19 11:41:25 -070021import java.util.Collections;
alshabibd58d3522014-09-13 17:14:53 -070022
alshabibae857582014-09-12 23:53:10 -070023import org.apache.felix.scr.annotations.Activate;
24import org.apache.felix.scr.annotations.Component;
25import org.apache.felix.scr.annotations.Deactivate;
26import org.apache.felix.scr.annotations.Reference;
27import org.apache.felix.scr.annotations.ReferenceCardinality;
alshabibd58d3522014-09-13 17:14:53 -070028import org.onlab.onos.net.ConnectPoint;
29import org.onlab.onos.net.DeviceId;
30import org.onlab.onos.net.PortNumber;
Ayaka Koshibeab3374b2014-09-19 11:41:25 -070031import org.onlab.onos.net.flow.instructions.Instruction;
32import org.onlab.onos.net.flow.instructions.Instructions.OutputInstruction;
alshabibd58d3522014-09-13 17:14:53 -070033import org.onlab.onos.net.packet.DefaultInboundPacket;
alshabibe9d3a322014-09-23 15:18:33 -070034import org.onlab.onos.net.packet.DefaultOutboundPacket;
alshabibae857582014-09-12 23:53:10 -070035import org.onlab.onos.net.packet.OutboundPacket;
36import org.onlab.onos.net.packet.PacketProvider;
37import org.onlab.onos.net.packet.PacketProviderRegistry;
38import org.onlab.onos.net.packet.PacketProviderService;
39import org.onlab.onos.net.provider.AbstractProvider;
40import org.onlab.onos.net.provider.ProviderId;
tom9c94c5b2014-09-17 13:14:42 -070041import org.onlab.onos.openflow.controller.Dpid;
42import org.onlab.onos.openflow.controller.OpenFlowController;
43import org.onlab.onos.openflow.controller.OpenFlowPacketContext;
Ayaka Koshibeab3374b2014-09-19 11:41:25 -070044import org.onlab.onos.openflow.controller.OpenFlowSwitch;
tom9c94c5b2014-09-17 13:14:42 -070045import org.onlab.onos.openflow.controller.PacketListener;
Ayaka Koshibeab3374b2014-09-19 11:41:25 -070046import org.projectfloodlight.openflow.protocol.OFPacketOut;
47import org.projectfloodlight.openflow.protocol.OFPortDesc;
48import org.projectfloodlight.openflow.protocol.action.OFAction;
49import org.projectfloodlight.openflow.protocol.ver10.OFFactoryVer10;
50import org.projectfloodlight.openflow.types.OFBufferId;
51import org.projectfloodlight.openflow.types.OFPort;
alshabibae857582014-09-12 23:53:10 -070052import org.slf4j.Logger;
53
Ayaka Koshibeab3374b2014-09-19 11:41:25 -070054
alshabibae857582014-09-12 23:53:10 -070055/**
56 * Provider which uses an OpenFlow controller to detect network
57 * infrastructure links.
58 */
59@Component(immediate = true)
60public class OpenFlowPacketProvider extends AbstractProvider implements PacketProvider {
61
62 private final Logger log = getLogger(getClass());
63
64 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
65 protected PacketProviderRegistry providerRegistry;
66
67 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
68 protected OpenFlowController controller;
69
70 private PacketProviderService providerService;
71
alshabibae857582014-09-12 23:53:10 -070072 private final InternalPacketProvider listener = new InternalPacketProvider();
73
alshabibae857582014-09-12 23:53:10 -070074 /**
75 * Creates an OpenFlow link provider.
76 */
77 public OpenFlowPacketProvider() {
tom7e02cda2014-09-18 12:05:46 -070078 super(new ProviderId("of", "org.onlab.onos.provider.openflow"));
alshabibae857582014-09-12 23:53:10 -070079 }
80
81 @Activate
82 public void activate() {
83 providerService = providerRegistry.register(this);
alshabib8aef1ad2014-09-15 17:47:31 -070084 controller.addPacketListener(20, listener);
alshabibae857582014-09-12 23:53:10 -070085 log.info("Started");
86 }
87
88 @Deactivate
89 public void deactivate() {
90 providerRegistry.unregister(this);
91 controller.removePacketListener(listener);
92 providerService = null;
93 log.info("Stopped");
94 }
95
96 @Override
97 public void emit(OutboundPacket packet) {
Ayaka Koshibeab3374b2014-09-19 11:41:25 -070098 DeviceId devId = packet.sendThrough();
99 String scheme = devId.toString().split(":")[0];
100
101 if (!scheme.equals(this.id().scheme())) {
102 throw new IllegalArgumentException(
103 "Don't know how to handle Device with scheme " + scheme);
104 }
105
106 Dpid dpid = Dpid.dpid(devId.uri());
107 OpenFlowSwitch sw = controller.getSwitch(dpid);
108 if (sw == null) {
109 log.warn("Device {} isn't available?", devId);
110 return;
Ayaka Koshibeab3374b2014-09-19 11:41:25 -0700111 }
112
alshabib7911a052014-10-16 17:49:37 -0700113 //Ethernet eth = new Ethernet();
114 //eth.deserialize(packet.data().array(), 0, packet.data().array().length);
Ayaka Koshibeab3374b2014-09-19 11:41:25 -0700115 OFPortDesc p = null;
116 for (Instruction inst : packet.treatment().instructions()) {
117 if (inst.type().equals(Instruction.Type.OUTPUT)) {
118 p = portDesc(((OutputInstruction) inst).port());
alshabib7911a052014-10-16 17:49:37 -0700119 OFPacketOut po = packetOut(sw, packet.data().array(), p.getPortNo());
Ayaka Koshibeab3374b2014-09-19 11:41:25 -0700120 sw.sendMsg(po);
121 }
122 }
alshabibae857582014-09-12 23:53:10 -0700123
124 }
125
Ayaka Koshibeab3374b2014-09-19 11:41:25 -0700126 private OFPortDesc portDesc(PortNumber port) {
127 OFPortDesc.Builder builder = OFFactoryVer10.INSTANCE.buildPortDesc();
128 builder.setPortNo(OFPort.of((int) port.toLong()));
129
130 return builder.build();
131 }
132
alshabib7911a052014-10-16 17:49:37 -0700133 private OFPacketOut packetOut(OpenFlowSwitch sw, byte[] eth, OFPort out) {
Ayaka Koshibeab3374b2014-09-19 11:41:25 -0700134 OFPacketOut.Builder builder = sw.factory().buildPacketOut();
135 OFAction act = sw.factory().actions()
136 .buildOutput()
137 .setPort(out)
138 .build();
139 return builder
140 .setBufferId(OFBufferId.NO_BUFFER)
141 .setInPort(OFPort.NO_MASK)
142 .setActions(Collections.singletonList(act))
alshabib7911a052014-10-16 17:49:37 -0700143 .setData(eth)
Ayaka Koshibeab3374b2014-09-19 11:41:25 -0700144 .build();
145 }
alshabibae857582014-09-12 23:53:10 -0700146
alshabibd58d3522014-09-13 17:14:53 -0700147 /**
148 * Internal Packet Provider implementation.
149 *
150 */
alshabibae857582014-09-12 23:53:10 -0700151 private class InternalPacketProvider implements PacketListener {
152
alshabibae857582014-09-12 23:53:10 -0700153 @Override
154 public void handlePacket(OpenFlowPacketContext pktCtx) {
alshabibd58d3522014-09-13 17:14:53 -0700155 DeviceId id = DeviceId.deviceId(Dpid.uri(pktCtx.dpid().value()));
alshabibae857582014-09-12 23:53:10 -0700156
alshabibd58d3522014-09-13 17:14:53 -0700157 DefaultInboundPacket inPkt = new DefaultInboundPacket(
158 new ConnectPoint(id, PortNumber.portNumber(pktCtx.inPort())),
159 pktCtx.parsed(), ByteBuffer.wrap(pktCtx.unparsed()));
alshabibae857582014-09-12 23:53:10 -0700160
alshabibe9d3a322014-09-23 15:18:33 -0700161 DefaultOutboundPacket outPkt = null;
162 if (!pktCtx.isBuffered()) {
163 outPkt = new DefaultOutboundPacket(id, null,
164 ByteBuffer.wrap(pktCtx.unparsed()));
165 }
166
alshabibd58d3522014-09-13 17:14:53 -0700167 OpenFlowCorePacketContext corePktCtx =
alshabib9842a4e2014-09-16 21:42:35 -0700168 new OpenFlowCorePacketContext(System.currentTimeMillis(),
alshabibe9d3a322014-09-23 15:18:33 -0700169 inPkt, outPkt, pktCtx.isHandled(), pktCtx);
alshabibd58d3522014-09-13 17:14:53 -0700170 providerService.processPacket(corePktCtx);
alshabibae857582014-09-12 23:53:10 -0700171 }
172
173 }
174
175
176}