2 * Copyright 2014-2015 Open Networking Laboratory
4 * 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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 package org.onosproject.openflow.controller;
18 import org.onlab.packet.DeserializationException;
19 import org.onlab.packet.Ethernet;
20 import org.projectfloodlight.openflow.protocol.OFPacketIn;
21 import org.projectfloodlight.openflow.protocol.OFPacketOut;
22 import org.projectfloodlight.openflow.protocol.OFVersion;
23 import org.projectfloodlight.openflow.protocol.action.OFAction;
24 import org.projectfloodlight.openflow.protocol.action.OFActionOutput;
25 import org.projectfloodlight.openflow.protocol.match.MatchField;
26 import org.projectfloodlight.openflow.types.OFBufferId;
27 import org.projectfloodlight.openflow.types.OFPort;
28 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory;
31 import java.nio.BufferUnderflowException;
32 import java.util.Collections;
33 import java.util.concurrent.atomic.AtomicBoolean;
35 import static org.onosproject.security.AppGuard.checkPermission;
36 import static org.onosproject.security.AppPermission.Type.*;
40 * Default implementation of an OpenFlowPacketContext.
42 public final class DefaultOpenFlowPacketContext implements OpenFlowPacketContext {
44 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;
50 private final boolean isBuffered;
52 private DefaultOpenFlowPacketContext(OpenFlowSwitch s, OFPacketIn pkt) {
55 this.isBuffered = pktin.getBufferId() != OFBufferId.NO_BUFFER;
60 checkPermission(PACKET_WRITE);
62 if (block() && isBuilt.get()) {
68 public void build(OFPort outPort) {
69 if (isBuilt.getAndSet(true)) {
72 OFPacketOut.Builder builder = sw.factory().buildPacketOut();
73 OFAction act = buildOutput(outPort.getPortNumber());
74 pktout = builder.setXid(pktin.getXid())
75 .setInPort(pktinInPort())
76 .setBufferId(OFBufferId.NO_BUFFER)
77 .setData(pktin.getData())
78 // .setBufferId(pktin.getBufferId())
79 .setActions(Collections.singletonList(act))
84 public void build(Ethernet ethFrame, OFPort outPort) {
85 if (isBuilt.getAndSet(true)) {
88 OFPacketOut.Builder builder = sw.factory().buildPacketOut();
89 OFAction act = buildOutput(outPort.getPortNumber());
90 pktout = builder.setXid(pktin.getXid())
91 .setBufferId(OFBufferId.NO_BUFFER)
92 .setInPort(pktinInPort())
93 .setActions(Collections.singletonList(act))
94 .setData(ethFrame.serialize())
99 public Ethernet parsed() {
100 checkPermission(PACKET_READ);
103 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 : {}", e.getMessage());
114 checkPermission(PACKET_READ);
116 return new Dpid(sw.getId());
120 * Creates an OpenFlow packet context based on a packet-in.
122 * @param s OpenFlow switch
123 * @param pkt OpenFlow packet-in
124 * @return the OpenFlow packet context
126 public static OpenFlowPacketContext packetContextFromPacketIn(OpenFlowSwitch s,
128 return new DefaultOpenFlowPacketContext(s, pkt);
132 public Integer inPort() {
133 checkPermission(PACKET_READ);
135 return pktinInPort().getPortNumber();
138 private OFPort pktinInPort() {
139 if (pktin.getVersion() == OFVersion.OF_10) {
140 return pktin.getInPort();
142 return pktin.getMatch().get(MatchField.IN_PORT);
146 public byte[] unparsed() {
147 checkPermission(PACKET_READ);
149 return pktin.getData().clone();
153 private OFActionOutput buildOutput(Integer port) {
154 OFActionOutput act = sw.factory().actions()
156 .setPort(OFPort.of(port))
162 public boolean block() {
163 checkPermission(PACKET_WRITE);
165 return free.getAndSet(false);
169 public boolean isHandled() {
170 checkPermission(PACKET_READ);
176 public boolean isBuffered() {
177 checkPermission(PACKET_READ);