blob: 5fe41ddea91bf444dd525580d79b57a5edd640be [file] [log] [blame]
alshabib9af70072015-02-09 14:34:16 -08001/*
2 * Copyright 2015 Open Networking Laboratory
3 *
4 * 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
7 *
8 * 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.
15 */
16package org.onosproject.openflow.drivers;
17
18import com.google.common.collect.Lists;
sanghoc0b3c342015-03-12 17:12:10 -070019import org.onlab.packet.Ethernet;
alshabib9af70072015-02-09 14:34:16 -080020import org.onosproject.openflow.controller.Dpid;
alshabib9af70072015-02-09 14:34:16 -080021import org.onosproject.openflow.controller.driver.AbstractOpenFlowSwitch;
alshabibda1644e2015-03-13 14:01:35 -070022import org.onosproject.openflow.controller.driver.SwitchDriverSubHandshakeAlreadyStarted;
23import org.onosproject.openflow.controller.driver.SwitchDriverSubHandshakeCompleted;
24import org.onosproject.openflow.controller.driver.SwitchDriverSubHandshakeNotStarted;
25import org.projectfloodlight.openflow.protocol.OFBarrierRequest;
alshabib9af70072015-02-09 14:34:16 -080026import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
27import org.projectfloodlight.openflow.protocol.OFFlowMod;
sanghoc0b3c342015-03-12 17:12:10 -070028import org.projectfloodlight.openflow.protocol.OFMatchV3;
alshabib9af70072015-02-09 14:34:16 -080029import org.projectfloodlight.openflow.protocol.OFMessage;
30import org.projectfloodlight.openflow.protocol.OFType;
31import org.projectfloodlight.openflow.protocol.instruction.OFInstruction;
32import org.projectfloodlight.openflow.protocol.instruction.OFInstructionGotoTable;
sanghoc0b3c342015-03-12 17:12:10 -070033import org.projectfloodlight.openflow.protocol.match.Match;
34import org.projectfloodlight.openflow.protocol.match.MatchField;
35import org.projectfloodlight.openflow.protocol.oxm.OFOxm;
36import org.projectfloodlight.openflow.types.EthType;
alshabibda1644e2015-03-13 14:01:35 -070037import org.projectfloodlight.openflow.types.OFGroup;
sanghoc0b3c342015-03-12 17:12:10 -070038import org.projectfloodlight.openflow.types.OFVlanVidMatch;
alshabib9af70072015-02-09 14:34:16 -080039import org.projectfloodlight.openflow.types.TableId;
40
Saurav Das3ea46622015-04-22 14:01:34 -070041//import java.util.ArrayList;
alshabib9af70072015-02-09 14:34:16 -080042import java.util.Collections;
43import java.util.List;
alshabibda1644e2015-03-13 14:01:35 -070044import java.util.concurrent.atomic.AtomicBoolean;
alshabib9af70072015-02-09 14:34:16 -080045
46/**
47 * Corsa switch driver for BGP Router deployment.
48 */
49public class OFCorsaSwitchDriver extends AbstractOpenFlowSwitch {
alshabibda1644e2015-03-13 14:01:35 -070050
sanghoc0b3c342015-03-12 17:12:10 -070051 protected static final int FIRST_TABLE = 0;
52 protected static final int VLAN_MPLS_TABLE = 1;
53 protected static final int VLAN_TABLE = 2;
54 protected static final int MPLS_TABLE = 3;
55 protected static final int ETHER_TABLE = 4;
56 protected static final int COS_MAP_TABLE = 5;
57 protected static final int FIB_TABLE = 6;
58 protected static final int LOCAL_TABLE = 9;
59
alshabib9af70072015-02-09 14:34:16 -080060
alshabibda1644e2015-03-13 14:01:35 -070061 private AtomicBoolean handShakeComplete = new AtomicBoolean(false);
62
63 private int barrierXid;
64
alshabib9af70072015-02-09 14:34:16 -080065 OFCorsaSwitchDriver(Dpid dpid, OFDescStatsReply desc) {
66 super(dpid);
67
68 setSwitchDescription(desc);
69 }
70
Saurav Dasfa2fa932015-03-03 11:29:48 -080071 /**
72 * Used by the default sendMsg to 'write' to the switch.
73 * This method is indirectly used by generic onos services like proxyarp
74 * to request packets from the default flow table. In a multi-table
75 * pipeline, these requests are redirected to the correct table.
76 *
77 * For the Corsa switch, the equivalent table is the LOCAL TABLE
78 *
79 */
alshabib9af70072015-02-09 14:34:16 -080080 @Override
81 public void write(OFMessage msg) {
Saurav Das3ea46622015-04-22 14:01:34 -070082/* if (msg.getType() == OFType.FLOW_MOD) {
Saurav Dasfa2fa932015-03-03 11:29:48 -080083 OFFlowMod flowMod = (OFFlowMod) msg;
84 OFFlowMod.Builder builder = flowMod.createBuilder();
85 builder.setTableId(TableId.of(LOCAL_TABLE));
86 channel.write(Collections.singletonList(builder.build()));
87 } else {
88 channel.write(Collections.singletonList(msg));
89 }
Saurav Das3ea46622015-04-22 14:01:34 -070090*/
91 channel.write(Collections.singletonList(msg));
alshabib9af70072015-02-09 14:34:16 -080092 }
93
94 @Override
95 public void write(List<OFMessage> msgs) {
Saurav Das3ea46622015-04-22 14:01:34 -070096/* List<OFMessage> newMsgs = new ArrayList<OFMessage>();
Saurav Dasfa2fa932015-03-03 11:29:48 -080097 for (OFMessage msg : msgs) {
98 if (msg.getType() == OFType.FLOW_MOD) {
99 OFFlowMod flowMod = (OFFlowMod) msg;
100 OFFlowMod.Builder builder = flowMod.createBuilder();
101 builder.setTableId(TableId.of(LOCAL_TABLE));
102 newMsgs.add(builder.build());
103 } else {
104 newMsgs.add(msg);
105 }
106 }
107 channel.write(newMsgs);
Saurav Das3ea46622015-04-22 14:01:34 -0700108*/
109 channel.write(msgs);
alshabib9af70072015-02-09 14:34:16 -0800110 }
111
112 @Override
Saurav Dasfa2fa932015-03-03 11:29:48 -0800113 public void transformAndSendMsg(OFMessage msg, TableType type) {
Saurav Dasfbe25c52015-03-04 11:12:00 -0800114 log.trace("Trying to send {} of TableType {}", msg, type);
alshabib9af70072015-02-09 14:34:16 -0800115 if (msg.getType() == OFType.FLOW_MOD) {
116 OFFlowMod flowMod = (OFFlowMod) msg;
117 OFFlowMod.Builder builder = flowMod.createBuilder();
Saurav Dascbe6de32015-03-01 18:30:46 -0800118 List<OFInstruction> instructions = flowMod.getInstructions();
alshabib9af70072015-02-09 14:34:16 -0800119 List<OFInstruction> newInstructions = Lists.newArrayList();
120 for (OFInstruction i : instructions) {
121 if (i instanceof OFInstructionGotoTable) {
122 OFInstructionGotoTable gotoTable = (OFInstructionGotoTable) i;
123 TableType tid = TableType.values()[gotoTable.getTableId().getValue()];
124 switch (tid) {
125 case VLAN_MPLS:
126 newInstructions.add(
127 gotoTable.createBuilder()
128 .setTableId(TableId.of(VLAN_MPLS_TABLE)).build());
129 break;
130 case VLAN:
131 newInstructions.add(
132 gotoTable.createBuilder()
133 .setTableId(TableId.of(VLAN_TABLE)).build());
134 break;
135 case ETHER:
136 newInstructions.add(
137 gotoTable.createBuilder()
138 .setTableId(TableId.of(ETHER_TABLE)).build());
139 break;
140 case COS:
141 newInstructions.add(
142 gotoTable.createBuilder()
143 .setTableId(TableId.of(COS_MAP_TABLE)).build());
144 break;
145 case IP:
146 newInstructions.add(
147 gotoTable.createBuilder()
148 .setTableId(TableId.of(FIB_TABLE)).build());
149 break;
150 case MPLS:
151 newInstructions.add(
152 gotoTable.createBuilder()
153 .setTableId(TableId.of(MPLS_TABLE)).build());
154 break;
155 case ACL:
156 newInstructions.add(
157 gotoTable.createBuilder()
158 .setTableId(TableId.of(LOCAL_TABLE)).build());
159 break;
160 case NONE:
Saurav Dascbe6de32015-03-01 18:30:46 -0800161 log.error("Should never have to go to Table 0");
162 /*newInstructions.add(
alshabib9af70072015-02-09 14:34:16 -0800163 gotoTable.createBuilder()
164 .setTableId(TableId.of(0)).build());
Saurav Dascbe6de32015-03-01 18:30:46 -0800165 */
alshabib9af70072015-02-09 14:34:16 -0800166 break;
167 default:
168 log.warn("Unknown table type: {}", tid);
169 }
170
171 } else {
172 newInstructions.add(i);
173 }
174 }
175 switch (type) {
176 case VLAN_MPLS:
177 builder.setTableId(TableId.of(VLAN_MPLS_TABLE));
178 break;
179 case VLAN:
180 builder.setTableId(TableId.of(VLAN_TABLE));
181 break;
182 case ETHER:
183 builder.setTableId(TableId.of(ETHER_TABLE));
184 break;
185 case COS:
186 builder.setTableId(TableId.of(COS_MAP_TABLE));
187 break;
188 case IP:
189 builder.setTableId(TableId.of(FIB_TABLE));
190 break;
191 case MPLS:
192 builder.setTableId(TableId.of(MPLS_TABLE));
193 break;
194 case ACL:
195 builder.setTableId(TableId.of(LOCAL_TABLE));
196 break;
Saurav Dasfa2fa932015-03-03 11:29:48 -0800197 case FIRST:
198 builder.setTableId(TableId.of(FIRST_TABLE));
199 break;
alshabib9af70072015-02-09 14:34:16 -0800200 case NONE:
Saurav Dasfa2fa932015-03-03 11:29:48 -0800201 builder.setTableId(TableId.of(LOCAL_TABLE));
alshabib9af70072015-02-09 14:34:16 -0800202 break;
203 default:
204 log.warn("Unknown table type: {}", type);
205 }
alshabib10580802015-02-18 18:30:33 -0800206 builder.setInstructions(newInstructions);
sanghoc0b3c342015-03-12 17:12:10 -0700207
208 OFMatchV3 match = (OFMatchV3) flowMod.getMatch();
209 for (OFOxm oxm: match.getOxmList()) {
210 if (oxm.getMatchField() == MatchField.VLAN_VID &&
211 oxm.getValue().equals(OFVlanVidMatch.PRESENT)) {
212 Match.Builder mBuilder = factory().buildMatchV3();
213 mBuilder.setExact(MatchField.ETH_TYPE, EthType.of(Ethernet.TYPE_VLAN));
214 builder.setMatch(mBuilder.build());
215 }
216 }
217
Saurav Dascbe6de32015-03-01 18:30:46 -0800218 OFMessage msgnew = builder.build();
Saurav Dasfa2fa932015-03-03 11:29:48 -0800219 channel.write(Collections.singletonList(msgnew));
Saurav Dascbe6de32015-03-01 18:30:46 -0800220 log.debug("Installed {}", msgnew);
221
alshabib9af70072015-02-09 14:34:16 -0800222 } else {
Saurav Dasfa2fa932015-03-03 11:29:48 -0800223 channel.write(Collections.singletonList(msg));
224 }
225 }
226
227 @Override
228 public TableType getTableType(TableId tid) {
229 switch (tid.getValue()) {
230 case VLAN_MPLS_TABLE:
231 return TableType.VLAN_MPLS;
232 case VLAN_TABLE:
233 return TableType.VLAN;
234 case ETHER_TABLE:
235 return TableType.ETHER;
236 case COS_MAP_TABLE:
237 return TableType.COS;
238 case FIB_TABLE:
239 return TableType.IP;
240 case MPLS_TABLE:
241 return TableType.MPLS;
242 case LOCAL_TABLE:
243 return TableType.NONE;
244 case FIRST_TABLE:
245 return TableType.FIRST;
246 default:
247 log.warn("Unknown table type: {}", tid.getValue());
248 return TableType.NONE;
alshabib9af70072015-02-09 14:34:16 -0800249 }
250 }
251
252 @Override
253 public Boolean supportNxRole() {
254 return false;
255 }
256
257 @Override
alshabibda1644e2015-03-13 14:01:35 -0700258 public void startDriverHandshake() {
259 if (startDriverHandshakeCalled) {
260 throw new SwitchDriverSubHandshakeAlreadyStarted();
261 }
262 startDriverHandshakeCalled = true;
263 OFFlowMod fm = factory().buildFlowDelete()
264 .setTableId(TableId.ALL)
265 .setOutGroup(OFGroup.ANY)
266 .build();
alshabib9af70072015-02-09 14:34:16 -0800267
alshabibda1644e2015-03-13 14:01:35 -0700268 channel.write(Collections.singletonList(fm));
269
270 barrierXid = getNextTransactionId();
271 OFBarrierRequest barrier = factory().buildBarrierRequest()
272 .setXid(barrierXid).build();
273
274
275 channel.write(Collections.singletonList(barrier));
276
alshabib9af70072015-02-09 14:34:16 -0800277 }
278
279 @Override
alshabibda1644e2015-03-13 14:01:35 -0700280 public boolean isDriverHandshakeComplete() {
281 if (!startDriverHandshakeCalled) {
282 throw new SwitchDriverSubHandshakeAlreadyStarted();
283 }
284 return handShakeComplete.get();
285 }
286
287 @Override
288 public void processDriverHandshakeMessage(OFMessage m) {
289 if (!startDriverHandshakeCalled) {
290 throw new SwitchDriverSubHandshakeNotStarted();
291 }
292 if (handShakeComplete.get()) {
293 throw new SwitchDriverSubHandshakeCompleted(m);
294 }
295 if (m.getType() == OFType.BARRIER_REPLY &&
296 m.getXid() == barrierXid) {
297 handShakeComplete.set(true);
298 }
299 }
alshabib9af70072015-02-09 14:34:16 -0800300}