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