alshabib
Committed by Gerrit Code Review

support for corsa pipeline. EXPERIMENTAL.

Change-Id: Ic3db0a7a18f11c41c8a84f25a249dfb63109da97
......@@ -249,6 +249,11 @@ public final class DefaultTrafficTreatment implements TrafficTreatment {
}
@Override
public TrafficTreatment.Builder transition(FlowRule.Type type) {
return add(Instructions.transition(type));
}
@Override
public TrafficTreatment build() {
//If we are dropping should we just return an empty list?
......
......@@ -40,7 +40,19 @@ public interface FlowRule {
/* Used in flow entry for MPLS table */
MPLS,
/* Used in flow entry for ACL table */
ACL
ACL,
/* VLAN-to-MPLS table */
VLAN_MPLS,
/* VLAN table */
VLAN,
/* L2 table */
ETHER,
/* Class of Service table */
COS,
}
//TODO: build cookie value
......
......@@ -195,6 +195,15 @@ public interface TrafficTreatment {
*/
public Builder group(GroupId groupId);
/**
* Sets the next table type to transition to.
*
* @param type the table type
* @return a treatement builder
*/
public Builder transition(FlowRule.Type type);
/**
* Builds an immutable traffic treatment descriptor.
*
......
......@@ -50,6 +50,11 @@ public interface Instruction {
L2MODIFICATION,
/**
* Signifies that the traffic should be passed to another table.
*/
TABLE,
/**
* Signifies that the traffic should be modified in L3 way.
*/
L3MODIFICATION
......
......@@ -23,6 +23,7 @@ import java.util.Objects;
import org.onosproject.core.GroupId;
import org.onosproject.net.PortNumber;
import org.onosproject.net.flow.FlowRule;
import org.onosproject.net.flow.instructions.L0ModificationInstruction.L0SubType;
import org.onosproject.net.flow.instructions.L0ModificationInstruction.ModLambdaInstruction;
import org.onosproject.net.flow.instructions.L2ModificationInstruction.L2SubType;
......@@ -254,6 +255,11 @@ public final class Instructions {
return new PushHeaderInstructions(L2SubType.MPLS_POP, etherType);
}
public static Instruction transition(FlowRule.Type type) {
checkNotNull(type, "Table type cannot be null");
return new TableTypeTransition(type);
}
/*
* Drop instructions
*/
......@@ -352,6 +358,7 @@ public final class Instructions {
public Type type() {
return Type.GROUP;
}
@Override
public String toString() {
return toStringHelper(type().toString())
......@@ -377,6 +384,49 @@ public final class Instructions {
}
}
// FIXME: Temporary support for this. This should probably become it's own
// type like other instructions.
public static class TableTypeTransition implements Instruction {
private final FlowRule.Type tableType;
public TableTypeTransition(FlowRule.Type type) {
this.tableType = type;
}
@Override
public Type type() {
return Type.TABLE;
}
public FlowRule.Type tableType() {
return this.tableType;
}
@Override
public String toString() {
return toStringHelper(type().toString())
.add("group ID", this.tableType).toString();
}
@Override
public int hashCode() {
return Objects.hash(type(), tableType);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof TableTypeTransition) {
TableTypeTransition that = (TableTypeTransition) obj;
return Objects.equals(tableType, that.tableType);
}
return false;
}
}
}
......
......@@ -32,6 +32,18 @@ public interface OpenFlowSwitch {
* It is used only for multi-table support switch.
*/
public static enum TableType {
/* VLAN-to-MPLS table */
VLAN_MPLS,
/* VLAN table */
VLAN,
/* L2 table */
ETHER,
/* Class of Service table */
COS,
/* IP table */
IP,
/* MPLS table */
......@@ -40,6 +52,8 @@ public interface OpenFlowSwitch {
ACL,
/* Single table */
NONE,
}
/**
......
......@@ -406,4 +406,6 @@ public abstract class AbstractOpenFlowSwitch implements OpenFlowSwitchDriver {
return false;
}
}
......
/*
* Copyright 2015 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.openflow.drivers;
import com.google.common.collect.Lists;
import org.onosproject.openflow.controller.Dpid;
import org.onosproject.openflow.controller.RoleState;
import org.onosproject.openflow.controller.driver.AbstractOpenFlowSwitch;
import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
import org.projectfloodlight.openflow.protocol.OFFlowMod;
import org.projectfloodlight.openflow.protocol.OFMessage;
import org.projectfloodlight.openflow.protocol.OFType;
import org.projectfloodlight.openflow.protocol.instruction.OFInstruction;
import org.projectfloodlight.openflow.protocol.instruction.OFInstructionGotoTable;
import org.projectfloodlight.openflow.types.TableId;
import java.util.Collections;
import java.util.List;
/**
* Corsa switch driver for BGP Router deployment.
*/
public class OFCorsaSwitchDriver extends AbstractOpenFlowSwitch {
private static final int VLAN_MPLS_TABLE = 1;
private static final int VLAN_TABLE = 2;
private static final int MPLS_TABLE = 3;
private static final int ETHER_TABLE = 4;
private static final int COS_MAP_TABLE = 5;
private static final int FIB_TABLE = 6;
private static final int LOCAL_TABLE = 9;
OFCorsaSwitchDriver(Dpid dpid, OFDescStatsReply desc) {
super(dpid);
setSwitchDescription(desc);
}
@Override
public void write(OFMessage msg) {
this.write(Collections.singletonList(msg));
}
@Override
public void write(List<OFMessage> msgs) {
if (role == RoleState.MASTER) {
channel.write(msgs);
}
}
@Override
public void sendMsg(OFMessage msg, TableType type) {
if (msg.getType() == OFType.FLOW_MOD) {
OFFlowMod flowMod = (OFFlowMod) msg;
OFFlowMod.Builder builder = flowMod.createBuilder();
List<OFInstruction> instructions = builder.getInstructions();
List<OFInstruction> newInstructions = Lists.newArrayList();
for (OFInstruction i : instructions) {
if (i instanceof OFInstructionGotoTable) {
OFInstructionGotoTable gotoTable = (OFInstructionGotoTable) i;
TableType tid = TableType.values()[gotoTable.getTableId().getValue()];
switch (tid) {
case VLAN_MPLS:
newInstructions.add(
gotoTable.createBuilder()
.setTableId(TableId.of(VLAN_MPLS_TABLE)).build());
break;
case VLAN:
newInstructions.add(
gotoTable.createBuilder()
.setTableId(TableId.of(VLAN_TABLE)).build());
break;
case ETHER:
newInstructions.add(
gotoTable.createBuilder()
.setTableId(TableId.of(ETHER_TABLE)).build());
break;
case COS:
newInstructions.add(
gotoTable.createBuilder()
.setTableId(TableId.of(COS_MAP_TABLE)).build());
break;
case IP:
newInstructions.add(
gotoTable.createBuilder()
.setTableId(TableId.of(FIB_TABLE)).build());
break;
case MPLS:
newInstructions.add(
gotoTable.createBuilder()
.setTableId(TableId.of(MPLS_TABLE)).build());
break;
case ACL:
newInstructions.add(
gotoTable.createBuilder()
.setTableId(TableId.of(LOCAL_TABLE)).build());
break;
case NONE:
newInstructions.add(
gotoTable.createBuilder()
.setTableId(TableId.of(0)).build());
break;
default:
log.warn("Unknown table type: {}", tid);
}
} else {
newInstructions.add(i);
}
}
switch (type) {
case VLAN_MPLS:
builder.setTableId(TableId.of(VLAN_MPLS_TABLE));
break;
case VLAN:
builder.setTableId(TableId.of(VLAN_TABLE));
break;
case ETHER:
builder.setTableId(TableId.of(ETHER_TABLE));
break;
case COS:
builder.setTableId(TableId.of(COS_MAP_TABLE));
break;
case IP:
builder.setTableId(TableId.of(FIB_TABLE));
break;
case MPLS:
builder.setTableId(TableId.of(MPLS_TABLE));
break;
case ACL:
builder.setTableId(TableId.of(LOCAL_TABLE));
break;
case NONE:
builder.setTableId(TableId.of(0));
break;
default:
log.warn("Unknown table type: {}", type);
}
this.write(builder.build());
} else {
this.write(msg);
}
}
@Override
public Boolean supportNxRole() {
return false;
}
@Override
public void startDriverHandshake() {}
@Override
public boolean isDriverHandshakeComplete() {
return true;
}
@Override
public void processDriverHandshakeMessage(OFMessage m) {}
}
......@@ -25,10 +25,6 @@ import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.criteria.Criteria;
import org.onosproject.net.flow.criteria.Criteria.EthCriterion;
import org.onosproject.net.flow.criteria.Criteria.EthTypeCriterion;
import org.onosproject.net.flow.criteria.Criteria.IcmpCodeCriterion;
import org.onosproject.net.flow.criteria.Criteria.IcmpTypeCriterion;
import org.onosproject.net.flow.criteria.Criteria.Icmpv6CodeCriterion;
import org.onosproject.net.flow.criteria.Criteria.Icmpv6TypeCriterion;
import org.onosproject.net.flow.criteria.Criteria.IPCriterion;
import org.onosproject.net.flow.criteria.Criteria.IPDscpCriterion;
import org.onosproject.net.flow.criteria.Criteria.IPEcnCriterion;
......@@ -36,6 +32,10 @@ import org.onosproject.net.flow.criteria.Criteria.IPProtocolCriterion;
import org.onosproject.net.flow.criteria.Criteria.IPv6FlowLabelCriterion;
import org.onosproject.net.flow.criteria.Criteria.IPv6NDLinkLayerAddressCriterion;
import org.onosproject.net.flow.criteria.Criteria.IPv6NDTargetAddressCriterion;
import org.onosproject.net.flow.criteria.Criteria.IcmpCodeCriterion;
import org.onosproject.net.flow.criteria.Criteria.IcmpTypeCriterion;
import org.onosproject.net.flow.criteria.Criteria.Icmpv6CodeCriterion;
import org.onosproject.net.flow.criteria.Criteria.Icmpv6TypeCriterion;
import org.onosproject.net.flow.criteria.Criteria.LambdaCriterion;
import org.onosproject.net.flow.criteria.Criteria.MetadataCriterion;
import org.onosproject.net.flow.criteria.Criteria.PortCriterion;
......@@ -99,7 +99,8 @@ public abstract class FlowModBuilder {
* @return the new flow mod builder
*/
public static FlowModBuilder builder(FlowRule flowRule,
OFFactory factory, Optional<Long> xid) {
OFFactory factory,
Optional<Long> xid) {
switch (factory.getVersion()) {
case OF_10:
return new FlowModBuilderVer10(flowRule, factory, xid);
......
......@@ -21,8 +21,9 @@ import org.onosproject.net.PortNumber;
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;
import org.onosproject.net.flow.instructions.Instructions.GroupInstruction;
import org.onosproject.net.flow.instructions.Instructions.OutputInstruction;
import org.onosproject.net.flow.instructions.L0ModificationInstruction;
import org.onosproject.net.flow.instructions.L0ModificationInstruction.ModLambdaInstruction;
import org.onosproject.net.flow.instructions.L2ModificationInstruction;
......@@ -34,6 +35,7 @@ import org.onosproject.net.flow.instructions.L2ModificationInstruction.PushHeade
import org.onosproject.net.flow.instructions.L3ModificationInstruction;
import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModIPInstruction;
import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModIPv6FlowLabelInstruction;
import org.onosproject.openflow.controller.OpenFlowSwitch;
import org.projectfloodlight.openflow.protocol.OFFactory;
import org.projectfloodlight.openflow.protocol.OFFlowAdd;
import org.projectfloodlight.openflow.protocol.OFFlowDelete;
......@@ -42,6 +44,7 @@ import org.projectfloodlight.openflow.protocol.OFFlowModFlags;
import org.projectfloodlight.openflow.protocol.action.OFAction;
import org.projectfloodlight.openflow.protocol.action.OFActionGroup;
import org.projectfloodlight.openflow.protocol.action.OFActionOutput;
import org.projectfloodlight.openflow.protocol.instruction.OFInstruction;
import org.projectfloodlight.openflow.protocol.match.Match;
import org.projectfloodlight.openflow.protocol.oxm.OFOxm;
import org.projectfloodlight.openflow.types.CircuitSignalID;
......@@ -54,6 +57,7 @@ import org.projectfloodlight.openflow.types.OFBufferId;
import org.projectfloodlight.openflow.types.OFGroup;
import org.projectfloodlight.openflow.types.OFPort;
import org.projectfloodlight.openflow.types.OFVlanVidMatch;
import org.projectfloodlight.openflow.types.TableId;
import org.projectfloodlight.openflow.types.U32;
import org.projectfloodlight.openflow.types.U64;
import org.projectfloodlight.openflow.types.VlanPcp;
......@@ -92,7 +96,7 @@ public class FlowModBuilderVer13 extends FlowModBuilder {
public OFFlowAdd buildFlowAdd() {
Match match = buildMatch();
List<OFAction> actions = buildActions();
List<OFInstruction> instructions = buildInstructions();
// FIXME had to revert back to using apply-actions instead of
// write-actions because LINC-OE apparently doesn't support
// write-actions. I would prefer to change this back in the future
......@@ -109,7 +113,7 @@ public class FlowModBuilderVer13 extends FlowModBuilder {
.setCookie(U64.of(cookie))
.setBufferId(OFBufferId.NO_BUFFER)
.setActions(actions)
//.setInstructions(Collections.singletonList(writeActions))
.setInstructions(instructions)
.setMatch(match)
.setFlags(Collections.singleton(OFFlowModFlags.SEND_FLOW_REM))
.setPriority(flowRule().priority())
......@@ -122,6 +126,7 @@ public class FlowModBuilderVer13 extends FlowModBuilder {
public OFFlowMod buildFlowMod() {
Match match = buildMatch();
List<OFAction> actions = buildActions();
List<OFInstruction> instructions = buildInstructions();
//OFInstruction writeActions =
//factory().instructions().writeActions(actions);
......@@ -133,7 +138,7 @@ public class FlowModBuilderVer13 extends FlowModBuilder {
.setCookie(U64.of(cookie))
.setBufferId(OFBufferId.NO_BUFFER)
.setActions(actions)
//.setInstructions(Collections.singletonList(writeActions))
.setInstructions(instructions)
.setMatch(match)
.setFlags(Collections.singleton(OFFlowModFlags.SEND_FLOW_REM))
.setPriority(flowRule().priority())
......@@ -145,7 +150,6 @@ public class FlowModBuilderVer13 extends FlowModBuilder {
@Override
public OFFlowDelete buildFlowDel() {
Match match = buildMatch();
List<OFAction> actions = buildActions();
long cookie = flowRule().id().value();
......@@ -161,6 +165,24 @@ public class FlowModBuilderVer13 extends FlowModBuilder {
return fm;
}
private List<OFInstruction> buildInstructions() {
List<OFInstruction> instructions = new LinkedList<>();
if (treatment == null) {
return instructions;
}
for (Instruction i : treatment.instructions()) {
switch (i.type()) {
case TABLE:
instructions.add(buildTableGoto(((Instructions.TableTypeTransition) i)));
break;
default:
break;
}
}
return instructions;
}
private List<OFAction> buildActions() {
List<OFAction> actions = new LinkedList<>();
if (treatment == null) {
......@@ -203,6 +225,38 @@ public class FlowModBuilderVer13 extends FlowModBuilder {
return actions;
}
private OFInstruction buildTableGoto(Instructions.TableTypeTransition i) {
OFInstruction instruction = factory().instructions().gotoTable(
TableId.of(getTableType(i.tableType()).ordinal()));
return instruction;
}
// FIXME: this has to go as well perhaps when we implement the SelectorService.
private OpenFlowSwitch.TableType getTableType(FlowRule.Type type) {
switch (type) {
case DEFAULT:
return OpenFlowSwitch.TableType.NONE;
case IP:
return OpenFlowSwitch.TableType.IP;
case MPLS:
return OpenFlowSwitch.TableType.MPLS;
case ACL:
return OpenFlowSwitch.TableType.ACL;
case VLAN_MPLS:
return OpenFlowSwitch.TableType.VLAN_MPLS;
case VLAN:
return OpenFlowSwitch.TableType.VLAN;
case ETHER:
return OpenFlowSwitch.TableType.ETHER;
case COS:
return OpenFlowSwitch.TableType.COS;
default:
return OpenFlowSwitch.TableType.NONE;
}
}
private OFAction buildL0Modification(Instruction i) {
L0ModificationInstruction l0m = (L0ModificationInstruction) i;
switch (l0m.subtype()) {
......
......@@ -159,8 +159,10 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr
sw.sendMsg(FlowModBuilder.builder(flowRule, sw.factory(),
Optional.empty()).buildFlowAdd());
} else {
OpenFlowSwitch.TableType type = getTableType(flowRule.type());
sw.sendMsg(FlowModBuilder.builder(flowRule, sw.factory(),
Optional.empty()).buildFlowAdd(), getTableType(flowRule.type()));
Optional.empty()).buildFlowAdd(),
type);
}
}
......@@ -230,12 +232,23 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr
private OpenFlowSwitch.TableType getTableType(FlowRule.Type type) {
switch (type) {
case DEFAULT:
return OpenFlowSwitch.TableType.NONE;
case IP:
return OpenFlowSwitch.TableType.IP;
case MPLS:
return OpenFlowSwitch.TableType.MPLS;
case ACL:
return OpenFlowSwitch.TableType.ACL;
case VLAN_MPLS:
return OpenFlowSwitch.TableType.VLAN_MPLS;
case VLAN:
return OpenFlowSwitch.TableType.VLAN;
case ETHER:
return OpenFlowSwitch.TableType.ETHER;
case COS:
return OpenFlowSwitch.TableType.COS;
default:
return OpenFlowSwitch.TableType.NONE;
}
......