blob: be7e4b0872ac8aedc69938be08c200437cb8e544 [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
Marc De Leenheer49087752014-10-23 13:54:09 -070018
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;
tom1679e182014-10-09 13:50:45 -070029
Jonathan Harte46c0412015-01-20 13:19:55 -080030import java.nio.BufferUnderflowException;
31import java.util.Collections;
32import java.util.concurrent.atomic.AtomicBoolean;
33
Changhoon Yoon541ef712015-05-23 17:18:34 +090034import static org.onosproject.security.AppGuard.checkPermission;
35
36
Jonathan Hartcc36be82015-04-09 11:54:56 -070037/**
38 * Default implementation of an OpenFlowPacketContext.
39 */
tom7ef8ff92014-09-17 13:08:06 -070040public final class DefaultOpenFlowPacketContext implements OpenFlowPacketContext {
41
tom7ef8ff92014-09-17 13:08:06 -070042 private final AtomicBoolean free = new AtomicBoolean(true);
43 private final AtomicBoolean isBuilt = new AtomicBoolean(false);
44 private final OpenFlowSwitch sw;
45 private final OFPacketIn pktin;
46 private OFPacketOut pktout = null;
47
alshabibe9d3a322014-09-23 15:18:33 -070048 private final boolean isBuffered;
49
tom7ef8ff92014-09-17 13:08:06 -070050 private DefaultOpenFlowPacketContext(OpenFlowSwitch s, OFPacketIn pkt) {
51 this.sw = s;
52 this.pktin = pkt;
alshabibe9d3a322014-09-23 15:18:33 -070053 this.isBuffered = pktin.getBufferId() != OFBufferId.NO_BUFFER;
tom7ef8ff92014-09-17 13:08:06 -070054 }
55
56 @Override
57 public void send() {
Changhoon Yoon541ef712015-05-23 17:18:34 +090058 checkPermission(Permission.PACKET_WRITE);
59
tom7ef8ff92014-09-17 13:08:06 -070060 if (block() && isBuilt.get()) {
61 sw.sendMsg(pktout);
62 }
63 }
64
65 @Override
66 public void build(OFPort outPort) {
67 if (isBuilt.getAndSet(true)) {
68 return;
69 }
70 OFPacketOut.Builder builder = sw.factory().buildPacketOut();
71 OFAction act = buildOutput(outPort.getPortNumber());
72 pktout = builder.setXid(pktin.getXid())
Pavlin Radoslavov20318992015-02-04 13:41:14 -080073 .setInPort(pktinInPort())
Thomas Vachuska5f998492014-10-31 00:46:11 -070074 .setBufferId(OFBufferId.NO_BUFFER)
75 .setData(pktin.getData())
76// .setBufferId(pktin.getBufferId())
tom7ef8ff92014-09-17 13:08:06 -070077 .setActions(Collections.singletonList(act))
78 .build();
79 }
80
81 @Override
82 public void build(Ethernet ethFrame, OFPort outPort) {
83 if (isBuilt.getAndSet(true)) {
84 return;
85 }
86 OFPacketOut.Builder builder = sw.factory().buildPacketOut();
87 OFAction act = buildOutput(outPort.getPortNumber());
88 pktout = builder.setXid(pktin.getXid())
89 .setBufferId(OFBufferId.NO_BUFFER)
Pavlin Radoslavov20318992015-02-04 13:41:14 -080090 .setInPort(pktinInPort())
tom7ef8ff92014-09-17 13:08:06 -070091 .setActions(Collections.singletonList(act))
92 .setData(ethFrame.serialize())
93 .build();
94 }
95
96 @Override
97 public Ethernet parsed() {
Changhoon Yoon541ef712015-05-23 17:18:34 +090098 checkPermission(Permission.PACKET_READ);
99
tom7ef8ff92014-09-17 13:08:06 -0700100 Ethernet eth = new Ethernet();
Jonathan Harte8600eb2015-01-12 10:30:45 -0800101 try {
102 eth.deserialize(pktin.getData(), 0, pktin.getData().length);
103 return eth;
Jonathan Harte46c0412015-01-20 13:19:55 -0800104 } catch (BufferUnderflowException | NullPointerException e) {
Jonathan Harte8600eb2015-01-12 10:30:45 -0800105 return null;
106 }
tom7ef8ff92014-09-17 13:08:06 -0700107 }
108
109 @Override
110 public Dpid dpid() {
Changhoon Yoon541ef712015-05-23 17:18:34 +0900111 checkPermission(Permission.PACKET_READ);
112
tom7ef8ff92014-09-17 13:08:06 -0700113 return new Dpid(sw.getId());
114 }
115
Jonathan Hartcc36be82015-04-09 11:54:56 -0700116 /**
117 * Creates an OpenFlow packet context based on a packet-in.
118 *
119 * @param s OpenFlow switch
120 * @param pkt OpenFlow packet-in
121 * @return the OpenFlow packet context
122 */
tom7ef8ff92014-09-17 13:08:06 -0700123 public static OpenFlowPacketContext packetContextFromPacketIn(OpenFlowSwitch s,
tom1679e182014-10-09 13:50:45 -0700124 OFPacketIn pkt) {
tom7ef8ff92014-09-17 13:08:06 -0700125 return new DefaultOpenFlowPacketContext(s, pkt);
126 }
127
128 @Override
129 public Integer inPort() {
Changhoon Yoon541ef712015-05-23 17:18:34 +0900130 checkPermission(Permission.PACKET_READ);
131
Pavlin Radoslavov20318992015-02-04 13:41:14 -0800132 return pktinInPort().getPortNumber();
alshabib6eb438a2014-10-01 16:39:37 -0700133 }
134
Pavlin Radoslavov20318992015-02-04 13:41:14 -0800135 private OFPort pktinInPort() {
Jonathan Hartcc36be82015-04-09 11:54:56 -0700136 if (pktin.getVersion() == OFVersion.OF_10) {
alshabib6eb438a2014-10-01 16:39:37 -0700137 return pktin.getInPort();
tom7ef8ff92014-09-17 13:08:06 -0700138 }
Jonathan Hartcc36be82015-04-09 11:54:56 -0700139 return pktin.getMatch().get(MatchField.IN_PORT);
tom7ef8ff92014-09-17 13:08:06 -0700140 }
141
142 @Override
143 public byte[] unparsed() {
Changhoon Yoon541ef712015-05-23 17:18:34 +0900144 checkPermission(Permission.PACKET_READ);
tom7ef8ff92014-09-17 13:08:06 -0700145
146 return pktin.getData().clone();
147
148 }
149
150 private OFActionOutput buildOutput(Integer port) {
151 OFActionOutput act = sw.factory().actions()
152 .buildOutput()
153 .setPort(OFPort.of(port))
154 .build();
155 return act;
156 }
157
158 @Override
159 public boolean block() {
Changhoon Yoon541ef712015-05-23 17:18:34 +0900160 checkPermission(Permission.PACKET_WRITE);
161
tom7ef8ff92014-09-17 13:08:06 -0700162 return free.getAndSet(false);
163 }
164
165 @Override
166 public boolean isHandled() {
Changhoon Yoon541ef712015-05-23 17:18:34 +0900167 checkPermission(Permission.PACKET_READ);
168
tom7ef8ff92014-09-17 13:08:06 -0700169 return !free.get();
170 }
171
alshabibe9d3a322014-09-23 15:18:33 -0700172 @Override
173 public boolean isBuffered() {
Changhoon Yoon541ef712015-05-23 17:18:34 +0900174 checkPermission(Permission.PACKET_READ);
175
alshabibe9d3a322014-09-23 15:18:33 -0700176 return isBuffered;
177 }
178
tom7ef8ff92014-09-17 13:08:06 -0700179}