Ray Milkey
Committed by Gerrit Code Review

REST API to create flows

Change-Id: I5d001782249c0eab249d7aa857ae465da95b5955
Showing 22 changed files with 2180 additions and 500 deletions
......@@ -35,6 +35,7 @@ import org.onosproject.net.Path;
import org.onosproject.net.Port;
import org.onosproject.net.driver.Driver;
import org.onosproject.net.flow.FlowEntry;
import org.onosproject.net.flow.FlowRule;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.flow.criteria.Criterion;
......@@ -83,6 +84,7 @@ public class CodecManager implements CodecService {
registerCodec(Intent.class, new IntentCodec());
registerCodec(ConnectivityIntent.class, new ConnectivityIntentCodec());
registerCodec(FlowEntry.class, new FlowEntryCodec());
registerCodec(FlowRule.class, new FlowRuleCodec());
registerCodec(TrafficTreatment.class, new TrafficTreatmentCodec());
registerCodec(TrafficSelector.class, new TrafficSelectorCodec());
registerCodec(Instruction.class, new InstructionCodec());
......
......@@ -15,43 +15,14 @@
*/
package org.onosproject.codec.impl;
import java.util.EnumMap;
import org.onosproject.codec.CodecContext;
import org.onosproject.codec.JsonCodec;
import org.onosproject.net.OchSignal;
import org.onosproject.net.flow.criteria.Criterion;
import org.onosproject.net.flow.criteria.EthCriterion;
import org.onosproject.net.flow.criteria.EthTypeCriterion;
import org.onosproject.net.flow.criteria.IPCriterion;
import org.onosproject.net.flow.criteria.IPDscpCriterion;
import org.onosproject.net.flow.criteria.IPEcnCriterion;
import org.onosproject.net.flow.criteria.IPProtocolCriterion;
import org.onosproject.net.flow.criteria.IPv6ExthdrFlagsCriterion;
import org.onosproject.net.flow.criteria.IPv6FlowLabelCriterion;
import org.onosproject.net.flow.criteria.IPv6NDLinkLayerAddressCriterion;
import org.onosproject.net.flow.criteria.IPv6NDTargetAddressCriterion;
import org.onosproject.net.flow.criteria.IcmpCodeCriterion;
import org.onosproject.net.flow.criteria.IcmpTypeCriterion;
import org.onosproject.net.flow.criteria.Icmpv6CodeCriterion;
import org.onosproject.net.flow.criteria.Icmpv6TypeCriterion;
import org.onosproject.net.flow.criteria.MetadataCriterion;
import org.onosproject.net.flow.criteria.MplsCriterion;
import org.onosproject.net.flow.criteria.OchSignalCriterion;
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.UdpPortCriterion;
import org.onosproject.net.flow.criteria.VlanIdCriterion;
import org.onosproject.net.flow.criteria.VlanPcpCriterion;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.databind.node.ObjectNode;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Criterion codec.
*/
......@@ -60,318 +31,46 @@ public final class CriterionCodec extends JsonCodec<Criterion> {
protected static final Logger log =
LoggerFactory.getLogger(CriterionCodec.class);
private final EnumMap<Criterion.Type, CriterionTypeFormatter> formatMap;
public CriterionCodec() {
formatMap = new EnumMap<>(Criterion.Type.class);
formatMap.put(Criterion.Type.IN_PORT, new FormatInPort());
formatMap.put(Criterion.Type.IN_PHY_PORT, new FormatInPort());
formatMap.put(Criterion.Type.METADATA, new FormatMetadata());
formatMap.put(Criterion.Type.ETH_DST, new FormatEth());
formatMap.put(Criterion.Type.ETH_SRC, new FormatEth());
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.IP_DSCP, new FormatIpDscp());
formatMap.put(Criterion.Type.IP_ECN, new FormatIpEcn());
formatMap.put(Criterion.Type.IP_PROTO, new FormatIpProto());
formatMap.put(Criterion.Type.IPV4_SRC, new FormatIp());
formatMap.put(Criterion.Type.IPV4_DST, new FormatIp());
formatMap.put(Criterion.Type.TCP_SRC, new FormatTcp());
formatMap.put(Criterion.Type.TCP_DST, new FormatTcp());
formatMap.put(Criterion.Type.UDP_SRC, new FormatUdp());
formatMap.put(Criterion.Type.UDP_DST, new FormatUdp());
formatMap.put(Criterion.Type.SCTP_SRC, new FormatSctp());
formatMap.put(Criterion.Type.SCTP_DST, new FormatSctp());
formatMap.put(Criterion.Type.ICMPV4_TYPE, new FormatIcmpV4Type());
formatMap.put(Criterion.Type.ICMPV4_CODE, new FormatIcmpV4Code());
formatMap.put(Criterion.Type.IPV6_SRC, new FormatIp());
formatMap.put(Criterion.Type.IPV6_DST, new FormatIp());
formatMap.put(Criterion.Type.IPV6_FLABEL, new FormatIpV6FLabel());
formatMap.put(Criterion.Type.ICMPV6_TYPE, new FormatIcmpV6Type());
formatMap.put(Criterion.Type.ICMPV6_CODE, new FormatIcmpV6Code());
formatMap.put(Criterion.Type.IPV6_ND_TARGET, new FormatV6NDTarget());
formatMap.put(Criterion.Type.IPV6_ND_SLL, new FormatV6NDTll());
formatMap.put(Criterion.Type.IPV6_ND_TLL, new FormatV6NDTll());
formatMap.put(Criterion.Type.MPLS_LABEL, new FormatMplsLabel());
formatMap.put(Criterion.Type.IPV6_EXTHDR, new FormatIpV6Exthdr());
formatMap.put(Criterion.Type.OCH_SIGID, new FormatOchSigId());
formatMap.put(Criterion.Type.OCH_SIGTYPE, new FormatOchSigType());
formatMap.put(Criterion.Type.DUMMY, new FormatDummyType());
// Currently unimplemented
formatMap.put(Criterion.Type.ARP_OP, new FormatUnknown());
formatMap.put(Criterion.Type.ARP_SPA, new FormatUnknown());
formatMap.put(Criterion.Type.ARP_TPA, new FormatUnknown());
formatMap.put(Criterion.Type.ARP_SHA, new FormatUnknown());
formatMap.put(Criterion.Type.ARP_THA, new FormatUnknown());
formatMap.put(Criterion.Type.MPLS_TC, new FormatUnknown());
formatMap.put(Criterion.Type.MPLS_BOS, new FormatUnknown());
formatMap.put(Criterion.Type.PBB_ISID, new FormatUnknown());
formatMap.put(Criterion.Type.TUNNEL_ID, new FormatUnknown());
formatMap.put(Criterion.Type.UNASSIGNED_40, new FormatUnknown());
formatMap.put(Criterion.Type.PBB_UCA, new FormatUnknown());
formatMap.put(Criterion.Type.TCP_FLAGS, new FormatUnknown());
formatMap.put(Criterion.Type.ACTSET_OUTPUT, new FormatUnknown());
formatMap.put(Criterion.Type.PACKET_TYPE, new FormatUnknown());
}
private interface CriterionTypeFormatter {
ObjectNode encodeCriterion(ObjectNode root, Criterion criterion);
}
private static class FormatUnknown implements CriterionTypeFormatter {
@Override
public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
return root;
}
}
private static class FormatInPort implements CriterionTypeFormatter {
@Override
public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
final PortCriterion portCriterion = (PortCriterion) criterion;
return root.put("port", portCriterion.port().toLong());
}
}
private static class FormatMetadata implements CriterionTypeFormatter {
@Override
public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
final MetadataCriterion metadataCriterion =
(MetadataCriterion) criterion;
return root.put("metadata", metadataCriterion.metadata());
}
}
private static class FormatEth implements CriterionTypeFormatter {
@Override
public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
final EthCriterion ethCriterion = (EthCriterion) criterion;
return root.put("mac", ethCriterion.mac().toString());
}
}
private static class FormatEthType implements CriterionTypeFormatter {
@Override
public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
final EthTypeCriterion ethTypeCriterion =
(EthTypeCriterion) criterion;
return root.put("ethType", ethTypeCriterion.ethType());
}
}
private static class FormatVlanVid implements CriterionTypeFormatter {
@Override
public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
final VlanIdCriterion vlanIdCriterion =
(VlanIdCriterion) criterion;
return root.put("vlanId", vlanIdCriterion.vlanId().toShort());
}
}
private static class FormatVlanPcp implements CriterionTypeFormatter {
@Override
public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
final VlanPcpCriterion vlanPcpCriterion =
(VlanPcpCriterion) criterion;
return root.put("priority", vlanPcpCriterion.priority());
}
}
private static class FormatIpDscp implements CriterionTypeFormatter {
@Override
public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
final IPDscpCriterion ipDscpCriterion =
(IPDscpCriterion) criterion;
return root.put("ipDscp", ipDscpCriterion.ipDscp());
}
}
private static class FormatIpEcn implements CriterionTypeFormatter {
@Override
public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
final IPEcnCriterion ipEcnCriterion =
(IPEcnCriterion) criterion;
return root.put("ipEcn", ipEcnCriterion.ipEcn());
}
}
private static class FormatIpProto implements CriterionTypeFormatter {
@Override
public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
final IPProtocolCriterion iPProtocolCriterion =
(IPProtocolCriterion) criterion;
return root.put("protocol", iPProtocolCriterion.protocol());
}
}
private static class FormatIp implements CriterionTypeFormatter {
@Override
public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
final IPCriterion iPCriterion = (IPCriterion) criterion;
return root.put("ip", iPCriterion.ip().toString());
}
}
private static class FormatTcp implements CriterionTypeFormatter {
@Override
public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
final TcpPortCriterion tcpPortCriterion =
(TcpPortCriterion) criterion;
return root.put("tcpPort", tcpPortCriterion.tcpPort());
}
}
private static class FormatUdp implements CriterionTypeFormatter {
@Override
public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
final UdpPortCriterion udpPortCriterion =
(UdpPortCriterion) criterion;
return root.put("udpPort", udpPortCriterion.udpPort());
}
}
protected static final String TYPE = "type";
protected static final String ETH_TYPE = "ethType";
protected static final String MAC = "mac";
protected static final String PORT = "port";
protected static final String METADATA = "metadata";
protected static final String VLAN_ID = "vlanId";
protected static final String PRIORITY = "priority";
protected static final String IP_DSCP = "ipDscp";
protected static final String IP_ECN = "ipEcn";
protected static final String PROTOCOL = "protocol";
protected static final String IP = "ip";
protected static final String TCP_PORT = "tcpPort";
protected static final String UDP_PORT = "udpPort";
protected static final String SCTP_PORT = "sctpPort";
protected static final String ICMP_TYPE = "icmpType";
protected static final String ICMP_CODE = "icmpCode";
protected static final String FLOW_LABEL = "flowLabel";
protected static final String ICMPV6_TYPE = "icmpv6Type";
protected static final String ICMPV6_CODE = "icmpv6Code";
protected static final String TARGET_ADDRESS = "targetAddress";
protected static final String LABEL = "label";
protected static final String EXT_HDR_FLAGS = "exthdrFlags";
protected static final String LAMBDA = "lambda";
protected static final String GRID_TYPE = "gridType";
protected static final String CHANNEL_SPACING = "channelSpacing";
protected static final String SPACING_MULIPLIER = "spacingMultiplier";
protected static final String SLOT_GRANULARITY = "slotGranularity";
protected static final String OCH_SIGNAL_ID = "ochSignalId";
private static class FormatSctp implements CriterionTypeFormatter {
@Override
public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
final SctpPortCriterion sctpPortCriterion =
(SctpPortCriterion) criterion;
return root.put("sctpPort", sctpPortCriterion.sctpPort());
}
}
private static class FormatIcmpV4Type implements CriterionTypeFormatter {
@Override
public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
final IcmpTypeCriterion icmpTypeCriterion =
(IcmpTypeCriterion) criterion;
return root.put("icmpType", icmpTypeCriterion.icmpType());
}
}
private static class FormatIcmpV4Code implements CriterionTypeFormatter {
@Override
public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
final IcmpCodeCriterion icmpCodeCriterion =
(IcmpCodeCriterion) criterion;
return root.put("icmpCode", icmpCodeCriterion.icmpCode());
}
}
private static class FormatIpV6FLabel implements CriterionTypeFormatter {
@Override
public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
final IPv6FlowLabelCriterion ipv6FlowLabelCriterion =
(IPv6FlowLabelCriterion) criterion;
return root.put("flowLabel", ipv6FlowLabelCriterion.flowLabel());
}
}
private static class FormatIcmpV6Type implements CriterionTypeFormatter {
@Override
public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
final Icmpv6TypeCriterion icmpv6TypeCriterion =
(Icmpv6TypeCriterion) criterion;
return root.put("icmpv6Type", icmpv6TypeCriterion.icmpv6Type());
}
}
private static class FormatIcmpV6Code implements CriterionTypeFormatter {
@Override
public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
final Icmpv6CodeCriterion icmpv6CodeCriterion =
(Icmpv6CodeCriterion) criterion;
return root.put("icmpv6Code", icmpv6CodeCriterion.icmpv6Code());
}
}
private static class FormatV6NDTarget implements CriterionTypeFormatter {
@Override
public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
final IPv6NDTargetAddressCriterion ipv6NDTargetAddressCriterion
= (IPv6NDTargetAddressCriterion) criterion;
return root.put("targetAddress", ipv6NDTargetAddressCriterion.targetAddress().toString());
}
}
private static class FormatV6NDTll implements CriterionTypeFormatter {
@Override
public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
final IPv6NDLinkLayerAddressCriterion ipv6NDLinkLayerAddressCriterion
= (IPv6NDLinkLayerAddressCriterion) criterion;
return root.put("mac", ipv6NDLinkLayerAddressCriterion.mac().toString());
}
}
private static class FormatMplsLabel implements CriterionTypeFormatter {
@Override
public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
final MplsCriterion mplsCriterion =
(MplsCriterion) criterion;
return root.put("label", mplsCriterion.label().toInt());
}
}
private static class FormatIpV6Exthdr implements CriterionTypeFormatter {
@Override
public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
final IPv6ExthdrFlagsCriterion exthdrCriterion =
(IPv6ExthdrFlagsCriterion) criterion;
return root.put("exthdrFlags", exthdrCriterion.exthdrFlags());
}
}
private static class FormatOchSigId implements CriterionTypeFormatter {
@Override
public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
OchSignal ochSignal = ((OchSignalCriterion) criterion).lambda();
ObjectNode child = root.putObject("ochSignalId");
child.put("gridType", ochSignal.gridType().name());
child.put("channelSpacing", ochSignal.channelSpacing().name());
child.put("spacingMultiplier", ochSignal.spacingMultiplier());
child.put("slotGranularity", ochSignal.slotGranularity());
return root;
}
}
private static class FormatOchSigType implements CriterionTypeFormatter {
@Override
public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
final OchSignalTypeCriterion ochSignalTypeCriterion =
(OchSignalTypeCriterion) criterion;
return root.put("ochSignalType", ochSignalTypeCriterion.signalType().name());
}
}
private class FormatDummyType implements CriterionTypeFormatter {
@Override
public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
checkNotNull(criterion, "Criterion cannot be null");
return root.put("type", criterion.type().toString());
}
public ObjectNode encode(Criterion criterion, CodecContext context) {
EncodeCriterionCodec encoder = new EncodeCriterionCodec(criterion, context);
return encoder.encode();
}
@Override
public ObjectNode encode(Criterion criterion, CodecContext context) {
checkNotNull(criterion, "Criterion cannot be null");
final ObjectNode result = context.mapper().createObjectNode()
.put("type", criterion.type().toString());
CriterionTypeFormatter formatter =
checkNotNull(
formatMap.get(criterion.type()),
"No formatter found for criterion type "
+ criterion.type().toString());
return formatter.encodeCriterion(result, criterion);
public Criterion decode(ObjectNode json, CodecContext context) {
DecodeCriterionCodec decoder = new DecodeCriterionCodec(json);
return decoder.decode();
}
......
/*
* 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 java.util.HashMap;
import java.util.Map;
import org.onlab.packet.Ip6Address;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
import org.onlab.packet.MplsLabel;
import org.onlab.packet.VlanId;
import org.onosproject.net.ChannelSpacing;
import org.onosproject.net.GridType;
import org.onosproject.net.Lambda;
import org.onosproject.net.PortNumber;
import org.onosproject.net.flow.criteria.Criteria;
import org.onosproject.net.flow.criteria.Criterion;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import static org.onlab.util.Tools.nullIsIllegal;
/**
* Decode portion of the criterion codec.
*/
public final class DecodeCriterionCodec {
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 DecodeCriterionCodec(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());
}
private class EthTypeDecoder implements CriterionDecoder {
@Override
public Criterion decodeCriterion(ObjectNode json) {
int ethType = nullIsIllegal(json.get(CriterionCodec.ETH_TYPE),
CriterionCodec.ETH_TYPE + MISSING_MEMBER_MESSAGE).asInt();
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) {
int tcpPort = 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) {
int tcpPort = 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) {
int udpPort = 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) {
int udpPort = 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) {
int sctpPort = 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) {
int sctpPort = 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) {
return null;
}
}
/**
* 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");
}
}
/*
* 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 org.onlab.packet.IpAddress;
import org.onlab.packet.MacAddress;
import org.onlab.packet.MplsLabel;
import org.onlab.packet.VlanId;
import org.onosproject.net.ChannelSpacing;
import org.onosproject.net.GridType;
import org.onosproject.net.Lambda;
import org.onosproject.net.OchSignal;
import org.onosproject.net.PortNumber;
import org.onosproject.net.flow.instructions.Instruction;
import org.onosproject.net.flow.instructions.Instructions;
import org.onosproject.net.flow.instructions.L0ModificationInstruction;
import org.onosproject.net.flow.instructions.L2ModificationInstruction;
import org.onosproject.net.flow.instructions.L3ModificationInstruction;
import com.fasterxml.jackson.databind.node.ObjectNode;
import static org.onlab.util.Tools.nullIsIllegal;
/**
* Decoding portion of the instruction codec.
*/
public final class DecodeInstructionCodec {
private final ObjectNode json;
/**
* Creates a decode instruction codec object.
*
* @param json JSON object to decode
*/
public DecodeInstructionCodec(ObjectNode json) {
this.json = json;
}
/**
* Decodes a Layer 2 instruction.
*
* @return instruction object decoded from the JSON
* @throws IllegalArgumentException if the JSON is invalid
*/
private Instruction decodeL2() {
String subType = json.get(InstructionCodec.SUBTYPE).asText();
if (subType.equals(L2ModificationInstruction.L2SubType.ETH_SRC.name())) {
String mac = nullIsIllegal(json.get(InstructionCodec.MAC),
InstructionCodec.MAC + InstructionCodec.MISSING_MEMBER_MESSAGE).asText();
return Instructions.modL2Src(MacAddress.valueOf(mac));
} else if (subType.equals(L2ModificationInstruction.L2SubType.ETH_DST.name())) {
String mac = nullIsIllegal(json.get(InstructionCodec.MAC),
InstructionCodec.MAC + InstructionCodec.MISSING_MEMBER_MESSAGE).asText();
return Instructions.modL2Dst(MacAddress.valueOf(mac));
} else if (subType.equals(L2ModificationInstruction.L2SubType.VLAN_ID.name())) {
short vlanId = (short) nullIsIllegal(json.get(InstructionCodec.VLAN_ID),
InstructionCodec.VLAN_ID + InstructionCodec.MISSING_MEMBER_MESSAGE).asInt();
return Instructions.modVlanId(VlanId.vlanId(vlanId));
} else if (subType.equals(L2ModificationInstruction.L2SubType.VLAN_PCP.name())) {
byte vlanPcp = (byte) nullIsIllegal(json.get(InstructionCodec.VLAN_PCP),
InstructionCodec.VLAN_PCP + InstructionCodec.MISSING_MEMBER_MESSAGE).asInt();
return Instructions.modVlanPcp(vlanPcp);
} else if (subType.equals(L2ModificationInstruction.L2SubType.MPLS_LABEL.name())) {
int label = nullIsIllegal(json.get(InstructionCodec.MPLS_LABEL),
InstructionCodec.MPLS_LABEL + InstructionCodec.MISSING_MEMBER_MESSAGE).asInt();
return Instructions.modMplsLabel(MplsLabel.mplsLabel(label));
} else if (subType.equals(L2ModificationInstruction.L2SubType.MPLS_PUSH.name())) {
return Instructions.pushMpls();
} else if (subType.equals(L2ModificationInstruction.L2SubType.MPLS_POP.name())) {
return Instructions.popMpls();
} else if (subType.equals(L2ModificationInstruction.L2SubType.DEC_MPLS_TTL.name())) {
return Instructions.decMplsTtl();
} else if (subType.equals(L2ModificationInstruction.L2SubType.VLAN_POP.name())) {
return Instructions.popVlan();
} else if (subType.equals(L2ModificationInstruction.L2SubType.VLAN_PUSH.name())) {
return Instructions.pushVlan();
}
throw new IllegalArgumentException("L2 Instruction subtype "
+ subType + " is not supported");
}
/**
* Decodes a Layer 3 instruction.
*
* @return instruction object decoded from the JSON
* @throws IllegalArgumentException if the JSON is invalid
*/
private Instruction decodeL3() {
String subType = json.get(InstructionCodec.SUBTYPE).asText();
if (subType.equals(L3ModificationInstruction.L3SubType.IPV4_SRC.name())) {
IpAddress ip = IpAddress.valueOf(nullIsIllegal(json.get(InstructionCodec.IP),
InstructionCodec.IP + InstructionCodec.MISSING_MEMBER_MESSAGE).asText());
return Instructions.modL3Src(ip);
} else if (subType.equals(L3ModificationInstruction.L3SubType.IPV4_DST.name())) {
IpAddress ip = IpAddress.valueOf(nullIsIllegal(json.get(InstructionCodec.IP),
InstructionCodec.IP + InstructionCodec.MISSING_MEMBER_MESSAGE).asText());
return Instructions.modL3Dst(ip);
} else if (subType.equals(L3ModificationInstruction.L3SubType.IPV6_SRC.name())) {
IpAddress ip = IpAddress.valueOf(nullIsIllegal(json.get(InstructionCodec.IP),
InstructionCodec.IP + InstructionCodec.MISSING_MEMBER_MESSAGE).asText());
return Instructions.modL3IPv6Src(ip);
} else if (subType.equals(L3ModificationInstruction.L3SubType.IPV6_DST.name())) {
IpAddress ip = IpAddress.valueOf(nullIsIllegal(json.get(InstructionCodec.IP),
InstructionCodec.IP + InstructionCodec.MISSING_MEMBER_MESSAGE).asText());
return Instructions.modL3IPv6Dst(ip);
} else if (subType.equals(L3ModificationInstruction.L3SubType.IPV6_FLABEL.name())) {
int flowLabel = nullIsIllegal(json.get(InstructionCodec.FLOW_LABEL),
InstructionCodec.FLOW_LABEL + InstructionCodec.MISSING_MEMBER_MESSAGE).asInt();
return Instructions.modL3IPv6FlowLabel(flowLabel);
}
throw new IllegalArgumentException("L3 Instruction subtype "
+ subType + " is not supported");
}
/**
* Decodes a Layer 0 instruction.
*
* @return instruction object decoded from the JSON
* @throws IllegalArgumentException if the JSON is invalid
*/
private Instruction decodeL0() {
String subType = json.get(InstructionCodec.SUBTYPE).asText();
if (subType.equals(L0ModificationInstruction.L0SubType.LAMBDA.name())) {
int lambda = nullIsIllegal(json.get(InstructionCodec.LAMBDA),
InstructionCodec.LAMBDA + InstructionCodec.MISSING_MEMBER_MESSAGE).asInt();
return Instructions.modL0Lambda(Lambda.indexedLambda(lambda));
} else if (subType.equals(L0ModificationInstruction.L0SubType.OCH.name())) {
String gridTypeString = nullIsIllegal(json.get(InstructionCodec.GRID_TYPE),
InstructionCodec.GRID_TYPE + InstructionCodec.MISSING_MEMBER_MESSAGE).asText();
GridType gridType = GridType.valueOf(gridTypeString);
if (gridType == null) {
throw new IllegalArgumentException("Unknown grid type "
+ gridTypeString);
}
String channelSpacingString = nullIsIllegal(json.get(InstructionCodec.CHANNEL_SPACING),
InstructionCodec.CHANNEL_SPACING + InstructionCodec.MISSING_MEMBER_MESSAGE).asText();
ChannelSpacing channelSpacing = ChannelSpacing.valueOf(channelSpacingString);
if (channelSpacing == null) {
throw new IllegalArgumentException("Unknown channel spacing "
+ channelSpacingString);
}
int spacingMultiplier = nullIsIllegal(json.get(InstructionCodec.SPACING_MULTIPLIER),
InstructionCodec.SPACING_MULTIPLIER + InstructionCodec.MISSING_MEMBER_MESSAGE).asInt();
int slotGranularity = nullIsIllegal(json.get(InstructionCodec.SLOT_GRANULARITY),
InstructionCodec.SLOT_GRANULARITY + InstructionCodec.MISSING_MEMBER_MESSAGE).asInt();
return Instructions.modL0Lambda(new OchSignal(gridType, channelSpacing,
spacingMultiplier, slotGranularity));
}
throw new IllegalArgumentException("L0 Instruction subtype "
+ subType + " is not supported");
}
/**
* Decodes the JSON into an instruction object.
*
* @return Criterion object
* @throws IllegalArgumentException if the JSON is invalid
*/
public Instruction decode() {
String type = json.get(InstructionCodec.TYPE).asText();
if (type.equals(Instruction.Type.OUTPUT.name())) {
PortNumber portNumber =
PortNumber.portNumber(nullIsIllegal(json.get(InstructionCodec.PORT),
InstructionCodec.PORT + InstructionCodec.MISSING_MEMBER_MESSAGE).asLong());
return Instructions.createOutput(portNumber);
} else if (type.equals(Instruction.Type.DROP.name())) {
return Instructions.createDrop();
} else if (type.equals(Instruction.Type.L0MODIFICATION.name())) {
return decodeL0();
} else if (type.equals(Instruction.Type.L2MODIFICATION.name())) {
return decodeL2();
} else if (type.equals(Instruction.Type.L3MODIFICATION.name())) {
return decodeL3();
}
throw new IllegalArgumentException("Instruction type "
+ type + " is not supported");
}
}
/*
* 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 java.util.EnumMap;
import org.onosproject.codec.CodecContext;
import org.onosproject.net.OchSignal;
import org.onosproject.net.flow.criteria.Criterion;
import org.onosproject.net.flow.criteria.EthCriterion;
import org.onosproject.net.flow.criteria.EthTypeCriterion;
import org.onosproject.net.flow.criteria.IPCriterion;
import org.onosproject.net.flow.criteria.IPDscpCriterion;
import org.onosproject.net.flow.criteria.IPEcnCriterion;
import org.onosproject.net.flow.criteria.IPProtocolCriterion;
import org.onosproject.net.flow.criteria.IPv6ExthdrFlagsCriterion;
import org.onosproject.net.flow.criteria.IPv6FlowLabelCriterion;
import org.onosproject.net.flow.criteria.IPv6NDLinkLayerAddressCriterion;
import org.onosproject.net.flow.criteria.IPv6NDTargetAddressCriterion;
import org.onosproject.net.flow.criteria.IcmpCodeCriterion;
import org.onosproject.net.flow.criteria.IcmpTypeCriterion;
import org.onosproject.net.flow.criteria.Icmpv6CodeCriterion;
import org.onosproject.net.flow.criteria.Icmpv6TypeCriterion;
import org.onosproject.net.flow.criteria.MetadataCriterion;
import org.onosproject.net.flow.criteria.MplsCriterion;
import org.onosproject.net.flow.criteria.OchSignalCriterion;
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.UdpPortCriterion;
import org.onosproject.net.flow.criteria.VlanIdCriterion;
import org.onosproject.net.flow.criteria.VlanPcpCriterion;
import com.fasterxml.jackson.databind.node.ObjectNode;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Encode portion of the criterion codec.
*/
public final class EncodeCriterionCodec {
private final Criterion criterion;
private final CodecContext context;
private final EnumMap<Criterion.Type, CriterionTypeFormatter> formatMap;
/**
* Creates an encoder object for a criterion.
* Initializes the formatter lookup map for the criterion subclasses.
*
* @param criterion Criterion to encode
* @param context context of the JSON encoding
*/
public EncodeCriterionCodec(Criterion criterion, CodecContext context) {
this.criterion = criterion;
this.context = context;
formatMap = new EnumMap<>(Criterion.Type.class);
formatMap.put(Criterion.Type.IN_PORT, new FormatInPort());
formatMap.put(Criterion.Type.IN_PHY_PORT, new FormatInPort());
formatMap.put(Criterion.Type.METADATA, new FormatMetadata());
formatMap.put(Criterion.Type.ETH_DST, new FormatEth());
formatMap.put(Criterion.Type.ETH_SRC, new FormatEth());
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.IP_DSCP, new FormatIpDscp());
formatMap.put(Criterion.Type.IP_ECN, new FormatIpEcn());
formatMap.put(Criterion.Type.IP_PROTO, new FormatIpProto());
formatMap.put(Criterion.Type.IPV4_SRC, new FormatIp());
formatMap.put(Criterion.Type.IPV4_DST, new FormatIp());
formatMap.put(Criterion.Type.TCP_SRC, new FormatTcp());
formatMap.put(Criterion.Type.TCP_DST, new FormatTcp());
formatMap.put(Criterion.Type.UDP_SRC, new FormatUdp());
formatMap.put(Criterion.Type.UDP_DST, new FormatUdp());
formatMap.put(Criterion.Type.SCTP_SRC, new FormatSctp());
formatMap.put(Criterion.Type.SCTP_DST, new FormatSctp());
formatMap.put(Criterion.Type.ICMPV4_TYPE, new FormatIcmpV4Type());
formatMap.put(Criterion.Type.ICMPV4_CODE, new FormatIcmpV4Code());
formatMap.put(Criterion.Type.IPV6_SRC, new FormatIp());
formatMap.put(Criterion.Type.IPV6_DST, new FormatIp());
formatMap.put(Criterion.Type.IPV6_FLABEL, new FormatIpV6FLabel());
formatMap.put(Criterion.Type.ICMPV6_TYPE, new FormatIcmpV6Type());
formatMap.put(Criterion.Type.ICMPV6_CODE, new FormatIcmpV6Code());
formatMap.put(Criterion.Type.IPV6_ND_TARGET, new FormatV6NDTarget());
formatMap.put(Criterion.Type.IPV6_ND_SLL, new FormatV6NDTll());
formatMap.put(Criterion.Type.IPV6_ND_TLL, new FormatV6NDTll());
formatMap.put(Criterion.Type.MPLS_LABEL, new FormatMplsLabel());
formatMap.put(Criterion.Type.IPV6_EXTHDR, new FormatIpV6Exthdr());
formatMap.put(Criterion.Type.OCH_SIGID, new FormatOchSigId());
formatMap.put(Criterion.Type.OCH_SIGTYPE, new FormatOchSigType());
formatMap.put(Criterion.Type.DUMMY, new FormatDummyType());
// Currently unimplemented
formatMap.put(Criterion.Type.ARP_OP, new FormatUnknown());
formatMap.put(Criterion.Type.ARP_SPA, new FormatUnknown());
formatMap.put(Criterion.Type.ARP_TPA, new FormatUnknown());
formatMap.put(Criterion.Type.ARP_SHA, new FormatUnknown());
formatMap.put(Criterion.Type.ARP_THA, new FormatUnknown());
formatMap.put(Criterion.Type.MPLS_TC, new FormatUnknown());
formatMap.put(Criterion.Type.MPLS_BOS, new FormatUnknown());
formatMap.put(Criterion.Type.PBB_ISID, new FormatUnknown());
formatMap.put(Criterion.Type.TUNNEL_ID, new FormatUnknown());
formatMap.put(Criterion.Type.UNASSIGNED_40, new FormatUnknown());
formatMap.put(Criterion.Type.PBB_UCA, new FormatUnknown());
formatMap.put(Criterion.Type.TCP_FLAGS, new FormatUnknown());
formatMap.put(Criterion.Type.ACTSET_OUTPUT, new FormatUnknown());
formatMap.put(Criterion.Type.PACKET_TYPE, new FormatUnknown());
}
private interface CriterionTypeFormatter {
ObjectNode encodeCriterion(ObjectNode root, Criterion criterion);
}
private static class FormatUnknown implements CriterionTypeFormatter {
@Override
public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
return root;
}
}
private static class FormatInPort implements CriterionTypeFormatter {
@Override
public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
final PortCriterion portCriterion = (PortCriterion) criterion;
return root.put(CriterionCodec.PORT, portCriterion.port().toLong());
}
}
private static class FormatMetadata implements CriterionTypeFormatter {
@Override
public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
final MetadataCriterion metadataCriterion =
(MetadataCriterion) criterion;
return root.put(CriterionCodec.METADATA, metadataCriterion.metadata());
}
}
private static class FormatEth implements CriterionTypeFormatter {
@Override
public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
final EthCriterion ethCriterion = (EthCriterion) criterion;
return root.put(CriterionCodec.MAC, ethCriterion.mac().toString());
}
}
private static class FormatEthType implements CriterionTypeFormatter {
@Override
public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
final EthTypeCriterion ethTypeCriterion =
(EthTypeCriterion) criterion;
return root.put(CriterionCodec.ETH_TYPE, ethTypeCriterion.ethType());
}
}
private static class FormatVlanVid implements CriterionTypeFormatter {
@Override
public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
final VlanIdCriterion vlanIdCriterion =
(VlanIdCriterion) criterion;
return root.put(CriterionCodec.VLAN_ID, vlanIdCriterion.vlanId().toShort());
}
}
private static class FormatVlanPcp implements CriterionTypeFormatter {
@Override
public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
final VlanPcpCriterion vlanPcpCriterion =
(VlanPcpCriterion) criterion;
return root.put(CriterionCodec.PRIORITY, vlanPcpCriterion.priority());
}
}
private static class FormatIpDscp implements CriterionTypeFormatter {
@Override
public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
final IPDscpCriterion ipDscpCriterion =
(IPDscpCriterion) criterion;
return root.put(CriterionCodec.IP_DSCP, ipDscpCriterion.ipDscp());
}
}
private static class FormatIpEcn implements CriterionTypeFormatter {
@Override
public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
final IPEcnCriterion ipEcnCriterion =
(IPEcnCriterion) criterion;
return root.put(CriterionCodec.IP_ECN, ipEcnCriterion.ipEcn());
}
}
private static class FormatIpProto implements CriterionTypeFormatter {
@Override
public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
final IPProtocolCriterion iPProtocolCriterion =
(IPProtocolCriterion) criterion;
return root.put(CriterionCodec.PROTOCOL, iPProtocolCriterion.protocol());
}
}
private static class FormatIp implements CriterionTypeFormatter {
@Override
public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
final IPCriterion iPCriterion = (IPCriterion) criterion;
return root.put(CriterionCodec.IP, iPCriterion.ip().toString());
}
}
private static class FormatTcp implements CriterionTypeFormatter {
@Override
public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
final TcpPortCriterion tcpPortCriterion =
(TcpPortCriterion) criterion;
return root.put(CriterionCodec.TCP_PORT, tcpPortCriterion.tcpPort());
}
}
private static class FormatUdp implements CriterionTypeFormatter {
@Override
public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
final UdpPortCriterion udpPortCriterion =
(UdpPortCriterion) criterion;
return root.put(CriterionCodec.UDP_PORT, udpPortCriterion.udpPort());
}
}
private static class FormatSctp implements CriterionTypeFormatter {
@Override
public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
final SctpPortCriterion sctpPortCriterion =
(SctpPortCriterion) criterion;
return root.put(CriterionCodec.SCTP_PORT, sctpPortCriterion.sctpPort());
}
}
private static class FormatIcmpV4Type implements CriterionTypeFormatter {
@Override
public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
final IcmpTypeCriterion icmpTypeCriterion =
(IcmpTypeCriterion) criterion;
return root.put(CriterionCodec.ICMP_TYPE, icmpTypeCriterion.icmpType());
}
}
private static class FormatIcmpV4Code implements CriterionTypeFormatter {
@Override
public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
final IcmpCodeCriterion icmpCodeCriterion =
(IcmpCodeCriterion) criterion;
return root.put(CriterionCodec.ICMP_CODE, icmpCodeCriterion.icmpCode());
}
}
private static class FormatIpV6FLabel implements CriterionTypeFormatter {
@Override
public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
final IPv6FlowLabelCriterion ipv6FlowLabelCriterion =
(IPv6FlowLabelCriterion) criterion;
return root.put(CriterionCodec.FLOW_LABEL, ipv6FlowLabelCriterion.flowLabel());
}
}
private static class FormatIcmpV6Type implements CriterionTypeFormatter {
@Override
public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
final Icmpv6TypeCriterion icmpv6TypeCriterion =
(Icmpv6TypeCriterion) criterion;
return root.put(CriterionCodec.ICMPV6_TYPE, icmpv6TypeCriterion.icmpv6Type());
}
}
private static class FormatIcmpV6Code implements CriterionTypeFormatter {
@Override
public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
final Icmpv6CodeCriterion icmpv6CodeCriterion =
(Icmpv6CodeCriterion) criterion;
return root.put(CriterionCodec.ICMPV6_CODE, icmpv6CodeCriterion.icmpv6Code());
}
}
private static class FormatV6NDTarget implements CriterionTypeFormatter {
@Override
public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
final IPv6NDTargetAddressCriterion ipv6NDTargetAddressCriterion
= (IPv6NDTargetAddressCriterion) criterion;
return root.put(CriterionCodec.TARGET_ADDRESS, ipv6NDTargetAddressCriterion.targetAddress().toString());
}
}
private static class FormatV6NDTll implements CriterionTypeFormatter {
@Override
public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
final IPv6NDLinkLayerAddressCriterion ipv6NDLinkLayerAddressCriterion
= (IPv6NDLinkLayerAddressCriterion) criterion;
return root.put(CriterionCodec.MAC, ipv6NDLinkLayerAddressCriterion.mac().toString());
}
}
private static class FormatMplsLabel implements CriterionTypeFormatter {
@Override
public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
final MplsCriterion mplsCriterion =
(MplsCriterion) criterion;
return root.put(CriterionCodec.LABEL, mplsCriterion.label().toInt());
}
}
private static class FormatIpV6Exthdr implements CriterionTypeFormatter {
@Override
public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
final IPv6ExthdrFlagsCriterion exthdrCriterion =
(IPv6ExthdrFlagsCriterion) criterion;
return root.put(CriterionCodec.EXT_HDR_FLAGS, exthdrCriterion.exthdrFlags());
}
}
private static class FormatOchSigId implements CriterionTypeFormatter {
@Override
public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
OchSignal ochSignal = ((OchSignalCriterion) criterion).lambda();
ObjectNode child = root.putObject(CriterionCodec.OCH_SIGNAL_ID);
child.put(CriterionCodec.GRID_TYPE, ochSignal.gridType().name());
child.put(CriterionCodec.CHANNEL_SPACING, ochSignal.channelSpacing().name());
child.put(CriterionCodec.SPACING_MULIPLIER, ochSignal.spacingMultiplier());
child.put(CriterionCodec.SLOT_GRANULARITY, ochSignal.slotGranularity());
return root;
}
}
private static class FormatOchSigType implements CriterionTypeFormatter {
@Override
public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
final OchSignalTypeCriterion ochSignalTypeCriterion =
(OchSignalTypeCriterion) criterion;
return root.put("ochSignalType", ochSignalTypeCriterion.signalType().name());
}
}
private class FormatDummyType implements CriterionTypeFormatter {
@Override
public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
checkNotNull(criterion, "Criterion cannot be null");
return root.put(CriterionCodec.TYPE, criterion.type().toString());
}
}
/**
* Encodes a criterion into a JSON node.
*
* @return encoded JSON object for the given criterion
*/
public ObjectNode encode() {
final ObjectNode result = context.mapper().createObjectNode()
.put(CriterionCodec.TYPE, criterion.type().toString());
CriterionTypeFormatter formatter =
checkNotNull(
formatMap.get(criterion.type()),
"No formatter found for criterion type "
+ criterion.type().toString());
return formatter.encodeCriterion(result, criterion);
}
}
/*
* 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 org.onosproject.codec.CodecContext;
import org.onosproject.net.OchSignal;
import org.onosproject.net.flow.instructions.Instruction;
import org.onosproject.net.flow.instructions.Instructions;
import org.onosproject.net.flow.instructions.L0ModificationInstruction;
import org.onosproject.net.flow.instructions.L2ModificationInstruction;
import org.onosproject.net.flow.instructions.L3ModificationInstruction;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.databind.node.ObjectNode;
/**
* JSON encoding of Instructions.
*/
public final class EncodeInstructionCodec {
protected static final Logger log = LoggerFactory.getLogger(EncodeInstructionCodec.class);
private final Instruction instruction;
private final CodecContext context;
/**
* Creates an instruction object encoder.
*
* @param instruction instruction to encode
* @param context codec context for the encoding
*/
public EncodeInstructionCodec(Instruction instruction, CodecContext context) {
this.instruction = instruction;
this.context = context;
}
/**
* Encode an L0 modification instruction.
*
* @param result json node that the instruction attributes are added to
*/
private void encodeL0(ObjectNode result) {
L0ModificationInstruction instruction =
(L0ModificationInstruction) this.instruction;
result.put(InstructionCodec.SUBTYPE, instruction.subtype().name());
switch (instruction.subtype()) {
case LAMBDA:
final L0ModificationInstruction.ModLambdaInstruction modLambdaInstruction =
(L0ModificationInstruction.ModLambdaInstruction) instruction;
result.put(InstructionCodec.LAMBDA, modLambdaInstruction.lambda());
break;
case OCH:
L0ModificationInstruction.ModOchSignalInstruction ochSignalInstruction =
(L0ModificationInstruction.ModOchSignalInstruction) instruction;
OchSignal ochSignal = ochSignalInstruction.lambda();
result.put(InstructionCodec.GRID_TYPE, ochSignal.gridType().name());
result.put(InstructionCodec.CHANNEL_SPACING, ochSignal.channelSpacing().name());
result.put(InstructionCodec.SPACING_MULTIPLIER, ochSignal.spacingMultiplier());
result.put(InstructionCodec.SLOT_GRANULARITY, ochSignal.slotGranularity());
break;
default:
log.info("Cannot convert L0 subtype of {}", instruction.subtype());
}
}
/**
* Encode an L2 modification instruction.
*
* @param result json node that the instruction attributes are added to
*/
private void encodeL2(ObjectNode result) {
L2ModificationInstruction instruction =
(L2ModificationInstruction) this.instruction;
result.put(InstructionCodec.SUBTYPE, instruction.subtype().name());
switch (instruction.subtype()) {
case ETH_SRC:
case ETH_DST:
final L2ModificationInstruction.ModEtherInstruction modEtherInstruction =
(L2ModificationInstruction.ModEtherInstruction) instruction;
result.put(InstructionCodec.MAC, modEtherInstruction.mac().toString());
break;
case VLAN_ID:
final L2ModificationInstruction.ModVlanIdInstruction modVlanIdInstruction =
(L2ModificationInstruction.ModVlanIdInstruction) instruction;
result.put(InstructionCodec.VLAN_ID, modVlanIdInstruction.vlanId().toShort());
break;
case VLAN_PCP:
final L2ModificationInstruction.ModVlanPcpInstruction modVlanPcpInstruction =
(L2ModificationInstruction.ModVlanPcpInstruction) instruction;
result.put(InstructionCodec.VLAN_PCP, modVlanPcpInstruction.vlanPcp());
break;
case MPLS_LABEL:
final L2ModificationInstruction.ModMplsLabelInstruction modMplsLabelInstruction =
(L2ModificationInstruction.ModMplsLabelInstruction) instruction;
result.put(InstructionCodec.MPLS_LABEL, modMplsLabelInstruction.label());
break;
case MPLS_PUSH:
final L2ModificationInstruction.PushHeaderInstructions pushHeaderInstructions =
(L2ModificationInstruction.PushHeaderInstructions) instruction;
result.put(InstructionCodec.ETHERNET_TYPE, pushHeaderInstructions.ethernetType());
break;
default:
log.info("Cannot convert L2 subtype of {}", instruction.subtype());
break;
}
}
/**
* Encode an L3 modification instruction.
*
* @param result json node that the instruction attributes are added to
*/
private void encodeL3(ObjectNode result) {
L3ModificationInstruction instruction =
(L3ModificationInstruction) this.instruction;
result.put(InstructionCodec.SUBTYPE, instruction.subtype().name());
switch (instruction.subtype()) {
case IPV4_SRC:
case IPV4_DST:
case IPV6_SRC:
case IPV6_DST:
final L3ModificationInstruction.ModIPInstruction modIPInstruction =
(L3ModificationInstruction.ModIPInstruction) instruction;
result.put(InstructionCodec.IP, modIPInstruction.ip().toString());
break;
case IPV6_FLABEL:
final L3ModificationInstruction.ModIPv6FlowLabelInstruction
modFlowLabelInstruction =
(L3ModificationInstruction.ModIPv6FlowLabelInstruction) instruction;
result.put(InstructionCodec.FLOW_LABEL, modFlowLabelInstruction.flowLabel());
break;
default:
log.info("Cannot convert L3 subtype of {}", instruction.subtype());
break;
}
}
/**
* Encodes the given instruction into JSON.
*
* @return JSON object node representing the instruction
*/
public ObjectNode encode() {
final ObjectNode result = context.mapper().createObjectNode()
.put(InstructionCodec.TYPE, instruction.type().toString());
switch (instruction.type()) {
case OUTPUT:
final Instructions.OutputInstruction outputInstruction =
(Instructions.OutputInstruction) instruction;
result.put(InstructionCodec.PORT, outputInstruction.port().toLong());
break;
case DROP:
break;
case L0MODIFICATION:
encodeL0(result);
break;
case L2MODIFICATION:
encodeL2(result);
break;
case L3MODIFICATION:
encodeL3(result);
break;
default:
log.info("Cannot convert instruction type of {}", instruction.type());
break;
}
return result;
}
}
/*
* 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 org.onosproject.codec.CodecContext;
import org.onosproject.codec.JsonCodec;
import org.onosproject.core.CoreService;
import org.onosproject.net.DeviceId;
import org.onosproject.net.flow.DefaultFlowRule;
import org.onosproject.net.flow.FlowRule;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
import com.fasterxml.jackson.databind.node.ObjectNode;
import static org.onlab.util.Tools.nullIsIllegal;
/**
* Flow rule JSON codec.
*/
public final class FlowRuleCodec extends JsonCodec<FlowRule> {
private static final String APP_ID = "appId";
private static final String PRIORITY = "priority";
private static final String TIMEOUT = "timeout";
private static final String IS_PERMANENT = "isPermanent";
private static final String DEVICE_ID = "deviceId";
private static final String TREATMENT = "treatment";
private static final String SELECTOR = "selector";
private static final String MISSING_MEMBER_MESSAGE =
" member is required in FlowRule";
@Override
public FlowRule decode(ObjectNode json, CodecContext context) {
if (json == null || !json.isObject()) {
return null;
}
FlowRule.Builder resultBuilder = new DefaultFlowRule.Builder();
short appId = nullIsIllegal(json.get(APP_ID),
APP_ID + MISSING_MEMBER_MESSAGE).shortValue();
CoreService coreService = context.getService(CoreService.class);
resultBuilder.fromApp(coreService.getAppId(appId));
int priority = nullIsIllegal(json.get(PRIORITY),
PRIORITY + MISSING_MEMBER_MESSAGE).asInt();
resultBuilder.withPriority(priority);
boolean isPermanent = nullIsIllegal(json.get(IS_PERMANENT),
IS_PERMANENT + MISSING_MEMBER_MESSAGE).asBoolean();
if (isPermanent) {
resultBuilder.makePermanent();
} else {
resultBuilder.makeTemporary(nullIsIllegal(json.get(TIMEOUT),
TIMEOUT
+ MISSING_MEMBER_MESSAGE
+ " if the flow is temporary").asInt());
}
DeviceId deviceId = DeviceId.deviceId(nullIsIllegal(json.get(DEVICE_ID),
DEVICE_ID + MISSING_MEMBER_MESSAGE).asText());
resultBuilder.forDevice(deviceId);
ObjectNode treatmentJson = (ObjectNode) json.get(TREATMENT);
if (treatmentJson != null) {
JsonCodec<TrafficTreatment> treatmentCodec =
context.codec(TrafficTreatment.class);
resultBuilder.withTreatment(treatmentCodec.decode(treatmentJson, context));
}
ObjectNode selectorJson = (ObjectNode) json.get(SELECTOR);
if (selectorJson != null) {
JsonCodec<TrafficSelector> selectorCodec =
context.codec(TrafficSelector.class);
resultBuilder.withSelector(selectorCodec.decode(selectorJson, context));
}
return resultBuilder.build();
}
}
......@@ -17,12 +17,7 @@ package org.onosproject.codec.impl;
import org.onosproject.codec.CodecContext;
import org.onosproject.codec.JsonCodec;
import org.onosproject.net.OchSignal;
import org.onosproject.net.flow.instructions.Instruction;
import org.onosproject.net.flow.instructions.Instructions;
import org.onosproject.net.flow.instructions.L0ModificationInstruction;
import org.onosproject.net.flow.instructions.L2ModificationInstruction;
import org.onosproject.net.flow.instructions.L3ModificationInstruction;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
......@@ -37,159 +32,39 @@ public final class InstructionCodec extends JsonCodec<Instruction> {
protected static final Logger log = LoggerFactory.getLogger(InstructionCodec.class);
/**
* Encode an L0 modification instruction.
*
* @param result json node that the instruction attributes are added to
* @param instruction The L0 instruction
*/
private void encodeL0(ObjectNode result, L0ModificationInstruction instruction) {
result.put("subtype", instruction.subtype().name());
switch (instruction.subtype()) {
case LAMBDA:
final L0ModificationInstruction.ModLambdaInstruction modLambdaInstruction =
(L0ModificationInstruction.ModLambdaInstruction) instruction;
result.put("lambda", modLambdaInstruction.lambda());
break;
case OCH:
L0ModificationInstruction.ModOchSignalInstruction ochSignalInstruction =
(L0ModificationInstruction.ModOchSignalInstruction) instruction;
OchSignal ochSignal = ochSignalInstruction.lambda();
result.put("gridType", ochSignal.gridType().name());
result.put("channelSpacing", ochSignal.channelSpacing().name());
result.put("spacingMultiplier", ochSignal.spacingMultiplier());
result.put("slotGranularity", ochSignal.slotGranularity());
break;
default:
log.info("Cannot convert L0 subtype of {}", instruction.subtype());
}
}
/**
* Encode an L2 modification instruction.
*
* @param result json node that the instruction attributes are added to
* @param instruction The L2 instruction
* @param context context of the request
*/
private void encodeL2(ObjectNode result,
L2ModificationInstruction instruction,
CodecContext context) {
result.put("subtype", instruction.subtype().name());
switch (instruction.subtype()) {
case ETH_SRC:
case ETH_DST:
final L2ModificationInstruction.ModEtherInstruction modEtherInstruction =
(L2ModificationInstruction.ModEtherInstruction) instruction;
result.put("mac", modEtherInstruction.mac().toString());
break;
case VLAN_ID:
final L2ModificationInstruction.ModVlanIdInstruction modVlanIdInstruction =
(L2ModificationInstruction.ModVlanIdInstruction) instruction;
result.put("vlanId", modVlanIdInstruction.vlanId().toShort());
break;
case VLAN_PCP:
final L2ModificationInstruction.ModVlanPcpInstruction modVlanPcpInstruction =
(L2ModificationInstruction.ModVlanPcpInstruction) instruction;
result.put("vlanPcp", modVlanPcpInstruction.vlanPcp());
break;
case MPLS_LABEL:
final L2ModificationInstruction.ModMplsLabelInstruction modMplsLabelInstruction =
(L2ModificationInstruction.ModMplsLabelInstruction) instruction;
result.put("label", modMplsLabelInstruction.label());
break;
case MPLS_PUSH:
final L2ModificationInstruction.PushHeaderInstructions pushHeaderInstructions =
(L2ModificationInstruction.PushHeaderInstructions) instruction;
result.put("ethernetType", pushHeaderInstructions.ethernetType());
break;
default:
log.info("Cannot convert L2 subtype of {}", instruction.subtype());
break;
}
}
/**
* Encode an L3 modification instruction.
*
* @param result json node that the instruction attributes are added to
* @param instruction The L3 instruction
*/
private void encodeL3(ObjectNode result, L3ModificationInstruction instruction) {
result.put("subtype", instruction.subtype().name());
switch (instruction.subtype()) {
case IPV4_SRC:
case IPV4_DST:
case IPV6_SRC:
case IPV6_DST:
final L3ModificationInstruction.ModIPInstruction modIPInstruction =
(L3ModificationInstruction.ModIPInstruction) instruction;
result.put("ip", modIPInstruction.ip().toString());
break;
protected static final String TYPE = "type";
protected static final String SUBTYPE = "subtype";
protected static final String PORT = "port";
protected static final String MAC = "mac";
protected static final String VLAN_ID = "vlanId";
protected static final String VLAN_PCP = "vlanPcp";
protected static final String MPLS_LABEL = "label";
protected static final String IP = "ip";
protected static final String FLOW_LABEL = "flowLabel";
protected static final String LAMBDA = "lambda";
protected static final String GRID_TYPE = "gridType";
protected static final String CHANNEL_SPACING = "channelSpacing";
protected static final String SPACING_MULTIPLIER = "spacingMultiplier";
protected static final String SLOT_GRANULARITY = "slotGranularity";
protected static final String ETHERNET_TYPE = "ethernetType";
protected static final String MISSING_MEMBER_MESSAGE =
" member is required in Instruction";
case IPV6_FLABEL:
final L3ModificationInstruction.ModIPv6FlowLabelInstruction
modFlowLabelInstruction =
(L3ModificationInstruction.ModIPv6FlowLabelInstruction) instruction;
result.put("flowLabel", modFlowLabelInstruction.flowLabel());
break;
default:
log.info("Cannot convert L3 subtype of {}", instruction.subtype());
break;
}
}
@Override
public ObjectNode encode(Instruction instruction, CodecContext context) {
checkNotNull(instruction, "Instruction cannot be null");
final ObjectNode result = context.mapper().createObjectNode()
.put("type", instruction.type().toString());
switch (instruction.type()) {
case OUTPUT:
final Instructions.OutputInstruction outputInstruction =
(Instructions.OutputInstruction) instruction;
result.put("port", outputInstruction.port().toLong());
break;
case DROP:
break;
case L0MODIFICATION:
final L0ModificationInstruction l0ModificationInstruction =
(L0ModificationInstruction) instruction;
encodeL0(result, l0ModificationInstruction);
break;
case L2MODIFICATION:
final L2ModificationInstruction l2ModificationInstruction =
(L2ModificationInstruction) instruction;
encodeL2(result, l2ModificationInstruction, context);
break;
case L3MODIFICATION:
final L3ModificationInstruction l3ModificationInstruction =
(L3ModificationInstruction) instruction;
encodeL3(result, l3ModificationInstruction);
break;
return new EncodeInstructionCodec(instruction, context).encode();
}
default:
log.info("Cannot convert instruction type of {}", instruction.type());
break;
@Override
public Instruction decode(ObjectNode json, CodecContext context) {
if (json == null || !json.isObject()) {
return null;
}
return result;
return new DecodeInstructionCodec(json).decode();
}
}
......
......@@ -15,11 +15,15 @@
*/
package org.onosproject.codec.impl;
import java.util.stream.IntStream;
import org.onosproject.codec.CodecContext;
import org.onosproject.codec.JsonCodec;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.criteria.Criterion;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
......@@ -29,12 +33,14 @@ import static com.google.common.base.Preconditions.checkNotNull;
* Traffic selector codec.
*/
public final class TrafficSelectorCodec extends JsonCodec<TrafficSelector> {
private static final String CRITERIA = "criteria";
@Override
public ObjectNode encode(TrafficSelector selector, CodecContext context) {
checkNotNull(selector, "Traffic selector cannot be null");
final ObjectNode result = context.mapper().createObjectNode();
final ArrayNode jsonCriteria = result.putArray("criteria");
final ArrayNode jsonCriteria = result.putArray(CRITERIA);
if (selector.criteria() != null) {
final JsonCodec<Criterion> criterionCodec =
......@@ -46,4 +52,20 @@ public final class TrafficSelectorCodec extends JsonCodec<TrafficSelector> {
return result;
}
@Override
public TrafficSelector decode(ObjectNode json, CodecContext context) {
final JsonCodec<Criterion> criterionCodec =
context.codec(Criterion.class);
JsonNode criteriaJson = json.get(CRITERIA);
TrafficSelector.Builder builder = DefaultTrafficSelector.builder();
if (criteriaJson != null) {
IntStream.range(0, criteriaJson.size())
.forEach(i -> builder.add(
criterionCodec.decode((ObjectNode) criteriaJson.get(i),
context)));
}
return builder.build();
}
}
......
......@@ -15,11 +15,15 @@
*/
package org.onosproject.codec.impl;
import java.util.stream.IntStream;
import org.onosproject.codec.CodecContext;
import org.onosproject.codec.JsonCodec;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.flow.instructions.Instruction;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
......@@ -29,12 +33,14 @@ import static com.google.common.base.Preconditions.checkNotNull;
* Traffic treatment codec.
*/
public final class TrafficTreatmentCodec extends JsonCodec<TrafficTreatment> {
private static final String INSTRUCTIONS = "instructions";
@Override
public ObjectNode encode(TrafficTreatment treatment, CodecContext context) {
checkNotNull(treatment, "Traffic treatment cannot be null");
final ObjectNode result = context.mapper().createObjectNode();
final ArrayNode jsonInstructions = result.putArray("instructions");
final ArrayNode jsonInstructions = result.putArray(INSTRUCTIONS);
final JsonCodec<Instruction> instructionCodec =
context.codec(Instruction.class);
......@@ -51,4 +57,20 @@ public final class TrafficTreatmentCodec extends JsonCodec<TrafficTreatment> {
return result;
}
@Override
public TrafficTreatment decode(ObjectNode json, CodecContext context) {
final JsonCodec<Instruction> instructionsCodec =
context.codec(Instruction.class);
JsonNode instructionsJson = json.get(INSTRUCTIONS);
TrafficTreatment.Builder builder = DefaultTrafficTreatment.builder();
if (instructionsJson != null) {
IntStream.range(0, instructionsJson.size())
.forEach(i -> builder.add(
instructionsCodec.decode((ObjectNode) instructionsJson.get(i),
context)));
}
return builder.build();
}
}
......
......@@ -72,8 +72,10 @@ public class CriterionCodecTest {
*/
@Test
public void checkCriterionTypes() throws Exception {
EncodeCriterionCodec encoder = new EncodeCriterionCodec(
Criteria.dummy(), context);
EnumMap<Criterion.Type, Object> formatMap =
getField(criterionCodec, "formatMap");
getField(encoder, "formatMap");
assertThat(formatMap, notNullValue());
for (Criterion.Type type : Criterion.Type.values()) {
......
/*
* 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 java.io.IOException;
import java.io.InputStream;
import java.util.SortedMap;
import java.util.TreeMap;
import org.junit.Before;
import org.junit.Test;
import org.onlab.packet.Ethernet;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
import org.onlab.packet.MplsLabel;
import org.onlab.packet.VlanId;
import org.onosproject.codec.JsonCodec;
import org.onosproject.core.CoreService;
import org.onosproject.net.ChannelSpacing;
import org.onosproject.net.GridType;
import org.onosproject.net.Lambda;
import org.onosproject.net.OchSignal;
import org.onosproject.net.PortNumber;
import org.onosproject.net.flow.FlowRule;
import org.onosproject.net.flow.criteria.Criterion;
import org.onosproject.net.flow.criteria.EthCriterion;
import org.onosproject.net.flow.criteria.EthTypeCriterion;
import org.onosproject.net.flow.criteria.IPCriterion;
import org.onosproject.net.flow.criteria.IPDscpCriterion;
import org.onosproject.net.flow.criteria.IPEcnCriterion;
import org.onosproject.net.flow.criteria.IPProtocolCriterion;
import org.onosproject.net.flow.criteria.IPv6ExthdrFlagsCriterion;
import org.onosproject.net.flow.criteria.IPv6FlowLabelCriterion;
import org.onosproject.net.flow.criteria.IPv6NDLinkLayerAddressCriterion;
import org.onosproject.net.flow.criteria.IPv6NDTargetAddressCriterion;
import org.onosproject.net.flow.criteria.IcmpCodeCriterion;
import org.onosproject.net.flow.criteria.IcmpTypeCriterion;
import org.onosproject.net.flow.criteria.Icmpv6CodeCriterion;
import org.onosproject.net.flow.criteria.Icmpv6TypeCriterion;
import org.onosproject.net.flow.criteria.IndexedLambdaCriterion;
import org.onosproject.net.flow.criteria.MplsCriterion;
import org.onosproject.net.flow.criteria.OchSignalCriterion;
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.UdpPortCriterion;
import org.onosproject.net.flow.criteria.VlanIdCriterion;
import org.onosproject.net.flow.criteria.VlanPcpCriterion;
import org.onosproject.net.flow.instructions.Instruction;
import org.onosproject.net.flow.instructions.Instructions;
import org.onosproject.net.flow.instructions.L0ModificationInstruction;
import org.onosproject.net.flow.instructions.L2ModificationInstruction;
import org.onosproject.net.flow.instructions.L3ModificationInstruction;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.onosproject.net.NetTestTools.APP_ID;
/**
* Flow rule codec unit tests.
*/
public class FlowRuleCodecTest {
MockCodecContext context;
JsonCodec<FlowRule> flowRuleCodec;
final CoreService mockCoreService = createMock(CoreService.class);
/**
* Sets up for each test. Creates a context and fetches the flow rule
* codec.
*/
@Before
public void setUp() {
context = new MockCodecContext();
flowRuleCodec = context.codec(FlowRule.class);
assertThat(flowRuleCodec, notNullValue());
expect(mockCoreService.getAppId(APP_ID.id()))
.andReturn(APP_ID).anyTimes();
replay(mockCoreService);
context.registerService(CoreService.class, mockCoreService);
}
/**
* Reads in a rule from the given resource and decodes it.
*
* @param resourceName resource to use to read the JSON for the rule
* @return decoded flow rule
* @throws IOException if processing the resource fails
*/
private FlowRule getRule(String resourceName) throws IOException {
InputStream jsonStream = FlowRuleCodecTest.class
.getResourceAsStream(resourceName);
JsonNode json = context.mapper().readTree(jsonStream);
assertThat(json, notNullValue());
FlowRule rule = flowRuleCodec.decode((ObjectNode) json, context);
assertThat(rule, notNullValue());
return rule;
}
/**
* Checks that the data shared by all the resources is correct for a
* given rule.
*
* @param rule rule to check
*/
private void checkCommonData(FlowRule rule) {
assertThat(rule.appId(), is(APP_ID.id()));
assertThat(rule.isPermanent(), is(false));
assertThat(rule.timeout(), is(1));
assertThat(rule.priority(), is(1));
assertThat(rule.deviceId().toString(), is("of:0000000000000001"));
}
/**
* Checks that a simple rule decodes properly.
*
* @throws IOException if the resource cannot be processed
*/
@Test
public void codecSimpleFlowTest() throws IOException {
FlowRule rule = getRule("simple-flow.json");
checkCommonData(rule);
assertThat(rule.selector().criteria().size(), is(1));
Criterion criterion1 = rule.selector().criteria().iterator().next();
assertThat(criterion1.type(), is(Criterion.Type.ETH_TYPE));
assertThat(((EthTypeCriterion) criterion1).ethType(), is(2054));
assertThat(rule.treatment().allInstructions().size(), is(1));
Instruction instruction1 = rule.treatment().allInstructions().get(0);
assertThat(instruction1.type(), is(Instruction.Type.OUTPUT));
assertThat(((Instructions.OutputInstruction) instruction1).port(), is(PortNumber.CONTROLLER));
}
SortedMap<String, Instruction> instructions = new TreeMap<>();
/**
* Looks up an instruction in the instruction map based on type and subtype.
*
* @param type type string
* @param subType subtype string
* @return instruction that matches
*/
private Instruction getInstruction(Instruction.Type type, String subType) {
Instruction instruction = instructions.get(type.name() + "/" + subType);
assertThat(instruction, notNullValue());
assertThat(instruction.type(), is(type));
return instruction;
}
/**
* Checks that a rule with one of each instruction type decodes properly.
*
* @throws IOException if the resource cannot be processed
*/
@Test
public void decodeInstructionsFlowTest() throws Exception {
FlowRule rule = getRule("instructions-flow.json");
checkCommonData(rule);
rule.treatment().allInstructions()
.stream()
.forEach(instruction ->
{
String subType;
if (instruction.type() == Instruction.Type.L0MODIFICATION) {
subType = ((L0ModificationInstruction) instruction)
.subtype().name();
} else if (instruction.type() == Instruction.Type.L2MODIFICATION) {
subType = ((L2ModificationInstruction) instruction)
.subtype().name();
} else if (instruction.type() == Instruction.Type.L3MODIFICATION) {
subType = ((L3ModificationInstruction) instruction)
.subtype().name();
} else {
subType = "";
}
instructions.put(
instruction.type().name() + "/" + subType, instruction);
});
assertThat(rule.treatment().allInstructions().size(), is(19));
Instruction instruction;
instruction = getInstruction(Instruction.Type.OUTPUT, "");
assertThat(instruction.type(), is(Instruction.Type.OUTPUT));
assertThat(((Instructions.OutputInstruction) instruction).port(), is(PortNumber.CONTROLLER));
instruction = getInstruction(Instruction.Type.L2MODIFICATION,
L2ModificationInstruction.L2SubType.ETH_SRC.name());
assertThat(instruction.type(), is(Instruction.Type.L2MODIFICATION));
assertThat(((L2ModificationInstruction.ModEtherInstruction) instruction).mac(),
is(MacAddress.valueOf("12:34:56:78:90:12")));
instruction = getInstruction(Instruction.Type.L2MODIFICATION,
L2ModificationInstruction.L2SubType.ETH_DST.name());
assertThat(instruction.type(), is(Instruction.Type.L2MODIFICATION));
assertThat(((L2ModificationInstruction.ModEtherInstruction) instruction).mac(),
is(MacAddress.valueOf("98:76:54:32:01:00")));
instruction = getInstruction(Instruction.Type.L2MODIFICATION,
L2ModificationInstruction.L2SubType.VLAN_ID.name());
assertThat(instruction.type(), is(Instruction.Type.L2MODIFICATION));
assertThat(((L2ModificationInstruction.ModVlanIdInstruction) instruction).vlanId().toShort(),
is((short) 22));
instruction = getInstruction(Instruction.Type.L2MODIFICATION,
L2ModificationInstruction.L2SubType.VLAN_PCP.name());
assertThat(instruction.type(), is(Instruction.Type.L2MODIFICATION));
assertThat(((L2ModificationInstruction.ModVlanPcpInstruction) instruction).vlanPcp(),
is((byte) 1));
instruction = getInstruction(Instruction.Type.L2MODIFICATION,
L2ModificationInstruction.L2SubType.MPLS_LABEL.name());
assertThat(instruction.type(), is(Instruction.Type.L2MODIFICATION));
assertThat(((L2ModificationInstruction.ModMplsLabelInstruction) instruction)
.label().shortValue(),
is((short) 777));
instruction = getInstruction(Instruction.Type.L2MODIFICATION,
L2ModificationInstruction.L2SubType.MPLS_PUSH.name());
assertThat(instruction.type(), is(Instruction.Type.L2MODIFICATION));
assertThat((short) ((L2ModificationInstruction.PushHeaderInstructions) instruction)
.ethernetType(),
is(Ethernet.MPLS_UNICAST));
instruction = getInstruction(Instruction.Type.L2MODIFICATION,
L2ModificationInstruction.L2SubType.MPLS_POP.name());
assertThat(instruction.type(), is(Instruction.Type.L2MODIFICATION));
assertThat((short) ((L2ModificationInstruction.PushHeaderInstructions) instruction)
.ethernetType(),
is(Ethernet.MPLS_UNICAST));
instruction = getInstruction(Instruction.Type.L2MODIFICATION,
L2ModificationInstruction.L2SubType.DEC_MPLS_TTL.name());
assertThat(instruction.type(), is(Instruction.Type.L2MODIFICATION));
assertThat(instruction, instanceOf(L2ModificationInstruction.ModMplsTtlInstruction.class));
instruction = getInstruction(Instruction.Type.L2MODIFICATION,
L2ModificationInstruction.L2SubType.VLAN_POP.name());
assertThat(instruction.type(), is(Instruction.Type.L2MODIFICATION));
assertThat(instruction, instanceOf(L2ModificationInstruction.PopVlanInstruction.class));
instruction = getInstruction(Instruction.Type.L2MODIFICATION,
L2ModificationInstruction.L2SubType.VLAN_PUSH.name());
assertThat(instruction.type(), is(Instruction.Type.L2MODIFICATION));
assertThat(instruction, instanceOf(L2ModificationInstruction.PushHeaderInstructions.class));
instruction = getInstruction(Instruction.Type.L3MODIFICATION,
L3ModificationInstruction.L3SubType.IPV4_SRC.name());
assertThat(instruction.type(), is(Instruction.Type.L3MODIFICATION));
assertThat(((L3ModificationInstruction.ModIPInstruction) instruction).ip(),
is(IpAddress.valueOf("1.2.3.4")));
instruction = getInstruction(Instruction.Type.L3MODIFICATION,
L3ModificationInstruction.L3SubType.IPV4_DST.name());
assertThat(instruction.type(), is(Instruction.Type.L3MODIFICATION));
assertThat(((L3ModificationInstruction.ModIPInstruction) instruction).ip(),
is(IpAddress.valueOf("1.2.3.3")));
instruction = getInstruction(Instruction.Type.L3MODIFICATION,
L3ModificationInstruction.L3SubType.IPV6_SRC.name());
assertThat(instruction.type(), is(Instruction.Type.L3MODIFICATION));
assertThat(((L3ModificationInstruction.ModIPInstruction) instruction).ip(),
is(IpAddress.valueOf("1.2.3.2")));
instruction = getInstruction(Instruction.Type.L3MODIFICATION,
L3ModificationInstruction.L3SubType.IPV6_DST.name());
assertThat(instruction.type(), is(Instruction.Type.L3MODIFICATION));
assertThat(((L3ModificationInstruction.ModIPInstruction) instruction).ip(),
is(IpAddress.valueOf("1.2.3.1")));
instruction = getInstruction(Instruction.Type.L3MODIFICATION,
L3ModificationInstruction.L3SubType.IPV6_FLABEL.name());
assertThat(instruction.type(), is(Instruction.Type.L3MODIFICATION));
assertThat(((L3ModificationInstruction.ModIPv6FlowLabelInstruction) instruction)
.flowLabel(),
is(8));
instruction = getInstruction(Instruction.Type.L0MODIFICATION,
L0ModificationInstruction.L0SubType.LAMBDA.name());
assertThat(instruction.type(), is(Instruction.Type.L0MODIFICATION));
assertThat(((L0ModificationInstruction.ModLambdaInstruction) instruction)
.lambda(),
is((short) 7));
instruction = getInstruction(Instruction.Type.L0MODIFICATION,
L0ModificationInstruction.L0SubType.OCH.name());
assertThat(instruction.type(), is(Instruction.Type.L0MODIFICATION));
L0ModificationInstruction.ModOchSignalInstruction och =
(L0ModificationInstruction.ModOchSignalInstruction) instruction;
assertThat(och.lambda().spacingMultiplier(), is(4));
assertThat(och.lambda().slotGranularity(), is(8));
assertThat(och.lambda().gridType(), is(GridType.DWDM));
assertThat(och.lambda().channelSpacing(), is(ChannelSpacing.CHL_100GHZ));
}
SortedMap<String, Criterion> criteria = new TreeMap<>();
/**
* Looks up a criterion in the instruction map based on type and subtype.
*
* @param type type string
* @return criterion that matches
*/
private Criterion getCriterion(Criterion.Type type) {
Criterion criterion = criteria.get(type.name());
assertThat(criterion.type(), is(type));
return criterion;
}
/**
* Checks that a rule with one of each kind of criterion decodes properly.
*
* @throws IOException if the resource cannot be processed
*/
@Test
public void codecCriteriaFlowTest() throws Exception {
FlowRule rule = getRule("criteria-flow.json");
checkCommonData(rule);
assertThat(rule.selector().criteria().size(), is(32));
rule.selector().criteria()
.stream()
.forEach(criterion ->
criteria.put(criterion.type().name(), criterion));
Criterion criterion;
criterion = getCriterion(Criterion.Type.ETH_TYPE);
assertThat(((EthTypeCriterion) criterion).ethType(), is(2054));
criterion = getCriterion(Criterion.Type.ETH_DST);
assertThat(((EthCriterion) criterion).mac(),
is(MacAddress.valueOf("00:11:22:33:44:55")));
criterion = getCriterion(Criterion.Type.ETH_SRC);
assertThat(((EthCriterion) criterion).mac(),
is(MacAddress.valueOf("00:11:22:33:44:55")));
criterion = getCriterion(Criterion.Type.IN_PORT);
assertThat(((PortCriterion) criterion).port(),
is(PortNumber.portNumber(23)));
criterion = getCriterion(Criterion.Type.IN_PHY_PORT);
assertThat(((PortCriterion) criterion).port(),
is(PortNumber.portNumber(44)));
criterion = getCriterion(Criterion.Type.VLAN_VID);
assertThat(((VlanIdCriterion) criterion).vlanId(),
is(VlanId.vlanId((short) 777)));
criterion = getCriterion(Criterion.Type.VLAN_PCP);
assertThat(((VlanPcpCriterion) criterion).priority(),
is(((byte) 3)));
criterion = getCriterion(Criterion.Type.IP_DSCP);
assertThat(((IPDscpCriterion) criterion).ipDscp(),
is(((byte) 2)));
criterion = getCriterion(Criterion.Type.IP_ECN);
assertThat(((IPEcnCriterion) criterion).ipEcn(),
is(((byte) 1)));
criterion = getCriterion(Criterion.Type.IP_PROTO);
assertThat(((IPProtocolCriterion) criterion).protocol(),
is(((short) 4)));
criterion = getCriterion(Criterion.Type.IPV4_SRC);
assertThat(((IPCriterion) criterion).ip(),
is((IpPrefix.valueOf("1.2.0.0/32"))));
criterion = getCriterion(Criterion.Type.IPV4_DST);
assertThat(((IPCriterion) criterion).ip(),
is((IpPrefix.valueOf("2.2.0.0/32"))));
criterion = getCriterion(Criterion.Type.IPV6_SRC);
assertThat(((IPCriterion) criterion).ip(),
is((IpPrefix.valueOf("3.2.0.0/32"))));
criterion = getCriterion(Criterion.Type.IPV6_DST);
assertThat(((IPCriterion) criterion).ip(),
is((IpPrefix.valueOf("4.2.0.0/32"))));
criterion = getCriterion(Criterion.Type.TCP_SRC);
assertThat(((TcpPortCriterion) criterion).tcpPort(),
is(80));
criterion = getCriterion(Criterion.Type.TCP_DST);
assertThat(((TcpPortCriterion) criterion).tcpPort(),
is(443));
criterion = getCriterion(Criterion.Type.UDP_SRC);
assertThat(((UdpPortCriterion) criterion).udpPort(),
is(180));
criterion = getCriterion(Criterion.Type.UDP_DST);
assertThat(((UdpPortCriterion) criterion).udpPort(),
is(1443));
criterion = getCriterion(Criterion.Type.SCTP_SRC);
assertThat(((SctpPortCriterion) criterion).sctpPort(),
is(280));
criterion = getCriterion(Criterion.Type.SCTP_DST);
assertThat(((SctpPortCriterion) criterion).sctpPort(),
is(2443));
criterion = getCriterion(Criterion.Type.ICMPV4_TYPE);
assertThat(((IcmpTypeCriterion) criterion).icmpType(),
is((short) 24));
criterion = getCriterion(Criterion.Type.ICMPV4_CODE);
assertThat(((IcmpCodeCriterion) criterion).icmpCode(),
is((short) 16));
criterion = getCriterion(Criterion.Type.ICMPV6_TYPE);
assertThat(((Icmpv6TypeCriterion) criterion).icmpv6Type(),
is((short) 14));
criterion = getCriterion(Criterion.Type.ICMPV6_CODE);
assertThat(((Icmpv6CodeCriterion) criterion).icmpv6Code(),
is((short) 6));
criterion = getCriterion(Criterion.Type.IPV6_FLABEL);
assertThat(((IPv6FlowLabelCriterion) criterion).flowLabel(),
is(8));
criterion = getCriterion(Criterion.Type.IPV6_ND_TARGET);
assertThat(((IPv6NDTargetAddressCriterion) criterion)
.targetAddress().toString(),
is("1111:2222:3333:4444:5555:6666:7777:8888"));
criterion = getCriterion(Criterion.Type.IPV6_ND_SLL);
assertThat(((IPv6NDLinkLayerAddressCriterion) criterion).mac(),
is(MacAddress.valueOf("00:11:22:33:44:56")));
criterion = getCriterion(Criterion.Type.IPV6_ND_TLL);
assertThat(((IPv6NDLinkLayerAddressCriterion) criterion).mac(),
is(MacAddress.valueOf("00:11:22:33:44:57")));
criterion = getCriterion(Criterion.Type.MPLS_LABEL);
assertThat(((MplsCriterion) criterion).label(),
is(MplsLabel.mplsLabel(123)));
criterion = getCriterion(Criterion.Type.IPV6_EXTHDR);
assertThat(((IPv6ExthdrFlagsCriterion) criterion).exthdrFlags(),
is(99));
criterion = getCriterion(Criterion.Type.OCH_SIGID);
assertThat(((IndexedLambdaCriterion) criterion).lambda(),
is(Lambda.indexedLambda(122)));
}
/**
* Checks that a rule with a SigId criterion decodes properly.
*
* @throws IOException if the resource cannot be processed
*/
@Test
public void codecSigIdCriteriaFlowTest() throws Exception {
FlowRule rule = getRule("sigid-flow.json");
checkCommonData(rule);
assertThat(rule.selector().criteria().size(), is(1));
Criterion criterion = rule.selector().criteria().iterator().next();
assertThat(criterion.type(), is(Criterion.Type.OCH_SIGID));
Lambda lambda = ((OchSignalCriterion) criterion).lambda();
assertThat(lambda, instanceOf(OchSignal.class));
OchSignal ochSignal = (OchSignal) lambda;
assertThat(ochSignal.spacingMultiplier(), is(3));
assertThat(ochSignal.slotGranularity(), is(4));
assertThat(ochSignal.gridType(), is(GridType.CWDM));
assertThat(ochSignal.channelSpacing(), is(ChannelSpacing.CHL_25GHZ));
}
}
......@@ -38,6 +38,8 @@ public class ImmutableCodecsTest {
assertThatClassIsImmutable(ConnectPointCodec.class);
assertThatClassIsImmutable(ConstraintCodec.class);
assertThatClassIsImmutable(CriterionCodec.class);
assertThatClassIsImmutable(EncodeCriterionCodec.class);
assertThatClassIsImmutable(DecodeCriterionCodec.class);
assertThatClassIsImmutable(DeviceCodec.class);
assertThatClassIsImmutable(EthernetCodec.class);
assertThatClassIsImmutable(FlowEntryCodec.class);
......@@ -45,6 +47,8 @@ public class ImmutableCodecsTest {
assertThatClassIsImmutable(HostLocationCodec.class);
assertThatClassIsImmutable(HostToHostIntentCodec.class);
assertThatClassIsImmutable(InstructionCodec.class);
assertThatClassIsImmutable(EncodeInstructionCodec.class);
assertThatClassIsImmutable(DecodeInstructionCodec.class);
assertThatClassIsImmutable(IntentCodec.class);
assertThatClassIsImmutable(LinkCodec.class);
assertThatClassIsImmutable(PathCodec.class);
......@@ -54,5 +58,6 @@ public class ImmutableCodecsTest {
assertThatClassIsImmutable(TopologyCodec.class);
assertThatClassIsImmutable(TrafficSelectorCodec.class);
assertThatClassIsImmutable(TrafficTreatmentCodec.class);
assertThatClassIsImmutable(FlowRuleCodec.class);
}
}
......
{
"appId":-29467,
"priority":1,
"isPermanent":"false",
"timeout":1,
"deviceId":"of:0000000000000001",
"selector":
{"criteria":
[
{"type":"IN_PORT", "port":23},
{"type":"IN_PHY_PORT", "port":44},
{"type":"METADATA", "metadata":123456},
{"type":"ETH_TYPE","ethType":2054},
{"type":"ETH_SRC","mac":"00:11:22:33:44:55"},
{"type":"ETH_DST","mac":"00:11:22:33:44:55"},
{"type":"VLAN_VID","vlanId":777},
{"type":"VLAN_PCP","priority":3},
{"type":"IP_DSCP","ipDscp":2},
{"type":"IP_ECN","ipEcn":1},
{"type":"IP_PROTO","protocol":4},
{"type":"IPV4_SRC", "ip":"1.2.0.0/32"},
{"type":"IPV4_DST", "ip":"2.2.0.0/32"},
{"type":"IPV6_SRC", "ip":"3.2.0.0/32"},
{"type":"IPV6_DST", "ip":"4.2.0.0/32"},
{"type":"TCP_SRC", "tcpPort":80},
{"type":"TCP_DST", "tcpPort":443},
{"type":"UDP_SRC", "udpPort":180},
{"type":"UDP_DST", "udpPort":1443},
{"type":"SCTP_SRC", "sctpPort":280},
{"type":"SCTP_DST", "sctpPort":2443},
{"type":"ICMPV4_TYPE", "icmpType":24},
{"type":"ICMPV4_CODE", "icmpCode":16},
{"type":"ICMPV6_TYPE", "icmpv6Type":14},
{"type":"ICMPV6_CODE", "icmpv6Code":6},
{"type":"IPV6_FLABEL", "flowLabel":8},
{"type":"IPV6_ND_TARGET", "targetAddress":"1111:2222:3333:4444:5555:6666:7777:8888"},
{"type":"IPV6_ND_SLL", "mac":"00:11:22:33:44:56"},
{"type":"IPV6_ND_TLL", "mac":"00:11:22:33:44:57"},
{"type":"MPLS_LABEL", "label":123},
{"type":"IPV6_EXTHDR", "exthdrFlags":99},
{"type":"OCH_SIGID", "lambda":122}
]
}
}
{
"appId":-29467,
"priority":1,
"isPermanent":"false",
"timeout":1,
"deviceId":"of:0000000000000001",
"treatment":
{
"instructions":
[
{"type":"OUTPUT","port":-3},
{"type":"DROP"},
{"type":"L2MODIFICATION","subtype":"ETH_SRC","mac":"12:34:56:78:90:12"},
{"type":"L2MODIFICATION","subtype":"ETH_DST","mac":"98:76:54:32:01:00"},
{"type":"L2MODIFICATION","subtype":"VLAN_ID","vlanId":22},
{"type":"L2MODIFICATION","subtype":"VLAN_PCP","vlanPcp":1},
{"type":"L2MODIFICATION","subtype":"MPLS_LABEL","label":777},
{"type":"L2MODIFICATION","subtype":"MPLS_PUSH"},
{"type":"L2MODIFICATION","subtype":"MPLS_POP"},
{"type":"L2MODIFICATION","subtype":"DEC_MPLS_TTL"},
{"type":"L2MODIFICATION","subtype":"VLAN_POP"},
{"type":"L2MODIFICATION","subtype":"VLAN_PUSH"},
{"type":"L3MODIFICATION","subtype":"IPV4_SRC", "ip":"1.2.3.4"},
{"type":"L3MODIFICATION","subtype":"IPV4_DST", "ip":"1.2.3.3"},
{"type":"L3MODIFICATION","subtype":"IPV6_SRC", "ip":"1.2.3.2"},
{"type":"L3MODIFICATION","subtype":"IPV6_DST", "ip":"1.2.3.1"},
{"type":"L3MODIFICATION","subtype":"IPV6_FLABEL", "flowLabel":8},
{"type":"L0MODIFICATION","subtype":"LAMBDA","lambda":7},
{"type":"L0MODIFICATION","subtype":"OCH","gridType":"DWDM",
"channelSpacing":"CHL_100GHZ","spacingMultiplier":4,"slotGranularity":8}
],
"deferred":[]
},
"selector": {"criteria":[{"type":"ETH_TYPE","ethType":2054}]}
}
{
"appId":-29467,
"priority":1,
"isPermanent":"false",
"timeout":1,
"deviceId":"of:0000000000000001",
"selector":
{"criteria":
[
{"type":"OCH_SIGID",
"ochSignalId":
{
"gridType":"CWDM",
"channelSpacing":"CHL_25GHZ",
"spacingMultiplier":3,
"slotGranularity":4
}
}
]
}
}
{
"appId":-29467,
"priority":1,
"isPermanent":"false",
"timeout":1,
"deviceId":"of:0000000000000001",
"treatment":
{"instructions":
[{"type":"OUTPUT","port":-3}],"deferred":[]},
"selector":
{"criteria":
[{"type":"ETH_TYPE","ethType":2054}]}
}
......@@ -123,7 +123,7 @@ public abstract class Tools {
}
/**
* Returns the specified item if that items is null; otherwise throws
* Returns the specified item if that item is not null; otherwise throws
* not found exception.
*
* @param item item to check
......@@ -140,6 +140,23 @@ public abstract class Tools {
}
/**
* Returns the specified item if that item is not null; otherwise throws
* bad argument exception.
*
* @param item item to check
* @param message not found message
* @param <T> item type
* @return item if not null
* @throws IllegalArgumentException if item is null
*/
public static <T> T nullIsIllegal(T item, String message) {
if (item == null) {
throw new IllegalArgumentException(message);
}
return item;
}
/**
* Converts a string from hex to long.
*
* @param string hex number in string form; sans 0x
......
/*
* Copyright 2014-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.rest.exceptions;
import javax.ws.rs.core.Response;
/**
* Mapper for illegal argument exceptions to the BAD_REQUEST response code.
*/
public class IllegalArgumentExceptionMapper extends AbstractMapper<IllegalArgumentException> {
@Override
protected Response.Status responseStatus() {
return Response.Status.BAD_REQUEST;
}
}
......@@ -15,22 +15,29 @@
*/
package org.onosproject.rest.resources;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import java.io.IOException;
import java.io.InputStream;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.onlab.util.ItemNotFoundException;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.flow.FlowEntry;
import org.onosproject.net.flow.FlowRule;
import org.onosproject.net.flow.FlowRuleService;
import org.onosproject.rest.AbstractWebResource;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
/**
* REST resource for interacting with the inventory of flows.
......@@ -113,4 +120,27 @@ public class FlowsWebResource extends AbstractWebResource {
}
return ok(root).build();
}
/**
* Creates a flow rule from a POST of a JSON string and attempts to apply it.
*
* @param stream input JSON
* @return status of the request - ACCEPTED if the JSON is correct,
* BAD_REQUEST if the JSON is invalid
*/
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response createFlow(InputStream stream) {
try {
FlowRuleService service = get(FlowRuleService.class);
ObjectNode root = (ObjectNode) mapper().readTree(stream);
FlowRule rule = codec(FlowRule.class).decode(root, this);
service.applyFlowRules(rule);
} catch (IOException ex) {
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
}
return Response.status(Response.Status.ACCEPTED).build();
}
}
......
......@@ -61,6 +61,7 @@
org.onosproject.rest.exceptions.ServerErrorMapper,
org.onosproject.rest.exceptions.BadRequestMapper,
org.onosproject.rest.exceptions.WebApplicationExceptionMapper,
org.onosproject.rest.exceptions.IllegalArgumentExceptionMapper,
org.onosproject.rest.resources.JsonBodyWriter,
org.onosproject.rest.resources.ApplicationsWebResource,
......
......@@ -15,10 +15,13 @@
*/
package org.onosproject.rest;
import java.net.HttpURLConnection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.core.MediaType;
import org.hamcrest.Description;
import org.hamcrest.TypeSafeMatcher;
import org.junit.After;
......@@ -30,11 +33,13 @@ import org.onlab.packet.MacAddress;
import org.onlab.rest.BaseResource;
import org.onosproject.codec.CodecService;
import org.onosproject.codec.impl.CodecManager;
import org.onosproject.core.CoreService;
import org.onosproject.core.DefaultGroupId;
import org.onosproject.core.GroupId;
import org.onosproject.net.DefaultDevice;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.NetTestTools;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
......@@ -51,12 +56,15 @@ import org.onosproject.net.flow.instructions.Instructions;
import com.eclipsesource.json.JsonArray;
import com.eclipsesource.json.JsonObject;
import com.google.common.collect.ImmutableSet;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.UniformInterfaceException;
import com.sun.jersey.api.client.WebResource;
import static org.easymock.EasyMock.anyObject;
import static org.easymock.EasyMock.anyShort;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.expectLastCall;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import static org.hamcrest.Matchers.containsString;
......@@ -72,6 +80,8 @@ import static org.junit.Assert.fail;
*/
public class FlowsResourceTest extends ResourceTest {
final FlowRuleService mockFlowService = createMock(FlowRuleService.class);
CoreService mockCoreService = createMock(CoreService.class);
final HashMap<DeviceId, Set<FlowEntry>> rules = new HashMap<>();
final DeviceService mockDeviceService = createMock(DeviceService.class);
......@@ -245,6 +255,11 @@ public class FlowsResourceTest extends ResourceTest {
expect(mockDeviceService.getDevices())
.andReturn(ImmutableSet.of(device1, device2));
// Mock Core Service
expect(mockCoreService.getAppId(anyShort()))
.andReturn(NetTestTools.APP_ID).anyTimes();
replay(mockCoreService);
// Register the services needed for the test
final CodecManager codecService = new CodecManager();
codecService.activate();
......@@ -252,7 +267,8 @@ public class FlowsResourceTest extends ResourceTest {
new TestServiceDirectory()
.add(FlowRuleService.class, mockFlowService)
.add(DeviceService.class, mockDeviceService)
.add(CodecService.class, codecService);
.add(CodecService.class, codecService)
.add(CoreService.class, mockCoreService);
BaseResource.setServiceDirectory(testDirectory);
}
......@@ -263,6 +279,7 @@ public class FlowsResourceTest extends ResourceTest {
@After
public void tearDownTest() {
verify(mockFlowService);
verify(mockCoreService);
}
/**
......@@ -542,4 +559,27 @@ public class FlowsResourceTest extends ResourceTest {
containsString("returned a response status of"));
}
}
/**
* Tests creating a flow with POST.
*/
@Test
public void testPost() {
String json = "{\"appId\":2,\"priority\":1,\"isPermanent\":true,"
+ "\"deviceId\":\"of:0000000000000001\","
+ "\"treatment\":{\"instructions\":[ {\"type\":\"OUTPUT\",\"port\":2}]},"
+ "\"selector\":{\"criteria\":[ {\"type\":\"ETH_TYPE\",\"ethType\":2054}]}}";
mockFlowService.applyFlowRules(anyObject());
expectLastCall();
replay(mockFlowService);
WebResource rs = resource();
ClientResponse response = rs.path("flows/")
.type(MediaType.APPLICATION_JSON_TYPE)
.post(ClientResponse.class, json);
assertThat(response.getStatus(), is(HttpURLConnection.HTTP_ACCEPTED));
}
}
......