blob: c8b63b4f9e75633ea7f943dad1924943c4f16330 [file] [log] [blame]
Thomas Vachuska781d18b2014-10-27 10:31:25 -07001/*
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07002 * Copyright 2014 Open Networking Laboratory
Thomas Vachuska781d18b2014-10-27 10:31:25 -07003 *
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07004 * 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
Thomas Vachuska781d18b2014-10-27 10:31:25 -07007 *
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07008 * 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.
Thomas Vachuska781d18b2014-10-27 10:31:25 -070015 */
Brian O'Connorabafb502014-12-02 22:26:20 -080016package org.onosproject.provider.of.flow.impl;
Jonathan Hart86e59352014-10-22 10:42:16 -070017
Jonathan Hart29afca32015-01-20 18:17:39 -080018import org.onlab.packet.Ip4Address;
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -080019import org.onlab.packet.Ip6Address;
Charles M.C. Chanfe421812015-01-12 18:20:51 +080020import org.onosproject.net.PortNumber;
Brian O'Connorabafb502014-12-02 22:26:20 -080021import org.onosproject.net.flow.FlowRule;
22import org.onosproject.net.flow.TrafficTreatment;
23import org.onosproject.net.flow.instructions.Instruction;
alshabib9af70072015-02-09 14:34:16 -080024import org.onosproject.net.flow.instructions.Instructions;
sangho8995ac52015-02-04 11:29:03 -080025import org.onosproject.net.flow.instructions.Instructions.GroupInstruction;
alshabib9af70072015-02-09 14:34:16 -080026import org.onosproject.net.flow.instructions.Instructions.OutputInstruction;
Brian O'Connorabafb502014-12-02 22:26:20 -080027import org.onosproject.net.flow.instructions.L0ModificationInstruction;
28import org.onosproject.net.flow.instructions.L0ModificationInstruction.ModLambdaInstruction;
29import org.onosproject.net.flow.instructions.L2ModificationInstruction;
30import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModEtherInstruction;
Jonathan Hart29afca32015-01-20 18:17:39 -080031import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModMplsLabelInstruction;
Brian O'Connorabafb502014-12-02 22:26:20 -080032import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction;
33import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanPcpInstruction;
Brian O'Connorabafb502014-12-02 22:26:20 -080034import org.onosproject.net.flow.instructions.L2ModificationInstruction.PushHeaderInstructions;
35import org.onosproject.net.flow.instructions.L3ModificationInstruction;
36import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModIPInstruction;
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -080037import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModIPv6FlowLabelInstruction;
alshabib9af70072015-02-09 14:34:16 -080038import org.onosproject.openflow.controller.OpenFlowSwitch;
Jonathan Hart86e59352014-10-22 10:42:16 -070039import org.projectfloodlight.openflow.protocol.OFFactory;
40import org.projectfloodlight.openflow.protocol.OFFlowAdd;
41import org.projectfloodlight.openflow.protocol.OFFlowDelete;
42import org.projectfloodlight.openflow.protocol.OFFlowMod;
43import org.projectfloodlight.openflow.protocol.OFFlowModFlags;
44import org.projectfloodlight.openflow.protocol.action.OFAction;
sangho8995ac52015-02-04 11:29:03 -080045import org.projectfloodlight.openflow.protocol.action.OFActionGroup;
Charles M.C. Chanfe421812015-01-12 18:20:51 +080046import org.projectfloodlight.openflow.protocol.action.OFActionOutput;
alshabib9af70072015-02-09 14:34:16 -080047import org.projectfloodlight.openflow.protocol.instruction.OFInstruction;
Jonathan Hart86e59352014-10-22 10:42:16 -070048import org.projectfloodlight.openflow.protocol.match.Match;
49import org.projectfloodlight.openflow.protocol.oxm.OFOxm;
50import org.projectfloodlight.openflow.types.CircuitSignalID;
Praseed Balakrishnan8c67d172014-11-10 10:15:41 -080051import org.projectfloodlight.openflow.types.EthType;
Jonathan Hart86e59352014-10-22 10:42:16 -070052import org.projectfloodlight.openflow.types.IPv4Address;
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -080053import org.projectfloodlight.openflow.types.IPv6Address;
54import org.projectfloodlight.openflow.types.IPv6FlowLabel;
Jonathan Hart86e59352014-10-22 10:42:16 -070055import org.projectfloodlight.openflow.types.MacAddress;
56import org.projectfloodlight.openflow.types.OFBufferId;
sangho8995ac52015-02-04 11:29:03 -080057import org.projectfloodlight.openflow.types.OFGroup;
Jonathan Hart86e59352014-10-22 10:42:16 -070058import org.projectfloodlight.openflow.types.OFPort;
59import org.projectfloodlight.openflow.types.OFVlanVidMatch;
alshabib9af70072015-02-09 14:34:16 -080060import org.projectfloodlight.openflow.types.TableId;
Praseed Balakrishnan8c67d172014-11-10 10:15:41 -080061import org.projectfloodlight.openflow.types.U32;
Jonathan Hart86e59352014-10-22 10:42:16 -070062import org.projectfloodlight.openflow.types.U64;
63import org.projectfloodlight.openflow.types.VlanPcp;
64import org.slf4j.Logger;
65import org.slf4j.LoggerFactory;
66
Jonathan Hart29afca32015-01-20 18:17:39 -080067import java.util.Collections;
68import java.util.LinkedList;
69import java.util.List;
70import java.util.Optional;
71
Jonathan Hart86e59352014-10-22 10:42:16 -070072/**
73 * Flow mod builder for OpenFlow 1.3+.
74 */
75public class FlowModBuilderVer13 extends FlowModBuilder {
76
alshabib10580802015-02-18 18:30:33 -080077 private final Logger log = LoggerFactory.getLogger(getClass());
Charles M.C. Chanfe421812015-01-12 18:20:51 +080078 private static final int OFPCML_NO_BUFFER = 0xffff;
Jonathan Hart86e59352014-10-22 10:42:16 -070079
80 private final TrafficTreatment treatment;
81
82 /**
83 * Constructor for a flow mod builder for OpenFlow 1.3.
84 *
85 * @param flowRule the flow rule to transform into a flow mod
86 * @param factory the OpenFlow factory to use to build the flow mod
Pavlin Radoslavov119fd5c2014-11-25 19:08:19 -080087 * @param xid the transaction ID
Jonathan Hart86e59352014-10-22 10:42:16 -070088 */
Brian O'Connor427a1762014-11-19 18:40:32 -080089 protected FlowModBuilderVer13(FlowRule flowRule, OFFactory factory, Optional<Long> xid) {
90 super(flowRule, factory, xid);
Jonathan Hart86e59352014-10-22 10:42:16 -070091
92 this.treatment = flowRule.treatment();
93 }
94
95 @Override
96 public OFFlowAdd buildFlowAdd() {
97 Match match = buildMatch();
Jonathan Hartd4a8bba2014-10-28 12:44:20 -070098 List<OFAction> actions = buildActions();
alshabib9af70072015-02-09 14:34:16 -080099 List<OFInstruction> instructions = buildInstructions();
Saurav Dascbe6de32015-03-01 18:30:46 -0800100
Jonathan Hartd4a8bba2014-10-28 12:44:20 -0700101 // FIXME had to revert back to using apply-actions instead of
102 // write-actions because LINC-OE apparently doesn't support
103 // write-actions. I would prefer to change this back in the future
104 // because apply-actions is an optional instruction in OF 1.3.
105
Saurav Dascbe6de32015-03-01 18:30:46 -0800106 if (actions != null) {
107 OFInstruction applyActions =
108 factory().instructions().applyActions(actions);
109 instructions.add(applyActions);
110 }
Jonathan Hart86e59352014-10-22 10:42:16 -0700111
112 long cookie = flowRule().id().value();
113
Jonathan Hart86e59352014-10-22 10:42:16 -0700114 OFFlowAdd fm = factory().buildFlowAdd()
Brian O'Connor427a1762014-11-19 18:40:32 -0800115 .setXid(xid)
Jonathan Hart86e59352014-10-22 10:42:16 -0700116 .setCookie(U64.of(cookie))
117 .setBufferId(OFBufferId.NO_BUFFER)
alshabib9af70072015-02-09 14:34:16 -0800118 .setInstructions(instructions)
Jonathan Hart86e59352014-10-22 10:42:16 -0700119 .setMatch(match)
120 .setFlags(Collections.singleton(OFFlowModFlags.SEND_FLOW_REM))
121 .setPriority(flowRule().priority())
alshabib10580802015-02-18 18:30:33 -0800122 .setTableId(TableId.of(flowRule().type().ordinal()))
Jonathan Hart86e59352014-10-22 10:42:16 -0700123 .build();
124
125 return fm;
126 }
127
128 @Override
129 public OFFlowMod buildFlowMod() {
130 Match match = buildMatch();
Jonathan Hartd4a8bba2014-10-28 12:44:20 -0700131 List<OFAction> actions = buildActions();
alshabib9af70072015-02-09 14:34:16 -0800132 List<OFInstruction> instructions = buildInstructions();
Jonathan Harteda33872015-02-18 10:22:32 -0800133
Saurav Dascbe6de32015-03-01 18:30:46 -0800134 if (actions != null) {
135 OFInstruction applyActions =
136 factory().instructions().applyActions(actions);
137 instructions.add(applyActions);
138 }
Jonathan Hart86e59352014-10-22 10:42:16 -0700139
140 long cookie = flowRule().id().value();
141
Jonathan Hart86e59352014-10-22 10:42:16 -0700142 OFFlowMod fm = factory().buildFlowModify()
Brian O'Connor427a1762014-11-19 18:40:32 -0800143 .setXid(xid)
Jonathan Hart86e59352014-10-22 10:42:16 -0700144 .setCookie(U64.of(cookie))
145 .setBufferId(OFBufferId.NO_BUFFER)
alshabib9af70072015-02-09 14:34:16 -0800146 .setInstructions(instructions)
Jonathan Hart86e59352014-10-22 10:42:16 -0700147 .setMatch(match)
148 .setFlags(Collections.singleton(OFFlowModFlags.SEND_FLOW_REM))
149 .setPriority(flowRule().priority())
alshabib10580802015-02-18 18:30:33 -0800150 .setTableId(TableId.of(flowRule().type().ordinal()))
Jonathan Hart86e59352014-10-22 10:42:16 -0700151 .build();
152
153 return fm;
154 }
155
156 @Override
157 public OFFlowDelete buildFlowDel() {
158 Match match = buildMatch();
Jonathan Hart86e59352014-10-22 10:42:16 -0700159
160 long cookie = flowRule().id().value();
161
162 OFFlowDelete fm = factory().buildFlowDelete()
Brian O'Connor427a1762014-11-19 18:40:32 -0800163 .setXid(xid)
Jonathan Hart86e59352014-10-22 10:42:16 -0700164 .setCookie(U64.of(cookie))
165 .setBufferId(OFBufferId.NO_BUFFER)
Jonathan Hart86e59352014-10-22 10:42:16 -0700166 .setMatch(match)
167 .setFlags(Collections.singleton(OFFlowModFlags.SEND_FLOW_REM))
168 .setPriority(flowRule().priority())
169 .build();
170
171 return fm;
172 }
173
alshabib9af70072015-02-09 14:34:16 -0800174
175 private List<OFInstruction> buildInstructions() {
176 List<OFInstruction> instructions = new LinkedList<>();
177 if (treatment == null) {
178 return instructions;
179 }
180 for (Instruction i : treatment.instructions()) {
181 switch (i.type()) {
182 case TABLE:
183 instructions.add(buildTableGoto(((Instructions.TableTypeTransition) i)));
184 break;
185 default:
186 break;
187 }
188 }
189 return instructions;
190 }
191
Jonathan Hart86e59352014-10-22 10:42:16 -0700192 private List<OFAction> buildActions() {
193 List<OFAction> actions = new LinkedList<>();
Saurav Dascbe6de32015-03-01 18:30:46 -0800194 boolean tableFound = false;
Jonathan Hart86e59352014-10-22 10:42:16 -0700195 if (treatment == null) {
196 return actions;
197 }
198 for (Instruction i : treatment.instructions()) {
199 switch (i.type()) {
alshabib9af70072015-02-09 14:34:16 -0800200 case DROP:
201 log.warn("Saw drop action; assigning drop action");
202 return new LinkedList<>();
203 case L0MODIFICATION:
204 actions.add(buildL0Modification(i));
205 break;
206 case L2MODIFICATION:
207 actions.add(buildL2Modification(i));
208 break;
209 case L3MODIFICATION:
210 actions.add(buildL3Modification(i));
211 break;
212 case OUTPUT:
213 OutputInstruction out = (OutputInstruction) i;
214 OFActionOutput.Builder action = factory().actions().buildOutput()
215 .setPort(OFPort.of((int) out.port().toLong()));
216 if (out.port().equals(PortNumber.CONTROLLER)) {
217 action.setMaxLen(OFPCML_NO_BUFFER);
218 }
219 actions.add(action.build());
220 break;
221 case GROUP:
222 GroupInstruction group = (GroupInstruction) i;
223 OFActionGroup.Builder groupBuilder = factory().actions().buildGroup()
224 .setGroup(OFGroup.of(group.groupId().id()));
225 actions.add(groupBuilder.build());
226 break;
alshabib10580802015-02-18 18:30:33 -0800227 case TABLE:
228 //FIXME: should not occur here.
Saurav Dascbe6de32015-03-01 18:30:46 -0800229 tableFound = true;
alshabib10580802015-02-18 18:30:33 -0800230 break;
alshabib9af70072015-02-09 14:34:16 -0800231 default:
232 log.warn("Instruction type {} not yet implemented.", i.type());
Jonathan Hart86e59352014-10-22 10:42:16 -0700233 }
234 }
Saurav Dascbe6de32015-03-01 18:30:46 -0800235 if (tableFound && actions.isEmpty()) {
236 // handles the case where there are no actions, but there is
237 // a goto instruction for the next table
238 return null;
239 }
Jonathan Hart86e59352014-10-22 10:42:16 -0700240 return actions;
241 }
242
alshabib9af70072015-02-09 14:34:16 -0800243 private OFInstruction buildTableGoto(Instructions.TableTypeTransition i) {
244 OFInstruction instruction = factory().instructions().gotoTable(
245 TableId.of(getTableType(i.tableType()).ordinal()));
246 return instruction;
247 }
248
249 // FIXME: this has to go as well perhaps when we implement the SelectorService.
250 private OpenFlowSwitch.TableType getTableType(FlowRule.Type type) {
251 switch (type) {
252
253 case DEFAULT:
254 return OpenFlowSwitch.TableType.NONE;
255 case IP:
256 return OpenFlowSwitch.TableType.IP;
257 case MPLS:
258 return OpenFlowSwitch.TableType.MPLS;
259 case ACL:
260 return OpenFlowSwitch.TableType.ACL;
261 case VLAN_MPLS:
262 return OpenFlowSwitch.TableType.VLAN_MPLS;
263 case VLAN:
264 return OpenFlowSwitch.TableType.VLAN;
265 case ETHER:
266 return OpenFlowSwitch.TableType.ETHER;
267 case COS:
268 return OpenFlowSwitch.TableType.COS;
Saurav Dasfa2fa932015-03-03 11:29:48 -0800269 case FIRST:
270 return OpenFlowSwitch.TableType.FIRST;
alshabib9af70072015-02-09 14:34:16 -0800271 default:
272 return OpenFlowSwitch.TableType.NONE;
273 }
274 }
275
276
Jonathan Hart86e59352014-10-22 10:42:16 -0700277 private OFAction buildL0Modification(Instruction i) {
278 L0ModificationInstruction l0m = (L0ModificationInstruction) i;
279 switch (l0m.subtype()) {
280 case LAMBDA:
281 ModLambdaInstruction ml = (ModLambdaInstruction) i;
282 return factory().actions().circuit(factory().oxms().ochSigidBasic(
283 new CircuitSignalID((byte) 1, (byte) 2, ml.lambda(), (short) 1)));
284 default:
285 log.warn("Unimplemented action type {}.", l0m.subtype());
286 break;
287 }
288 return null;
289 }
290
291 private OFAction buildL2Modification(Instruction i) {
292 L2ModificationInstruction l2m = (L2ModificationInstruction) i;
293 ModEtherInstruction eth;
294 OFOxm<?> oxm = null;
295 switch (l2m.subtype()) {
Praseed Balakrishnan8c67d172014-11-10 10:15:41 -0800296 case ETH_DST:
297 eth = (ModEtherInstruction) l2m;
298 oxm = factory().oxms().ethDst(MacAddress.of(eth.mac().toLong()));
299 break;
300 case ETH_SRC:
301 eth = (ModEtherInstruction) l2m;
302 oxm = factory().oxms().ethSrc(MacAddress.of(eth.mac().toLong()));
303 break;
304 case VLAN_ID:
305 ModVlanIdInstruction vlanId = (ModVlanIdInstruction) l2m;
306 oxm = factory().oxms().vlanVid(OFVlanVidMatch.ofVlan(vlanId.vlanId().toShort()));
307 break;
308 case VLAN_PCP:
309 ModVlanPcpInstruction vlanPcp = (ModVlanPcpInstruction) l2m;
310 oxm = factory().oxms().vlanPcp(VlanPcp.of(vlanPcp.vlanPcp()));
311 break;
312 case MPLS_PUSH:
313 PushHeaderInstructions pushHeaderInstructions =
314 (PushHeaderInstructions) l2m;
315 return factory().actions().pushMpls(EthType.of(pushHeaderInstructions
Yuta HIGUCHI32a53c52015-02-08 01:25:40 -0800316 .ethernetType()));
Praseed Balakrishnan8c67d172014-11-10 10:15:41 -0800317 case MPLS_POP:
318 PushHeaderInstructions popHeaderInstructions =
319 (PushHeaderInstructions) l2m;
320 return factory().actions().popMpls(EthType.of(popHeaderInstructions
Yuta HIGUCHI32a53c52015-02-08 01:25:40 -0800321 .ethernetType()));
alshabibab21b2d2015-03-04 18:35:33 -0800322 case STRIP_VLAN:
323 return factory().actions().stripVlan();
Praseed Balakrishnan8c67d172014-11-10 10:15:41 -0800324 case MPLS_LABEL:
325 ModMplsLabelInstruction mplsLabel =
326 (ModMplsLabelInstruction) l2m;
327 oxm = factory().oxms().mplsLabel(U32.of(mplsLabel.label()
328 .longValue()));
Praseed Balakrishnan8c67d172014-11-10 10:15:41 -0800329 break;
sangho3f97a17d2015-01-29 22:56:29 -0800330 case DEC_MPLS_TTL:
331 return factory().actions().decMplsTtl();
Saurav Dasfbe25c52015-03-04 11:12:00 -0800332 case VLAN_POP:
333 return factory().actions().popVlan();
Praseed Balakrishnan8c67d172014-11-10 10:15:41 -0800334 default:
335 log.warn("Unimplemented action type {}.", l2m.subtype());
336 break;
Jonathan Hart86e59352014-10-22 10:42:16 -0700337 }
338
339 if (oxm != null) {
340 return factory().actions().buildSetField().setField(oxm).build();
341 }
342 return null;
343 }
344
345 private OFAction buildL3Modification(Instruction i) {
346 L3ModificationInstruction l3m = (L3ModificationInstruction) i;
347 ModIPInstruction ip;
Pavlin Radoslavov23e398d2014-11-05 15:17:57 -0800348 Ip4Address ip4;
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800349 Ip6Address ip6;
Jonathan Hart86e59352014-10-22 10:42:16 -0700350 OFOxm<?> oxm = null;
351 switch (l3m.subtype()) {
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800352 case IPV4_SRC:
353 ip = (ModIPInstruction) i;
354 ip4 = ip.ip().getIp4Address();
355 oxm = factory().oxms().ipv4Src(IPv4Address.of(ip4.toInt()));
356 break;
357 case IPV4_DST:
Jonathan Hart86e59352014-10-22 10:42:16 -0700358 ip = (ModIPInstruction) i;
Pavlin Radoslavov23e398d2014-11-05 15:17:57 -0800359 ip4 = ip.ip().getIp4Address();
360 oxm = factory().oxms().ipv4Dst(IPv4Address.of(ip4.toInt()));
Ray Milkey241b96a2014-11-17 13:08:20 -0800361 break;
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800362 case IPV6_SRC:
Jonathan Hart86e59352014-10-22 10:42:16 -0700363 ip = (ModIPInstruction) i;
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800364 ip6 = ip.ip().getIp6Address();
365 oxm = factory().oxms().ipv6Src(IPv6Address.of(ip6.toOctets()));
366 break;
367 case IPV6_DST:
368 ip = (ModIPInstruction) i;
369 ip6 = ip.ip().getIp6Address();
370 oxm = factory().oxms().ipv6Dst(IPv6Address.of(ip6.toOctets()));
371 break;
372 case IPV6_FLABEL:
373 ModIPv6FlowLabelInstruction flowLabelInstruction =
374 (ModIPv6FlowLabelInstruction) i;
375 int flowLabel = flowLabelInstruction.flowLabel();
376 oxm = factory().oxms().ipv6Flabel(IPv6FlowLabel.of(flowLabel));
Ray Milkey241b96a2014-11-17 13:08:20 -0800377 break;
sangho3f97a17d2015-01-29 22:56:29 -0800378 case DEC_TTL:
379 return factory().actions().decNwTtl();
380 case TTL_IN:
381 return factory().actions().copyTtlIn();
382 case TTL_OUT:
383 return factory().actions().copyTtlOut();
Jonathan Hart86e59352014-10-22 10:42:16 -0700384 default:
385 log.warn("Unimplemented action type {}.", l3m.subtype());
386 break;
387 }
388
389 if (oxm != null) {
390 return factory().actions().buildSetField().setField(oxm).build();
391 }
392 return null;
393 }
394
395}