blob: e7c75fe0b7a4c00ad45d0b69988b765b96d74457 [file] [log] [blame]
Thomas Vachuska781d18b2014-10-27 10:31:25 -07001/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
tom9c94c5b2014-09-17 13:14:42 -070019package org.onlab.onos.openflow.controller;
tom7ef8ff92014-09-17 13:08:06 -070020
Marc De Leenheer49087752014-10-23 13:54:09 -070021
22import java.util.Collections;
23import java.util.concurrent.atomic.AtomicBoolean;
24
tom7ef8ff92014-09-17 13:08:06 -070025import org.onlab.packet.Ethernet;
26import org.projectfloodlight.openflow.protocol.OFPacketIn;
27import org.projectfloodlight.openflow.protocol.OFPacketOut;
28import org.projectfloodlight.openflow.protocol.action.OFAction;
29import org.projectfloodlight.openflow.protocol.action.OFActionOutput;
30import org.projectfloodlight.openflow.protocol.match.MatchField;
31import org.projectfloodlight.openflow.types.OFBufferId;
32import org.projectfloodlight.openflow.types.OFPort;
tom1679e182014-10-09 13:50:45 -070033
tom7ef8ff92014-09-17 13:08:06 -070034public final class DefaultOpenFlowPacketContext implements OpenFlowPacketContext {
35
tom7ef8ff92014-09-17 13:08:06 -070036 private final AtomicBoolean free = new AtomicBoolean(true);
37 private final AtomicBoolean isBuilt = new AtomicBoolean(false);
38 private final OpenFlowSwitch sw;
39 private final OFPacketIn pktin;
40 private OFPacketOut pktout = null;
41
alshabibe9d3a322014-09-23 15:18:33 -070042 private final boolean isBuffered;
43
tom7ef8ff92014-09-17 13:08:06 -070044 private DefaultOpenFlowPacketContext(OpenFlowSwitch s, OFPacketIn pkt) {
45 this.sw = s;
46 this.pktin = pkt;
alshabibe9d3a322014-09-23 15:18:33 -070047 this.isBuffered = pktin.getBufferId() != OFBufferId.NO_BUFFER;
tom7ef8ff92014-09-17 13:08:06 -070048 }
49
50 @Override
51 public void send() {
52 if (block() && isBuilt.get()) {
53 sw.sendMsg(pktout);
54 }
55 }
56
57 @Override
58 public void build(OFPort outPort) {
59 if (isBuilt.getAndSet(true)) {
60 return;
61 }
62 OFPacketOut.Builder builder = sw.factory().buildPacketOut();
63 OFAction act = buildOutput(outPort.getPortNumber());
64 pktout = builder.setXid(pktin.getXid())
alshabib6eb438a2014-10-01 16:39:37 -070065 .setInPort(inport())
tom7ef8ff92014-09-17 13:08:06 -070066 .setBufferId(pktin.getBufferId())
67 .setActions(Collections.singletonList(act))
68 .build();
69 }
70
71 @Override
72 public void build(Ethernet ethFrame, OFPort outPort) {
73 if (isBuilt.getAndSet(true)) {
74 return;
75 }
76 OFPacketOut.Builder builder = sw.factory().buildPacketOut();
77 OFAction act = buildOutput(outPort.getPortNumber());
78 pktout = builder.setXid(pktin.getXid())
79 .setBufferId(OFBufferId.NO_BUFFER)
alshabib6eb438a2014-10-01 16:39:37 -070080 .setInPort(inport())
tom7ef8ff92014-09-17 13:08:06 -070081 .setActions(Collections.singletonList(act))
82 .setData(ethFrame.serialize())
83 .build();
84 }
85
86 @Override
87 public Ethernet parsed() {
88 Ethernet eth = new Ethernet();
89 eth.deserialize(pktin.getData(), 0, pktin.getTotalLen());
90 return eth;
91 }
92
93 @Override
94 public Dpid dpid() {
95 return new Dpid(sw.getId());
96 }
97
98 public static OpenFlowPacketContext packetContextFromPacketIn(OpenFlowSwitch s,
tom1679e182014-10-09 13:50:45 -070099 OFPacketIn pkt) {
tom7ef8ff92014-09-17 13:08:06 -0700100 return new DefaultOpenFlowPacketContext(s, pkt);
101 }
102
103 @Override
104 public Integer inPort() {
alshabib6eb438a2014-10-01 16:39:37 -0700105 return inport().getPortNumber();
106 }
107
108
109 private OFPort inport() {
110 //FIXME: this has to change in fucking loxi
tom7ef8ff92014-09-17 13:08:06 -0700111 try {
alshabib6eb438a2014-10-01 16:39:37 -0700112 return pktin.getInPort();
tom7ef8ff92014-09-17 13:08:06 -0700113 } catch (UnsupportedOperationException e) {
alshabib6eb438a2014-10-01 16:39:37 -0700114 return pktin.getMatch().get(MatchField.IN_PORT);
tom7ef8ff92014-09-17 13:08:06 -0700115 }
116 }
117
118 @Override
119 public byte[] unparsed() {
120
121 return pktin.getData().clone();
122
123 }
124
125 private OFActionOutput buildOutput(Integer port) {
126 OFActionOutput act = sw.factory().actions()
127 .buildOutput()
128 .setPort(OFPort.of(port))
129 .build();
130 return act;
131 }
132
133 @Override
134 public boolean block() {
135 return free.getAndSet(false);
136 }
137
138 @Override
139 public boolean isHandled() {
140 return !free.get();
141 }
142
alshabibe9d3a322014-09-23 15:18:33 -0700143 @Override
144 public boolean isBuffered() {
145 return isBuffered;
146 }
147
tom7ef8ff92014-09-17 13:08:06 -0700148}