blob: 1554fa3ff242679cbc55f1909b175efd8d7bdc4f [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
alshabib346b5b32015-03-06 00:42:16 -080018import com.google.common.collect.Lists;
Jonathan Hart29afca32015-01-20 18:17:39 -080019import org.onlab.packet.Ip4Address;
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -080020import org.onlab.packet.Ip6Address;
Charles M.C. Chanfe421812015-01-12 18:20:51 +080021import org.onosproject.net.PortNumber;
Brian O'Connorabafb502014-12-02 22:26:20 -080022import org.onosproject.net.flow.FlowRule;
23import org.onosproject.net.flow.TrafficTreatment;
24import org.onosproject.net.flow.instructions.Instruction;
alshabib9af70072015-02-09 14:34:16 -080025import org.onosproject.net.flow.instructions.Instructions;
sangho8995ac52015-02-04 11:29:03 -080026import org.onosproject.net.flow.instructions.Instructions.GroupInstruction;
alshabib9af70072015-02-09 14:34:16 -080027import org.onosproject.net.flow.instructions.Instructions.OutputInstruction;
Brian O'Connorabafb502014-12-02 22:26:20 -080028import org.onosproject.net.flow.instructions.L0ModificationInstruction;
29import org.onosproject.net.flow.instructions.L0ModificationInstruction.ModLambdaInstruction;
30import org.onosproject.net.flow.instructions.L2ModificationInstruction;
31import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModEtherInstruction;
Jonathan Hart29afca32015-01-20 18:17:39 -080032import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModMplsLabelInstruction;
Brian O'Connorabafb502014-12-02 22:26:20 -080033import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction;
34import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanPcpInstruction;
Brian O'Connorabafb502014-12-02 22:26:20 -080035import org.onosproject.net.flow.instructions.L2ModificationInstruction.PushHeaderInstructions;
36import org.onosproject.net.flow.instructions.L3ModificationInstruction;
37import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModIPInstruction;
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -080038import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModIPv6FlowLabelInstruction;
alshabib9af70072015-02-09 14:34:16 -080039import org.onosproject.openflow.controller.OpenFlowSwitch;
Jonathan Hart86e59352014-10-22 10:42:16 -070040import org.projectfloodlight.openflow.protocol.OFFactory;
41import org.projectfloodlight.openflow.protocol.OFFlowAdd;
42import org.projectfloodlight.openflow.protocol.OFFlowDelete;
43import org.projectfloodlight.openflow.protocol.OFFlowMod;
44import org.projectfloodlight.openflow.protocol.OFFlowModFlags;
45import org.projectfloodlight.openflow.protocol.action.OFAction;
sangho8995ac52015-02-04 11:29:03 -080046import org.projectfloodlight.openflow.protocol.action.OFActionGroup;
Charles M.C. Chanfe421812015-01-12 18:20:51 +080047import org.projectfloodlight.openflow.protocol.action.OFActionOutput;
alshabib9af70072015-02-09 14:34:16 -080048import org.projectfloodlight.openflow.protocol.instruction.OFInstruction;
Jonathan Hart86e59352014-10-22 10:42:16 -070049import org.projectfloodlight.openflow.protocol.match.Match;
50import org.projectfloodlight.openflow.protocol.oxm.OFOxm;
51import org.projectfloodlight.openflow.types.CircuitSignalID;
Praseed Balakrishnan8c67d172014-11-10 10:15:41 -080052import org.projectfloodlight.openflow.types.EthType;
Jonathan Hart86e59352014-10-22 10:42:16 -070053import org.projectfloodlight.openflow.types.IPv4Address;
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -080054import org.projectfloodlight.openflow.types.IPv6Address;
55import org.projectfloodlight.openflow.types.IPv6FlowLabel;
Jonathan Hart86e59352014-10-22 10:42:16 -070056import org.projectfloodlight.openflow.types.MacAddress;
57import org.projectfloodlight.openflow.types.OFBufferId;
sangho8995ac52015-02-04 11:29:03 -080058import org.projectfloodlight.openflow.types.OFGroup;
Jonathan Hart86e59352014-10-22 10:42:16 -070059import org.projectfloodlight.openflow.types.OFPort;
60import org.projectfloodlight.openflow.types.OFVlanVidMatch;
alshabib9af70072015-02-09 14:34:16 -080061import org.projectfloodlight.openflow.types.TableId;
Praseed Balakrishnan8c67d172014-11-10 10:15:41 -080062import org.projectfloodlight.openflow.types.U32;
Jonathan Hart86e59352014-10-22 10:42:16 -070063import org.projectfloodlight.openflow.types.U64;
64import org.projectfloodlight.openflow.types.VlanPcp;
65import org.slf4j.Logger;
66import org.slf4j.LoggerFactory;
67
Jonathan Hart29afca32015-01-20 18:17:39 -080068import java.util.Collections;
69import java.util.LinkedList;
70import java.util.List;
71import java.util.Optional;
72
Jonathan Hart86e59352014-10-22 10:42:16 -070073/**
74 * Flow mod builder for OpenFlow 1.3+.
75 */
76public class FlowModBuilderVer13 extends FlowModBuilder {
77
alshabib10580802015-02-18 18:30:33 -080078 private final Logger log = LoggerFactory.getLogger(getClass());
Charles M.C. Chanfe421812015-01-12 18:20:51 +080079 private static final int OFPCML_NO_BUFFER = 0xffff;
Jonathan Hart86e59352014-10-22 10:42:16 -070080
81 private final TrafficTreatment treatment;
82
83 /**
84 * Constructor for a flow mod builder for OpenFlow 1.3.
85 *
86 * @param flowRule the flow rule to transform into a flow mod
87 * @param factory the OpenFlow factory to use to build the flow mod
Pavlin Radoslavov119fd5c2014-11-25 19:08:19 -080088 * @param xid the transaction ID
Jonathan Hart86e59352014-10-22 10:42:16 -070089 */
Brian O'Connor427a1762014-11-19 18:40:32 -080090 protected FlowModBuilderVer13(FlowRule flowRule, OFFactory factory, Optional<Long> xid) {
91 super(flowRule, factory, xid);
Jonathan Hart86e59352014-10-22 10:42:16 -070092
93 this.treatment = flowRule.treatment();
94 }
95
96 @Override
97 public OFFlowAdd buildFlowAdd() {
98 Match match = buildMatch();
alshabib346b5b32015-03-06 00:42:16 -080099 List<OFAction> deferredActions = buildActions(treatment.deferred());
100 List<OFAction> immediateActions = buildActions(treatment.immediate());
101 List<OFInstruction> instructions = Lists.newLinkedList();
Saurav Dascbe6de32015-03-01 18:30:46 -0800102
Jonathan Hartd4a8bba2014-10-28 12:44:20 -0700103
alshabib346b5b32015-03-06 00:42:16 -0800104 if (immediateActions.size() > 0) {
105 instructions.add(factory().instructions().applyActions(immediateActions));
106 }
107 if (treatment.clearedDeferred()) {
108 instructions.add(factory().instructions().clearActions());
109 }
110 if (deferredActions.size() > 0) {
111 instructions.add(factory().instructions().writeActions(deferredActions));
112 }
113 if (treatment.tableTransition() != null) {
114 instructions.add(buildTableGoto(treatment.tableTransition()));
Saurav Dascbe6de32015-03-01 18:30:46 -0800115 }
Jonathan Hart86e59352014-10-22 10:42:16 -0700116
117 long cookie = flowRule().id().value();
118
Jonathan Hart86e59352014-10-22 10:42:16 -0700119 OFFlowAdd fm = factory().buildFlowAdd()
Brian O'Connor427a1762014-11-19 18:40:32 -0800120 .setXid(xid)
Jonathan Hart86e59352014-10-22 10:42:16 -0700121 .setCookie(U64.of(cookie))
122 .setBufferId(OFBufferId.NO_BUFFER)
alshabib9af70072015-02-09 14:34:16 -0800123 .setInstructions(instructions)
Jonathan Hart86e59352014-10-22 10:42:16 -0700124 .setMatch(match)
125 .setFlags(Collections.singleton(OFFlowModFlags.SEND_FLOW_REM))
126 .setPriority(flowRule().priority())
alshabib10580802015-02-18 18:30:33 -0800127 .setTableId(TableId.of(flowRule().type().ordinal()))
Jonathan Hart86e59352014-10-22 10:42:16 -0700128 .build();
129
130 return fm;
131 }
132
133 @Override
134 public OFFlowMod buildFlowMod() {
135 Match match = buildMatch();
alshabib346b5b32015-03-06 00:42:16 -0800136 List<OFAction> deferredActions = buildActions(treatment.deferred());
137 List<OFAction> immediateActions = buildActions(treatment.immediate());
138 List<OFInstruction> instructions = Lists.newLinkedList();
Jonathan Harteda33872015-02-18 10:22:32 -0800139
alshabib346b5b32015-03-06 00:42:16 -0800140
141 if (immediateActions.size() > 0) {
142 instructions.add(factory().instructions().applyActions(immediateActions));
143 }
144 if (treatment.clearedDeferred()) {
145 instructions.add(factory().instructions().clearActions());
146 }
147 if (deferredActions.size() > 0) {
148 instructions.add(factory().instructions().writeActions(deferredActions));
149 }
150 if (treatment.tableTransition() != null) {
151 instructions.add(buildTableGoto(treatment.tableTransition()));
Saurav Dascbe6de32015-03-01 18:30:46 -0800152 }
Jonathan Hart86e59352014-10-22 10:42:16 -0700153
154 long cookie = flowRule().id().value();
155
Jonathan Hart86e59352014-10-22 10:42:16 -0700156 OFFlowMod fm = factory().buildFlowModify()
Brian O'Connor427a1762014-11-19 18:40:32 -0800157 .setXid(xid)
Jonathan Hart86e59352014-10-22 10:42:16 -0700158 .setCookie(U64.of(cookie))
159 .setBufferId(OFBufferId.NO_BUFFER)
alshabib9af70072015-02-09 14:34:16 -0800160 .setInstructions(instructions)
Jonathan Hart86e59352014-10-22 10:42:16 -0700161 .setMatch(match)
162 .setFlags(Collections.singleton(OFFlowModFlags.SEND_FLOW_REM))
163 .setPriority(flowRule().priority())
alshabib10580802015-02-18 18:30:33 -0800164 .setTableId(TableId.of(flowRule().type().ordinal()))
Jonathan Hart86e59352014-10-22 10:42:16 -0700165 .build();
166
167 return fm;
168 }
169
170 @Override
171 public OFFlowDelete buildFlowDel() {
172 Match match = buildMatch();
Jonathan Hart86e59352014-10-22 10:42:16 -0700173
174 long cookie = flowRule().id().value();
175
176 OFFlowDelete fm = factory().buildFlowDelete()
Brian O'Connor427a1762014-11-19 18:40:32 -0800177 .setXid(xid)
Jonathan Hart86e59352014-10-22 10:42:16 -0700178 .setCookie(U64.of(cookie))
179 .setBufferId(OFBufferId.NO_BUFFER)
Jonathan Hart86e59352014-10-22 10:42:16 -0700180 .setMatch(match)
181 .setFlags(Collections.singleton(OFFlowModFlags.SEND_FLOW_REM))
182 .setPriority(flowRule().priority())
Jonathan Hart37d659c2015-03-08 19:20:38 -0700183 .setTableId(TableId.of(flowRule().type().ordinal()))
Jonathan Hart86e59352014-10-22 10:42:16 -0700184 .build();
185
186 return fm;
187 }
188
alshabib9af70072015-02-09 14:34:16 -0800189
190 private List<OFInstruction> buildInstructions() {
191 List<OFInstruction> instructions = new LinkedList<>();
192 if (treatment == null) {
193 return instructions;
194 }
195 for (Instruction i : treatment.instructions()) {
196 switch (i.type()) {
197 case TABLE:
198 instructions.add(buildTableGoto(((Instructions.TableTypeTransition) i)));
199 break;
200 default:
201 break;
202 }
203 }
204 return instructions;
205 }
206
alshabib346b5b32015-03-06 00:42:16 -0800207 private List<OFAction> buildActions(List<Instruction> treatments) {
Jonathan Hart86e59352014-10-22 10:42:16 -0700208 List<OFAction> actions = new LinkedList<>();
Saurav Dascbe6de32015-03-01 18:30:46 -0800209 boolean tableFound = false;
Jonathan Hart86e59352014-10-22 10:42:16 -0700210 if (treatment == null) {
211 return actions;
212 }
alshabib346b5b32015-03-06 00:42:16 -0800213 for (Instruction i : treatments) {
Jonathan Hart86e59352014-10-22 10:42:16 -0700214 switch (i.type()) {
alshabib9af70072015-02-09 14:34:16 -0800215 case DROP:
216 log.warn("Saw drop action; assigning drop action");
217 return new LinkedList<>();
218 case L0MODIFICATION:
219 actions.add(buildL0Modification(i));
220 break;
221 case L2MODIFICATION:
222 actions.add(buildL2Modification(i));
223 break;
224 case L3MODIFICATION:
225 actions.add(buildL3Modification(i));
226 break;
227 case OUTPUT:
228 OutputInstruction out = (OutputInstruction) i;
229 OFActionOutput.Builder action = factory().actions().buildOutput()
230 .setPort(OFPort.of((int) out.port().toLong()));
231 if (out.port().equals(PortNumber.CONTROLLER)) {
232 action.setMaxLen(OFPCML_NO_BUFFER);
233 }
234 actions.add(action.build());
235 break;
236 case GROUP:
237 GroupInstruction group = (GroupInstruction) i;
238 OFActionGroup.Builder groupBuilder = factory().actions().buildGroup()
239 .setGroup(OFGroup.of(group.groupId().id()));
240 actions.add(groupBuilder.build());
241 break;
alshabib10580802015-02-18 18:30:33 -0800242 case TABLE:
243 //FIXME: should not occur here.
Saurav Dascbe6de32015-03-01 18:30:46 -0800244 tableFound = true;
alshabib10580802015-02-18 18:30:33 -0800245 break;
alshabib9af70072015-02-09 14:34:16 -0800246 default:
247 log.warn("Instruction type {} not yet implemented.", i.type());
Jonathan Hart86e59352014-10-22 10:42:16 -0700248 }
249 }
Saurav Dascbe6de32015-03-01 18:30:46 -0800250 if (tableFound && actions.isEmpty()) {
251 // handles the case where there are no actions, but there is
252 // a goto instruction for the next table
253 return null;
254 }
Jonathan Hart86e59352014-10-22 10:42:16 -0700255 return actions;
256 }
257
alshabib9af70072015-02-09 14:34:16 -0800258 private OFInstruction buildTableGoto(Instructions.TableTypeTransition i) {
259 OFInstruction instruction = factory().instructions().gotoTable(
260 TableId.of(getTableType(i.tableType()).ordinal()));
261 return instruction;
262 }
263
264 // FIXME: this has to go as well perhaps when we implement the SelectorService.
265 private OpenFlowSwitch.TableType getTableType(FlowRule.Type type) {
266 switch (type) {
267
268 case DEFAULT:
269 return OpenFlowSwitch.TableType.NONE;
270 case IP:
271 return OpenFlowSwitch.TableType.IP;
272 case MPLS:
273 return OpenFlowSwitch.TableType.MPLS;
274 case ACL:
275 return OpenFlowSwitch.TableType.ACL;
276 case VLAN_MPLS:
277 return OpenFlowSwitch.TableType.VLAN_MPLS;
278 case VLAN:
279 return OpenFlowSwitch.TableType.VLAN;
280 case ETHER:
281 return OpenFlowSwitch.TableType.ETHER;
282 case COS:
283 return OpenFlowSwitch.TableType.COS;
Saurav Dasfa2fa932015-03-03 11:29:48 -0800284 case FIRST:
285 return OpenFlowSwitch.TableType.FIRST;
alshabib9af70072015-02-09 14:34:16 -0800286 default:
287 return OpenFlowSwitch.TableType.NONE;
288 }
289 }
290
291
Jonathan Hart86e59352014-10-22 10:42:16 -0700292 private OFAction buildL0Modification(Instruction i) {
293 L0ModificationInstruction l0m = (L0ModificationInstruction) i;
294 switch (l0m.subtype()) {
295 case LAMBDA:
296 ModLambdaInstruction ml = (ModLambdaInstruction) i;
297 return factory().actions().circuit(factory().oxms().ochSigidBasic(
298 new CircuitSignalID((byte) 1, (byte) 2, ml.lambda(), (short) 1)));
299 default:
300 log.warn("Unimplemented action type {}.", l0m.subtype());
301 break;
302 }
303 return null;
304 }
305
306 private OFAction buildL2Modification(Instruction i) {
307 L2ModificationInstruction l2m = (L2ModificationInstruction) i;
308 ModEtherInstruction eth;
309 OFOxm<?> oxm = null;
310 switch (l2m.subtype()) {
Praseed Balakrishnan8c67d172014-11-10 10:15:41 -0800311 case ETH_DST:
312 eth = (ModEtherInstruction) l2m;
313 oxm = factory().oxms().ethDst(MacAddress.of(eth.mac().toLong()));
314 break;
315 case ETH_SRC:
316 eth = (ModEtherInstruction) l2m;
317 oxm = factory().oxms().ethSrc(MacAddress.of(eth.mac().toLong()));
318 break;
319 case VLAN_ID:
320 ModVlanIdInstruction vlanId = (ModVlanIdInstruction) l2m;
321 oxm = factory().oxms().vlanVid(OFVlanVidMatch.ofVlan(vlanId.vlanId().toShort()));
322 break;
323 case VLAN_PCP:
324 ModVlanPcpInstruction vlanPcp = (ModVlanPcpInstruction) l2m;
325 oxm = factory().oxms().vlanPcp(VlanPcp.of(vlanPcp.vlanPcp()));
326 break;
327 case MPLS_PUSH:
328 PushHeaderInstructions pushHeaderInstructions =
329 (PushHeaderInstructions) l2m;
330 return factory().actions().pushMpls(EthType.of(pushHeaderInstructions
Yuta HIGUCHI32a53c52015-02-08 01:25:40 -0800331 .ethernetType()));
Praseed Balakrishnan8c67d172014-11-10 10:15:41 -0800332 case MPLS_POP:
Jonathan Hart67fc0972015-03-19 15:21:20 -0700333 PushHeaderInstructions popHeaderInstructions =
Praseed Balakrishnan8c67d172014-11-10 10:15:41 -0800334 (PushHeaderInstructions) l2m;
335 return factory().actions().popMpls(EthType.of(popHeaderInstructions
Yuta HIGUCHI32a53c52015-02-08 01:25:40 -0800336 .ethernetType()));
Praseed Balakrishnan8c67d172014-11-10 10:15:41 -0800337 case MPLS_LABEL:
338 ModMplsLabelInstruction mplsLabel =
339 (ModMplsLabelInstruction) l2m;
340 oxm = factory().oxms().mplsLabel(U32.of(mplsLabel.label()
341 .longValue()));
Praseed Balakrishnan8c67d172014-11-10 10:15:41 -0800342 break;
sangho3f97a17d2015-01-29 22:56:29 -0800343 case DEC_MPLS_TTL:
344 return factory().actions().decMplsTtl();
Saurav Dasfbe25c52015-03-04 11:12:00 -0800345 case VLAN_POP:
346 return factory().actions().popVlan();
Jonathan Hart54b406b2015-03-06 16:24:14 -0800347 case VLAN_PUSH:
348 PushHeaderInstructions pushVlanInstruction = (PushHeaderInstructions) l2m;
349 return factory().actions().pushVlan(
350 EthType.of(pushVlanInstruction.ethernetType()));
Praseed Balakrishnan8c67d172014-11-10 10:15:41 -0800351 default:
352 log.warn("Unimplemented action type {}.", l2m.subtype());
353 break;
Jonathan Hart86e59352014-10-22 10:42:16 -0700354 }
355
356 if (oxm != null) {
357 return factory().actions().buildSetField().setField(oxm).build();
358 }
359 return null;
360 }
361
362 private OFAction buildL3Modification(Instruction i) {
363 L3ModificationInstruction l3m = (L3ModificationInstruction) i;
364 ModIPInstruction ip;
Pavlin Radoslavov23e398d2014-11-05 15:17:57 -0800365 Ip4Address ip4;
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800366 Ip6Address ip6;
Jonathan Hart86e59352014-10-22 10:42:16 -0700367 OFOxm<?> oxm = null;
368 switch (l3m.subtype()) {
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800369 case IPV4_SRC:
370 ip = (ModIPInstruction) i;
371 ip4 = ip.ip().getIp4Address();
372 oxm = factory().oxms().ipv4Src(IPv4Address.of(ip4.toInt()));
373 break;
374 case IPV4_DST:
Jonathan Hart86e59352014-10-22 10:42:16 -0700375 ip = (ModIPInstruction) i;
Pavlin Radoslavov23e398d2014-11-05 15:17:57 -0800376 ip4 = ip.ip().getIp4Address();
377 oxm = factory().oxms().ipv4Dst(IPv4Address.of(ip4.toInt()));
Ray Milkey241b96a2014-11-17 13:08:20 -0800378 break;
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800379 case IPV6_SRC:
Jonathan Hart86e59352014-10-22 10:42:16 -0700380 ip = (ModIPInstruction) i;
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800381 ip6 = ip.ip().getIp6Address();
382 oxm = factory().oxms().ipv6Src(IPv6Address.of(ip6.toOctets()));
383 break;
384 case IPV6_DST:
385 ip = (ModIPInstruction) i;
386 ip6 = ip.ip().getIp6Address();
387 oxm = factory().oxms().ipv6Dst(IPv6Address.of(ip6.toOctets()));
388 break;
389 case IPV6_FLABEL:
390 ModIPv6FlowLabelInstruction flowLabelInstruction =
391 (ModIPv6FlowLabelInstruction) i;
392 int flowLabel = flowLabelInstruction.flowLabel();
393 oxm = factory().oxms().ipv6Flabel(IPv6FlowLabel.of(flowLabel));
Ray Milkey241b96a2014-11-17 13:08:20 -0800394 break;
sangho3f97a17d2015-01-29 22:56:29 -0800395 case DEC_TTL:
396 return factory().actions().decNwTtl();
397 case TTL_IN:
398 return factory().actions().copyTtlIn();
399 case TTL_OUT:
400 return factory().actions().copyTtlOut();
Jonathan Hart86e59352014-10-22 10:42:16 -0700401 default:
402 log.warn("Unimplemented action type {}.", l3m.subtype());
403 break;
404 }
405
406 if (oxm != null) {
407 return factory().actions().buildSetField().setField(oxm).build();
408 }
409 return null;
410 }
411
412}