blob: 847bb2dde4bfb0e88348fc0445317b20028ca86d [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;
sangho5afd02a2015-02-03 20:07:35 -080056import org.projectfloodlight.openflow.types.EthType;
57import org.projectfloodlight.openflow.types.IPv4Address;
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -080058import org.projectfloodlight.openflow.types.IPv6Address;
59import org.projectfloodlight.openflow.types.IPv6FlowLabel;
sangho5afd02a2015-02-03 20:07:35 -080060import org.projectfloodlight.openflow.types.MacAddress;
Saurav Das73a7dd42015-08-19 22:20:31 -070061import org.projectfloodlight.openflow.types.OFBooleanValue;
sangho5afd02a2015-02-03 20:07:35 -080062import org.projectfloodlight.openflow.types.OFGroup;
63import org.projectfloodlight.openflow.types.OFPort;
64import org.projectfloodlight.openflow.types.OFVlanVidMatch;
65import org.projectfloodlight.openflow.types.U32;
Hyunsun Moon9ae22e92015-12-15 20:34:51 -080066import org.projectfloodlight.openflow.types.U64;
sangho5afd02a2015-02-03 20:07:35 -080067import 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 }
AdrianAlan0be87242015-11-15 18:43:29 +0100157
158 if (type == GroupDescription.Type.FAILOVER && bucket.watchPort() != null) {
159 bucketBuilder.setWatchPort(OFPort.of((int) bucket.watchPort().toLong()));
160 } else {
161 bucketBuilder.setWatchPort(OFPort.ANY);
162 }
163 if (type == GroupDescription.Type.FAILOVER && bucket.watchGroup() != null) {
164 bucketBuilder.setWatchGroup(OFGroup.of(bucket.watchGroup().id()));
165 } else {
166 bucketBuilder.setWatchGroup(OFGroup.ANY);
167 }
sangho5afd02a2015-02-03 20:07:35 -0800168 OFBucket ofBucket = bucketBuilder.build();
169 ofBuckets.add(ofBucket);
170 }
171
172 OFGroupAdd groupMsg = factory.buildGroupAdd()
173 .setGroup(OFGroup.of(groupId.id()))
174 .setBuckets(ofBuckets)
175 .setGroupType(getOFGroupType(type))
176 .setXid(xid)
177 .build();
178
179 return groupMsg;
180 }
181
182 /**
183 * Builds the GroupMod OF message.
184 *
185 * @return GroupMod OF message
186 */
187 public OFGroupMod buildGroupMod() {
188 List<OFBucket> ofBuckets = new ArrayList<OFBucket>();
189 for (GroupBucket bucket: buckets.buckets()) {
190 List<OFAction> actions = buildActions(bucket.treatment());
191
192 OFBucket.Builder bucketBuilder = factory.buildBucket();
193 bucketBuilder.setActions(actions);
194 if (type == GroupDescription.Type.SELECT) {
195 bucketBuilder.setWeight(1);
196 }
197 bucketBuilder.setWatchGroup(OFGroup.ANY);
198 bucketBuilder.setWatchPort(OFPort.ANY);
199 OFBucket ofBucket = bucketBuilder.build();
200 ofBuckets.add(ofBucket);
201 }
202
203 OFGroupMod groupMsg = factory.buildGroupModify()
204 .setGroup(OFGroup.of(groupId.id()))
205 .setBuckets(ofBuckets)
206 .setGroupType(getOFGroupType(type))
207 .setXid(xid)
208 .build();
209
210 return groupMsg;
211 }
212
213 /**
214 * Builds the GroupDel OF message.
215 *
216 * @return GroupDel OF message
217 */
218 public OFGroupDelete buildGroupDel() {
219
220 OFGroupDelete groupMsg = factory.buildGroupDelete()
221 .setGroup(OFGroup.of(groupId.id()))
222 .setGroupType(OFGroupType.SELECT)
223 .setXid(xid)
224 .build();
225
226 return groupMsg;
227 }
228
229 private List<OFAction> buildActions(TrafficTreatment treatment) {
sangho5afd02a2015-02-03 20:07:35 -0800230 if (treatment == null) {
Sho SHIMIZUb35ed362015-04-28 11:05:19 -0700231 return Collections.emptyList();
sangho5afd02a2015-02-03 20:07:35 -0800232 }
Jonathan Hart54b406b2015-03-06 16:24:14 -0800233
Sho SHIMIZUb35ed362015-04-28 11:05:19 -0700234 List<OFAction> actions = new LinkedList<>();
Ray Milkey42507352015-03-20 15:16:10 -0700235 for (Instruction i : treatment.allInstructions()) {
sangho5afd02a2015-02-03 20:07:35 -0800236 switch (i.type()) {
sangho5afd02a2015-02-03 20:07:35 -0800237 case L0MODIFICATION:
238 actions.add(buildL0Modification(i));
239 break;
240 case L2MODIFICATION:
241 actions.add(buildL2Modification(i));
242 break;
243 case L3MODIFICATION:
244 actions.add(buildL3Modification(i));
245 break;
246 case OUTPUT:
247 Instructions.OutputInstruction out =
248 (Instructions.OutputInstruction) i;
249 OFActionOutput.Builder action = factory.actions().buildOutput()
250 .setPort(OFPort.of((int) out.port().toLong()));
251 if (out.port().equals(PortNumber.CONTROLLER)) {
252 action.setMaxLen(OFPCML_NO_BUFFER);
253 }
254 actions.add(action.build());
255 break;
256 case GROUP:
Saurav Das100e3b82015-04-30 11:12:10 -0700257 Instructions.GroupInstruction grp =
258 (Instructions.GroupInstruction) i;
259 OFActionGroup.Builder actgrp = factory.actions().buildGroup()
260 .setGroup(OFGroup.of(grp.groupId().id()));
261 actions.add(actgrp.build());
262 break;
jiangruia6b46092015-11-11 16:28:51 +0800263 case EXTENSION:
264 Instructions.ExtensionInstructionWrapper wrapper =
265 (Instructions.ExtensionInstructionWrapper) i;
266 actions.add(buildExtensionAction(
267 wrapper.extensionInstruction(), wrapper.deviceId()));
268 break;
sangho5afd02a2015-02-03 20:07:35 -0800269 default:
270 log.warn("Instruction type {} not yet implemented.", i.type());
271 }
272 }
273
274 return actions;
275 }
276
277 private OFAction buildL0Modification(Instruction i) {
278 L0ModificationInstruction l0m = (L0ModificationInstruction) i;
279 switch (l0m.subtype()) {
sangho5afd02a2015-02-03 20:07:35 -0800280 default:
281 log.warn("Unimplemented action type {}.", l0m.subtype());
282 break;
283 }
284 return null;
285 }
286
287 private OFAction buildL2Modification(Instruction i) {
288 L2ModificationInstruction l2m = (L2ModificationInstruction) i;
289 L2ModificationInstruction.ModEtherInstruction eth;
290 OFOxm<?> oxm = null;
291 switch (l2m.subtype()) {
292 case ETH_DST:
293 eth = (L2ModificationInstruction.ModEtherInstruction) l2m;
294 oxm = factory.oxms().ethDst(MacAddress.of(eth.mac().toLong()));
295 break;
296 case ETH_SRC:
297 eth = (L2ModificationInstruction.ModEtherInstruction) l2m;
298 oxm = factory.oxms().ethSrc(MacAddress.of(eth.mac().toLong()));
299 break;
300 case VLAN_ID:
301 L2ModificationInstruction.ModVlanIdInstruction vlanId =
302 (L2ModificationInstruction.ModVlanIdInstruction) l2m;
303 oxm = factory.oxms().vlanVid(OFVlanVidMatch.ofVlan(vlanId.vlanId().toShort()));
304 break;
305 case VLAN_PCP:
306 L2ModificationInstruction.ModVlanPcpInstruction vlanPcp =
307 (L2ModificationInstruction.ModVlanPcpInstruction) l2m;
308 oxm = factory.oxms().vlanPcp(VlanPcp.of(vlanPcp.vlanPcp()));
309 break;
Jonathan Hart54b406b2015-03-06 16:24:14 -0800310 case VLAN_POP:
311 return factory.actions().popVlan();
312 case VLAN_PUSH:
313 L2ModificationInstruction.PushHeaderInstructions pushVlanInstruction
314 = (L2ModificationInstruction.PushHeaderInstructions) l2m;
315 return factory.actions().pushVlan(
alshabib7b808c52015-06-26 14:22:24 -0700316 EthType.of(pushVlanInstruction.ethernetType().toShort()));
sangho5afd02a2015-02-03 20:07:35 -0800317 case MPLS_PUSH:
318 L2ModificationInstruction.PushHeaderInstructions pushHeaderInstructions =
319 (L2ModificationInstruction.PushHeaderInstructions) l2m;
320 return factory.actions().pushMpls(EthType.of(pushHeaderInstructions
alshabib7b808c52015-06-26 14:22:24 -0700321 .ethernetType().toShort()));
sangho5afd02a2015-02-03 20:07:35 -0800322 case MPLS_POP:
323 L2ModificationInstruction.PushHeaderInstructions popHeaderInstructions =
324 (L2ModificationInstruction.PushHeaderInstructions) l2m;
325 return factory.actions().popMpls(EthType.of(popHeaderInstructions
alshabib7b808c52015-06-26 14:22:24 -0700326 .ethernetType().toShort()));
sangho5afd02a2015-02-03 20:07:35 -0800327 case MPLS_LABEL:
328 L2ModificationInstruction.ModMplsLabelInstruction mplsLabel =
329 (L2ModificationInstruction.ModMplsLabelInstruction) l2m;
Ray Milkey125572b2016-02-22 16:48:17 -0800330 oxm = factory.oxms().mplsLabel(U32.of(mplsLabel.label().toInt()));
sangho5afd02a2015-02-03 20:07:35 -0800331 break;
Saurav Das73a7dd42015-08-19 22:20:31 -0700332 case MPLS_BOS:
333 L2ModificationInstruction.ModMplsBosInstruction mplsBos =
334 (L2ModificationInstruction.ModMplsBosInstruction) l2m;
335 oxm = factory.oxms()
336 .mplsBos(mplsBos.mplsBos() ? OFBooleanValue.TRUE
337 : OFBooleanValue.FALSE);
338 break;
sangho5afd02a2015-02-03 20:07:35 -0800339 case DEC_MPLS_TTL:
340 return factory.actions().decMplsTtl();
Hyunsun Moon9ae22e92015-12-15 20:34:51 -0800341 case TUNNEL_ID:
342 L2ModificationInstruction.ModTunnelIdInstruction tunnelId =
343 (L2ModificationInstruction.ModTunnelIdInstruction) l2m;
344 oxm = factory.oxms().tunnelId(U64.of(tunnelId.tunnelId()));
345 break;
sangho5afd02a2015-02-03 20:07:35 -0800346 default:
347 log.warn("Unimplemented action type {}.", l2m.subtype());
348 break;
349 }
350
351 if (oxm != null) {
352 return factory.actions().buildSetField().setField(oxm).build();
353 }
354 return null;
355 }
356
357 private OFAction buildL3Modification(Instruction i) {
358 L3ModificationInstruction l3m = (L3ModificationInstruction) i;
359 L3ModificationInstruction.ModIPInstruction ip;
360 Ip4Address ip4;
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800361 Ip6Address ip6;
sangho5afd02a2015-02-03 20:07:35 -0800362 OFOxm<?> oxm = null;
363 switch (l3m.subtype()) {
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800364 case IPV4_SRC:
365 ip = (L3ModificationInstruction.ModIPInstruction) i;
366 ip4 = ip.ip().getIp4Address();
367 oxm = factory.oxms().ipv4Src(IPv4Address.of(ip4.toInt()));
368 break;
369 case IPV4_DST:
sangho5afd02a2015-02-03 20:07:35 -0800370 ip = (L3ModificationInstruction.ModIPInstruction) i;
371 ip4 = ip.ip().getIp4Address();
372 oxm = factory.oxms().ipv4Dst(IPv4Address.of(ip4.toInt()));
373 break;
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800374 case IPV6_SRC:
sangho5afd02a2015-02-03 20:07:35 -0800375 ip = (L3ModificationInstruction.ModIPInstruction) i;
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800376 ip6 = ip.ip().getIp6Address();
377 oxm = factory.oxms().ipv6Src(IPv6Address.of(ip6.toOctets()));
378 break;
379 case IPV6_DST:
380 ip = (L3ModificationInstruction.ModIPInstruction) i;
381 ip6 = ip.ip().getIp6Address();
382 oxm = factory.oxms().ipv6Dst(IPv6Address.of(ip6.toOctets()));
383 break;
384 case IPV6_FLABEL:
385 L3ModificationInstruction.ModIPv6FlowLabelInstruction flowLabelInstruction =
386 (L3ModificationInstruction.ModIPv6FlowLabelInstruction) i;
387 int flowLabel = flowLabelInstruction.flowLabel();
388 oxm = factory.oxms().ipv6Flabel(IPv6FlowLabel.of(flowLabel));
sangho5afd02a2015-02-03 20:07:35 -0800389 break;
390 case DEC_TTL:
391 return factory.actions().decNwTtl();
392 case TTL_IN:
393 return factory.actions().copyTtlIn();
394 case TTL_OUT:
395 return factory.actions().copyTtlOut();
396 default:
397 log.warn("Unimplemented action type {}.", l3m.subtype());
398 break;
399 }
400
401 if (oxm != null) {
402 return factory.actions().buildSetField().setField(oxm).build();
403 }
404 return null;
405 }
406
407 private OFGroupType getOFGroupType(GroupDescription.Type groupType) {
408 switch (groupType) {
409 case INDIRECT:
410 return OFGroupType.INDIRECT;
411 case SELECT:
412 return OFGroupType.SELECT;
413 case FAILOVER:
414 return OFGroupType.FF;
415 case ALL:
416 return OFGroupType.ALL;
417 default:
418 log.error("Unsupported group type : {}", groupType);
419 break;
420 }
421 return null;
422 }
jiangruia6b46092015-11-11 16:28:51 +0800423
alshabib880b6442015-11-23 22:13:04 -0800424 private OFAction buildExtensionAction(ExtensionTreatment i, DeviceId deviceId) {
jiangruia6b46092015-11-11 16:28:51 +0800425 if (!driverService.isPresent()) {
426 log.error("No driver service present");
427 return null;
428 }
429 Driver driver = driverService.get().getDriver(deviceId);
alshabib880b6442015-11-23 22:13:04 -0800430 if (driver.hasBehaviour(ExtensionTreatmentInterpreter.class)) {
jiangruia6b46092015-11-11 16:28:51 +0800431 DefaultDriverHandler handler =
432 new DefaultDriverHandler(new DefaultDriverData(driver, deviceId));
alshabib880b6442015-11-23 22:13:04 -0800433 ExtensionTreatmentInterpreter interpreter = handler.behaviour(ExtensionTreatmentInterpreter.class);
jiangruia6b46092015-11-11 16:28:51 +0800434 return interpreter.mapInstruction(factory, i);
435 }
436
437 return null;
438 }
sangho5afd02a2015-02-03 20:07:35 -0800439}
440