Steffen Gebert
Committed by Gerrit Code Review

Implement OFActionEnqueue (OpenFlow 1.0 only)

Realize the QUEUE Treatment using OpenFlow 1.0 Enqueue action.

The ConnectivityIntentCommand's --setQueue parameter is extended by a notion of
<port>/<queue> to support the difference from OpenFlow 1.3 Set-Queue, which is
not bound to a port.

Change-Id: I28cf70a7c004a1a3a14361e5186cfe42f09f1356
......@@ -33,6 +33,7 @@ import org.onosproject.cli.AbstractShellCommand;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.net.Link;
import org.onosproject.net.PortNumber;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.TrafficSelector;
......@@ -166,7 +167,8 @@ public abstract class ConnectivityIntentCommand extends AbstractShellCommand {
required = false, multiValued = false)
private String pushVlan = null;
@Option(name = "--setQueue", description = "Set Queue ID",
@Option(name = "--setQueue", description = "Set Queue ID (for OpenFlow 1.0, " +
"also the port has to be specified, i.e., <port>/<queue>",
required = false, multiValued = false)
private String setQueue = null;
......@@ -332,7 +334,15 @@ public abstract class ConnectivityIntentCommand extends AbstractShellCommand {
emptyTreatment = false;
}
if (!isNullOrEmpty(setQueue)) {
treatmentBuilder.setQueue(Long.parseLong(setQueue));
// OpenFlow 1.0 notation (for ENQUEUE): <port>/<queue>
if (setQueue.contains("/")) {
String[] queueConfig = setQueue.split("/");
PortNumber port = PortNumber.portNumber(Long.parseLong(queueConfig[0]));
long queueId = Long.parseLong(queueConfig[1]);
treatmentBuilder.setQueue(queueId, port);
} else {
treatmentBuilder.setQueue(Long.parseLong(setQueue));
}
emptyTreatment = false;
}
......
......@@ -388,7 +388,12 @@ public final class DefaultTrafficTreatment implements TrafficTreatment {
@Override
public Builder setQueue(long queueId) {
return add(Instructions.setQueue(queueId));
return add(Instructions.setQueue(queueId, null));
}
@Override
public Builder setQueue(long queueId, PortNumber port) {
return add(Instructions.setQueue(queueId, port));
}
@Override
......
......@@ -271,6 +271,15 @@ public interface TrafficTreatment {
Builder setQueue(long queueId);
/**
* Sets the Queue ID for a specific port.
*
* @param queueId a queue ID
* @param port a port number
* @return a treatment builder
*/
Builder setQueue(long queueId, PortNumber port);
/**
* Sets a meter to be used by this flow.
*
* @param meterId a meter id
......
......@@ -15,6 +15,7 @@
*/
package org.onosproject.net.flow.instructions;
import com.google.common.base.MoreObjects;
import org.onlab.packet.EthType;
import org.onlab.packet.IpAddress;
import org.onlab.packet.MacAddress;
......@@ -99,11 +100,12 @@ public final class Instructions {
* Creates a set-queue instruction.
*
* @param queueId Queue Id
* @param port Port number
* @return set-queue instruction
*/
public static SetQueueInstruction setQueue(final long queueId) {
public static SetQueueInstruction setQueue(final long queueId, final PortNumber port) {
checkNotNull(queueId, "queue ID cannot be null");
return new SetQueueInstruction(queueId);
return new SetQueueInstruction(queueId, port);
}
public static MeterInstruction meterTraffic(final MeterId meterId) {
......@@ -655,15 +657,26 @@ public final class Instructions {
*/
public static final class SetQueueInstruction implements Instruction {
private final long queueId;
private final PortNumber port;
private SetQueueInstruction(long queueId) {
this.queueId = queueId;
this.port = null;
}
private SetQueueInstruction(long queueId, PortNumber port) {
this.queueId = queueId;
this.port = port;
}
public long queueId() {
return queueId;
}
public PortNumber port() {
return port;
}
@Override
public Type type() {
return Type.QUEUE;
......@@ -671,13 +684,18 @@ public final class Instructions {
@Override
public String toString() {
return toStringHelper(type().toString())
.add("queueId", queueId).toString();
MoreObjects.ToStringHelper toStringHelper = toStringHelper(type().toString());
toStringHelper.add("queueId", queueId);
if (port() != null) {
toStringHelper.add("port", port);
}
return toStringHelper.toString();
}
@Override
public int hashCode() {
return Objects.hash(type().ordinal(), queueId);
return Objects.hash(type().ordinal(), queueId, port);
}
@Override
......@@ -687,7 +705,7 @@ public final class Instructions {
}
if (obj instanceof SetQueueInstruction) {
SetQueueInstruction that = (SetQueueInstruction) obj;
return Objects.equals(queueId, that.queueId);
return Objects.equals(queueId, that.queueId) && Objects.equals(port, that.port);
}
return false;
......
......@@ -50,6 +50,7 @@ import org.projectfloodlight.openflow.protocol.OFFlowRemoved;
import org.projectfloodlight.openflow.protocol.OFFlowStatsEntry;
import org.projectfloodlight.openflow.protocol.action.OFAction;
import org.projectfloodlight.openflow.protocol.action.OFActionCircuit;
import org.projectfloodlight.openflow.protocol.action.OFActionEnqueue;
import org.projectfloodlight.openflow.protocol.action.OFActionExperimenter;
import org.projectfloodlight.openflow.protocol.action.OFActionGroup;
import org.projectfloodlight.openflow.protocol.action.OFActionOutput;
......@@ -346,6 +347,10 @@ public class FlowEntryBuilder {
OFActionSetQueue setQueue = (OFActionSetQueue) act;
builder.setQueue(setQueue.getQueueId());
break;
case ENQUEUE:
OFActionEnqueue enqueue = (OFActionEnqueue) act;
builder.setQueue(enqueue.getQueueId(), PortNumber.portNumber(enqueue.getPort().getPortNumber()));
break;
case STRIP_VLAN:
case POP_VLAN:
builder.popVlan();
......@@ -364,7 +369,6 @@ public class FlowEntryBuilder {
case SET_NW_TOS:
case SET_NW_TTL:
case ENQUEUE:
default:
log.warn("Action type {} not yet implemented.", act.getType());
}
......
......@@ -22,6 +22,7 @@ import org.onosproject.net.flow.FlowRule;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.flow.instructions.Instruction;
import org.onosproject.net.flow.instructions.Instructions.OutputInstruction;
import org.onosproject.net.flow.instructions.Instructions.SetQueueInstruction;
import org.onosproject.net.flow.instructions.L2ModificationInstruction;
import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModEtherInstruction;
import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction;
......@@ -35,6 +36,7 @@ import org.projectfloodlight.openflow.protocol.OFFlowMod;
import org.projectfloodlight.openflow.protocol.OFFlowModFlags;
import org.projectfloodlight.openflow.protocol.action.OFAction;
import org.projectfloodlight.openflow.protocol.action.OFActionOutput;
import org.projectfloodlight.openflow.protocol.action.OFActionEnqueue;
import org.projectfloodlight.openflow.protocol.match.Match;
import org.projectfloodlight.openflow.types.IPv4Address;
import org.projectfloodlight.openflow.types.MacAddress;
......@@ -167,6 +169,16 @@ public class FlowModBuilderVer10 extends FlowModBuilder {
}
acts.add(action.build());
break;
case QUEUE:
SetQueueInstruction queue = (SetQueueInstruction) i;
if (queue.port() == null) {
log.warn("Required argument 'port' undefined for OFActionEnqueue");
}
OFActionEnqueue.Builder queueBuilder = factory().actions().buildEnqueue()
.setQueueId(queue.queueId())
.setPort(OFPort.ofInt((int) queue.port().toLong()));
acts.add(queueBuilder.build());
break;
case L0MODIFICATION:
case GROUP:
case TABLE:
......