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