Jonathan Hart

Change the way 1.3 flow mods are built to support rewrite actions.

Change-Id: I9c1c3059822b19d0665702162dee9904f95127d8
......@@ -201,7 +201,7 @@ public final class DefaultTrafficTreatment implements TrafficTreatment {
@Override
public TrafficTreatment build() {
//If we are dropping should we just return an emptry list?
//If we are dropping should we just return an empty list?
List<Instruction> instructions = new LinkedList<Instruction>();
instructions.addAll(modifications);
instructions.addAll(groups);
......
......@@ -33,7 +33,7 @@ import org.projectfloodlight.openflow.protocol.action.OFActionSetNwSrc;
import org.projectfloodlight.openflow.protocol.action.OFActionSetVlanPcp;
import org.projectfloodlight.openflow.protocol.action.OFActionSetVlanVid;
import org.projectfloodlight.openflow.protocol.instruction.OFInstruction;
import org.projectfloodlight.openflow.protocol.instruction.OFInstructionApplyActions;
import org.projectfloodlight.openflow.protocol.instruction.OFInstructionWriteActions;
import org.projectfloodlight.openflow.protocol.match.Match;
import org.projectfloodlight.openflow.protocol.match.MatchField;
import org.projectfloodlight.openflow.protocol.oxm.OFOxmOchSigidBasic;
......@@ -104,8 +104,8 @@ public class FlowEntryBuilder {
case OF_13:
List<OFInstruction> ins = entry.getInstructions();
for (OFInstruction in : ins) {
if (in.getType().equals(OFInstructionType.APPLY_ACTIONS)) {
OFInstructionApplyActions apply = (OFInstructionApplyActions) in;
if (in.getType().equals(OFInstructionType.WRITE_ACTIONS)) {
OFInstructionWriteActions apply = (OFInstructionWriteActions) in;
return apply.getActions();
}
}
......
package org.onlab.onos.provider.of.flow.impl;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import org.onlab.onos.net.flow.FlowRule;
import org.onlab.onos.net.flow.TrafficTreatment;
import org.onlab.onos.net.flow.instructions.Instruction;
import org.onlab.onos.net.flow.instructions.Instructions.OutputInstruction;
import org.onlab.onos.net.flow.instructions.L2ModificationInstruction;
import org.onlab.onos.net.flow.instructions.L2ModificationInstruction.ModEtherInstruction;
import org.onlab.onos.net.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction;
import org.onlab.onos.net.flow.instructions.L2ModificationInstruction.ModVlanPcpInstruction;
import org.onlab.onos.net.flow.instructions.L3ModificationInstruction;
import org.onlab.onos.net.flow.instructions.L3ModificationInstruction.ModIPInstruction;
import org.projectfloodlight.openflow.protocol.OFFactory;
import org.projectfloodlight.openflow.protocol.OFFlowAdd;
import org.projectfloodlight.openflow.protocol.OFFlowDelete;
import org.projectfloodlight.openflow.protocol.OFFlowMod;
import org.projectfloodlight.openflow.protocol.OFFlowModFlags;
import org.projectfloodlight.openflow.protocol.action.OFAction;
import org.projectfloodlight.openflow.protocol.match.Match;
import org.projectfloodlight.openflow.types.IPv4Address;
import org.projectfloodlight.openflow.types.MacAddress;
import org.projectfloodlight.openflow.types.OFBufferId;
import org.projectfloodlight.openflow.types.OFPort;
import org.projectfloodlight.openflow.types.U64;
import org.projectfloodlight.openflow.types.VlanPcp;
import org.projectfloodlight.openflow.types.VlanVid;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Flow mod builder for OpenFlow 1.0.
*/
public class FlowModBuilderVer10 extends FlowModBuilder {
private static final Logger log = LoggerFactory.getLogger(FlowModBuilderVer10.class);
private final TrafficTreatment treatment;
/**
* Constructor for a flow mod builder for OpenFlow 1.0.
*
* @param flowRule the flow rule to transform into a flow mod
* @param factory the OpenFlow factory to use to build the flow mod
*/
protected FlowModBuilderVer10(FlowRule flowRule, OFFactory factory) {
super(flowRule, factory);
this.treatment = flowRule.treatment();
}
@Override
public OFFlowAdd buildFlowAdd() {
Match match = buildMatch();
List<OFAction> actions = buildActions();
long cookie = flowRule().id().value();
//TODO: what to do without bufferid? do we assume that there will be a pktout as well?
OFFlowAdd fm = factory().buildFlowAdd()
.setXid(cookie)
.setCookie(U64.of(cookie))
.setBufferId(OFBufferId.NO_BUFFER)
.setActions(actions)
.setMatch(match)
.setFlags(Collections.singleton(OFFlowModFlags.SEND_FLOW_REM))
.setPriority(flowRule().priority())
.build();
return fm;
}
@Override
public OFFlowMod buildFlowMod() {
Match match = buildMatch();
List<OFAction> actions = buildActions();
long cookie = flowRule().id().value();
//TODO: what to do without bufferid? do we assume that there will be a pktout as well?
OFFlowMod fm = factory().buildFlowModify()
.setXid(cookie)
.setCookie(U64.of(cookie))
.setBufferId(OFBufferId.NO_BUFFER)
.setActions(actions)
.setMatch(match)
.setFlags(Collections.singleton(OFFlowModFlags.SEND_FLOW_REM))
.setPriority(flowRule().priority())
.build();
return fm;
}
@Override
public OFFlowDelete buildFlowDel() {
Match match = buildMatch();
List<OFAction> actions = buildActions();
long cookie = flowRule().id().value();
OFFlowDelete fm = factory().buildFlowDelete()
.setXid(cookie)
.setCookie(U64.of(cookie))
.setBufferId(OFBufferId.NO_BUFFER)
.setActions(actions)
.setMatch(match)
.setFlags(Collections.singleton(OFFlowModFlags.SEND_FLOW_REM))
.setPriority(flowRule().priority())
.build();
return fm;
}
private List<OFAction> buildActions() {
List<OFAction> acts = new LinkedList<>();
if (treatment == null) {
return acts;
}
for (Instruction i : treatment.instructions()) {
switch (i.type()) {
case DROP:
log.warn("Saw drop action; assigning drop action");
return new LinkedList<>();
case L2MODIFICATION:
acts.add(buildL2Modification(i));
break;
case L3MODIFICATION:
acts.add(buildL3Modification(i));
break;
case OUTPUT:
OutputInstruction out = (OutputInstruction) i;
acts.add(factory().actions().buildOutput().setPort(
OFPort.of((int) out.port().toLong())).build());
break;
case L0MODIFICATION:
case GROUP:
log.warn("Instruction type {} not supported with protocol version {}",
i.type(), factory().getVersion());
break;
default:
log.warn("Instruction type {} not yet implemented.", i.type());
}
}
return acts;
}
private OFAction buildL3Modification(Instruction i) {
L3ModificationInstruction l3m = (L3ModificationInstruction) i;
ModIPInstruction ip;
switch (l3m.subtype()) {
case IP_DST:
ip = (ModIPInstruction) i;
return factory().actions().setNwDst(IPv4Address.of(ip.ip().toInt()));
case IP_SRC:
ip = (ModIPInstruction) i;
return factory().actions().setNwSrc(IPv4Address.of(ip.ip().toInt()));
default:
log.warn("Unimplemented action type {}.", l3m.subtype());
break;
}
return null;
}
private OFAction buildL2Modification(Instruction i) {
L2ModificationInstruction l2m = (L2ModificationInstruction) i;
ModEtherInstruction eth;
switch (l2m.subtype()) {
case ETH_DST:
eth = (ModEtherInstruction) l2m;
return factory().actions().setDlDst(MacAddress.of(eth.mac().toLong()));
case ETH_SRC:
eth = (ModEtherInstruction) l2m;
return factory().actions().setDlSrc(MacAddress.of(eth.mac().toLong()));
case VLAN_ID:
ModVlanIdInstruction vlanId = (ModVlanIdInstruction) l2m;
return factory().actions().setVlanVid(VlanVid.ofVlan(vlanId.vlanId.toShort()));
case VLAN_PCP:
ModVlanPcpInstruction vlanPcp = (ModVlanPcpInstruction) l2m;
return factory().actions().setVlanPcp(VlanPcp.of(vlanPcp.vlanPcp()));
default:
log.warn("Unimplemented action type {}.", l2m.subtype());
break;
}
return null;
}
}
package org.onlab.onos.provider.of.flow.impl;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import org.onlab.onos.net.flow.FlowRule;
import org.onlab.onos.net.flow.TrafficTreatment;
import org.onlab.onos.net.flow.instructions.Instruction;
import org.onlab.onos.net.flow.instructions.Instructions.OutputInstruction;
import org.onlab.onos.net.flow.instructions.L0ModificationInstruction;
import org.onlab.onos.net.flow.instructions.L0ModificationInstruction.ModLambdaInstruction;
import org.onlab.onos.net.flow.instructions.L2ModificationInstruction;
import org.onlab.onos.net.flow.instructions.L2ModificationInstruction.ModEtherInstruction;
import org.onlab.onos.net.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction;
import org.onlab.onos.net.flow.instructions.L2ModificationInstruction.ModVlanPcpInstruction;
import org.onlab.onos.net.flow.instructions.L3ModificationInstruction;
import org.onlab.onos.net.flow.instructions.L3ModificationInstruction.ModIPInstruction;
import org.projectfloodlight.openflow.protocol.OFFactory;
import org.projectfloodlight.openflow.protocol.OFFlowAdd;
import org.projectfloodlight.openflow.protocol.OFFlowDelete;
import org.projectfloodlight.openflow.protocol.OFFlowMod;
import org.projectfloodlight.openflow.protocol.OFFlowModFlags;
import org.projectfloodlight.openflow.protocol.action.OFAction;
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;
import org.projectfloodlight.openflow.types.IPv4Address;
import org.projectfloodlight.openflow.types.MacAddress;
import org.projectfloodlight.openflow.types.OFBufferId;
import org.projectfloodlight.openflow.types.OFPort;
import org.projectfloodlight.openflow.types.OFVlanVidMatch;
import org.projectfloodlight.openflow.types.U64;
import org.projectfloodlight.openflow.types.VlanPcp;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Flow mod builder for OpenFlow 1.3+.
*/
public class FlowModBuilderVer13 extends FlowModBuilder {
private static final Logger log = LoggerFactory.getLogger(FlowModBuilderVer10.class);
private final TrafficTreatment treatment;
/**
* Constructor for a flow mod builder for OpenFlow 1.3.
*
* @param flowRule the flow rule to transform into a flow mod
* @param factory the OpenFlow factory to use to build the flow mod
*/
protected FlowModBuilderVer13(FlowRule flowRule, OFFactory factory) {
super(flowRule, factory);
this.treatment = flowRule.treatment();
}
@Override
public OFFlowAdd buildFlowAdd() {
Match match = buildMatch();
OFInstruction writeActions =
factory().instructions().writeActions(buildActions());
long cookie = flowRule().id().value();
//TODO: what to do without bufferid? do we assume that there will be a pktout as well?
OFFlowAdd fm = factory().buildFlowAdd()
.setXid(cookie)
.setCookie(U64.of(cookie))
.setBufferId(OFBufferId.NO_BUFFER)
.setInstructions(Collections.singletonList(writeActions))
.setMatch(match)
.setFlags(Collections.singleton(OFFlowModFlags.SEND_FLOW_REM))
.setPriority(flowRule().priority())
.build();
return fm;
}
@Override
public OFFlowMod buildFlowMod() {
Match match = buildMatch();
OFInstruction writeActions =
factory().instructions().writeActions(buildActions());
long cookie = flowRule().id().value();
//TODO: what to do without bufferid? do we assume that there will be a pktout as well?
OFFlowMod fm = factory().buildFlowModify()
.setXid(cookie)
.setCookie(U64.of(cookie))
.setBufferId(OFBufferId.NO_BUFFER)
.setInstructions(Collections.singletonList(writeActions))
.setMatch(match)
.setFlags(Collections.singleton(OFFlowModFlags.SEND_FLOW_REM))
.setPriority(flowRule().priority())
.build();
return fm;
}
@Override
public OFFlowDelete buildFlowDel() {
Match match = buildMatch();
OFInstruction writeActions =
factory().instructions().writeActions(buildActions());
long cookie = flowRule().id().value();
OFFlowDelete fm = factory().buildFlowDelete()
.setXid(cookie)
.setCookie(U64.of(cookie))
.setBufferId(OFBufferId.NO_BUFFER)
.setInstructions(Collections.singletonList(writeActions))
.setMatch(match)
.setFlags(Collections.singleton(OFFlowModFlags.SEND_FLOW_REM))
.setPriority(flowRule().priority())
.build();
return fm;
}
private List<OFAction> buildActions() {
List<OFAction> actions = new LinkedList<>();
if (treatment == null) {
return actions;
}
for (Instruction i : treatment.instructions()) {
switch (i.type()) {
case DROP:
log.warn("Saw drop action; assigning drop action");
return new LinkedList<>();
case L0MODIFICATION:
actions.add(buildL0Modification(i));
break;
case L2MODIFICATION:
actions.add(buildL2Modification(i));
break;
case L3MODIFICATION:
actions.add(buildL3Modification(i));
break;
case OUTPUT:
OutputInstruction out = (OutputInstruction) i;
actions.add(factory().actions().buildOutput().setPort(
OFPort.of((int) out.port().toLong())).build());
break;
case GROUP:
default:
log.warn("Instruction type {} not yet implemented.", i.type());
}
}
return actions;
}
private OFAction buildL0Modification(Instruction i) {
L0ModificationInstruction l0m = (L0ModificationInstruction) i;
switch (l0m.subtype()) {
case LAMBDA:
ModLambdaInstruction ml = (ModLambdaInstruction) i;
return factory().actions().circuit(factory().oxms().ochSigidBasic(
new CircuitSignalID((byte) 1, (byte) 2, ml.lambda(), (short) 1)));
default:
log.warn("Unimplemented action type {}.", l0m.subtype());
break;
}
return null;
}
private OFAction buildL2Modification(Instruction i) {
L2ModificationInstruction l2m = (L2ModificationInstruction) i;
ModEtherInstruction eth;
OFOxm<?> oxm = null;
switch (l2m.subtype()) {
case ETH_DST:
eth = (ModEtherInstruction) l2m;
oxm = factory().oxms().ethDst(MacAddress.of(eth.mac().toLong()));
break;
case ETH_SRC:
eth = (ModEtherInstruction) l2m;
oxm = factory().oxms().ethSrc(MacAddress.of(eth.mac().toLong()));
break;
case VLAN_ID:
ModVlanIdInstruction vlanId = (ModVlanIdInstruction) l2m;
oxm = factory().oxms().vlanVid(OFVlanVidMatch.ofVlan(vlanId.vlanId.toShort()));
break;
case VLAN_PCP:
ModVlanPcpInstruction vlanPcp = (ModVlanPcpInstruction) l2m;
oxm = factory().oxms().vlanPcp(VlanPcp.of(vlanPcp.vlanPcp));
break;
default:
log.warn("Unimplemented action type {}.", l2m.subtype());
break;
}
if (oxm != null) {
return factory().actions().buildSetField().setField(oxm).build();
}
return null;
}
private OFAction buildL3Modification(Instruction i) {
L3ModificationInstruction l3m = (L3ModificationInstruction) i;
ModIPInstruction ip;
OFOxm<?> oxm = null;
switch (l3m.subtype()) {
case IP_DST:
ip = (ModIPInstruction) i;
oxm = factory().oxms().ipv4Dst(IPv4Address.of(ip.ip().toInt()));
case IP_SRC:
ip = (ModIPInstruction) i;
oxm = factory().oxms().ipv4Src(IPv4Address.of(ip.ip().toInt()));
default:
log.warn("Unimplemented action type {}.", l3m.subtype());
break;
}
if (oxm != null) {
return factory().actions().buildSetField().setField(oxm).build();
}
return null;
}
}
......@@ -22,6 +22,7 @@ import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.onlab.onos.ApplicationId;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.flow.BatchOperation;
import org.onlab.onos.net.flow.CompletedBatchOperation;
import org.onlab.onos.net.flow.DefaultFlowEntry;
import org.onlab.onos.net.flow.FlowEntry;
......@@ -31,7 +32,6 @@ import org.onlab.onos.net.flow.FlowRuleBatchEntry.FlowRuleOperation;
import org.onlab.onos.net.flow.FlowRuleProvider;
import org.onlab.onos.net.flow.FlowRuleProviderRegistry;
import org.onlab.onos.net.flow.FlowRuleProviderService;
import org.onlab.onos.net.flow.BatchOperation;
import org.onlab.onos.net.provider.AbstractProvider;
import org.onlab.onos.net.provider.ProviderId;
import org.onlab.onos.net.topology.TopologyService;
......@@ -148,7 +148,7 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr
private void applyRule(FlowRule flowRule) {
OpenFlowSwitch sw = controller.getSwitch(Dpid.dpid(flowRule.deviceId().uri()));
sw.sendMsg(new FlowModBuilder(flowRule, sw.factory()).buildFlowAdd());
sw.sendMsg(FlowModBuilder.builder(flowRule, sw.factory()).buildFlowAdd());
}
......@@ -163,7 +163,7 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr
private void removeRule(FlowRule flowRule) {
OpenFlowSwitch sw = controller.getSwitch(Dpid.dpid(flowRule.deviceId().uri()));
sw.sendMsg(new FlowModBuilder(flowRule, sw.factory()).buildFlowDel());
sw.sendMsg(FlowModBuilder.builder(flowRule, sw.factory()).buildFlowDel());
}
@Override
......@@ -192,7 +192,7 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr
return failed;
}
sws.add(new Dpid(sw.getId()));
FlowModBuilder builder = new FlowModBuilder(flowRule, sw.factory());
FlowModBuilder builder = FlowModBuilder.builder(flowRule, sw.factory());
switch (fbe.getOperator()) {
case ADD:
mod = builder.buildFlowAdd();
......