blob: a363339381af62e3beee29eab6fa050b072b227f [file] [log] [blame]
Thomas Vachuska781d18b2014-10-27 10:31:25 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2014-present Open Networking Foundation
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 */
Brian O'Connorabafb502014-12-02 22:26:20 -080016package org.onosproject.provider.of.packet.impl;
alshabibae857582014-09-12 23:53:10 -070017
Ray Milkeyd84f89b2018-08-17 14:54:17 -070018import org.osgi.service.component.annotations.Activate;
19import org.osgi.service.component.annotations.Component;
20import org.osgi.service.component.annotations.Deactivate;
21import org.osgi.service.component.annotations.Reference;
22import org.osgi.service.component.annotations.ReferenceCardinality;
Brian O'Connorabafb502014-12-02 22:26:20 -080023import org.onosproject.net.ConnectPoint;
24import org.onosproject.net.DeviceId;
25import org.onosproject.net.PortNumber;
26import org.onosproject.net.flow.instructions.Instruction;
27import org.onosproject.net.flow.instructions.Instructions.OutputInstruction;
28import org.onosproject.net.packet.DefaultInboundPacket;
29import org.onosproject.net.packet.DefaultOutboundPacket;
30import org.onosproject.net.packet.OutboundPacket;
31import org.onosproject.net.packet.PacketProvider;
32import org.onosproject.net.packet.PacketProviderRegistry;
33import org.onosproject.net.packet.PacketProviderService;
34import org.onosproject.net.provider.AbstractProvider;
35import org.onosproject.net.provider.ProviderId;
36import org.onosproject.openflow.controller.Dpid;
37import org.onosproject.openflow.controller.OpenFlowController;
38import org.onosproject.openflow.controller.OpenFlowPacketContext;
39import org.onosproject.openflow.controller.OpenFlowSwitch;
40import org.onosproject.openflow.controller.PacketListener;
Ayaka Koshibeab3374b2014-09-19 11:41:25 -070041import org.projectfloodlight.openflow.protocol.OFPacketOut;
42import org.projectfloodlight.openflow.protocol.OFPortDesc;
Cem Türker3baff672017-10-12 15:09:01 +030043import org.projectfloodlight.openflow.protocol.OFVersion;
Ayaka Koshibeab3374b2014-09-19 11:41:25 -070044import org.projectfloodlight.openflow.protocol.action.OFAction;
45import org.projectfloodlight.openflow.protocol.ver10.OFFactoryVer10;
46import org.projectfloodlight.openflow.types.OFBufferId;
47import org.projectfloodlight.openflow.types.OFPort;
alshabibae857582014-09-12 23:53:10 -070048import org.slf4j.Logger;
49
Jonathan Hart85463482015-02-18 14:58:21 -080050import java.nio.ByteBuffer;
51import java.util.Collections;
52
53import static org.slf4j.LoggerFactory.getLogger;
54
Ayaka Koshibeab3374b2014-09-19 11:41:25 -070055
alshabibae857582014-09-12 23:53:10 -070056/**
57 * Provider which uses an OpenFlow controller to detect network
58 * infrastructure links.
59 */
60@Component(immediate = true)
61public class OpenFlowPacketProvider extends AbstractProvider implements PacketProvider {
62
63 private final Logger log = getLogger(getClass());
64
Ray Milkeyd84f89b2018-08-17 14:54:17 -070065 @Reference(cardinality = ReferenceCardinality.MANDATORY)
alshabibae857582014-09-12 23:53:10 -070066 protected PacketProviderRegistry providerRegistry;
67
Ray Milkeyd84f89b2018-08-17 14:54:17 -070068 @Reference(cardinality = ReferenceCardinality.MANDATORY)
alshabibae857582014-09-12 23:53:10 -070069 protected OpenFlowController controller;
70
71 private PacketProviderService providerService;
72
alshabibae857582014-09-12 23:53:10 -070073 private final InternalPacketProvider listener = new InternalPacketProvider();
74
alshabibae857582014-09-12 23:53:10 -070075 /**
76 * Creates an OpenFlow link provider.
77 */
78 public OpenFlowPacketProvider() {
Brian O'Connorabafb502014-12-02 22:26:20 -080079 super(new ProviderId("of", "org.onosproject.provider.openflow"));
alshabibae857582014-09-12 23:53:10 -070080 }
81
82 @Activate
83 public void activate() {
84 providerService = providerRegistry.register(this);
alshabib8aef1ad2014-09-15 17:47:31 -070085 controller.addPacketListener(20, listener);
alshabibae857582014-09-12 23:53:10 -070086 log.info("Started");
87 }
88
89 @Deactivate
90 public void deactivate() {
91 providerRegistry.unregister(this);
92 controller.removePacketListener(listener);
93 providerService = null;
94 log.info("Stopped");
95 }
96
97 @Override
98 public void emit(OutboundPacket packet) {
Ayaka Koshibeab3374b2014-09-19 11:41:25 -070099 DeviceId devId = packet.sendThrough();
100 String scheme = devId.toString().split(":")[0];
101
102 if (!scheme.equals(this.id().scheme())) {
103 throw new IllegalArgumentException(
104 "Don't know how to handle Device with scheme " + scheme);
105 }
106
107 Dpid dpid = Dpid.dpid(devId.uri());
108 OpenFlowSwitch sw = controller.getSwitch(dpid);
109 if (sw == null) {
110 log.warn("Device {} isn't available?", devId);
111 return;
Ayaka Koshibeab3374b2014-09-19 11:41:25 -0700112 }
113
alshabib7911a052014-10-16 17:49:37 -0700114 //Ethernet eth = new Ethernet();
115 //eth.deserialize(packet.data().array(), 0, packet.data().array().length);
Ayaka Koshibeab3374b2014-09-19 11:41:25 -0700116 OFPortDesc p = null;
Ray Milkey42507352015-03-20 15:16:10 -0700117 for (Instruction inst : packet.treatment().allInstructions()) {
Ayaka Koshibeab3374b2014-09-19 11:41:25 -0700118 if (inst.type().equals(Instruction.Type.OUTPUT)) {
119 p = portDesc(((OutputInstruction) inst).port());
alshabib7911a052014-10-16 17:49:37 -0700120 OFPacketOut po = packetOut(sw, packet.data().array(), p.getPortNo());
Ayaka Koshibeab3374b2014-09-19 11:41:25 -0700121 sw.sendMsg(po);
122 }
123 }
alshabibae857582014-09-12 23:53:10 -0700124
125 }
126
Ayaka Koshibeab3374b2014-09-19 11:41:25 -0700127 private OFPortDesc portDesc(PortNumber port) {
128 OFPortDesc.Builder builder = OFFactoryVer10.INSTANCE.buildPortDesc();
129 builder.setPortNo(OFPort.of((int) port.toLong()));
130
131 return builder.build();
132 }
133
alshabib7911a052014-10-16 17:49:37 -0700134 private OFPacketOut packetOut(OpenFlowSwitch sw, byte[] eth, OFPort out) {
Ayaka Koshibeab3374b2014-09-19 11:41:25 -0700135 OFPacketOut.Builder builder = sw.factory().buildPacketOut();
136 OFAction act = sw.factory().actions()
137 .buildOutput()
138 .setPort(out)
139 .build();
Cem Türker3baff672017-10-12 15:09:01 +0300140 builder.setBufferId(OFBufferId.NO_BUFFER)
Ayaka Koshibeab3374b2014-09-19 11:41:25 -0700141 .setActions(Collections.singletonList(act))
Cem Türker3baff672017-10-12 15:09:01 +0300142 .setData(eth);
143 if (sw.factory().getVersion().getWireVersion() <= OFVersion.OF_14.getWireVersion()) {
144 builder.setInPort(OFPort.CONTROLLER);
145 }
146
147 return builder.build();
Ayaka Koshibeab3374b2014-09-19 11:41:25 -0700148 }
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())),
Charles Chancb13d122016-02-10 13:03:40 -0800162 pktCtx.parsed(), ByteBuffer.wrap(pktCtx.unparsed()),
163 pktCtx.cookie());
alshabibae857582014-09-12 23:53:10 -0700164
alshabibe9d3a322014-09-23 15:18:33 -0700165 DefaultOutboundPacket outPkt = null;
166 if (!pktCtx.isBuffered()) {
167 outPkt = new DefaultOutboundPacket(id, null,
168 ByteBuffer.wrap(pktCtx.unparsed()));
169 }
170
alshabibd58d3522014-09-13 17:14:53 -0700171 OpenFlowCorePacketContext corePktCtx =
alshabib9842a4e2014-09-16 21:42:35 -0700172 new OpenFlowCorePacketContext(System.currentTimeMillis(),
alshabibe9d3a322014-09-23 15:18:33 -0700173 inPkt, outPkt, pktCtx.isHandled(), pktCtx);
alshabibd58d3522014-09-13 17:14:53 -0700174 providerService.processPacket(corePktCtx);
alshabibae857582014-09-12 23:53:10 -0700175 }
176
177 }
178
179
180}