alshabib
Committed by Gerrit Code Review

adding a criterion for inner vlans

used by olt to match on the inner vlan

Change-Id: I7671b68d9860d598395cba134a589ca23f264c7e
......@@ -147,7 +147,13 @@ public class Olt
}
provisionVlans(olt.deviceId(), olt.uplink(), port.port(), vlan, olt.vlan(),
olt.defaultVlan());
olt.defaultVlan());
}
@Override
public void removeSubscriber(ConnectPoint port) {
throw new UnsupportedOperationException();
}
private void provisionVlans(DeviceId deviceId, PortNumber uplinkPort,
......@@ -166,6 +172,7 @@ public class Olt
TrafficSelector downstream = DefaultTrafficSelector.builder()
.matchVlanId(deviceVlan)
.matchInPort(uplinkPort)
.matchInnerVlanId(subscriberVlan)
.build();
TrafficTreatment upstreamTreatment = DefaultTrafficTreatment.builder()
......@@ -243,11 +250,6 @@ public class Olt
}
@Override
public void removeSubscriber(ConnectPoint port) {
throw new UnsupportedOperationException("Not yet implemented");
}
private class InternalDeviceListener implements DeviceListener {
@Override
public void event(DeviceEvent event) {
......
......@@ -194,6 +194,16 @@ public final class DefaultTrafficSelector implements TrafficSelector {
}
@Override
public Builder matchInnerVlanId(VlanId vlanId) {
return add(Criteria.matchInnerVlanId(vlanId));
}
@Override
public Builder matchInnerVlanPcp(byte vlanPcp) {
return add(Criteria.matchInnerVlanPcp(vlanPcp));
}
@Override
public Builder matchIPDscp(byte ipDscp) {
return add(Criteria.matchIPDscp(ipDscp));
}
......
......@@ -129,6 +129,22 @@ public interface TrafficSelector {
Builder matchVlanPcp(byte vlanPcp);
/**
* Matches the inner vlan id.
*
* @param vlanId a vlan id
* @return a selection builder
*/
Builder matchInnerVlanId(VlanId vlanId);
/**
* Matches a vlan priority.
*
* @param vlanPcp a vlan priority
* @return a selection builder
*/
Builder matchInnerVlanPcp(byte vlanPcp);
/**
* Matches an IP DSCP (6 bits in ToS field).
*
* @param ipDscp an IP DSCP value
......
......@@ -127,6 +127,16 @@ public final class Criteria {
}
/**
* Creates a match on the inner VLAN ID field using the specified value.
*
* @param vlanId vlan id value
* @return match criterion
*/
public static Criterion matchInnerVlanId(VlanId vlanId) {
return new VlanIdCriterion(vlanId, Type.INNER_VLAN_VID);
}
/**
* Creates a match on VLAN PCP field using the specified value.
*
* @param vlanPcp vlan pcp value (3 bits)
......@@ -137,6 +147,16 @@ public final class Criteria {
}
/**
* Creates a match on the inner VLAN PCP field using the specified value.
*
* @param vlanPcp vlan pcp value (3 bits)
* @return match criterion
*/
public static Criterion matchInnerVlanPcp(byte vlanPcp) {
return new VlanPcpCriterion(vlanPcp, Type.INNER_VLAN_PCP);
}
/**
* Creates a match on IP DSCP field using the specified value.
*
* @param ipDscp ip dscp value (6 bits)
......
......@@ -50,6 +50,20 @@ public interface Criterion {
/** VLAN priority. */
VLAN_PCP,
/**
* Inner VLAN id.
*
* Note: Some drivers may not support this.
*/
INNER_VLAN_VID,
/**
* Inner VLAN pcp.
*
* Note: Some drivers may not support this.
*/
INNER_VLAN_PCP,
/** IP DSCP (6 bits in ToS field). */
IP_DSCP,
......
......@@ -20,12 +20,14 @@ import org.onlab.packet.VlanId;
import java.util.Objects;
import static com.google.common.base.MoreObjects.toStringHelper;
import static com.google.common.base.Preconditions.checkArgument;
/**
* Implementation of VLAN ID criterion.
*/
public final class VlanIdCriterion implements Criterion {
private final VlanId vlanId;
private final Type type;
/**
* Constructor.
......@@ -34,11 +36,26 @@ public final class VlanIdCriterion implements Criterion {
*/
VlanIdCriterion(VlanId vlanId) {
this.vlanId = vlanId;
this.type = Type.VLAN_VID;
}
/**
* Constructs a vlan criterion with a specific type.
*
* @param vlanId a vlan id to match
* @param type a criterion type (only INNER_VLAN_VID and VLAN_ID are supported)
*/
VlanIdCriterion(VlanId vlanId, Type type) {
checkArgument(
type == Type.INNER_VLAN_VID || type == Type.VLAN_VID,
"Type can only be inner vlan or vlan");
this.vlanId = vlanId;
this.type = type;
}
@Override
public Type type() {
return Type.VLAN_VID;
return type;
}
/**
......
......@@ -18,6 +18,7 @@ package org.onosproject.net.flow.criteria;
import java.util.Objects;
import static com.google.common.base.MoreObjects.toStringHelper;
import static com.google.common.base.Preconditions.checkArgument;
/**
* Implementation of VLAN priority criterion (3 bits).
......@@ -25,6 +26,7 @@ import static com.google.common.base.MoreObjects.toStringHelper;
public final class VlanPcpCriterion implements Criterion {
private static final byte MASK = 0x7;
private final byte vlanPcp; // VLAN pcp value: 3 bits
private final Type type;
/**
* Constructor.
......@@ -33,11 +35,26 @@ public final class VlanPcpCriterion implements Criterion {
*/
VlanPcpCriterion(byte vlanPcp) {
this.vlanPcp = (byte) (vlanPcp & MASK);
this.type = Type.VLAN_PCP;
}
/**
* Constructs a vlan priority criterion with a specific type.
*
* @param vlanPcp the VLAN priority to match (3 bits)
* @param type a criterion type (only INNER_VLAN_PCP and VLAN_PCP are supported)
*/
VlanPcpCriterion(byte vlanPcp, Type type) {
checkArgument(
type == Type.INNER_VLAN_PCP || type == Type.VLAN_PCP,
"Type can only be inner vlan or vlan");
this.vlanPcp = (byte) (vlanPcp & MASK);
this.type = type;
}
@Override
public Type type() {
return Type.VLAN_PCP;
return type;
}
/**
......
......@@ -38,6 +38,8 @@ public final class CriterionCodec extends JsonCodec<Criterion> {
protected static final String METADATA = "metadata";
protected static final String VLAN_ID = "vlanId";
protected static final String INNER_VLAN_ID = "innerVlanId";
protected static final String INNER_PRIORITY = "innerPriority";
protected static final String PRIORITY = "priority";
protected static final String IP_DSCP = "ipDscp";
protected static final String IP_ECN = "ipEcn";
......
......@@ -72,6 +72,8 @@ public final class DecodeCriterionCodecHelper {
decoderMap.put(Criterion.Type.ETH_TYPE.name(), new EthTypeDecoder());
decoderMap.put(Criterion.Type.VLAN_VID.name(), new VlanVidDecoder());
decoderMap.put(Criterion.Type.VLAN_PCP.name(), new VlanPcpDecoder());
decoderMap.put(Criterion.Type.INNER_VLAN_VID.name(), new InnerVlanVidDecoder());
decoderMap.put(Criterion.Type.INNER_VLAN_PCP.name(), new InnerVlanPcpDecoder());
decoderMap.put(Criterion.Type.IP_DSCP.name(), new IpDscpDecoder());
decoderMap.put(Criterion.Type.IP_ECN.name(), new IpEcnDecoder());
decoderMap.put(Criterion.Type.IP_PROTO.name(), new IpProtoDecoder());
......@@ -139,7 +141,8 @@ public final class DecodeCriterionCodecHelper {
@Override
public Criterion decodeCriterion(ObjectNode json) {
PortNumber port = PortNumber.portNumber(nullIsIllegal(json.get(CriterionCodec.PORT),
CriterionCodec.PORT + MISSING_MEMBER_MESSAGE).asLong());
CriterionCodec.PORT +
MISSING_MEMBER_MESSAGE).asLong());
return Criteria.matchInPort(port);
}
......@@ -149,7 +152,8 @@ public final class DecodeCriterionCodecHelper {
@Override
public Criterion decodeCriterion(ObjectNode json) {
PortNumber port = PortNumber.portNumber(nullIsIllegal(json.get(CriterionCodec.PORT),
CriterionCodec.PORT + MISSING_MEMBER_MESSAGE).asLong());
CriterionCodec.PORT +
MISSING_MEMBER_MESSAGE).asLong());
return Criteria.matchInPhyPort(port);
}
......@@ -179,12 +183,34 @@ public final class DecodeCriterionCodecHelper {
@Override
public Criterion decodeCriterion(ObjectNode json) {
byte priority = (byte) nullIsIllegal(json.get(CriterionCodec.PRIORITY),
CriterionCodec.VLAN_ID + MISSING_MEMBER_MESSAGE).asInt();
CriterionCodec.PRIORITY + MISSING_MEMBER_MESSAGE).asInt();
return Criteria.matchVlanPcp(priority);
}
}
private class InnerVlanVidDecoder implements CriterionDecoder {
@Override
public Criterion decodeCriterion(ObjectNode json) {
short vlanId = (short) nullIsIllegal(json.get(CriterionCodec.INNER_VLAN_ID),
CriterionCodec.INNER_VLAN_ID +
MISSING_MEMBER_MESSAGE).asInt();
return Criteria.matchInnerVlanId(VlanId.vlanId(vlanId));
}
}
private class InnerVlanPcpDecoder implements CriterionDecoder {
@Override
public Criterion decodeCriterion(ObjectNode json) {
byte priority = (byte) nullIsIllegal(json.get(CriterionCodec.INNER_PRIORITY),
CriterionCodec.INNER_PRIORITY +
MISSING_MEMBER_MESSAGE).asInt();
return Criteria.matchInnerVlanPcp(priority);
}
}
private class IpDscpDecoder implements CriterionDecoder {
@Override
public Criterion decodeCriterion(ObjectNode json) {
......
......@@ -84,6 +84,8 @@ public final class EncodeCriterionCodecHelper {
formatMap.put(Criterion.Type.ETH_TYPE, new FormatEthType());
formatMap.put(Criterion.Type.VLAN_VID, new FormatVlanVid());
formatMap.put(Criterion.Type.VLAN_PCP, new FormatVlanPcp());
formatMap.put(Criterion.Type.INNER_VLAN_VID, new FormatInnerVlanVid());
formatMap.put(Criterion.Type.INNER_VLAN_PCP, new FormatInnerVlanPcp());
formatMap.put(Criterion.Type.IP_DSCP, new FormatIpDscp());
formatMap.put(Criterion.Type.IP_ECN, new FormatIpEcn());
formatMap.put(Criterion.Type.IP_PROTO, new FormatIpProto());
......@@ -194,6 +196,24 @@ public final class EncodeCriterionCodecHelper {
}
}
private static class FormatInnerVlanVid implements CriterionTypeFormatter {
@Override
public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
final VlanIdCriterion vlanIdCriterion =
(VlanIdCriterion) criterion;
return root.put(CriterionCodec.INNER_VLAN_ID, vlanIdCriterion.vlanId().toShort());
}
}
private static class FormatInnerVlanPcp implements CriterionTypeFormatter {
@Override
public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
final VlanPcpCriterion vlanPcpCriterion =
(VlanPcpCriterion) criterion;
return root.put(CriterionCodec.INNER_PRIORITY, vlanPcpCriterion.priority());
}
}
private static class FormatIpDscp implements CriterionTypeFormatter {
@Override
public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
......
......@@ -214,24 +214,34 @@ public class OltPipeline extends AbstractHandlerBehaviour implements Pipeliner {
Pair<Instruction, Instruction> popAndRewrite = vlanOps.remove(0);
FlowRule.Builder inner = DefaultFlowRule.builder()
TrafficSelector selector = fwd.selector();
Criterion outerVlan = selector.getCriterion(Criterion.Type.VLAN_VID);
Criterion innerVlan = selector.getCriterion(Criterion.Type.INNER_VLAN_VID);
Criterion inport = selector.getCriterion(Criterion.Type.IN_PORT);
if (outerVlan == null || innerVlan == null || inport == null) {
log.error("Forwarding objective is underspecified: {}", fwd);
fail(fwd, ObjectiveError.BADPARAMS);
return;
}
FlowRule.Builder outer = DefaultFlowRule.builder()
.forDevice(deviceId)
.fromApp(appId)
.makePermanent()
.withPriority(fwd.priority())
.withSelector(fwd.selector())
.withSelector(buildSelector(inport, outerVlan))
.withTreatment(buildTreatment(popAndRewrite.getLeft(),
Instructions.transition(QQ_TABLE)));
PortCriterion inPort = (PortCriterion)
fwd.selector().getCriterion(Criterion.Type.IN_PORT);
FlowRule.Builder outer = DefaultFlowRule.builder()
FlowRule.Builder inner = DefaultFlowRule.builder()
.forDevice(deviceId)
.fromApp(appId)
.forTable(QQ_TABLE)
.makePermanent()
.withPriority(fwd.priority())
.withSelector(buildSelector(inPort))
.withSelector(buildSelector(inport, innerVlan))
.withTreatment(buildTreatment(popAndRewrite.getRight(),
output));
......