2 * Copyright 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.group.impl;
18 import org.onlab.packet.Ip4Address;
19 import org.onlab.packet.Ip6Address;
20 import org.onosproject.core.GroupId;
21 import org.onosproject.net.PortNumber;
22 import org.onosproject.net.flow.TrafficTreatment;
23 import org.onosproject.net.flow.instructions.Instruction;
24 import org.onosproject.net.flow.instructions.Instructions;
25 import org.onosproject.net.flow.instructions.L0ModificationInstruction;
26 import org.onosproject.net.flow.instructions.L2ModificationInstruction;
27 import org.onosproject.net.flow.instructions.L3ModificationInstruction;
28 import org.onosproject.net.group.GroupBucket;
29 import org.onosproject.net.group.GroupBuckets;
30 import org.onosproject.net.group.GroupDescription;
31 import org.projectfloodlight.openflow.protocol.OFBucket;
32 import org.projectfloodlight.openflow.protocol.OFFactory;
33 import org.projectfloodlight.openflow.protocol.OFGroupAdd;
34 import org.projectfloodlight.openflow.protocol.OFGroupDelete;
35 import org.projectfloodlight.openflow.protocol.OFGroupMod;
36 import org.projectfloodlight.openflow.protocol.OFGroupType;
37 import org.projectfloodlight.openflow.protocol.action.OFAction;
38 import org.projectfloodlight.openflow.protocol.action.OFActionGroup;
39 import org.projectfloodlight.openflow.protocol.action.OFActionOutput;
40 import org.projectfloodlight.openflow.protocol.oxm.OFOxm;
41 import org.projectfloodlight.openflow.types.CircuitSignalID;
42 import org.projectfloodlight.openflow.types.EthType;
43 import org.projectfloodlight.openflow.types.IPv4Address;
44 import org.projectfloodlight.openflow.types.IPv6Address;
45 import org.projectfloodlight.openflow.types.IPv6FlowLabel;
46 import org.projectfloodlight.openflow.types.MacAddress;
47 import org.projectfloodlight.openflow.types.OFBooleanValue;
48 import org.projectfloodlight.openflow.types.OFGroup;
49 import org.projectfloodlight.openflow.types.OFPort;
50 import org.projectfloodlight.openflow.types.OFVlanVidMatch;
51 import org.projectfloodlight.openflow.types.U32;
52 import org.projectfloodlight.openflow.types.VlanPcp;
53 import org.slf4j.Logger;
55 import java.util.ArrayList;
56 import java.util.Collections;
57 import java.util.LinkedList;
58 import java.util.List;
59 import java.util.Optional;
61 import static org.slf4j.LoggerFactory.getLogger;
64 * Builder for GroupMod.
66 public final class GroupModBuilder {
68 private GroupBuckets buckets;
69 private GroupId groupId;
70 private GroupDescription.Type type;
71 private OFFactory factory;
74 private final Logger log = getLogger(getClass());
76 private static final int OFPCML_NO_BUFFER = 0xffff;
78 private GroupModBuilder(GroupBuckets buckets, GroupId groupId,
79 GroupDescription.Type type, OFFactory factory,
81 this.buckets = buckets;
82 this.groupId = groupId;
84 this.factory = factory;
85 this.xid = xid.orElse((long) 0);
89 * Creates a builder for GroupMod.
91 * @param buckets GroupBuckets object
92 * @param groupId Group Id to create
93 * @param type Group type
94 * @param factory OFFactory object
95 * @param xid transaction ID
96 * @return GroupModBuilder object
98 public static GroupModBuilder builder(GroupBuckets buckets, GroupId groupId,
99 GroupDescription.Type type, OFFactory factory,
100 Optional<Long> xid) {
102 return new GroupModBuilder(buckets, groupId, type, factory, xid);
106 * Builds the GroupAdd OF message.
108 * @return GroupAdd OF message
110 public OFGroupAdd buildGroupAdd() {
112 List<OFBucket> ofBuckets = new ArrayList<OFBucket>();
113 for (GroupBucket bucket: buckets.buckets()) {
114 List<OFAction> actions = buildActions(bucket.treatment());
116 OFBucket.Builder bucketBuilder = factory.buildBucket();
117 bucketBuilder.setActions(actions);
118 if (type == GroupDescription.Type.SELECT) {
119 bucketBuilder.setWeight(1);
121 bucketBuilder.setWatchGroup(OFGroup.ANY);
122 bucketBuilder.setWatchPort(OFPort.ANY);
123 OFBucket ofBucket = bucketBuilder.build();
124 ofBuckets.add(ofBucket);
127 OFGroupAdd groupMsg = factory.buildGroupAdd()
128 .setGroup(OFGroup.of(groupId.id()))
129 .setBuckets(ofBuckets)
130 .setGroupType(getOFGroupType(type))
138 * Builds the GroupMod OF message.
140 * @return GroupMod OF message
142 public OFGroupMod buildGroupMod() {
143 List<OFBucket> ofBuckets = new ArrayList<OFBucket>();
144 for (GroupBucket bucket: buckets.buckets()) {
145 List<OFAction> actions = buildActions(bucket.treatment());
147 OFBucket.Builder bucketBuilder = factory.buildBucket();
148 bucketBuilder.setActions(actions);
149 if (type == GroupDescription.Type.SELECT) {
150 bucketBuilder.setWeight(1);
152 bucketBuilder.setWatchGroup(OFGroup.ANY);
153 bucketBuilder.setWatchPort(OFPort.ANY);
154 OFBucket ofBucket = bucketBuilder.build();
155 ofBuckets.add(ofBucket);
158 OFGroupMod groupMsg = factory.buildGroupModify()
159 .setGroup(OFGroup.of(groupId.id()))
160 .setBuckets(ofBuckets)
161 .setGroupType(getOFGroupType(type))
169 * Builds the GroupDel OF message.
171 * @return GroupDel OF message
173 public OFGroupDelete buildGroupDel() {
175 OFGroupDelete groupMsg = factory.buildGroupDelete()
176 .setGroup(OFGroup.of(groupId.id()))
177 .setGroupType(OFGroupType.SELECT)
184 private List<OFAction> buildActions(TrafficTreatment treatment) {
185 if (treatment == null) {
186 return Collections.emptyList();
189 List<OFAction> actions = new LinkedList<>();
190 for (Instruction i : treatment.allInstructions()) {
193 log.warn("Saw drop action; assigning drop action");
194 return Collections.emptyList();
196 actions.add(buildL0Modification(i));
199 actions.add(buildL2Modification(i));
202 actions.add(buildL3Modification(i));
205 Instructions.OutputInstruction out =
206 (Instructions.OutputInstruction) i;
207 OFActionOutput.Builder action = factory.actions().buildOutput()
208 .setPort(OFPort.of((int) out.port().toLong()));
209 if (out.port().equals(PortNumber.CONTROLLER)) {
210 action.setMaxLen(OFPCML_NO_BUFFER);
212 actions.add(action.build());
215 Instructions.GroupInstruction grp =
216 (Instructions.GroupInstruction) i;
217 OFActionGroup.Builder actgrp = factory.actions().buildGroup()
218 .setGroup(OFGroup.of(grp.groupId().id()));
219 actions.add(actgrp.build());
222 log.warn("Instruction type {} not yet implemented.", i.type());
229 private OFAction buildL0Modification(Instruction i) {
230 L0ModificationInstruction l0m = (L0ModificationInstruction) i;
231 switch (l0m.subtype()) {
233 L0ModificationInstruction.ModLambdaInstruction ml =
234 (L0ModificationInstruction.ModLambdaInstruction) i;
235 return factory.actions().circuit(factory.oxms().ochSigidBasic(
236 new CircuitSignalID((byte) 1, (byte) 2, ml.lambda(), (short) 1)));
238 log.warn("Unimplemented action type {}.", l0m.subtype());
244 private OFAction buildL2Modification(Instruction i) {
245 L2ModificationInstruction l2m = (L2ModificationInstruction) i;
246 L2ModificationInstruction.ModEtherInstruction eth;
248 switch (l2m.subtype()) {
250 eth = (L2ModificationInstruction.ModEtherInstruction) l2m;
251 oxm = factory.oxms().ethDst(MacAddress.of(eth.mac().toLong()));
254 eth = (L2ModificationInstruction.ModEtherInstruction) l2m;
255 oxm = factory.oxms().ethSrc(MacAddress.of(eth.mac().toLong()));
258 L2ModificationInstruction.ModVlanIdInstruction vlanId =
259 (L2ModificationInstruction.ModVlanIdInstruction) l2m;
260 oxm = factory.oxms().vlanVid(OFVlanVidMatch.ofVlan(vlanId.vlanId().toShort()));
263 L2ModificationInstruction.ModVlanPcpInstruction vlanPcp =
264 (L2ModificationInstruction.ModVlanPcpInstruction) l2m;
265 oxm = factory.oxms().vlanPcp(VlanPcp.of(vlanPcp.vlanPcp()));
268 return factory.actions().popVlan();
270 L2ModificationInstruction.PushHeaderInstructions pushVlanInstruction
271 = (L2ModificationInstruction.PushHeaderInstructions) l2m;
272 return factory.actions().pushVlan(
273 EthType.of(pushVlanInstruction.ethernetType().toShort()));
275 L2ModificationInstruction.PushHeaderInstructions pushHeaderInstructions =
276 (L2ModificationInstruction.PushHeaderInstructions) l2m;
277 return factory.actions().pushMpls(EthType.of(pushHeaderInstructions
278 .ethernetType().toShort()));
280 L2ModificationInstruction.PushHeaderInstructions popHeaderInstructions =
281 (L2ModificationInstruction.PushHeaderInstructions) l2m;
282 return factory.actions().popMpls(EthType.of(popHeaderInstructions
283 .ethernetType().toShort()));
285 L2ModificationInstruction.ModMplsLabelInstruction mplsLabel =
286 (L2ModificationInstruction.ModMplsLabelInstruction) l2m;
287 oxm = factory.oxms().mplsLabel(U32.of(mplsLabel.mplsLabel().toInt()));
290 L2ModificationInstruction.ModMplsBosInstruction mplsBos =
291 (L2ModificationInstruction.ModMplsBosInstruction) l2m;
293 .mplsBos(mplsBos.mplsBos() ? OFBooleanValue.TRUE
294 : OFBooleanValue.FALSE);
297 return factory.actions().decMplsTtl();
299 log.warn("Unimplemented action type {}.", l2m.subtype());
304 return factory.actions().buildSetField().setField(oxm).build();
309 private OFAction buildL3Modification(Instruction i) {
310 L3ModificationInstruction l3m = (L3ModificationInstruction) i;
311 L3ModificationInstruction.ModIPInstruction ip;
315 switch (l3m.subtype()) {
317 ip = (L3ModificationInstruction.ModIPInstruction) i;
318 ip4 = ip.ip().getIp4Address();
319 oxm = factory.oxms().ipv4Src(IPv4Address.of(ip4.toInt()));
322 ip = (L3ModificationInstruction.ModIPInstruction) i;
323 ip4 = ip.ip().getIp4Address();
324 oxm = factory.oxms().ipv4Dst(IPv4Address.of(ip4.toInt()));
327 ip = (L3ModificationInstruction.ModIPInstruction) i;
328 ip6 = ip.ip().getIp6Address();
329 oxm = factory.oxms().ipv6Src(IPv6Address.of(ip6.toOctets()));
332 ip = (L3ModificationInstruction.ModIPInstruction) i;
333 ip6 = ip.ip().getIp6Address();
334 oxm = factory.oxms().ipv6Dst(IPv6Address.of(ip6.toOctets()));
337 L3ModificationInstruction.ModIPv6FlowLabelInstruction flowLabelInstruction =
338 (L3ModificationInstruction.ModIPv6FlowLabelInstruction) i;
339 int flowLabel = flowLabelInstruction.flowLabel();
340 oxm = factory.oxms().ipv6Flabel(IPv6FlowLabel.of(flowLabel));
343 return factory.actions().decNwTtl();
345 return factory.actions().copyTtlIn();
347 return factory.actions().copyTtlOut();
349 log.warn("Unimplemented action type {}.", l3m.subtype());
354 return factory.actions().buildSetField().setField(oxm).build();
359 private OFGroupType getOFGroupType(GroupDescription.Type groupType) {
362 return OFGroupType.INDIRECT;
364 return OFGroupType.SELECT;
366 return OFGroupType.FF;
368 return OFGroupType.ALL;
370 log.error("Unsupported group type : {}", groupType);