blob: 6b32bcd1f49437dc23350554436cbd4ef90a3ca3 [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;
19import org.onosproject.openflow.controller.Dpid;
alshabib9af70072015-02-09 14:34:16 -080020import org.onosproject.openflow.controller.driver.AbstractOpenFlowSwitch;
alshabibda1644e2015-03-13 14:01:35 -070021import org.onosproject.openflow.controller.driver.SwitchDriverSubHandshakeAlreadyStarted;
22import org.onosproject.openflow.controller.driver.SwitchDriverSubHandshakeCompleted;
23import org.onosproject.openflow.controller.driver.SwitchDriverSubHandshakeNotStarted;
24import org.projectfloodlight.openflow.protocol.OFBarrierRequest;
alshabib9af70072015-02-09 14:34:16 -080025import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
26import org.projectfloodlight.openflow.protocol.OFFlowMod;
27import org.projectfloodlight.openflow.protocol.OFMessage;
28import org.projectfloodlight.openflow.protocol.OFType;
29import org.projectfloodlight.openflow.protocol.instruction.OFInstruction;
30import org.projectfloodlight.openflow.protocol.instruction.OFInstructionGotoTable;
alshabibda1644e2015-03-13 14:01:35 -070031import org.projectfloodlight.openflow.types.OFGroup;
alshabib9af70072015-02-09 14:34:16 -080032import org.projectfloodlight.openflow.types.TableId;
33
Saurav Dasfa2fa932015-03-03 11:29:48 -080034import java.util.ArrayList;
alshabib9af70072015-02-09 14:34:16 -080035import java.util.Collections;
36import java.util.List;
alshabibda1644e2015-03-13 14:01:35 -070037import java.util.concurrent.atomic.AtomicBoolean;
alshabib9af70072015-02-09 14:34:16 -080038
39/**
40 * Corsa switch driver for BGP Router deployment.
41 */
42public class OFCorsaSwitchDriver extends AbstractOpenFlowSwitch {
alshabibda1644e2015-03-13 14:01:35 -070043
Saurav Dasfa2fa932015-03-03 11:29:48 -080044 private static final int FIRST_TABLE = 0;
alshabib9af70072015-02-09 14:34:16 -080045 private static final int VLAN_MPLS_TABLE = 1;
46 private static final int VLAN_TABLE = 2;
47 private static final int MPLS_TABLE = 3;
48 private static final int ETHER_TABLE = 4;
49 private static final int COS_MAP_TABLE = 5;
50 private static final int FIB_TABLE = 6;
51 private static final int LOCAL_TABLE = 9;
52
alshabibda1644e2015-03-13 14:01:35 -070053 private AtomicBoolean handShakeComplete = new AtomicBoolean(false);
54
55 private int barrierXid;
56
alshabib9af70072015-02-09 14:34:16 -080057 OFCorsaSwitchDriver(Dpid dpid, OFDescStatsReply desc) {
58 super(dpid);
59
60 setSwitchDescription(desc);
61 }
62
Saurav Dasfa2fa932015-03-03 11:29:48 -080063 /**
64 * Used by the default sendMsg to 'write' to the switch.
65 * This method is indirectly used by generic onos services like proxyarp
66 * to request packets from the default flow table. In a multi-table
67 * pipeline, these requests are redirected to the correct table.
68 *
69 * For the Corsa switch, the equivalent table is the LOCAL TABLE
70 *
71 */
alshabib9af70072015-02-09 14:34:16 -080072 @Override
73 public void write(OFMessage msg) {
Saurav Dasfa2fa932015-03-03 11:29:48 -080074 if (msg.getType() == OFType.FLOW_MOD) {
75 OFFlowMod flowMod = (OFFlowMod) msg;
76 OFFlowMod.Builder builder = flowMod.createBuilder();
77 builder.setTableId(TableId.of(LOCAL_TABLE));
78 channel.write(Collections.singletonList(builder.build()));
79 } else {
80 channel.write(Collections.singletonList(msg));
81 }
alshabib9af70072015-02-09 14:34:16 -080082 }
83
84 @Override
85 public void write(List<OFMessage> msgs) {
Saurav Dasfa2fa932015-03-03 11:29:48 -080086 List<OFMessage> newMsgs = new ArrayList<OFMessage>();
87 for (OFMessage msg : msgs) {
88 if (msg.getType() == OFType.FLOW_MOD) {
89 OFFlowMod flowMod = (OFFlowMod) msg;
90 OFFlowMod.Builder builder = flowMod.createBuilder();
91 builder.setTableId(TableId.of(LOCAL_TABLE));
92 newMsgs.add(builder.build());
93 } else {
94 newMsgs.add(msg);
95 }
96 }
97 channel.write(newMsgs);
alshabib9af70072015-02-09 14:34:16 -080098 }
99
100 @Override
Saurav Dasfa2fa932015-03-03 11:29:48 -0800101 public void transformAndSendMsg(OFMessage msg, TableType type) {
Saurav Dasfbe25c52015-03-04 11:12:00 -0800102 log.trace("Trying to send {} of TableType {}", msg, type);
alshabib9af70072015-02-09 14:34:16 -0800103 if (msg.getType() == OFType.FLOW_MOD) {
104 OFFlowMod flowMod = (OFFlowMod) msg;
105 OFFlowMod.Builder builder = flowMod.createBuilder();
Saurav Dascbe6de32015-03-01 18:30:46 -0800106 List<OFInstruction> instructions = flowMod.getInstructions();
alshabib9af70072015-02-09 14:34:16 -0800107 List<OFInstruction> newInstructions = Lists.newArrayList();
108 for (OFInstruction i : instructions) {
109 if (i instanceof OFInstructionGotoTable) {
110 OFInstructionGotoTable gotoTable = (OFInstructionGotoTable) i;
111 TableType tid = TableType.values()[gotoTable.getTableId().getValue()];
112 switch (tid) {
113 case VLAN_MPLS:
114 newInstructions.add(
115 gotoTable.createBuilder()
116 .setTableId(TableId.of(VLAN_MPLS_TABLE)).build());
117 break;
118 case VLAN:
119 newInstructions.add(
120 gotoTable.createBuilder()
121 .setTableId(TableId.of(VLAN_TABLE)).build());
122 break;
123 case ETHER:
124 newInstructions.add(
125 gotoTable.createBuilder()
126 .setTableId(TableId.of(ETHER_TABLE)).build());
127 break;
128 case COS:
129 newInstructions.add(
130 gotoTable.createBuilder()
131 .setTableId(TableId.of(COS_MAP_TABLE)).build());
132 break;
133 case IP:
134 newInstructions.add(
135 gotoTable.createBuilder()
136 .setTableId(TableId.of(FIB_TABLE)).build());
137 break;
138 case MPLS:
139 newInstructions.add(
140 gotoTable.createBuilder()
141 .setTableId(TableId.of(MPLS_TABLE)).build());
142 break;
143 case ACL:
144 newInstructions.add(
145 gotoTable.createBuilder()
146 .setTableId(TableId.of(LOCAL_TABLE)).build());
147 break;
148 case NONE:
Saurav Dascbe6de32015-03-01 18:30:46 -0800149 log.error("Should never have to go to Table 0");
150 /*newInstructions.add(
alshabib9af70072015-02-09 14:34:16 -0800151 gotoTable.createBuilder()
152 .setTableId(TableId.of(0)).build());
Saurav Dascbe6de32015-03-01 18:30:46 -0800153 */
alshabib9af70072015-02-09 14:34:16 -0800154 break;
155 default:
156 log.warn("Unknown table type: {}", tid);
157 }
158
159 } else {
160 newInstructions.add(i);
161 }
162 }
163 switch (type) {
164 case VLAN_MPLS:
165 builder.setTableId(TableId.of(VLAN_MPLS_TABLE));
166 break;
167 case VLAN:
168 builder.setTableId(TableId.of(VLAN_TABLE));
169 break;
170 case ETHER:
171 builder.setTableId(TableId.of(ETHER_TABLE));
172 break;
173 case COS:
174 builder.setTableId(TableId.of(COS_MAP_TABLE));
175 break;
176 case IP:
177 builder.setTableId(TableId.of(FIB_TABLE));
178 break;
179 case MPLS:
180 builder.setTableId(TableId.of(MPLS_TABLE));
181 break;
182 case ACL:
183 builder.setTableId(TableId.of(LOCAL_TABLE));
184 break;
Saurav Dasfa2fa932015-03-03 11:29:48 -0800185 case FIRST:
186 builder.setTableId(TableId.of(FIRST_TABLE));
187 break;
alshabib9af70072015-02-09 14:34:16 -0800188 case NONE:
Saurav Dasfa2fa932015-03-03 11:29:48 -0800189 builder.setTableId(TableId.of(LOCAL_TABLE));
alshabib9af70072015-02-09 14:34:16 -0800190 break;
191 default:
192 log.warn("Unknown table type: {}", type);
193 }
alshabib10580802015-02-18 18:30:33 -0800194 builder.setInstructions(newInstructions);
Saurav Dascbe6de32015-03-01 18:30:46 -0800195 OFMessage msgnew = builder.build();
Saurav Dasfa2fa932015-03-03 11:29:48 -0800196 channel.write(Collections.singletonList(msgnew));
Saurav Dascbe6de32015-03-01 18:30:46 -0800197 log.debug("Installed {}", msgnew);
198
alshabib9af70072015-02-09 14:34:16 -0800199 } else {
Saurav Dasfa2fa932015-03-03 11:29:48 -0800200 channel.write(Collections.singletonList(msg));
201 }
202 }
203
204 @Override
205 public TableType getTableType(TableId tid) {
206 switch (tid.getValue()) {
207 case VLAN_MPLS_TABLE:
208 return TableType.VLAN_MPLS;
209 case VLAN_TABLE:
210 return TableType.VLAN;
211 case ETHER_TABLE:
212 return TableType.ETHER;
213 case COS_MAP_TABLE:
214 return TableType.COS;
215 case FIB_TABLE:
216 return TableType.IP;
217 case MPLS_TABLE:
218 return TableType.MPLS;
219 case LOCAL_TABLE:
220 return TableType.NONE;
221 case FIRST_TABLE:
222 return TableType.FIRST;
223 default:
224 log.warn("Unknown table type: {}", tid.getValue());
225 return TableType.NONE;
alshabib9af70072015-02-09 14:34:16 -0800226 }
227 }
228
229 @Override
230 public Boolean supportNxRole() {
231 return false;
232 }
233
234 @Override
alshabibda1644e2015-03-13 14:01:35 -0700235 public void startDriverHandshake() {
236 if (startDriverHandshakeCalled) {
237 throw new SwitchDriverSubHandshakeAlreadyStarted();
238 }
239 startDriverHandshakeCalled = true;
240 OFFlowMod fm = factory().buildFlowDelete()
241 .setTableId(TableId.ALL)
242 .setOutGroup(OFGroup.ANY)
243 .build();
alshabib9af70072015-02-09 14:34:16 -0800244
alshabibda1644e2015-03-13 14:01:35 -0700245 channel.write(Collections.singletonList(fm));
246
247 barrierXid = getNextTransactionId();
248 OFBarrierRequest barrier = factory().buildBarrierRequest()
249 .setXid(barrierXid).build();
250
251
252 channel.write(Collections.singletonList(barrier));
253
alshabib9af70072015-02-09 14:34:16 -0800254 }
255
256 @Override
alshabibda1644e2015-03-13 14:01:35 -0700257 public boolean isDriverHandshakeComplete() {
258 if (!startDriverHandshakeCalled) {
259 throw new SwitchDriverSubHandshakeAlreadyStarted();
260 }
261 return handShakeComplete.get();
262 }
263
264 @Override
265 public void processDriverHandshakeMessage(OFMessage m) {
266 if (!startDriverHandshakeCalled) {
267 throw new SwitchDriverSubHandshakeNotStarted();
268 }
269 if (handShakeComplete.get()) {
270 throw new SwitchDriverSubHandshakeCompleted(m);
271 }
272 if (m.getType() == OFType.BARRIER_REPLY &&
273 m.getXid() == barrierXid) {
274 handShakeComplete.set(true);
275 }
276 }
alshabib9af70072015-02-09 14:34:16 -0800277}