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