blob: cecdba6b20b80615ded9d66961d044484a008759 [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;
alshabib880b6442015-11-23 22:13:04 -080036import org.onosproject.net.flow.instructions.ExtensionTreatment;
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;
alshabib880b6442015-11-23 22:13:04 -080045import org.onosproject.openflow.controller.ExtensionTreatmentInterpreter;
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;
Hyunsun Moon9ae22e92015-12-15 20:34:51 -080067import org.projectfloodlight.openflow.types.U64;
sangho5afd02a2015-02-03 20:07:35 -080068import org.projectfloodlight.openflow.types.VlanPcp;
69import org.slf4j.Logger;
70
sangho5afd02a2015-02-03 20:07:35 -080071/*
72 * Builder for GroupMod.
73 */
74public final class GroupModBuilder {
75
76 private GroupBuckets buckets;
77 private GroupId groupId;
78 private GroupDescription.Type type;
79 private OFFactory factory;
80 private Long xid;
jiangruia6b46092015-11-11 16:28:51 +080081 private Optional<DriverService> driverService;
sangho5afd02a2015-02-03 20:07:35 -080082
83 private final Logger log = getLogger(getClass());
84
85 private static final int OFPCML_NO_BUFFER = 0xffff;
86
87 private GroupModBuilder(GroupBuckets buckets, GroupId groupId,
88 GroupDescription.Type type, OFFactory factory,
89 Optional<Long> xid) {
90 this.buckets = buckets;
91 this.groupId = groupId;
92 this.type = type;
93 this.factory = factory;
94 this.xid = xid.orElse((long) 0);
95 }
96
jiangruia6b46092015-11-11 16:28:51 +080097 private GroupModBuilder(GroupBuckets buckets, GroupId groupId,
98 GroupDescription.Type type, OFFactory factory,
99 Optional<Long> xid, Optional<DriverService> driverService) {
100 this.buckets = buckets;
101 this.groupId = groupId;
102 this.type = type;
103 this.factory = factory;
104 this.xid = xid.orElse((long) 0);
105 this.driverService = driverService;
106 }
sangho5afd02a2015-02-03 20:07:35 -0800107 /**
108 * Creates a builder for GroupMod.
109 *
110 * @param buckets GroupBuckets object
111 * @param groupId Group Id to create
112 * @param type Group type
113 * @param factory OFFactory object
114 * @param xid transaction ID
115 * @return GroupModBuilder object
116 */
117 public static GroupModBuilder builder(GroupBuckets buckets, GroupId groupId,
118 GroupDescription.Type type, OFFactory factory,
119 Optional<Long> xid) {
120
121 return new GroupModBuilder(buckets, groupId, type, factory, xid);
122 }
123
124 /**
jiangruia6b46092015-11-11 16:28:51 +0800125 * Creates a builder for GroupMod.
126 *
127 * @param buckets GroupBuckets object
128 * @param groupId Group Id to create
129 * @param type Group type
130 * @param factory OFFactory object
131 * @param xid transaction ID
132 * @param driverService driver Service
133 * @return GroupModBuilder object
134 */
135 public static GroupModBuilder builder(GroupBuckets buckets, GroupId groupId,
136 GroupDescription.Type type, OFFactory factory,
137 Optional<Long> xid, Optional<DriverService> driverService) {
138
139 return new GroupModBuilder(buckets, groupId, type, factory, xid, driverService);
140 }
141
142 /**
sangho5afd02a2015-02-03 20:07:35 -0800143 * Builds the GroupAdd OF message.
144 *
145 * @return GroupAdd OF message
146 */
147 public OFGroupAdd buildGroupAdd() {
148
149 List<OFBucket> ofBuckets = new ArrayList<OFBucket>();
150 for (GroupBucket bucket: buckets.buckets()) {
151 List<OFAction> actions = buildActions(bucket.treatment());
152
153 OFBucket.Builder bucketBuilder = factory.buildBucket();
154 bucketBuilder.setActions(actions);
155 if (type == GroupDescription.Type.SELECT) {
156 bucketBuilder.setWeight(1);
157 }
AdrianAlan0be87242015-11-15 18:43:29 +0100158
159 if (type == GroupDescription.Type.FAILOVER && bucket.watchPort() != null) {
160 bucketBuilder.setWatchPort(OFPort.of((int) bucket.watchPort().toLong()));
161 } else {
162 bucketBuilder.setWatchPort(OFPort.ANY);
163 }
164 if (type == GroupDescription.Type.FAILOVER && bucket.watchGroup() != null) {
165 bucketBuilder.setWatchGroup(OFGroup.of(bucket.watchGroup().id()));
166 } else {
167 bucketBuilder.setWatchGroup(OFGroup.ANY);
168 }
sangho5afd02a2015-02-03 20:07:35 -0800169 OFBucket ofBucket = bucketBuilder.build();
170 ofBuckets.add(ofBucket);
171 }
172
173 OFGroupAdd groupMsg = factory.buildGroupAdd()
174 .setGroup(OFGroup.of(groupId.id()))
175 .setBuckets(ofBuckets)
176 .setGroupType(getOFGroupType(type))
177 .setXid(xid)
178 .build();
179
180 return groupMsg;
181 }
182
183 /**
184 * Builds the GroupMod OF message.
185 *
186 * @return GroupMod OF message
187 */
188 public OFGroupMod buildGroupMod() {
189 List<OFBucket> ofBuckets = new ArrayList<OFBucket>();
190 for (GroupBucket bucket: buckets.buckets()) {
191 List<OFAction> actions = buildActions(bucket.treatment());
192
193 OFBucket.Builder bucketBuilder = factory.buildBucket();
194 bucketBuilder.setActions(actions);
195 if (type == GroupDescription.Type.SELECT) {
196 bucketBuilder.setWeight(1);
197 }
198 bucketBuilder.setWatchGroup(OFGroup.ANY);
199 bucketBuilder.setWatchPort(OFPort.ANY);
200 OFBucket ofBucket = bucketBuilder.build();
201 ofBuckets.add(ofBucket);
202 }
203
204 OFGroupMod groupMsg = factory.buildGroupModify()
205 .setGroup(OFGroup.of(groupId.id()))
206 .setBuckets(ofBuckets)
207 .setGroupType(getOFGroupType(type))
208 .setXid(xid)
209 .build();
210
211 return groupMsg;
212 }
213
214 /**
215 * Builds the GroupDel OF message.
216 *
217 * @return GroupDel OF message
218 */
219 public OFGroupDelete buildGroupDel() {
220
221 OFGroupDelete groupMsg = factory.buildGroupDelete()
222 .setGroup(OFGroup.of(groupId.id()))
223 .setGroupType(OFGroupType.SELECT)
224 .setXid(xid)
225 .build();
226
227 return groupMsg;
228 }
229
230 private List<OFAction> buildActions(TrafficTreatment treatment) {
sangho5afd02a2015-02-03 20:07:35 -0800231 if (treatment == null) {
Sho SHIMIZUb35ed362015-04-28 11:05:19 -0700232 return Collections.emptyList();
sangho5afd02a2015-02-03 20:07:35 -0800233 }
Jonathan Hart54b406b2015-03-06 16:24:14 -0800234
Sho SHIMIZUb35ed362015-04-28 11:05:19 -0700235 List<OFAction> actions = new LinkedList<>();
Ray Milkey42507352015-03-20 15:16:10 -0700236 for (Instruction i : treatment.allInstructions()) {
sangho5afd02a2015-02-03 20:07:35 -0800237 switch (i.type()) {
sangho5afd02a2015-02-03 20:07:35 -0800238 case L0MODIFICATION:
239 actions.add(buildL0Modification(i));
240 break;
241 case L2MODIFICATION:
242 actions.add(buildL2Modification(i));
243 break;
244 case L3MODIFICATION:
245 actions.add(buildL3Modification(i));
246 break;
247 case OUTPUT:
248 Instructions.OutputInstruction out =
249 (Instructions.OutputInstruction) i;
250 OFActionOutput.Builder action = factory.actions().buildOutput()
251 .setPort(OFPort.of((int) out.port().toLong()));
252 if (out.port().equals(PortNumber.CONTROLLER)) {
253 action.setMaxLen(OFPCML_NO_BUFFER);
254 }
255 actions.add(action.build());
256 break;
257 case GROUP:
Saurav Das100e3b82015-04-30 11:12:10 -0700258 Instructions.GroupInstruction grp =
259 (Instructions.GroupInstruction) i;
260 OFActionGroup.Builder actgrp = factory.actions().buildGroup()
261 .setGroup(OFGroup.of(grp.groupId().id()));
262 actions.add(actgrp.build());
263 break;
jiangruia6b46092015-11-11 16:28:51 +0800264 case EXTENSION:
265 Instructions.ExtensionInstructionWrapper wrapper =
266 (Instructions.ExtensionInstructionWrapper) i;
267 actions.add(buildExtensionAction(
268 wrapper.extensionInstruction(), wrapper.deviceId()));
269 break;
sangho5afd02a2015-02-03 20:07:35 -0800270 default:
271 log.warn("Instruction type {} not yet implemented.", i.type());
272 }
273 }
274
275 return actions;
276 }
277
278 private OFAction buildL0Modification(Instruction i) {
279 L0ModificationInstruction l0m = (L0ModificationInstruction) i;
280 switch (l0m.subtype()) {
281 case LAMBDA:
282 L0ModificationInstruction.ModLambdaInstruction ml =
283 (L0ModificationInstruction.ModLambdaInstruction) i;
284 return factory.actions().circuit(factory.oxms().ochSigidBasic(
285 new CircuitSignalID((byte) 1, (byte) 2, ml.lambda(), (short) 1)));
286 default:
287 log.warn("Unimplemented action type {}.", l0m.subtype());
288 break;
289 }
290 return null;
291 }
292
293 private OFAction buildL2Modification(Instruction i) {
294 L2ModificationInstruction l2m = (L2ModificationInstruction) i;
295 L2ModificationInstruction.ModEtherInstruction eth;
296 OFOxm<?> oxm = null;
297 switch (l2m.subtype()) {
298 case ETH_DST:
299 eth = (L2ModificationInstruction.ModEtherInstruction) l2m;
300 oxm = factory.oxms().ethDst(MacAddress.of(eth.mac().toLong()));
301 break;
302 case ETH_SRC:
303 eth = (L2ModificationInstruction.ModEtherInstruction) l2m;
304 oxm = factory.oxms().ethSrc(MacAddress.of(eth.mac().toLong()));
305 break;
306 case VLAN_ID:
307 L2ModificationInstruction.ModVlanIdInstruction vlanId =
308 (L2ModificationInstruction.ModVlanIdInstruction) l2m;
309 oxm = factory.oxms().vlanVid(OFVlanVidMatch.ofVlan(vlanId.vlanId().toShort()));
310 break;
311 case VLAN_PCP:
312 L2ModificationInstruction.ModVlanPcpInstruction vlanPcp =
313 (L2ModificationInstruction.ModVlanPcpInstruction) l2m;
314 oxm = factory.oxms().vlanPcp(VlanPcp.of(vlanPcp.vlanPcp()));
315 break;
Jonathan Hart54b406b2015-03-06 16:24:14 -0800316 case VLAN_POP:
317 return factory.actions().popVlan();
318 case VLAN_PUSH:
319 L2ModificationInstruction.PushHeaderInstructions pushVlanInstruction
320 = (L2ModificationInstruction.PushHeaderInstructions) l2m;
321 return factory.actions().pushVlan(
alshabib7b808c52015-06-26 14:22:24 -0700322 EthType.of(pushVlanInstruction.ethernetType().toShort()));
sangho5afd02a2015-02-03 20:07:35 -0800323 case MPLS_PUSH:
324 L2ModificationInstruction.PushHeaderInstructions pushHeaderInstructions =
325 (L2ModificationInstruction.PushHeaderInstructions) l2m;
326 return factory.actions().pushMpls(EthType.of(pushHeaderInstructions
alshabib7b808c52015-06-26 14:22:24 -0700327 .ethernetType().toShort()));
sangho5afd02a2015-02-03 20:07:35 -0800328 case MPLS_POP:
329 L2ModificationInstruction.PushHeaderInstructions popHeaderInstructions =
330 (L2ModificationInstruction.PushHeaderInstructions) l2m;
331 return factory.actions().popMpls(EthType.of(popHeaderInstructions
alshabib7b808c52015-06-26 14:22:24 -0700332 .ethernetType().toShort()));
sangho5afd02a2015-02-03 20:07:35 -0800333 case MPLS_LABEL:
334 L2ModificationInstruction.ModMplsLabelInstruction mplsLabel =
335 (L2ModificationInstruction.ModMplsLabelInstruction) l2m;
Ray Milkey125572b2016-02-22 16:48:17 -0800336 oxm = factory.oxms().mplsLabel(U32.of(mplsLabel.label().toInt()));
sangho5afd02a2015-02-03 20:07:35 -0800337 break;
Saurav Das73a7dd42015-08-19 22:20:31 -0700338 case MPLS_BOS:
339 L2ModificationInstruction.ModMplsBosInstruction mplsBos =
340 (L2ModificationInstruction.ModMplsBosInstruction) l2m;
341 oxm = factory.oxms()
342 .mplsBos(mplsBos.mplsBos() ? OFBooleanValue.TRUE
343 : OFBooleanValue.FALSE);
344 break;
sangho5afd02a2015-02-03 20:07:35 -0800345 case DEC_MPLS_TTL:
346 return factory.actions().decMplsTtl();
Hyunsun Moon9ae22e92015-12-15 20:34:51 -0800347 case TUNNEL_ID:
348 L2ModificationInstruction.ModTunnelIdInstruction tunnelId =
349 (L2ModificationInstruction.ModTunnelIdInstruction) l2m;
350 oxm = factory.oxms().tunnelId(U64.of(tunnelId.tunnelId()));
351 break;
sangho5afd02a2015-02-03 20:07:35 -0800352 default:
353 log.warn("Unimplemented action type {}.", l2m.subtype());
354 break;
355 }
356
357 if (oxm != null) {
358 return factory.actions().buildSetField().setField(oxm).build();
359 }
360 return null;
361 }
362
363 private OFAction buildL3Modification(Instruction i) {
364 L3ModificationInstruction l3m = (L3ModificationInstruction) i;
365 L3ModificationInstruction.ModIPInstruction ip;
366 Ip4Address ip4;
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800367 Ip6Address ip6;
sangho5afd02a2015-02-03 20:07:35 -0800368 OFOxm<?> oxm = null;
369 switch (l3m.subtype()) {
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800370 case IPV4_SRC:
371 ip = (L3ModificationInstruction.ModIPInstruction) i;
372 ip4 = ip.ip().getIp4Address();
373 oxm = factory.oxms().ipv4Src(IPv4Address.of(ip4.toInt()));
374 break;
375 case IPV4_DST:
sangho5afd02a2015-02-03 20:07:35 -0800376 ip = (L3ModificationInstruction.ModIPInstruction) i;
377 ip4 = ip.ip().getIp4Address();
378 oxm = factory.oxms().ipv4Dst(IPv4Address.of(ip4.toInt()));
379 break;
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800380 case IPV6_SRC:
sangho5afd02a2015-02-03 20:07:35 -0800381 ip = (L3ModificationInstruction.ModIPInstruction) i;
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800382 ip6 = ip.ip().getIp6Address();
383 oxm = factory.oxms().ipv6Src(IPv6Address.of(ip6.toOctets()));
384 break;
385 case IPV6_DST:
386 ip = (L3ModificationInstruction.ModIPInstruction) i;
387 ip6 = ip.ip().getIp6Address();
388 oxm = factory.oxms().ipv6Dst(IPv6Address.of(ip6.toOctets()));
389 break;
390 case IPV6_FLABEL:
391 L3ModificationInstruction.ModIPv6FlowLabelInstruction flowLabelInstruction =
392 (L3ModificationInstruction.ModIPv6FlowLabelInstruction) i;
393 int flowLabel = flowLabelInstruction.flowLabel();
394 oxm = factory.oxms().ipv6Flabel(IPv6FlowLabel.of(flowLabel));
sangho5afd02a2015-02-03 20:07:35 -0800395 break;
396 case DEC_TTL:
397 return factory.actions().decNwTtl();
398 case TTL_IN:
399 return factory.actions().copyTtlIn();
400 case TTL_OUT:
401 return factory.actions().copyTtlOut();
402 default:
403 log.warn("Unimplemented action type {}.", l3m.subtype());
404 break;
405 }
406
407 if (oxm != null) {
408 return factory.actions().buildSetField().setField(oxm).build();
409 }
410 return null;
411 }
412
413 private OFGroupType getOFGroupType(GroupDescription.Type groupType) {
414 switch (groupType) {
415 case INDIRECT:
416 return OFGroupType.INDIRECT;
417 case SELECT:
418 return OFGroupType.SELECT;
419 case FAILOVER:
420 return OFGroupType.FF;
421 case ALL:
422 return OFGroupType.ALL;
423 default:
424 log.error("Unsupported group type : {}", groupType);
425 break;
426 }
427 return null;
428 }
jiangruia6b46092015-11-11 16:28:51 +0800429
alshabib880b6442015-11-23 22:13:04 -0800430 private OFAction buildExtensionAction(ExtensionTreatment i, DeviceId deviceId) {
jiangruia6b46092015-11-11 16:28:51 +0800431 if (!driverService.isPresent()) {
432 log.error("No driver service present");
433 return null;
434 }
435 Driver driver = driverService.get().getDriver(deviceId);
alshabib880b6442015-11-23 22:13:04 -0800436 if (driver.hasBehaviour(ExtensionTreatmentInterpreter.class)) {
jiangruia6b46092015-11-11 16:28:51 +0800437 DefaultDriverHandler handler =
438 new DefaultDriverHandler(new DefaultDriverData(driver, deviceId));
alshabib880b6442015-11-23 22:13:04 -0800439 ExtensionTreatmentInterpreter interpreter = handler.behaviour(ExtensionTreatmentInterpreter.class);
jiangruia6b46092015-11-11 16:28:51 +0800440 return interpreter.mapInstruction(factory, i);
441 }
442
443 return null;
444 }
sangho5afd02a2015-02-03 20:07:35 -0800445}
446