238c4000057d2fe1e9a5e8e06c45c48f7f49788a
[onosfw.git] /
1 /*
2  * Copyright 2014-2015 Open Networking Laboratory
3  *
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
7  *
8  *     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.
15  */
16 package org.onosproject.openflow.controller;
17
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;
30
31 import java.nio.BufferUnderflowException;
32 import java.util.Collections;
33 import java.util.concurrent.atomic.AtomicBoolean;
34
35 import static org.onosproject.security.AppGuard.checkPermission;
36 import static org.onosproject.security.AppPermission.Type.*;
37
38
39 /**
40  * Default implementation of an OpenFlowPacketContext.
41  */
42 public final class DefaultOpenFlowPacketContext implements OpenFlowPacketContext {
43
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;
49
50     private final boolean isBuffered;
51
52     private DefaultOpenFlowPacketContext(OpenFlowSwitch s, OFPacketIn pkt) {
53         this.sw = s;
54         this.pktin = pkt;
55         this.isBuffered = pktin.getBufferId() != OFBufferId.NO_BUFFER;
56     }
57
58     @Override
59     public void send() {
60         checkPermission(PACKET_WRITE);
61
62         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())
75                 .setInPort(pktinInPort())
76                 .setBufferId(OFBufferId.NO_BUFFER)
77                 .setData(pktin.getData())
78 //                .setBufferId(pktin.getBufferId())
79                 .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)
92                 .setInPort(pktinInPort())
93                 .setActions(Collections.singletonList(act))
94                 .setData(ethFrame.serialize())
95                 .build();
96     }
97
98     @Override
99     public Ethernet parsed() {
100         checkPermission(PACKET_READ);
101
102         try {
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());
108             return null;
109         }
110     }
111
112     @Override
113     public Dpid dpid() {
114         checkPermission(PACKET_READ);
115
116         return new Dpid(sw.getId());
117     }
118
119     /**
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      */
126     public static OpenFlowPacketContext packetContextFromPacketIn(OpenFlowSwitch s,
127                                                                   OFPacketIn pkt) {
128         return new DefaultOpenFlowPacketContext(s, pkt);
129     }
130
131     @Override
132     public Integer inPort() {
133         checkPermission(PACKET_READ);
134
135         return pktinInPort().getPortNumber();
136     }
137
138     private OFPort pktinInPort() {
139         if (pktin.getVersion() == OFVersion.OF_10) {
140             return pktin.getInPort();
141         }
142         return pktin.getMatch().get(MatchField.IN_PORT);
143     }
144
145     @Override
146     public byte[] unparsed() {
147         checkPermission(PACKET_READ);
148
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() {
163         checkPermission(PACKET_WRITE);
164
165         return free.getAndSet(false);
166     }
167
168     @Override
169     public boolean isHandled() {
170         checkPermission(PACKET_READ);
171
172         return !free.get();
173     }
174
175     @Override
176     public boolean isBuffered() {
177         checkPermission(PACKET_READ);
178
179         return isBuffered;
180     }
181
182 }