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