blob: f4ca827ccd89adc3c47e4a3bcc8a0fb5b2749000 [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;
Changhoon Yoon541ef712015-05-23 17:18:34 +090020import org.onosproject.core.Permission;
tom7ef8ff92014-09-17 13:08:06 -070021import org.projectfloodlight.openflow.protocol.OFPacketIn;
22import org.projectfloodlight.openflow.protocol.OFPacketOut;
Jonathan Hartcc36be82015-04-09 11:54:56 -070023import org.projectfloodlight.openflow.protocol.OFVersion;
tom7ef8ff92014-09-17 13:08:06 -070024import org.projectfloodlight.openflow.protocol.action.OFAction;
25import org.projectfloodlight.openflow.protocol.action.OFActionOutput;
26import org.projectfloodlight.openflow.protocol.match.MatchField;
27import org.projectfloodlight.openflow.types.OFBufferId;
28import org.projectfloodlight.openflow.types.OFPort;
Jonathan Hart2a655752015-04-07 16:46:33 -070029import org.slf4j.Logger;
30import org.slf4j.LoggerFactory;
tom1679e182014-10-09 13:50:45 -070031
Jonathan Harte46c0412015-01-20 13:19:55 -080032import java.nio.BufferUnderflowException;
33import java.util.Collections;
34import java.util.concurrent.atomic.AtomicBoolean;
35
Changhoon Yoon541ef712015-05-23 17:18:34 +090036import static org.onosproject.security.AppGuard.checkPermission;
37
38
Jonathan Hartcc36be82015-04-09 11:54:56 -070039/**
40 * Default implementation of an OpenFlowPacketContext.
41 */
tom7ef8ff92014-09-17 13:08:06 -070042public final class DefaultOpenFlowPacketContext implements OpenFlowPacketContext {
43
tom7ef8ff92014-09-17 13:08:06 -070044 private final AtomicBoolean free = new AtomicBoolean(true);
45 private final AtomicBoolean isBuilt = new AtomicBoolean(false);
46 private final OpenFlowSwitch sw;
47 private final OFPacketIn pktin;
48 private OFPacketOut pktout = null;
49
alshabibe9d3a322014-09-23 15:18:33 -070050 private final boolean isBuffered;
51
tom7ef8ff92014-09-17 13:08:06 -070052 private DefaultOpenFlowPacketContext(OpenFlowSwitch s, OFPacketIn pkt) {
53 this.sw = s;
54 this.pktin = pkt;
alshabibe9d3a322014-09-23 15:18:33 -070055 this.isBuffered = pktin.getBufferId() != OFBufferId.NO_BUFFER;
tom7ef8ff92014-09-17 13:08:06 -070056 }
57
58 @Override
59 public void send() {
Changhoon Yoon541ef712015-05-23 17:18:34 +090060 checkPermission(Permission.PACKET_WRITE);
61
tom7ef8ff92014-09-17 13:08:06 -070062 if (block() && isBuilt.get()) {
63 sw.sendMsg(pktout);
64 }
65 }
66
67 @Override
68 public void build(OFPort outPort) {
69 if (isBuilt.getAndSet(true)) {
70 return;
71 }
72 OFPacketOut.Builder builder = sw.factory().buildPacketOut();
73 OFAction act = buildOutput(outPort.getPortNumber());
74 pktout = builder.setXid(pktin.getXid())
Pavlin Radoslavov20318992015-02-04 13:41:14 -080075 .setInPort(pktinInPort())
Thomas Vachuska5f998492014-10-31 00:46:11 -070076 .setBufferId(OFBufferId.NO_BUFFER)
77 .setData(pktin.getData())
78// .setBufferId(pktin.getBufferId())
tom7ef8ff92014-09-17 13:08:06 -070079 .setActions(Collections.singletonList(act))
80 .build();
81 }
82
83 @Override
84 public void build(Ethernet ethFrame, OFPort outPort) {
85 if (isBuilt.getAndSet(true)) {
86 return;
87 }
88 OFPacketOut.Builder builder = sw.factory().buildPacketOut();
89 OFAction act = buildOutput(outPort.getPortNumber());
90 pktout = builder.setXid(pktin.getXid())
91 .setBufferId(OFBufferId.NO_BUFFER)
Pavlin Radoslavov20318992015-02-04 13:41:14 -080092 .setInPort(pktinInPort())
tom7ef8ff92014-09-17 13:08:06 -070093 .setActions(Collections.singletonList(act))
94 .setData(ethFrame.serialize())
95 .build();
96 }
97
98 @Override
99 public Ethernet parsed() {
Changhoon Yoon541ef712015-05-23 17:18:34 +0900100 checkPermission(Permission.PACKET_READ);
101
Jonathan Harte8600eb2015-01-12 10:30:45 -0800102 try {
Jonathan Hart2a655752015-04-07 16:46:33 -0700103 return Ethernet.deserializer().deserialize(pktin.getData(), 0, pktin.getData().length);
104 } catch (BufferUnderflowException | NullPointerException |
105 DeserializationException e) {
106 Logger log = LoggerFactory.getLogger(getClass());
107 log.warn("packet deserialization problem");
Jonathan Harte8600eb2015-01-12 10:30:45 -0800108 return null;
109 }
tom7ef8ff92014-09-17 13:08:06 -0700110 }
111
112 @Override
113 public Dpid dpid() {
Changhoon Yoon541ef712015-05-23 17:18:34 +0900114 checkPermission(Permission.PACKET_READ);
115
tom7ef8ff92014-09-17 13:08:06 -0700116 return new Dpid(sw.getId());
117 }
118
Jonathan Hartcc36be82015-04-09 11:54:56 -0700119 /**
120 * Creates an OpenFlow packet context based on a packet-in.
121 *
122 * @param s OpenFlow switch
123 * @param pkt OpenFlow packet-in
124 * @return the OpenFlow packet context
125 */
tom7ef8ff92014-09-17 13:08:06 -0700126 public static OpenFlowPacketContext packetContextFromPacketIn(OpenFlowSwitch s,
tom1679e182014-10-09 13:50:45 -0700127 OFPacketIn pkt) {
tom7ef8ff92014-09-17 13:08:06 -0700128 return new DefaultOpenFlowPacketContext(s, pkt);
129 }
130
131 @Override
132 public Integer inPort() {
Changhoon Yoon541ef712015-05-23 17:18:34 +0900133 checkPermission(Permission.PACKET_READ);
134
Pavlin Radoslavov20318992015-02-04 13:41:14 -0800135 return pktinInPort().getPortNumber();
alshabib6eb438a2014-10-01 16:39:37 -0700136 }
137
Pavlin Radoslavov20318992015-02-04 13:41:14 -0800138 private OFPort pktinInPort() {
Jonathan Hartcc36be82015-04-09 11:54:56 -0700139 if (pktin.getVersion() == OFVersion.OF_10) {
alshabib6eb438a2014-10-01 16:39:37 -0700140 return pktin.getInPort();
tom7ef8ff92014-09-17 13:08:06 -0700141 }
Jonathan Hartcc36be82015-04-09 11:54:56 -0700142 return pktin.getMatch().get(MatchField.IN_PORT);
tom7ef8ff92014-09-17 13:08:06 -0700143 }
144
145 @Override
146 public byte[] unparsed() {
Changhoon Yoon541ef712015-05-23 17:18:34 +0900147 checkPermission(Permission.PACKET_READ);
tom7ef8ff92014-09-17 13:08:06 -0700148
149 return pktin.getData().clone();
150
151 }
152
153 private OFActionOutput buildOutput(Integer port) {
154 OFActionOutput act = sw.factory().actions()
155 .buildOutput()
156 .setPort(OFPort.of(port))
157 .build();
158 return act;
159 }
160
161 @Override
162 public boolean block() {
Changhoon Yoon541ef712015-05-23 17:18:34 +0900163 checkPermission(Permission.PACKET_WRITE);
164
tom7ef8ff92014-09-17 13:08:06 -0700165 return free.getAndSet(false);
166 }
167
168 @Override
169 public boolean isHandled() {
Changhoon Yoon541ef712015-05-23 17:18:34 +0900170 checkPermission(Permission.PACKET_READ);
171
tom7ef8ff92014-09-17 13:08:06 -0700172 return !free.get();
173 }
174
alshabibe9d3a322014-09-23 15:18:33 -0700175 @Override
176 public boolean isBuffered() {
Changhoon Yoon541ef712015-05-23 17:18:34 +0900177 checkPermission(Permission.PACKET_READ);
178
alshabibe9d3a322014-09-23 15:18:33 -0700179 return isBuffered;
180 }
181
tom7ef8ff92014-09-17 13:08:06 -0700182}