/* * Copyright (c) 2015 SNLAB and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ package org.opendaylight.alto.spce.impl; import org.opendaylight.alto.spce.impl.algorithm.PathComputation; import org.opendaylight.alto.spce.impl.util.FlowManager; import org.opendaylight.alto.spce.impl.util.InventoryReader; import org.opendaylight.alto.spce.impl.util.MeterManager; import org.opendaylight.alto.spce.impl.util.RouteManager; import org.opendaylight.controller.md.sal.binding.api.DataBroker; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address; import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev160718.AltoSpceMetric; import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev160718.AltoSpceService; import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev160718.ErrorCodeType; import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev160718.FlowType; import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev160718.GetRouteInput; import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev160718.GetRouteOutput; import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev160718.GetRouteOutputBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev160718.RemoveRateLimitingInput; import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev160718.RemoveRateLimitingOutput; import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev160718.RemoveRateLimitingOutputBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev160718.RemoveRouteInput; import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev160718.RemoveRouteOutput; import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev160718.RemoveRouteOutputBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev160718.SetupRouteInput; import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev160718.SetupRouteOutput; import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev160718.SetupRouteOutputBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev160718.UpdateRateLimitingInput; import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev160718.UpdateRateLimitingOutput; import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev160718.UpdateRateLimitingOutputBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev160718.endpoints.group.Endpoints; import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev160718.endpoints.group.EndpointsBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev160718.setup.route.input.ConstraintMetric; import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev160718.setup.route.input.ConstraintMetricBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.SalMeterService; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.tracker.rev151107.NetworkTrackerService; import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TpId; import org.opendaylight.yangtools.yang.common.RpcResult; import org.opendaylight.yangtools.yang.common.RpcResultBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.math.BigInteger; import java.util.LinkedList; import java.util.List; import java.util.concurrent.Future; public class AltoSpceImpl implements AltoSpceService { private static final Logger LOG = LoggerFactory.getLogger(FlowManager.class); private FlowManager flowManager; private MeterManager meterManager; private InventoryReader inventoryReader; private PathComputation pathComputation; private RouteManager routeManager; public AltoSpceImpl(SalMeterService salMeterService, NetworkTrackerService networkTrackerService, DataBroker dataBroker) { this.meterManager = new MeterManager(salMeterService, dataBroker); this.flowManager = new FlowManager(dataBroker); this.inventoryReader = new InventoryReader(dataBroker); this.pathComputation = new PathComputation(networkTrackerService); this.routeManager = new RouteManager(pathComputation, inventoryReader, networkTrackerService, flowManager, meterManager, dataBroker); } private List<ConstraintMetric> compressConstraint(List<ConstraintMetric> constraintMetrics) { if (constraintMetrics == null) return null; List<ConstraintMetric> compressedConstraintMetrics = new LinkedList<>(); BigInteger minHopcount = BigInteger.ZERO; BigInteger maxHopcount = BigInteger.valueOf(Long.MAX_VALUE); BigInteger minBandwidth = BigInteger.ZERO; BigInteger maxBandwidth = BigInteger.valueOf(Long.MAX_VALUE); for (ConstraintMetric constraintMetric : constraintMetrics) { if (constraintMetric.getMetric() == AltoSpceMetric.Hopcount) { minHopcount = minHopcount.max(constraintMetric.getMin()); maxHopcount = maxHopcount.min(constraintMetric.getMax()); if (minHopcount.compareTo(maxHopcount) == 1) { return null; } } else if (constraintMetric.getMetric() == AltoSpceMetric.Bandwidth) { minBandwidth = minBandwidth.max(constraintMetric.getMin()); maxBandwidth = maxBandwidth.min(constraintMetric.getMax()); if (minBandwidth.compareTo(maxBandwidth) == 1) { return null; } } } compressedConstraintMetrics.add(new ConstraintMetricBuilder() .setMetric(AltoSpceMetric.Hopcount) .setMin(minHopcount) .setMax(maxHopcount) .build()); compressedConstraintMetrics.add(new ConstraintMetricBuilder() .setMetric(AltoSpceMetric.Bandwidth) .setMin(minBandwidth) .setMax(maxBandwidth) .build()); return compressedConstraintMetrics; } private String showRoute(Endpoints endpoint, List<TpId> path) { String pathString = endpoint.getSrc().getValue(); if (path != null) { for (TpId tpId : path) { pathString += "|" + tpId.getValue(); } } pathString += "|" + endpoint.getDst().getValue(); return pathString; } @Override public Future<RpcResult<UpdateRateLimitingOutput>> updateRateLimiting(UpdateRateLimitingInput input) { ErrorCodeType errorCodeType = this.routeManager.updateRateLimiting(input.getEndpoints(), input.getLimitedRate(), input.getBurstSize()); UpdateRateLimitingOutputBuilder builder = new UpdateRateLimitingOutputBuilder().setErrorCode(errorCodeType); if (errorCodeType==ErrorCodeType.OK) { builder.setRoute(showRoute(input.getEndpoints(),this.routeManager.getRoute(input.getEndpoints()))); } return RpcResultBuilder.success(builder.build()).buildFuture(); } @Override public Future<RpcResult<RemoveRateLimitingOutput>> removeRateLimiting(RemoveRateLimitingInput input) { ErrorCodeType errorCodeType = this.routeManager.removeRateLimiting(input.getEndpoints()); RemoveRateLimitingOutputBuilder builder = new RemoveRateLimitingOutputBuilder().setErrorCode(errorCodeType); if (errorCodeType==ErrorCodeType.OK) { builder.setRoute(showRoute(input.getEndpoints(),this.routeManager.getRoute(input.getEndpoints()))); } return RpcResultBuilder.success(builder.build()).buildFuture(); } @Override public Future<RpcResult<RemoveRouteOutput>> removeRoute(RemoveRouteInput input) { String route = input.getRoute(); String src = route.substring(0, route.indexOf('|')); String dst = route.substring(route.lastIndexOf('|')+1); Endpoints endpoints = new EndpointsBuilder() .setSrc(new Ipv4Address(src)) .setDst(new Ipv4Address(dst)) .build(); ErrorCodeType errorCodeType = this.routeManager.removeRoute(endpoints); RemoveRouteOutputBuilder outputBuilder = new RemoveRouteOutputBuilder(); outputBuilder.setErrorCode(errorCodeType); return RpcResultBuilder.success(outputBuilder.build()).buildFuture(); } @Override public Future<RpcResult<SetupRouteOutput>> setupRoute(SetupRouteInput input) { if (null == input.getFlowLayer() || null == input.getEndpoints()) { SetupRouteOutputBuilder outputBuilder = new SetupRouteOutputBuilder(); outputBuilder.setErrorCode(ErrorCodeType.INVALIDINPUT); return RpcResultBuilder.success(outputBuilder.build()).buildFuture(); } Endpoints endpoints = input.getEndpoints(); Integer burstSize = input.getBurstSize(); Integer limitedRate = input.getLimitedRate(); FlowType flowLayer = input.getFlowLayer(); List<AltoSpceMetric> altoSpceMetrics = input.getObjectiveMetrics(); List<ConstraintMetric> constraintMetrics = compressConstraint(input.getConstraintMetric()); List<TpId> route; ErrorCodeType errorCode; route = this.routeManager.computeRoute(endpoints, altoSpceMetrics, constraintMetrics); if (route == null) { errorCode = ErrorCodeType.COMPUTINGROUTEERROR; SetupRouteOutput output = new SetupRouteOutputBuilder() .setErrorCode(errorCode).build(); return RpcResultBuilder.success(output).buildFuture(); } if (burstSize == null || limitedRate == null || burstSize.intValue() < 0 || limitedRate.intValue() < 0) { errorCode = this.routeManager.setupRoute(endpoints, route, flowLayer, -1, -1); } else { errorCode = this.routeManager.setupRoute(endpoints, route, flowLayer, limitedRate, burstSize); } if (errorCode != ErrorCodeType.OK) { SetupRouteOutput output = new SetupRouteOutputBuilder() .setErrorCode(errorCode).build(); return RpcResultBuilder.success(output).buildFuture(); } else { SetupRouteOutput output = new SetupRouteOutputBuilder() .setRoute(showRoute(endpoints, route)) .setErrorCode(errorCode) .build(); return RpcResultBuilder.success(output).buildFuture(); } } @Override public Future<RpcResult<GetRouteOutput>> getRoute(GetRouteInput input) { GetRouteOutputBuilder builder = new GetRouteOutputBuilder(); if (null == input || null == input.getEndpoints()) { builder.setErrorCode(ErrorCodeType.INVALIDINPUT); } else { builder.setErrorCode(ErrorCodeType.OK); List<TpId> route = this.routeManager.getRoute(input.getEndpoints()); if (null == route) { builder.setRoute("ROUTE_HAVE_NOT_BEEN_SET_UP"); } else { builder.setRoute(showRoute(input.getEndpoints(), route)); } } return RpcResultBuilder.success(builder.build()).buildFuture(); } }