blob: 88cc3328ddc7a4fc357d54ae1195e5b9a7a5129b [file] [log] [blame]
/*
* 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.codec.impl;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.onlab.packet.Ip6Address;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
import org.onlab.packet.MplsLabel;
import org.onlab.packet.TpPort;
import org.onlab.packet.VlanId;
import org.onlab.util.HexString;
import org.onosproject.net.ChannelSpacing;
import org.onosproject.net.GridType;
import org.onosproject.net.Lambda;
import org.onosproject.net.OchSignalType;
import org.onosproject.net.OduSignalId;
import org.onosproject.net.OduSignalType;
import org.onosproject.net.PortNumber;
import org.onosproject.net.flow.criteria.Criteria;
import org.onosproject.net.flow.criteria.Criterion;
import java.util.HashMap;
import java.util.Map;
import static org.onlab.util.Tools.nullIsIllegal;
/**
* Decode portion of the criterion codec.
*/
public final class DecodeCriterionCodecHelper {
private final ObjectNode json;
protected static final String MISSING_MEMBER_MESSAGE =
" member is required in Criterion";
private interface CriterionDecoder {
Criterion decodeCriterion(ObjectNode json);
}
private final Map<String, CriterionDecoder> decoderMap;
/**
* Creates a decode criterion codec object.
* Initializes the lookup map for criterion subclass decoders.
*
* @param json JSON object to decode
*/
public DecodeCriterionCodecHelper(ObjectNode json) {
this.json = json;
decoderMap = new HashMap<>();
decoderMap.put(Criterion.Type.IN_PORT.name(), new InPortDecoder());
decoderMap.put(Criterion.Type.IN_PHY_PORT.name(), new InPhyPortDecoder());
decoderMap.put(Criterion.Type.METADATA.name(), new MetadataDecoder());
decoderMap.put(Criterion.Type.ETH_DST.name(), new EthDstDecoder());
decoderMap.put(Criterion.Type.ETH_SRC.name(), new EthSrcDecoder());
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.IP_DSCP.name(), new IpDscpDecoder());
decoderMap.put(Criterion.Type.IP_ECN.name(), new IpEcnDecoder());
decoderMap.put(Criterion.Type.IP_PROTO.name(), new IpProtoDecoder());
decoderMap.put(Criterion.Type.IPV4_SRC.name(), new IpV4SrcDecoder());
decoderMap.put(Criterion.Type.IPV4_DST.name(), new IpV4DstDecoder());
decoderMap.put(Criterion.Type.TCP_SRC.name(), new TcpSrcDecoder());
decoderMap.put(Criterion.Type.TCP_DST.name(), new TcpDstDecoder());
decoderMap.put(Criterion.Type.UDP_SRC.name(), new UdpSrcDecoder());
decoderMap.put(Criterion.Type.UDP_DST.name(), new UdpDstDecoder());
decoderMap.put(Criterion.Type.SCTP_SRC.name(), new SctpSrcDecoder());
decoderMap.put(Criterion.Type.SCTP_DST.name(), new SctpDstDecoder());
decoderMap.put(Criterion.Type.ICMPV4_TYPE.name(), new IcmpV4TypeDecoder());
decoderMap.put(Criterion.Type.ICMPV4_CODE.name(), new IcmpV4CodeDecoder());
decoderMap.put(Criterion.Type.IPV6_SRC.name(), new IpV6SrcDecoder());
decoderMap.put(Criterion.Type.IPV6_DST.name(), new IpV6DstDecoder());
decoderMap.put(Criterion.Type.IPV6_FLABEL.name(), new IpV6FLabelDecoder());
decoderMap.put(Criterion.Type.ICMPV6_TYPE.name(), new IcmpV6TypeDecoder());
decoderMap.put(Criterion.Type.ICMPV6_CODE.name(), new IcmpV6CodeDecoder());
decoderMap.put(Criterion.Type.IPV6_ND_TARGET.name(), new V6NDTargetDecoder());
decoderMap.put(Criterion.Type.IPV6_ND_SLL.name(), new V6NDSllDecoder());
decoderMap.put(Criterion.Type.IPV6_ND_TLL.name(), new V6NDTllDecoder());
decoderMap.put(Criterion.Type.MPLS_LABEL.name(), new MplsLabelDecoder());
decoderMap.put(Criterion.Type.IPV6_EXTHDR.name(), new IpV6ExthdrDecoder());
decoderMap.put(Criterion.Type.OCH_SIGID.name(), new OchSigIdDecoder());
decoderMap.put(Criterion.Type.OCH_SIGTYPE.name(), new OchSigTypeDecoder());
decoderMap.put(Criterion.Type.TUNNEL_ID.name(), new TunnelIdDecoder());
decoderMap.put(Criterion.Type.ODU_SIGID.name(), new OduSigIdDecoder());
decoderMap.put(Criterion.Type.ODU_SIGTYPE.name(), new OduSigTypeDecoder());
}
private class EthTypeDecoder implements CriterionDecoder {
@Override
public Criterion decodeCriterion(ObjectNode json) {
int ethType;
if (json.get(CriterionCodec.ETH_TYPE).isInt()) {
ethType = nullIsIllegal(json.get(CriterionCodec.ETH_TYPE),
CriterionCodec.ETH_TYPE + MISSING_MEMBER_MESSAGE).asInt();
} else {
ethType = Integer.decode(json.get(CriterionCodec.ETH_TYPE).textValue());
}
return Criteria.matchEthType(ethType);
}
}
private class EthDstDecoder implements CriterionDecoder {
@Override
public Criterion decodeCriterion(ObjectNode json) {
MacAddress mac = MacAddress.valueOf(nullIsIllegal(json.get(CriterionCodec.MAC),
CriterionCodec.MAC + MISSING_MEMBER_MESSAGE).asText());
return Criteria.matchEthDst(mac);
}
}
private class EthSrcDecoder implements CriterionDecoder {
@Override
public Criterion decodeCriterion(ObjectNode json) {
MacAddress mac = MacAddress.valueOf(nullIsIllegal(json.get(CriterionCodec.MAC),
CriterionCodec.MAC + MISSING_MEMBER_MESSAGE).asText());
return Criteria.matchEthSrc(mac);
}
}
private class InPortDecoder implements CriterionDecoder {
@Override
public Criterion decodeCriterion(ObjectNode json) {
PortNumber port = PortNumber.portNumber(nullIsIllegal(json.get(CriterionCodec.PORT),
CriterionCodec.PORT + MISSING_MEMBER_MESSAGE).asLong());
return Criteria.matchInPort(port);
}
}
private class InPhyPortDecoder implements CriterionDecoder {
@Override
public Criterion decodeCriterion(ObjectNode json) {
PortNumber port = PortNumber.portNumber(nullIsIllegal(json.get(CriterionCodec.PORT),
CriterionCodec.PORT + MISSING_MEMBER_MESSAGE).asLong());
return Criteria.matchInPhyPort(port);
}
}
private class MetadataDecoder implements CriterionDecoder {
@Override
public Criterion decodeCriterion(ObjectNode json) {
long metadata = nullIsIllegal(json.get(CriterionCodec.METADATA),
CriterionCodec.METADATA + MISSING_MEMBER_MESSAGE).asLong();
return Criteria.matchMetadata(metadata);
}
}
private class VlanVidDecoder implements CriterionDecoder {
@Override
public Criterion decodeCriterion(ObjectNode json) {
short vlanId = (short) nullIsIllegal(json.get(CriterionCodec.VLAN_ID),
CriterionCodec.VLAN_ID + MISSING_MEMBER_MESSAGE).asInt();
return Criteria.matchVlanId(VlanId.vlanId(vlanId));
}
}
private class VlanPcpDecoder implements CriterionDecoder {
@Override
public Criterion decodeCriterion(ObjectNode json) {
byte priority = (byte) nullIsIllegal(json.get(CriterionCodec.PRIORITY),
CriterionCodec.VLAN_ID + MISSING_MEMBER_MESSAGE).asInt();
return Criteria.matchVlanPcp(priority);
}
}
private class IpDscpDecoder implements CriterionDecoder {
@Override
public Criterion decodeCriterion(ObjectNode json) {
byte ipDscp = (byte) nullIsIllegal(json.get(CriterionCodec.IP_DSCP),
CriterionCodec.IP_DSCP + MISSING_MEMBER_MESSAGE).asInt();
return Criteria.matchIPDscp(ipDscp);
}
}
private class IpEcnDecoder implements CriterionDecoder {
@Override
public Criterion decodeCriterion(ObjectNode json) {
byte ipEcn = (byte) nullIsIllegal(json.get(CriterionCodec.IP_ECN),
CriterionCodec.IP_ECN + MISSING_MEMBER_MESSAGE).asInt();
return Criteria.matchIPEcn(ipEcn);
}
}
private class IpProtoDecoder implements CriterionDecoder {
@Override
public Criterion decodeCriterion(ObjectNode json) {
short proto = (short) nullIsIllegal(json.get(CriterionCodec.PROTOCOL),
CriterionCodec.PROTOCOL + MISSING_MEMBER_MESSAGE).asInt();
return Criteria.matchIPProtocol(proto);
}
}
private class IpV4SrcDecoder implements CriterionDecoder {
@Override
public Criterion decodeCriterion(ObjectNode json) {
String ip = nullIsIllegal(json.get(CriterionCodec.IP),
CriterionCodec.IP + MISSING_MEMBER_MESSAGE).asText();
return Criteria.matchIPSrc(IpPrefix.valueOf(ip));
}
}
private class IpV4DstDecoder implements CriterionDecoder {
@Override
public Criterion decodeCriterion(ObjectNode json) {
String ip = nullIsIllegal(json.get(CriterionCodec.IP),
CriterionCodec.IP + MISSING_MEMBER_MESSAGE).asText();
return Criteria.matchIPDst(IpPrefix.valueOf(ip));
}
}
private class IpV6SrcDecoder implements CriterionDecoder {
@Override
public Criterion decodeCriterion(ObjectNode json) {
String ip = nullIsIllegal(json.get(CriterionCodec.IP),
CriterionCodec.IP + MISSING_MEMBER_MESSAGE).asText();
return Criteria.matchIPv6Src(IpPrefix.valueOf(ip));
}
}
private class IpV6DstDecoder implements CriterionDecoder {
@Override
public Criterion decodeCriterion(ObjectNode json) {
String ip = nullIsIllegal(json.get(CriterionCodec.IP),
CriterionCodec.IP + MISSING_MEMBER_MESSAGE).asText();
return Criteria.matchIPv6Dst(IpPrefix.valueOf(ip));
}
}
private class TcpSrcDecoder implements CriterionDecoder {
@Override
public Criterion decodeCriterion(ObjectNode json) {
TpPort tcpPort = TpPort.tpPort(nullIsIllegal(json.get(CriterionCodec.TCP_PORT),
CriterionCodec.TCP_PORT + MISSING_MEMBER_MESSAGE).asInt());
return Criteria.matchTcpSrc(tcpPort);
}
}
private class TcpDstDecoder implements CriterionDecoder {
@Override
public Criterion decodeCriterion(ObjectNode json) {
TpPort tcpPort = TpPort.tpPort(nullIsIllegal(json.get(CriterionCodec.TCP_PORT),
CriterionCodec.TCP_PORT + MISSING_MEMBER_MESSAGE).asInt());
return Criteria.matchTcpDst(tcpPort);
}
}
private class UdpSrcDecoder implements CriterionDecoder {
@Override
public Criterion decodeCriterion(ObjectNode json) {
TpPort udpPort = TpPort.tpPort(nullIsIllegal(json.get(CriterionCodec.UDP_PORT),
CriterionCodec.UDP_PORT + MISSING_MEMBER_MESSAGE).asInt());
return Criteria.matchUdpSrc(udpPort);
}
}
private class UdpDstDecoder implements CriterionDecoder {
@Override
public Criterion decodeCriterion(ObjectNode json) {
TpPort udpPort = TpPort.tpPort(nullIsIllegal(json.get(CriterionCodec.UDP_PORT),
CriterionCodec.UDP_PORT + MISSING_MEMBER_MESSAGE).asInt());
return Criteria.matchUdpDst(udpPort);
}
}
private class SctpSrcDecoder implements CriterionDecoder {
@Override
public Criterion decodeCriterion(ObjectNode json) {
TpPort sctpPort = TpPort.tpPort(nullIsIllegal(json.get(CriterionCodec.SCTP_PORT),
CriterionCodec.SCTP_PORT + MISSING_MEMBER_MESSAGE).asInt());
return Criteria.matchSctpSrc(sctpPort);
}
}
private class SctpDstDecoder implements CriterionDecoder {
@Override
public Criterion decodeCriterion(ObjectNode json) {
TpPort sctpPort = TpPort.tpPort(nullIsIllegal(json.get(CriterionCodec.SCTP_PORT),
CriterionCodec.SCTP_PORT + MISSING_MEMBER_MESSAGE).asInt());
return Criteria.matchSctpDst(sctpPort);
}
}
private class IcmpV4TypeDecoder implements CriterionDecoder {
@Override
public Criterion decodeCriterion(ObjectNode json) {
short type = (short) nullIsIllegal(json.get(CriterionCodec.ICMP_TYPE),
CriterionCodec.ICMP_TYPE + MISSING_MEMBER_MESSAGE).asInt();
return Criteria.matchIcmpType(type);
}
}
private class IcmpV4CodeDecoder implements CriterionDecoder {
@Override
public Criterion decodeCriterion(ObjectNode json) {
short code = (short) nullIsIllegal(json.get(CriterionCodec.ICMP_CODE),
CriterionCodec.ICMP_CODE + MISSING_MEMBER_MESSAGE).asInt();
return Criteria.matchIcmpCode(code);
}
}
private class IpV6FLabelDecoder implements CriterionDecoder {
@Override
public Criterion decodeCriterion(ObjectNode json) {
int flowLabel = nullIsIllegal(json.get(CriterionCodec.FLOW_LABEL),
CriterionCodec.FLOW_LABEL + MISSING_MEMBER_MESSAGE).asInt();
return Criteria.matchIPv6FlowLabel(flowLabel);
}
}
private class IcmpV6TypeDecoder implements CriterionDecoder {
@Override
public Criterion decodeCriterion(ObjectNode json) {
short type = (short) nullIsIllegal(json.get(CriterionCodec.ICMPV6_TYPE),
CriterionCodec.ICMPV6_TYPE + MISSING_MEMBER_MESSAGE).asInt();
return Criteria.matchIcmpv6Type(type);
}
}
private class IcmpV6CodeDecoder implements CriterionDecoder {
@Override
public Criterion decodeCriterion(ObjectNode json) {
short code = (short) nullIsIllegal(json.get(CriterionCodec.ICMPV6_CODE),
CriterionCodec.ICMPV6_CODE + MISSING_MEMBER_MESSAGE).asInt();
return Criteria.matchIcmpv6Code(code);
}
}
private class V6NDTargetDecoder implements CriterionDecoder {
@Override
public Criterion decodeCriterion(ObjectNode json) {
Ip6Address target = Ip6Address.valueOf(nullIsIllegal(json.get(CriterionCodec.TARGET_ADDRESS),
CriterionCodec.TARGET_ADDRESS + MISSING_MEMBER_MESSAGE).asText());
return Criteria.matchIPv6NDTargetAddress(target);
}
}
private class V6NDSllDecoder implements CriterionDecoder {
@Override
public Criterion decodeCriterion(ObjectNode json) {
MacAddress mac = MacAddress.valueOf(nullIsIllegal(json.get(CriterionCodec.MAC),
CriterionCodec.MAC + MISSING_MEMBER_MESSAGE).asText());
return Criteria.matchIPv6NDSourceLinkLayerAddress(mac);
}
}
private class V6NDTllDecoder implements CriterionDecoder {
@Override
public Criterion decodeCriterion(ObjectNode json) {
MacAddress mac = MacAddress.valueOf(nullIsIllegal(json.get(CriterionCodec.MAC),
CriterionCodec.MAC + MISSING_MEMBER_MESSAGE).asText());
return Criteria.matchIPv6NDTargetLinkLayerAddress(mac);
}
}
private class MplsLabelDecoder implements CriterionDecoder {
@Override
public Criterion decodeCriterion(ObjectNode json) {
int label = nullIsIllegal(json.get(CriterionCodec.LABEL),
CriterionCodec.LABEL + MISSING_MEMBER_MESSAGE).asInt();
return Criteria.matchMplsLabel(MplsLabel.mplsLabel(label));
}
}
private class IpV6ExthdrDecoder implements CriterionDecoder {
@Override
public Criterion decodeCriterion(ObjectNode json) {
int exthdrFlags = nullIsIllegal(json.get(CriterionCodec.EXT_HDR_FLAGS),
CriterionCodec.EXT_HDR_FLAGS + MISSING_MEMBER_MESSAGE).asInt();
return Criteria.matchIPv6ExthdrFlags(exthdrFlags);
}
}
private class OchSigIdDecoder implements CriterionDecoder {
@Override
public Criterion decodeCriterion(ObjectNode json) {
if (json.get(CriterionCodec.LAMBDA) != null) {
Lambda lambda = Lambda.indexedLambda(nullIsIllegal(json.get(CriterionCodec.LAMBDA),
CriterionCodec.LAMBDA + MISSING_MEMBER_MESSAGE).asInt());
return Criteria.matchLambda(lambda);
} else {
JsonNode ochSignalId = nullIsIllegal(json.get(CriterionCodec.OCH_SIGNAL_ID),
CriterionCodec.GRID_TYPE + MISSING_MEMBER_MESSAGE);
GridType gridType =
GridType.valueOf(
nullIsIllegal(ochSignalId.get(CriterionCodec.GRID_TYPE),
CriterionCodec.GRID_TYPE + MISSING_MEMBER_MESSAGE).asText());
ChannelSpacing channelSpacing =
ChannelSpacing.valueOf(
nullIsIllegal(ochSignalId.get(CriterionCodec.CHANNEL_SPACING),
CriterionCodec.CHANNEL_SPACING + MISSING_MEMBER_MESSAGE).asText());
int spacingMultiplier = nullIsIllegal(ochSignalId.get(CriterionCodec.SPACING_MULIPLIER),
CriterionCodec.SPACING_MULIPLIER + MISSING_MEMBER_MESSAGE).asInt();
int slotGranularity = nullIsIllegal(ochSignalId.get(CriterionCodec.SLOT_GRANULARITY),
CriterionCodec.SLOT_GRANULARITY + MISSING_MEMBER_MESSAGE).asInt();
return Criteria.matchLambda(
Lambda.ochSignal(gridType, channelSpacing,
spacingMultiplier, slotGranularity));
}
}
}
private class OchSigTypeDecoder implements CriterionDecoder {
@Override
public Criterion decodeCriterion(ObjectNode json) {
OchSignalType ochSignalType = OchSignalType.valueOf(nullIsIllegal(json.get(CriterionCodec.OCH_SIGNAL_TYPE),
CriterionCodec.OCH_SIGNAL_TYPE + MISSING_MEMBER_MESSAGE).asText());
return Criteria.matchOchSignalType(ochSignalType);
}
}
private class TunnelIdDecoder implements CriterionDecoder {
@Override
public Criterion decodeCriterion(ObjectNode json) {
long tunnelId = nullIsIllegal(json.get(CriterionCodec.TUNNEL_ID),
CriterionCodec.TUNNEL_ID + MISSING_MEMBER_MESSAGE).asLong();
return Criteria.matchTunnelId(tunnelId);
}
}
private class OduSigIdDecoder implements CriterionDecoder {
@Override
public Criterion decodeCriterion(ObjectNode json) {
JsonNode oduSignalId = nullIsIllegal(json.get(CriterionCodec.ODU_SIGNAL_ID),
CriterionCodec.TRIBUTARY_PORT_NUMBER + MISSING_MEMBER_MESSAGE);
int tributaryPortNumber = nullIsIllegal(oduSignalId.get(CriterionCodec.TRIBUTARY_PORT_NUMBER),
CriterionCodec.TRIBUTARY_PORT_NUMBER + MISSING_MEMBER_MESSAGE).asInt();
int tributarySlotLen = nullIsIllegal(oduSignalId.get(CriterionCodec.TRIBUTARY_SLOT_LEN),
CriterionCodec.TRIBUTARY_SLOT_LEN + MISSING_MEMBER_MESSAGE).asInt();
byte[] tributarySlotBitmap = HexString.fromHexString(
nullIsIllegal(oduSignalId.get(CriterionCodec.TRIBUTARY_SLOT_BITMAP),
CriterionCodec.TRIBUTARY_SLOT_BITMAP + MISSING_MEMBER_MESSAGE).asText());
return Criteria.matchOduSignalId(
OduSignalId.oduSignalId(tributaryPortNumber, tributarySlotLen, tributarySlotBitmap));
}
}
private class OduSigTypeDecoder implements CriterionDecoder {
@Override
public Criterion decodeCriterion(ObjectNode json) {
OduSignalType oduSignalType = OduSignalType.valueOf(nullIsIllegal(json.get(CriterionCodec.ODU_SIGNAL_TYPE),
CriterionCodec.ODU_SIGNAL_TYPE + MISSING_MEMBER_MESSAGE).asText());
return Criteria.matchOduSignalType(oduSignalType);
}
}
/**
* Decodes the JSON into a criterion object.
*
* @return Criterion object
* @throws IllegalArgumentException if the JSON is invalid
*/
public Criterion decode() {
String type = json.get(CriterionCodec.TYPE).asText();
CriterionDecoder decoder = decoderMap.get(type);
if (decoder != null) {
return decoder.decodeCriterion(json);
}
throw new IllegalArgumentException("Type " + type + " is unknown");
}
}