blob: 83abf3703a1f8d0e03a46e42698b06227df80100 [file] [log] [blame]
sangho5afd02a2015-02-03 20:07:35 -08001/*
2 * Copyright 2015 Open Networking Laboratory
3 *
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
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
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.
15 */
16package org.onosproject.provider.of.group.impl;
17
jiangruia6b46092015-11-11 16:28:51 +080018import static org.slf4j.LoggerFactory.getLogger;
19
20import java.util.ArrayList;
21import java.util.Collections;
22import java.util.LinkedList;
23import java.util.List;
24import java.util.Optional;
25
sangho5afd02a2015-02-03 20:07:35 -080026import org.onlab.packet.Ip4Address;
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -080027import org.onlab.packet.Ip6Address;
sangho5afd02a2015-02-03 20:07:35 -080028import org.onosproject.core.GroupId;
jiangruia6b46092015-11-11 16:28:51 +080029import org.onosproject.net.DeviceId;
sangho5afd02a2015-02-03 20:07:35 -080030import org.onosproject.net.PortNumber;
jiangruia6b46092015-11-11 16:28:51 +080031import org.onosproject.net.driver.DefaultDriverData;
32import org.onosproject.net.driver.DefaultDriverHandler;
33import org.onosproject.net.driver.Driver;
34import org.onosproject.net.driver.DriverService;
sangho5afd02a2015-02-03 20:07:35 -080035import org.onosproject.net.flow.TrafficTreatment;
jiangruia6b46092015-11-11 16:28:51 +080036import org.onosproject.net.flow.instructions.ExtensionInstruction;
sangho5afd02a2015-02-03 20:07:35 -080037import org.onosproject.net.flow.instructions.Instruction;
38import org.onosproject.net.flow.instructions.Instructions;
39import org.onosproject.net.flow.instructions.L0ModificationInstruction;
40import org.onosproject.net.flow.instructions.L2ModificationInstruction;
41import org.onosproject.net.flow.instructions.L3ModificationInstruction;
42import org.onosproject.net.group.GroupBucket;
43import org.onosproject.net.group.GroupBuckets;
44import org.onosproject.net.group.GroupDescription;
jiangruia6b46092015-11-11 16:28:51 +080045import org.onosproject.openflow.controller.ExtensionInterpreter;
sangho5afd02a2015-02-03 20:07:35 -080046import org.projectfloodlight.openflow.protocol.OFBucket;
47import org.projectfloodlight.openflow.protocol.OFFactory;
48import org.projectfloodlight.openflow.protocol.OFGroupAdd;
49import org.projectfloodlight.openflow.protocol.OFGroupDelete;
50import org.projectfloodlight.openflow.protocol.OFGroupMod;
51import org.projectfloodlight.openflow.protocol.OFGroupType;
52import org.projectfloodlight.openflow.protocol.action.OFAction;
Saurav Das100e3b82015-04-30 11:12:10 -070053import org.projectfloodlight.openflow.protocol.action.OFActionGroup;
sangho5afd02a2015-02-03 20:07:35 -080054import org.projectfloodlight.openflow.protocol.action.OFActionOutput;
55import org.projectfloodlight.openflow.protocol.oxm.OFOxm;
56import org.projectfloodlight.openflow.types.CircuitSignalID;
57import org.projectfloodlight.openflow.types.EthType;
58import org.projectfloodlight.openflow.types.IPv4Address;
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -080059import org.projectfloodlight.openflow.types.IPv6Address;
60import org.projectfloodlight.openflow.types.IPv6FlowLabel;
sangho5afd02a2015-02-03 20:07:35 -080061import org.projectfloodlight.openflow.types.MacAddress;
Saurav Das73a7dd42015-08-19 22:20:31 -070062import org.projectfloodlight.openflow.types.OFBooleanValue;
sangho5afd02a2015-02-03 20:07:35 -080063import org.projectfloodlight.openflow.types.OFGroup;
64import org.projectfloodlight.openflow.types.OFPort;
65import org.projectfloodlight.openflow.types.OFVlanVidMatch;
66import org.projectfloodlight.openflow.types.U32;
67import org.projectfloodlight.openflow.types.VlanPcp;
68import org.slf4j.Logger;
69
sangho5afd02a2015-02-03 20:07:35 -080070/*
71 * Builder for GroupMod.
72 */
73public final class GroupModBuilder {
74
75 private GroupBuckets buckets;
76 private GroupId groupId;
77 private GroupDescription.Type type;
78 private OFFactory factory;
79 private Long xid;
jiangruia6b46092015-11-11 16:28:51 +080080 private Optional<DriverService> driverService;
sangho5afd02a2015-02-03 20:07:35 -080081
82 private final Logger log = getLogger(getClass());
83
84 private static final int OFPCML_NO_BUFFER = 0xffff;
85
86 private GroupModBuilder(GroupBuckets buckets, GroupId groupId,
87 GroupDescription.Type type, OFFactory factory,
88 Optional<Long> xid) {
89 this.buckets = buckets;
90 this.groupId = groupId;
91 this.type = type;
92 this.factory = factory;
93 this.xid = xid.orElse((long) 0);
94 }
95
jiangruia6b46092015-11-11 16:28:51 +080096 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;
101 this.type = type;
102 this.factory = factory;
103 this.xid = xid.orElse((long) 0);
104 this.driverService = driverService;
105 }
sangho5afd02a2015-02-03 20:07:35 -0800106 /**
107 * Creates a builder for GroupMod.
108 *
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
115 */
116 public static GroupModBuilder builder(GroupBuckets buckets, GroupId groupId,
117 GroupDescription.Type type, OFFactory factory,
118 Optional<Long> xid) {
119
120 return new GroupModBuilder(buckets, groupId, type, factory, xid);
121 }
122
123 /**
jiangruia6b46092015-11-11 16:28:51 +0800124 * Creates a builder for GroupMod.
125 *
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
133 */
134 public static GroupModBuilder builder(GroupBuckets buckets, GroupId groupId,
135 GroupDescription.Type type, OFFactory factory,
136 Optional<Long> xid, Optional<DriverService> driverService) {
137
138 return new GroupModBuilder(buckets, groupId, type, factory, xid, driverService);
139 }
140
141 /**
sangho5afd02a2015-02-03 20:07:35 -0800142 * Builds the GroupAdd OF message.
143 *
144 * @return GroupAdd OF message
145 */
146 public OFGroupAdd buildGroupAdd() {
147
148 List<OFBucket> ofBuckets = new ArrayList<OFBucket>();
149 for (GroupBucket bucket: buckets.buckets()) {
150 List<OFAction> actions = buildActions(bucket.treatment());
151
152 OFBucket.Builder bucketBuilder = factory.buildBucket();
153 bucketBuilder.setActions(actions);
154 if (type == GroupDescription.Type.SELECT) {
155 bucketBuilder.setWeight(1);
156 }
157 bucketBuilder.setWatchGroup(OFGroup.ANY);
158 bucketBuilder.setWatchPort(OFPort.ANY);
159 OFBucket ofBucket = bucketBuilder.build();
160 ofBuckets.add(ofBucket);
161 }
162
163 OFGroupAdd groupMsg = factory.buildGroupAdd()
164 .setGroup(OFGroup.of(groupId.id()))
165 .setBuckets(ofBuckets)
166 .setGroupType(getOFGroupType(type))
167 .setXid(xid)
168 .build();
169
170 return groupMsg;
171 }
172
173 /**
174 * Builds the GroupMod OF message.
175 *
176 * @return GroupMod OF message
177 */
178 public OFGroupMod buildGroupMod() {
179 List<OFBucket> ofBuckets = new ArrayList<OFBucket>();
180 for (GroupBucket bucket: buckets.buckets()) {
181 List<OFAction> actions = buildActions(bucket.treatment());
182
183 OFBucket.Builder bucketBuilder = factory.buildBucket();
184 bucketBuilder.setActions(actions);
185 if (type == GroupDescription.Type.SELECT) {
186 bucketBuilder.setWeight(1);
187 }
188 bucketBuilder.setWatchGroup(OFGroup.ANY);
189 bucketBuilder.setWatchPort(OFPort.ANY);
190 OFBucket ofBucket = bucketBuilder.build();
191 ofBuckets.add(ofBucket);
192 }
193
194 OFGroupMod groupMsg = factory.buildGroupModify()
195 .setGroup(OFGroup.of(groupId.id()))
196 .setBuckets(ofBuckets)
197 .setGroupType(getOFGroupType(type))
198 .setXid(xid)
199 .build();
200
201 return groupMsg;
202 }
203
204 /**
205 * Builds the GroupDel OF message.
206 *
207 * @return GroupDel OF message
208 */
209 public OFGroupDelete buildGroupDel() {
210
211 OFGroupDelete groupMsg = factory.buildGroupDelete()
212 .setGroup(OFGroup.of(groupId.id()))
213 .setGroupType(OFGroupType.SELECT)
214 .setXid(xid)
215 .build();
216
217 return groupMsg;
218 }
219
220 private List<OFAction> buildActions(TrafficTreatment treatment) {
sangho5afd02a2015-02-03 20:07:35 -0800221 if (treatment == null) {
Sho SHIMIZUb35ed362015-04-28 11:05:19 -0700222 return Collections.emptyList();
sangho5afd02a2015-02-03 20:07:35 -0800223 }
Jonathan Hart54b406b2015-03-06 16:24:14 -0800224
Sho SHIMIZUb35ed362015-04-28 11:05:19 -0700225 List<OFAction> actions = new LinkedList<>();
Ray Milkey42507352015-03-20 15:16:10 -0700226 for (Instruction i : treatment.allInstructions()) {
sangho5afd02a2015-02-03 20:07:35 -0800227 switch (i.type()) {
228 case DROP:
229 log.warn("Saw drop action; assigning drop action");
Sho SHIMIZUb35ed362015-04-28 11:05:19 -0700230 return Collections.emptyList();
sangho5afd02a2015-02-03 20:07:35 -0800231 case L0MODIFICATION:
232 actions.add(buildL0Modification(i));
233 break;
234 case L2MODIFICATION:
235 actions.add(buildL2Modification(i));
236 break;
237 case L3MODIFICATION:
238 actions.add(buildL3Modification(i));
239 break;
240 case OUTPUT:
241 Instructions.OutputInstruction out =
242 (Instructions.OutputInstruction) i;
243 OFActionOutput.Builder action = factory.actions().buildOutput()
244 .setPort(OFPort.of((int) out.port().toLong()));
245 if (out.port().equals(PortNumber.CONTROLLER)) {
246 action.setMaxLen(OFPCML_NO_BUFFER);
247 }
248 actions.add(action.build());
249 break;
250 case GROUP:
Saurav Das100e3b82015-04-30 11:12:10 -0700251 Instructions.GroupInstruction grp =
252 (Instructions.GroupInstruction) i;
253 OFActionGroup.Builder actgrp = factory.actions().buildGroup()
254 .setGroup(OFGroup.of(grp.groupId().id()));
255 actions.add(actgrp.build());
256 break;
jiangruia6b46092015-11-11 16:28:51 +0800257 case EXTENSION:
258 Instructions.ExtensionInstructionWrapper wrapper =
259 (Instructions.ExtensionInstructionWrapper) i;
260 actions.add(buildExtensionAction(
261 wrapper.extensionInstruction(), wrapper.deviceId()));
262 break;
sangho5afd02a2015-02-03 20:07:35 -0800263 default:
264 log.warn("Instruction type {} not yet implemented.", i.type());
265 }
266 }
267
268 return actions;
269 }
270
271 private OFAction buildL0Modification(Instruction i) {
272 L0ModificationInstruction l0m = (L0ModificationInstruction) i;
273 switch (l0m.subtype()) {
274 case LAMBDA:
275 L0ModificationInstruction.ModLambdaInstruction ml =
276 (L0ModificationInstruction.ModLambdaInstruction) i;
277 return factory.actions().circuit(factory.oxms().ochSigidBasic(
278 new CircuitSignalID((byte) 1, (byte) 2, ml.lambda(), (short) 1)));
279 default:
280 log.warn("Unimplemented action type {}.", l0m.subtype());
281 break;
282 }
283 return null;
284 }
285
286 private OFAction buildL2Modification(Instruction i) {
287 L2ModificationInstruction l2m = (L2ModificationInstruction) i;
288 L2ModificationInstruction.ModEtherInstruction eth;
289 OFOxm<?> oxm = null;
290 switch (l2m.subtype()) {
291 case ETH_DST:
292 eth = (L2ModificationInstruction.ModEtherInstruction) l2m;
293 oxm = factory.oxms().ethDst(MacAddress.of(eth.mac().toLong()));
294 break;
295 case ETH_SRC:
296 eth = (L2ModificationInstruction.ModEtherInstruction) l2m;
297 oxm = factory.oxms().ethSrc(MacAddress.of(eth.mac().toLong()));
298 break;
299 case VLAN_ID:
300 L2ModificationInstruction.ModVlanIdInstruction vlanId =
301 (L2ModificationInstruction.ModVlanIdInstruction) l2m;
302 oxm = factory.oxms().vlanVid(OFVlanVidMatch.ofVlan(vlanId.vlanId().toShort()));
303 break;
304 case VLAN_PCP:
305 L2ModificationInstruction.ModVlanPcpInstruction vlanPcp =
306 (L2ModificationInstruction.ModVlanPcpInstruction) l2m;
307 oxm = factory.oxms().vlanPcp(VlanPcp.of(vlanPcp.vlanPcp()));
308 break;
Jonathan Hart54b406b2015-03-06 16:24:14 -0800309 case VLAN_POP:
310 return factory.actions().popVlan();
311 case VLAN_PUSH:
312 L2ModificationInstruction.PushHeaderInstructions pushVlanInstruction
313 = (L2ModificationInstruction.PushHeaderInstructions) l2m;
314 return factory.actions().pushVlan(
alshabib7b808c52015-06-26 14:22:24 -0700315 EthType.of(pushVlanInstruction.ethernetType().toShort()));
sangho5afd02a2015-02-03 20:07:35 -0800316 case MPLS_PUSH:
317 L2ModificationInstruction.PushHeaderInstructions pushHeaderInstructions =
318 (L2ModificationInstruction.PushHeaderInstructions) l2m;
319 return factory.actions().pushMpls(EthType.of(pushHeaderInstructions
alshabib7b808c52015-06-26 14:22:24 -0700320 .ethernetType().toShort()));
sangho5afd02a2015-02-03 20:07:35 -0800321 case MPLS_POP:
322 L2ModificationInstruction.PushHeaderInstructions popHeaderInstructions =
323 (L2ModificationInstruction.PushHeaderInstructions) l2m;
324 return factory.actions().popMpls(EthType.of(popHeaderInstructions
alshabib7b808c52015-06-26 14:22:24 -0700325 .ethernetType().toShort()));
sangho5afd02a2015-02-03 20:07:35 -0800326 case MPLS_LABEL:
327 L2ModificationInstruction.ModMplsLabelInstruction mplsLabel =
328 (L2ModificationInstruction.ModMplsLabelInstruction) l2m;
HIGUCHI Yuta04b49fc2015-08-28 09:58:58 -0700329 oxm = factory.oxms().mplsLabel(U32.of(mplsLabel.mplsLabel().toInt()));
sangho5afd02a2015-02-03 20:07:35 -0800330 break;
Saurav Das73a7dd42015-08-19 22:20:31 -0700331 case MPLS_BOS:
332 L2ModificationInstruction.ModMplsBosInstruction mplsBos =
333 (L2ModificationInstruction.ModMplsBosInstruction) l2m;
334 oxm = factory.oxms()
335 .mplsBos(mplsBos.mplsBos() ? OFBooleanValue.TRUE
336 : OFBooleanValue.FALSE);
337 break;
sangho5afd02a2015-02-03 20:07:35 -0800338 case DEC_MPLS_TTL:
339 return factory.actions().decMplsTtl();
340 default:
341 log.warn("Unimplemented action type {}.", l2m.subtype());
342 break;
343 }
344
345 if (oxm != null) {
346 return factory.actions().buildSetField().setField(oxm).build();
347 }
348 return null;
349 }
350
351 private OFAction buildL3Modification(Instruction i) {
352 L3ModificationInstruction l3m = (L3ModificationInstruction) i;
353 L3ModificationInstruction.ModIPInstruction ip;
354 Ip4Address ip4;
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800355 Ip6Address ip6;
sangho5afd02a2015-02-03 20:07:35 -0800356 OFOxm<?> oxm = null;
357 switch (l3m.subtype()) {
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800358 case IPV4_SRC:
359 ip = (L3ModificationInstruction.ModIPInstruction) i;
360 ip4 = ip.ip().getIp4Address();
361 oxm = factory.oxms().ipv4Src(IPv4Address.of(ip4.toInt()));
362 break;
363 case IPV4_DST:
sangho5afd02a2015-02-03 20:07:35 -0800364 ip = (L3ModificationInstruction.ModIPInstruction) i;
365 ip4 = ip.ip().getIp4Address();
366 oxm = factory.oxms().ipv4Dst(IPv4Address.of(ip4.toInt()));
367 break;
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800368 case IPV6_SRC:
sangho5afd02a2015-02-03 20:07:35 -0800369 ip = (L3ModificationInstruction.ModIPInstruction) i;
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800370 ip6 = ip.ip().getIp6Address();
371 oxm = factory.oxms().ipv6Src(IPv6Address.of(ip6.toOctets()));
372 break;
373 case IPV6_DST:
374 ip = (L3ModificationInstruction.ModIPInstruction) i;
375 ip6 = ip.ip().getIp6Address();
376 oxm = factory.oxms().ipv6Dst(IPv6Address.of(ip6.toOctets()));
377 break;
378 case IPV6_FLABEL:
379 L3ModificationInstruction.ModIPv6FlowLabelInstruction flowLabelInstruction =
380 (L3ModificationInstruction.ModIPv6FlowLabelInstruction) i;
381 int flowLabel = flowLabelInstruction.flowLabel();
382 oxm = factory.oxms().ipv6Flabel(IPv6FlowLabel.of(flowLabel));
sangho5afd02a2015-02-03 20:07:35 -0800383 break;
384 case DEC_TTL:
385 return factory.actions().decNwTtl();
386 case TTL_IN:
387 return factory.actions().copyTtlIn();
388 case TTL_OUT:
389 return factory.actions().copyTtlOut();
390 default:
391 log.warn("Unimplemented action type {}.", l3m.subtype());
392 break;
393 }
394
395 if (oxm != null) {
396 return factory.actions().buildSetField().setField(oxm).build();
397 }
398 return null;
399 }
400
401 private OFGroupType getOFGroupType(GroupDescription.Type groupType) {
402 switch (groupType) {
403 case INDIRECT:
404 return OFGroupType.INDIRECT;
405 case SELECT:
406 return OFGroupType.SELECT;
407 case FAILOVER:
408 return OFGroupType.FF;
409 case ALL:
410 return OFGroupType.ALL;
411 default:
412 log.error("Unsupported group type : {}", groupType);
413 break;
414 }
415 return null;
416 }
jiangruia6b46092015-11-11 16:28:51 +0800417
418 private OFAction buildExtensionAction(ExtensionInstruction i, DeviceId deviceId) {
419 if (!driverService.isPresent()) {
420 log.error("No driver service present");
421 return null;
422 }
423 Driver driver = driverService.get().getDriver(deviceId);
424 if (driver.hasBehaviour(ExtensionInterpreter.class)) {
425 DefaultDriverHandler handler =
426 new DefaultDriverHandler(new DefaultDriverData(driver, deviceId));
427 ExtensionInterpreter interpreter = handler.behaviour(ExtensionInterpreter.class);
428 return interpreter.mapInstruction(factory, i);
429 }
430
431 return null;
432 }
sangho5afd02a2015-02-03 20:07:35 -0800433}
434