Saurav Das
Committed by Gerrit Code Review

Adding support for writing metadata instruction.

Needed by Centec driver.

Change-Id: I705015c4d7ac881c273a01b36b05d39d9cd9ba87
...@@ -43,6 +43,7 @@ public final class DefaultTrafficTreatment implements TrafficTreatment { ...@@ -43,6 +43,7 @@ public final class DefaultTrafficTreatment implements TrafficTreatment {
43 private final List<Instruction> deferred; 43 private final List<Instruction> deferred;
44 private final List<Instruction> all; 44 private final List<Instruction> all;
45 private final Instructions.TableTypeTransition table; 45 private final Instructions.TableTypeTransition table;
46 + private final Instructions.MetadataInstruction meta;
46 47
47 private final boolean hasClear; 48 private final boolean hasClear;
48 49
...@@ -60,6 +61,7 @@ public final class DefaultTrafficTreatment implements TrafficTreatment { ...@@ -60,6 +61,7 @@ public final class DefaultTrafficTreatment implements TrafficTreatment {
60 this.all = this.immediate; 61 this.all = this.immediate;
61 this.hasClear = false; 62 this.hasClear = false;
62 this.table = null; 63 this.table = null;
64 + this.meta = null;
63 } 65 }
64 66
65 /** 67 /**
...@@ -73,13 +75,14 @@ public final class DefaultTrafficTreatment implements TrafficTreatment { ...@@ -73,13 +75,14 @@ public final class DefaultTrafficTreatment implements TrafficTreatment {
73 private DefaultTrafficTreatment(List<Instruction> deferred, 75 private DefaultTrafficTreatment(List<Instruction> deferred,
74 List<Instruction> immediate, 76 List<Instruction> immediate,
75 Instructions.TableTypeTransition table, 77 Instructions.TableTypeTransition table,
76 - boolean clear) { 78 + boolean clear,
79 + Instructions.MetadataInstruction meta) {
77 this.immediate = ImmutableList.copyOf(checkNotNull(immediate)); 80 this.immediate = ImmutableList.copyOf(checkNotNull(immediate));
78 this.deferred = ImmutableList.copyOf(checkNotNull(deferred)); 81 this.deferred = ImmutableList.copyOf(checkNotNull(deferred));
79 this.all = ListUtils.union(this.immediate, this.deferred); 82 this.all = ListUtils.union(this.immediate, this.deferred);
80 this.table = table; 83 this.table = table;
84 + this.meta = meta;
81 this.hasClear = clear; 85 this.hasClear = clear;
82 -
83 } 86 }
84 87
85 @Override 88 @Override
...@@ -107,6 +110,11 @@ public final class DefaultTrafficTreatment implements TrafficTreatment { ...@@ -107,6 +110,11 @@ public final class DefaultTrafficTreatment implements TrafficTreatment {
107 return hasClear; 110 return hasClear;
108 } 111 }
109 112
113 + @Override
114 + public Instructions.MetadataInstruction writeMetadata() {
115 + return meta;
116 + }
117 +
110 /** 118 /**
111 * Returns a new traffic treatment builder. 119 * Returns a new traffic treatment builder.
112 * 120 *
...@@ -139,7 +147,7 @@ public final class DefaultTrafficTreatment implements TrafficTreatment { ...@@ -139,7 +147,7 @@ public final class DefaultTrafficTreatment implements TrafficTreatment {
139 //FIXME: Order of instructions may affect hashcode 147 //FIXME: Order of instructions may affect hashcode
140 @Override 148 @Override
141 public int hashCode() { 149 public int hashCode() {
142 - return Objects.hash(immediate, deferred, table); 150 + return Objects.hash(immediate, deferred, table, meta);
143 } 151 }
144 152
145 @Override 153 @Override
...@@ -151,7 +159,8 @@ public final class DefaultTrafficTreatment implements TrafficTreatment { ...@@ -151,7 +159,8 @@ public final class DefaultTrafficTreatment implements TrafficTreatment {
151 DefaultTrafficTreatment that = (DefaultTrafficTreatment) obj; 159 DefaultTrafficTreatment that = (DefaultTrafficTreatment) obj;
152 return Objects.equals(immediate, that.immediate) && 160 return Objects.equals(immediate, that.immediate) &&
153 Objects.equals(deferred, that.deferred) && 161 Objects.equals(deferred, that.deferred) &&
154 - Objects.equals(table, that.table); 162 + Objects.equals(table, that.table) &&
163 + Objects.equals(meta, that.meta);
155 164
156 } 165 }
157 return false; 166 return false;
...@@ -164,6 +173,7 @@ public final class DefaultTrafficTreatment implements TrafficTreatment { ...@@ -164,6 +173,7 @@ public final class DefaultTrafficTreatment implements TrafficTreatment {
164 .add("deferred", deferred) 173 .add("deferred", deferred)
165 .add("transition", table == null ? "None" : table.toString()) 174 .add("transition", table == null ? "None" : table.toString())
166 .add("cleared", hasClear) 175 .add("cleared", hasClear)
176 + .add("metadata", meta)
167 .toString(); 177 .toString();
168 } 178 }
169 179
...@@ -177,6 +187,8 @@ public final class DefaultTrafficTreatment implements TrafficTreatment { ...@@ -177,6 +187,8 @@ public final class DefaultTrafficTreatment implements TrafficTreatment {
177 187
178 Instructions.TableTypeTransition table; 188 Instructions.TableTypeTransition table;
179 189
190 + Instructions.MetadataInstruction meta;
191 +
180 List<Instruction> deferred = Lists.newLinkedList(); 192 List<Instruction> deferred = Lists.newLinkedList();
181 193
182 List<Instruction> immediate = Lists.newLinkedList(); 194 List<Instruction> immediate = Lists.newLinkedList();
...@@ -213,6 +225,9 @@ public final class DefaultTrafficTreatment implements TrafficTreatment { ...@@ -213,6 +225,9 @@ public final class DefaultTrafficTreatment implements TrafficTreatment {
213 case TABLE: 225 case TABLE:
214 table = (Instructions.TableTypeTransition) instruction; 226 table = (Instructions.TableTypeTransition) instruction;
215 break; 227 break;
228 + case METADATA:
229 + meta = (Instructions.MetadataInstruction) instruction;
230 + break;
216 default: 231 default:
217 throw new IllegalArgumentException("Unknown instruction type: " + 232 throw new IllegalArgumentException("Unknown instruction type: " +
218 instruction.type()); 233 instruction.type());
...@@ -355,6 +370,11 @@ public final class DefaultTrafficTreatment implements TrafficTreatment { ...@@ -355,6 +370,11 @@ public final class DefaultTrafficTreatment implements TrafficTreatment {
355 } 370 }
356 371
357 @Override 372 @Override
373 + public Builder writeMetadata(long metadata, long metadataMask) {
374 + return add(Instructions.writeMetadata(metadata, metadataMask));
375 + }
376 +
377 + @Override
358 public TrafficTreatment build() { 378 public TrafficTreatment build() {
359 //Don't add DROP instruction by default when instruction 379 //Don't add DROP instruction by default when instruction
360 //set is empty. This will be handled in DefaultSingleTablePipeline 380 //set is empty. This will be handled in DefaultSingleTablePipeline
...@@ -364,7 +384,7 @@ public final class DefaultTrafficTreatment implements TrafficTreatment { ...@@ -364,7 +384,7 @@ public final class DefaultTrafficTreatment implements TrafficTreatment {
364 // && table == null && !clear) { 384 // && table == null && !clear) {
365 // drop(); 385 // drop();
366 //} 386 //}
367 - return new DefaultTrafficTreatment(deferred, immediate, table, clear); 387 + return new DefaultTrafficTreatment(deferred, immediate, table, clear, meta);
368 } 388 }
369 389
370 } 390 }
......
...@@ -67,6 +67,13 @@ public interface TrafficTreatment { ...@@ -67,6 +67,13 @@ public interface TrafficTreatment {
67 boolean clearedDeferred(); 67 boolean clearedDeferred();
68 68
69 /** 69 /**
70 + * Returns the metadata instruction if there is one.
71 + *
72 + * @return a metadata instruction that may be null
73 + */
74 + Instructions.MetadataInstruction writeMetadata();
75 +
76 + /**
70 * Builder of traffic treatment entities. 77 * Builder of traffic treatment entities.
71 */ 78 */
72 interface Builder { 79 interface Builder {
...@@ -276,6 +283,20 @@ public interface TrafficTreatment { ...@@ -276,6 +283,20 @@ public interface TrafficTreatment {
276 Builder wipeDeferred(); 283 Builder wipeDeferred();
277 284
278 /** 285 /**
286 + * Writes metadata to associate with a packet.
287 + * <pre>
288 + * {@code
289 + * new_metadata = (old_metadata & ̃mask) | (value & mask)
290 + * }
291 + * </pre>
292 + *
293 + * @param value the metadata to write
294 + * @param mask the masked bits for the value
295 + * @return a treatment builder
296 + */
297 + Builder writeMetadata(long value, long mask);
298 +
299 + /**
279 * Builds an immutable traffic treatment descriptor. 300 * Builds an immutable traffic treatment descriptor.
280 * <p> 301 * <p>
281 * If the treatment is empty when build() is called, it will add a default 302 * If the treatment is empty when build() is called, it will add a default
...@@ -286,5 +307,7 @@ public interface TrafficTreatment { ...@@ -286,5 +307,7 @@ public interface TrafficTreatment {
286 * @return traffic treatment 307 * @return traffic treatment
287 */ 308 */
288 TrafficTreatment build(); 309 TrafficTreatment build();
310 +
289 } 311 }
312 +
290 } 313 }
......
...@@ -35,7 +35,7 @@ public interface Instruction { ...@@ -35,7 +35,7 @@ public interface Instruction {
35 OUTPUT, 35 OUTPUT,
36 36
37 /** 37 /**
38 - * Signifies that.... (do we need this?) 38 + * Signifies that traffic should be sent out of a group.
39 */ 39 */
40 GROUP, 40 GROUP,
41 41
...@@ -57,7 +57,12 @@ public interface Instruction { ...@@ -57,7 +57,12 @@ public interface Instruction {
57 /** 57 /**
58 * Signifies that the traffic should be modified in L3 way. 58 * Signifies that the traffic should be modified in L3 way.
59 */ 59 */
60 - L3MODIFICATION 60 + L3MODIFICATION,
61 +
62 + /**
63 + * Signifies that metadata be attached to traffic.
64 + */
65 + METADATA
61 } 66 }
62 67
63 /** 68 /**
......
...@@ -323,6 +323,17 @@ public final class Instructions { ...@@ -323,6 +323,17 @@ public final class Instructions {
323 } 323 }
324 324
325 /** 325 /**
326 + * Writes metadata to associate with a packet.
327 + *
328 + * @param metadata the metadata value to write
329 + * @param metadataMask the bits to mask for the metadata value
330 + * @return metadata instruction
331 + */
332 + public static Instruction writeMetadata(long metadata, long metadataMask) {
333 + return new MetadataInstruction(metadata, metadataMask);
334 + }
335 +
336 + /**
326 * Drop instruction. 337 * Drop instruction.
327 */ 338 */
328 public static final class DropInstruction implements Instruction { 339 public static final class DropInstruction implements Instruction {
...@@ -443,7 +454,9 @@ public final class Instructions { ...@@ -443,7 +454,9 @@ public final class Instructions {
443 } 454 }
444 } 455 }
445 456
446 - 457 + /**
458 + * Transition instruction.
459 + */
447 public static class TableTypeTransition implements Instruction { 460 public static class TableTypeTransition implements Instruction {
448 private final Integer tableId; 461 private final Integer tableId;
449 462
...@@ -483,7 +496,59 @@ public final class Instructions { ...@@ -483,7 +496,59 @@ public final class Instructions {
483 } 496 }
484 return false; 497 return false;
485 } 498 }
499 + }
500 +
501 + /**
502 + * Metadata instruction.
503 + */
504 + public static class MetadataInstruction implements Instruction {
505 + private final long metadata;
506 + private final long metadataMask;
507 +
508 + MetadataInstruction(long metadata, long metadataMask) {
509 + this.metadata = metadata;
510 + this.metadataMask = metadataMask;
511 + }
512 +
513 + @Override
514 + public Type type() {
515 + return Type.METADATA;
516 + }
517 +
518 + public long metadata() {
519 + return this.metadata;
520 + }
486 521
522 + public long metadataMask() {
523 + return this.metadataMask;
524 + }
525 +
526 + @Override
527 + public String toString() {
528 + return toStringHelper(type().toString())
529 + .add("metadata", Long.toHexString(this.metadata))
530 + .add("metadata mask", Long.toHexString(this.metadataMask))
531 + .toString();
532 + }
533 +
534 + @Override
535 + public int hashCode() {
536 + return Objects.hash(type(), metadata, metadataMask);
537 + }
538 +
539 + @Override
540 + public boolean equals(Object obj) {
541 + if (this == obj) {
542 + return true;
543 + }
544 + if (obj instanceof MetadataInstruction) {
545 + MetadataInstruction that = (MetadataInstruction) obj;
546 + return Objects.equals(metadata, that.metadata) &&
547 + Objects.equals(metadataMask, that.metadataMask);
548 +
549 + }
550 + return false;
551 + }
487 } 552 }
488 } 553 }
489 554
......
...@@ -36,6 +36,7 @@ import org.onosproject.net.flow.criteria.Criterion; ...@@ -36,6 +36,7 @@ import org.onosproject.net.flow.criteria.Criterion;
36 import org.onosproject.net.flow.criteria.Criterion.Type; 36 import org.onosproject.net.flow.criteria.Criterion.Type;
37 import org.onosproject.net.flow.instructions.Instruction; 37 import org.onosproject.net.flow.instructions.Instruction;
38 import org.onosproject.net.flow.instructions.Instructions; 38 import org.onosproject.net.flow.instructions.Instructions;
39 +import org.onosproject.net.flow.instructions.Instructions.MetadataInstruction;
39 import org.onosproject.net.resource.link.BandwidthResource; 40 import org.onosproject.net.resource.link.BandwidthResource;
40 import org.onosproject.net.resource.link.BandwidthResourceRequest; 41 import org.onosproject.net.resource.link.BandwidthResourceRequest;
41 import org.onosproject.net.resource.link.LambdaResource; 42 import org.onosproject.net.resource.link.LambdaResource;
...@@ -118,6 +119,11 @@ public class IntentTestsMocks { ...@@ -118,6 +119,11 @@ public class IntentTestsMocks {
118 public boolean clearedDeferred() { 119 public boolean clearedDeferred() {
119 return false; 120 return false;
120 } 121 }
122 +
123 + @Override
124 + public MetadataInstruction writeMetadata() {
125 + return null;
126 + }
121 } 127 }
122 128
123 /** 129 /**
......
...@@ -21,6 +21,7 @@ import com.google.common.collect.Lists; ...@@ -21,6 +21,7 @@ import com.google.common.collect.Lists;
21 import com.google.common.collect.Sets; 21 import com.google.common.collect.Sets;
22 import com.google.common.util.concurrent.ListenableFuture; 22 import com.google.common.util.concurrent.ListenableFuture;
23 import com.google.common.util.concurrent.MoreExecutors; 23 import com.google.common.util.concurrent.MoreExecutors;
24 +
24 import org.junit.After; 25 import org.junit.After;
25 import org.junit.Before; 26 import org.junit.Before;
26 import org.junit.Test; 27 import org.junit.Test;
...@@ -58,6 +59,7 @@ import org.onosproject.net.flow.TrafficTreatment; ...@@ -58,6 +59,7 @@ import org.onosproject.net.flow.TrafficTreatment;
58 import org.onosproject.net.flow.criteria.Criterion; 59 import org.onosproject.net.flow.criteria.Criterion;
59 import org.onosproject.net.flow.instructions.Instruction; 60 import org.onosproject.net.flow.instructions.Instruction;
60 import org.onosproject.net.flow.instructions.Instructions; 61 import org.onosproject.net.flow.instructions.Instructions;
62 +import org.onosproject.net.flow.instructions.Instructions.MetadataInstruction;
61 import org.onosproject.net.provider.AbstractProvider; 63 import org.onosproject.net.provider.AbstractProvider;
62 import org.onosproject.net.provider.ProviderId; 64 import org.onosproject.net.provider.ProviderId;
63 import org.onosproject.store.trivial.impl.SimpleFlowRuleStore; 65 import org.onosproject.store.trivial.impl.SimpleFlowRuleStore;
...@@ -595,6 +597,11 @@ public class FlowRuleManagerTest { ...@@ -595,6 +597,11 @@ public class FlowRuleManagerTest {
595 return false; 597 return false;
596 } 598 }
597 599
600 + @Override
601 + public MetadataInstruction writeMetadata() {
602 + return null;
603 + }
604 +
598 } 605 }
599 606
600 public class TestApplicationId extends DefaultApplicationId { 607 public class TestApplicationId extends DefaultApplicationId {
......
...@@ -78,6 +78,7 @@ public class CentecV350Pipeline extends AbstractHandlerBehaviour implements Pipe ...@@ -78,6 +78,7 @@ public class CentecV350Pipeline extends AbstractHandlerBehaviour implements Pipe
78 protected static final int ROUTE_TABLE = 3; 78 protected static final int ROUTE_TABLE = 3;
79 79
80 private static final long DEFAULT_METADATA = 100; 80 private static final long DEFAULT_METADATA = 100;
81 + private static final long DEFAULT_METADATA_MASK = 0xff;
81 82
82 // Priority used in PORT_VLAN Table, the only priority accepted is PORT_VLAN_TABLE_PRIORITY. 83 // Priority used in PORT_VLAN Table, the only priority accepted is PORT_VLAN_TABLE_PRIORITY.
83 // The packet passed PORT+VLAN check will goto FILTER Table. 84 // The packet passed PORT+VLAN check will goto FILTER Table.
...@@ -408,10 +409,10 @@ public class CentecV350Pipeline extends AbstractHandlerBehaviour implements Pipe ...@@ -408,10 +409,10 @@ public class CentecV350Pipeline extends AbstractHandlerBehaviour implements Pipe
408 selector.matchInPort(p.port()); 409 selector.matchInPort(p.port());
409 // Although the accepted packets will be sent to filter table, we must 410 // Although the accepted packets will be sent to filter table, we must
410 // explicitly set goto_table instruction here. 411 // explicitly set goto_table instruction here.
412 + treatment.writeMetadata(DEFAULT_METADATA, DEFAULT_METADATA_MASK);
413 + // set default metadata written by PORT_VLAN Table.
411 treatment.transition(FILTER_TABLE); 414 treatment.transition(FILTER_TABLE);
412 // We do not support strip vlan here, treatment.deferred().popVlan(); 415 // We do not support strip vlan here, treatment.deferred().popVlan();
413 - // XXX: write_metadata seems not supported by ONOS now, use the switch CLI to
414 - // set default metadata written by PORT_VLAN Table.
415 // PORT_VLAN table only accept 0xffff priority since it does exact match only. 416 // PORT_VLAN table only accept 0xffff priority since it does exact match only.
416 FlowRule rule = DefaultFlowRule.builder() 417 FlowRule rule = DefaultFlowRule.builder()
417 .forDevice(deviceId) 418 .forDevice(deviceId)
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
16 package org.onosproject.provider.of.flow.impl; 16 package org.onosproject.provider.of.flow.impl;
17 17
18 import com.google.common.collect.Lists; 18 import com.google.common.collect.Lists;
19 +
19 import org.onlab.packet.Ip4Address; 20 import org.onlab.packet.Ip4Address;
20 import org.onlab.packet.Ip4Prefix; 21 import org.onlab.packet.Ip4Prefix;
21 import org.onlab.packet.Ip6Address; 22 import org.onlab.packet.Ip6Address;
...@@ -56,6 +57,7 @@ import org.projectfloodlight.openflow.protocol.instruction.OFInstruction; ...@@ -56,6 +57,7 @@ import org.projectfloodlight.openflow.protocol.instruction.OFInstruction;
56 import org.projectfloodlight.openflow.protocol.instruction.OFInstructionApplyActions; 57 import org.projectfloodlight.openflow.protocol.instruction.OFInstructionApplyActions;
57 import org.projectfloodlight.openflow.protocol.instruction.OFInstructionGotoTable; 58 import org.projectfloodlight.openflow.protocol.instruction.OFInstructionGotoTable;
58 import org.projectfloodlight.openflow.protocol.instruction.OFInstructionWriteActions; 59 import org.projectfloodlight.openflow.protocol.instruction.OFInstructionWriteActions;
60 +import org.projectfloodlight.openflow.protocol.instruction.OFInstructionWriteMetadata;
59 import org.projectfloodlight.openflow.protocol.match.Match; 61 import org.projectfloodlight.openflow.protocol.match.Match;
60 import org.projectfloodlight.openflow.protocol.match.MatchField; 62 import org.projectfloodlight.openflow.protocol.match.MatchField;
61 import org.projectfloodlight.openflow.protocol.oxm.OFOxm; 63 import org.projectfloodlight.openflow.protocol.oxm.OFOxm;
...@@ -219,6 +221,9 @@ public class FlowEntryBuilder { ...@@ -219,6 +221,9 @@ public class FlowEntryBuilder {
219 .getTableId().getValue())); 221 .getTableId().getValue()));
220 break; 222 break;
221 case WRITE_METADATA: 223 case WRITE_METADATA:
224 + OFInstructionWriteMetadata m = (OFInstructionWriteMetadata) in;
225 + builder.writeMetadata(m.getMetadata().getValue(),
226 + m.getMetadataMask().getValue());
222 break; 227 break;
223 case WRITE_ACTIONS: 228 case WRITE_ACTIONS:
224 builder.deferred(); 229 builder.deferred();
......
...@@ -167,6 +167,8 @@ public class FlowModBuilderVer10 extends FlowModBuilder { ...@@ -167,6 +167,8 @@ public class FlowModBuilderVer10 extends FlowModBuilder {
167 break; 167 break;
168 case L0MODIFICATION: 168 case L0MODIFICATION:
169 case GROUP: 169 case GROUP:
170 + case TABLE:
171 + case METADATA:
170 log.warn("Instruction type {} not supported with protocol version {}", 172 log.warn("Instruction type {} not supported with protocol version {}",
171 i.type(), factory().getVersion()); 173 i.type(), factory().getVersion());
172 break; 174 break;
......
...@@ -117,6 +117,9 @@ public class FlowModBuilderVer13 extends FlowModBuilder { ...@@ -117,6 +117,9 @@ public class FlowModBuilderVer13 extends FlowModBuilder {
117 if (treatment.tableTransition() != null) { 117 if (treatment.tableTransition() != null) {
118 instructions.add(buildTableGoto(treatment.tableTransition())); 118 instructions.add(buildTableGoto(treatment.tableTransition()));
119 } 119 }
120 + if (treatment.writeMetadata() != null) {
121 + instructions.add(buildMetadata(treatment.writeMetadata()));
122 + }
120 123
121 long cookie = flowRule().id().value(); 124 long cookie = flowRule().id().value();
122 125
...@@ -154,6 +157,9 @@ public class FlowModBuilderVer13 extends FlowModBuilder { ...@@ -154,6 +157,9 @@ public class FlowModBuilderVer13 extends FlowModBuilder {
154 if (treatment.tableTransition() != null) { 157 if (treatment.tableTransition() != null) {
155 instructions.add(buildTableGoto(treatment.tableTransition())); 158 instructions.add(buildTableGoto(treatment.tableTransition()));
156 } 159 }
160 + if (treatment.writeMetadata() != null) {
161 + instructions.add(buildMetadata(treatment.writeMetadata()));
162 + }
157 163
158 long cookie = flowRule().id().value(); 164 long cookie = flowRule().id().value();
159 165
...@@ -247,6 +253,12 @@ public class FlowModBuilderVer13 extends FlowModBuilder { ...@@ -247,6 +253,12 @@ public class FlowModBuilderVer13 extends FlowModBuilder {
247 return instruction; 253 return instruction;
248 } 254 }
249 255
256 + private OFInstruction buildMetadata(Instructions.MetadataInstruction m) {
257 + OFInstruction instruction = factory().instructions().writeMetadata(
258 + U64.of(m.metadata()), U64.of(m.metadataMask()));
259 + return instruction;
260 + }
261 +
250 private OFAction buildL0Modification(Instruction i) { 262 private OFAction buildL0Modification(Instruction i) {
251 L0ModificationInstruction l0m = (L0ModificationInstruction) i; 263 L0ModificationInstruction l0m = (L0ModificationInstruction) i;
252 switch (l0m.subtype()) { 264 switch (l0m.subtype()) {
......