blob: 40be64323d1fb5adcf3ec1a79288a969ac0fb78c [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
18import org.onlab.packet.Ip4Address;
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -080019import org.onlab.packet.Ip6Address;
sangho5afd02a2015-02-03 20:07:35 -080020import org.onosproject.core.GroupId;
21import org.onosproject.net.PortNumber;
22import org.onosproject.net.flow.TrafficTreatment;
23import org.onosproject.net.flow.instructions.Instruction;
24import org.onosproject.net.flow.instructions.Instructions;
25import org.onosproject.net.flow.instructions.L0ModificationInstruction;
26import org.onosproject.net.flow.instructions.L2ModificationInstruction;
27import org.onosproject.net.flow.instructions.L3ModificationInstruction;
28import org.onosproject.net.group.GroupBucket;
29import org.onosproject.net.group.GroupBuckets;
30import org.onosproject.net.group.GroupDescription;
31import org.projectfloodlight.openflow.protocol.OFBucket;
32import org.projectfloodlight.openflow.protocol.OFFactory;
33import org.projectfloodlight.openflow.protocol.OFGroupAdd;
34import org.projectfloodlight.openflow.protocol.OFGroupDelete;
35import org.projectfloodlight.openflow.protocol.OFGroupMod;
36import org.projectfloodlight.openflow.protocol.OFGroupType;
37import org.projectfloodlight.openflow.protocol.action.OFAction;
Saurav Das100e3b82015-04-30 11:12:10 -070038import org.projectfloodlight.openflow.protocol.action.OFActionGroup;
sangho5afd02a2015-02-03 20:07:35 -080039import org.projectfloodlight.openflow.protocol.action.OFActionOutput;
40import org.projectfloodlight.openflow.protocol.oxm.OFOxm;
41import org.projectfloodlight.openflow.types.CircuitSignalID;
42import org.projectfloodlight.openflow.types.EthType;
43import org.projectfloodlight.openflow.types.IPv4Address;
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -080044import org.projectfloodlight.openflow.types.IPv6Address;
45import org.projectfloodlight.openflow.types.IPv6FlowLabel;
sangho5afd02a2015-02-03 20:07:35 -080046import org.projectfloodlight.openflow.types.MacAddress;
47import org.projectfloodlight.openflow.types.OFGroup;
48import org.projectfloodlight.openflow.types.OFPort;
49import org.projectfloodlight.openflow.types.OFVlanVidMatch;
50import org.projectfloodlight.openflow.types.U32;
51import org.projectfloodlight.openflow.types.VlanPcp;
52import org.slf4j.Logger;
53
54import java.util.ArrayList;
Sho SHIMIZUb35ed362015-04-28 11:05:19 -070055import java.util.Collections;
sangho5afd02a2015-02-03 20:07:35 -080056import java.util.LinkedList;
57import java.util.List;
58import java.util.Optional;
59
60import static org.slf4j.LoggerFactory.getLogger;
61
62/*
63 * Builder for GroupMod.
64 */
65public final class GroupModBuilder {
66
67 private GroupBuckets buckets;
68 private GroupId groupId;
69 private GroupDescription.Type type;
70 private OFFactory factory;
71 private Long xid;
72
73 private final Logger log = getLogger(getClass());
74
75 private static final int OFPCML_NO_BUFFER = 0xffff;
76
77 private GroupModBuilder(GroupBuckets buckets, GroupId groupId,
78 GroupDescription.Type type, OFFactory factory,
79 Optional<Long> xid) {
80 this.buckets = buckets;
81 this.groupId = groupId;
82 this.type = type;
83 this.factory = factory;
84 this.xid = xid.orElse((long) 0);
85 }
86
87 /**
88 * Creates a builder for GroupMod.
89 *
90 * @param buckets GroupBuckets object
91 * @param groupId Group Id to create
92 * @param type Group type
93 * @param factory OFFactory object
94 * @param xid transaction ID
95 * @return GroupModBuilder object
96 */
97 public static GroupModBuilder builder(GroupBuckets buckets, GroupId groupId,
98 GroupDescription.Type type, OFFactory factory,
99 Optional<Long> xid) {
100
101 return new GroupModBuilder(buckets, groupId, type, factory, xid);
102 }
103
104 /**
105 * Builds the GroupAdd OF message.
106 *
107 * @return GroupAdd OF message
108 */
109 public OFGroupAdd buildGroupAdd() {
110
111 List<OFBucket> ofBuckets = new ArrayList<OFBucket>();
112 for (GroupBucket bucket: buckets.buckets()) {
113 List<OFAction> actions = buildActions(bucket.treatment());
114
115 OFBucket.Builder bucketBuilder = factory.buildBucket();
116 bucketBuilder.setActions(actions);
117 if (type == GroupDescription.Type.SELECT) {
118 bucketBuilder.setWeight(1);
119 }
120 bucketBuilder.setWatchGroup(OFGroup.ANY);
121 bucketBuilder.setWatchPort(OFPort.ANY);
122 OFBucket ofBucket = bucketBuilder.build();
123 ofBuckets.add(ofBucket);
124 }
125
126 OFGroupAdd groupMsg = factory.buildGroupAdd()
127 .setGroup(OFGroup.of(groupId.id()))
128 .setBuckets(ofBuckets)
129 .setGroupType(getOFGroupType(type))
130 .setXid(xid)
131 .build();
132
133 return groupMsg;
134 }
135
136 /**
137 * Builds the GroupMod OF message.
138 *
139 * @return GroupMod OF message
140 */
141 public OFGroupMod buildGroupMod() {
142 List<OFBucket> ofBuckets = new ArrayList<OFBucket>();
143 for (GroupBucket bucket: buckets.buckets()) {
144 List<OFAction> actions = buildActions(bucket.treatment());
145
146 OFBucket.Builder bucketBuilder = factory.buildBucket();
147 bucketBuilder.setActions(actions);
148 if (type == GroupDescription.Type.SELECT) {
149 bucketBuilder.setWeight(1);
150 }
151 bucketBuilder.setWatchGroup(OFGroup.ANY);
152 bucketBuilder.setWatchPort(OFPort.ANY);
153 OFBucket ofBucket = bucketBuilder.build();
154 ofBuckets.add(ofBucket);
155 }
156
157 OFGroupMod groupMsg = factory.buildGroupModify()
158 .setGroup(OFGroup.of(groupId.id()))
159 .setBuckets(ofBuckets)
160 .setGroupType(getOFGroupType(type))
161 .setXid(xid)
162 .build();
163
164 return groupMsg;
165 }
166
167 /**
168 * Builds the GroupDel OF message.
169 *
170 * @return GroupDel OF message
171 */
172 public OFGroupDelete buildGroupDel() {
173
174 OFGroupDelete groupMsg = factory.buildGroupDelete()
175 .setGroup(OFGroup.of(groupId.id()))
176 .setGroupType(OFGroupType.SELECT)
177 .setXid(xid)
178 .build();
179
180 return groupMsg;
181 }
182
183 private List<OFAction> buildActions(TrafficTreatment treatment) {
sangho5afd02a2015-02-03 20:07:35 -0800184 if (treatment == null) {
Sho SHIMIZUb35ed362015-04-28 11:05:19 -0700185 return Collections.emptyList();
sangho5afd02a2015-02-03 20:07:35 -0800186 }
Jonathan Hart54b406b2015-03-06 16:24:14 -0800187
Sho SHIMIZUb35ed362015-04-28 11:05:19 -0700188 List<OFAction> actions = new LinkedList<>();
Ray Milkey42507352015-03-20 15:16:10 -0700189 for (Instruction i : treatment.allInstructions()) {
sangho5afd02a2015-02-03 20:07:35 -0800190 switch (i.type()) {
191 case DROP:
192 log.warn("Saw drop action; assigning drop action");
Sho SHIMIZUb35ed362015-04-28 11:05:19 -0700193 return Collections.emptyList();
sangho5afd02a2015-02-03 20:07:35 -0800194 case L0MODIFICATION:
195 actions.add(buildL0Modification(i));
196 break;
197 case L2MODIFICATION:
198 actions.add(buildL2Modification(i));
199 break;
200 case L3MODIFICATION:
201 actions.add(buildL3Modification(i));
202 break;
203 case OUTPUT:
204 Instructions.OutputInstruction out =
205 (Instructions.OutputInstruction) i;
206 OFActionOutput.Builder action = factory.actions().buildOutput()
207 .setPort(OFPort.of((int) out.port().toLong()));
208 if (out.port().equals(PortNumber.CONTROLLER)) {
209 action.setMaxLen(OFPCML_NO_BUFFER);
210 }
211 actions.add(action.build());
212 break;
213 case GROUP:
Saurav Das100e3b82015-04-30 11:12:10 -0700214 Instructions.GroupInstruction grp =
215 (Instructions.GroupInstruction) i;
216 OFActionGroup.Builder actgrp = factory.actions().buildGroup()
217 .setGroup(OFGroup.of(grp.groupId().id()));
218 actions.add(actgrp.build());
219 break;
sangho5afd02a2015-02-03 20:07:35 -0800220 default:
221 log.warn("Instruction type {} not yet implemented.", i.type());
222 }
223 }
224
225 return actions;
226 }
227
228 private OFAction buildL0Modification(Instruction i) {
229 L0ModificationInstruction l0m = (L0ModificationInstruction) i;
230 switch (l0m.subtype()) {
231 case LAMBDA:
232 L0ModificationInstruction.ModLambdaInstruction ml =
233 (L0ModificationInstruction.ModLambdaInstruction) i;
234 return factory.actions().circuit(factory.oxms().ochSigidBasic(
235 new CircuitSignalID((byte) 1, (byte) 2, ml.lambda(), (short) 1)));
236 default:
237 log.warn("Unimplemented action type {}.", l0m.subtype());
238 break;
239 }
240 return null;
241 }
242
243 private OFAction buildL2Modification(Instruction i) {
244 L2ModificationInstruction l2m = (L2ModificationInstruction) i;
245 L2ModificationInstruction.ModEtherInstruction eth;
246 OFOxm<?> oxm = null;
247 switch (l2m.subtype()) {
248 case ETH_DST:
249 eth = (L2ModificationInstruction.ModEtherInstruction) l2m;
250 oxm = factory.oxms().ethDst(MacAddress.of(eth.mac().toLong()));
251 break;
252 case ETH_SRC:
253 eth = (L2ModificationInstruction.ModEtherInstruction) l2m;
254 oxm = factory.oxms().ethSrc(MacAddress.of(eth.mac().toLong()));
255 break;
256 case VLAN_ID:
257 L2ModificationInstruction.ModVlanIdInstruction vlanId =
258 (L2ModificationInstruction.ModVlanIdInstruction) l2m;
259 oxm = factory.oxms().vlanVid(OFVlanVidMatch.ofVlan(vlanId.vlanId().toShort()));
260 break;
261 case VLAN_PCP:
262 L2ModificationInstruction.ModVlanPcpInstruction vlanPcp =
263 (L2ModificationInstruction.ModVlanPcpInstruction) l2m;
264 oxm = factory.oxms().vlanPcp(VlanPcp.of(vlanPcp.vlanPcp()));
265 break;
Jonathan Hart54b406b2015-03-06 16:24:14 -0800266 case VLAN_POP:
267 return factory.actions().popVlan();
268 case VLAN_PUSH:
269 L2ModificationInstruction.PushHeaderInstructions pushVlanInstruction
270 = (L2ModificationInstruction.PushHeaderInstructions) l2m;
271 return factory.actions().pushVlan(
272 EthType.of(pushVlanInstruction.ethernetType()));
sangho5afd02a2015-02-03 20:07:35 -0800273 case MPLS_PUSH:
274 L2ModificationInstruction.PushHeaderInstructions pushHeaderInstructions =
275 (L2ModificationInstruction.PushHeaderInstructions) l2m;
276 return factory.actions().pushMpls(EthType.of(pushHeaderInstructions
Yuta HIGUCHI32a53c52015-02-08 01:25:40 -0800277 .ethernetType()));
sangho5afd02a2015-02-03 20:07:35 -0800278 case MPLS_POP:
279 L2ModificationInstruction.PushHeaderInstructions popHeaderInstructions =
280 (L2ModificationInstruction.PushHeaderInstructions) l2m;
281 return factory.actions().popMpls(EthType.of(popHeaderInstructions
Yuta HIGUCHI32a53c52015-02-08 01:25:40 -0800282 .ethernetType()));
sangho5afd02a2015-02-03 20:07:35 -0800283 case MPLS_LABEL:
284 L2ModificationInstruction.ModMplsLabelInstruction mplsLabel =
285 (L2ModificationInstruction.ModMplsLabelInstruction) l2m;
286 oxm = factory.oxms().mplsLabel(U32.of(mplsLabel.label()
287 .longValue()));
288 break;
289 case DEC_MPLS_TTL:
290 return factory.actions().decMplsTtl();
291 default:
292 log.warn("Unimplemented action type {}.", l2m.subtype());
293 break;
294 }
295
296 if (oxm != null) {
297 return factory.actions().buildSetField().setField(oxm).build();
298 }
299 return null;
300 }
301
302 private OFAction buildL3Modification(Instruction i) {
303 L3ModificationInstruction l3m = (L3ModificationInstruction) i;
304 L3ModificationInstruction.ModIPInstruction ip;
305 Ip4Address ip4;
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800306 Ip6Address ip6;
sangho5afd02a2015-02-03 20:07:35 -0800307 OFOxm<?> oxm = null;
308 switch (l3m.subtype()) {
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800309 case IPV4_SRC:
310 ip = (L3ModificationInstruction.ModIPInstruction) i;
311 ip4 = ip.ip().getIp4Address();
312 oxm = factory.oxms().ipv4Src(IPv4Address.of(ip4.toInt()));
313 break;
314 case IPV4_DST:
sangho5afd02a2015-02-03 20:07:35 -0800315 ip = (L3ModificationInstruction.ModIPInstruction) i;
316 ip4 = ip.ip().getIp4Address();
317 oxm = factory.oxms().ipv4Dst(IPv4Address.of(ip4.toInt()));
318 break;
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800319 case IPV6_SRC:
sangho5afd02a2015-02-03 20:07:35 -0800320 ip = (L3ModificationInstruction.ModIPInstruction) i;
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800321 ip6 = ip.ip().getIp6Address();
322 oxm = factory.oxms().ipv6Src(IPv6Address.of(ip6.toOctets()));
323 break;
324 case IPV6_DST:
325 ip = (L3ModificationInstruction.ModIPInstruction) i;
326 ip6 = ip.ip().getIp6Address();
327 oxm = factory.oxms().ipv6Dst(IPv6Address.of(ip6.toOctets()));
328 break;
329 case IPV6_FLABEL:
330 L3ModificationInstruction.ModIPv6FlowLabelInstruction flowLabelInstruction =
331 (L3ModificationInstruction.ModIPv6FlowLabelInstruction) i;
332 int flowLabel = flowLabelInstruction.flowLabel();
333 oxm = factory.oxms().ipv6Flabel(IPv6FlowLabel.of(flowLabel));
sangho5afd02a2015-02-03 20:07:35 -0800334 break;
335 case DEC_TTL:
336 return factory.actions().decNwTtl();
337 case TTL_IN:
338 return factory.actions().copyTtlIn();
339 case TTL_OUT:
340 return factory.actions().copyTtlOut();
341 default:
342 log.warn("Unimplemented action type {}.", l3m.subtype());
343 break;
344 }
345
346 if (oxm != null) {
347 return factory.actions().buildSetField().setField(oxm).build();
348 }
349 return null;
350 }
351
352 private OFGroupType getOFGroupType(GroupDescription.Type groupType) {
353 switch (groupType) {
354 case INDIRECT:
355 return OFGroupType.INDIRECT;
356 case SELECT:
357 return OFGroupType.SELECT;
358 case FAILOVER:
359 return OFGroupType.FF;
360 case ALL:
361 return OFGroupType.ALL;
362 default:
363 log.error("Unsupported group type : {}", groupType);
364 break;
365 }
366 return null;
367 }
368}
369