blob: 2e1dcb72ee360ea03a9112682224146e9934f0f8 [file] [log] [blame]
Thomas Vachuska781d18b2014-10-27 10:31:25 -07001/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
alshabibae857582014-09-12 23:53:10 -070019package org.onlab.onos.provider.of.packet.impl;
20
21import static org.slf4j.LoggerFactory.getLogger;
22
alshabibd58d3522014-09-13 17:14:53 -070023import java.nio.ByteBuffer;
Ayaka Koshibeab3374b2014-09-19 11:41:25 -070024import java.util.Collections;
alshabibd58d3522014-09-13 17:14:53 -070025
alshabibae857582014-09-12 23:53:10 -070026import org.apache.felix.scr.annotations.Activate;
27import org.apache.felix.scr.annotations.Component;
28import org.apache.felix.scr.annotations.Deactivate;
29import org.apache.felix.scr.annotations.Reference;
30import org.apache.felix.scr.annotations.ReferenceCardinality;
alshabibd58d3522014-09-13 17:14:53 -070031import org.onlab.onos.net.ConnectPoint;
32import org.onlab.onos.net.DeviceId;
33import org.onlab.onos.net.PortNumber;
Ayaka Koshibeab3374b2014-09-19 11:41:25 -070034import org.onlab.onos.net.flow.instructions.Instruction;
35import org.onlab.onos.net.flow.instructions.Instructions.OutputInstruction;
alshabibd58d3522014-09-13 17:14:53 -070036import org.onlab.onos.net.packet.DefaultInboundPacket;
alshabibe9d3a322014-09-23 15:18:33 -070037import org.onlab.onos.net.packet.DefaultOutboundPacket;
alshabibae857582014-09-12 23:53:10 -070038import org.onlab.onos.net.packet.OutboundPacket;
39import org.onlab.onos.net.packet.PacketProvider;
40import org.onlab.onos.net.packet.PacketProviderRegistry;
41import org.onlab.onos.net.packet.PacketProviderService;
42import org.onlab.onos.net.provider.AbstractProvider;
43import org.onlab.onos.net.provider.ProviderId;
tom9c94c5b2014-09-17 13:14:42 -070044import org.onlab.onos.openflow.controller.Dpid;
45import org.onlab.onos.openflow.controller.OpenFlowController;
46import org.onlab.onos.openflow.controller.OpenFlowPacketContext;
Ayaka Koshibeab3374b2014-09-19 11:41:25 -070047import org.onlab.onos.openflow.controller.OpenFlowSwitch;
tom9c94c5b2014-09-17 13:14:42 -070048import org.onlab.onos.openflow.controller.PacketListener;
Ayaka Koshibeab3374b2014-09-19 11:41:25 -070049import org.projectfloodlight.openflow.protocol.OFPacketOut;
50import org.projectfloodlight.openflow.protocol.OFPortDesc;
51import org.projectfloodlight.openflow.protocol.action.OFAction;
52import org.projectfloodlight.openflow.protocol.ver10.OFFactoryVer10;
53import org.projectfloodlight.openflow.types.OFBufferId;
54import org.projectfloodlight.openflow.types.OFPort;
alshabibae857582014-09-12 23:53:10 -070055import org.slf4j.Logger;
56
Ayaka Koshibeab3374b2014-09-19 11:41:25 -070057
alshabibae857582014-09-12 23:53:10 -070058/**
59 * Provider which uses an OpenFlow controller to detect network
60 * infrastructure links.
61 */
62@Component(immediate = true)
63public class OpenFlowPacketProvider extends AbstractProvider implements PacketProvider {
64
65 private final Logger log = getLogger(getClass());
66
67 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
68 protected PacketProviderRegistry providerRegistry;
69
70 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
71 protected OpenFlowController controller;
72
73 private PacketProviderService providerService;
74
alshabibae857582014-09-12 23:53:10 -070075 private final InternalPacketProvider listener = new InternalPacketProvider();
76
alshabibae857582014-09-12 23:53:10 -070077 /**
78 * Creates an OpenFlow link provider.
79 */
80 public OpenFlowPacketProvider() {
tom7e02cda2014-09-18 12:05:46 -070081 super(new ProviderId("of", "org.onlab.onos.provider.openflow"));
alshabibae857582014-09-12 23:53:10 -070082 }
83
84 @Activate
85 public void activate() {
86 providerService = providerRegistry.register(this);
alshabib8aef1ad2014-09-15 17:47:31 -070087 controller.addPacketListener(20, listener);
alshabibae857582014-09-12 23:53:10 -070088 log.info("Started");
89 }
90
91 @Deactivate
92 public void deactivate() {
93 providerRegistry.unregister(this);
94 controller.removePacketListener(listener);
95 providerService = null;
96 log.info("Stopped");
97 }
98
99 @Override
100 public void emit(OutboundPacket packet) {
Ayaka Koshibeab3374b2014-09-19 11:41:25 -0700101 DeviceId devId = packet.sendThrough();
102 String scheme = devId.toString().split(":")[0];
103
104 if (!scheme.equals(this.id().scheme())) {
105 throw new IllegalArgumentException(
106 "Don't know how to handle Device with scheme " + scheme);
107 }
108
109 Dpid dpid = Dpid.dpid(devId.uri());
110 OpenFlowSwitch sw = controller.getSwitch(dpid);
111 if (sw == null) {
112 log.warn("Device {} isn't available?", devId);
113 return;
Ayaka Koshibeab3374b2014-09-19 11:41:25 -0700114 }
115
alshabib7911a052014-10-16 17:49:37 -0700116 //Ethernet eth = new Ethernet();
117 //eth.deserialize(packet.data().array(), 0, packet.data().array().length);
Ayaka Koshibeab3374b2014-09-19 11:41:25 -0700118 OFPortDesc p = null;
119 for (Instruction inst : packet.treatment().instructions()) {
120 if (inst.type().equals(Instruction.Type.OUTPUT)) {
121 p = portDesc(((OutputInstruction) inst).port());
alshabib7911a052014-10-16 17:49:37 -0700122 OFPacketOut po = packetOut(sw, packet.data().array(), p.getPortNo());
Ayaka Koshibeab3374b2014-09-19 11:41:25 -0700123 sw.sendMsg(po);
124 }
125 }
alshabibae857582014-09-12 23:53:10 -0700126
127 }
128
Ayaka Koshibeab3374b2014-09-19 11:41:25 -0700129 private OFPortDesc portDesc(PortNumber port) {
130 OFPortDesc.Builder builder = OFFactoryVer10.INSTANCE.buildPortDesc();
131 builder.setPortNo(OFPort.of((int) port.toLong()));
132
133 return builder.build();
134 }
135
alshabib7911a052014-10-16 17:49:37 -0700136 private OFPacketOut packetOut(OpenFlowSwitch sw, byte[] eth, OFPort out) {
Ayaka Koshibeab3374b2014-09-19 11:41:25 -0700137 OFPacketOut.Builder builder = sw.factory().buildPacketOut();
138 OFAction act = sw.factory().actions()
139 .buildOutput()
140 .setPort(out)
141 .build();
142 return builder
143 .setBufferId(OFBufferId.NO_BUFFER)
144 .setInPort(OFPort.NO_MASK)
145 .setActions(Collections.singletonList(act))
alshabib7911a052014-10-16 17:49:37 -0700146 .setData(eth)
Ayaka Koshibeab3374b2014-09-19 11:41:25 -0700147 .build();
148 }
alshabibae857582014-09-12 23:53:10 -0700149
alshabibd58d3522014-09-13 17:14:53 -0700150 /**
151 * Internal Packet Provider implementation.
152 *
153 */
alshabibae857582014-09-12 23:53:10 -0700154 private class InternalPacketProvider implements PacketListener {
155
alshabibae857582014-09-12 23:53:10 -0700156 @Override
157 public void handlePacket(OpenFlowPacketContext pktCtx) {
alshabibd58d3522014-09-13 17:14:53 -0700158 DeviceId id = DeviceId.deviceId(Dpid.uri(pktCtx.dpid().value()));
alshabibae857582014-09-12 23:53:10 -0700159
alshabibd58d3522014-09-13 17:14:53 -0700160 DefaultInboundPacket inPkt = new DefaultInboundPacket(
161 new ConnectPoint(id, PortNumber.portNumber(pktCtx.inPort())),
162 pktCtx.parsed(), ByteBuffer.wrap(pktCtx.unparsed()));
alshabibae857582014-09-12 23:53:10 -0700163
alshabibe9d3a322014-09-23 15:18:33 -0700164 DefaultOutboundPacket outPkt = null;
165 if (!pktCtx.isBuffered()) {
166 outPkt = new DefaultOutboundPacket(id, null,
167 ByteBuffer.wrap(pktCtx.unparsed()));
168 }
169
alshabibd58d3522014-09-13 17:14:53 -0700170 OpenFlowCorePacketContext corePktCtx =
alshabib9842a4e2014-09-16 21:42:35 -0700171 new OpenFlowCorePacketContext(System.currentTimeMillis(),
alshabibe9d3a322014-09-23 15:18:33 -0700172 inPkt, outPkt, pktCtx.isHandled(), pktCtx);
alshabibd58d3522014-09-13 17:14:53 -0700173 providerService.processPacket(corePktCtx);
alshabibae857582014-09-12 23:53:10 -0700174 }
175
176 }
177
178
179}