blob: d7ebbd82ea765641f8189f533b4feff2f5e64cd2 [file] [log] [blame]
/*
* Copyright 2014 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.onlab.onos.provider.of.flow.impl;
import static org.slf4j.LoggerFactory.getLogger;
import java.util.List;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.PortNumber;
import org.onlab.onos.net.flow.DefaultFlowEntry;
import org.onlab.onos.net.flow.DefaultFlowRule;
import org.onlab.onos.net.flow.DefaultTrafficSelector;
import org.onlab.onos.net.flow.DefaultTrafficTreatment;
import org.onlab.onos.net.flow.FlowEntry;
import org.onlab.onos.net.flow.FlowEntry.FlowEntryState;
import org.onlab.onos.net.flow.FlowRule;
import org.onlab.onos.net.flow.TrafficSelector;
import org.onlab.onos.net.flow.TrafficTreatment;
import org.onlab.onos.openflow.controller.Dpid;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.Ip4Prefix;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import org.projectfloodlight.openflow.protocol.OFFlowRemoved;
import org.projectfloodlight.openflow.protocol.OFFlowStatsEntry;
import org.projectfloodlight.openflow.protocol.OFInstructionType;
import org.projectfloodlight.openflow.protocol.action.OFAction;
import org.projectfloodlight.openflow.protocol.action.OFActionCircuit;
import org.projectfloodlight.openflow.protocol.action.OFActionExperimenter;
import org.projectfloodlight.openflow.protocol.action.OFActionOutput;
import org.projectfloodlight.openflow.protocol.action.OFActionSetDlDst;
import org.projectfloodlight.openflow.protocol.action.OFActionSetDlSrc;
import org.projectfloodlight.openflow.protocol.action.OFActionSetNwDst;
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.OFInstructionWriteActions;
import org.projectfloodlight.openflow.protocol.match.Match;
import org.projectfloodlight.openflow.protocol.match.MatchField;
import org.projectfloodlight.openflow.protocol.oxm.OFOxmOchSigidBasic;
import org.projectfloodlight.openflow.types.IPv4Address;
import org.projectfloodlight.openflow.types.Masked;
import org.slf4j.Logger;
import com.google.common.collect.Lists;
public class FlowEntryBuilder {
private final Logger log = getLogger(getClass());
private final OFFlowStatsEntry stat;
private final OFFlowRemoved removed;
private final Match match;
private final List<OFAction> actions;
private final Dpid dpid;
private final boolean addedRule;
public FlowEntryBuilder(Dpid dpid, OFFlowStatsEntry entry) {
this.stat = entry;
this.match = entry.getMatch();
this.actions = getActions(entry);
this.dpid = dpid;
this.removed = null;
this.addedRule = true;
}
public FlowEntryBuilder(Dpid dpid, OFFlowRemoved removed) {
this.match = removed.getMatch();
this.removed = removed;
this.dpid = dpid;
this.actions = null;
this.stat = null;
this.addedRule = false;
}
public FlowEntry build() {
if (addedRule) {
FlowRule rule = new DefaultFlowRule(DeviceId.deviceId(Dpid.uri(dpid)),
buildSelector(), buildTreatment(), stat.getPriority(),
stat.getCookie().getValue(), stat.getIdleTimeout(), false);
return new DefaultFlowEntry(rule, FlowEntryState.ADDED,
stat.getDurationSec(), stat.getPacketCount().getValue(),
stat.getByteCount().getValue());
} else {
FlowRule rule = new DefaultFlowRule(DeviceId.deviceId(Dpid.uri(dpid)),
buildSelector(), null, removed.getPriority(),
removed.getCookie().getValue(), removed.getIdleTimeout(), false);
return new DefaultFlowEntry(rule, FlowEntryState.REMOVED, removed.getDurationSec(),
removed.getPacketCount().getValue(), removed.getByteCount().getValue());
}
}
private List<OFAction> getActions(OFFlowStatsEntry entry) {
switch (entry.getVersion()) {
case OF_10:
return entry.getActions();
case OF_11:
case OF_12:
case OF_13:
List<OFInstruction> ins = entry.getInstructions();
for (OFInstruction in : ins) {
if (in.getType().equals(OFInstructionType.WRITE_ACTIONS)) {
OFInstructionWriteActions apply = (OFInstructionWriteActions) in;
return apply.getActions();
}
}
return Lists.newLinkedList();
default:
log.warn("Unknown OF version {}", entry.getVersion());
}
return Lists.newLinkedList();
}
private TrafficTreatment buildTreatment() {
TrafficTreatment.Builder builder = DefaultTrafficTreatment.builder();
// If this is a drop rule
if (actions.size() == 0) {
builder.drop();
return builder.build();
}
for (OFAction act : actions) {
switch (act.getType()) {
case OUTPUT:
OFActionOutput out = (OFActionOutput) act;
builder.setOutput(
PortNumber.portNumber(out.getPort().getPortNumber()));
break;
case SET_VLAN_VID:
OFActionSetVlanVid vlan = (OFActionSetVlanVid) act;
builder.setVlanId(VlanId.vlanId(vlan.getVlanVid().getVlan()));
break;
case SET_VLAN_PCP:
OFActionSetVlanPcp pcp = (OFActionSetVlanPcp) act;
builder.setVlanId(VlanId.vlanId(pcp.getVlanPcp().getValue()));
break;
case SET_DL_DST:
OFActionSetDlDst dldst = (OFActionSetDlDst) act;
builder.setEthDst(
MacAddress.valueOf(dldst.getDlAddr().getLong()));
break;
case SET_DL_SRC:
OFActionSetDlSrc dlsrc = (OFActionSetDlSrc) act;
builder.setEthSrc(
MacAddress.valueOf(dlsrc.getDlAddr().getLong()));
break;
case SET_NW_DST:
OFActionSetNwDst nwdst = (OFActionSetNwDst) act;
IPv4Address di = nwdst.getNwAddr();
builder.setIpDst(Ip4Address.valueOf(di.getInt()));
break;
case SET_NW_SRC:
OFActionSetNwSrc nwsrc = (OFActionSetNwSrc) act;
IPv4Address si = nwsrc.getNwAddr();
builder.setIpSrc(Ip4Address.valueOf(si.getInt()));
break;
case EXPERIMENTER:
OFActionExperimenter exp = (OFActionExperimenter) act;
if (exp.getExperimenter() == 0x80005A06) {
OFActionCircuit ct = (OFActionCircuit) exp;
builder.setLambda(((OFOxmOchSigidBasic) ct.getField()).getValue().getChannelNumber());
} else {
log.warn("Unsupported OFActionExperimenter {}", exp.getExperimenter());
}
break;
case SET_TP_DST:
case SET_TP_SRC:
case POP_MPLS:
case POP_PBB:
case POP_VLAN:
case PUSH_MPLS:
case PUSH_PBB:
case PUSH_VLAN:
case SET_FIELD:
case SET_MPLS_LABEL:
case SET_MPLS_TC:
case SET_MPLS_TTL:
case SET_NW_ECN:
case SET_NW_TOS:
case SET_NW_TTL:
case SET_QUEUE:
case STRIP_VLAN:
case COPY_TTL_IN:
case COPY_TTL_OUT:
case DEC_MPLS_TTL:
case DEC_NW_TTL:
case ENQUEUE:
case GROUP:
default:
log.warn("Action type {} not yet implemented.", act.getType());
}
}
return builder.build();
}
private TrafficSelector buildSelector() {
TrafficSelector.Builder builder = DefaultTrafficSelector.builder();
for (MatchField<?> field : match.getMatchFields()) {
switch (field.id) {
case IN_PORT:
builder.matchInport(PortNumber
.portNumber(match.get(MatchField.IN_PORT).getPortNumber()));
break;
case ETH_SRC:
MacAddress sMac = MacAddress.valueOf(match.get(MatchField.ETH_SRC).getLong());
builder.matchEthSrc(sMac);
break;
case ETH_DST:
MacAddress dMac = MacAddress.valueOf(match.get(MatchField.ETH_DST).getLong());
builder.matchEthDst(dMac);
break;
case ETH_TYPE:
int ethType = match.get(MatchField.ETH_TYPE).getValue();
builder.matchEthType((short) ethType);
break;
case IPV4_DST:
Ip4Prefix dip;
if (match.isPartiallyMasked(MatchField.IPV4_DST)) {
Masked<IPv4Address> maskedIp = match.getMasked(MatchField.IPV4_DST);
dip = Ip4Prefix.valueOf(
maskedIp.getValue().getInt(),
maskedIp.getMask().asCidrMaskLength());
} else {
dip = Ip4Prefix.valueOf(
match.get(MatchField.IPV4_DST).getInt(),
Ip4Prefix.MAX_MASK_LENGTH);
}
builder.matchIPDst(dip);
break;
case IPV4_SRC:
Ip4Prefix sip;
if (match.isPartiallyMasked(MatchField.IPV4_SRC)) {
Masked<IPv4Address> maskedIp = match.getMasked(MatchField.IPV4_SRC);
sip = Ip4Prefix.valueOf(
maskedIp.getValue().getInt(),
maskedIp.getMask().asCidrMaskLength());
} else {
sip = Ip4Prefix.valueOf(
match.get(MatchField.IPV4_SRC).getInt(),
Ip4Prefix.MAX_MASK_LENGTH);
}
builder.matchIPSrc(sip);
break;
case IP_PROTO:
short proto = match.get(MatchField.IP_PROTO).getIpProtocolNumber();
builder.matchIPProtocol((byte) proto);
break;
case VLAN_PCP:
byte vlanPcp = match.get(MatchField.VLAN_PCP).getValue();
builder.matchVlanPcp(vlanPcp);
break;
case VLAN_VID:
VlanId vlanId = VlanId.vlanId(match.get(MatchField.VLAN_VID).getVlan());
builder.matchVlanId(vlanId);
break;
case TCP_DST:
builder.matchTcpDst((short) match.get(MatchField.TCP_DST).getPort());
break;
case TCP_SRC:
builder.matchTcpSrc((short) match.get(MatchField.TCP_SRC).getPort());
break;
case MPLS_LABEL:
builder.matchMplsLabel((int) match.get(MatchField.MPLS_LABEL)
.getValue());
break;
case OCH_SIGID:
builder.matchLambda(match.get(MatchField.OCH_SIGID).getChannelNumber());
break;
case OCH_SIGTYPE:
builder.matchOpticalSignalType(match.get(MatchField
.OCH_SIGTYPE).getValue());
break;
case ARP_OP:
case ARP_SHA:
case ARP_SPA:
case ARP_THA:
case ARP_TPA:
case ICMPV4_CODE:
case ICMPV4_TYPE:
case ICMPV6_CODE:
case ICMPV6_TYPE:
case IN_PHY_PORT:
case IPV6_DST:
case IPV6_FLABEL:
case IPV6_ND_SLL:
case IPV6_ND_TARGET:
case IPV6_ND_TLL:
case IPV6_SRC:
case IP_DSCP:
case IP_ECN:
case METADATA:
case MPLS_TC:
case SCTP_DST:
case SCTP_SRC:
case TUNNEL_ID:
case UDP_DST:
case UDP_SRC:
default:
log.warn("Match type {} not yet implemented.", field.id);
}
}
return builder.build();
}
}