blob: ac3406a9e028a70082524559ab82ffaf58ce9445 [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())
tom7ef8ff92014-09-17 13:08:06 -070063 .setBufferId(pktin.getBufferId())
64 .setActions(Collections.singletonList(act))
65 .build();
66 }
67
68 @Override
69 public void build(Ethernet ethFrame, OFPort outPort) {
70 if (isBuilt.getAndSet(true)) {
71 return;
72 }
73 OFPacketOut.Builder builder = sw.factory().buildPacketOut();
74 OFAction act = buildOutput(outPort.getPortNumber());
75 pktout = builder.setXid(pktin.getXid())
76 .setBufferId(OFBufferId.NO_BUFFER)
alshabib6eb438a2014-10-01 16:39:37 -070077 .setInPort(inport())
tom7ef8ff92014-09-17 13:08:06 -070078 .setActions(Collections.singletonList(act))
79 .setData(ethFrame.serialize())
80 .build();
81 }
82
83 @Override
84 public Ethernet parsed() {
85 Ethernet eth = new Ethernet();
86 eth.deserialize(pktin.getData(), 0, pktin.getTotalLen());
87 return eth;
88 }
89
90 @Override
91 public Dpid dpid() {
92 return new Dpid(sw.getId());
93 }
94
95 public static OpenFlowPacketContext packetContextFromPacketIn(OpenFlowSwitch s,
tom1679e182014-10-09 13:50:45 -070096 OFPacketIn pkt) {
tom7ef8ff92014-09-17 13:08:06 -070097 return new DefaultOpenFlowPacketContext(s, pkt);
98 }
99
100 @Override
101 public Integer inPort() {
alshabib6eb438a2014-10-01 16:39:37 -0700102 return inport().getPortNumber();
103 }
104
105
106 private OFPort inport() {
107 //FIXME: this has to change in fucking loxi
tom7ef8ff92014-09-17 13:08:06 -0700108 try {
alshabib6eb438a2014-10-01 16:39:37 -0700109 return pktin.getInPort();
tom7ef8ff92014-09-17 13:08:06 -0700110 } catch (UnsupportedOperationException e) {
alshabib6eb438a2014-10-01 16:39:37 -0700111 return pktin.getMatch().get(MatchField.IN_PORT);
tom7ef8ff92014-09-17 13:08:06 -0700112 }
113 }
114
115 @Override
116 public byte[] unparsed() {
117
118 return pktin.getData().clone();
119
120 }
121
122 private OFActionOutput buildOutput(Integer port) {
123 OFActionOutput act = sw.factory().actions()
124 .buildOutput()
125 .setPort(OFPort.of(port))
126 .build();
127 return act;
128 }
129
130 @Override
131 public boolean block() {
132 return free.getAndSet(false);
133 }
134
135 @Override
136 public boolean isHandled() {
137 return !free.get();
138 }
139
alshabibe9d3a322014-09-23 15:18:33 -0700140 @Override
141 public boolean isBuffered() {
142 return isBuffered;
143 }
144
tom7ef8ff92014-09-17 13:08:06 -0700145}