blob: 9bd2146baa9705f8105d72283b3800079d386ed8 [file] [log] [blame]
Thomas Vachuska781d18b2014-10-27 10:31:25 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2015-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.openflow.controller;
tom7ef8ff92014-09-17 13:08:06 -070017
Jonathan Hart2a655752015-04-07 16:46:33 -070018import org.onlab.packet.DeserializationException;
tom7ef8ff92014-09-17 13:08:06 -070019import org.onlab.packet.Ethernet;
20import org.projectfloodlight.openflow.protocol.OFPacketIn;
21import org.projectfloodlight.openflow.protocol.OFPacketOut;
Jonathan Hartcc36be82015-04-09 11:54:56 -070022import org.projectfloodlight.openflow.protocol.OFVersion;
tom7ef8ff92014-09-17 13:08:06 -070023import org.projectfloodlight.openflow.protocol.action.OFAction;
24import org.projectfloodlight.openflow.protocol.action.OFActionOutput;
25import org.projectfloodlight.openflow.protocol.match.MatchField;
26import org.projectfloodlight.openflow.types.OFBufferId;
27import org.projectfloodlight.openflow.types.OFPort;
Jonathan Hart2a655752015-04-07 16:46:33 -070028import org.slf4j.Logger;
29import org.slf4j.LoggerFactory;
tom1679e182014-10-09 13:50:45 -070030
Jonathan Harte46c0412015-01-20 13:19:55 -080031import java.nio.BufferUnderflowException;
32import java.util.Collections;
Charles Chancb13d122016-02-10 13:03:40 -080033import java.util.Optional;
Jonathan Harte46c0412015-01-20 13:19:55 -080034import java.util.concurrent.atomic.AtomicBoolean;
35
Changhoon Yoon541ef712015-05-23 17:18:34 +090036import static org.onosproject.security.AppGuard.checkPermission;
Changhoon Yoonb856b812015-08-10 03:47:19 +090037import static org.onosproject.security.AppPermission.Type.*;
Changhoon Yoon541ef712015-05-23 17:18:34 +090038
39
Jonathan Hartcc36be82015-04-09 11:54:56 -070040/**
41 * Default implementation of an OpenFlowPacketContext.
42 */
tom7ef8ff92014-09-17 13:08:06 -070043public final class DefaultOpenFlowPacketContext implements OpenFlowPacketContext {
44
tom7ef8ff92014-09-17 13:08:06 -070045 private final AtomicBoolean free = new AtomicBoolean(true);
46 private final AtomicBoolean isBuilt = new AtomicBoolean(false);
47 private final OpenFlowSwitch sw;
48 private final OFPacketIn pktin;
49 private OFPacketOut pktout = null;
50
alshabibe9d3a322014-09-23 15:18:33 -070051 private final boolean isBuffered;
52
tom7ef8ff92014-09-17 13:08:06 -070053 private DefaultOpenFlowPacketContext(OpenFlowSwitch s, OFPacketIn pkt) {
54 this.sw = s;
55 this.pktin = pkt;
alshabibe9d3a322014-09-23 15:18:33 -070056 this.isBuffered = pktin.getBufferId() != OFBufferId.NO_BUFFER;
tom7ef8ff92014-09-17 13:08:06 -070057 }
58
59 @Override
60 public void send() {
Changhoon Yoonb856b812015-08-10 03:47:19 +090061 checkPermission(PACKET_WRITE);
Changhoon Yoon541ef712015-05-23 17:18:34 +090062
tom7ef8ff92014-09-17 13:08:06 -070063 if (block() && isBuilt.get()) {
64 sw.sendMsg(pktout);
65 }
66 }
67
68 @Override
69 public void build(OFPort outPort) {
70 if (isBuilt.getAndSet(true)) {
71 return;
72 }
tom7ef8ff92014-09-17 13:08:06 -070073 OFAction act = buildOutput(outPort.getPortNumber());
Cem Türker3baff672017-10-12 15:09:01 +030074 pktout = createOFPacketOut(pktin.getData(), act, pktin.getXid());
75 }
76
77 private OFPacketOut createOFPacketOut(byte[] data, OFAction act, long xid) {
78 OFPacketOut.Builder builder = sw.factory().buildPacketOut();
79 if (sw.factory().getVersion().getWireVersion() <= OFVersion.OF_14.getWireVersion()) {
80 return builder.setXid(xid)
81 .setInPort(pktinInPort())
82 .setBufferId(OFBufferId.NO_BUFFER)
83 .setData(data)
Thomas Vachuska5f998492014-10-31 00:46:11 -070084// .setBufferId(pktin.getBufferId())
Cem Türker3baff672017-10-12 15:09:01 +030085 .setActions(Collections.singletonList(act)).build();
86 }
87 return builder.setXid(xid)
88 .setBufferId(OFBufferId.NO_BUFFER)
tom7ef8ff92014-09-17 13:08:06 -070089 .setActions(Collections.singletonList(act))
Cem Türker3baff672017-10-12 15:09:01 +030090 .setData(data)
tom7ef8ff92014-09-17 13:08:06 -070091 .build();
92 }
93
94 @Override
95 public void build(Ethernet ethFrame, OFPort outPort) {
96 if (isBuilt.getAndSet(true)) {
97 return;
98 }
tom7ef8ff92014-09-17 13:08:06 -070099 OFAction act = buildOutput(outPort.getPortNumber());
Cem Türker3baff672017-10-12 15:09:01 +0300100 pktout = createOFPacketOut(ethFrame.serialize(), act, pktin.getXid());
tom7ef8ff92014-09-17 13:08:06 -0700101 }
102
103 @Override
104 public Ethernet parsed() {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900105 checkPermission(PACKET_READ);
Changhoon Yoon541ef712015-05-23 17:18:34 +0900106
Jonathan Harte8600eb2015-01-12 10:30:45 -0800107 try {
Jonathan Hart2a655752015-04-07 16:46:33 -0700108 return Ethernet.deserializer().deserialize(pktin.getData(), 0, pktin.getData().length);
109 } catch (BufferUnderflowException | NullPointerException |
110 DeserializationException e) {
111 Logger log = LoggerFactory.getLogger(getClass());
alshabiba55c1c62015-10-05 15:07:08 +0200112 log.error("packet deserialization problem : {}", e.getMessage());
Jonathan Harte8600eb2015-01-12 10:30:45 -0800113 return null;
114 }
tom7ef8ff92014-09-17 13:08:06 -0700115 }
116
117 @Override
118 public Dpid dpid() {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900119 checkPermission(PACKET_READ);
Changhoon Yoon541ef712015-05-23 17:18:34 +0900120
Yuta HIGUCHI6ee6b8c2017-05-09 14:44:30 -0700121 return sw.getDpid();
tom7ef8ff92014-09-17 13:08:06 -0700122 }
123
Jonathan Hartcc36be82015-04-09 11:54:56 -0700124 /**
125 * Creates an OpenFlow packet context based on a packet-in.
126 *
127 * @param s OpenFlow switch
128 * @param pkt OpenFlow packet-in
129 * @return the OpenFlow packet context
130 */
tom7ef8ff92014-09-17 13:08:06 -0700131 public static OpenFlowPacketContext packetContextFromPacketIn(OpenFlowSwitch s,
tom1679e182014-10-09 13:50:45 -0700132 OFPacketIn pkt) {
tom7ef8ff92014-09-17 13:08:06 -0700133 return new DefaultOpenFlowPacketContext(s, pkt);
134 }
135
136 @Override
137 public Integer inPort() {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900138 checkPermission(PACKET_READ);
Changhoon Yoon541ef712015-05-23 17:18:34 +0900139
Pavlin Radoslavov20318992015-02-04 13:41:14 -0800140 return pktinInPort().getPortNumber();
alshabib6eb438a2014-10-01 16:39:37 -0700141 }
142
Pavlin Radoslavov20318992015-02-04 13:41:14 -0800143 private OFPort pktinInPort() {
Jonathan Hartcc36be82015-04-09 11:54:56 -0700144 if (pktin.getVersion() == OFVersion.OF_10) {
alshabib6eb438a2014-10-01 16:39:37 -0700145 return pktin.getInPort();
tom7ef8ff92014-09-17 13:08:06 -0700146 }
Jonathan Hartcc36be82015-04-09 11:54:56 -0700147 return pktin.getMatch().get(MatchField.IN_PORT);
tom7ef8ff92014-09-17 13:08:06 -0700148 }
149
150 @Override
151 public byte[] unparsed() {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900152 checkPermission(PACKET_READ);
tom7ef8ff92014-09-17 13:08:06 -0700153
154 return pktin.getData().clone();
155
156 }
157
158 private OFActionOutput buildOutput(Integer port) {
159 OFActionOutput act = sw.factory().actions()
160 .buildOutput()
161 .setPort(OFPort.of(port))
162 .build();
163 return act;
164 }
165
166 @Override
167 public boolean block() {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900168 checkPermission(PACKET_WRITE);
Changhoon Yoon541ef712015-05-23 17:18:34 +0900169
tom7ef8ff92014-09-17 13:08:06 -0700170 return free.getAndSet(false);
171 }
172
173 @Override
174 public boolean isHandled() {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900175 checkPermission(PACKET_READ);
Changhoon Yoon541ef712015-05-23 17:18:34 +0900176
tom7ef8ff92014-09-17 13:08:06 -0700177 return !free.get();
178 }
179
alshabibe9d3a322014-09-23 15:18:33 -0700180 @Override
181 public boolean isBuffered() {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900182 checkPermission(PACKET_READ);
Changhoon Yoon541ef712015-05-23 17:18:34 +0900183
alshabibe9d3a322014-09-23 15:18:33 -0700184 return isBuffered;
185 }
186
Charles Chancb13d122016-02-10 13:03:40 -0800187 @Override
188 public Optional<Long> cookie() {
189 checkPermission(PACKET_READ);
190 if (pktin.getVersion() != OFVersion.OF_10) {
191 return Optional.of(pktin.getCookie().getValue());
192 } else {
193 return Optional.empty();
194 }
195 }
196
tom7ef8ff92014-09-17 13:08:06 -0700197}