diff options
Diffstat (limited to 'framework/src/onos/providers/openflow/group/src/main/java/org/onosproject/provider/of/group/impl/GroupModBuilder.java')
-rw-r--r-- | framework/src/onos/providers/openflow/group/src/main/java/org/onosproject/provider/of/group/impl/GroupModBuilder.java | 376 |
1 files changed, 376 insertions, 0 deletions
diff --git a/framework/src/onos/providers/openflow/group/src/main/java/org/onosproject/provider/of/group/impl/GroupModBuilder.java b/framework/src/onos/providers/openflow/group/src/main/java/org/onosproject/provider/of/group/impl/GroupModBuilder.java new file mode 100644 index 00000000..d5804f44 --- /dev/null +++ b/framework/src/onos/providers/openflow/group/src/main/java/org/onosproject/provider/of/group/impl/GroupModBuilder.java @@ -0,0 +1,376 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.provider.of.group.impl; + +import org.onlab.packet.Ip4Address; +import org.onlab.packet.Ip6Address; +import org.onosproject.core.GroupId; +import org.onosproject.net.PortNumber; +import org.onosproject.net.flow.TrafficTreatment; +import org.onosproject.net.flow.instructions.Instruction; +import org.onosproject.net.flow.instructions.Instructions; +import org.onosproject.net.flow.instructions.L0ModificationInstruction; +import org.onosproject.net.flow.instructions.L2ModificationInstruction; +import org.onosproject.net.flow.instructions.L3ModificationInstruction; +import org.onosproject.net.group.GroupBucket; +import org.onosproject.net.group.GroupBuckets; +import org.onosproject.net.group.GroupDescription; +import org.projectfloodlight.openflow.protocol.OFBucket; +import org.projectfloodlight.openflow.protocol.OFFactory; +import org.projectfloodlight.openflow.protocol.OFGroupAdd; +import org.projectfloodlight.openflow.protocol.OFGroupDelete; +import org.projectfloodlight.openflow.protocol.OFGroupMod; +import org.projectfloodlight.openflow.protocol.OFGroupType; +import org.projectfloodlight.openflow.protocol.action.OFAction; +import org.projectfloodlight.openflow.protocol.action.OFActionGroup; +import org.projectfloodlight.openflow.protocol.action.OFActionOutput; +import org.projectfloodlight.openflow.protocol.oxm.OFOxm; +import org.projectfloodlight.openflow.types.CircuitSignalID; +import org.projectfloodlight.openflow.types.EthType; +import org.projectfloodlight.openflow.types.IPv4Address; +import org.projectfloodlight.openflow.types.IPv6Address; +import org.projectfloodlight.openflow.types.IPv6FlowLabel; +import org.projectfloodlight.openflow.types.MacAddress; +import org.projectfloodlight.openflow.types.OFBooleanValue; +import org.projectfloodlight.openflow.types.OFGroup; +import org.projectfloodlight.openflow.types.OFPort; +import org.projectfloodlight.openflow.types.OFVlanVidMatch; +import org.projectfloodlight.openflow.types.U32; +import org.projectfloodlight.openflow.types.VlanPcp; +import org.slf4j.Logger; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import java.util.Optional; + +import static org.slf4j.LoggerFactory.getLogger; + +/* + * Builder for GroupMod. + */ +public final class GroupModBuilder { + + private GroupBuckets buckets; + private GroupId groupId; + private GroupDescription.Type type; + private OFFactory factory; + private Long xid; + + private final Logger log = getLogger(getClass()); + + private static final int OFPCML_NO_BUFFER = 0xffff; + + private GroupModBuilder(GroupBuckets buckets, GroupId groupId, + GroupDescription.Type type, OFFactory factory, + Optional<Long> xid) { + this.buckets = buckets; + this.groupId = groupId; + this.type = type; + this.factory = factory; + this.xid = xid.orElse((long) 0); + } + + /** + * Creates a builder for GroupMod. + * + * @param buckets GroupBuckets object + * @param groupId Group Id to create + * @param type Group type + * @param factory OFFactory object + * @param xid transaction ID + * @return GroupModBuilder object + */ + public static GroupModBuilder builder(GroupBuckets buckets, GroupId groupId, + GroupDescription.Type type, OFFactory factory, + Optional<Long> xid) { + + return new GroupModBuilder(buckets, groupId, type, factory, xid); + } + + /** + * Builds the GroupAdd OF message. + * + * @return GroupAdd OF message + */ + public OFGroupAdd buildGroupAdd() { + + List<OFBucket> ofBuckets = new ArrayList<OFBucket>(); + for (GroupBucket bucket: buckets.buckets()) { + List<OFAction> actions = buildActions(bucket.treatment()); + + OFBucket.Builder bucketBuilder = factory.buildBucket(); + bucketBuilder.setActions(actions); + if (type == GroupDescription.Type.SELECT) { + bucketBuilder.setWeight(1); + } + bucketBuilder.setWatchGroup(OFGroup.ANY); + bucketBuilder.setWatchPort(OFPort.ANY); + OFBucket ofBucket = bucketBuilder.build(); + ofBuckets.add(ofBucket); + } + + OFGroupAdd groupMsg = factory.buildGroupAdd() + .setGroup(OFGroup.of(groupId.id())) + .setBuckets(ofBuckets) + .setGroupType(getOFGroupType(type)) + .setXid(xid) + .build(); + + return groupMsg; + } + + /** + * Builds the GroupMod OF message. + * + * @return GroupMod OF message + */ + public OFGroupMod buildGroupMod() { + List<OFBucket> ofBuckets = new ArrayList<OFBucket>(); + for (GroupBucket bucket: buckets.buckets()) { + List<OFAction> actions = buildActions(bucket.treatment()); + + OFBucket.Builder bucketBuilder = factory.buildBucket(); + bucketBuilder.setActions(actions); + if (type == GroupDescription.Type.SELECT) { + bucketBuilder.setWeight(1); + } + bucketBuilder.setWatchGroup(OFGroup.ANY); + bucketBuilder.setWatchPort(OFPort.ANY); + OFBucket ofBucket = bucketBuilder.build(); + ofBuckets.add(ofBucket); + } + + OFGroupMod groupMsg = factory.buildGroupModify() + .setGroup(OFGroup.of(groupId.id())) + .setBuckets(ofBuckets) + .setGroupType(getOFGroupType(type)) + .setXid(xid) + .build(); + + return groupMsg; + } + + /** + * Builds the GroupDel OF message. + * + * @return GroupDel OF message + */ + public OFGroupDelete buildGroupDel() { + + OFGroupDelete groupMsg = factory.buildGroupDelete() + .setGroup(OFGroup.of(groupId.id())) + .setGroupType(OFGroupType.SELECT) + .setXid(xid) + .build(); + + return groupMsg; + } + + private List<OFAction> buildActions(TrafficTreatment treatment) { + if (treatment == null) { + return Collections.emptyList(); + } + + List<OFAction> actions = new LinkedList<>(); + for (Instruction i : treatment.allInstructions()) { + switch (i.type()) { + case DROP: + log.warn("Saw drop action; assigning drop action"); + return Collections.emptyList(); + case L0MODIFICATION: + actions.add(buildL0Modification(i)); + break; + case L2MODIFICATION: + actions.add(buildL2Modification(i)); + break; + case L3MODIFICATION: + actions.add(buildL3Modification(i)); + break; + case OUTPUT: + Instructions.OutputInstruction out = + (Instructions.OutputInstruction) i; + OFActionOutput.Builder action = factory.actions().buildOutput() + .setPort(OFPort.of((int) out.port().toLong())); + if (out.port().equals(PortNumber.CONTROLLER)) { + action.setMaxLen(OFPCML_NO_BUFFER); + } + actions.add(action.build()); + break; + case GROUP: + Instructions.GroupInstruction grp = + (Instructions.GroupInstruction) i; + OFActionGroup.Builder actgrp = factory.actions().buildGroup() + .setGroup(OFGroup.of(grp.groupId().id())); + actions.add(actgrp.build()); + break; + default: + log.warn("Instruction type {} not yet implemented.", i.type()); + } + } + + return actions; + } + + private OFAction buildL0Modification(Instruction i) { + L0ModificationInstruction l0m = (L0ModificationInstruction) i; + switch (l0m.subtype()) { + case LAMBDA: + L0ModificationInstruction.ModLambdaInstruction ml = + (L0ModificationInstruction.ModLambdaInstruction) i; + return factory.actions().circuit(factory.oxms().ochSigidBasic( + new CircuitSignalID((byte) 1, (byte) 2, ml.lambda(), (short) 1))); + default: + log.warn("Unimplemented action type {}.", l0m.subtype()); + break; + } + return null; + } + + private OFAction buildL2Modification(Instruction i) { + L2ModificationInstruction l2m = (L2ModificationInstruction) i; + L2ModificationInstruction.ModEtherInstruction eth; + OFOxm<?> oxm = null; + switch (l2m.subtype()) { + case ETH_DST: + eth = (L2ModificationInstruction.ModEtherInstruction) l2m; + oxm = factory.oxms().ethDst(MacAddress.of(eth.mac().toLong())); + break; + case ETH_SRC: + eth = (L2ModificationInstruction.ModEtherInstruction) l2m; + oxm = factory.oxms().ethSrc(MacAddress.of(eth.mac().toLong())); + break; + case VLAN_ID: + L2ModificationInstruction.ModVlanIdInstruction vlanId = + (L2ModificationInstruction.ModVlanIdInstruction) l2m; + oxm = factory.oxms().vlanVid(OFVlanVidMatch.ofVlan(vlanId.vlanId().toShort())); + break; + case VLAN_PCP: + L2ModificationInstruction.ModVlanPcpInstruction vlanPcp = + (L2ModificationInstruction.ModVlanPcpInstruction) l2m; + oxm = factory.oxms().vlanPcp(VlanPcp.of(vlanPcp.vlanPcp())); + break; + case VLAN_POP: + return factory.actions().popVlan(); + case VLAN_PUSH: + L2ModificationInstruction.PushHeaderInstructions pushVlanInstruction + = (L2ModificationInstruction.PushHeaderInstructions) l2m; + return factory.actions().pushVlan( + EthType.of(pushVlanInstruction.ethernetType().toShort())); + case MPLS_PUSH: + L2ModificationInstruction.PushHeaderInstructions pushHeaderInstructions = + (L2ModificationInstruction.PushHeaderInstructions) l2m; + return factory.actions().pushMpls(EthType.of(pushHeaderInstructions + .ethernetType().toShort())); + case MPLS_POP: + L2ModificationInstruction.PushHeaderInstructions popHeaderInstructions = + (L2ModificationInstruction.PushHeaderInstructions) l2m; + return factory.actions().popMpls(EthType.of(popHeaderInstructions + .ethernetType().toShort())); + case MPLS_LABEL: + L2ModificationInstruction.ModMplsLabelInstruction mplsLabel = + (L2ModificationInstruction.ModMplsLabelInstruction) l2m; + oxm = factory.oxms().mplsLabel(U32.of(mplsLabel.mplsLabel().toInt())); + break; + case MPLS_BOS: + L2ModificationInstruction.ModMplsBosInstruction mplsBos = + (L2ModificationInstruction.ModMplsBosInstruction) l2m; + oxm = factory.oxms() + .mplsBos(mplsBos.mplsBos() ? OFBooleanValue.TRUE + : OFBooleanValue.FALSE); + break; + case DEC_MPLS_TTL: + return factory.actions().decMplsTtl(); + default: + log.warn("Unimplemented action type {}.", l2m.subtype()); + break; + } + + if (oxm != null) { + return factory.actions().buildSetField().setField(oxm).build(); + } + return null; + } + + private OFAction buildL3Modification(Instruction i) { + L3ModificationInstruction l3m = (L3ModificationInstruction) i; + L3ModificationInstruction.ModIPInstruction ip; + Ip4Address ip4; + Ip6Address ip6; + OFOxm<?> oxm = null; + switch (l3m.subtype()) { + case IPV4_SRC: + ip = (L3ModificationInstruction.ModIPInstruction) i; + ip4 = ip.ip().getIp4Address(); + oxm = factory.oxms().ipv4Src(IPv4Address.of(ip4.toInt())); + break; + case IPV4_DST: + ip = (L3ModificationInstruction.ModIPInstruction) i; + ip4 = ip.ip().getIp4Address(); + oxm = factory.oxms().ipv4Dst(IPv4Address.of(ip4.toInt())); + break; + case IPV6_SRC: + ip = (L3ModificationInstruction.ModIPInstruction) i; + ip6 = ip.ip().getIp6Address(); + oxm = factory.oxms().ipv6Src(IPv6Address.of(ip6.toOctets())); + break; + case IPV6_DST: + ip = (L3ModificationInstruction.ModIPInstruction) i; + ip6 = ip.ip().getIp6Address(); + oxm = factory.oxms().ipv6Dst(IPv6Address.of(ip6.toOctets())); + break; + case IPV6_FLABEL: + L3ModificationInstruction.ModIPv6FlowLabelInstruction flowLabelInstruction = + (L3ModificationInstruction.ModIPv6FlowLabelInstruction) i; + int flowLabel = flowLabelInstruction.flowLabel(); + oxm = factory.oxms().ipv6Flabel(IPv6FlowLabel.of(flowLabel)); + break; + case DEC_TTL: + return factory.actions().decNwTtl(); + case TTL_IN: + return factory.actions().copyTtlIn(); + case TTL_OUT: + return factory.actions().copyTtlOut(); + default: + log.warn("Unimplemented action type {}.", l3m.subtype()); + break; + } + + if (oxm != null) { + return factory.actions().buildSetField().setField(oxm).build(); + } + return null; + } + + private OFGroupType getOFGroupType(GroupDescription.Type groupType) { + switch (groupType) { + case INDIRECT: + return OFGroupType.INDIRECT; + case SELECT: + return OFGroupType.SELECT; + case FAILOVER: + return OFGroupType.FF; + case ALL: + return OFGroupType.ALL; + default: + log.error("Unsupported group type : {}", groupType); + break; + } + return null; + } +} + |