blob: 7924b9d69a8d2f7875818f67d12605e913f89581 [file] [log] [blame]
Thomas Vachuska781d18b2014-10-27 10:31:25 -07001/*
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07002 * Copyright 2014 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 */
tom9c94c5b2014-09-17 13:14:42 -070016package org.onlab.onos.openflow.controller;
tom7ef8ff92014-09-17 13:08:06 -070017
Marc De Leenheer49087752014-10-23 13:54:09 -070018
19import java.util.Collections;
20import java.util.concurrent.atomic.AtomicBoolean;
21
tom7ef8ff92014-09-17 13:08:06 -070022import org.onlab.packet.Ethernet;
23import org.projectfloodlight.openflow.protocol.OFPacketIn;
24import org.projectfloodlight.openflow.protocol.OFPacketOut;
25import org.projectfloodlight.openflow.protocol.action.OFAction;
26import org.projectfloodlight.openflow.protocol.action.OFActionOutput;
27import org.projectfloodlight.openflow.protocol.match.MatchField;
28import org.projectfloodlight.openflow.types.OFBufferId;
29import org.projectfloodlight.openflow.types.OFPort;
tom1679e182014-10-09 13:50:45 -070030
tom7ef8ff92014-09-17 13:08:06 -070031public final class DefaultOpenFlowPacketContext implements OpenFlowPacketContext {
32
tom7ef8ff92014-09-17 13:08:06 -070033 private final AtomicBoolean free = new AtomicBoolean(true);
34 private final AtomicBoolean isBuilt = new AtomicBoolean(false);
35 private final OpenFlowSwitch sw;
36 private final OFPacketIn pktin;
37 private OFPacketOut pktout = null;
38
alshabibe9d3a322014-09-23 15:18:33 -070039 private final boolean isBuffered;
40
tom7ef8ff92014-09-17 13:08:06 -070041 private DefaultOpenFlowPacketContext(OpenFlowSwitch s, OFPacketIn pkt) {
42 this.sw = s;
43 this.pktin = pkt;
alshabibe9d3a322014-09-23 15:18:33 -070044 this.isBuffered = pktin.getBufferId() != OFBufferId.NO_BUFFER;
tom7ef8ff92014-09-17 13:08:06 -070045 }
46
47 @Override
48 public void send() {
49 if (block() && isBuilt.get()) {
50 sw.sendMsg(pktout);
51 }
52 }
53
54 @Override
55 public void build(OFPort outPort) {
56 if (isBuilt.getAndSet(true)) {
57 return;
58 }
59 OFPacketOut.Builder builder = sw.factory().buildPacketOut();
60 OFAction act = buildOutput(outPort.getPortNumber());
61 pktout = builder.setXid(pktin.getXid())
alshabib6eb438a2014-10-01 16:39:37 -070062 .setInPort(inport())
Thomas Vachuska5f998492014-10-31 00:46:11 -070063 .setBufferId(OFBufferId.NO_BUFFER)
64 .setData(pktin.getData())
65// .setBufferId(pktin.getBufferId())
tom7ef8ff92014-09-17 13:08:06 -070066 .setActions(Collections.singletonList(act))
67 .build();
68 }
69
70 @Override
71 public void build(Ethernet ethFrame, OFPort outPort) {
72 if (isBuilt.getAndSet(true)) {
73 return;
74 }
75 OFPacketOut.Builder builder = sw.factory().buildPacketOut();
76 OFAction act = buildOutput(outPort.getPortNumber());
77 pktout = builder.setXid(pktin.getXid())
78 .setBufferId(OFBufferId.NO_BUFFER)
alshabib6eb438a2014-10-01 16:39:37 -070079 .setInPort(inport())
tom7ef8ff92014-09-17 13:08:06 -070080 .setActions(Collections.singletonList(act))
81 .setData(ethFrame.serialize())
82 .build();
83 }
84
85 @Override
86 public Ethernet parsed() {
87 Ethernet eth = new Ethernet();
88 eth.deserialize(pktin.getData(), 0, pktin.getTotalLen());
89 return eth;
90 }
91
92 @Override
93 public Dpid dpid() {
94 return new Dpid(sw.getId());
95 }
96
97 public static OpenFlowPacketContext packetContextFromPacketIn(OpenFlowSwitch s,
tom1679e182014-10-09 13:50:45 -070098 OFPacketIn pkt) {
tom7ef8ff92014-09-17 13:08:06 -070099 return new DefaultOpenFlowPacketContext(s, pkt);
100 }
101
102 @Override
103 public Integer inPort() {
alshabib6eb438a2014-10-01 16:39:37 -0700104 return inport().getPortNumber();
105 }
106
107
108 private OFPort inport() {
109 //FIXME: this has to change in fucking loxi
tom7ef8ff92014-09-17 13:08:06 -0700110 try {
alshabib6eb438a2014-10-01 16:39:37 -0700111 return pktin.getInPort();
tom7ef8ff92014-09-17 13:08:06 -0700112 } catch (UnsupportedOperationException e) {
alshabib6eb438a2014-10-01 16:39:37 -0700113 return pktin.getMatch().get(MatchField.IN_PORT);
tom7ef8ff92014-09-17 13:08:06 -0700114 }
115 }
116
117 @Override
118 public byte[] unparsed() {
119
120 return pktin.getData().clone();
121
122 }
123
124 private OFActionOutput buildOutput(Integer port) {
125 OFActionOutput act = sw.factory().actions()
126 .buildOutput()
127 .setPort(OFPort.of(port))
128 .build();
129 return act;
130 }
131
132 @Override
133 public boolean block() {
134 return free.getAndSet(false);
135 }
136
137 @Override
138 public boolean isHandled() {
139 return !free.get();
140 }
141
alshabibe9d3a322014-09-23 15:18:33 -0700142 @Override
143 public boolean isBuffered() {
144 return isBuffered;
145 }
146
tom7ef8ff92014-09-17 13:08:06 -0700147}