diff options
Diffstat (limited to 'framework/src/onos/core/common/src/main/java/org/onosproject/codec')
37 files changed, 3979 insertions, 0 deletions
diff --git a/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/AnnotatedCodec.java b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/AnnotatedCodec.java new file mode 100644 index 00000000..8c714625 --- /dev/null +++ b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/AnnotatedCodec.java @@ -0,0 +1,64 @@ +/* + * 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.codec.impl; + +import com.fasterxml.jackson.databind.node.ObjectNode; + +import org.onosproject.codec.CodecContext; +import org.onosproject.codec.JsonCodec; +import org.onosproject.net.Annotated; +import org.onosproject.net.Annotations; +import org.onosproject.net.DefaultAnnotations; + +/** + * Base JSON codec for annotated entities. + */ +public abstract class AnnotatedCodec<T extends Annotated> extends JsonCodec<T> { + + /** + * Adds JSON encoding of the given item annotations to the specified node. + * + * @param node node to add annotations to + * @param entity annotated entity + * @param context encode context + * @return the given node + */ + protected ObjectNode annotate(ObjectNode node, T entity, CodecContext context) { + if (!entity.annotations().keys().isEmpty()) { + JsonCodec<Annotations> codec = context.codec(Annotations.class); + node.set("annotations", codec.encode(entity.annotations(), context)); + } + return node; + } + + /** + * Extracts annotations of given Object. + * + * @param objNode annotated JSON object node + * @param context decode context + * @return extracted Annotations + */ + protected Annotations extractAnnotations(ObjectNode objNode, CodecContext context) { + + JsonCodec<Annotations> codec = context.codec(Annotations.class); + if (objNode.has("annotations") && objNode.isObject()) { + return codec.decode(get(objNode, "annotations"), context); + } else { + return DefaultAnnotations.EMPTY; + } + } + +} diff --git a/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/AnnotationsCodec.java b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/AnnotationsCodec.java new file mode 100644 index 00000000..de6ca1b9 --- /dev/null +++ b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/AnnotationsCodec.java @@ -0,0 +1,49 @@ +/* + * 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.codec.impl; + +import com.fasterxml.jackson.databind.node.ObjectNode; + +import org.onosproject.codec.CodecContext; +import org.onosproject.codec.JsonCodec; +import org.onosproject.net.Annotations; +import org.onosproject.net.DefaultAnnotations; +import org.onosproject.net.DefaultAnnotations.Builder; + +/** + * Annotations JSON codec. + */ +public final class AnnotationsCodec extends JsonCodec<Annotations> { + + @Override + public ObjectNode encode(Annotations annotations, CodecContext context) { + ObjectNode result = context.mapper().createObjectNode(); + for (String key : annotations.keys()) { + result.put(key, annotations.value(key)); + } + return result; + } + + @Override + public Annotations decode(ObjectNode json, CodecContext context) { + Builder builder = DefaultAnnotations.builder(); + + json.fields().forEachRemaining(e -> + builder.set(e.getKey(), e.getValue().asText())); + + return builder.build(); + } +} diff --git a/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/ApplicationCodec.java b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/ApplicationCodec.java new file mode 100644 index 00000000..b2cab094 --- /dev/null +++ b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/ApplicationCodec.java @@ -0,0 +1,49 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.codec.impl; + +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.onosproject.app.ApplicationService; +import org.onosproject.codec.CodecContext; +import org.onosproject.codec.JsonCodec; +import org.onosproject.core.Application; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * Application JSON codec. + */ +public final class ApplicationCodec extends JsonCodec<Application> { + + @Override + public ObjectNode encode(Application app, CodecContext context) { + checkNotNull(app, "Application cannot be null"); + ApplicationService service = context.getService(ApplicationService.class); + ObjectNode result = context.mapper().createObjectNode() + .put("name", app.id().name()) + .put("id", app.id().id()) + .put("version", app.version().toString()) + .put("description", app.description()) + .put("origin", app.origin()) + .put("permissions", app.permissions().toString()) + .put("featuresRepo", app.featuresRepo().isPresent() ? + app.featuresRepo().get().toString() : "") + .put("features", app.features().toString()) + .put("state", service.getState(app.id()).toString()); + return result; + } + +} diff --git a/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/CodecManager.java b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/CodecManager.java new file mode 100644 index 00000000..eb53152e --- /dev/null +++ b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/CodecManager.java @@ -0,0 +1,132 @@ +/* + * 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.codec.impl; + +import com.google.common.collect.ImmutableSet; +import org.apache.felix.scr.annotations.Activate; +import org.apache.felix.scr.annotations.Component; +import org.apache.felix.scr.annotations.Deactivate; +import org.apache.felix.scr.annotations.Service; +import org.onlab.packet.Ethernet; +import org.onosproject.cluster.ControllerNode; +import org.onosproject.codec.CodecService; +import org.onosproject.codec.JsonCodec; +import org.onosproject.core.Application; +import org.onosproject.net.Annotations; +import org.onosproject.net.ConnectPoint; +import org.onosproject.net.Device; +import org.onosproject.net.Host; +import org.onosproject.net.HostLocation; +import org.onosproject.net.Link; +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; +import org.onosproject.net.flow.instructions.Instruction; +import org.onosproject.net.group.Group; +import org.onosproject.net.group.GroupBucket; +import org.onosproject.net.intent.ConnectivityIntent; +import org.onosproject.net.intent.Constraint; +import org.onosproject.net.intent.HostToHostIntent; +import org.onosproject.net.intent.Intent; +import org.onosproject.net.intent.PointToPointIntent; +import org.onosproject.net.statistic.Load; +import org.onosproject.net.topology.Topology; +import org.onosproject.net.topology.TopologyCluster; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +/** + * Implementation of the JSON codec brokering service. + */ +@Component(immediate = true) +@Service +public class CodecManager implements CodecService { + + private static Logger log = LoggerFactory.getLogger(CodecManager.class); + + private final Map<Class<?>, JsonCodec> codecs = new ConcurrentHashMap<>(); + + @Activate + public void activate() { + codecs.clear(); + registerCodec(Application.class, new ApplicationCodec()); + registerCodec(ControllerNode.class, new ControllerNodeCodec()); + registerCodec(Annotations.class, new AnnotationsCodec()); + registerCodec(Device.class, new DeviceCodec()); + registerCodec(Port.class, new PortCodec()); + registerCodec(ConnectPoint.class, new ConnectPointCodec()); + registerCodec(Link.class, new LinkCodec()); + registerCodec(Host.class, new HostCodec()); + registerCodec(HostLocation.class, new HostLocationCodec()); + registerCodec(HostToHostIntent.class, new HostToHostIntentCodec()); + registerCodec(PointToPointIntent.class, new PointToPointIntentCodec()); + 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()); + registerCodec(Criterion.class, new CriterionCodec()); + registerCodec(Ethernet.class, new EthernetCodec()); + registerCodec(Constraint.class, new ConstraintCodec()); + registerCodec(Topology.class, new TopologyCodec()); + registerCodec(TopologyCluster.class, new TopologyClusterCodec()); + registerCodec(Path.class, new PathCodec()); + registerCodec(Group.class, new GroupCodec()); + registerCodec(Driver.class, new DriverCodec()); + registerCodec(GroupBucket.class, new GroupBucketCodec()); + registerCodec(Load.class, new LoadCodec()); + log.info("Started"); + } + + @Deactivate + public void deactivate() { + codecs.clear(); + log.info("Stopped"); + } + + @Override + public Set<Class<?>> getCodecs() { + return ImmutableSet.copyOf(codecs.keySet()); + } + + @Override + @SuppressWarnings("unchecked") + public <T> JsonCodec<T> getCodec(Class<T> entityClass) { + return codecs.get(entityClass); + } + + @Override + public <T> void registerCodec(Class<T> entityClass, JsonCodec<T> codec) { + codecs.putIfAbsent(entityClass, codec); + } + + @Override + public void unregisterCodec(Class<?> entityClass) { + codecs.remove(entityClass); + } + +} diff --git a/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/ConnectPointCodec.java b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/ConnectPointCodec.java new file mode 100644 index 00000000..ac23ef89 --- /dev/null +++ b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/ConnectPointCodec.java @@ -0,0 +1,74 @@ +/* + * 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.codec.impl; + +import com.fasterxml.jackson.databind.node.ObjectNode; + +import org.onosproject.codec.CodecContext; +import org.onosproject.codec.JsonCodec; +import org.onosproject.net.ConnectPoint; +import org.onosproject.net.DeviceId; +import org.onosproject.net.ElementId; +import org.onosproject.net.HostId; +import org.onosproject.net.PortNumber; + +import static com.google.common.base.Preconditions.checkNotNull; +import static org.onosproject.net.PortNumber.portNumber; + +/** + * Connection point JSON codec. + */ +public final class ConnectPointCodec extends JsonCodec<ConnectPoint> { + + // JSON field names + private static final String ELEMENT_HOST = "host"; + private static final String ELEMENT_DEVICE = "device"; + private static final String PORT = "port"; + + @Override + public ObjectNode encode(ConnectPoint point, CodecContext context) { + checkNotNull(point, "Connect point cannot be null"); + ObjectNode root = context.mapper().createObjectNode() + .put(PORT, point.port().toString()); + + if (point.elementId() instanceof DeviceId) { + root.put(ELEMENT_DEVICE, point.deviceId().toString()); + } else if (point.elementId() instanceof HostId) { + root.put(ELEMENT_HOST, point.hostId().toString()); + } + + return root; + } + + @Override + public ConnectPoint decode(ObjectNode json, CodecContext context) { + if (json == null || !json.isObject()) { + return null; + } + + ElementId elementId; + if (json.has(ELEMENT_DEVICE)) { + elementId = DeviceId.deviceId(json.get(ELEMENT_DEVICE).asText()); + } else if (json.has(ELEMENT_HOST)) { + elementId = HostId.hostId(json.get(ELEMENT_HOST).asText()); + } else { + // invalid JSON + return null; + } + PortNumber portNumber = portNumber(json.get(PORT).asText()); + return new ConnectPoint(elementId, portNumber); + } +} diff --git a/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/ConnectivityIntentCodec.java b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/ConnectivityIntentCodec.java new file mode 100644 index 00000000..9e8cd86c --- /dev/null +++ b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/ConnectivityIntentCodec.java @@ -0,0 +1,118 @@ +/* + * 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.ArrayList; +import java.util.stream.IntStream; + +import org.onosproject.codec.CodecContext; +import org.onosproject.codec.JsonCodec; +import org.onosproject.net.flow.TrafficSelector; +import org.onosproject.net.flow.TrafficTreatment; +import org.onosproject.net.intent.ConnectivityIntent; +import org.onosproject.net.intent.Constraint; +import org.onosproject.net.intent.Intent; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * Connectivity intent codec. + */ +public final class ConnectivityIntentCodec extends JsonCodec<ConnectivityIntent> { + + private static final String CONSTRAINTS = "constraints"; + private static final String SELECTOR = "selector"; + private static final String TREATMENT = "treatment"; + + @Override + public ObjectNode encode(ConnectivityIntent intent, CodecContext context) { + checkNotNull(intent, "Connectivity intent cannot be null"); + + final JsonCodec<Intent> intentCodec = context.codec(Intent.class); + final ObjectNode result = intentCodec.encode(intent, context); + + if (intent.selector() != null) { + final JsonCodec<TrafficSelector> selectorCodec = + context.codec(TrafficSelector.class); + result.set(SELECTOR, selectorCodec.encode(intent.selector(), context)); + } + + if (intent.treatment() != null) { + final JsonCodec<TrafficTreatment> treatmentCodec = + context.codec(TrafficTreatment.class); + result.set(TREATMENT, treatmentCodec.encode(intent.treatment(), context)); + } + + result.put(IntentCodec.PRIORITY, intent.priority()); + + if (intent.constraints() != null) { + final ArrayNode jsonConstraints = result.putArray(CONSTRAINTS); + + if (intent.constraints() != null) { + final JsonCodec<Constraint> constraintCodec = + context.codec(Constraint.class); + for (final Constraint constraint : intent.constraints()) { + final ObjectNode constraintNode = + constraintCodec.encode(constraint, context); + jsonConstraints.add(constraintNode); + } + } + } + + return result; + } + + /** + * Extracts connectivity intent specific attributes from a JSON object + * and adds them to a builder. + * + * @param json root JSON object + * @param context code context + * @param builder builder to use for storing the attributes. Constraints, + * selector and treatment are modified by this call. + */ + public static void intentAttributes(ObjectNode json, CodecContext context, + ConnectivityIntent.Builder builder) { + JsonNode constraintsJson = json.get(CONSTRAINTS); + if (constraintsJson != null) { + JsonCodec<Constraint> constraintsCodec = context.codec(Constraint.class); + ArrayList<Constraint> constraints = new ArrayList<>(constraintsJson.size()); + IntStream.range(0, constraintsJson.size()) + .forEach(i -> constraints.add( + constraintsCodec.decode(get(constraintsJson, i), + context))); + builder.constraints(constraints); + } + + ObjectNode selectorJson = get(json, SELECTOR); + if (selectorJson != null) { + JsonCodec<TrafficSelector> selectorCodec = context.codec(TrafficSelector.class); + TrafficSelector selector = selectorCodec.decode(selectorJson, context); + builder.selector(selector); + } + + ObjectNode treatmentJson = get(json, TREATMENT); + if (treatmentJson != null) { + JsonCodec<TrafficTreatment> treatmentCodec = context.codec(TrafficTreatment.class); + TrafficTreatment treatment = treatmentCodec.decode(treatmentJson, context); + builder.treatment(treatment); + } + } +} diff --git a/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/ConstraintCodec.java b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/ConstraintCodec.java new file mode 100644 index 00000000..50738341 --- /dev/null +++ b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/ConstraintCodec.java @@ -0,0 +1,63 @@ +/* + * 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.net.intent.Constraint; + +import com.fasterxml.jackson.databind.node.ObjectNode; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * Constraint JSON codec. + */ +public final class ConstraintCodec extends JsonCodec<Constraint> { + + protected static final String MISSING_MEMBER_MESSAGE = + " member is required in Constraint"; + protected static final String TYPE = "type"; + protected static final String TYPES = "types"; + protected static final String INCLUSIVE = "inclusive"; + protected static final String KEY = "key"; + protected static final String THRESHOLD = "threshold"; + protected static final String BANDWIDTH = "bandwidth"; + protected static final String LAMBDA = "lambda"; + protected static final String LATENCY_MILLIS = "latencyMillis"; + protected static final String OBSTACLES = "obstacles"; + protected static final String WAYPOINTS = "waypoints"; + + @Override + public ObjectNode encode(Constraint constraint, CodecContext context) { + checkNotNull(constraint, "Constraint cannot be null"); + + final EncodeConstraintCodecHelper encodeCodec = + new EncodeConstraintCodecHelper(constraint, context); + + return encodeCodec.encode(); + } + + @Override + public Constraint decode(ObjectNode json, CodecContext context) { + checkNotNull(json, "JSON cannot be null"); + + final DecodeConstraintCodecHelper decodeCodec = + new DecodeConstraintCodecHelper(json); + + return decodeCodec.decode(); + } +} diff --git a/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/ControllerNodeCodec.java b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/ControllerNodeCodec.java new file mode 100644 index 00000000..65d758ee --- /dev/null +++ b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/ControllerNodeCodec.java @@ -0,0 +1,57 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.codec.impl; + +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.onlab.packet.IpAddress; +import org.onosproject.cluster.ClusterService; +import org.onosproject.cluster.ControllerNode; +import org.onosproject.cluster.DefaultControllerNode; +import org.onosproject.cluster.NodeId; +import org.onosproject.codec.CodecContext; +import org.onosproject.codec.JsonCodec; + +import static com.google.common.base.Preconditions.checkNotNull; +import static org.onosproject.cluster.DefaultControllerNode.DEFAULT_PORT; + +/** + * Device JSON codec. + */ +public final class ControllerNodeCodec extends JsonCodec<ControllerNode> { + + @Override + public ObjectNode encode(ControllerNode node, CodecContext context) { + checkNotNull(node, "Controller node cannot be null"); + ClusterService service = context.getService(ClusterService.class); + return context.mapper().createObjectNode() + .put("id", node.id().toString()) + .put("ip", node.ip().toString()) + .put("tcpPort", node.tcpPort()) + .put("status", service.getState(node.id()).toString()); + } + + + @Override + public ControllerNode decode(ObjectNode json, CodecContext context) { + checkNotNull(json, "JSON cannot be null"); + String ip = json.path("ip").asText(); + return new DefaultControllerNode(new NodeId(json.path("id").asText(ip)), + IpAddress.valueOf(ip), + json.path("tcpPort").asInt(DEFAULT_PORT)); + } + + +} diff --git a/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/CriterionCodec.java b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/CriterionCodec.java new file mode 100644 index 00000000..76f621f2 --- /dev/null +++ b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/CriterionCodec.java @@ -0,0 +1,78 @@ +/* + * 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.net.flow.criteria.Criterion; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.fasterxml.jackson.databind.node.ObjectNode; + +/** + * Criterion codec. + */ +public final class CriterionCodec extends JsonCodec<Criterion> { + + protected static final Logger log = + LoggerFactory.getLogger(CriterionCodec.class); + + 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"; + protected static final String TUNNEL_ID = "tunnelId"; + + @Override + public ObjectNode encode(Criterion criterion, CodecContext context) { + EncodeCriterionCodecHelper encoder = new EncodeCriterionCodecHelper(criterion, context); + return encoder.encode(); + } + + @Override + public Criterion decode(ObjectNode json, CodecContext context) { + DecodeCriterionCodecHelper decoder = new DecodeCriterionCodecHelper(json); + return decoder.decode(); + } + + +} diff --git a/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/DecodeConstraintCodecHelper.java b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/DecodeConstraintCodecHelper.java new file mode 100644 index 00000000..5746003c --- /dev/null +++ b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/DecodeConstraintCodecHelper.java @@ -0,0 +1,225 @@ +/* + * 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.time.Duration; +import java.util.ArrayList; +import java.util.stream.IntStream; + +import org.onlab.util.Bandwidth; +import org.onosproject.net.DeviceId; +import org.onosproject.net.IndexedLambda; +import org.onosproject.net.Link; +import org.onosproject.net.intent.Constraint; +import org.onosproject.net.intent.constraint.AnnotationConstraint; +import org.onosproject.net.intent.constraint.AsymmetricPathConstraint; +import org.onosproject.net.intent.constraint.BandwidthConstraint; +import org.onosproject.net.intent.constraint.LambdaConstraint; +import org.onosproject.net.intent.constraint.LatencyConstraint; +import org.onosproject.net.intent.constraint.LinkTypeConstraint; +import org.onosproject.net.intent.constraint.ObstacleConstraint; +import org.onosproject.net.intent.constraint.WaypointConstraint; +import org.onosproject.net.resource.link.BandwidthResource; +import org.onosproject.net.resource.link.LambdaResource; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ObjectNode; + +import static org.onlab.util.Tools.nullIsIllegal; + +/** + * Constraint JSON decoder. + */ +public final class DecodeConstraintCodecHelper { + private final ObjectNode json; + + /** + * Constructs a constraint decoder. + * + * @param json object node to decode + */ + public DecodeConstraintCodecHelper(ObjectNode json) { + this.json = json; + } + + /** + * Decodes a link type constraint. + * + * @return link type constraint object. + */ + private Constraint decodeLinkTypeConstraint() { + boolean inclusive = nullIsIllegal(json.get(ConstraintCodec.INCLUSIVE), + ConstraintCodec.INCLUSIVE + ConstraintCodec.MISSING_MEMBER_MESSAGE).asBoolean(); + + JsonNode types = nullIsIllegal(json.get(ConstraintCodec.TYPES), + ConstraintCodec.TYPES + ConstraintCodec.MISSING_MEMBER_MESSAGE); + if (types.size() < 1) { + throw new IllegalArgumentException( + "types array in link constraint must have at least one value"); + } + + ArrayList<Link.Type> typesEntries = new ArrayList<>(types.size()); + IntStream.range(0, types.size()) + .forEach(index -> + typesEntries.add(Link.Type.valueOf(types.get(index).asText()))); + + return new LinkTypeConstraint(inclusive, + typesEntries.toArray(new Link.Type[types.size()])); + } + + /** + * Decodes an annotation constraint. + * + * @return annotation constraint object. + */ + private Constraint decodeAnnotationConstraint() { + String key = nullIsIllegal(json.get(ConstraintCodec.KEY), + ConstraintCodec.KEY + ConstraintCodec.MISSING_MEMBER_MESSAGE) + .asText(); + double threshold = nullIsIllegal(json.get(ConstraintCodec.THRESHOLD), + ConstraintCodec.THRESHOLD + ConstraintCodec.MISSING_MEMBER_MESSAGE) + .asDouble(); + + return new AnnotationConstraint(key, threshold); + } + + /** + * Decodes a lambda constraint. + * + * @return lambda constraint object. + */ + private Constraint decodeLambdaConstraint() { + long lambda = nullIsIllegal(json.get(ConstraintCodec.LAMBDA), + ConstraintCodec.LAMBDA + ConstraintCodec.MISSING_MEMBER_MESSAGE) + .asLong(); + + return new LambdaConstraint(LambdaResource.valueOf(new IndexedLambda(lambda))); + } + + /** + * Decodes a latency constraint. + * + * @return latency constraint object. + */ + private Constraint decodeLatencyConstraint() { + long latencyMillis = nullIsIllegal(json.get(ConstraintCodec.LATENCY_MILLIS), + ConstraintCodec.LATENCY_MILLIS + ConstraintCodec.MISSING_MEMBER_MESSAGE) + .asLong(); + + return new LatencyConstraint(Duration.ofMillis(latencyMillis)); + } + + /** + * Decodes an obstacle constraint. + * + * @return obstacle constraint object. + */ + private Constraint decodeObstacleConstraint() { + JsonNode obstacles = nullIsIllegal(json.get(ConstraintCodec.OBSTACLES), + ConstraintCodec.OBSTACLES + ConstraintCodec.MISSING_MEMBER_MESSAGE); + if (obstacles.size() < 1) { + throw new IllegalArgumentException( + "obstacles array in obstacles constraint must have at least one value"); + } + + ArrayList<DeviceId> obstacleEntries = new ArrayList<>(obstacles.size()); + IntStream.range(0, obstacles.size()) + .forEach(index -> + obstacleEntries.add(DeviceId.deviceId(obstacles.get(index).asText()))); + + return new ObstacleConstraint( + obstacleEntries.toArray(new DeviceId[obstacles.size()])); + } + + /** + * Decodes a waypoint constraint. + * + * @return waypoint constraint object. + */ + private Constraint decodeWaypointConstraint() { + JsonNode waypoints = nullIsIllegal(json.get(ConstraintCodec.WAYPOINTS), + ConstraintCodec.WAYPOINTS + ConstraintCodec.MISSING_MEMBER_MESSAGE); + if (waypoints.size() < 1) { + throw new IllegalArgumentException( + "obstacles array in obstacles constraint must have at least one value"); + } + + ArrayList<DeviceId> waypointEntries = new ArrayList<>(waypoints.size()); + IntStream.range(0, waypoints.size()) + .forEach(index -> + waypointEntries.add(DeviceId.deviceId(waypoints.get(index).asText()))); + + return new WaypointConstraint( + waypointEntries.toArray(new DeviceId[waypoints.size()])); + } + + /** + * Decodes an asymmetric path constraint. + * + * @return asymmetric path constraint object. + */ + private Constraint decodeAsymmetricPathConstraint() { + return new AsymmetricPathConstraint(); + } + + /** + * Decodes a bandwidth constraint. + * + * @return bandwidth constraint object. + */ + private Constraint decodeBandwidthConstraint() { + double bandwidth = nullIsIllegal(json.get(ConstraintCodec.BANDWIDTH), + ConstraintCodec.BANDWIDTH + ConstraintCodec.MISSING_MEMBER_MESSAGE) + .asDouble(); + + return new BandwidthConstraint(new BandwidthResource(Bandwidth.bps(bandwidth))); + } + + /** + * Decodes the given constraint. + * + * @return constraint object. + */ + public Constraint decode() { + final String type = nullIsIllegal(json.get(ConstraintCodec.TYPE), + ConstraintCodec.TYPE + ConstraintCodec.MISSING_MEMBER_MESSAGE) + .asText(); + + if (type.equals(BandwidthConstraint.class.getSimpleName())) { + return decodeBandwidthConstraint(); + } else if (type.equals(LambdaConstraint.class.getSimpleName())) { + return decodeLambdaConstraint(); + } else if (type.equals(LinkTypeConstraint.class.getSimpleName())) { + return decodeLinkTypeConstraint(); + } else if (type.equals(AnnotationConstraint.class.getSimpleName())) { + return decodeAnnotationConstraint(); + } else if (type.equals(LatencyConstraint.class.getSimpleName())) { + return decodeLatencyConstraint(); + } else if (type.equals(ObstacleConstraint.class.getSimpleName())) { + return decodeObstacleConstraint(); + } else if (type.equals(WaypointConstraint.class.getSimpleName())) { + return decodeWaypointConstraint(); + } else if (type.equals(AsymmetricPathConstraint.class.getSimpleName())) { + return decodeAsymmetricPathConstraint(); + } else if (type.equals(LinkTypeConstraint.class.getSimpleName())) { + return decodeLinkTypeConstraint(); + } else if (type.equals(AnnotationConstraint.class.getSimpleName())) { + return decodeAnnotationConstraint(); + } + throw new IllegalArgumentException("Instruction type " + + type + " is not supported"); + } +} diff --git a/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/DecodeCriterionCodecHelper.java b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/DecodeCriterionCodecHelper.java new file mode 100644 index 00000000..4e0f2bd9 --- /dev/null +++ b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/DecodeCriterionCodecHelper.java @@ -0,0 +1,449 @@ +/* + * 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.TpPort; +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 DecodeCriterionCodecHelper { + + private final ObjectNode json; + + protected static final String MISSING_MEMBER_MESSAGE = + " member is required in Criterion"; + + private interface CriterionDecoder { + Criterion decodeCriterion(ObjectNode json); + } + private final Map<String, CriterionDecoder> decoderMap; + + /** + * Creates a decode criterion codec object. + * Initializes the lookup map for criterion subclass decoders. + * + * @param json JSON object to decode + */ + public DecodeCriterionCodecHelper(ObjectNode json) { + this.json = json; + decoderMap = new HashMap<>(); + + decoderMap.put(Criterion.Type.IN_PORT.name(), new InPortDecoder()); + decoderMap.put(Criterion.Type.IN_PHY_PORT.name(), new InPhyPortDecoder()); + decoderMap.put(Criterion.Type.METADATA.name(), new MetadataDecoder()); + decoderMap.put(Criterion.Type.ETH_DST.name(), new EthDstDecoder()); + decoderMap.put(Criterion.Type.ETH_SRC.name(), new EthSrcDecoder()); + decoderMap.put(Criterion.Type.ETH_TYPE.name(), new EthTypeDecoder()); + decoderMap.put(Criterion.Type.VLAN_VID.name(), new VlanVidDecoder()); + decoderMap.put(Criterion.Type.VLAN_PCP.name(), new VlanPcpDecoder()); + decoderMap.put(Criterion.Type.IP_DSCP.name(), new IpDscpDecoder()); + decoderMap.put(Criterion.Type.IP_ECN.name(), new IpEcnDecoder()); + decoderMap.put(Criterion.Type.IP_PROTO.name(), new IpProtoDecoder()); + decoderMap.put(Criterion.Type.IPV4_SRC.name(), new IpV4SrcDecoder()); + decoderMap.put(Criterion.Type.IPV4_DST.name(), new IpV4DstDecoder()); + decoderMap.put(Criterion.Type.TCP_SRC.name(), new TcpSrcDecoder()); + decoderMap.put(Criterion.Type.TCP_DST.name(), new TcpDstDecoder()); + decoderMap.put(Criterion.Type.UDP_SRC.name(), new UdpSrcDecoder()); + decoderMap.put(Criterion.Type.UDP_DST.name(), new UdpDstDecoder()); + decoderMap.put(Criterion.Type.SCTP_SRC.name(), new SctpSrcDecoder()); + decoderMap.put(Criterion.Type.SCTP_DST.name(), new SctpDstDecoder()); + decoderMap.put(Criterion.Type.ICMPV4_TYPE.name(), new IcmpV4TypeDecoder()); + decoderMap.put(Criterion.Type.ICMPV4_CODE.name(), new IcmpV4CodeDecoder()); + decoderMap.put(Criterion.Type.IPV6_SRC.name(), new IpV6SrcDecoder()); + decoderMap.put(Criterion.Type.IPV6_DST.name(), new IpV6DstDecoder()); + decoderMap.put(Criterion.Type.IPV6_FLABEL.name(), new IpV6FLabelDecoder()); + decoderMap.put(Criterion.Type.ICMPV6_TYPE.name(), new IcmpV6TypeDecoder()); + decoderMap.put(Criterion.Type.ICMPV6_CODE.name(), new IcmpV6CodeDecoder()); + decoderMap.put(Criterion.Type.IPV6_ND_TARGET.name(), new V6NDTargetDecoder()); + decoderMap.put(Criterion.Type.IPV6_ND_SLL.name(), new V6NDSllDecoder()); + decoderMap.put(Criterion.Type.IPV6_ND_TLL.name(), new V6NDTllDecoder()); + decoderMap.put(Criterion.Type.MPLS_LABEL.name(), new MplsLabelDecoder()); + decoderMap.put(Criterion.Type.IPV6_EXTHDR.name(), new IpV6ExthdrDecoder()); + decoderMap.put(Criterion.Type.OCH_SIGID.name(), new OchSigIdDecoder()); + decoderMap.put(Criterion.Type.OCH_SIGTYPE.name(), new OchSigTypeDecoder()); + decoderMap.put(Criterion.Type.TUNNEL_ID.name(), new TunnelIdDecoder()); + } + + 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) { + TpPort tcpPort = TpPort.tpPort(nullIsIllegal(json.get(CriterionCodec.TCP_PORT), + CriterionCodec.TCP_PORT + MISSING_MEMBER_MESSAGE).asInt()); + return Criteria.matchTcpSrc(tcpPort); + } + } + + private class TcpDstDecoder implements CriterionDecoder { + @Override + public Criterion decodeCriterion(ObjectNode json) { + TpPort tcpPort = TpPort.tpPort(nullIsIllegal(json.get(CriterionCodec.TCP_PORT), + CriterionCodec.TCP_PORT + MISSING_MEMBER_MESSAGE).asInt()); + return Criteria.matchTcpDst(tcpPort); + } + } + + private class UdpSrcDecoder implements CriterionDecoder { + @Override + public Criterion decodeCriterion(ObjectNode json) { + TpPort udpPort = TpPort.tpPort(nullIsIllegal(json.get(CriterionCodec.UDP_PORT), + CriterionCodec.UDP_PORT + MISSING_MEMBER_MESSAGE).asInt()); + return Criteria.matchUdpSrc(udpPort); + } + } + + private class UdpDstDecoder implements CriterionDecoder { + @Override + public Criterion decodeCriterion(ObjectNode json) { + TpPort udpPort = TpPort.tpPort(nullIsIllegal(json.get(CriterionCodec.UDP_PORT), + CriterionCodec.UDP_PORT + MISSING_MEMBER_MESSAGE).asInt()); + return Criteria.matchUdpDst(udpPort); + } + } + + private class SctpSrcDecoder implements CriterionDecoder { + @Override + public Criterion decodeCriterion(ObjectNode json) { + TpPort sctpPort = TpPort.tpPort(nullIsIllegal(json.get(CriterionCodec.SCTP_PORT), + CriterionCodec.SCTP_PORT + MISSING_MEMBER_MESSAGE).asInt()); + return Criteria.matchSctpSrc(sctpPort); + } + } + + private class SctpDstDecoder implements CriterionDecoder { + @Override + public Criterion decodeCriterion(ObjectNode json) { + TpPort sctpPort = TpPort.tpPort(nullIsIllegal(json.get(CriterionCodec.SCTP_PORT), + CriterionCodec.SCTP_PORT + MISSING_MEMBER_MESSAGE).asInt()); + return Criteria.matchSctpDst(sctpPort); + } + } + + private class IcmpV4TypeDecoder implements CriterionDecoder { + @Override + public Criterion decodeCriterion(ObjectNode json) { + short type = (short) nullIsIllegal(json.get(CriterionCodec.ICMP_TYPE), + CriterionCodec.ICMP_TYPE + MISSING_MEMBER_MESSAGE).asInt(); + return Criteria.matchIcmpType(type); + } + } + + private class IcmpV4CodeDecoder implements CriterionDecoder { + @Override + public Criterion decodeCriterion(ObjectNode json) { + short code = (short) nullIsIllegal(json.get(CriterionCodec.ICMP_CODE), + CriterionCodec.ICMP_CODE + MISSING_MEMBER_MESSAGE).asInt(); + return Criteria.matchIcmpCode(code); + } + } + + private class IpV6FLabelDecoder implements CriterionDecoder { + @Override + public Criterion decodeCriterion(ObjectNode json) { + int flowLabel = nullIsIllegal(json.get(CriterionCodec.FLOW_LABEL), + CriterionCodec.FLOW_LABEL + MISSING_MEMBER_MESSAGE).asInt(); + return Criteria.matchIPv6FlowLabel(flowLabel); + } + } + + private class IcmpV6TypeDecoder implements CriterionDecoder { + @Override + public Criterion decodeCriterion(ObjectNode json) { + short type = (short) nullIsIllegal(json.get(CriterionCodec.ICMPV6_TYPE), + CriterionCodec.ICMPV6_TYPE + MISSING_MEMBER_MESSAGE).asInt(); + return Criteria.matchIcmpv6Type(type); + } + } + + private class IcmpV6CodeDecoder implements CriterionDecoder { + @Override + public Criterion decodeCriterion(ObjectNode json) { + short code = (short) nullIsIllegal(json.get(CriterionCodec.ICMPV6_CODE), + CriterionCodec.ICMPV6_CODE + MISSING_MEMBER_MESSAGE).asInt(); + return Criteria.matchIcmpv6Code(code); + } + } + + private class V6NDTargetDecoder implements CriterionDecoder { + @Override + public Criterion decodeCriterion(ObjectNode json) { + Ip6Address target = Ip6Address.valueOf(nullIsIllegal(json.get(CriterionCodec.TARGET_ADDRESS), + CriterionCodec.TARGET_ADDRESS + MISSING_MEMBER_MESSAGE).asText()); + return Criteria.matchIPv6NDTargetAddress(target); + } + } + + private class V6NDSllDecoder implements CriterionDecoder { + @Override + public Criterion decodeCriterion(ObjectNode json) { + MacAddress mac = MacAddress.valueOf(nullIsIllegal(json.get(CriterionCodec.MAC), + CriterionCodec.MAC + MISSING_MEMBER_MESSAGE).asText()); + return Criteria.matchIPv6NDSourceLinkLayerAddress(mac); + } + } + + private class V6NDTllDecoder implements CriterionDecoder { + @Override + public Criterion decodeCriterion(ObjectNode json) { + MacAddress mac = MacAddress.valueOf(nullIsIllegal(json.get(CriterionCodec.MAC), + CriterionCodec.MAC + MISSING_MEMBER_MESSAGE).asText()); + return Criteria.matchIPv6NDTargetLinkLayerAddress(mac); + } + } + + private class MplsLabelDecoder implements CriterionDecoder { + @Override + public Criterion decodeCriterion(ObjectNode json) { + int label = nullIsIllegal(json.get(CriterionCodec.LABEL), + CriterionCodec.LABEL + MISSING_MEMBER_MESSAGE).asInt(); + return Criteria.matchMplsLabel(MplsLabel.mplsLabel(label)); + } + } + + private class IpV6ExthdrDecoder implements CriterionDecoder { + @Override + public Criterion decodeCriterion(ObjectNode json) { + int exthdrFlags = nullIsIllegal(json.get(CriterionCodec.EXT_HDR_FLAGS), + CriterionCodec.EXT_HDR_FLAGS + MISSING_MEMBER_MESSAGE).asInt(); + return Criteria.matchIPv6ExthdrFlags(exthdrFlags); + } + } + + private class OchSigIdDecoder implements CriterionDecoder { + @Override + public Criterion decodeCriterion(ObjectNode json) { + if (json.get(CriterionCodec.LAMBDA) != null) { + Lambda lambda = Lambda.indexedLambda(nullIsIllegal(json.get(CriterionCodec.LAMBDA), + CriterionCodec.LAMBDA + MISSING_MEMBER_MESSAGE).asInt()); + return Criteria.matchLambda(lambda); + } else { + JsonNode ochSignalId = nullIsIllegal(json.get(CriterionCodec.OCH_SIGNAL_ID), + CriterionCodec.GRID_TYPE + MISSING_MEMBER_MESSAGE); + GridType gridType = + GridType.valueOf( + nullIsIllegal(ochSignalId.get(CriterionCodec.GRID_TYPE), + CriterionCodec.GRID_TYPE + MISSING_MEMBER_MESSAGE).asText()); + ChannelSpacing channelSpacing = + ChannelSpacing.valueOf( + nullIsIllegal(ochSignalId.get(CriterionCodec.CHANNEL_SPACING), + CriterionCodec.CHANNEL_SPACING + MISSING_MEMBER_MESSAGE).asText()); + int spacingMultiplier = nullIsIllegal(ochSignalId.get(CriterionCodec.SPACING_MULIPLIER), + CriterionCodec.SPACING_MULIPLIER + MISSING_MEMBER_MESSAGE).asInt(); + int slotGranularity = nullIsIllegal(ochSignalId.get(CriterionCodec.SLOT_GRANULARITY), + CriterionCodec.SLOT_GRANULARITY + MISSING_MEMBER_MESSAGE).asInt(); + return Criteria.matchLambda( + Lambda.ochSignal(gridType, channelSpacing, + spacingMultiplier, slotGranularity)); + } + } + } + + private class OchSigTypeDecoder implements CriterionDecoder { + @Override + public Criterion decodeCriterion(ObjectNode json) { + return null; + } + } + + private class TunnelIdDecoder implements CriterionDecoder { + @Override + public Criterion decodeCriterion(ObjectNode json) { + long tunnelId = nullIsIllegal(json.get(CriterionCodec.TUNNEL_ID), + CriterionCodec.TUNNEL_ID + MISSING_MEMBER_MESSAGE).asLong(); + return Criteria.matchTunnelId(tunnelId); + } + } + + /** + * 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"); + } + + +} diff --git a/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/DecodeInstructionCodecHelper.java b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/DecodeInstructionCodecHelper.java new file mode 100644 index 00000000..6a97a076 --- /dev/null +++ b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/DecodeInstructionCodecHelper.java @@ -0,0 +1,235 @@ +/* + * 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.TpPort; +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 com.fasterxml.jackson.databind.node.ObjectNode; +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.onosproject.net.flow.instructions.L4ModificationInstruction; + +import static org.onlab.util.Tools.nullIsIllegal; + +/** + * Decoding portion of the instruction codec. + */ +public final class DecodeInstructionCodecHelper { + private final ObjectNode json; + + /** + * Creates a decode instruction codec object. + * + * @param json JSON object to decode + */ + public DecodeInstructionCodecHelper(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(); + } else if (subType.equals(L2ModificationInstruction.L2SubType.TUNNEL_ID.name())) { + long tunnelId = nullIsIllegal(json.get(InstructionCodec.TUNNEL_ID), + InstructionCodec.TUNNEL_ID + InstructionCodec.MISSING_MEMBER_MESSAGE).asLong(); + return Instructions.modTunnelId(tunnelId); + } + 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 a Layer 4 instruction. + * + * @return instruction object decoded from the JSON + * @throws IllegalArgumentException if the JSON is invalid + */ + private Instruction decodeL4() { + String subType = json.get(InstructionCodec.SUBTYPE).asText(); + + if (subType.equals(L4ModificationInstruction.L4SubType.TCP_DST.name())) { + TpPort tcpPort = TpPort.tpPort(nullIsIllegal(json.get(InstructionCodec.TCP_PORT), + InstructionCodec.TCP_PORT + InstructionCodec.MISSING_MEMBER_MESSAGE).asInt()); + return Instructions.modTcpDst(tcpPort); + } else if (subType.equals(L4ModificationInstruction.L4SubType.TCP_SRC.name())) { + TpPort tcpPort = TpPort.tpPort(nullIsIllegal(json.get(InstructionCodec.TCP_PORT), + InstructionCodec.TCP_PORT + InstructionCodec.MISSING_MEMBER_MESSAGE).asInt()); + return Instructions.modTcpSrc(tcpPort); + } else if (subType.equals(L4ModificationInstruction.L4SubType.UDP_DST.name())) { + TpPort udpPort = TpPort.tpPort(nullIsIllegal(json.get(InstructionCodec.UDP_PORT), + InstructionCodec.UDP_PORT + InstructionCodec.MISSING_MEMBER_MESSAGE).asInt()); + return Instructions.modUdpDst(udpPort); + } else if (subType.equals(L4ModificationInstruction.L4SubType.UDP_SRC.name())) { + TpPort udpPort = TpPort.tpPort(nullIsIllegal(json.get(InstructionCodec.UDP_PORT), + InstructionCodec.UDP_PORT + InstructionCodec.MISSING_MEMBER_MESSAGE).asInt()); + return Instructions.modUdpSrc(udpPort); + } + throw new IllegalArgumentException("L4 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(); + } else if (type.equals(Instruction.Type.L4MODIFICATION.name())) { + return decodeL4(); + } + throw new IllegalArgumentException("Instruction type " + + type + " is not supported"); + } + +} diff --git a/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/DeviceCodec.java b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/DeviceCodec.java new file mode 100644 index 00000000..f1a4f786 --- /dev/null +++ b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/DeviceCodec.java @@ -0,0 +1,93 @@ +/* + * 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.codec.impl; + +import com.fasterxml.jackson.databind.node.ObjectNode; + +import org.onlab.packet.ChassisId; +import org.onosproject.codec.CodecContext; +import org.onosproject.net.Annotations; +import org.onosproject.net.DefaultDevice; +import org.onosproject.net.Device; +import org.onosproject.net.Device.Type; +import org.onosproject.net.DeviceId; +import org.onosproject.net.device.DeviceService; +import org.onosproject.net.provider.ProviderId; + +import static com.google.common.base.Preconditions.checkNotNull; +import static org.onosproject.net.DeviceId.deviceId; + +/** + * Device JSON codec. + */ +public final class DeviceCodec extends AnnotatedCodec<Device> { + + // JSON fieldNames + private static final String ID = "id"; + private static final String TYPE = "type"; + private static final String MFR = "mfr"; + private static final String HW = "hw"; + private static final String SW = "sw"; + private static final String SERIAL = "serial"; + private static final String CHASSIS_ID = "chassisId"; + + + @Override + public ObjectNode encode(Device device, CodecContext context) { + checkNotNull(device, "Device cannot be null"); + DeviceService service = context.getService(DeviceService.class); + ObjectNode result = context.mapper().createObjectNode() + .put(ID, device.id().toString()) + .put(TYPE, device.type().name()) + .put("available", service.isAvailable(device.id())) + .put("role", service.getRole(device.id()).toString()) + .put(MFR, device.manufacturer()) + .put(HW, device.hwVersion()) + .put(SW, device.swVersion()) + .put(SERIAL, device.serialNumber()) + .put(CHASSIS_ID, device.chassisId().toString()); + return annotate(result, device, context); + } + + + /** + * {@inheritDoc} + * + * Note: ProviderId is not part of JSON representation. + * Returned object will have random ProviderId set. + */ + @Override + public Device decode(ObjectNode json, CodecContext context) { + if (json == null || !json.isObject()) { + return null; + } + + DeviceId id = deviceId(json.get(ID).asText()); + // TODO: add providerId to JSON if we need to recover them. + ProviderId pid = new ProviderId(id.uri().getScheme(), "DeviceCodec"); + + Type type = Type.valueOf(json.get(TYPE).asText()); + String mfr = json.get(MFR).asText(); + String hw = json.get(HW).asText(); + String sw = json.get(SW).asText(); + String serial = json.get(SERIAL).asText(); + ChassisId chassisId = new ChassisId(json.get(CHASSIS_ID).asText()); + Annotations annotations = extractAnnotations(json, context); + + return new DefaultDevice(pid, id, type, mfr, hw, sw, serial, + chassisId, annotations); + } +} diff --git a/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/DriverCodec.java b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/DriverCodec.java new file mode 100644 index 00000000..4935d992 --- /dev/null +++ b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/DriverCodec.java @@ -0,0 +1,78 @@ +/* + * 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.net.driver.Driver; + +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * JSON codec for the Driver class. + */ +public final class DriverCodec extends JsonCodec<Driver> { + private static final String PARENT = "parent"; + private static final String NAME = "name"; + private static final String MANUFACTURER = "manufacturer"; + private static final String HW_VERSION = "hwVersion"; + private static final String SW_VERSION = "swVersion"; + private static final String BEHAVIOURS = "behaviours"; + private static final String BEHAVIORS_NAME = "name"; + private static final String BEHAVIORS_IMPLEMENTATION_NAME = "implementationName"; + private static final String PROPERTIES = "properties"; + + @Override + public ObjectNode encode(Driver driver, CodecContext context) { + checkNotNull(driver, "Driver cannot be null"); + + ObjectNode result = context.mapper().createObjectNode() + .put(NAME, driver.name()) + .put(MANUFACTURER, driver.manufacturer()) + .put(HW_VERSION, driver.hwVersion()) + .put(SW_VERSION, driver.swVersion()); + + if (driver.parent() != null) { + result.put(PARENT, driver.parent().name()); + } + + ArrayNode behaviours = context.mapper().createArrayNode(); + driver.behaviours().forEach(behaviour -> { + ObjectNode entry = context.mapper().createObjectNode() + .put(BEHAVIORS_NAME, behaviour.getCanonicalName()) + .put(BEHAVIORS_IMPLEMENTATION_NAME, + driver.implementation(behaviour).getCanonicalName()); + + behaviours.add(entry); + }); + result.set(BEHAVIOURS, behaviours); + + ArrayNode properties = context.mapper().createArrayNode(); + driver.properties().forEach((name, value) -> { + ObjectNode entry = context.mapper().createObjectNode() + .put("name", name) + .put("value", value); + + properties.add(entry); + }); + result.set(PROPERTIES, properties); + + return result; + } +} diff --git a/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/EncodeConstraintCodecHelper.java b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/EncodeConstraintCodecHelper.java new file mode 100644 index 00000000..61f4dbf4 --- /dev/null +++ b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/EncodeConstraintCodecHelper.java @@ -0,0 +1,201 @@ +/* + * 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.DeviceId; +import org.onosproject.net.Link; +import org.onosproject.net.intent.Constraint; +import org.onosproject.net.intent.constraint.AnnotationConstraint; +import org.onosproject.net.intent.constraint.BandwidthConstraint; +import org.onosproject.net.intent.constraint.LambdaConstraint; +import org.onosproject.net.intent.constraint.LatencyConstraint; +import org.onosproject.net.intent.constraint.LinkTypeConstraint; +import org.onosproject.net.intent.constraint.ObstacleConstraint; +import org.onosproject.net.intent.constraint.WaypointConstraint; + +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * Implementation of encoder for constraint JSON codec. + */ +public final class EncodeConstraintCodecHelper { + + private final Constraint constraint; + private final CodecContext context; + + /** + * Constructs a constraint encoder. + * + * @param constraint constraint to encode + * @param context to use for look ups + */ + public EncodeConstraintCodecHelper(Constraint constraint, CodecContext context) { + this.constraint = constraint; + this.context = context; + } + + /** + * Encodes a latency constraint. + * + * @return JSON ObjectNode representing the constraint + */ + private ObjectNode encodeLatencyConstraint() { + checkNotNull(constraint, "Duration constraint cannot be null"); + final LatencyConstraint latencyConstraint = + (LatencyConstraint) constraint; + return context.mapper().createObjectNode() + .put("latencyMillis", latencyConstraint.latency().toMillis()); + } + + /** + * Encodes an obstacle constraint. + * + * @return JSON ObjectNode representing the constraint + */ + private ObjectNode encodeObstacleConstraint() { + checkNotNull(constraint, "Obstacle constraint cannot be null"); + final ObstacleConstraint obstacleConstraint = + (ObstacleConstraint) constraint; + + final ObjectNode result = context.mapper().createObjectNode(); + final ArrayNode jsonObstacles = result.putArray("obstacles"); + + for (DeviceId did : obstacleConstraint.obstacles()) { + jsonObstacles.add(did.toString()); + } + + return result; + } + + /** + * Encodes a waypoint constraint. + * + * @return JSON ObjectNode representing the constraint + */ + private ObjectNode encodeWaypointConstraint() { + checkNotNull(constraint, "Waypoint constraint cannot be null"); + final WaypointConstraint waypointConstraint = + (WaypointConstraint) constraint; + + final ObjectNode result = context.mapper().createObjectNode(); + final ArrayNode jsonWaypoints = result.putArray("waypoints"); + + for (DeviceId did : waypointConstraint.waypoints()) { + jsonWaypoints.add(did.toString()); + } + + return result; + } + + /** + * Encodes a annotation constraint. + * + * @return JSON ObjectNode representing the constraint + */ + private ObjectNode encodeAnnotationConstraint() { + checkNotNull(constraint, "Annotation constraint cannot be null"); + final AnnotationConstraint annotationConstraint = + (AnnotationConstraint) constraint; + return context.mapper().createObjectNode() + .put("key", annotationConstraint.key()) + .put("threshold", annotationConstraint.threshold()); + } + + /** + * Encodes a bandwidth constraint. + * + * @return JSON ObjectNode representing the constraint + */ + private ObjectNode encodeBandwidthConstraint() { + checkNotNull(constraint, "Bandwidth constraint cannot be null"); + final BandwidthConstraint bandwidthConstraint = + (BandwidthConstraint) constraint; + return context.mapper().createObjectNode() + .put("bandwidth", bandwidthConstraint.bandwidth().toDouble()); + } + + /** + * Encodes a lambda constraint. + * + * @return JSON ObjectNode representing the constraint + */ + private ObjectNode encodeLambdaConstraint() { + checkNotNull(constraint, "Lambda constraint cannot be null"); + final LambdaConstraint lambdaConstraint = + (LambdaConstraint) constraint; + + return context.mapper().createObjectNode() + .put("lambda", lambdaConstraint.lambda().toInt()); + } + + /** + * Encodes a link type constraint. + * + * @return JSON ObjectNode representing the constraint + */ + private ObjectNode encodeLinkTypeConstraint() { + checkNotNull(constraint, "Link type constraint cannot be null"); + + final LinkTypeConstraint linkTypeConstraint = + (LinkTypeConstraint) constraint; + + final ObjectNode result = context.mapper().createObjectNode() + .put(ConstraintCodec.INCLUSIVE, linkTypeConstraint.isInclusive()); + + final ArrayNode jsonTypes = result.putArray(ConstraintCodec.TYPES); + + if (linkTypeConstraint.types() != null) { + for (Link.Type type : linkTypeConstraint.types()) { + jsonTypes.add(type.name()); + } + } + + return result; + } + + /** + * Encodes the constraint in JSON. + * + * @return JSON node + */ + public ObjectNode encode() { + final ObjectNode result; + if (constraint instanceof BandwidthConstraint) { + result = encodeBandwidthConstraint(); + } else if (constraint instanceof LambdaConstraint) { + result = encodeLambdaConstraint(); + } else if (constraint instanceof LinkTypeConstraint) { + result = encodeLinkTypeConstraint(); + } else if (constraint instanceof AnnotationConstraint) { + result = encodeAnnotationConstraint(); + } else if (constraint instanceof LatencyConstraint) { + result = encodeLatencyConstraint(); + } else if (constraint instanceof ObstacleConstraint) { + result = encodeObstacleConstraint(); + } else if (constraint instanceof WaypointConstraint) { + result = encodeWaypointConstraint(); + } else { + result = context.mapper().createObjectNode(); + } + + result.put(ConstraintCodec.TYPE, constraint.getClass().getSimpleName()); + return result; + } +} diff --git a/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/EncodeCriterionCodecHelper.java b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/EncodeCriterionCodecHelper.java new file mode 100644 index 00000000..a962c0dd --- /dev/null +++ b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/EncodeCriterionCodecHelper.java @@ -0,0 +1,396 @@ +/* + * 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.TunnelIdCriterion; +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 EncodeCriterionCodecHelper { + + 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 EncodeCriterionCodecHelper(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.TUNNEL_ID, new FormatTunnelId()); + 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.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().toShort()); + } + } + + 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().toInt()); + } + } + + 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().toInt()); + } + } + + 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().toInt()); + } + } + + 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 static class FormatTunnelId implements CriterionTypeFormatter { + @Override + public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) { + final TunnelIdCriterion tunnelIdCriterion = + (TunnelIdCriterion) criterion; + return root.put(CriterionCodec.TUNNEL_ID, tunnelIdCriterion.tunnelId()); + } + } + + 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); + } + +} diff --git a/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/EncodeInstructionCodecHelper.java b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/EncodeInstructionCodecHelper.java new file mode 100644 index 00000000..d61cf38b --- /dev/null +++ b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/EncodeInstructionCodecHelper.java @@ -0,0 +1,243 @@ +/* + * 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.onosproject.net.flow.instructions.L4ModificationInstruction; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.fasterxml.jackson.databind.node.ObjectNode; + +/** + * JSON encoding of Instructions. + */ +public final class EncodeInstructionCodecHelper { + protected static final Logger log = LoggerFactory.getLogger(EncodeInstructionCodecHelper.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 EncodeInstructionCodecHelper(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.mplsLabel().toInt()); + break; + + case MPLS_PUSH: + final L2ModificationInstruction.PushHeaderInstructions pushHeaderInstructions = + (L2ModificationInstruction.PushHeaderInstructions) instruction; + + result.put(InstructionCodec.ETHERNET_TYPE, + pushHeaderInstructions.ethernetType().toShort()); + break; + + case TUNNEL_ID: + final L2ModificationInstruction.ModTunnelIdInstruction modTunnelIdInstruction = + (L2ModificationInstruction.ModTunnelIdInstruction) instruction; + result.put(InstructionCodec.TUNNEL_ID, modTunnelIdInstruction.tunnelId()); + 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; + } + } + + /** + * Encode a L4 modification instruction. + * + * @param result json node that the instruction attributes are added to + */ + private void encodeL4(ObjectNode result) { + L4ModificationInstruction instruction = + (L4ModificationInstruction) this.instruction; + result.put(InstructionCodec.SUBTYPE, instruction.subtype().name()); + switch (instruction.subtype()) { + case TCP_DST: + case TCP_SRC: + final L4ModificationInstruction.ModTransportPortInstruction modTcpPortInstruction = + (L4ModificationInstruction.ModTransportPortInstruction) instruction; + result.put(InstructionCodec.TCP_PORT, modTcpPortInstruction.port().toInt()); + break; + + case UDP_DST: + case UDP_SRC: + final L4ModificationInstruction.ModTransportPortInstruction modUdpPortInstruction = + (L4ModificationInstruction.ModTransportPortInstruction) instruction; + result.put(InstructionCodec.UDP_PORT, modUdpPortInstruction.port().toInt()); + break; + + default: + log.info("Cannot convert L4 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; + + case L4MODIFICATION: + encodeL4(result); + break; + + default: + log.info("Cannot convert instruction type of {}", instruction.type()); + break; + } + return result; + } + +} diff --git a/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/EthernetCodec.java b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/EthernetCodec.java new file mode 100644 index 00000000..f56bca46 --- /dev/null +++ b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/EthernetCodec.java @@ -0,0 +1,58 @@ +/* + * 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.Ethernet; +import org.onosproject.codec.CodecContext; +import org.onosproject.codec.JsonCodec; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.fasterxml.jackson.databind.node.ObjectNode; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * Ethernet codec. + */ +public final class EthernetCodec extends JsonCodec<Ethernet> { + + protected static final Logger log = LoggerFactory.getLogger(CriterionCodec.class); + + @Override + public ObjectNode encode(Ethernet ethernet, CodecContext context) { + checkNotNull(ethernet, "Ethernet cannot be null"); + + final ObjectNode result = context.mapper().createObjectNode() + .put("vlanId", ethernet.getVlanID()) + .put("etherType", ethernet.getEtherType()) + .put("priorityCode", ethernet.getPriorityCode()) + .put("pad", ethernet.isPad()); + + if (ethernet.getDestinationMAC() != null) { + result.put("destMac", + ethernet.getDestinationMAC().toString()); + } + + if (ethernet.getSourceMAC() != null) { + result.put("srcMac", + ethernet.getSourceMAC().toString()); + } + + return result; + } + +} diff --git a/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/FlowEntryCodec.java b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/FlowEntryCodec.java new file mode 100644 index 00000000..923bdf2b --- /dev/null +++ b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/FlowEntryCodec.java @@ -0,0 +1,70 @@ +/* + * 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.codec.impl; + +import org.onosproject.codec.CodecContext; +import org.onosproject.codec.JsonCodec; +import org.onosproject.core.CoreService; +import org.onosproject.net.flow.FlowEntry; +import org.onosproject.net.flow.TrafficSelector; +import org.onosproject.net.flow.TrafficTreatment; + +import com.fasterxml.jackson.databind.node.ObjectNode; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * Flow entry JSON codec. + */ +public final class FlowEntryCodec extends JsonCodec<FlowEntry> { + + @Override + public ObjectNode encode(FlowEntry flowEntry, CodecContext context) { + checkNotNull(flowEntry, "Flow entry cannot be null"); + + CoreService service = context.getService(CoreService.class); + + final ObjectNode result = context.mapper().createObjectNode() + .put("id", Long.toString(flowEntry.id().value())) + .put("appId", service.getAppId(flowEntry.appId()).name()) + .put("groupId", flowEntry.groupId().id()) + .put("priority", flowEntry.priority()) + .put("timeout", flowEntry.timeout()) + .put("isPermanent", flowEntry.isPermanent()) + .put("deviceId", flowEntry.deviceId().toString()) + .put("state", flowEntry.state().toString()) + .put("life", flowEntry.life()) + .put("packets", flowEntry.packets()) + .put("bytes", flowEntry.bytes()) + .put("lastSeen", flowEntry.lastSeen()); + + if (flowEntry.treatment() != null) { + final JsonCodec<TrafficTreatment> treatmentCodec = + context.codec(TrafficTreatment.class); + result.set("treatment", treatmentCodec.encode(flowEntry.treatment(), context)); + } + + if (flowEntry.selector() != null) { + final JsonCodec<TrafficSelector> selectorCodec = + context.codec(TrafficSelector.class); + result.set("selector", selectorCodec.encode(flowEntry.selector(), context)); + } + + return result; + } + +} + diff --git a/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/FlowRuleCodec.java b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/FlowRuleCodec.java new file mode 100644 index 00000000..6c02841e --- /dev/null +++ b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/FlowRuleCodec.java @@ -0,0 +1,94 @@ +/* + * 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 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"; + public static final String REST_APP_ID = "org.onosproject.rest"; + + + @Override + public FlowRule decode(ObjectNode json, CodecContext context) { + if (json == null || !json.isObject()) { + return null; + } + + FlowRule.Builder resultBuilder = new DefaultFlowRule.Builder(); + + CoreService coreService = context.getService(CoreService.class); + resultBuilder.fromApp(coreService + .registerApplication(REST_APP_ID)); + + 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 = get(json, TREATMENT); + if (treatmentJson != null) { + JsonCodec<TrafficTreatment> treatmentCodec = + context.codec(TrafficTreatment.class); + resultBuilder.withTreatment(treatmentCodec.decode(treatmentJson, context)); + } + + ObjectNode selectorJson = get(json, SELECTOR); + if (selectorJson != null) { + JsonCodec<TrafficSelector> selectorCodec = + context.codec(TrafficSelector.class); + resultBuilder.withSelector(selectorCodec.decode(selectorJson, context)); + } + + return resultBuilder.build(); + } +} diff --git a/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/GroupBucketCodec.java b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/GroupBucketCodec.java new file mode 100644 index 00000000..c710514f --- /dev/null +++ b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/GroupBucketCodec.java @@ -0,0 +1,64 @@ +/* + * 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.net.flow.TrafficTreatment; +import org.onosproject.net.group.GroupBucket; + +import com.fasterxml.jackson.databind.node.ObjectNode; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * Group bucket JSON codec. + */ +public class GroupBucketCodec extends JsonCodec<GroupBucket> { + + private static final String TYPE = "type"; + private static final String TREATMENT = "treatment"; + private static final String WEIGHT = "weight"; + private static final String WATCH_PORT = "watchPort"; + private static final String WATCH_GROUP = "watchGroup"; + private static final String PACKETS = "packets"; + private static final String BYTES = "bytes"; + + @Override + public ObjectNode encode(GroupBucket bucket, CodecContext context) { + checkNotNull(bucket, "Driver cannot be null"); + + ObjectNode result = context.mapper().createObjectNode() + .put(TYPE, bucket.type().toString()) + .put(WEIGHT, bucket.weight()) + .put(PACKETS, bucket.packets()) + .put(BYTES, bucket.bytes()); + + if (bucket.watchPort() != null) { + result.put(WATCH_PORT, bucket.watchPort().toString()); + } + + if (bucket.watchGroup() != null) { + result.put(WATCH_GROUP, bucket.watchGroup().toString()); + } + + if (bucket.treatment() != null) { + result.set(TREATMENT, context.codec(TrafficTreatment.class).encode(bucket.treatment(), context)); + } + + return result; + } +} diff --git a/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/GroupCodec.java b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/GroupCodec.java new file mode 100644 index 00000000..a2f33cee --- /dev/null +++ b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/GroupCodec.java @@ -0,0 +1,79 @@ +/* + * 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.net.group.Group; +import org.onosproject.net.group.GroupBucket; + +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * Group JSON codec. + */ +public final class GroupCodec extends JsonCodec<Group> { + // JSON field names + private static final String ID = "id"; + private static final String STATE = "state"; + private static final String LIFE = "life"; + private static final String PACKETS = "packets"; + private static final String BYTES = "bytes"; + private static final String REFERENCE_COUNT = "referenceCount"; + private static final String TYPE = "type"; + private static final String DEVICE_ID = "deviceId"; + private static final String APP_ID = "appId"; + private static final String APP_COOKIE = "appCookie"; + private static final String GIVEN_GROUP_ID = "givenGroupId"; + private static final String BUCKETS = "buckets"; + + @Override + public ObjectNode encode(Group group, CodecContext context) { + checkNotNull(group, "Group cannot be null"); + ObjectNode result = context.mapper().createObjectNode() + .put(ID, group.id().toString()) + .put(STATE, group.state().toString()) + .put(LIFE, group.life()) + .put(PACKETS, group.packets()) + .put(BYTES, group.bytes()) + .put(REFERENCE_COUNT, group.referenceCount()) + .put(TYPE, group.type().toString()) + .put(DEVICE_ID, group.deviceId().toString()); + + if (group.appId() != null) { + result.put(APP_ID, group.appId().toString()); + } + + if (group.appCookie() != null) { + result.put(APP_COOKIE, group.appCookie().toString()); + } + + if (group.givenGroupId() != null) { + result.put(GIVEN_GROUP_ID, group.givenGroupId()); + } + + ArrayNode buckets = context.mapper().createArrayNode(); + group.buckets().buckets().forEach(bucket -> { + ObjectNode bucketJson = context.codec(GroupBucket.class).encode(bucket, context); + buckets.add(bucketJson); + }); + result.set(BUCKETS, buckets); + return result; + } +} diff --git a/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/HostCodec.java b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/HostCodec.java new file mode 100644 index 00000000..a2402728 --- /dev/null +++ b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/HostCodec.java @@ -0,0 +1,55 @@ +/* + * 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.codec.impl; + +import org.onlab.packet.IpAddress; +import org.onosproject.codec.CodecContext; +import org.onosproject.codec.JsonCodec; +import org.onosproject.net.Host; +import org.onosproject.net.HostLocation; + +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * Host JSON codec. + */ +public final class HostCodec extends AnnotatedCodec<Host> { + + @Override + public ObjectNode encode(Host host, CodecContext context) { + checkNotNull(host, "Host cannot be null"); + final JsonCodec<HostLocation> locationCodec = + context.codec(HostLocation.class); + final ObjectNode result = context.mapper().createObjectNode() + .put("id", host.id().toString()) + .put("mac", host.mac().toString()) + .put("vlan", host.vlan().toString()); + + final ArrayNode jsonIpAddresses = result.putArray("ipAddresses"); + for (final IpAddress ipAddress : host.ipAddresses()) { + jsonIpAddresses.add(ipAddress.toString()); + } + result.set("ipAddresses", jsonIpAddresses); + result.set("location", locationCodec.encode(host.location(), context)); + + return annotate(result, host, context); + } + +} + diff --git a/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/HostLocationCodec.java b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/HostLocationCodec.java new file mode 100644 index 00000000..f8f616d0 --- /dev/null +++ b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/HostLocationCodec.java @@ -0,0 +1,39 @@ +/* + * 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.codec.impl; + +import org.onosproject.codec.CodecContext; +import org.onosproject.codec.JsonCodec; +import org.onosproject.net.HostLocation; + +import com.fasterxml.jackson.databind.node.ObjectNode; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * Host JSON codec. + */ +public final class HostLocationCodec extends JsonCodec<HostLocation> { + + @Override + public ObjectNode encode(HostLocation hostLocation, CodecContext context) { + checkNotNull(hostLocation, "Host location cannot be null"); + return context.mapper().createObjectNode() + .put("elementId", hostLocation.elementId().toString()) + .put("port", hostLocation.port().toString()); + } + +} diff --git a/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/HostToHostIntentCodec.java b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/HostToHostIntentCodec.java new file mode 100644 index 00000000..597ab55c --- /dev/null +++ b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/HostToHostIntentCodec.java @@ -0,0 +1,70 @@ +/* + * 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.net.HostId; +import org.onosproject.net.intent.ConnectivityIntent; +import org.onosproject.net.intent.HostToHostIntent; + +import com.fasterxml.jackson.databind.node.ObjectNode; + +import static com.google.common.base.Preconditions.checkNotNull; +import static org.onlab.util.Tools.nullIsIllegal; + +/** + * Host to host intent codec. + */ +public final class HostToHostIntentCodec extends JsonCodec<HostToHostIntent> { + + private static final String ONE = "one"; + private static final String TWO = "two"; + + @Override + public ObjectNode encode(HostToHostIntent intent, CodecContext context) { + checkNotNull(intent, "Host to host intent cannot be null"); + + final JsonCodec<ConnectivityIntent> connectivityIntentCodec = + context.codec(ConnectivityIntent.class); + final ObjectNode result = connectivityIntentCodec.encode(intent, context); + + final String one = intent.one().toString(); + final String two = intent.two().toString(); + result.put(ONE, one); + result.put(TWO, two); + + return result; + } + + @Override + public HostToHostIntent decode(ObjectNode json, CodecContext context) { + HostToHostIntent.Builder builder = HostToHostIntent.builder(); + + IntentCodec.intentAttributes(json, context, builder); + ConnectivityIntentCodec.intentAttributes(json, context, builder); + + String one = nullIsIllegal(json.get(ONE), + ONE + IntentCodec.MISSING_MEMBER_MESSAGE).asText(); + builder.one(HostId.hostId(one)); + + String two = nullIsIllegal(json.get(TWO), + TWO + IntentCodec.MISSING_MEMBER_MESSAGE).asText(); + builder.two(HostId.hostId(two)); + + return builder.build(); + } +} diff --git a/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/InstructionCodec.java b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/InstructionCodec.java new file mode 100644 index 00000000..f4d5008a --- /dev/null +++ b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/InstructionCodec.java @@ -0,0 +1,73 @@ +/* + * 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.net.flow.instructions.Instruction; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.fasterxml.jackson.databind.node.ObjectNode; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * Instruction codec. + */ +public final class InstructionCodec extends JsonCodec<Instruction> { + + protected static final Logger log = LoggerFactory.getLogger(InstructionCodec.class); + + 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 TUNNEL_ID = "tunnelId"; + protected static final String TCP_PORT = "tcpPort"; + protected static final String UDP_PORT = "udpPort"; + + protected static final String MISSING_MEMBER_MESSAGE = + " member is required in Instruction"; + + + @Override + public ObjectNode encode(Instruction instruction, CodecContext context) { + checkNotNull(instruction, "Instruction cannot be null"); + + return new EncodeInstructionCodecHelper(instruction, context).encode(); + } + + @Override + public Instruction decode(ObjectNode json, CodecContext context) { + if (json == null || !json.isObject()) { + return null; + } + + return new DecodeInstructionCodecHelper(json).decode(); + } +} diff --git a/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/IntentCodec.java b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/IntentCodec.java new file mode 100644 index 00000000..8613a964 --- /dev/null +++ b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/IntentCodec.java @@ -0,0 +1,112 @@ +/* + * 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.codec.impl; + +import org.onosproject.codec.CodecContext; +import org.onosproject.codec.JsonCodec; +import org.onosproject.core.CoreService; +import org.onosproject.net.NetworkResource; +import org.onosproject.net.intent.HostToHostIntent; +import org.onosproject.net.intent.Intent; +import org.onosproject.net.intent.IntentService; +import org.onosproject.net.intent.IntentState; +import org.onosproject.net.intent.PointToPointIntent; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.google.common.net.UrlEscapers; + +import static com.google.common.base.Preconditions.checkNotNull; +import static org.onlab.util.Tools.nullIsIllegal; + +/** + * Intent JSON codec. + */ +public final class IntentCodec extends JsonCodec<Intent> { + + protected static final String TYPE = "type"; + protected static final String ID = "id"; + protected static final String APP_ID = "appId"; + protected static final String STATE = "state"; + protected static final String PRIORITY = "priority"; + protected static final String RESOURCES = "resources"; + protected static final String MISSING_MEMBER_MESSAGE = + " member is required in Intent"; + + @Override + public ObjectNode encode(Intent intent, CodecContext context) { + checkNotNull(intent, "Intent cannot be null"); + + final ObjectNode result = context.mapper().createObjectNode() + .put(TYPE, intent.getClass().getSimpleName()) + .put(ID, intent.id().toString()) + .put(APP_ID, UrlEscapers.urlPathSegmentEscaper() + .escape(intent.appId().name())); + + final ArrayNode jsonResources = result.putArray(RESOURCES); + + for (final NetworkResource resource : intent.resources()) { + jsonResources.add(resource.toString()); + } + + IntentService service = context.getService(IntentService.class); + IntentState state = service.getIntentState(intent.key()); + if (state != null) { + result.put(STATE, state.toString()); + } + + return result; + } + + @Override + public Intent decode(ObjectNode json, CodecContext context) { + checkNotNull(json, "JSON cannot be null"); + + String type = nullIsIllegal(json.get(TYPE), + TYPE + MISSING_MEMBER_MESSAGE).asText(); + + if (type.equals(PointToPointIntent.class.getSimpleName())) { + return context.codec(PointToPointIntent.class).decode(json, context); + } else if (type.equals(HostToHostIntent.class.getSimpleName())) { + return context.codec(HostToHostIntent.class).decode(json, context); + } + + throw new IllegalArgumentException("Intent type " + + type + " is not supported"); + } + + /** + * Extracts base intent specific attributes from a JSON object + * and adds them to a builder. + * + * @param json root JSON object + * @param context code context + * @param builder builder to use for storing the attributes + */ + public static void intentAttributes(ObjectNode json, CodecContext context, + Intent.Builder builder) { + String appId = nullIsIllegal(json.get(IntentCodec.APP_ID), + IntentCodec.APP_ID + IntentCodec.MISSING_MEMBER_MESSAGE).asText(); + CoreService service = context.getService(CoreService.class); + builder.appId(service.getAppId(appId)); + + JsonNode priorityJson = json.get(IntentCodec.PRIORITY); + if (priorityJson != null) { + builder.priority(priorityJson.asInt()); + } + } +} diff --git a/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/LinkCodec.java b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/LinkCodec.java new file mode 100644 index 00000000..14ee9b7c --- /dev/null +++ b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/LinkCodec.java @@ -0,0 +1,80 @@ +/* + * 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.codec.impl; + +import com.fasterxml.jackson.databind.node.ObjectNode; + +import org.onosproject.codec.CodecContext; +import org.onosproject.codec.JsonCodec; +import org.onosproject.net.Annotations; +import org.onosproject.net.ConnectPoint; +import org.onosproject.net.DefaultLink; +import org.onosproject.net.Link; +import org.onosproject.net.Link.Type; +import org.onosproject.net.provider.ProviderId; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * Link JSON codec. + */ +public final class LinkCodec extends AnnotatedCodec<Link> { + + // JSON field names + private static final String SRC = "src"; + private static final String DST = "dst"; + private static final String TYPE = "type"; + private static final String STATE = "state"; + + @Override + public ObjectNode encode(Link link, CodecContext context) { + checkNotNull(link, "Link cannot be null"); + JsonCodec<ConnectPoint> codec = context.codec(ConnectPoint.class); + ObjectNode result = context.mapper().createObjectNode(); + result.set(SRC, codec.encode(link.src(), context)); + result.set(DST, codec.encode(link.dst(), context)); + result.put(TYPE, link.type().toString()); + if (link.state() != null) { + result.put(STATE, link.state().toString()); + } + return annotate(result, link, context); + } + + + /** + * {@inheritDoc} + * + * Note: ProviderId is not part of JSON representation. + * Returned object will have random ProviderId set. + */ + @Override + public Link decode(ObjectNode json, CodecContext context) { + if (json == null || !json.isObject()) { + return null; + } + + JsonCodec<ConnectPoint> codec = context.codec(ConnectPoint.class); + // TODO: add providerId to JSON if we need to recover them. + ProviderId pid = new ProviderId("json", "LinkCodec"); + + ConnectPoint src = codec.decode(get(json, SRC), context); + ConnectPoint dst = codec.decode(get(json, DST), context); + Type type = Type.valueOf(json.get(TYPE).asText()); + Annotations annotations = extractAnnotations(json, context); + + return new DefaultLink(pid, src, dst, type, annotations); + } +} diff --git a/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/LoadCodec.java b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/LoadCodec.java new file mode 100644 index 00000000..0e55592d --- /dev/null +++ b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/LoadCodec.java @@ -0,0 +1,45 @@ +/* + * 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.net.statistic.Load; + +import com.fasterxml.jackson.databind.node.ObjectNode; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * Codec for the Load class. + */ +public class LoadCodec extends JsonCodec<Load> { + + private static final String RATE = "rate"; + private static final String LATEST = "latest"; + private static final String VALID = "valid"; + private static final String TIME = "time"; + + @Override + public ObjectNode encode(Load load, CodecContext context) { + checkNotNull(load, "Load cannot be null"); + return context.mapper().createObjectNode() + .put(RATE, load.rate()) + .put(LATEST, load.latest()) + .put(VALID, load.isValid()) + .put(TIME, load.time()); + } +} diff --git a/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/PathCodec.java b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/PathCodec.java new file mode 100644 index 00000000..58b48529 --- /dev/null +++ b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/PathCodec.java @@ -0,0 +1,47 @@ +/* + * 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.net.Link; +import org.onosproject.net.Path; + +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * Path JSON codec. + */ +public final class PathCodec extends AnnotatedCodec<Path> { + @Override + public ObjectNode encode(Path path, CodecContext context) { + checkNotNull(path, "Path cannot be null"); + JsonCodec<Link> codec = context.codec(Link.class); + ObjectNode result = context.mapper() + .createObjectNode() + .put("cost", path.cost()); + ArrayNode jsonLinks = result.putArray("links"); + + for (Link link : path.links()) { + jsonLinks.add(codec.encode(link, context)); + } + + return annotate(result, path, context); + } +} diff --git a/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/PointToPointIntentCodec.java b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/PointToPointIntentCodec.java new file mode 100644 index 00000000..20df4890 --- /dev/null +++ b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/PointToPointIntentCodec.java @@ -0,0 +1,80 @@ +/* + * 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.net.ConnectPoint; +import org.onosproject.net.intent.ConnectivityIntent; +import org.onosproject.net.intent.PointToPointIntent; + +import com.fasterxml.jackson.databind.node.ObjectNode; + +import static com.google.common.base.Preconditions.checkNotNull; +import static org.onlab.util.Tools.nullIsIllegal; + +/** + * Point to point intent codec. + */ +public final class PointToPointIntentCodec extends JsonCodec<PointToPointIntent> { + + private static final String INGRESS_POINT = "ingressPoint"; + private static final String EGRESS_POINT = "egressPoint"; + + @Override + public ObjectNode encode(PointToPointIntent intent, CodecContext context) { + checkNotNull(intent, "Point to point intent cannot be null"); + + final JsonCodec<ConnectivityIntent> connectivityIntentCodec = + context.codec(ConnectivityIntent.class); + final ObjectNode result = connectivityIntentCodec.encode(intent, context); + + final JsonCodec<ConnectPoint> connectPointCodec = + context.codec(ConnectPoint.class); + final ObjectNode ingress = + connectPointCodec.encode(intent.ingressPoint(), context); + final ObjectNode egress = + connectPointCodec.encode(intent.egressPoint(), context); + + result.set(INGRESS_POINT, ingress); + result.set(EGRESS_POINT, egress); + + return result; + } + + + @Override + public PointToPointIntent decode(ObjectNode json, CodecContext context) { + PointToPointIntent.Builder builder = PointToPointIntent.builder(); + + IntentCodec.intentAttributes(json, context, builder); + ConnectivityIntentCodec.intentAttributes(json, context, builder); + + ObjectNode ingressJson = nullIsIllegal(get(json, INGRESS_POINT), + INGRESS_POINT + IntentCodec.MISSING_MEMBER_MESSAGE); + ConnectPoint ingress = context.codec(ConnectPoint.class) + .decode(ingressJson, context); + builder.ingressPoint(ingress); + + ObjectNode egressJson = nullIsIllegal(get(json, EGRESS_POINT), + EGRESS_POINT + IntentCodec.MISSING_MEMBER_MESSAGE); + ConnectPoint egress = context.codec(ConnectPoint.class) + .decode(egressJson, context); + builder.egressPoint(egress); + + return builder.build(); + } +} diff --git a/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/PortCodec.java b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/PortCodec.java new file mode 100644 index 00000000..c6f2ac76 --- /dev/null +++ b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/PortCodec.java @@ -0,0 +1,160 @@ +/* + * 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.codec.impl; + +import com.fasterxml.jackson.databind.node.ObjectNode; + +import org.onlab.packet.ChassisId; +import org.onosproject.codec.CodecContext; +import org.onosproject.net.Annotations; +import org.onosproject.net.DefaultAnnotations; +import org.onosproject.net.DefaultPort; +import org.onosproject.net.Device; +import org.onosproject.net.DeviceId; +import org.onosproject.net.Port; +import org.onosproject.net.Port.Type; +import org.onosproject.net.PortNumber; +import org.onosproject.net.provider.ProviderId; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * Device port JSON codec. + */ +public final class PortCodec extends AnnotatedCodec<Port> { + + // JSON field names + private static final String ELEMENT = "element"; // DeviceId + private static final String PORT_NAME = "port"; + private static final String IS_ENABLED = "isEnabled"; + private static final String TYPE = "type"; + private static final String PORT_SPEED = "portSpeed"; + + // Special port name alias + private static final String PORT_NAME_LOCAL = "local"; + + @Override + public ObjectNode encode(Port port, CodecContext context) { + checkNotNull(port, "Port cannot be null"); + ObjectNode result = context.mapper().createObjectNode() + .put(ELEMENT, port.element().id().toString()) + .put(PORT_NAME, portName(port.number())) + .put(IS_ENABLED, port.isEnabled()) + .put(TYPE, port.type().toString().toLowerCase()) + .put(PORT_SPEED, port.portSpeed()); + return annotate(result, port, context); + } + + private String portName(PortNumber port) { + return port.equals(PortNumber.LOCAL) ? PORT_NAME_LOCAL : port.toString(); + } + + private static PortNumber portNumber(String portName) { + if (portName.equalsIgnoreCase(PORT_NAME_LOCAL)) { + return PortNumber.LOCAL; + } + + return PortNumber.portNumber(portName); + } + + + /** + * {@inheritDoc} + * + * Note: Result of {@link Port#element()} returned Port object, + * is not a full Device object. + * Only it's DeviceId can be used. + */ + @Override + public Port decode(ObjectNode json, CodecContext context) { + if (json == null || !json.isObject()) { + return null; + } + + DeviceId did = DeviceId.deviceId(json.get(ELEMENT).asText()); + Device device = new DummyDevice(did); + PortNumber number = portNumber(json.get(PORT_NAME).asText()); + boolean isEnabled = json.get(IS_ENABLED).asBoolean(); + Type type = Type.valueOf(json.get(TYPE).asText().toUpperCase()); + long portSpeed = json.get(PORT_SPEED).asLong(); + Annotations annotations = extractAnnotations(json, context); + + return new DefaultPort(device, number, isEnabled, type, portSpeed, annotations); + } + + + /** + * Dummy Device which only holds DeviceId. + */ + private static final class DummyDevice implements Device { + + private final DeviceId did; + + /** + * Constructs Dummy Device which only holds DeviceId. + * + * @param did device Id + */ + public DummyDevice(DeviceId did) { + this.did = did; + } + + @Override + public Annotations annotations() { + return DefaultAnnotations.EMPTY; + } + + @Override + public ProviderId providerId() { + return new ProviderId(did.uri().getScheme(), "PortCodec"); + } + + @Override + public DeviceId id() { + return did; + } + + @Override + public Type type() { + return Type.SWITCH; + } + + @Override + public String manufacturer() { + return "dummy"; + } + + @Override + public String hwVersion() { + return "0"; + } + + @Override + public String swVersion() { + return "0"; + } + + @Override + public String serialNumber() { + return "0"; + } + + @Override + public ChassisId chassisId() { + return new ChassisId(); + } + } +} diff --git a/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/TopologyClusterCodec.java b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/TopologyClusterCodec.java new file mode 100644 index 00000000..dc4c79a7 --- /dev/null +++ b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/TopologyClusterCodec.java @@ -0,0 +1,41 @@ +/* + * 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.net.topology.TopologyCluster; + +import com.fasterxml.jackson.databind.node.ObjectNode; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * Topology cluster JSON codec. + */ +public final class TopologyClusterCodec extends JsonCodec<TopologyCluster> { + + @Override + public ObjectNode encode(TopologyCluster cluster, CodecContext context) { + checkNotNull(cluster, "Cluster cannot be null"); + + return context.mapper().createObjectNode() + .put("id", cluster.id().index()) + .put("deviceCount", cluster.deviceCount()) + .put("linkCount", cluster.linkCount()) + .put("root", cluster.root().toString()); + } +} diff --git a/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/TopologyCodec.java b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/TopologyCodec.java new file mode 100644 index 00000000..f6529eb5 --- /dev/null +++ b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/TopologyCodec.java @@ -0,0 +1,41 @@ +/* + * 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.net.topology.Topology; + +import com.fasterxml.jackson.databind.node.ObjectNode; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * Topology JSON codec. + */ +public final class TopologyCodec extends JsonCodec<Topology> { + + @Override + public ObjectNode encode(Topology topology, CodecContext context) { + checkNotNull(topology, "Topology cannot be null"); + + return context.mapper().createObjectNode() + .put("time", topology.time()) + .put("devices", topology.deviceCount()) + .put("links", topology.linkCount()) + .put("clusters", topology.clusterCount()); + } +} diff --git a/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/TrafficSelectorCodec.java b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/TrafficSelectorCodec.java new file mode 100644 index 00000000..24ebef1a --- /dev/null +++ b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/TrafficSelectorCodec.java @@ -0,0 +1,71 @@ +/* + * 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.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; + +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); + + if (selector.criteria() != null) { + final JsonCodec<Criterion> criterionCodec = + context.codec(Criterion.class); + for (final Criterion criterion : selector.criteria()) { + jsonCriteria.add(criterionCodec.encode(criterion, context)); + } + } + + 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(get(criteriaJson, i), + context))); + } + return builder.build(); + } +} diff --git a/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/TrafficTreatmentCodec.java b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/TrafficTreatmentCodec.java new file mode 100644 index 00000000..0d7fb420 --- /dev/null +++ b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/TrafficTreatmentCodec.java @@ -0,0 +1,76 @@ +/* + * 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.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; + +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 JsonCodec<Instruction> instructionCodec = + context.codec(Instruction.class); + + for (final Instruction instruction : treatment.immediate()) { + jsonInstructions.add(instructionCodec.encode(instruction, context)); + } + + final ArrayNode jsonDeferred = result.putArray("deferred"); + + for (final Instruction instruction : treatment.deferred()) { + jsonDeferred.add(instructionCodec.encode(instruction, context)); + } + + 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(get(instructionsJson, i), + context))); + } + return builder.build(); + } +} diff --git a/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/package-info.java b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/package-info.java new file mode 100644 index 00000000..b3113e97 --- /dev/null +++ b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/package-info.java @@ -0,0 +1,20 @@ +/* + * 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. + */ + +/** + * Implementations of the codec broker and built-in entity JSON codecs. + */ +package org.onosproject.codec.impl; |