blob: 52e23b33dafceefad39e5f00d623d64dc1d3c94e [file] [log] [blame]
Thomas Vachuska781d18b2014-10-27 10:31:25 -07001/*
Ray Milkey34c95902015-04-15 09:47:53 -07002 * Copyright 2014-2015 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 */
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 }
73 OFPacketOut.Builder builder = sw.factory().buildPacketOut();
74 OFAction act = buildOutput(outPort.getPortNumber());
75 pktout = builder.setXid(pktin.getXid())
Pavlin Radoslavov20318992015-02-04 13:41:14 -080076 .setInPort(pktinInPort())
Thomas Vachuska5f998492014-10-31 00:46:11 -070077 .setBufferId(OFBufferId.NO_BUFFER)
78 .setData(pktin.getData())
79// .setBufferId(pktin.getBufferId())
tom7ef8ff92014-09-17 13:08:06 -070080 .setActions(Collections.singletonList(act))
81 .build();
82 }
83
84 @Override
85 public void build(Ethernet ethFrame, OFPort outPort) {
86 if (isBuilt.getAndSet(true)) {
87 return;
88 }
89 OFPacketOut.Builder builder = sw.factory().buildPacketOut();
90 OFAction act = buildOutput(outPort.getPortNumber());
91 pktout = builder.setXid(pktin.getXid())
92 .setBufferId(OFBufferId.NO_BUFFER)
Pavlin Radoslavov20318992015-02-04 13:41:14 -080093 .setInPort(pktinInPort())
tom7ef8ff92014-09-17 13:08:06 -070094 .setActions(Collections.singletonList(act))
95 .setData(ethFrame.serialize())
96 .build();
97 }
98
99 @Override
100 public Ethernet parsed() {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900101 checkPermission(PACKET_READ);
Changhoon Yoon541ef712015-05-23 17:18:34 +0900102
Jonathan Harte8600eb2015-01-12 10:30:45 -0800103 try {
Jonathan Hart2a655752015-04-07 16:46:33 -0700104 return Ethernet.deserializer().deserialize(pktin.getData(), 0, pktin.getData().length);
105 } catch (BufferUnderflowException | NullPointerException |
106 DeserializationException e) {
107 Logger log = LoggerFactory.getLogger(getClass());
alshabiba55c1c62015-10-05 15:07:08 +0200108 log.error("packet deserialization problem : {}", e.getMessage());
Jonathan Harte8600eb2015-01-12 10:30:45 -0800109 return null;
110 }
tom7ef8ff92014-09-17 13:08:06 -0700111 }
112
113 @Override
114 public Dpid dpid() {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900115 checkPermission(PACKET_READ);
Changhoon Yoon541ef712015-05-23 17:18:34 +0900116
tom7ef8ff92014-09-17 13:08:06 -0700117 return new Dpid(sw.getId());
118 }
119
Jonathan Hartcc36be82015-04-09 11:54:56 -0700120 /**
121 * Creates an OpenFlow packet context based on a packet-in.
122 *
123 * @param s OpenFlow switch
124 * @param pkt OpenFlow packet-in
125 * @return the OpenFlow packet context
126 */
tom7ef8ff92014-09-17 13:08:06 -0700127 public static OpenFlowPacketContext packetContextFromPacketIn(OpenFlowSwitch s,
tom1679e182014-10-09 13:50:45 -0700128 OFPacketIn pkt) {
tom7ef8ff92014-09-17 13:08:06 -0700129 return new DefaultOpenFlowPacketContext(s, pkt);
130 }
131
132 @Override
133 public Integer inPort() {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900134 checkPermission(PACKET_READ);
Changhoon Yoon541ef712015-05-23 17:18:34 +0900135
Pavlin Radoslavov20318992015-02-04 13:41:14 -0800136 return pktinInPort().getPortNumber();
alshabib6eb438a2014-10-01 16:39:37 -0700137 }
138
Pavlin Radoslavov20318992015-02-04 13:41:14 -0800139 private OFPort pktinInPort() {
Jonathan Hartcc36be82015-04-09 11:54:56 -0700140 if (pktin.getVersion() == OFVersion.OF_10) {
alshabib6eb438a2014-10-01 16:39:37 -0700141 return pktin.getInPort();
tom7ef8ff92014-09-17 13:08:06 -0700142 }
Jonathan Hartcc36be82015-04-09 11:54:56 -0700143 return pktin.getMatch().get(MatchField.IN_PORT);
tom7ef8ff92014-09-17 13:08:06 -0700144 }
145
146 @Override
147 public byte[] unparsed() {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900148 checkPermission(PACKET_READ);
tom7ef8ff92014-09-17 13:08:06 -0700149
150 return pktin.getData().clone();
151
152 }
153
154 private OFActionOutput buildOutput(Integer port) {
155 OFActionOutput act = sw.factory().actions()
156 .buildOutput()
157 .setPort(OFPort.of(port))
158 .build();
159 return act;
160 }
161
162 @Override
163 public boolean block() {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900164 checkPermission(PACKET_WRITE);
Changhoon Yoon541ef712015-05-23 17:18:34 +0900165
tom7ef8ff92014-09-17 13:08:06 -0700166 return free.getAndSet(false);
167 }
168
169 @Override
170 public boolean isHandled() {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900171 checkPermission(PACKET_READ);
Changhoon Yoon541ef712015-05-23 17:18:34 +0900172
tom7ef8ff92014-09-17 13:08:06 -0700173 return !free.get();
174 }
175
alshabibe9d3a322014-09-23 15:18:33 -0700176 @Override
177 public boolean isBuffered() {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900178 checkPermission(PACKET_READ);
Changhoon Yoon541ef712015-05-23 17:18:34 +0900179
alshabibe9d3a322014-09-23 15:18:33 -0700180 return isBuffered;
181 }
182
Charles Chancb13d122016-02-10 13:03:40 -0800183 @Override
184 public Optional<Long> cookie() {
185 checkPermission(PACKET_READ);
186 if (pktin.getVersion() != OFVersion.OF_10) {
187 return Optional.of(pktin.getCookie().getValue());
188 } else {
189 return Optional.empty();
190 }
191 }
192
tom7ef8ff92014-09-17 13:08:06 -0700193}