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.OchSignal;
22 import org.onosproject.net.PortNumber;
23 import org.onosproject.net.flow.FlowRule;
24 import org.onosproject.net.flow.TrafficTreatment;
25 import org.onosproject.net.flow.instructions.Instruction;
26 import org.onosproject.net.flow.instructions.Instructions;
27 import org.onosproject.net.flow.instructions.Instructions.GroupInstruction;
28 import org.onosproject.net.flow.instructions.Instructions.OutputInstruction;
29 import org.onosproject.net.flow.instructions.L0ModificationInstruction;
30 import org.onosproject.net.flow.instructions.L0ModificationInstruction.ModLambdaInstruction;
31 import org.onosproject.net.flow.instructions.L0ModificationInstruction.ModOchSignalInstruction;
32 import org.onosproject.net.flow.instructions.L2ModificationInstruction;
33 import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModEtherInstruction;
34 import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModMplsBosInstruction;
35 import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModMplsLabelInstruction;
36 import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction;
37 import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanPcpInstruction;
38 import org.onosproject.net.flow.instructions.L2ModificationInstruction.PushHeaderInstructions;
39 import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModTunnelIdInstruction;
40 import org.onosproject.net.flow.instructions.L3ModificationInstruction;
41 import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModIPInstruction;
42 import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModIPv6FlowLabelInstruction;
43 import org.onosproject.net.flow.instructions.L4ModificationInstruction;
44 import org.onosproject.net.flow.instructions.L4ModificationInstruction.ModTransportPortInstruction;
45 import org.projectfloodlight.openflow.protocol.OFFactory;
46 import org.projectfloodlight.openflow.protocol.OFFlowAdd;
47 import org.projectfloodlight.openflow.protocol.OFFlowDelete;
48 import org.projectfloodlight.openflow.protocol.OFFlowMod;
49 import org.projectfloodlight.openflow.protocol.OFFlowModFlags;
50 import org.projectfloodlight.openflow.protocol.action.OFAction;
51 import org.projectfloodlight.openflow.protocol.action.OFActionGroup;
52 import org.projectfloodlight.openflow.protocol.action.OFActionOutput;
53 import org.projectfloodlight.openflow.protocol.instruction.OFInstruction;
54 import org.projectfloodlight.openflow.protocol.match.Match;
55 import org.projectfloodlight.openflow.protocol.oxm.OFOxm;
56 import org.projectfloodlight.openflow.types.CircuitSignalID;
57 import org.projectfloodlight.openflow.types.EthType;
58 import org.projectfloodlight.openflow.types.IPv4Address;
59 import org.projectfloodlight.openflow.types.IPv6Address;
60 import org.projectfloodlight.openflow.types.IPv6FlowLabel;
61 import org.projectfloodlight.openflow.types.MacAddress;
62 import org.projectfloodlight.openflow.types.OFBooleanValue;
63 import org.projectfloodlight.openflow.types.OFBufferId;
64 import org.projectfloodlight.openflow.types.OFGroup;
65 import org.projectfloodlight.openflow.types.OFPort;
66 import org.projectfloodlight.openflow.types.OFVlanVidMatch;
67 import org.projectfloodlight.openflow.types.TableId;
68 import org.projectfloodlight.openflow.types.TransportPort;
69 import org.projectfloodlight.openflow.types.U32;
70 import org.projectfloodlight.openflow.types.U64;
71 import org.projectfloodlight.openflow.types.VlanPcp;
72 import org.slf4j.Logger;
73 import org.slf4j.LoggerFactory;
75 import java.util.Collections;
76 import java.util.LinkedList;
77 import java.util.List;
78 import java.util.Optional;
81 * Flow mod builder for OpenFlow 1.3+.
83 public class FlowModBuilderVer13 extends FlowModBuilder {
85 private final Logger log = LoggerFactory.getLogger(getClass());
86 private static final int OFPCML_NO_BUFFER = 0xffff;
88 private final TrafficTreatment treatment;
91 * Constructor for a flow mod builder for OpenFlow 1.3.
93 * @param flowRule the flow rule to transform into a flow mod
94 * @param factory the OpenFlow factory to use to build the flow mod
95 * @param xid the transaction ID
97 protected FlowModBuilderVer13(FlowRule flowRule, OFFactory factory, Optional<Long> xid) {
98 super(flowRule, factory, xid);
100 this.treatment = flowRule.treatment();
104 public OFFlowAdd buildFlowAdd() {
105 Match match = buildMatch();
106 List<OFAction> deferredActions = buildActions(treatment.deferred());
107 List<OFAction> immediateActions = buildActions(treatment.immediate());
108 List<OFInstruction> instructions = Lists.newLinkedList();
111 if (treatment.clearedDeferred()) {
112 instructions.add(factory().instructions().clearActions());
114 if (immediateActions.size() > 0) {
115 instructions.add(factory().instructions().applyActions(immediateActions));
117 if (deferredActions.size() > 0) {
118 instructions.add(factory().instructions().writeActions(deferredActions));
120 if (treatment.tableTransition() != null) {
121 instructions.add(buildTableGoto(treatment.tableTransition()));
123 if (treatment.writeMetadata() != null) {
124 instructions.add(buildMetadata(treatment.writeMetadata()));
126 if (treatment.metered() != null) {
127 instructions.add(buildMeter(treatment.metered()));
130 long cookie = flowRule().id().value();
132 OFFlowAdd fm = factory().buildFlowAdd()
134 .setCookie(U64.of(cookie))
135 .setBufferId(OFBufferId.NO_BUFFER)
136 .setInstructions(instructions)
138 .setFlags(Collections.singleton(OFFlowModFlags.SEND_FLOW_REM))
139 .setPriority(flowRule().priority())
140 .setTableId(TableId.of(flowRule().tableId()))
147 public OFFlowMod buildFlowMod() {
148 Match match = buildMatch();
149 List<OFAction> deferredActions = buildActions(treatment.deferred());
150 List<OFAction> immediateActions = buildActions(treatment.immediate());
151 List<OFInstruction> instructions = Lists.newLinkedList();
154 if (immediateActions.size() > 0) {
155 instructions.add(factory().instructions().applyActions(immediateActions));
157 if (treatment.clearedDeferred()) {
158 instructions.add(factory().instructions().clearActions());
160 if (deferredActions.size() > 0) {
161 instructions.add(factory().instructions().writeActions(deferredActions));
163 if (treatment.tableTransition() != null) {
164 instructions.add(buildTableGoto(treatment.tableTransition()));
166 if (treatment.writeMetadata() != null) {
167 instructions.add(buildMetadata(treatment.writeMetadata()));
169 if (treatment.metered() != null) {
170 instructions.add(buildMeter(treatment.metered()));
173 long cookie = flowRule().id().value();
175 OFFlowMod fm = factory().buildFlowModify()
177 .setCookie(U64.of(cookie))
178 .setBufferId(OFBufferId.NO_BUFFER)
179 .setInstructions(instructions)
181 .setFlags(Collections.singleton(OFFlowModFlags.SEND_FLOW_REM))
182 .setPriority(flowRule().priority())
183 .setTableId(TableId.of(flowRule().tableId()))
190 public OFFlowDelete buildFlowDel() {
191 Match match = buildMatch();
193 long cookie = flowRule().id().value();
195 OFFlowDelete fm = factory().buildFlowDelete()
197 .setCookie(U64.of(cookie))
198 .setBufferId(OFBufferId.NO_BUFFER)
200 .setFlags(Collections.singleton(OFFlowModFlags.SEND_FLOW_REM))
201 .setPriority(flowRule().priority())
202 .setTableId(TableId.of(flowRule().tableId()))
208 private List<OFAction> buildActions(List<Instruction> treatments) {
209 if (treatment == null) {
210 return Collections.emptyList();
213 boolean tableFound = false;
214 List<OFAction> actions = new LinkedList<>();
215 for (Instruction i : treatments) {
219 return Collections.emptyList();
221 actions.add(buildL0Modification(i));
224 actions.add(buildL2Modification(i));
227 actions.add(buildL3Modification(i));
230 actions.add(buildL4Modification(i));
233 OutputInstruction out = (OutputInstruction) i;
234 OFActionOutput.Builder action = factory().actions().buildOutput()
235 .setPort(OFPort.of((int) out.port().toLong()));
236 if (out.port().equals(PortNumber.CONTROLLER)) {
237 action.setMaxLen(OFPCML_NO_BUFFER);
239 actions.add(action.build());
242 GroupInstruction group = (GroupInstruction) i;
243 OFActionGroup.Builder groupBuilder = factory().actions().buildGroup()
244 .setGroup(OFGroup.of(group.groupId().id()));
245 actions.add(groupBuilder.build());
248 //FIXME: should not occur here.
252 log.warn("Instruction type {} not yet implemented.", i.type());
255 if (tableFound && actions.isEmpty()) {
256 // handles the case where there are no actions, but there is
257 // a goto instruction for the next table
258 return Collections.emptyList();
263 private OFInstruction buildTableGoto(Instructions.TableTypeTransition i) {
264 OFInstruction instruction = factory().instructions().gotoTable(
265 TableId.of(i.tableId()));
269 private OFInstruction buildMetadata(Instructions.MetadataInstruction m) {
270 OFInstruction instruction = factory().instructions().writeMetadata(
271 U64.of(m.metadata()), U64.of(m.metadataMask()));
275 private OFInstruction buildMeter(Instructions.MeterInstruction metered) {
276 return factory().instructions().meter(metered.meterId().id());
280 private OFAction buildL0Modification(Instruction i) {
281 L0ModificationInstruction l0m = (L0ModificationInstruction) i;
282 switch (l0m.subtype()) {
284 return buildModLambdaInstruction((ModLambdaInstruction) i);
287 return buildModOchSignalInstruction((ModOchSignalInstruction) i);
288 } catch (NoMappingFoundException e) {
289 log.warn(e.getMessage());
293 log.warn("Unimplemented action type {}.", l0m.subtype());
299 private OFAction buildModLambdaInstruction(ModLambdaInstruction instruction) {
300 return factory().actions().circuit(factory().oxms().ochSigidBasic(
301 new CircuitSignalID((byte) 1, (byte) 2, instruction.lambda(), (short) 1)));
304 private OFAction buildModOchSignalInstruction(ModOchSignalInstruction instruction) {
305 OchSignal signal = instruction.lambda();
306 byte gridType = OpenFlowValueMapper.lookupGridType(signal.gridType());
307 byte channelSpacing = OpenFlowValueMapper.lookupChannelSpacing(signal.channelSpacing());
309 return factory().actions().circuit(factory().oxms().ochSigidBasic(
310 new CircuitSignalID(gridType, channelSpacing,
311 (short) signal.spacingMultiplier(), (short) signal.slotGranularity())
315 private OFAction buildL2Modification(Instruction i) {
316 L2ModificationInstruction l2m = (L2ModificationInstruction) i;
317 ModEtherInstruction eth;
319 switch (l2m.subtype()) {
321 eth = (ModEtherInstruction) l2m;
322 oxm = factory().oxms().ethDst(MacAddress.of(eth.mac().toLong()));
325 eth = (ModEtherInstruction) l2m;
326 oxm = factory().oxms().ethSrc(MacAddress.of(eth.mac().toLong()));
329 ModVlanIdInstruction vlanId = (ModVlanIdInstruction) l2m;
330 oxm = factory().oxms().vlanVid(OFVlanVidMatch.ofVlan(vlanId.vlanId().toShort()));
333 ModVlanPcpInstruction vlanPcp = (ModVlanPcpInstruction) l2m;
334 oxm = factory().oxms().vlanPcp(VlanPcp.of(vlanPcp.vlanPcp()));
337 PushHeaderInstructions pushHeaderInstructions =
338 (PushHeaderInstructions) l2m;
339 return factory().actions().pushMpls(EthType.of(pushHeaderInstructions
340 .ethernetType().toShort()));
342 PushHeaderInstructions popHeaderInstructions =
343 (PushHeaderInstructions) l2m;
344 return factory().actions().popMpls(EthType.of(popHeaderInstructions
345 .ethernetType().toShort()));
347 ModMplsLabelInstruction mplsLabel =
348 (ModMplsLabelInstruction) l2m;
349 oxm = factory().oxms().mplsLabel(U32.of(mplsLabel.mplsLabel().toInt()));
352 ModMplsBosInstruction mplsBos = (ModMplsBosInstruction) l2m;
353 oxm = factory().oxms()
354 .mplsBos(mplsBos.mplsBos() ? OFBooleanValue.TRUE
355 : OFBooleanValue.FALSE);
358 return factory().actions().decMplsTtl();
360 return factory().actions().popVlan();
362 PushHeaderInstructions pushVlanInstruction = (PushHeaderInstructions) l2m;
363 return factory().actions().pushVlan(
364 EthType.of(pushVlanInstruction.ethernetType().toShort()));
366 ModTunnelIdInstruction tunnelId = (ModTunnelIdInstruction) l2m;
367 oxm = factory().oxms().tunnelId(U64.of(tunnelId.tunnelId()));
370 log.warn("Unimplemented action type {}.", l2m.subtype());
375 return factory().actions().buildSetField().setField(oxm).build();
380 private OFAction buildL3Modification(Instruction i) {
381 L3ModificationInstruction l3m = (L3ModificationInstruction) i;
386 switch (l3m.subtype()) {
388 ip = (ModIPInstruction) i;
389 ip4 = ip.ip().getIp4Address();
390 oxm = factory().oxms().ipv4Src(IPv4Address.of(ip4.toInt()));
393 ip = (ModIPInstruction) i;
394 ip4 = ip.ip().getIp4Address();
395 oxm = factory().oxms().ipv4Dst(IPv4Address.of(ip4.toInt()));
398 ip = (ModIPInstruction) i;
399 ip6 = ip.ip().getIp6Address();
400 oxm = factory().oxms().ipv6Src(IPv6Address.of(ip6.toOctets()));
403 ip = (ModIPInstruction) i;
404 ip6 = ip.ip().getIp6Address();
405 oxm = factory().oxms().ipv6Dst(IPv6Address.of(ip6.toOctets()));
408 ModIPv6FlowLabelInstruction flowLabelInstruction =
409 (ModIPv6FlowLabelInstruction) i;
410 int flowLabel = flowLabelInstruction.flowLabel();
411 oxm = factory().oxms().ipv6Flabel(IPv6FlowLabel.of(flowLabel));
414 return factory().actions().decNwTtl();
416 return factory().actions().copyTtlIn();
418 return factory().actions().copyTtlOut();
420 log.warn("Unimplemented action type {}.", l3m.subtype());
425 return factory().actions().buildSetField().setField(oxm).build();
430 private OFAction buildL4Modification(Instruction i) {
431 L4ModificationInstruction l4m = (L4ModificationInstruction) i;
432 ModTransportPortInstruction tp;
434 switch (l4m.subtype()) {
436 tp = (ModTransportPortInstruction) l4m;
437 oxm = factory().oxms().tcpSrc(TransportPort.of(tp.port().toInt()));
440 tp = (ModTransportPortInstruction) l4m;
441 oxm = factory().oxms().tcpDst(TransportPort.of(tp.port().toInt()));
444 tp = (ModTransportPortInstruction) l4m;
445 oxm = factory().oxms().udpSrc(TransportPort.of(tp.port().toInt()));
448 tp = (ModTransportPortInstruction) l4m;
449 oxm = factory().oxms().udpDst(TransportPort.of(tp.port().toInt()));
452 log.warn("Unimplemented action type {}.", l4m.subtype());
457 return factory().actions().buildSetField().setField(oxm).build();