Steffen Gebert
Committed by Gerrit Code Review

Implement OFActionSetQueue (OpenFlow 1.3 only)

Action "Set-Queue" (OFPAT_SET_QUEUE) is not yet implemented.

This patch adds such a QUEUE Treatment and implements it using the Set-Queue
action of OpenFlow 1.3.

The --setQueue parameter can be used when defining intents so that flows with
the respective Set-Queue action are installed.

This includes contributions by Michael Jarschel and Arne Schwabe and is the
result of our ONOS Hackaton project at EWSDN 2015.

Change-Id: Ie7bf01e8fd90fe68977477327ac4f53d7930e186
...@@ -166,6 +166,10 @@ public abstract class ConnectivityIntentCommand extends AbstractShellCommand { ...@@ -166,6 +166,10 @@ public abstract class ConnectivityIntentCommand extends AbstractShellCommand {
166 required = false, multiValued = false) 166 required = false, multiValued = false)
167 private String pushVlan = null; 167 private String pushVlan = null;
168 168
169 + @Option(name = "--setQueue", description = "Set Queue ID",
170 + required = false, multiValued = false)
171 + private String setQueue = null;
172 +
169 // Priorities 173 // Priorities
170 @Option(name = "-p", aliases = "--priority", description = "Priority", 174 @Option(name = "-p", aliases = "--priority", description = "Priority",
171 required = false, multiValued = false) 175 required = false, multiValued = false)
...@@ -327,6 +331,10 @@ public abstract class ConnectivityIntentCommand extends AbstractShellCommand { ...@@ -327,6 +331,10 @@ public abstract class ConnectivityIntentCommand extends AbstractShellCommand {
327 treatmentBuilder.setVlanId(VlanId.vlanId(Short.parseShort(pushVlan))); 331 treatmentBuilder.setVlanId(VlanId.vlanId(Short.parseShort(pushVlan)));
328 emptyTreatment = false; 332 emptyTreatment = false;
329 } 333 }
334 + if (!isNullOrEmpty(setQueue)) {
335 + treatmentBuilder.setQueue(Long.parseLong(setQueue));
336 + emptyTreatment = false;
337 + }
330 338
331 if (emptyTreatment) { 339 if (emptyTreatment) {
332 return DefaultTrafficTreatment.emptyTreatment(); 340 return DefaultTrafficTreatment.emptyTreatment();
......
...@@ -237,6 +237,7 @@ public final class DefaultTrafficTreatment implements TrafficTreatment { ...@@ -237,6 +237,7 @@ public final class DefaultTrafficTreatment implements TrafficTreatment {
237 case NOACTION: 237 case NOACTION:
238 case OUTPUT: 238 case OUTPUT:
239 case GROUP: 239 case GROUP:
240 + case QUEUE:
240 case L0MODIFICATION: 241 case L0MODIFICATION:
241 case L2MODIFICATION: 242 case L2MODIFICATION:
242 case L3MODIFICATION: 243 case L3MODIFICATION:
...@@ -381,6 +382,11 @@ public final class DefaultTrafficTreatment implements TrafficTreatment { ...@@ -381,6 +382,11 @@ public final class DefaultTrafficTreatment implements TrafficTreatment {
381 } 382 }
382 383
383 @Override 384 @Override
385 + public Builder setQueue(long queueId) {
386 + return add(Instructions.setQueue(queueId));
387 + }
388 +
389 + @Override
384 public TrafficTreatment.Builder meter(MeterId meterId) { 390 public TrafficTreatment.Builder meter(MeterId meterId) {
385 return add(Instructions.meterTraffic(meterId)); 391 return add(Instructions.meterTraffic(meterId));
386 } 392 }
......
...@@ -261,6 +261,14 @@ public interface TrafficTreatment { ...@@ -261,6 +261,14 @@ public interface TrafficTreatment {
261 Builder group(GroupId groupId); 261 Builder group(GroupId groupId);
262 262
263 /** 263 /**
264 + * Sets the Queue ID.
265 + *
266 + * @param queueId a queue ID
267 + * @return a treatment builder
268 + */
269 + Builder setQueue(long queueId);
270 +
271 + /**
264 * Sets a meter to be used by this flow. 272 * Sets a meter to be used by this flow.
265 * 273 *
266 * @param meterId a meter id 274 * @param meterId a meter id
......
...@@ -49,6 +49,12 @@ public interface Instruction { ...@@ -49,6 +49,12 @@ public interface Instruction {
49 GROUP, 49 GROUP,
50 50
51 /** 51 /**
52 + * Signifies that the traffic should be enqueued to an already-configured
53 + queue on a port.
54 + */
55 + QUEUE,
56 +
57 + /**
52 * Signifies that traffic should be metered according to a meter. 58 * Signifies that traffic should be metered according to a meter.
53 */ 59 */
54 METER, 60 METER,
......
...@@ -94,6 +94,17 @@ public final class Instructions { ...@@ -94,6 +94,17 @@ public final class Instructions {
94 return new GroupInstruction(groupId); 94 return new GroupInstruction(groupId);
95 } 95 }
96 96
97 + /**
98 + * Creates a set-queue instruction.
99 + *
100 + * @param queueId Queue Id
101 + * @return set-queue instruction
102 + */
103 + public static SetQueueInstruction setQueue(final long queueId) {
104 + checkNotNull(queueId, "queue ID cannot be null");
105 + return new SetQueueInstruction(queueId);
106 + }
107 +
97 public static MeterInstruction meterTraffic(final MeterId meterId) { 108 public static MeterInstruction meterTraffic(final MeterId meterId) {
98 checkNotNull(meterId, "meter id cannot be null"); 109 checkNotNull(meterId, "meter id cannot be null");
99 return new MeterInstruction(meterId); 110 return new MeterInstruction(meterId);
...@@ -625,6 +636,50 @@ public final class Instructions { ...@@ -625,6 +636,50 @@ public final class Instructions {
625 } 636 }
626 637
627 /** 638 /**
639 + * Set-Queue Instruction.
640 + */
641 + public static final class SetQueueInstruction implements Instruction {
642 + private final long queueId;
643 +
644 + private SetQueueInstruction(long queueId) {
645 + this.queueId = queueId;
646 + }
647 +
648 + public long queueId() {
649 + return queueId;
650 + }
651 +
652 + @Override
653 + public Type type() {
654 + return Type.QUEUE;
655 + }
656 +
657 + @Override
658 + public String toString() {
659 + return toStringHelper(type().toString())
660 + .add("queueId", queueId).toString();
661 + }
662 +
663 + @Override
664 + public int hashCode() {
665 + return Objects.hash(type().ordinal(), queueId);
666 + }
667 +
668 + @Override
669 + public boolean equals(Object obj) {
670 + if (this == obj) {
671 + return true;
672 + }
673 + if (obj instanceof SetQueueInstruction) {
674 + SetQueueInstruction that = (SetQueueInstruction) obj;
675 + return Objects.equals(queueId, that.queueId);
676 +
677 + }
678 + return false;
679 + }
680 + }
681 +
682 + /**
628 * A meter instruction. 683 * A meter instruction.
629 */ 684 */
630 public static final class MeterInstruction implements Instruction { 685 public static final class MeterInstruction implements Instruction {
......
...@@ -55,6 +55,7 @@ import org.projectfloodlight.openflow.protocol.action.OFActionCircuit; ...@@ -55,6 +55,7 @@ import org.projectfloodlight.openflow.protocol.action.OFActionCircuit;
55 import org.projectfloodlight.openflow.protocol.action.OFActionExperimenter; 55 import org.projectfloodlight.openflow.protocol.action.OFActionExperimenter;
56 import org.projectfloodlight.openflow.protocol.action.OFActionGroup; 56 import org.projectfloodlight.openflow.protocol.action.OFActionGroup;
57 import org.projectfloodlight.openflow.protocol.action.OFActionOutput; 57 import org.projectfloodlight.openflow.protocol.action.OFActionOutput;
58 +import org.projectfloodlight.openflow.protocol.action.OFActionSetQueue;
58 import org.projectfloodlight.openflow.protocol.action.OFActionPopMpls; 59 import org.projectfloodlight.openflow.protocol.action.OFActionPopMpls;
59 import org.projectfloodlight.openflow.protocol.action.OFActionSetDlDst; 60 import org.projectfloodlight.openflow.protocol.action.OFActionSetDlDst;
60 import org.projectfloodlight.openflow.protocol.action.OFActionSetDlSrc; 61 import org.projectfloodlight.openflow.protocol.action.OFActionSetDlSrc;
...@@ -333,6 +334,10 @@ public class FlowEntryBuilder { ...@@ -333,6 +334,10 @@ public class FlowEntryBuilder {
333 OFActionGroup group = (OFActionGroup) act; 334 OFActionGroup group = (OFActionGroup) act;
334 builder.group(new DefaultGroupId(group.getGroup().getGroupNumber())); 335 builder.group(new DefaultGroupId(group.getGroup().getGroupNumber()));
335 break; 336 break;
337 + case SET_QUEUE:
338 + OFActionSetQueue setQueue = (OFActionSetQueue) act;
339 + builder.setQueue(setQueue.getQueueId());
340 + break;
336 case STRIP_VLAN: 341 case STRIP_VLAN:
337 case POP_VLAN: 342 case POP_VLAN:
338 builder.popVlan(); 343 builder.popVlan();
...@@ -350,7 +355,6 @@ public class FlowEntryBuilder { ...@@ -350,7 +355,6 @@ public class FlowEntryBuilder {
350 case SET_NW_ECN: 355 case SET_NW_ECN:
351 case SET_NW_TOS: 356 case SET_NW_TOS:
352 case SET_NW_TTL: 357 case SET_NW_TTL:
353 - case SET_QUEUE:
354 358
355 case ENQUEUE: 359 case ENQUEUE:
356 default: 360 default:
......
...@@ -26,6 +26,7 @@ import org.onosproject.net.flow.instructions.Instruction; ...@@ -26,6 +26,7 @@ import org.onosproject.net.flow.instructions.Instruction;
26 import org.onosproject.net.flow.instructions.Instructions; 26 import org.onosproject.net.flow.instructions.Instructions;
27 import org.onosproject.net.flow.instructions.Instructions.GroupInstruction; 27 import org.onosproject.net.flow.instructions.Instructions.GroupInstruction;
28 import org.onosproject.net.flow.instructions.Instructions.OutputInstruction; 28 import org.onosproject.net.flow.instructions.Instructions.OutputInstruction;
29 +import org.onosproject.net.flow.instructions.Instructions.SetQueueInstruction;
29 import org.onosproject.net.flow.instructions.L0ModificationInstruction; 30 import org.onosproject.net.flow.instructions.L0ModificationInstruction;
30 import org.onosproject.net.flow.instructions.L0ModificationInstruction.ModLambdaInstruction; 31 import org.onosproject.net.flow.instructions.L0ModificationInstruction.ModLambdaInstruction;
31 import org.onosproject.net.flow.instructions.L0ModificationInstruction.ModOchSignalInstruction; 32 import org.onosproject.net.flow.instructions.L0ModificationInstruction.ModOchSignalInstruction;
...@@ -50,6 +51,7 @@ import org.projectfloodlight.openflow.protocol.OFFlowModFlags; ...@@ -50,6 +51,7 @@ import org.projectfloodlight.openflow.protocol.OFFlowModFlags;
50 import org.projectfloodlight.openflow.protocol.action.OFAction; 51 import org.projectfloodlight.openflow.protocol.action.OFAction;
51 import org.projectfloodlight.openflow.protocol.action.OFActionGroup; 52 import org.projectfloodlight.openflow.protocol.action.OFActionGroup;
52 import org.projectfloodlight.openflow.protocol.action.OFActionOutput; 53 import org.projectfloodlight.openflow.protocol.action.OFActionOutput;
54 +import org.projectfloodlight.openflow.protocol.action.OFActionSetQueue;
53 import org.projectfloodlight.openflow.protocol.instruction.OFInstruction; 55 import org.projectfloodlight.openflow.protocol.instruction.OFInstruction;
54 import org.projectfloodlight.openflow.protocol.match.Match; 56 import org.projectfloodlight.openflow.protocol.match.Match;
55 import org.projectfloodlight.openflow.protocol.oxm.OFOxm; 57 import org.projectfloodlight.openflow.protocol.oxm.OFOxm;
...@@ -244,6 +246,12 @@ public class FlowModBuilderVer13 extends FlowModBuilder { ...@@ -244,6 +246,12 @@ public class FlowModBuilderVer13 extends FlowModBuilder {
244 .setGroup(OFGroup.of(group.groupId().id())); 246 .setGroup(OFGroup.of(group.groupId().id()));
245 actions.add(groupBuilder.build()); 247 actions.add(groupBuilder.build());
246 break; 248 break;
249 + case QUEUE:
250 + SetQueueInstruction queue = (SetQueueInstruction) i;
251 + OFActionSetQueue.Builder queueBuilder = factory().actions().buildSetQueue()
252 + .setQueueId(queue.queueId());
253 + actions.add(queueBuilder.build());
254 + break;
247 case TABLE: 255 case TABLE:
248 //FIXME: should not occur here. 256 //FIXME: should not occur here.
249 tableFound = true; 257 tableFound = true;
......