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