blob: 20671f72725a60794d144b5525266f1bc19e7ed0 [file] [log] [blame]
/*
* Copyright 2016-present Open Networking Foundation
*
* 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.pcerest;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.onosproject.net.Link.State.ACTIVE;
import static org.onosproject.net.Link.Type.DIRECT;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import org.onosproject.codec.CodecContext;
import org.onosproject.codec.JsonCodec;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DefaultLink;
import org.onosproject.net.DeviceId;
import org.onosproject.net.NetworkResource;
import org.onosproject.net.PortNumber;
import org.onosproject.net.provider.ProviderId;
import org.onosproject.pce.pceservice.ExplicitPathInfo;
import org.onosproject.pce.pceservice.PcePath;
import org.onosproject.pce.pceservice.DefaultPcePath;
import org.onosproject.pce.pceservice.constraint.CostConstraint;
import org.onosproject.pce.pceservice.constraint.PceBandwidthConstraint;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.databind.JsonNode;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
/**
* PCE path json codec.
*/
public final class PcePathCodec extends JsonCodec<PcePath> {
private final Logger log = LoggerFactory.getLogger(PcePathCodec.class);
private static final String SOURCE = "source";
private static final String DESTINATION = "destination";
private static final String LSP_TYPE = "pathType";
private static final String SYMBOLIC_PATH_NAME = "name";
private static final String CONSTRAINT = "constraint";
private static final String COST = "cost";
private static final String BANDWIDTH = "bandwidth";
private static final String PATH_ID = "pathId";
private static final String EXPLICIT_PATH_INFO = "explicitPathInfo";
private static final String MISSING_MEMBER_MESSAGE = " member is required in pce-path";
public static final String JSON_NOT_NULL = "JsonNode can not be null";
public static final byte SOURCE_DEVICEID_INDEX = 0;
public static final byte SOURCE_PORTNO_INDEX = 1;
public static final byte DESTINATION_DEVICEID_INDEX = 2;
public static final byte DESTINATION_PORTNO_INDEX = 3;
@Override
public PcePath decode(ObjectNode json, CodecContext context) {
if (json == null || !json.isObject()) {
log.error("Empty json input");
return null;
}
// build pce-path
PcePath.Builder resultBuilder = new DefaultPcePath.Builder();
// retrieve source
JsonNode jNode = json.get(SOURCE);
if (jNode != null) {
String src = jNode.asText();
resultBuilder.source(src);
}
// retrieve destination
jNode = json.get(DESTINATION);
if (jNode != null) {
String dst = jNode.asText();
resultBuilder.destination(dst);
}
// retrieve lsp-type
jNode = json.get(LSP_TYPE);
if (jNode != null) {
String lspType = jNode.asText();
//Validating LSP type
int type = Integer.parseInt(lspType);
if ((type < 0) || (type > 2)) {
return null;
}
resultBuilder.lspType(lspType);
}
// retrieve symbolic-path-name
jNode = json.get(SYMBOLIC_PATH_NAME);
if (jNode != null) {
String name = jNode.asText();
resultBuilder.name(name);
}
// retrieve constraint
JsonNode constraintJNode = (JsonNode) json.path(CONSTRAINT);
if ((constraintJNode != null) && (!constraintJNode.isMissingNode())) {
// retrieve cost
jNode = constraintJNode.get(COST);
if (jNode != null) {
String cost = jNode.asText();
//Validating Cost type
int costType = Integer.parseInt(cost);
if ((costType < 1) || (costType > 2)) {
return null;
}
resultBuilder.costConstraint(cost);
}
// retrieve bandwidth
jNode = constraintJNode.get(BANDWIDTH);
if (jNode != null) {
String bandwidth = jNode.asText();
double bw = Double.parseDouble(bandwidth);
if (bw < 0) {
return null;
}
resultBuilder.bandwidthConstraint(bandwidth);
}
}
// Retrieve explicit path info
JsonNode explicitPathInfo = json.get(EXPLICIT_PATH_INFO);
if (explicitPathInfo != null) {
List<ExplicitPathInfo> explicitPathInfoList =
ImmutableList.copyOf(jsonNodeToExplicitPathInfo(explicitPathInfo));
if (explicitPathInfoList != null) {
resultBuilder.explicitPathInfo(explicitPathInfoList);
}
}
return resultBuilder.build();
}
private ExplicitPathInfo createListOfExplicitPathObj(JsonNode node) {
int explicitPathType = Integer.parseInt(node.get("type").asText());
DeviceId deviceId;
PortNumber portNo;
NetworkResource res;
LinkedList<ExplicitPathInfo> list = Lists.newLinkedList();
if ((explicitPathType < 0) || (explicitPathType > 1)) {
return null;
}
ExplicitPathInfo.Type type = ExplicitPathInfo.Type.values()[explicitPathType];
String subType = node.get("subtype").asText();
if (Integer.parseInt(subType) == 0) {
res = DeviceId.deviceId(node.get("value").asText());
} else if (Integer.parseInt(subType) == 1) {
String[] splitted = node.get("value").asText().split("/");
if (splitted[SOURCE_DEVICEID_INDEX] != null
&& splitted[SOURCE_PORTNO_INDEX] != null
&& splitted[DESTINATION_DEVICEID_INDEX] != null
&& splitted[DESTINATION_PORTNO_INDEX] != null) {
return null;
}
deviceId = DeviceId.deviceId(splitted[SOURCE_DEVICEID_INDEX]);
portNo = PortNumber.portNumber(splitted[SOURCE_PORTNO_INDEX]);
ConnectPoint cpSrc = new ConnectPoint(deviceId, portNo);
deviceId = DeviceId.deviceId(splitted[DESTINATION_DEVICEID_INDEX]);
portNo = PortNumber.portNumber(splitted[DESTINATION_PORTNO_INDEX]);
ConnectPoint cpDst = new ConnectPoint(deviceId, portNo);
res = DefaultLink.builder()
.providerId(ProviderId.NONE)
.src(cpSrc)
.dst(cpDst)
.type(DIRECT)
.state(ACTIVE)
.build();
} else {
return null;
}
return new ExplicitPathInfo(type, res);
}
private Collection<ExplicitPathInfo> jsonNodeToExplicitPathInfo(JsonNode explicitPathInfo) {
checkNotNull(explicitPathInfo, JSON_NOT_NULL);
Integer i = 0;
NetworkResource res;
LinkedList<ExplicitPathInfo> list = Lists.newLinkedList();
if (explicitPathInfo.isArray()) {
for (JsonNode node : explicitPathInfo) {
ExplicitPathInfo obj = createListOfExplicitPathObj(node);
if (obj == null) {
return null;
}
list.add(obj);
}
} else {
ExplicitPathInfo obj = createListOfExplicitPathObj(explicitPathInfo);
if (obj == null) {
return null;
}
list.add(obj);
}
return Collections.unmodifiableCollection(list);
}
@Override
public ObjectNode encode(PcePath path, CodecContext context) {
checkNotNull(path, "path output cannot be null");
ObjectNode result = context.mapper()
.createObjectNode()
.put(PATH_ID, path.id().id())
.put(SOURCE, path.source())
.put(DESTINATION, path.destination())
.put(LSP_TYPE, path.lspType().type())
.put(SYMBOLIC_PATH_NAME, path.name());
ObjectNode constraintNode = context.mapper()
.createObjectNode()
.put(COST, ((CostConstraint) path.costConstraint()).type().type())
.put(BANDWIDTH, ((PceBandwidthConstraint) path.bandwidthConstraint()).bandwidth().bps());
if (path.explicitPathInfo() != null && !path.explicitPathInfo().isEmpty()) {
ArrayNode arrayNode = context.mapper().createArrayNode();
for (ExplicitPathInfo e : path.explicitPathInfo()) {
ObjectNode node = context.mapper()
.createObjectNode()
.put("type", e.type().toString())
.put("value", e.value().toString());
arrayNode.add(node);
}
result.set(EXPLICIT_PATH_INFO, arrayNode);
}
result.set(CONSTRAINT, constraintNode);
return result;
}
}