blob: 31148abdeaee89951a8ebe70012bf1481147ea56 [file] [log] [blame]
Thomas Vachuska83e090e2014-10-22 14:25:35 -07001/*
Ray Milkey34c95902015-04-15 09:47:53 -07002 * Copyright 2014-2015 Open Networking Laboratory
Thomas Vachuska83e090e2014-10-22 14:25:35 -07003 *
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07004 * 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
Thomas Vachuska83e090e2014-10-22 14:25:35 -07007 *
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07008 * 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.
Thomas Vachuska83e090e2014-10-22 14:25:35 -070015 */
Brian O'Connorabafb502014-12-02 22:26:20 -080016package org.onosproject.net.flow;
alshabib1d4cace2014-09-13 19:16:26 -070017
Thomas Vachuskaf4df0052015-01-06 12:30:11 -080018import com.google.common.base.MoreObjects;
19import com.google.common.collect.ImmutableList;
alshabib346b5b32015-03-06 00:42:16 -080020import com.google.common.collect.Lists;
Jonathan Hart8ef6d3b2015-03-08 21:21:27 -070021import org.apache.commons.collections.ListUtils;
Pavlin Radoslavov855ea2d2014-10-30 15:32:39 -070022import org.onlab.packet.IpAddress;
alshabib010c31d2014-09-26 10:01:12 -070023import org.onlab.packet.MacAddress;
Michele Santuari4b6019e2014-12-19 11:31:45 +010024import org.onlab.packet.MplsLabel;
alshabib010c31d2014-09-26 10:01:12 -070025import org.onlab.packet.VlanId;
sangho8995ac52015-02-04 11:29:03 -080026import org.onosproject.core.GroupId;
Thomas Vachuskaf4df0052015-01-06 12:30:11 -080027import org.onosproject.net.PortNumber;
28import org.onosproject.net.flow.instructions.Instruction;
29import org.onosproject.net.flow.instructions.Instructions;
tom1679e182014-10-09 13:50:45 -070030
Brian O'Connor6b528132015-03-10 16:39:52 -070031import java.util.Collections;
Thomas Vachuskaf4df0052015-01-06 12:30:11 -080032import java.util.List;
33import java.util.Objects;
Yuta HIGUCHI2809bf32014-10-20 22:44:12 -070034
Ray Milkey42507352015-03-20 15:16:10 -070035import static com.google.common.base.Preconditions.checkNotNull;
36
tom9a693fd2014-10-03 11:32:19 -070037/**
38 * Default traffic treatment implementation.
39 */
alshabib7b2748f2014-09-16 20:21:11 -070040public final class DefaultTrafficTreatment implements TrafficTreatment {
alshabib1d4cace2014-09-13 19:16:26 -070041
alshabib346b5b32015-03-06 00:42:16 -080042 private final List<Instruction> immediate;
43 private final List<Instruction> deferred;
Jonathan Hart4a0ba562015-03-23 17:23:33 -070044 private final List<Instruction> all;
alshabib346b5b32015-03-06 00:42:16 -080045 private final Instructions.TableTypeTransition table;
Saurav Das86af8f12015-05-25 23:55:33 -070046 private final Instructions.MetadataInstruction meta;
alshabib346b5b32015-03-06 00:42:16 -080047
48 private final boolean hasClear;
alshabib1d4cace2014-09-13 19:16:26 -070049
Brian O'Connor6b528132015-03-10 16:39:52 -070050 private static final DefaultTrafficTreatment EMPTY
51 = new DefaultTrafficTreatment(Collections.emptyList());
52
tom9a693fd2014-10-03 11:32:19 -070053 /**
54 * Creates a new traffic treatment from the specified list of instructions.
55 *
Jonathan Hart4a0ba562015-03-23 17:23:33 -070056 * @param immediate immediate instructions
tom9a693fd2014-10-03 11:32:19 -070057 */
Jonathan Hart4a0ba562015-03-23 17:23:33 -070058 private DefaultTrafficTreatment(List<Instruction> immediate) {
59 this.immediate = ImmutableList.copyOf(checkNotNull(immediate));
alshabib346b5b32015-03-06 00:42:16 -080060 this.deferred = ImmutableList.of();
Jonathan Hart4a0ba562015-03-23 17:23:33 -070061 this.all = this.immediate;
alshabib346b5b32015-03-06 00:42:16 -080062 this.hasClear = false;
63 this.table = null;
Saurav Das86af8f12015-05-25 23:55:33 -070064 this.meta = null;
alshabib346b5b32015-03-06 00:42:16 -080065 }
66
Jonathan Hart4a0ba562015-03-23 17:23:33 -070067 /**
68 * Creates a new traffic treatment from the specified list of instructions.
69 *
70 * @param deferred deferred instructions
71 * @param immediate immediate instructions
72 * @param table table transition instruction
73 * @param clear instruction to clear the deferred actions list
74 */
alshabib346b5b32015-03-06 00:42:16 -080075 private DefaultTrafficTreatment(List<Instruction> deferred,
76 List<Instruction> immediate,
77 Instructions.TableTypeTransition table,
Saurav Das86af8f12015-05-25 23:55:33 -070078 boolean clear,
79 Instructions.MetadataInstruction meta) {
Ray Milkey42507352015-03-20 15:16:10 -070080 this.immediate = ImmutableList.copyOf(checkNotNull(immediate));
81 this.deferred = ImmutableList.copyOf(checkNotNull(deferred));
Jonathan Hart4a0ba562015-03-23 17:23:33 -070082 this.all = ListUtils.union(this.immediate, this.deferred);
alshabib346b5b32015-03-06 00:42:16 -080083 this.table = table;
Saurav Das86af8f12015-05-25 23:55:33 -070084 this.meta = meta;
alshabib346b5b32015-03-06 00:42:16 -080085 this.hasClear = clear;
alshabib1d4cace2014-09-13 19:16:26 -070086 }
87
88 @Override
alshabib346b5b32015-03-06 00:42:16 -080089 public List<Instruction> deferred() {
90 return deferred;
91 }
92
93 @Override
94 public List<Instruction> immediate() {
95 return immediate;
96 }
97
98 @Override
Jonathan Hart8ef6d3b2015-03-08 21:21:27 -070099 public List<Instruction> allInstructions() {
Jonathan Hart4a0ba562015-03-23 17:23:33 -0700100 return all;
Jonathan Hart8ef6d3b2015-03-08 21:21:27 -0700101 }
102
103 @Override
alshabib346b5b32015-03-06 00:42:16 -0800104 public Instructions.TableTypeTransition tableTransition() {
105 return table;
106 }
107
108 @Override
Jonathan Hart4a0ba562015-03-23 17:23:33 -0700109 public boolean clearedDeferred() {
alshabib346b5b32015-03-06 00:42:16 -0800110 return hasClear;
alshabib1d4cace2014-09-13 19:16:26 -0700111 }
112
Saurav Das86af8f12015-05-25 23:55:33 -0700113 @Override
114 public Instructions.MetadataInstruction writeMetadata() {
115 return meta;
116 }
117
alshabib1d4cace2014-09-13 19:16:26 -0700118 /**
tom9a693fd2014-10-03 11:32:19 -0700119 * Returns a new traffic treatment builder.
120 *
121 * @return traffic treatment builder
122 */
123 public static TrafficTreatment.Builder builder() {
124 return new Builder();
125 }
126
Jonathan Hart6e88c682014-10-21 17:05:25 -0700127 /**
Brian O'Connor6b528132015-03-10 16:39:52 -0700128 * Returns an empty traffic treatment.
129 *
130 * @return empty traffic treatment
131 */
132 public static TrafficTreatment emptyTreatment() {
133 return EMPTY;
134 }
135
136 /**
Jonathan Hart6e88c682014-10-21 17:05:25 -0700137 * Returns a new traffic treatment builder primed to produce entities
138 * patterned after the supplied treatment.
139 *
Yuta HIGUCHI5c947272014-11-03 21:39:21 -0800140 * @param treatment base treatment
Jonathan Hart6e88c682014-10-21 17:05:25 -0700141 * @return traffic treatment builder
142 */
143 public static TrafficTreatment.Builder builder(TrafficTreatment treatment) {
144 return new Builder(treatment);
145 }
146
alshabib8ca53902014-10-07 13:11:17 -0700147 //FIXME: Order of instructions may affect hashcode
148 @Override
149 public int hashCode() {
Saurav Das86af8f12015-05-25 23:55:33 -0700150 return Objects.hash(immediate, deferred, table, meta);
alshabib8ca53902014-10-07 13:11:17 -0700151 }
152
153 @Override
154 public boolean equals(Object obj) {
155 if (this == obj) {
156 return true;
157 }
158 if (obj instanceof DefaultTrafficTreatment) {
159 DefaultTrafficTreatment that = (DefaultTrafficTreatment) obj;
alshabib346b5b32015-03-06 00:42:16 -0800160 return Objects.equals(immediate, that.immediate) &&
161 Objects.equals(deferred, that.deferred) &&
Saurav Das86af8f12015-05-25 23:55:33 -0700162 Objects.equals(table, that.table) &&
163 Objects.equals(meta, that.meta);
alshabib8ca53902014-10-07 13:11:17 -0700164
165 }
166 return false;
167 }
168
Jonathan Hartd87aeca2014-10-21 10:42:52 -0700169 @Override
170 public String toString() {
171 return MoreObjects.toStringHelper(getClass())
alshabib346b5b32015-03-06 00:42:16 -0800172 .add("immediate", immediate)
173 .add("deferred", deferred)
174 .add("transition", table == null ? "None" : table.toString())
175 .add("cleared", hasClear)
Saurav Das86af8f12015-05-25 23:55:33 -0700176 .add("metadata", meta)
Jonathan Hartd87aeca2014-10-21 10:42:52 -0700177 .toString();
178 }
179
tom9a693fd2014-10-03 11:32:19 -0700180 /**
alshabib1d4cace2014-09-13 19:16:26 -0700181 * Builds a list of treatments following the following order.
Thomas Vachuska4b420772014-10-30 16:46:17 -0700182 * Modifications -&gt; Group -&gt; Output (including drop)
alshabib1d4cace2014-09-13 19:16:26 -0700183 */
tom9a693fd2014-10-03 11:32:19 -0700184 public static final class Builder implements TrafficTreatment.Builder {
alshabib1d4cace2014-09-13 19:16:26 -0700185
alshabib346b5b32015-03-06 00:42:16 -0800186 boolean clear = false;
alshabib1d4cace2014-09-13 19:16:26 -0700187
alshabib346b5b32015-03-06 00:42:16 -0800188 Instructions.TableTypeTransition table;
alshabib1d4cace2014-09-13 19:16:26 -0700189
Saurav Das86af8f12015-05-25 23:55:33 -0700190 Instructions.MetadataInstruction meta;
191
alshabib346b5b32015-03-06 00:42:16 -0800192 List<Instruction> deferred = Lists.newLinkedList();
193
194 List<Instruction> immediate = Lists.newLinkedList();
195
196 List<Instruction> current = immediate;
alshabib1d4cace2014-09-13 19:16:26 -0700197
tom9a693fd2014-10-03 11:32:19 -0700198 // Creates a new builder
199 private Builder() {
200 }
201
Jonathan Hart6e88c682014-10-21 17:05:25 -0700202 // Creates a new builder based off an existing treatment
203 private Builder(TrafficTreatment treatment) {
Jonathan Hart4a0ba562015-03-23 17:23:33 -0700204 deferred();
205 treatment.deferred().forEach(i -> add(i));
206
207 immediate();
208 treatment.immediate().forEach(i -> add(i));
209
210 clear = treatment.clearedDeferred();
Jonathan Hart6e88c682014-10-21 17:05:25 -0700211 }
212
alshabib8ca53902014-10-07 13:11:17 -0700213 @Override
alshabib1d4cace2014-09-13 19:16:26 -0700214 public Builder add(Instruction instruction) {
alshabib346b5b32015-03-06 00:42:16 -0800215
alshabib1d4cace2014-09-13 19:16:26 -0700216 switch (instruction.type()) {
tom9a693fd2014-10-03 11:32:19 -0700217 case DROP:
tom9a693fd2014-10-03 11:32:19 -0700218 case OUTPUT:
alshabib346b5b32015-03-06 00:42:16 -0800219 case GROUP:
Marc De Leenheer49087752014-10-23 13:54:09 -0700220 case L0MODIFICATION:
tom9a693fd2014-10-03 11:32:19 -0700221 case L2MODIFICATION:
222 case L3MODIFICATION:
alshabib346b5b32015-03-06 00:42:16 -0800223 current.add(instruction);
tom9a693fd2014-10-03 11:32:19 -0700224 break;
alshabib346b5b32015-03-06 00:42:16 -0800225 case TABLE:
226 table = (Instructions.TableTypeTransition) instruction;
tom9a693fd2014-10-03 11:32:19 -0700227 break;
Saurav Das86af8f12015-05-25 23:55:33 -0700228 case METADATA:
229 meta = (Instructions.MetadataInstruction) instruction;
230 break;
tom9a693fd2014-10-03 11:32:19 -0700231 default:
tom1679e182014-10-09 13:50:45 -0700232 throw new IllegalArgumentException("Unknown instruction type: " +
233 instruction.type());
alshabib1d4cace2014-09-13 19:16:26 -0700234 }
alshabib346b5b32015-03-06 00:42:16 -0800235
alshabib1d4cace2014-09-13 19:16:26 -0700236 return this;
237 }
238
239 @Override
Thomas Vachuskaf4df0052015-01-06 12:30:11 -0800240 public Builder drop() {
241 return add(Instructions.createDrop());
242 }
243
244 @Override
245 public Builder punt() {
246 return add(Instructions.createOutput(PortNumber.CONTROLLER));
alshabib010c31d2014-09-26 10:01:12 -0700247 }
248
249 @Override
250 public Builder setOutput(PortNumber number) {
251 return add(Instructions.createOutput(number));
252 }
253
254 @Override
255 public Builder setEthSrc(MacAddress addr) {
256 return add(Instructions.modL2Src(addr));
257 }
258
259 @Override
260 public Builder setEthDst(MacAddress addr) {
261 return add(Instructions.modL2Dst(addr));
262 }
263
264 @Override
265 public Builder setVlanId(VlanId id) {
266 return add(Instructions.modVlanId(id));
267 }
268
269 @Override
270 public Builder setVlanPcp(Byte pcp) {
271 return add(Instructions.modVlanPcp(pcp));
272 }
273
274 @Override
Pavlin Radoslavov855ea2d2014-10-30 15:32:39 -0700275 public Builder setIpSrc(IpAddress addr) {
alshabib010c31d2014-09-26 10:01:12 -0700276 return add(Instructions.modL3Src(addr));
277 }
278
279 @Override
Pavlin Radoslavov855ea2d2014-10-30 15:32:39 -0700280 public Builder setIpDst(IpAddress addr) {
alshabib010c31d2014-09-26 10:01:12 -0700281 return add(Instructions.modL3Dst(addr));
282 }
283
284 @Override
sangho3f97a17d2015-01-29 22:56:29 -0800285 public Builder decNwTtl() {
286 return add(Instructions.decNwTtl());
287 }
288
289 @Override
290 public Builder copyTtlIn() {
291 return add(Instructions.copyTtlIn());
292 }
293
294 @Override
295 public Builder copyTtlOut() {
296 return add(Instructions.copyTtlOut());
297 }
298
299 @Override
Praseed Balakrishnan8c67d172014-11-10 10:15:41 -0800300 public Builder pushMpls() {
301 return add(Instructions.pushMpls());
302 }
303
304 @Override
305 public Builder popMpls() {
306 return add(Instructions.popMpls());
307 }
308
sangho3f97a17d2015-01-29 22:56:29 -0800309 @Override
alshabib0ad43982015-05-07 13:43:13 -0700310 public Builder popMpls(int etherType) {
sangho3f97a17d2015-01-29 22:56:29 -0800311 return add(Instructions.popMpls(etherType));
312 }
Praseed Balakrishnan8c67d172014-11-10 10:15:41 -0800313
314 @Override
Michele Santuari4b6019e2014-12-19 11:31:45 +0100315 public Builder setMpls(MplsLabel mplsLabel) {
Praseed Balakrishnan8c67d172014-11-10 10:15:41 -0800316 return add(Instructions.modMplsLabel(mplsLabel));
317 }
318
319 @Override
sangho3f97a17d2015-01-29 22:56:29 -0800320 public Builder decMplsTtl() {
321 return add(Instructions.decMplsTtl());
322 }
323
324 @Override
Marc De Leenheer49087752014-10-23 13:54:09 -0700325 public Builder setLambda(short lambda) {
326 return add(Instructions.modL0Lambda(lambda));
327 }
328
329 @Override
sangho8995ac52015-02-04 11:29:03 -0800330 public Builder group(GroupId groupId) {
331 return add(Instructions.createGroup(groupId));
332 }
333
334 @Override
Saurav Dasfbe25c52015-03-04 11:12:00 -0800335 public Builder popVlan() {
336 return add(Instructions.popVlan());
337 }
338
339 @Override
Jonathan Hart54b406b2015-03-06 16:24:14 -0800340 public Builder pushVlan() {
341 return add(Instructions.pushVlan());
342 }
343
344 @Override
alshabib346b5b32015-03-06 00:42:16 -0800345 public Builder transition(FlowRule.Type type) {
alshabibd17abc22015-04-21 18:26:35 -0700346 return add(Instructions.transition(type.ordinal()));
347 }
348
349 @Override
350 public Builder transition(Integer tableId) {
351 return add(Instructions.transition(tableId));
alshabib346b5b32015-03-06 00:42:16 -0800352 }
353
354 @Override
355 public Builder immediate() {
356 current = immediate;
357 return this;
358 }
359
360 @Override
361 public Builder deferred() {
362 current = deferred;
363 return this;
364 }
365
366 @Override
367 public Builder wipeDeferred() {
368 clear = true;
369 return this;
370 }
371
372 @Override
Saurav Das86af8f12015-05-25 23:55:33 -0700373 public Builder writeMetadata(long metadata, long metadataMask) {
374 return add(Instructions.writeMetadata(metadata, metadataMask));
375 }
376
377 @Override
alshabib1d4cace2014-09-13 19:16:26 -0700378 public TrafficTreatment build() {
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700379 //Don't add DROP instruction by default when instruction
380 //set is empty. This will be handled in DefaultSingleTablePipeline
381 //driver.
382
383 //if (deferred.size() == 0 && immediate.size() == 0
384 // && table == null && !clear) {
385 // drop();
386 //}
Saurav Das86af8f12015-05-25 23:55:33 -0700387 return new DefaultTrafficTreatment(deferred, immediate, table, clear, meta);
alshabib1d4cace2014-09-13 19:16:26 -0700388 }
389
390 }
391
392}