blob: ce2df5fa3314de18ec537b413f2c4f10198dccad [file] [log] [blame]
sangho5afd02a2015-02-03 20:07:35 -08001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2015-present Open Networking Laboratory
sangho5afd02a2015-02-03 20:07:35 -08003 *
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 }
heisenbergd35113e2016-04-28 06:12:34 -0700197 if (type == GroupDescription.Type.FAILOVER && bucket.watchPort() != null) {
198 bucketBuilder.setWatchPort(OFPort.of((int) bucket.watchPort().toLong()));
199 } else {
200 bucketBuilder.setWatchPort(OFPort.ANY);
201 }
202 if (type == GroupDescription.Type.FAILOVER && bucket.watchGroup() != null) {
203 bucketBuilder.setWatchGroup(OFGroup.of(bucket.watchGroup().id()));
204 } else {
205 bucketBuilder.setWatchGroup(OFGroup.ANY);
206 }
207
sangho5afd02a2015-02-03 20:07:35 -0800208 OFBucket ofBucket = bucketBuilder.build();
209 ofBuckets.add(ofBucket);
210 }
211
212 OFGroupMod groupMsg = factory.buildGroupModify()
213 .setGroup(OFGroup.of(groupId.id()))
214 .setBuckets(ofBuckets)
215 .setGroupType(getOFGroupType(type))
216 .setXid(xid)
217 .build();
218
219 return groupMsg;
220 }
221
222 /**
223 * Builds the GroupDel OF message.
224 *
225 * @return GroupDel OF message
226 */
227 public OFGroupDelete buildGroupDel() {
228
229 OFGroupDelete groupMsg = factory.buildGroupDelete()
230 .setGroup(OFGroup.of(groupId.id()))
231 .setGroupType(OFGroupType.SELECT)
232 .setXid(xid)
233 .build();
234
235 return groupMsg;
236 }
237
238 private List<OFAction> buildActions(TrafficTreatment treatment) {
sangho5afd02a2015-02-03 20:07:35 -0800239 if (treatment == null) {
Sho SHIMIZUb35ed362015-04-28 11:05:19 -0700240 return Collections.emptyList();
sangho5afd02a2015-02-03 20:07:35 -0800241 }
Jonathan Hart54b406b2015-03-06 16:24:14 -0800242
Sho SHIMIZUb35ed362015-04-28 11:05:19 -0700243 List<OFAction> actions = new LinkedList<>();
Ray Milkey42507352015-03-20 15:16:10 -0700244 for (Instruction i : treatment.allInstructions()) {
sangho5afd02a2015-02-03 20:07:35 -0800245 switch (i.type()) {
sangho5afd02a2015-02-03 20:07:35 -0800246 case L0MODIFICATION:
247 actions.add(buildL0Modification(i));
248 break;
249 case L2MODIFICATION:
250 actions.add(buildL2Modification(i));
251 break;
252 case L3MODIFICATION:
253 actions.add(buildL3Modification(i));
254 break;
255 case OUTPUT:
256 Instructions.OutputInstruction out =
257 (Instructions.OutputInstruction) i;
258 OFActionOutput.Builder action = factory.actions().buildOutput()
259 .setPort(OFPort.of((int) out.port().toLong()));
260 if (out.port().equals(PortNumber.CONTROLLER)) {
261 action.setMaxLen(OFPCML_NO_BUFFER);
262 }
263 actions.add(action.build());
264 break;
265 case GROUP:
Saurav Das100e3b82015-04-30 11:12:10 -0700266 Instructions.GroupInstruction grp =
267 (Instructions.GroupInstruction) i;
268 OFActionGroup.Builder actgrp = factory.actions().buildGroup()
269 .setGroup(OFGroup.of(grp.groupId().id()));
270 actions.add(actgrp.build());
271 break;
jiangruia6b46092015-11-11 16:28:51 +0800272 case EXTENSION:
273 Instructions.ExtensionInstructionWrapper wrapper =
274 (Instructions.ExtensionInstructionWrapper) i;
275 actions.add(buildExtensionAction(
276 wrapper.extensionInstruction(), wrapper.deviceId()));
277 break;
sangho5afd02a2015-02-03 20:07:35 -0800278 default:
279 log.warn("Instruction type {} not yet implemented.", i.type());
280 }
281 }
282
283 return actions;
284 }
285
286 private OFAction buildL0Modification(Instruction i) {
287 L0ModificationInstruction l0m = (L0ModificationInstruction) i;
288 switch (l0m.subtype()) {
sangho5afd02a2015-02-03 20:07:35 -0800289 default:
290 log.warn("Unimplemented action type {}.", l0m.subtype());
291 break;
292 }
293 return null;
294 }
295
296 private OFAction buildL2Modification(Instruction i) {
297 L2ModificationInstruction l2m = (L2ModificationInstruction) i;
298 L2ModificationInstruction.ModEtherInstruction eth;
299 OFOxm<?> oxm = null;
300 switch (l2m.subtype()) {
301 case ETH_DST:
302 eth = (L2ModificationInstruction.ModEtherInstruction) l2m;
303 oxm = factory.oxms().ethDst(MacAddress.of(eth.mac().toLong()));
304 break;
305 case ETH_SRC:
306 eth = (L2ModificationInstruction.ModEtherInstruction) l2m;
307 oxm = factory.oxms().ethSrc(MacAddress.of(eth.mac().toLong()));
308 break;
309 case VLAN_ID:
310 L2ModificationInstruction.ModVlanIdInstruction vlanId =
311 (L2ModificationInstruction.ModVlanIdInstruction) l2m;
312 oxm = factory.oxms().vlanVid(OFVlanVidMatch.ofVlan(vlanId.vlanId().toShort()));
313 break;
314 case VLAN_PCP:
315 L2ModificationInstruction.ModVlanPcpInstruction vlanPcp =
316 (L2ModificationInstruction.ModVlanPcpInstruction) l2m;
317 oxm = factory.oxms().vlanPcp(VlanPcp.of(vlanPcp.vlanPcp()));
318 break;
Jonathan Hart54b406b2015-03-06 16:24:14 -0800319 case VLAN_POP:
320 return factory.actions().popVlan();
321 case VLAN_PUSH:
322 L2ModificationInstruction.PushHeaderInstructions pushVlanInstruction
323 = (L2ModificationInstruction.PushHeaderInstructions) l2m;
324 return factory.actions().pushVlan(
alshabib7b808c52015-06-26 14:22:24 -0700325 EthType.of(pushVlanInstruction.ethernetType().toShort()));
sangho5afd02a2015-02-03 20:07:35 -0800326 case MPLS_PUSH:
327 L2ModificationInstruction.PushHeaderInstructions pushHeaderInstructions =
328 (L2ModificationInstruction.PushHeaderInstructions) l2m;
329 return factory.actions().pushMpls(EthType.of(pushHeaderInstructions
alshabib7b808c52015-06-26 14:22:24 -0700330 .ethernetType().toShort()));
sangho5afd02a2015-02-03 20:07:35 -0800331 case MPLS_POP:
332 L2ModificationInstruction.PushHeaderInstructions popHeaderInstructions =
333 (L2ModificationInstruction.PushHeaderInstructions) l2m;
334 return factory.actions().popMpls(EthType.of(popHeaderInstructions
alshabib7b808c52015-06-26 14:22:24 -0700335 .ethernetType().toShort()));
sangho5afd02a2015-02-03 20:07:35 -0800336 case MPLS_LABEL:
337 L2ModificationInstruction.ModMplsLabelInstruction mplsLabel =
338 (L2ModificationInstruction.ModMplsLabelInstruction) l2m;
Ray Milkey125572b2016-02-22 16:48:17 -0800339 oxm = factory.oxms().mplsLabel(U32.of(mplsLabel.label().toInt()));
sangho5afd02a2015-02-03 20:07:35 -0800340 break;
Saurav Das73a7dd42015-08-19 22:20:31 -0700341 case MPLS_BOS:
342 L2ModificationInstruction.ModMplsBosInstruction mplsBos =
343 (L2ModificationInstruction.ModMplsBosInstruction) l2m;
344 oxm = factory.oxms()
345 .mplsBos(mplsBos.mplsBos() ? OFBooleanValue.TRUE
346 : OFBooleanValue.FALSE);
347 break;
sangho5afd02a2015-02-03 20:07:35 -0800348 case DEC_MPLS_TTL:
349 return factory.actions().decMplsTtl();
Hyunsun Moon9ae22e92015-12-15 20:34:51 -0800350 case TUNNEL_ID:
351 L2ModificationInstruction.ModTunnelIdInstruction tunnelId =
352 (L2ModificationInstruction.ModTunnelIdInstruction) l2m;
353 oxm = factory.oxms().tunnelId(U64.of(tunnelId.tunnelId()));
354 break;
sangho5afd02a2015-02-03 20:07:35 -0800355 default:
356 log.warn("Unimplemented action type {}.", l2m.subtype());
357 break;
358 }
359
360 if (oxm != null) {
361 return factory.actions().buildSetField().setField(oxm).build();
362 }
363 return null;
364 }
365
366 private OFAction buildL3Modification(Instruction i) {
367 L3ModificationInstruction l3m = (L3ModificationInstruction) i;
368 L3ModificationInstruction.ModIPInstruction ip;
369 Ip4Address ip4;
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800370 Ip6Address ip6;
sangho5afd02a2015-02-03 20:07:35 -0800371 OFOxm<?> oxm = null;
372 switch (l3m.subtype()) {
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800373 case IPV4_SRC:
374 ip = (L3ModificationInstruction.ModIPInstruction) i;
375 ip4 = ip.ip().getIp4Address();
376 oxm = factory.oxms().ipv4Src(IPv4Address.of(ip4.toInt()));
377 break;
378 case IPV4_DST:
sangho5afd02a2015-02-03 20:07:35 -0800379 ip = (L3ModificationInstruction.ModIPInstruction) i;
380 ip4 = ip.ip().getIp4Address();
381 oxm = factory.oxms().ipv4Dst(IPv4Address.of(ip4.toInt()));
382 break;
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800383 case IPV6_SRC:
sangho5afd02a2015-02-03 20:07:35 -0800384 ip = (L3ModificationInstruction.ModIPInstruction) i;
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800385 ip6 = ip.ip().getIp6Address();
386 oxm = factory.oxms().ipv6Src(IPv6Address.of(ip6.toOctets()));
387 break;
388 case IPV6_DST:
389 ip = (L3ModificationInstruction.ModIPInstruction) i;
390 ip6 = ip.ip().getIp6Address();
391 oxm = factory.oxms().ipv6Dst(IPv6Address.of(ip6.toOctets()));
392 break;
393 case IPV6_FLABEL:
394 L3ModificationInstruction.ModIPv6FlowLabelInstruction flowLabelInstruction =
395 (L3ModificationInstruction.ModIPv6FlowLabelInstruction) i;
396 int flowLabel = flowLabelInstruction.flowLabel();
397 oxm = factory.oxms().ipv6Flabel(IPv6FlowLabel.of(flowLabel));
sangho5afd02a2015-02-03 20:07:35 -0800398 break;
399 case DEC_TTL:
400 return factory.actions().decNwTtl();
401 case TTL_IN:
402 return factory.actions().copyTtlIn();
403 case TTL_OUT:
404 return factory.actions().copyTtlOut();
405 default:
406 log.warn("Unimplemented action type {}.", l3m.subtype());
407 break;
408 }
409
410 if (oxm != null) {
411 return factory.actions().buildSetField().setField(oxm).build();
412 }
413 return null;
414 }
415
416 private OFGroupType getOFGroupType(GroupDescription.Type groupType) {
417 switch (groupType) {
418 case INDIRECT:
419 return OFGroupType.INDIRECT;
420 case SELECT:
421 return OFGroupType.SELECT;
422 case FAILOVER:
423 return OFGroupType.FF;
424 case ALL:
425 return OFGroupType.ALL;
426 default:
427 log.error("Unsupported group type : {}", groupType);
428 break;
429 }
430 return null;
431 }
jiangruia6b46092015-11-11 16:28:51 +0800432
alshabib880b6442015-11-23 22:13:04 -0800433 private OFAction buildExtensionAction(ExtensionTreatment i, DeviceId deviceId) {
jiangruia6b46092015-11-11 16:28:51 +0800434 if (!driverService.isPresent()) {
435 log.error("No driver service present");
436 return null;
437 }
438 Driver driver = driverService.get().getDriver(deviceId);
alshabib880b6442015-11-23 22:13:04 -0800439 if (driver.hasBehaviour(ExtensionTreatmentInterpreter.class)) {
jiangruia6b46092015-11-11 16:28:51 +0800440 DefaultDriverHandler handler =
441 new DefaultDriverHandler(new DefaultDriverData(driver, deviceId));
alshabib880b6442015-11-23 22:13:04 -0800442 ExtensionTreatmentInterpreter interpreter = handler.behaviour(ExtensionTreatmentInterpreter.class);
jiangruia6b46092015-11-11 16:28:51 +0800443 return interpreter.mapInstruction(factory, i);
444 }
445
446 return null;
447 }
sangho5afd02a2015-02-03 20:07:35 -0800448}
449