From 41718fced10866805d5851e2dc71562d4a4f260e Mon Sep 17 00:00:00 2001 From: Brian O'Connor Date: Thu, 30 Oct 2014 16:57:21 -0700 Subject: [PATCH] Applied some fixes to Intents - Use classname instead of class in IntentId - Added hashcode and equals to LambdaResourceAllocation - Untrack resources in IntentManger during uninstall - Refactored common code in OpticalPathIntentInstaller - Copied SimpleLinkResourceStore to DistributedLinkResourceStore - Added a few unserializable files to KryoNamespaces Change-Id: Ic35d102244972d5cf0c64482fd99e8c9bb1293a6 --- .../org/onlab/onos/net/intent/Intent.java | 6 +- .../resource/LambdaResourceAllocation.java | 19 ++ .../onos/net/intent/impl/IntentManager.java | 2 + .../impl/OpticalPathIntentInstaller.java | 97 ++------ .../impl/DistributedLinkResourceStore.java | 232 ++++++++++++++++++ .../store/resource/impl/package-info.java | 4 + .../store/serializers/KryoNamespaces.java | 8 +- 7 files changed, 292 insertions(+), 76 deletions(-) create mode 100644 core/store/dist/src/main/java/org/onlab/onos/store/resource/impl/DistributedLinkResourceStore.java create mode 100644 core/store/dist/src/main/java/org/onlab/onos/store/resource/impl/package-info.java diff --git a/core/api/src/main/java/org/onlab/onos/net/intent/Intent.java b/core/api/src/main/java/org/onlab/onos/net/intent/Intent.java index 206552e8e2..885b8517a2 100644 --- a/core/api/src/main/java/org/onlab/onos/net/intent/Intent.java +++ b/core/api/src/main/java/org/onlab/onos/net/intent/Intent.java @@ -19,6 +19,7 @@ import org.onlab.onos.core.ApplicationId; import org.onlab.onos.net.NetworkResource; import org.onlab.onos.net.flow.BatchOperationTarget; +import java.util.Arrays; import java.util.Collection; import java.util.Objects; @@ -93,9 +94,10 @@ public abstract class Intent implements BatchOperationTarget { * @param fields intent fields * @return intent identifier */ - protected static IntentId id(Object... fields) { + protected static IntentId id(Class intentClass, Object... fields) { // FIXME: spread the bits across the full long spectrum - return IntentId.valueOf(Objects.hash(fields)); + return IntentId.valueOf(Objects.hash(intentClass.getName(), + Arrays.hashCode(fields))); } /** diff --git a/core/api/src/main/java/org/onlab/onos/net/resource/LambdaResourceAllocation.java b/core/api/src/main/java/org/onlab/onos/net/resource/LambdaResourceAllocation.java index 7499f6db85..1c81f1fe1e 100644 --- a/core/api/src/main/java/org/onlab/onos/net/resource/LambdaResourceAllocation.java +++ b/core/api/src/main/java/org/onlab/onos/net/resource/LambdaResourceAllocation.java @@ -15,6 +15,8 @@ */ package org.onlab.onos.net.resource; +import java.util.Objects; + /** * Representation of allocated lambda resource. */ @@ -45,4 +47,21 @@ public class LambdaResourceAllocation extends LambdaResourceRequest public Lambda lambda() { return lambda; } + + @Override + public int hashCode() { + return Objects.hash(lambda); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null || getClass() != obj.getClass()) { + return false; + } + final LambdaResourceAllocation other = (LambdaResourceAllocation) obj; + return Objects.equals(this.lambda, other.lambda); + } } diff --git a/core/net/src/main/java/org/onlab/onos/net/intent/impl/IntentManager.java b/core/net/src/main/java/org/onlab/onos/net/intent/impl/IntentManager.java index 7b1d7a92e2..31df87aa52 100644 --- a/core/net/src/main/java/org/onlab/onos/net/intent/impl/IntentManager.java +++ b/core/net/src/main/java/org/onlab/onos/net/intent/impl/IntentManager.java @@ -407,6 +407,8 @@ public class IntentManager List installables = store.getInstallableIntents(intent.id()); if (installables != null) { for (Intent installable : installables) { + trackerService.removeTrackedResources(intent.id(), + installable.resources()); List batches = getInstaller(installable).uninstall(installable); uninstallWork.addAll(batches); } diff --git a/core/net/src/main/java/org/onlab/onos/net/intent/impl/OpticalPathIntentInstaller.java b/core/net/src/main/java/org/onlab/onos/net/intent/impl/OpticalPathIntentInstaller.java index f0747ddd12..5faae4d26f 100644 --- a/core/net/src/main/java/org/onlab/onos/net/intent/impl/OpticalPathIntentInstaller.java +++ b/core/net/src/main/java/org/onlab/onos/net/intent/impl/OpticalPathIntentInstaller.java @@ -94,7 +94,26 @@ public class OpticalPathIntentInstaller implements IntentInstaller install(OpticalPathIntent intent) { LinkResourceAllocations allocations = assignWavelength(intent); + return generateRules(intent, allocations, FlowRuleOperation.ADD); + } + @Override + public List uninstall(OpticalPathIntent intent) { + LinkResourceAllocations allocations = resourceService.getAllocations(intent.id()); + return generateRules(intent, allocations, FlowRuleOperation.REMOVE); + } + + private LinkResourceAllocations assignWavelength(OpticalPathIntent intent) { + LinkResourceRequest.Builder request = DefaultLinkResourceRequest.builder(intent.id(), + intent.path().links()) + .addLambdaRequest(); + LinkResourceAllocations retLambda = resourceService.requestResources(request.build()); + return retLambda; + } + + private List generateRules(OpticalPathIntent intent, + LinkResourceAllocations allocations, + FlowRuleOperation operation) { TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder(); selectorBuilder.matchInport(intent.src().port()); @@ -128,7 +147,7 @@ public class OpticalPathIntentInstaller implements IntentInstaller links) { // TODO More wavelength assignment algorithm int wavenum = 0; @@ -194,64 +205,4 @@ public class OpticalPathIntentInstaller implements IntentInstaller uninstall(OpticalPathIntent intent) { - LinkResourceAllocations allocations = resourceService.getAllocations(intent.id()); - - TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder(); - selectorBuilder.matchInport(intent.src().port()); - - TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder(); - - List rules = Lists.newLinkedList(); - ConnectPoint prev = intent.src(); - - //TODO throw exception if the lambda was not retrieved successfully - for (Link link : intent.path().links()) { - Lambda la = null; - for (ResourceAllocation allocation : allocations.getResourceAllocation(link)) { - if (allocation.type() == ResourceType.LAMBDA) { - la = ((LambdaResourceAllocation) allocation).lambda(); - break; - } - } - - if (la == null) { - log.info("Lambda was not retrieved successfully"); - return null; - } - - treatmentBuilder.setOutput(link.src().port()); - treatmentBuilder.setLambda((short) la.toInt()); - - FlowRule rule = new DefaultFlowRule(prev.deviceId(), - selectorBuilder.build(), - treatmentBuilder.build(), - 100, - appId, - 100, - true); - rules.add(new FlowRuleBatchEntry(FlowRuleOperation.REMOVE, rule)); - - prev = link.dst(); - selectorBuilder.matchInport(link.dst().port()); - selectorBuilder.matchLambda((short) la.toInt()); - } - - // build the last T port rule - TrafficTreatment treatmentLast = builder() - .setOutput(intent.dst().port()).build(); - FlowRule rule = new DefaultFlowRule(intent.dst().deviceId(), - selectorBuilder.build(), - treatmentLast, - 100, - appId, - 100, - true); - rules.add(new FlowRuleBatchEntry(FlowRuleOperation.REMOVE, rule)); - - return Lists.newArrayList(new FlowRuleBatchOperation(rules)); - } - } diff --git a/core/store/dist/src/main/java/org/onlab/onos/store/resource/impl/DistributedLinkResourceStore.java b/core/store/dist/src/main/java/org/onlab/onos/store/resource/impl/DistributedLinkResourceStore.java new file mode 100644 index 0000000000..41172cdc45 --- /dev/null +++ b/core/store/dist/src/main/java/org/onlab/onos/store/resource/impl/DistributedLinkResourceStore.java @@ -0,0 +1,232 @@ +/* + * Copyright 2014 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.onlab.onos.store.resource.impl; + +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.onos.net.Link; +import org.onlab.onos.net.intent.IntentId; +import org.onlab.onos.net.resource.Bandwidth; +import org.onlab.onos.net.resource.BandwidthResourceAllocation; +import org.onlab.onos.net.resource.Lambda; +import org.onlab.onos.net.resource.LambdaResourceAllocation; +import org.onlab.onos.net.resource.LinkResourceAllocations; +import org.onlab.onos.net.resource.LinkResourceStore; +import org.onlab.onos.net.resource.ResourceAllocation; +import org.onlab.onos.net.resource.ResourceType; +import org.slf4j.Logger; + +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; +import static org.slf4j.LoggerFactory.getLogger; + +/** + * Manages link resources using trivial in-memory structures implementation. + */ +@Component(immediate = true) +@Service +public class DistributedLinkResourceStore implements LinkResourceStore { + private final Logger log = getLogger(getClass()); + private Map linkResourceAllocationsMap; + private Map> allocatedResources; + private Map> freeResources; + + @Activate + public void activate() { + linkResourceAllocationsMap = new HashMap<>(); + allocatedResources = new HashMap<>(); + freeResources = new HashMap<>(); + + log.info("Started"); + } + + @Deactivate + public void deactivate() { + log.info("Stopped"); + } + + /** + * Returns free resources for a given link obtaining from topology + * information. + * + * @param link the target link + * @return free resources + */ + private Set readOriginalFreeResources(Link link) { + // TODO read capacity and lambda resources from topology + Set allocations = new HashSet<>(); + for (int i = 1; i <= 100; i++) { + allocations.add(new LambdaResourceAllocation(Lambda.valueOf(i))); + } + allocations.add(new BandwidthResourceAllocation(Bandwidth.valueOf(1000000))); + return allocations; + } + + /** + * Finds and returns {@link org.onlab.onos.net.resource.BandwidthResourceAllocation} object from a given + * set. + * + * @param freeRes a set of ResourceAllocation object. + * @return {@link org.onlab.onos.net.resource.BandwidthResourceAllocation} object if found, otherwise + * {@link org.onlab.onos.net.resource.BandwidthResourceAllocation} object with 0 bandwidth + * + */ + private BandwidthResourceAllocation getBandwidth(Set freeRes) { + for (ResourceAllocation res : freeRes) { + if (res.type() == ResourceType.BANDWIDTH) { + return (BandwidthResourceAllocation) res; + } + } + return new BandwidthResourceAllocation(Bandwidth.valueOf(0)); + } + + /** + * Subtracts given resources from free resources for given link. + * + * @param link the target link + * @param allocations the resources to be subtracted + */ + private void subtractFreeResources(Link link, LinkResourceAllocations allocations) { + // TODO Use lock or version for updating freeResources. + checkNotNull(link); + Set freeRes = new HashSet<>(getFreeResources(link)); + Set subRes = allocations.getResourceAllocation(link); + for (ResourceAllocation res : subRes) { + switch (res.type()) { + case BANDWIDTH: + BandwidthResourceAllocation ba = getBandwidth(freeRes); + double requestedBandwidth = + ((BandwidthResourceAllocation) res).bandwidth().toDouble(); + double newBandwidth = ba.bandwidth().toDouble() - requestedBandwidth; + checkState(newBandwidth >= 0.0); + freeRes.remove(ba); + freeRes.add(new BandwidthResourceAllocation( + Bandwidth.valueOf(newBandwidth))); + break; + case LAMBDA: + checkState(freeRes.remove(res)); + break; + default: + break; + } + } + freeResources.put(link, freeRes); + + } + + /** + * Adds given resources to free resources for given link. + * + * @param link the target link + * @param allocations the resources to be added + */ + private void addFreeResources(Link link, LinkResourceAllocations allocations) { + // TODO Use lock or version for updating freeResources. + Set freeRes = new HashSet<>(getFreeResources(link)); + Set addRes = allocations.getResourceAllocation(link); + for (ResourceAllocation res : addRes) { + switch (res.type()) { + case BANDWIDTH: + BandwidthResourceAllocation ba = getBandwidth(freeRes); + double requestedBandwidth = + ((BandwidthResourceAllocation) res).bandwidth().toDouble(); + double newBandwidth = ba.bandwidth().toDouble() + requestedBandwidth; + freeRes.remove(ba); + freeRes.add(new BandwidthResourceAllocation( + Bandwidth.valueOf(newBandwidth))); + break; + case LAMBDA: + checkState(freeRes.add(res)); + break; + default: + break; + } + } + freeResources.put(link, freeRes); + } + + @Override + public Set getFreeResources(Link link) { + checkNotNull(link); + Set freeRes = freeResources.get(link); + if (freeRes == null) { + freeRes = readOriginalFreeResources(link); + } + + return freeRes; + } + + @Override + public void allocateResources(LinkResourceAllocations allocations) { + checkNotNull(allocations); + linkResourceAllocationsMap.put(allocations.intendId(), allocations); + for (Link link : allocations.links()) { + subtractFreeResources(link, allocations); + Set linkAllocs = allocatedResources.get(link); + if (linkAllocs == null) { + linkAllocs = new HashSet<>(); + } + linkAllocs.add(allocations); + allocatedResources.put(link, linkAllocs); + } + } + + @Override + public void releaseResources(LinkResourceAllocations allocations) { + checkNotNull(allocations); + linkResourceAllocationsMap.remove(allocations); + for (Link link : allocations.links()) { + addFreeResources(link, allocations); + Set linkAllocs = allocatedResources.get(link); + if (linkAllocs == null) { + log.error("Missing resource allocation."); + } else { + linkAllocs.remove(allocations); + } + allocatedResources.put(link, linkAllocs); + } + } + + @Override + public LinkResourceAllocations getAllocations(IntentId intentId) { + checkNotNull(intentId); + return linkResourceAllocationsMap.get(intentId); + } + + @Override + public Iterable getAllocations(Link link) { + checkNotNull(link); + Set result = allocatedResources.get(link); + if (result == null) { + result = Collections.emptySet(); + } + return Collections.unmodifiableSet(result); + } + + @Override + public Iterable getAllocations() { + return Collections.unmodifiableCollection(linkResourceAllocationsMap.values()); + } + +} diff --git a/core/store/dist/src/main/java/org/onlab/onos/store/resource/impl/package-info.java b/core/store/dist/src/main/java/org/onlab/onos/store/resource/impl/package-info.java new file mode 100644 index 0000000000..1e34e3789a --- /dev/null +++ b/core/store/dist/src/main/java/org/onlab/onos/store/resource/impl/package-info.java @@ -0,0 +1,4 @@ +/** + * Implementation of distributed packet store. + */ +package org.onlab.onos.store.resource.impl; \ No newline at end of file diff --git a/core/store/serializers/src/main/java/org/onlab/onos/store/serializers/KryoNamespaces.java b/core/store/serializers/src/main/java/org/onlab/onos/store/serializers/KryoNamespaces.java index b91e8fcd5e..2a4c10c89a 100644 --- a/core/store/serializers/src/main/java/org/onlab/onos/store/serializers/KryoNamespaces.java +++ b/core/store/serializers/src/main/java/org/onlab/onos/store/serializers/KryoNamespaces.java @@ -71,11 +71,14 @@ import org.onlab.onos.net.intent.IntentId; import org.onlab.onos.net.intent.IntentState; import org.onlab.onos.net.intent.LinkCollectionIntent; import org.onlab.onos.net.intent.MultiPointToSinglePointIntent; +import org.onlab.onos.net.intent.OpticalConnectivityIntent; +import org.onlab.onos.net.intent.OpticalPathIntent; import org.onlab.onos.net.intent.PathIntent; import org.onlab.onos.net.intent.PointToPointIntent; import org.onlab.onos.net.link.DefaultLinkDescription; import org.onlab.onos.net.packet.DefaultOutboundPacket; import org.onlab.onos.net.provider.ProviderId; +import org.onlab.onos.net.resource.LinkResourceRequest; import org.onlab.onos.store.Timestamp; import org.onlab.packet.ChassisId; import org.onlab.packet.IpAddress; @@ -182,7 +185,10 @@ public final class KryoNamespaces { HostToHostIntent.class, PointToPointIntent.class, MultiPointToSinglePointIntent.class, - LinkCollectionIntent.class + LinkCollectionIntent.class, + OpticalConnectivityIntent.class, + OpticalPathIntent.class, + LinkResourceRequest.class ) .register(DefaultApplicationId.class, new DefaultApplicationIdSerializer()) .register(URI.class, new URISerializer())