blob: f4a7b9d7f9457ac3f7ebb71412d4aeb69140bdba [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 */
alshabib452234e2014-11-25 00:03:49 -050016package org.onlab.onos.openflow.drivers;
tom7ef8ff92014-09-17 13:08:06 -070017
tom9c94c5b2014-09-17 13:14:42 -070018import org.onlab.onos.openflow.controller.Dpid;
19import org.onlab.onos.openflow.controller.driver.AbstractOpenFlowSwitch;
20import org.onlab.onos.openflow.controller.driver.SwitchDriverSubHandshakeAlreadyStarted;
21import org.onlab.onos.openflow.controller.driver.SwitchDriverSubHandshakeCompleted;
22import org.onlab.onos.openflow.controller.driver.SwitchDriverSubHandshakeNotStarted;
tom7ef8ff92014-09-17 13:08:06 -070023import org.projectfloodlight.openflow.protocol.OFBarrierRequest;
24import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
25import org.projectfloodlight.openflow.protocol.OFFactory;
26import org.projectfloodlight.openflow.protocol.OFMatchV3;
27import org.projectfloodlight.openflow.protocol.OFMessage;
28import org.projectfloodlight.openflow.protocol.OFOxmList;
29import org.projectfloodlight.openflow.protocol.action.OFAction;
30import org.projectfloodlight.openflow.protocol.instruction.OFInstruction;
31import org.projectfloodlight.openflow.types.OFBufferId;
32import org.projectfloodlight.openflow.types.OFPort;
33import org.projectfloodlight.openflow.types.TableId;
tom7ef8ff92014-09-17 13:08:06 -070034
alshabib452234e2014-11-25 00:03:49 -050035import java.util.ArrayList;
36import java.util.Collections;
37import java.util.List;
38import java.util.concurrent.atomic.AtomicBoolean;
39
tom7ef8ff92014-09-17 13:08:06 -070040/**
41 * OFDescriptionStatistics Vendor (Manufacturer Desc.): Nicira, Inc. Make
42 * (Hardware Desc.) : Open vSwitch Model (Datapath Desc.) : None Software :
43 * 2.1.0 (or whatever version + build) Serial : None
44 */
45public class OFSwitchImplOVS13 extends AbstractOpenFlowSwitch {
46
tom7ef8ff92014-09-17 13:08:06 -070047 private final AtomicBoolean driverHandshakeComplete;
48 private OFFactory factory;
49 private long barrierXidToWaitFor = -1;
50
51 private static final short MIN_PRIORITY = 0x0;
52 private static final int OFPCML_NO_BUFFER = 0xffff;
53
54 public OFSwitchImplOVS13(Dpid dpid, OFDescStatsReply desc) {
55 super(dpid);
56 driverHandshakeComplete = new AtomicBoolean(false);
57 setSwitchDescription(desc);
58 }
59
60 @Override
61 public String toString() {
62 return "OFSwitchImplOVS13 [" + ((channel != null)
63 ? channel.getRemoteAddress() : "?")
64 + " DPID[" + ((getStringId() != null) ? getStringId() : "?") + "]]";
65 }
66
67 @Override
68 public void startDriverHandshake() {
69 log.debug("Starting driver handshake for sw {}", getStringId());
70 if (startDriverHandshakeCalled) {
71 throw new SwitchDriverSubHandshakeAlreadyStarted();
72 }
73 startDriverHandshakeCalled = true;
74 factory = factory();
75 configureSwitch();
76 }
77
78 @Override
79 public boolean isDriverHandshakeComplete() {
80 if (!startDriverHandshakeCalled) {
81 throw new SwitchDriverSubHandshakeNotStarted();
82 }
83 return driverHandshakeComplete.get();
84 }
85
86 @Override
87 public void processDriverHandshakeMessage(OFMessage m) {
88 if (!startDriverHandshakeCalled) {
89 throw new SwitchDriverSubHandshakeNotStarted();
90 }
91 if (driverHandshakeComplete.get()) {
92 throw new SwitchDriverSubHandshakeCompleted(m);
93 }
94
95 switch (m.getType()) {
96 case BARRIER_REPLY:
97 if (m.getXid() == barrierXidToWaitFor) {
98 driverHandshakeComplete.set(true);
99 }
100 break;
101
102 case ERROR:
103 log.error("Switch {} Error {}", getStringId(), m);
104 break;
105
106 case FEATURES_REPLY:
107 break;
108 case FLOW_REMOVED:
109 break;
110 case GET_ASYNC_REPLY:
111 // OFAsyncGetReply asrep = (OFAsyncGetReply)m;
112 // decodeAsyncGetReply(asrep);
113 break;
114
115 case PACKET_IN:
116 break;
117 case PORT_STATUS:
118 break;
119 case QUEUE_GET_CONFIG_REPLY:
120 break;
121 case ROLE_REPLY:
122 break;
123
124 case STATS_REPLY:
125 // processStatsReply((OFStatsReply) m);
126 break;
127
128 default:
129 log.debug("Received message {} during switch-driver subhandshake "
130 + "from switch {} ... Ignoring message", m, getStringId());
131
132 }
133 }
134
135
136 private void configureSwitch() {
137 populateTableMissEntry(0, true, false, false, 0);
138 sendBarrier(true);
139 }
140
141
142 private void sendBarrier(boolean finalBarrier) {
143 int xid = getNextTransactionId();
144 if (finalBarrier) {
145 barrierXidToWaitFor = xid;
146 }
147 OFBarrierRequest br = factory
148 .buildBarrierRequest()
149 .setXid(xid)
150 .build();
alshabib19fdc122014-10-03 11:38:19 -0700151 write(br);
tom7ef8ff92014-09-17 13:08:06 -0700152 }
153
154 @Override
155 public Boolean supportNxRole() {
156 return false;
157 }
158
159 @Override
160 public void write(OFMessage msg) {
161 channel.write(Collections.singletonList(msg));
162
163 }
164
165 @Override
166 public void write(List<OFMessage> msgs) {
167 channel.write(msgs);
168 }
169
170 /**
171 * By default if none of the booleans in the call are set, then the
172 * table-miss entry is added with no instructions, which means that pipeline
173 * execution will stop, and the action set associated with the packet will
174 * be executed.
175 *
176 * @param tableToAdd
177 * @param toControllerNow as an APPLY_ACTION instruction
178 * @param toControllerWrite as a WRITE_ACITION instruction
179 * @param toTable as a GOTO_TABLE instruction
180 * @param tableToSend
181 */
182 @SuppressWarnings("unchecked")
183 private void populateTableMissEntry(int tableToAdd, boolean toControllerNow,
184 boolean toControllerWrite,
185 boolean toTable, int tableToSend) {
186 OFOxmList oxmList = OFOxmList.EMPTY;
187 OFMatchV3 match = factory.buildMatchV3()
188 .setOxmList(oxmList)
189 .build();
190 OFAction outc = factory.actions()
191 .buildOutput()
192 .setPort(OFPort.CONTROLLER)
193 .setMaxLen(OFPCML_NO_BUFFER)
194 .build();
195 List<OFInstruction> instructions = new ArrayList<OFInstruction>();
196 if (toControllerNow) {
197 // table-miss instruction to send to controller immediately
198 OFInstruction instr = factory.instructions()
199 .buildApplyActions()
200 .setActions(Collections.singletonList(outc))
201 .build();
202 instructions.add(instr);
203 }
204
205 if (toControllerWrite) {
206 // table-miss instruction to write-action to send to controller
207 // this will be executed whenever the action-set gets executed
208 OFInstruction instr = factory.instructions()
209 .buildWriteActions()
210 .setActions(Collections.singletonList(outc))
211 .build();
212 instructions.add(instr);
213 }
214
215 if (toTable) {
216 // table-miss instruction to goto-table x
217 OFInstruction instr = factory.instructions()
218 .gotoTable(TableId.of(tableToSend));
219 instructions.add(instr);
220 }
221
222 if (!toControllerNow && !toControllerWrite && !toTable) {
223 // table-miss has no instruction - at which point action-set will be
224 // executed - if there is an action to output/group in the action
225 // set
226 // the packet will be sent there, otherwise it will be dropped.
227 instructions = Collections.EMPTY_LIST;
228 }
229
230 OFMessage tableMissEntry = factory.buildFlowAdd()
231 .setTableId(TableId.of(tableToAdd))
232 .setMatch(match) // match everything
233 .setInstructions(instructions)
234 .setPriority(MIN_PRIORITY)
235 .setBufferId(OFBufferId.NO_BUFFER)
236 .setIdleTimeout(0)
237 .setHardTimeout(0)
238 .setXid(getNextTransactionId())
239 .build();
alshabib19fdc122014-10-03 11:38:19 -0700240 write(tableMissEntry);
tom7ef8ff92014-09-17 13:08:06 -0700241 }
242
243}