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