Hyunsun Moon

TUNNEL_ID field support in flow matching and actions

Change-Id: I886123a7c8d57dc4a3e12727ec8a9be4920da79e
......@@ -294,6 +294,11 @@ public final class DefaultTrafficSelector implements TrafficSelector {
}
@Override
public TrafficSelector.Builder matchTunnelId(long tunnelId) {
return add(Criteria.matchTunnelId(tunnelId));
}
@Override
public Builder matchIPv6ExthdrFlags(short exthdrFlags) {
return add(Criteria.matchIPv6ExthdrFlags(exthdrFlags));
}
......
......@@ -385,6 +385,11 @@ public final class DefaultTrafficTreatment implements TrafficTreatment {
}
@Override
public Builder setTunnelId(long tunnelId) {
return add(Instructions.modTunnelId(tunnelId));
}
@Override
public TrafficTreatment build() {
//Don't add DROP instruction by default when instruction
//set is empty. This will be handled in DefaultSingleTablePipeline
......
......@@ -301,6 +301,14 @@ public interface TrafficSelector {
Builder matchMplsLabel(MplsLabel mplsLabel);
/**
* Matches a tunnel id.
*
* @param tunnelId a tunnel id
* @return a selection builder
*/
Builder matchTunnelId(long tunnelId);
/**
* Matches on IPv6 Extension Header pseudo-field flags.
*
* @param exthdrFlags the IPv6 Extension Header pseudo-field flags
......
......@@ -311,6 +311,14 @@ public interface TrafficTreatment {
Builder writeMetadata(long value, long mask);
/**
* Sets the tunnel id.
*
* @param tunnelId a tunnel id.
* @return a treatment builder.
*/
Builder setTunnelId(long tunnelId);
/**
* Builds an immutable traffic treatment descriptor.
* <p>
* If the treatment is empty when build() is called, it will add a default
......
......@@ -356,6 +356,16 @@ public final class Criteria {
}
/**
* Creates a match on Tunnel ID.
*
* @param tunnelId Tunnel ID (64 bits)
* @return match criterion
*/
public static Criterion matchTunnelId(long tunnelId) {
return new TunnelIdCriterion(tunnelId);
}
/**
* Creates a match on IPv6 Extension Header pseudo-field fiags.
* Those are defined in Criterion.IPv6ExthdrFlags.
*
......
/*
* 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.net.flow.criteria;
import java.util.Objects;
import static com.google.common.base.MoreObjects.toStringHelper;
/**
* Implementation of Tunnel ID criterion.
*/
public class TunnelIdCriterion implements Criterion {
private final long tunnelId;
/**
* Constructor.
*
* @param tunnelId a Tunnel ID to match(64 bits)
*/
TunnelIdCriterion(long tunnelId) {
this.tunnelId = tunnelId;
}
@Override
public Type type() {
return Type.TUNNEL_ID;
}
/**
* Gets the Tunnel ID to match.
*
* @return the Tunnel ID to match (64 bits)
*/
public long tunnelId() {
return tunnelId;
}
@Override
public String toString() {
return toStringHelper(type().toString())
.add("tunnelId", Long.toHexString(tunnelId))
.toString();
}
@Override
public int hashCode() {
return Objects.hash(type().ordinal(), tunnelId);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof TunnelIdCriterion) {
TunnelIdCriterion that = (TunnelIdCriterion) obj;
return Objects.equals(tunnelId, that.tunnelId) &&
Objects.equals(this.type(), that.type());
}
return false;
}
}
......@@ -350,6 +350,17 @@ public final class Instructions {
}
/**
* Creates a Tunnel ID modification.
*
* @param tunnelId the Tunnel ID to modify to
* @return a L2 modification
*/
public static L2ModificationInstruction modTunnelId(long tunnelId) {
checkNotNull(tunnelId, "Tunnel id cannot be null");
return new L2ModificationInstruction.ModTunnelIdInstruction(tunnelId);
}
/**
* Drop instruction.
*/
public static final class DropInstruction implements Instruction {
......
......@@ -81,7 +81,12 @@ public abstract class L2ModificationInstruction implements Instruction {
/**
* VLAN Push modification.
*/
VLAN_PUSH
VLAN_PUSH,
/**
* Tunnle id modification.
*/
TUNNEL_ID
}
// TODO: Create factory class 'Instructions' that will have various factory
......@@ -401,4 +406,50 @@ public abstract class L2ModificationInstruction implements Instruction {
return false;
}
}
/**
* Represents a Tunnel id modification.
*/
public static final class ModTunnelIdInstruction
extends L2ModificationInstruction {
private final long tunnelId;
ModTunnelIdInstruction(long tunnelId) {
this.tunnelId = tunnelId;
}
public long tunnelId() {
return this.tunnelId;
}
@Override
public L2SubType subtype() {
return L2SubType.TUNNEL_ID;
}
@Override
public String toString() {
return toStringHelper(subtype().toString())
.add("id", Long.toHexString(tunnelId))
.toString();
}
@Override
public int hashCode() {
return Objects.hash(type(), subtype(), tunnelId);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof ModTunnelIdInstruction) {
ModTunnelIdInstruction that = (ModTunnelIdInstruction) obj;
return Objects.equals(tunnelId, that.tunnelId);
}
return false;
}
}
}
......
......@@ -198,6 +198,12 @@ public class CriteriaTest {
Criterion sameAsMatchMpls1 = Criteria.matchMplsLabel(mpls1);
Criterion matchMpls2 = Criteria.matchMplsLabel(mpls2);
long tunnelId1 = 1;
long tunnelId2 = 2;
Criterion matchTunnelId1 = Criteria.matchTunnelId(tunnelId1);
Criterion sameAsMatchTunnelId1 = Criteria.matchTunnelId(tunnelId1);
Criterion matchTunnelId2 = Criteria.matchTunnelId(tunnelId2);
int ipv6ExthdrFlags1 =
Criterion.IPv6ExthdrFlags.NONEXT.getValue() |
Criterion.IPv6ExthdrFlags.ESP.getValue() |
......@@ -992,6 +998,33 @@ public class CriteriaTest {
.testEquals();
}
// TunnelIdCriterion class
/**
* Test the matchTunnelId method.
*/
@Test
public void testMatchTunnelIdMethod() {
Criterion matchTunnelId = Criteria.matchTunnelId(tunnelId1);
TunnelIdCriterion tunnelIdCriterion =
checkAndConvert(matchTunnelId,
Criterion.Type.TUNNEL_ID,
TunnelIdCriterion.class);
assertThat(tunnelIdCriterion.tunnelId(), is(equalTo(tunnelId1)));
}
/**
* Test the equals() method of the TunnelIdCriterion class.
*/
@Test
public void testTunnelIdCriterionEquals() {
new EqualsTester()
.addEqualityGroup(matchTunnelId1, sameAsMatchTunnelId1)
.addEqualityGroup(matchTunnelId2)
.testEquals();
}
// IPv6ExthdrFlagsCriterion class
/**
......
......@@ -119,6 +119,7 @@ import org.onosproject.net.flow.criteria.OpticalSignalTypeCriterion;
import org.onosproject.net.flow.criteria.PortCriterion;
import org.onosproject.net.flow.criteria.SctpPortCriterion;
import org.onosproject.net.flow.criteria.TcpPortCriterion;
import org.onosproject.net.flow.criteria.TunnelIdCriterion;
import org.onosproject.net.flow.criteria.UdpPortCriterion;
import org.onosproject.net.flow.criteria.VlanIdCriterion;
import org.onosproject.net.flow.criteria.VlanPcpCriterion;
......@@ -320,6 +321,7 @@ public final class KryoNamespaces {
IPv6NDTargetAddressCriterion.class,
IPv6NDLinkLayerAddressCriterion.class,
MplsCriterion.class,
TunnelIdCriterion.class,
IPv6ExthdrFlagsCriterion.class,
LambdaCriterion.class,
IndexedLambdaCriterion.class,
......@@ -346,6 +348,7 @@ public final class KryoNamespaces {
L2ModificationInstruction.PopVlanInstruction.class,
L2ModificationInstruction.ModMplsLabelInstruction.class,
L2ModificationInstruction.ModMplsTtlInstruction.class,
L2ModificationInstruction.ModTunnelIdInstruction.class,
L3ModificationInstruction.class,
L3ModificationInstruction.L3SubType.class,
L3ModificationInstruction.ModIPInstruction.class,
......
......@@ -72,6 +72,7 @@ import org.projectfloodlight.openflow.types.IPv6Address;
import org.projectfloodlight.openflow.types.Masked;
import org.projectfloodlight.openflow.types.OFVlanVidMatch;
import org.projectfloodlight.openflow.types.U32;
import org.projectfloodlight.openflow.types.U64;
import org.projectfloodlight.openflow.types.U8;
import org.projectfloodlight.openflow.types.VlanPcp;
import org.slf4j.Logger;
......@@ -402,6 +403,11 @@ public class FlowEntryBuilder {
OFOxm<U32> labelId = (OFOxm<U32>) oxm;
builder.setMpls(MplsLabel.mplsLabel((int) labelId.getValue().getValue()));
break;
case TUNNEL_ID:
@SuppressWarnings("unchecked")
OFOxm<U64> tunnelId = (OFOxm<U64>) oxm;
builder.setTunnelId(tunnelId.getValue().getValue());
break;
case ARP_OP:
case ARP_SHA:
case ARP_SPA:
......@@ -451,7 +457,6 @@ public class FlowEntryBuilder {
case SCTP_SRC:
case TCP_DST:
case TCP_SRC:
case TUNNEL_ID:
case UDP_DST:
case UDP_SRC:
default:
......@@ -640,7 +645,7 @@ public class FlowEntryBuilder {
break;
case IPV6_EXTHDR:
builder.matchIPv6ExthdrFlags((short) match.get(MatchField.IPV6_EXTHDR)
.getValue());
.getValue());
break;
case OCH_SIGID:
CircuitSignalID sigId = match.get(MatchField.OCH_SIGID);
......@@ -653,13 +658,16 @@ public class FlowEntryBuilder {
U8 sigType = match.get(MatchField.OCH_SIGTYPE);
builder.add(matchOchSignalType(lookupOchSignalType((byte) sigType.getValue())));
break;
case TUNNEL_ID:
long tunnelId = match.get(MatchField.TUNNEL_ID).getValue();
builder.matchTunnelId(tunnelId);
break;
case ARP_OP:
case ARP_SHA:
case ARP_SPA:
case ARP_THA:
case ARP_TPA:
case MPLS_TC:
case TUNNEL_ID:
default:
log.warn("Match type {} not yet implemented.", field.id);
}
......
......@@ -44,6 +44,7 @@ import org.onosproject.net.flow.criteria.OchSignalTypeCriterion;
import org.onosproject.net.flow.criteria.PortCriterion;
import org.onosproject.net.flow.criteria.SctpPortCriterion;
import org.onosproject.net.flow.criteria.TcpPortCriterion;
import org.onosproject.net.flow.criteria.TunnelIdCriterion;
import org.onosproject.net.flow.criteria.UdpPortCriterion;
import org.onosproject.net.flow.criteria.VlanIdCriterion;
import org.onosproject.net.flow.criteria.VlanPcpCriterion;
......@@ -72,6 +73,7 @@ import org.projectfloodlight.openflow.types.OFVlanVidMatch;
import org.projectfloodlight.openflow.types.TransportPort;
import org.projectfloodlight.openflow.types.U16;
import org.projectfloodlight.openflow.types.U32;
import org.projectfloodlight.openflow.types.U64;
import org.projectfloodlight.openflow.types.U8;
import org.projectfloodlight.openflow.types.VlanPcp;
import org.projectfloodlight.openflow.types.VlanVid;
......@@ -392,6 +394,11 @@ public abstract class FlowModBuilder {
byte signalType = OpenFlowValueMapper.lookupOchSignalType(sc.signalType());
mBuilder.setExact(MatchField.OCH_SIGTYPE, U8.of(signalType));
break;
case TUNNEL_ID:
TunnelIdCriterion tunnelId = (TunnelIdCriterion) c;
mBuilder.setExact(MatchField.TUNNEL_ID,
U64.of(tunnelId.tunnelId()));
break;
case ARP_OP:
case ARP_SHA:
case ARP_SPA:
......@@ -400,7 +407,6 @@ public abstract class FlowModBuilder {
case MPLS_BOS:
case MPLS_TC:
case PBB_ISID:
case TUNNEL_ID:
default:
log.warn("Match type {} not yet implemented.", c.type());
}
......
......@@ -35,6 +35,7 @@ import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModMplsLa
import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction;
import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanPcpInstruction;
import org.onosproject.net.flow.instructions.L2ModificationInstruction.PushHeaderInstructions;
import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModTunnelIdInstruction;
import org.onosproject.net.flow.instructions.L3ModificationInstruction;
import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModIPInstruction;
import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModIPv6FlowLabelInstruction;
......@@ -336,6 +337,10 @@ public class FlowModBuilderVer13 extends FlowModBuilder {
PushHeaderInstructions pushVlanInstruction = (PushHeaderInstructions) l2m;
return factory().actions().pushVlan(
EthType.of(pushVlanInstruction.ethernetType().toShort()));
case TUNNEL_ID:
ModTunnelIdInstruction tunnelId = (ModTunnelIdInstruction) l2m;
oxm = factory().oxms().tunnelId(U64.of(tunnelId.tunnelId()));
break;
default:
log.warn("Unimplemented action type {}.", l2m.subtype());
break;
......