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 static org.slf4j.LoggerFactory.getLogger;
20 import java.util.ArrayList;
21 import java.util.Collections;
22 import java.util.LinkedList;
23 import java.util.List;
24 import java.util.Optional;
26 import org.onlab.packet.Ip4Address;
27 import org.onlab.packet.Ip6Address;
28 import org.onosproject.core.GroupId;
29 import org.onosproject.net.DeviceId;
30 import org.onosproject.net.PortNumber;
31 import org.onosproject.net.driver.DefaultDriverData;
32 import org.onosproject.net.driver.DefaultDriverHandler;
33 import org.onosproject.net.driver.Driver;
34 import org.onosproject.net.driver.DriverService;
35 import org.onosproject.net.flow.TrafficTreatment;
36 import org.onosproject.net.flow.instructions.ExtensionInstruction;
37 import org.onosproject.net.flow.instructions.Instruction;
38 import org.onosproject.net.flow.instructions.Instructions;
39 import org.onosproject.net.flow.instructions.L0ModificationInstruction;
40 import org.onosproject.net.flow.instructions.L2ModificationInstruction;
41 import org.onosproject.net.flow.instructions.L3ModificationInstruction;
42 import org.onosproject.net.group.GroupBucket;
43 import org.onosproject.net.group.GroupBuckets;
44 import org.onosproject.net.group.GroupDescription;
45 import org.onosproject.openflow.controller.ExtensionInterpreter;
46 import org.projectfloodlight.openflow.protocol.OFBucket;
47 import org.projectfloodlight.openflow.protocol.OFFactory;
48 import org.projectfloodlight.openflow.protocol.OFGroupAdd;
49 import org.projectfloodlight.openflow.protocol.OFGroupDelete;
50 import org.projectfloodlight.openflow.protocol.OFGroupMod;
51 import org.projectfloodlight.openflow.protocol.OFGroupType;
52 import org.projectfloodlight.openflow.protocol.action.OFAction;
53 import org.projectfloodlight.openflow.protocol.action.OFActionGroup;
54 import org.projectfloodlight.openflow.protocol.action.OFActionOutput;
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.OFGroup;
64 import org.projectfloodlight.openflow.types.OFPort;
65 import org.projectfloodlight.openflow.types.OFVlanVidMatch;
66 import org.projectfloodlight.openflow.types.U32;
67 import org.projectfloodlight.openflow.types.VlanPcp;
68 import org.slf4j.Logger;
71 * Builder for GroupMod.
73 public final class GroupModBuilder {
75 private GroupBuckets buckets;
76 private GroupId groupId;
77 private GroupDescription.Type type;
78 private OFFactory factory;
80 private Optional<DriverService> driverService;
82 private final Logger log = getLogger(getClass());
84 private static final int OFPCML_NO_BUFFER = 0xffff;
86 private GroupModBuilder(GroupBuckets buckets, GroupId groupId,
87 GroupDescription.Type type, OFFactory factory,
89 this.buckets = buckets;
90 this.groupId = groupId;
92 this.factory = factory;
93 this.xid = xid.orElse((long) 0);
96 private GroupModBuilder(GroupBuckets buckets, GroupId groupId,
97 GroupDescription.Type type, OFFactory factory,
98 Optional<Long> xid, Optional<DriverService> driverService) {
99 this.buckets = buckets;
100 this.groupId = groupId;
102 this.factory = factory;
103 this.xid = xid.orElse((long) 0);
104 this.driverService = driverService;
107 * Creates a builder for GroupMod.
109 * @param buckets GroupBuckets object
110 * @param groupId Group Id to create
111 * @param type Group type
112 * @param factory OFFactory object
113 * @param xid transaction ID
114 * @return GroupModBuilder object
116 public static GroupModBuilder builder(GroupBuckets buckets, GroupId groupId,
117 GroupDescription.Type type, OFFactory factory,
118 Optional<Long> xid) {
120 return new GroupModBuilder(buckets, groupId, type, factory, xid);
124 * Creates a builder for GroupMod.
126 * @param buckets GroupBuckets object
127 * @param groupId Group Id to create
128 * @param type Group type
129 * @param factory OFFactory object
130 * @param xid transaction ID
131 * @param driverService driver Service
132 * @return GroupModBuilder object
134 public static GroupModBuilder builder(GroupBuckets buckets, GroupId groupId,
135 GroupDescription.Type type, OFFactory factory,
136 Optional<Long> xid, Optional<DriverService> driverService) {
138 return new GroupModBuilder(buckets, groupId, type, factory, xid, driverService);
142 * Builds the GroupAdd OF message.
144 * @return GroupAdd OF message
146 public OFGroupAdd buildGroupAdd() {
148 List<OFBucket> ofBuckets = new ArrayList<OFBucket>();
149 for (GroupBucket bucket: buckets.buckets()) {
150 List<OFAction> actions = buildActions(bucket.treatment());
152 OFBucket.Builder bucketBuilder = factory.buildBucket();
153 bucketBuilder.setActions(actions);
154 if (type == GroupDescription.Type.SELECT) {
155 bucketBuilder.setWeight(1);
158 if (type == GroupDescription.Type.FAILOVER && bucket.watchPort() != null) {
159 bucketBuilder.setWatchPort(OFPort.of((int) bucket.watchPort().toLong()));
161 bucketBuilder.setWatchPort(OFPort.ANY);
163 if (type == GroupDescription.Type.FAILOVER && bucket.watchGroup() != null) {
164 bucketBuilder.setWatchGroup(OFGroup.of(bucket.watchGroup().id()));
166 bucketBuilder.setWatchGroup(OFGroup.ANY);
168 OFBucket ofBucket = bucketBuilder.build();
169 ofBuckets.add(ofBucket);
172 OFGroupAdd groupMsg = factory.buildGroupAdd()
173 .setGroup(OFGroup.of(groupId.id()))
174 .setBuckets(ofBuckets)
175 .setGroupType(getOFGroupType(type))
183 * Builds the GroupMod OF message.
185 * @return GroupMod OF message
187 public OFGroupMod buildGroupMod() {
188 List<OFBucket> ofBuckets = new ArrayList<OFBucket>();
189 for (GroupBucket bucket: buckets.buckets()) {
190 List<OFAction> actions = buildActions(bucket.treatment());
192 OFBucket.Builder bucketBuilder = factory.buildBucket();
193 bucketBuilder.setActions(actions);
194 if (type == GroupDescription.Type.SELECT) {
195 bucketBuilder.setWeight(1);
197 bucketBuilder.setWatchGroup(OFGroup.ANY);
198 bucketBuilder.setWatchPort(OFPort.ANY);
199 OFBucket ofBucket = bucketBuilder.build();
200 ofBuckets.add(ofBucket);
203 OFGroupMod groupMsg = factory.buildGroupModify()
204 .setGroup(OFGroup.of(groupId.id()))
205 .setBuckets(ofBuckets)
206 .setGroupType(getOFGroupType(type))
214 * Builds the GroupDel OF message.
216 * @return GroupDel OF message
218 public OFGroupDelete buildGroupDel() {
220 OFGroupDelete groupMsg = factory.buildGroupDelete()
221 .setGroup(OFGroup.of(groupId.id()))
222 .setGroupType(OFGroupType.SELECT)
229 private List<OFAction> buildActions(TrafficTreatment treatment) {
230 if (treatment == null) {
231 return Collections.emptyList();
234 List<OFAction> actions = new LinkedList<>();
235 for (Instruction i : treatment.allInstructions()) {
238 log.warn("Saw drop action; assigning drop action");
239 return Collections.emptyList();
241 actions.add(buildL0Modification(i));
244 actions.add(buildL2Modification(i));
247 actions.add(buildL3Modification(i));
250 Instructions.OutputInstruction out =
251 (Instructions.OutputInstruction) i;
252 OFActionOutput.Builder action = factory.actions().buildOutput()
253 .setPort(OFPort.of((int) out.port().toLong()));
254 if (out.port().equals(PortNumber.CONTROLLER)) {
255 action.setMaxLen(OFPCML_NO_BUFFER);
257 actions.add(action.build());
260 Instructions.GroupInstruction grp =
261 (Instructions.GroupInstruction) i;
262 OFActionGroup.Builder actgrp = factory.actions().buildGroup()
263 .setGroup(OFGroup.of(grp.groupId().id()));
264 actions.add(actgrp.build());
267 Instructions.ExtensionInstructionWrapper wrapper =
268 (Instructions.ExtensionInstructionWrapper) i;
269 actions.add(buildExtensionAction(
270 wrapper.extensionInstruction(), wrapper.deviceId()));
273 log.warn("Instruction type {} not yet implemented.", i.type());
280 private OFAction buildL0Modification(Instruction i) {
281 L0ModificationInstruction l0m = (L0ModificationInstruction) i;
282 switch (l0m.subtype()) {
284 L0ModificationInstruction.ModLambdaInstruction ml =
285 (L0ModificationInstruction.ModLambdaInstruction) i;
286 return factory.actions().circuit(factory.oxms().ochSigidBasic(
287 new CircuitSignalID((byte) 1, (byte) 2, ml.lambda(), (short) 1)));
289 log.warn("Unimplemented action type {}.", l0m.subtype());
295 private OFAction buildL2Modification(Instruction i) {
296 L2ModificationInstruction l2m = (L2ModificationInstruction) i;
297 L2ModificationInstruction.ModEtherInstruction eth;
299 switch (l2m.subtype()) {
301 eth = (L2ModificationInstruction.ModEtherInstruction) l2m;
302 oxm = factory.oxms().ethDst(MacAddress.of(eth.mac().toLong()));
305 eth = (L2ModificationInstruction.ModEtherInstruction) l2m;
306 oxm = factory.oxms().ethSrc(MacAddress.of(eth.mac().toLong()));
309 L2ModificationInstruction.ModVlanIdInstruction vlanId =
310 (L2ModificationInstruction.ModVlanIdInstruction) l2m;
311 oxm = factory.oxms().vlanVid(OFVlanVidMatch.ofVlan(vlanId.vlanId().toShort()));
314 L2ModificationInstruction.ModVlanPcpInstruction vlanPcp =
315 (L2ModificationInstruction.ModVlanPcpInstruction) l2m;
316 oxm = factory.oxms().vlanPcp(VlanPcp.of(vlanPcp.vlanPcp()));
319 return factory.actions().popVlan();
321 L2ModificationInstruction.PushHeaderInstructions pushVlanInstruction
322 = (L2ModificationInstruction.PushHeaderInstructions) l2m;
323 return factory.actions().pushVlan(
324 EthType.of(pushVlanInstruction.ethernetType().toShort()));
326 L2ModificationInstruction.PushHeaderInstructions pushHeaderInstructions =
327 (L2ModificationInstruction.PushHeaderInstructions) l2m;
328 return factory.actions().pushMpls(EthType.of(pushHeaderInstructions
329 .ethernetType().toShort()));
331 L2ModificationInstruction.PushHeaderInstructions popHeaderInstructions =
332 (L2ModificationInstruction.PushHeaderInstructions) l2m;
333 return factory.actions().popMpls(EthType.of(popHeaderInstructions
334 .ethernetType().toShort()));
336 L2ModificationInstruction.ModMplsLabelInstruction mplsLabel =
337 (L2ModificationInstruction.ModMplsLabelInstruction) l2m;
338 oxm = factory.oxms().mplsLabel(U32.of(mplsLabel.mplsLabel().toInt()));
341 L2ModificationInstruction.ModMplsBosInstruction mplsBos =
342 (L2ModificationInstruction.ModMplsBosInstruction) l2m;
344 .mplsBos(mplsBos.mplsBos() ? OFBooleanValue.TRUE
345 : OFBooleanValue.FALSE);
348 return factory.actions().decMplsTtl();
350 log.warn("Unimplemented action type {}.", l2m.subtype());
355 return factory.actions().buildSetField().setField(oxm).build();
360 private OFAction buildL3Modification(Instruction i) {
361 L3ModificationInstruction l3m = (L3ModificationInstruction) i;
362 L3ModificationInstruction.ModIPInstruction ip;
366 switch (l3m.subtype()) {
368 ip = (L3ModificationInstruction.ModIPInstruction) i;
369 ip4 = ip.ip().getIp4Address();
370 oxm = factory.oxms().ipv4Src(IPv4Address.of(ip4.toInt()));
373 ip = (L3ModificationInstruction.ModIPInstruction) i;
374 ip4 = ip.ip().getIp4Address();
375 oxm = factory.oxms().ipv4Dst(IPv4Address.of(ip4.toInt()));
378 ip = (L3ModificationInstruction.ModIPInstruction) i;
379 ip6 = ip.ip().getIp6Address();
380 oxm = factory.oxms().ipv6Src(IPv6Address.of(ip6.toOctets()));
383 ip = (L3ModificationInstruction.ModIPInstruction) i;
384 ip6 = ip.ip().getIp6Address();
385 oxm = factory.oxms().ipv6Dst(IPv6Address.of(ip6.toOctets()));
388 L3ModificationInstruction.ModIPv6FlowLabelInstruction flowLabelInstruction =
389 (L3ModificationInstruction.ModIPv6FlowLabelInstruction) i;
390 int flowLabel = flowLabelInstruction.flowLabel();
391 oxm = factory.oxms().ipv6Flabel(IPv6FlowLabel.of(flowLabel));
394 return factory.actions().decNwTtl();
396 return factory.actions().copyTtlIn();
398 return factory.actions().copyTtlOut();
400 log.warn("Unimplemented action type {}.", l3m.subtype());
405 return factory.actions().buildSetField().setField(oxm).build();
410 private OFGroupType getOFGroupType(GroupDescription.Type groupType) {
413 return OFGroupType.INDIRECT;
415 return OFGroupType.SELECT;
417 return OFGroupType.FF;
419 return OFGroupType.ALL;
421 log.error("Unsupported group type : {}", groupType);
427 private OFAction buildExtensionAction(ExtensionInstruction i, DeviceId deviceId) {
428 if (!driverService.isPresent()) {
429 log.error("No driver service present");
432 Driver driver = driverService.get().getDriver(deviceId);
433 if (driver.hasBehaviour(ExtensionInterpreter.class)) {
434 DefaultDriverHandler handler =
435 new DefaultDriverHandler(new DefaultDriverData(driver, deviceId));
436 ExtensionInterpreter interpreter = handler.behaviour(ExtensionInterpreter.class);
437 return interpreter.mapInstruction(factory, i);