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