blob: 191372c06af843dcd18aa1a2961aa7aaea54f67d [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;
19import org.onosproject.core.GroupId;
20import org.onosproject.net.PortNumber;
21import org.onosproject.net.flow.TrafficTreatment;
22import org.onosproject.net.flow.instructions.Instruction;
23import org.onosproject.net.flow.instructions.Instructions;
24import org.onosproject.net.flow.instructions.L0ModificationInstruction;
25import org.onosproject.net.flow.instructions.L2ModificationInstruction;
26import org.onosproject.net.flow.instructions.L3ModificationInstruction;
27import org.onosproject.net.group.GroupBucket;
28import org.onosproject.net.group.GroupBuckets;
29import org.onosproject.net.group.GroupDescription;
30import org.projectfloodlight.openflow.protocol.OFBucket;
31import org.projectfloodlight.openflow.protocol.OFFactory;
32import org.projectfloodlight.openflow.protocol.OFGroupAdd;
33import org.projectfloodlight.openflow.protocol.OFGroupDelete;
34import org.projectfloodlight.openflow.protocol.OFGroupMod;
35import org.projectfloodlight.openflow.protocol.OFGroupType;
36import org.projectfloodlight.openflow.protocol.action.OFAction;
37import org.projectfloodlight.openflow.protocol.action.OFActionOutput;
38import org.projectfloodlight.openflow.protocol.oxm.OFOxm;
39import org.projectfloodlight.openflow.types.CircuitSignalID;
40import org.projectfloodlight.openflow.types.EthType;
41import org.projectfloodlight.openflow.types.IPv4Address;
42import org.projectfloodlight.openflow.types.MacAddress;
43import org.projectfloodlight.openflow.types.OFGroup;
44import org.projectfloodlight.openflow.types.OFPort;
45import org.projectfloodlight.openflow.types.OFVlanVidMatch;
46import org.projectfloodlight.openflow.types.U32;
47import org.projectfloodlight.openflow.types.VlanPcp;
48import org.slf4j.Logger;
49
50import java.util.ArrayList;
51import java.util.LinkedList;
52import java.util.List;
53import java.util.Optional;
54
55import static org.slf4j.LoggerFactory.getLogger;
56
57/*
58 * Builder for GroupMod.
59 */
60public final class GroupModBuilder {
61
62 private GroupBuckets buckets;
63 private GroupId groupId;
64 private GroupDescription.Type type;
65 private OFFactory factory;
66 private Long xid;
67
68 private final Logger log = getLogger(getClass());
69
70 private static final int OFPCML_NO_BUFFER = 0xffff;
71
72 private GroupModBuilder(GroupBuckets buckets, GroupId groupId,
73 GroupDescription.Type type, OFFactory factory,
74 Optional<Long> xid) {
75 this.buckets = buckets;
76 this.groupId = groupId;
77 this.type = type;
78 this.factory = factory;
79 this.xid = xid.orElse((long) 0);
80 }
81
82 /**
83 * Creates a builder for GroupMod.
84 *
85 * @param buckets GroupBuckets object
86 * @param groupId Group Id to create
87 * @param type Group type
88 * @param factory OFFactory object
89 * @param xid transaction ID
90 * @return GroupModBuilder object
91 */
92 public static GroupModBuilder builder(GroupBuckets buckets, GroupId groupId,
93 GroupDescription.Type type, OFFactory factory,
94 Optional<Long> xid) {
95
96 return new GroupModBuilder(buckets, groupId, type, factory, xid);
97 }
98
99 /**
100 * Builds the GroupAdd OF message.
101 *
102 * @return GroupAdd OF message
103 */
104 public OFGroupAdd buildGroupAdd() {
105
106 List<OFBucket> ofBuckets = new ArrayList<OFBucket>();
107 for (GroupBucket bucket: buckets.buckets()) {
108 List<OFAction> actions = buildActions(bucket.treatment());
109
110 OFBucket.Builder bucketBuilder = factory.buildBucket();
111 bucketBuilder.setActions(actions);
112 if (type == GroupDescription.Type.SELECT) {
113 bucketBuilder.setWeight(1);
114 }
115 bucketBuilder.setWatchGroup(OFGroup.ANY);
116 bucketBuilder.setWatchPort(OFPort.ANY);
117 OFBucket ofBucket = bucketBuilder.build();
118 ofBuckets.add(ofBucket);
119 }
120
121 OFGroupAdd groupMsg = factory.buildGroupAdd()
122 .setGroup(OFGroup.of(groupId.id()))
123 .setBuckets(ofBuckets)
124 .setGroupType(getOFGroupType(type))
125 .setXid(xid)
126 .build();
127
128 return groupMsg;
129 }
130
131 /**
132 * Builds the GroupMod OF message.
133 *
134 * @return GroupMod OF message
135 */
136 public OFGroupMod buildGroupMod() {
137 List<OFBucket> ofBuckets = new ArrayList<OFBucket>();
138 for (GroupBucket bucket: buckets.buckets()) {
139 List<OFAction> actions = buildActions(bucket.treatment());
140
141 OFBucket.Builder bucketBuilder = factory.buildBucket();
142 bucketBuilder.setActions(actions);
143 if (type == GroupDescription.Type.SELECT) {
144 bucketBuilder.setWeight(1);
145 }
146 bucketBuilder.setWatchGroup(OFGroup.ANY);
147 bucketBuilder.setWatchPort(OFPort.ANY);
148 OFBucket ofBucket = bucketBuilder.build();
149 ofBuckets.add(ofBucket);
150 }
151
152 OFGroupMod groupMsg = factory.buildGroupModify()
153 .setGroup(OFGroup.of(groupId.id()))
154 .setBuckets(ofBuckets)
155 .setGroupType(getOFGroupType(type))
156 .setXid(xid)
157 .build();
158
159 return groupMsg;
160 }
161
162 /**
163 * Builds the GroupDel OF message.
164 *
165 * @return GroupDel OF message
166 */
167 public OFGroupDelete buildGroupDel() {
168
169 OFGroupDelete groupMsg = factory.buildGroupDelete()
170 .setGroup(OFGroup.of(groupId.id()))
171 .setGroupType(OFGroupType.SELECT)
172 .setXid(xid)
173 .build();
174
175 return groupMsg;
176 }
177
178 private List<OFAction> buildActions(TrafficTreatment treatment) {
179 List<OFAction> actions = new LinkedList<>();
180 if (treatment == null) {
181 return actions;
182 }
183 for (Instruction i : treatment.instructions()) {
184 switch (i.type()) {
185 case DROP:
186 log.warn("Saw drop action; assigning drop action");
187 return new LinkedList<>();
188 case L0MODIFICATION:
189 actions.add(buildL0Modification(i));
190 break;
191 case L2MODIFICATION:
192 actions.add(buildL2Modification(i));
193 break;
194 case L3MODIFICATION:
195 actions.add(buildL3Modification(i));
196 break;
197 case OUTPUT:
198 Instructions.OutputInstruction out =
199 (Instructions.OutputInstruction) i;
200 OFActionOutput.Builder action = factory.actions().buildOutput()
201 .setPort(OFPort.of((int) out.port().toLong()));
202 if (out.port().equals(PortNumber.CONTROLLER)) {
203 action.setMaxLen(OFPCML_NO_BUFFER);
204 }
205 actions.add(action.build());
206 break;
207 case GROUP:
208 default:
209 log.warn("Instruction type {} not yet implemented.", i.type());
210 }
211 }
212
213 return actions;
214 }
215
216 private OFAction buildL0Modification(Instruction i) {
217 L0ModificationInstruction l0m = (L0ModificationInstruction) i;
218 switch (l0m.subtype()) {
219 case LAMBDA:
220 L0ModificationInstruction.ModLambdaInstruction ml =
221 (L0ModificationInstruction.ModLambdaInstruction) i;
222 return factory.actions().circuit(factory.oxms().ochSigidBasic(
223 new CircuitSignalID((byte) 1, (byte) 2, ml.lambda(), (short) 1)));
224 default:
225 log.warn("Unimplemented action type {}.", l0m.subtype());
226 break;
227 }
228 return null;
229 }
230
231 private OFAction buildL2Modification(Instruction i) {
232 L2ModificationInstruction l2m = (L2ModificationInstruction) i;
233 L2ModificationInstruction.ModEtherInstruction eth;
234 OFOxm<?> oxm = null;
235 switch (l2m.subtype()) {
236 case ETH_DST:
237 eth = (L2ModificationInstruction.ModEtherInstruction) l2m;
238 oxm = factory.oxms().ethDst(MacAddress.of(eth.mac().toLong()));
239 break;
240 case ETH_SRC:
241 eth = (L2ModificationInstruction.ModEtherInstruction) l2m;
242 oxm = factory.oxms().ethSrc(MacAddress.of(eth.mac().toLong()));
243 break;
244 case VLAN_ID:
245 L2ModificationInstruction.ModVlanIdInstruction vlanId =
246 (L2ModificationInstruction.ModVlanIdInstruction) l2m;
247 oxm = factory.oxms().vlanVid(OFVlanVidMatch.ofVlan(vlanId.vlanId().toShort()));
248 break;
249 case VLAN_PCP:
250 L2ModificationInstruction.ModVlanPcpInstruction vlanPcp =
251 (L2ModificationInstruction.ModVlanPcpInstruction) l2m;
252 oxm = factory.oxms().vlanPcp(VlanPcp.of(vlanPcp.vlanPcp()));
253 break;
254 case MPLS_PUSH:
255 L2ModificationInstruction.PushHeaderInstructions pushHeaderInstructions =
256 (L2ModificationInstruction.PushHeaderInstructions) l2m;
257 return factory.actions().pushMpls(EthType.of(pushHeaderInstructions
Yuta HIGUCHI32a53c52015-02-08 01:25:40 -0800258 .ethernetType()));
sangho5afd02a2015-02-03 20:07:35 -0800259 case MPLS_POP:
260 L2ModificationInstruction.PushHeaderInstructions popHeaderInstructions =
261 (L2ModificationInstruction.PushHeaderInstructions) l2m;
262 return factory.actions().popMpls(EthType.of(popHeaderInstructions
Yuta HIGUCHI32a53c52015-02-08 01:25:40 -0800263 .ethernetType()));
sangho5afd02a2015-02-03 20:07:35 -0800264 case MPLS_LABEL:
265 L2ModificationInstruction.ModMplsLabelInstruction mplsLabel =
266 (L2ModificationInstruction.ModMplsLabelInstruction) l2m;
267 oxm = factory.oxms().mplsLabel(U32.of(mplsLabel.label()
268 .longValue()));
269 break;
270 case DEC_MPLS_TTL:
271 return factory.actions().decMplsTtl();
272 default:
273 log.warn("Unimplemented action type {}.", l2m.subtype());
274 break;
275 }
276
277 if (oxm != null) {
278 return factory.actions().buildSetField().setField(oxm).build();
279 }
280 return null;
281 }
282
283 private OFAction buildL3Modification(Instruction i) {
284 L3ModificationInstruction l3m = (L3ModificationInstruction) i;
285 L3ModificationInstruction.ModIPInstruction ip;
286 Ip4Address ip4;
287 OFOxm<?> oxm = null;
288 switch (l3m.subtype()) {
289 case IP_DST:
290 ip = (L3ModificationInstruction.ModIPInstruction) i;
291 ip4 = ip.ip().getIp4Address();
292 oxm = factory.oxms().ipv4Dst(IPv4Address.of(ip4.toInt()));
293 break;
294 case IP_SRC:
295 ip = (L3ModificationInstruction.ModIPInstruction) i;
296 ip4 = ip.ip().getIp4Address();
297 oxm = factory.oxms().ipv4Src(IPv4Address.of(ip4.toInt()));
298 break;
299 case DEC_TTL:
300 return factory.actions().decNwTtl();
301 case TTL_IN:
302 return factory.actions().copyTtlIn();
303 case TTL_OUT:
304 return factory.actions().copyTtlOut();
305 default:
306 log.warn("Unimplemented action type {}.", l3m.subtype());
307 break;
308 }
309
310 if (oxm != null) {
311 return factory.actions().buildSetField().setField(oxm).build();
312 }
313 return null;
314 }
315
316 private OFGroupType getOFGroupType(GroupDescription.Type groupType) {
317 switch (groupType) {
318 case INDIRECT:
319 return OFGroupType.INDIRECT;
320 case SELECT:
321 return OFGroupType.SELECT;
322 case FAILOVER:
323 return OFGroupType.FF;
324 case ALL:
325 return OFGroupType.ALL;
326 default:
327 log.error("Unsupported group type : {}", groupType);
328 break;
329 }
330 return null;
331 }
332}
333