2 * Copyright 2014-2015 Open Networking Laboratory
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 package org.onosproject.provider.of.flow.impl;
18 import com.google.common.collect.Lists;
19 import org.onlab.packet.Ip4Address;
20 import org.onlab.packet.Ip6Address;
21 import org.onosproject.net.DeviceId;
22 import org.onosproject.net.OchSignal;
23 import org.onosproject.net.PortNumber;
24 import org.onosproject.net.driver.DefaultDriverData;
25 import org.onosproject.net.driver.DefaultDriverHandler;
26 import org.onosproject.net.driver.Driver;
27 import org.onosproject.net.driver.DriverService;
28 import org.onosproject.net.flow.FlowRule;
29 import org.onosproject.net.flow.TrafficTreatment;
30 import org.onosproject.net.flow.instructions.ExtensionTreatment;
31 import org.onosproject.net.flow.instructions.Instruction;
32 import org.onosproject.net.flow.instructions.Instructions;
33 import org.onosproject.net.flow.instructions.Instructions.GroupInstruction;
34 import org.onosproject.net.flow.instructions.Instructions.OutputInstruction;
35 import org.onosproject.net.flow.instructions.Instructions.SetQueueInstruction;
36 import org.onosproject.net.flow.instructions.L0ModificationInstruction;
37 import org.onosproject.net.flow.instructions.L0ModificationInstruction.ModLambdaInstruction;
38 import org.onosproject.net.flow.instructions.L0ModificationInstruction.ModOchSignalInstruction;
39 import org.onosproject.net.flow.instructions.L2ModificationInstruction;
40 import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModEtherInstruction;
41 import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModMplsBosInstruction;
42 import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModMplsLabelInstruction;
43 import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModTunnelIdInstruction;
44 import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction;
45 import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanPcpInstruction;
46 import org.onosproject.net.flow.instructions.L2ModificationInstruction.PushHeaderInstructions;
47 import org.onosproject.net.flow.instructions.L3ModificationInstruction;
48 import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModIPInstruction;
49 import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModIPv6FlowLabelInstruction;
50 import org.onosproject.net.flow.instructions.L4ModificationInstruction;
51 import org.onosproject.net.flow.instructions.L4ModificationInstruction.ModTransportPortInstruction;
52 import org.onosproject.openflow.controller.ExtensionTreatmentInterpreter;
53 import org.projectfloodlight.openflow.protocol.OFFactory;
54 import org.projectfloodlight.openflow.protocol.OFFlowAdd;
55 import org.projectfloodlight.openflow.protocol.OFFlowDelete;
56 import org.projectfloodlight.openflow.protocol.OFFlowMod;
57 import org.projectfloodlight.openflow.protocol.OFFlowModFlags;
58 import org.projectfloodlight.openflow.protocol.action.OFAction;
59 import org.projectfloodlight.openflow.protocol.action.OFActionGroup;
60 import org.projectfloodlight.openflow.protocol.action.OFActionOutput;
61 import org.projectfloodlight.openflow.protocol.action.OFActionSetQueue;
62 import org.projectfloodlight.openflow.protocol.instruction.OFInstruction;
63 import org.projectfloodlight.openflow.protocol.match.Match;
64 import org.projectfloodlight.openflow.protocol.oxm.OFOxm;
65 import org.projectfloodlight.openflow.types.CircuitSignalID;
66 import org.projectfloodlight.openflow.types.EthType;
67 import org.projectfloodlight.openflow.types.IPv4Address;
68 import org.projectfloodlight.openflow.types.IPv6Address;
69 import org.projectfloodlight.openflow.types.IPv6FlowLabel;
70 import org.projectfloodlight.openflow.types.MacAddress;
71 import org.projectfloodlight.openflow.types.OFBooleanValue;
72 import org.projectfloodlight.openflow.types.OFBufferId;
73 import org.projectfloodlight.openflow.types.OFGroup;
74 import org.projectfloodlight.openflow.types.OFPort;
75 import org.projectfloodlight.openflow.types.OFVlanVidMatch;
76 import org.projectfloodlight.openflow.types.TableId;
77 import org.projectfloodlight.openflow.types.TransportPort;
78 import org.projectfloodlight.openflow.types.U32;
79 import org.projectfloodlight.openflow.types.U64;
80 import org.projectfloodlight.openflow.types.VlanPcp;
81 import org.slf4j.Logger;
82 import org.slf4j.LoggerFactory;
84 import java.util.Collections;
85 import java.util.LinkedList;
86 import java.util.List;
87 import java.util.Optional;
90 * Flow mod builder for OpenFlow 1.3+.
92 public class FlowModBuilderVer13 extends FlowModBuilder {
94 private final Logger log = LoggerFactory.getLogger(getClass());
95 private static final int OFPCML_NO_BUFFER = 0xffff;
97 private final TrafficTreatment treatment;
98 private final DeviceId deviceId;
101 * Constructor for a flow mod builder for OpenFlow 1.3.
103 * @param flowRule the flow rule to transform into a flow mod
104 * @param factory the OpenFlow factory to use to build the flow mod
105 * @param xid the transaction ID
106 * @param driverService the device driver service
108 protected FlowModBuilderVer13(FlowRule flowRule, OFFactory factory, Optional<Long> xid,
109 Optional<DriverService> driverService) {
110 super(flowRule, factory, xid, driverService);
112 this.treatment = flowRule.treatment();
113 this.deviceId = flowRule.deviceId();
117 public OFFlowAdd buildFlowAdd() {
118 Match match = buildMatch();
119 List<OFAction> deferredActions = buildActions(treatment.deferred());
120 List<OFAction> immediateActions = buildActions(treatment.immediate());
121 List<OFInstruction> instructions = Lists.newLinkedList();
124 if (treatment.clearedDeferred()) {
125 instructions.add(factory().instructions().clearActions());
127 if (immediateActions.size() > 0) {
128 instructions.add(factory().instructions().applyActions(immediateActions));
130 if (deferredActions.size() > 0) {
131 instructions.add(factory().instructions().writeActions(deferredActions));
133 if (treatment.tableTransition() != null) {
134 instructions.add(buildTableGoto(treatment.tableTransition()));
136 if (treatment.writeMetadata() != null) {
137 instructions.add(buildMetadata(treatment.writeMetadata()));
139 if (treatment.metered() != null) {
140 instructions.add(buildMeter(treatment.metered()));
143 long cookie = flowRule().id().value();
145 OFFlowAdd fm = factory().buildFlowAdd()
147 .setCookie(U64.of(cookie))
148 .setBufferId(OFBufferId.NO_BUFFER)
149 .setInstructions(instructions)
151 .setFlags(Collections.singleton(OFFlowModFlags.SEND_FLOW_REM))
152 .setPriority(flowRule().priority())
153 .setTableId(TableId.of(flowRule().tableId()))
160 public OFFlowMod buildFlowMod() {
161 Match match = buildMatch();
162 List<OFAction> deferredActions = buildActions(treatment.deferred());
163 List<OFAction> immediateActions = buildActions(treatment.immediate());
164 List<OFInstruction> instructions = Lists.newLinkedList();
167 if (immediateActions.size() > 0) {
168 instructions.add(factory().instructions().applyActions(immediateActions));
170 if (treatment.clearedDeferred()) {
171 instructions.add(factory().instructions().clearActions());
173 if (deferredActions.size() > 0) {
174 instructions.add(factory().instructions().writeActions(deferredActions));
176 if (treatment.tableTransition() != null) {
177 instructions.add(buildTableGoto(treatment.tableTransition()));
179 if (treatment.writeMetadata() != null) {
180 instructions.add(buildMetadata(treatment.writeMetadata()));
182 if (treatment.metered() != null) {
183 instructions.add(buildMeter(treatment.metered()));
186 long cookie = flowRule().id().value();
188 OFFlowMod fm = factory().buildFlowModify()
190 .setCookie(U64.of(cookie))
191 .setBufferId(OFBufferId.NO_BUFFER)
192 .setInstructions(instructions)
194 .setFlags(Collections.singleton(OFFlowModFlags.SEND_FLOW_REM))
195 .setPriority(flowRule().priority())
196 .setTableId(TableId.of(flowRule().tableId()))
203 public OFFlowDelete buildFlowDel() {
204 Match match = buildMatch();
206 long cookie = flowRule().id().value();
208 OFFlowDelete fm = factory().buildFlowDelete()
210 .setCookie(U64.of(cookie))
211 .setBufferId(OFBufferId.NO_BUFFER)
213 .setFlags(Collections.singleton(OFFlowModFlags.SEND_FLOW_REM))
214 .setPriority(flowRule().priority())
215 .setTableId(TableId.of(flowRule().tableId()))
221 private List<OFAction> buildActions(List<Instruction> treatments) {
222 if (treatment == null) {
223 return Collections.emptyList();
226 boolean tableFound = false;
227 List<OFAction> actions = new LinkedList<>();
228 for (Instruction i : treatments) {
232 return Collections.emptyList();
234 actions.add(buildL0Modification(i));
237 actions.add(buildL2Modification(i));
240 actions.add(buildL3Modification(i));
243 actions.add(buildL4Modification(i));
246 OutputInstruction out = (OutputInstruction) i;
247 OFActionOutput.Builder action = factory().actions().buildOutput()
248 .setPort(OFPort.of((int) out.port().toLong()));
249 if (out.port().equals(PortNumber.CONTROLLER)) {
250 action.setMaxLen(OFPCML_NO_BUFFER);
252 actions.add(action.build());
255 GroupInstruction group = (GroupInstruction) i;
256 OFActionGroup.Builder groupBuilder = factory().actions().buildGroup()
257 .setGroup(OFGroup.of(group.groupId().id()));
258 actions.add(groupBuilder.build());
261 SetQueueInstruction queue = (SetQueueInstruction) i;
262 OFActionSetQueue.Builder queueBuilder = factory().actions().buildSetQueue()
263 .setQueueId(queue.queueId());
264 actions.add(queueBuilder.build());
267 //FIXME: should not occur here.
271 actions.add(buildExtensionAction(((Instructions.ExtensionInstructionWrapper) i)
272 .extensionInstruction()));
275 log.warn("Instruction type {} not yet implemented.", i.type());
278 if (tableFound && actions.isEmpty()) {
279 // handles the case where there are no actions, but there is
280 // a goto instruction for the next table
281 return Collections.emptyList();
286 private OFInstruction buildTableGoto(Instructions.TableTypeTransition i) {
287 OFInstruction instruction = factory().instructions().gotoTable(
288 TableId.of(i.tableId()));
292 private OFInstruction buildMetadata(Instructions.MetadataInstruction m) {
293 OFInstruction instruction = factory().instructions().writeMetadata(
294 U64.of(m.metadata()), U64.of(m.metadataMask()));
298 private OFInstruction buildMeter(Instructions.MeterInstruction metered) {
299 return factory().instructions().meter(metered.meterId().id());
303 private OFAction buildL0Modification(Instruction i) {
304 L0ModificationInstruction l0m = (L0ModificationInstruction) i;
305 switch (l0m.subtype()) {
307 return buildModLambdaInstruction((ModLambdaInstruction) i);
310 return buildModOchSignalInstruction((ModOchSignalInstruction) i);
311 } catch (NoMappingFoundException e) {
312 log.warn(e.getMessage());
316 log.warn("Unimplemented action type {}.", l0m.subtype());
322 private OFAction buildModLambdaInstruction(ModLambdaInstruction instruction) {
323 return factory().actions().circuit(factory().oxms().expOchSigId(
324 new CircuitSignalID((byte) 1, (byte) 2, instruction.lambda(), (short) 1)));
327 private OFAction buildModOchSignalInstruction(ModOchSignalInstruction instruction) {
328 OchSignal signal = instruction.lambda();
329 byte gridType = OpenFlowValueMapper.lookupGridType(signal.gridType());
330 byte channelSpacing = OpenFlowValueMapper.lookupChannelSpacing(signal.channelSpacing());
332 return factory().actions().circuit(factory().oxms().expOchSigId(
333 new CircuitSignalID(gridType, channelSpacing,
334 (short) signal.spacingMultiplier(), (short) signal.slotGranularity())
338 private OFAction buildL2Modification(Instruction i) {
339 L2ModificationInstruction l2m = (L2ModificationInstruction) i;
340 ModEtherInstruction eth;
342 switch (l2m.subtype()) {
344 eth = (ModEtherInstruction) l2m;
345 oxm = factory().oxms().ethDst(MacAddress.of(eth.mac().toLong()));
348 eth = (ModEtherInstruction) l2m;
349 oxm = factory().oxms().ethSrc(MacAddress.of(eth.mac().toLong()));
352 ModVlanIdInstruction vlanId = (ModVlanIdInstruction) l2m;
353 oxm = factory().oxms().vlanVid(OFVlanVidMatch.ofVlan(vlanId.vlanId().toShort()));
356 ModVlanPcpInstruction vlanPcp = (ModVlanPcpInstruction) l2m;
357 oxm = factory().oxms().vlanPcp(VlanPcp.of(vlanPcp.vlanPcp()));
360 PushHeaderInstructions pushHeaderInstructions =
361 (PushHeaderInstructions) l2m;
362 return factory().actions().pushMpls(EthType.of(pushHeaderInstructions
363 .ethernetType().toShort()));
365 PushHeaderInstructions popHeaderInstructions =
366 (PushHeaderInstructions) l2m;
367 return factory().actions().popMpls(EthType.of(popHeaderInstructions
368 .ethernetType().toShort()));
370 ModMplsLabelInstruction mplsLabel =
371 (ModMplsLabelInstruction) l2m;
372 oxm = factory().oxms().mplsLabel(U32.of(mplsLabel.mplsLabel().toInt()));
375 ModMplsBosInstruction mplsBos = (ModMplsBosInstruction) l2m;
376 oxm = factory().oxms()
377 .mplsBos(mplsBos.mplsBos() ? OFBooleanValue.TRUE
378 : OFBooleanValue.FALSE);
381 return factory().actions().decMplsTtl();
383 return factory().actions().popVlan();
385 PushHeaderInstructions pushVlanInstruction = (PushHeaderInstructions) l2m;
386 return factory().actions().pushVlan(
387 EthType.of(pushVlanInstruction.ethernetType().toShort()));
389 ModTunnelIdInstruction tunnelId = (ModTunnelIdInstruction) l2m;
390 oxm = factory().oxms().tunnelId(U64.of(tunnelId.tunnelId()));
393 log.warn("Unimplemented action type {}.", l2m.subtype());
398 return factory().actions().buildSetField().setField(oxm).build();
403 private OFAction buildL3Modification(Instruction i) {
404 L3ModificationInstruction l3m = (L3ModificationInstruction) i;
409 switch (l3m.subtype()) {
411 ip = (ModIPInstruction) i;
412 ip4 = ip.ip().getIp4Address();
413 oxm = factory().oxms().ipv4Src(IPv4Address.of(ip4.toInt()));
416 ip = (ModIPInstruction) i;
417 ip4 = ip.ip().getIp4Address();
418 oxm = factory().oxms().ipv4Dst(IPv4Address.of(ip4.toInt()));
421 ip = (ModIPInstruction) i;
422 ip6 = ip.ip().getIp6Address();
423 oxm = factory().oxms().ipv6Src(IPv6Address.of(ip6.toOctets()));
426 ip = (ModIPInstruction) i;
427 ip6 = ip.ip().getIp6Address();
428 oxm = factory().oxms().ipv6Dst(IPv6Address.of(ip6.toOctets()));
431 ModIPv6FlowLabelInstruction flowLabelInstruction =
432 (ModIPv6FlowLabelInstruction) i;
433 int flowLabel = flowLabelInstruction.flowLabel();
434 oxm = factory().oxms().ipv6Flabel(IPv6FlowLabel.of(flowLabel));
437 return factory().actions().decNwTtl();
439 return factory().actions().copyTtlIn();
441 return factory().actions().copyTtlOut();
443 log.warn("Unimplemented action type {}.", l3m.subtype());
448 return factory().actions().buildSetField().setField(oxm).build();
453 private OFAction buildL4Modification(Instruction i) {
454 L4ModificationInstruction l4m = (L4ModificationInstruction) i;
455 ModTransportPortInstruction tp;
457 switch (l4m.subtype()) {
459 tp = (ModTransportPortInstruction) l4m;
460 oxm = factory().oxms().tcpSrc(TransportPort.of(tp.port().toInt()));
463 tp = (ModTransportPortInstruction) l4m;
464 oxm = factory().oxms().tcpDst(TransportPort.of(tp.port().toInt()));
467 tp = (ModTransportPortInstruction) l4m;
468 oxm = factory().oxms().udpSrc(TransportPort.of(tp.port().toInt()));
471 tp = (ModTransportPortInstruction) l4m;
472 oxm = factory().oxms().udpDst(TransportPort.of(tp.port().toInt()));
475 log.warn("Unimplemented action type {}.", l4m.subtype());
480 return factory().actions().buildSetField().setField(oxm).build();
485 private OFAction buildExtensionAction(ExtensionTreatment i) {
486 if (!driverService.isPresent()) {
487 log.error("No driver service present");
490 Driver driver = driverService.get().getDriver(deviceId);
491 if (driver.hasBehaviour(ExtensionTreatmentInterpreter.class)) {
492 DefaultDriverHandler handler =
493 new DefaultDriverHandler(new DefaultDriverData(driver, deviceId));
494 ExtensionTreatmentInterpreter interpreter = handler.behaviour(ExtensionTreatmentInterpreter.class);
495 return interpreter.mapInstruction(factory(), i);