blob: 5cbdc0fef0ca2cf30eef92be932747ff9b28527c [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 Dasfa2fa932015-03-03 11:29:48 -080041import 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 Dasfa2fa932015-03-03 11:29:48 -080082 if (msg.getType() == OFType.FLOW_MOD) {
83 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 }
alshabib9af70072015-02-09 14:34:16 -080090 }
91
92 @Override
93 public void write(List<OFMessage> msgs) {
Saurav Dasfa2fa932015-03-03 11:29:48 -080094 List<OFMessage> newMsgs = new ArrayList<OFMessage>();
95 for (OFMessage msg : msgs) {
96 if (msg.getType() == OFType.FLOW_MOD) {
97 OFFlowMod flowMod = (OFFlowMod) msg;
98 OFFlowMod.Builder builder = flowMod.createBuilder();
99 builder.setTableId(TableId.of(LOCAL_TABLE));
100 newMsgs.add(builder.build());
101 } else {
102 newMsgs.add(msg);
103 }
104 }
105 channel.write(newMsgs);
alshabib9af70072015-02-09 14:34:16 -0800106 }
107
108 @Override
Saurav Dasfa2fa932015-03-03 11:29:48 -0800109 public void transformAndSendMsg(OFMessage msg, TableType type) {
Saurav Dasfbe25c52015-03-04 11:12:00 -0800110 log.trace("Trying to send {} of TableType {}", msg, type);
alshabib9af70072015-02-09 14:34:16 -0800111 if (msg.getType() == OFType.FLOW_MOD) {
112 OFFlowMod flowMod = (OFFlowMod) msg;
113 OFFlowMod.Builder builder = flowMod.createBuilder();
Saurav Dascbe6de32015-03-01 18:30:46 -0800114 List<OFInstruction> instructions = flowMod.getInstructions();
alshabib9af70072015-02-09 14:34:16 -0800115 List<OFInstruction> newInstructions = Lists.newArrayList();
116 for (OFInstruction i : instructions) {
117 if (i instanceof OFInstructionGotoTable) {
118 OFInstructionGotoTable gotoTable = (OFInstructionGotoTable) i;
119 TableType tid = TableType.values()[gotoTable.getTableId().getValue()];
120 switch (tid) {
121 case VLAN_MPLS:
122 newInstructions.add(
123 gotoTable.createBuilder()
124 .setTableId(TableId.of(VLAN_MPLS_TABLE)).build());
125 break;
126 case VLAN:
127 newInstructions.add(
128 gotoTable.createBuilder()
129 .setTableId(TableId.of(VLAN_TABLE)).build());
130 break;
131 case ETHER:
132 newInstructions.add(
133 gotoTable.createBuilder()
134 .setTableId(TableId.of(ETHER_TABLE)).build());
135 break;
136 case COS:
137 newInstructions.add(
138 gotoTable.createBuilder()
139 .setTableId(TableId.of(COS_MAP_TABLE)).build());
140 break;
141 case IP:
142 newInstructions.add(
143 gotoTable.createBuilder()
144 .setTableId(TableId.of(FIB_TABLE)).build());
145 break;
146 case MPLS:
147 newInstructions.add(
148 gotoTable.createBuilder()
149 .setTableId(TableId.of(MPLS_TABLE)).build());
150 break;
151 case ACL:
152 newInstructions.add(
153 gotoTable.createBuilder()
154 .setTableId(TableId.of(LOCAL_TABLE)).build());
155 break;
156 case NONE:
Saurav Dascbe6de32015-03-01 18:30:46 -0800157 log.error("Should never have to go to Table 0");
158 /*newInstructions.add(
alshabib9af70072015-02-09 14:34:16 -0800159 gotoTable.createBuilder()
160 .setTableId(TableId.of(0)).build());
Saurav Dascbe6de32015-03-01 18:30:46 -0800161 */
alshabib9af70072015-02-09 14:34:16 -0800162 break;
163 default:
164 log.warn("Unknown table type: {}", tid);
165 }
166
167 } else {
168 newInstructions.add(i);
169 }
170 }
171 switch (type) {
172 case VLAN_MPLS:
173 builder.setTableId(TableId.of(VLAN_MPLS_TABLE));
174 break;
175 case VLAN:
176 builder.setTableId(TableId.of(VLAN_TABLE));
177 break;
178 case ETHER:
179 builder.setTableId(TableId.of(ETHER_TABLE));
180 break;
181 case COS:
182 builder.setTableId(TableId.of(COS_MAP_TABLE));
183 break;
184 case IP:
185 builder.setTableId(TableId.of(FIB_TABLE));
186 break;
187 case MPLS:
188 builder.setTableId(TableId.of(MPLS_TABLE));
189 break;
190 case ACL:
191 builder.setTableId(TableId.of(LOCAL_TABLE));
192 break;
Saurav Dasfa2fa932015-03-03 11:29:48 -0800193 case FIRST:
194 builder.setTableId(TableId.of(FIRST_TABLE));
195 break;
alshabib9af70072015-02-09 14:34:16 -0800196 case NONE:
Saurav Dasfa2fa932015-03-03 11:29:48 -0800197 builder.setTableId(TableId.of(LOCAL_TABLE));
alshabib9af70072015-02-09 14:34:16 -0800198 break;
199 default:
200 log.warn("Unknown table type: {}", type);
201 }
alshabib10580802015-02-18 18:30:33 -0800202 builder.setInstructions(newInstructions);
sanghoc0b3c342015-03-12 17:12:10 -0700203
204 OFMatchV3 match = (OFMatchV3) flowMod.getMatch();
205 for (OFOxm oxm: match.getOxmList()) {
206 if (oxm.getMatchField() == MatchField.VLAN_VID &&
207 oxm.getValue().equals(OFVlanVidMatch.PRESENT)) {
208 Match.Builder mBuilder = factory().buildMatchV3();
209 mBuilder.setExact(MatchField.ETH_TYPE, EthType.of(Ethernet.TYPE_VLAN));
210 builder.setMatch(mBuilder.build());
211 }
212 }
213
Saurav Dascbe6de32015-03-01 18:30:46 -0800214 OFMessage msgnew = builder.build();
Saurav Dasfa2fa932015-03-03 11:29:48 -0800215 channel.write(Collections.singletonList(msgnew));
Saurav Dascbe6de32015-03-01 18:30:46 -0800216 log.debug("Installed {}", msgnew);
217
alshabib9af70072015-02-09 14:34:16 -0800218 } else {
Saurav Dasfa2fa932015-03-03 11:29:48 -0800219 channel.write(Collections.singletonList(msg));
220 }
221 }
222
223 @Override
224 public TableType getTableType(TableId tid) {
225 switch (tid.getValue()) {
226 case VLAN_MPLS_TABLE:
227 return TableType.VLAN_MPLS;
228 case VLAN_TABLE:
229 return TableType.VLAN;
230 case ETHER_TABLE:
231 return TableType.ETHER;
232 case COS_MAP_TABLE:
233 return TableType.COS;
234 case FIB_TABLE:
235 return TableType.IP;
236 case MPLS_TABLE:
237 return TableType.MPLS;
238 case LOCAL_TABLE:
239 return TableType.NONE;
240 case FIRST_TABLE:
241 return TableType.FIRST;
242 default:
243 log.warn("Unknown table type: {}", tid.getValue());
244 return TableType.NONE;
alshabib9af70072015-02-09 14:34:16 -0800245 }
246 }
247
248 @Override
249 public Boolean supportNxRole() {
250 return false;
251 }
252
253 @Override
alshabibda1644e2015-03-13 14:01:35 -0700254 public void startDriverHandshake() {
255 if (startDriverHandshakeCalled) {
256 throw new SwitchDriverSubHandshakeAlreadyStarted();
257 }
258 startDriverHandshakeCalled = true;
259 OFFlowMod fm = factory().buildFlowDelete()
260 .setTableId(TableId.ALL)
261 .setOutGroup(OFGroup.ANY)
262 .build();
alshabib9af70072015-02-09 14:34:16 -0800263
alshabibda1644e2015-03-13 14:01:35 -0700264 channel.write(Collections.singletonList(fm));
265
266 barrierXid = getNextTransactionId();
267 OFBarrierRequest barrier = factory().buildBarrierRequest()
268 .setXid(barrierXid).build();
269
270
271 channel.write(Collections.singletonList(barrier));
272
alshabib9af70072015-02-09 14:34:16 -0800273 }
274
275 @Override
alshabibda1644e2015-03-13 14:01:35 -0700276 public boolean isDriverHandshakeComplete() {
277 if (!startDriverHandshakeCalled) {
278 throw new SwitchDriverSubHandshakeAlreadyStarted();
279 }
280 return handShakeComplete.get();
281 }
282
283 @Override
284 public void processDriverHandshakeMessage(OFMessage m) {
285 if (!startDriverHandshakeCalled) {
286 throw new SwitchDriverSubHandshakeNotStarted();
287 }
288 if (handShakeComplete.get()) {
289 throw new SwitchDriverSubHandshakeCompleted(m);
290 }
291 if (m.getType() == OFType.BARRIER_REPLY &&
292 m.getXid() == barrierXid) {
293 handShakeComplete.set(true);
294 }
295 }
alshabib9af70072015-02-09 14:34:16 -0800296}