Merge "Prototype bandwidth reservation"
diff --git a/apps/calendar/src/main/java/org/onlab/onos/calendar/BandwidthCalendarResource.java b/apps/calendar/src/main/java/org/onlab/onos/calendar/BandwidthCalendarResource.java
index c534371..cd8cc5c 100644
--- a/apps/calendar/src/main/java/org/onlab/onos/calendar/BandwidthCalendarResource.java
+++ b/apps/calendar/src/main/java/org/onlab/onos/calendar/BandwidthCalendarResource.java
@@ -15,18 +15,29 @@
*/
package org.onlab.onos.calendar;
-import org.onlab.onos.net.ConnectPoint;
-import org.onlab.onos.net.DeviceId;
-import org.onlab.onos.net.intent.IntentService;
-import org.onlab.rest.BaseResource;
+import java.net.URI;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.Response;
-import java.net.URI;
+
+import org.onlab.onos.core.ApplicationId;
+import org.onlab.onos.core.CoreService;
+import org.onlab.onos.net.ConnectPoint;
+import org.onlab.onos.net.DeviceId;
+import org.onlab.onos.net.flow.DefaultTrafficSelector;
+import org.onlab.onos.net.flow.TrafficSelector;
+import org.onlab.onos.net.flow.TrafficTreatment;
+import org.onlab.onos.net.intent.Intent;
+import org.onlab.onos.net.intent.IntentService;
+import org.onlab.onos.net.intent.PointToPointIntentWithBandwidthConstraint;
+import org.onlab.onos.net.resource.BandwidthResourceRequest;
+import org.onlab.packet.Ethernet;
+import org.onlab.rest.BaseResource;
import static org.onlab.onos.net.PortNumber.portNumber;
+import static org.onlab.onos.net.flow.DefaultTrafficTreatment.builder;
/**
* Web resource for triggering calendared intents.
@@ -47,12 +58,33 @@
ConnectPoint srcPoint = new ConnectPoint(deviceId(src), portNumber(srcPort));
ConnectPoint dstPoint = new ConnectPoint(deviceId(dst), portNumber(dstPort));
+ TrafficSelector selector = buildTrafficSelector();
+ TrafficTreatment treatment = builder().build();
+
+ Intent intent = new PointToPointIntentWithBandwidthConstraint(
+ appId(), selector, treatment,
+ srcPoint, dstPoint, new BandwidthResourceRequest(Double.parseDouble(bandwidth)));
+ service.submit(intent);
+
return Response.ok("Yo! We got src=" + srcPoint + "; dst=" + dstPoint +
"; bw=" + bandwidth + "; intent service " + service).build();
}
+ private TrafficSelector buildTrafficSelector() {
+ TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder();
+ Short ethType = Ethernet.TYPE_IPV4;
+
+ selectorBuilder.matchEthType(ethType);
+
+ return selectorBuilder.build();
+ }
+
private DeviceId deviceId(String dpid) {
return DeviceId.deviceId(URI.create("of:" + dpid));
}
+ protected ApplicationId appId() {
+ return get(CoreService.class).registerApplication("org.onlab.onos.calendar");
+ }
+
}
diff --git a/cli/src/main/java/org/onlab/onos/cli/net/AddPointToPointIntentWithBandwidthConstraintCommand.java b/cli/src/main/java/org/onlab/onos/cli/net/AddPointToPointIntentWithBandwidthConstraintCommand.java
new file mode 100644
index 0000000..1207f1a
--- /dev/null
+++ b/cli/src/main/java/org/onlab/onos/cli/net/AddPointToPointIntentWithBandwidthConstraintCommand.java
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.cli.net;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onlab.onos.net.ConnectPoint;
+import org.onlab.onos.net.DeviceId;
+import org.onlab.onos.net.PortNumber;
+import org.onlab.onos.net.flow.TrafficSelector;
+import org.onlab.onos.net.flow.TrafficTreatment;
+import org.onlab.onos.net.intent.Intent;
+import org.onlab.onos.net.intent.IntentService;
+import org.onlab.onos.net.intent.PointToPointIntentWithBandwidthConstraint;
+import org.onlab.onos.net.resource.BandwidthResourceRequest;
+
+import static org.onlab.onos.net.DeviceId.deviceId;
+import static org.onlab.onos.net.PortNumber.portNumber;
+import static org.onlab.onos.net.flow.DefaultTrafficTreatment.builder;
+
+/**
+ * Installs point-to-point connectivity intents.
+ */
+@Command(scope = "onos", name = "add-point-intent-bw",
+ description = "Installs point-to-point connectivity intent with bandwidth constraint")
+public class AddPointToPointIntentWithBandwidthConstraintCommand extends ConnectivityIntentCommand {
+
+ @Argument(index = 0, name = "ingressDevice",
+ description = "Ingress Device/Port Description",
+ required = true, multiValued = false)
+ String ingressDeviceString = null;
+
+ @Argument(index = 1, name = "egressDevice",
+ description = "Egress Device/Port Description",
+ required = true, multiValued = false)
+ String egressDeviceString = null;
+
+ @Argument(index = 2, name = "bandwidth",
+ description = "Bandwidth",
+ required = true, multiValued = false)
+ String bandwidthString = null;
+
+ @Override
+ protected void execute() {
+ IntentService service = get(IntentService.class);
+
+ DeviceId ingressDeviceId = deviceId(getDeviceId(ingressDeviceString));
+ PortNumber ingressPortNumber = portNumber(getPortNumber(ingressDeviceString));
+ ConnectPoint ingress = new ConnectPoint(ingressDeviceId, ingressPortNumber);
+
+ DeviceId egressDeviceId = deviceId(getDeviceId(egressDeviceString));
+ PortNumber egressPortNumber = portNumber(getPortNumber(egressDeviceString));
+ ConnectPoint egress = new ConnectPoint(egressDeviceId, egressPortNumber);
+
+ long bandwidth = Long.parseLong(bandwidthString);
+
+ TrafficSelector selector = buildTrafficSelector();
+ TrafficTreatment treatment = builder().build();
+
+ Intent intent = new PointToPointIntentWithBandwidthConstraint(
+ appId(), selector, treatment,
+ ingress, egress, new BandwidthResourceRequest(bandwidth));
+ service.submit(intent);
+ }
+
+ /**
+ * Extracts the port number portion of the ConnectPoint.
+ *
+ * @param deviceString string representing the device/port
+ * @return port number as a string, empty string if the port is not found
+ */
+ private String getPortNumber(String deviceString) {
+ int slash = deviceString.indexOf('/');
+ if (slash <= 0) {
+ return "";
+ }
+ return deviceString.substring(slash + 1, deviceString.length());
+ }
+
+ /**
+ * Extracts the device ID portion of the ConnectPoint.
+ *
+ * @param deviceString string representing the device/port
+ * @return device ID string
+ */
+ private String getDeviceId(String deviceString) {
+ int slash = deviceString.indexOf('/');
+ if (slash <= 0) {
+ return "";
+ }
+ return deviceString.substring(0, slash);
+ }
+}
diff --git a/cli/src/main/java/org/onlab/onos/cli/net/ConnectivityIntentCommand.java b/cli/src/main/java/org/onlab/onos/cli/net/ConnectivityIntentCommand.java
index b9b071f..b61a646 100644
--- a/cli/src/main/java/org/onlab/onos/cli/net/ConnectivityIntentCommand.java
+++ b/cli/src/main/java/org/onlab/onos/cli/net/ConnectivityIntentCommand.java
@@ -47,8 +47,8 @@
*/
protected TrafficSelector buildTrafficSelector() {
TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder();
-
Short ethType = Ethernet.TYPE_IPV4;
+
if (!Strings.isNullOrEmpty(ethTypeString)) {
EthType ethTypeParameter = EthType.valueOf(ethTypeString);
ethType = ethTypeParameter.value();
diff --git a/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml b/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml
index 418ee26..f8b6a13 100644
--- a/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml
+++ b/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml
@@ -116,6 +116,17 @@
</optional-completers>
</command>
<command>
+ <action class="org.onlab.onos.cli.net.AddPointToPointIntentWithBandwidthConstraintCommand"/>
+ <completers>
+ <ref component-id="connectPointCompleter"/>
+ <ref component-id="connectPointCompleter"/>
+ <null/>
+ </completers>
+ <optional-completers>
+ <entry key="-t" value-ref="ethTypeCompleter"/>
+ </optional-completers>
+ </command>
+ <command>
<action class="org.onlab.onos.cli.net.AddOpticalIntentCommand"/>
<completers>
<ref component-id="connectPointCompleter"/>
diff --git a/core/api/src/main/java/org/onlab/onos/net/intent/PathIntent.java b/core/api/src/main/java/org/onlab/onos/net/intent/PathIntent.java
index 721a8fd..0789db0 100644
--- a/core/api/src/main/java/org/onlab/onos/net/intent/PathIntent.java
+++ b/core/api/src/main/java/org/onlab/onos/net/intent/PathIntent.java
@@ -20,6 +20,7 @@
import org.onlab.onos.net.Path;
import org.onlab.onos.net.flow.TrafficSelector;
import org.onlab.onos.net.flow.TrafficTreatment;
+import org.onlab.onos.net.resource.LinkResourceRequest;
/**
* Abstraction of explicitly path specified connectivity intent.
@@ -27,6 +28,7 @@
public class PathIntent extends ConnectivityIntent {
private final Path path;
+ private final LinkResourceRequest[] resourceRequests;
/**
* Creates a new point-to-point intent with the supplied ingress/egress
@@ -39,10 +41,11 @@
* @throws NullPointerException {@code path} is null
*/
public PathIntent(ApplicationId appId, TrafficSelector selector,
- TrafficTreatment treatment, Path path) {
+ TrafficTreatment treatment, Path path, LinkResourceRequest[] resourceRequests) {
super(id(PathIntent.class, selector, treatment, path), appId,
resources(path.links()), selector, treatment);
this.path = path;
+ this.resourceRequests = resourceRequests;
}
/**
@@ -51,6 +54,7 @@
protected PathIntent() {
super();
this.path = null;
+ this.resourceRequests = new LinkResourceRequest[0];
}
/**
@@ -67,6 +71,10 @@
return true;
}
+ public LinkResourceRequest[] resourceRequests() {
+ return resourceRequests;
+ }
+
@Override
public String toString() {
return MoreObjects.toStringHelper(getClass())
diff --git a/core/api/src/main/java/org/onlab/onos/net/intent/PointToPointIntentWithBandwidthConstraint.java b/core/api/src/main/java/org/onlab/onos/net/intent/PointToPointIntentWithBandwidthConstraint.java
new file mode 100644
index 0000000..d5c4d57
--- /dev/null
+++ b/core/api/src/main/java/org/onlab/onos/net/intent/PointToPointIntentWithBandwidthConstraint.java
@@ -0,0 +1,110 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.net.intent;
+
+import org.onlab.onos.core.ApplicationId;
+import org.onlab.onos.net.ConnectPoint;
+import org.onlab.onos.net.flow.TrafficSelector;
+import org.onlab.onos.net.flow.TrafficTreatment;
+import org.onlab.onos.net.resource.BandwidthResourceRequest;
+
+import com.google.common.base.MoreObjects;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Abstraction of point-to-point connectivity.
+ */
+public class PointToPointIntentWithBandwidthConstraint extends ConnectivityIntent {
+
+ private final ConnectPoint ingressPoint;
+ private final ConnectPoint egressPoint;
+ private final BandwidthResourceRequest bandwidthResourceRequest;
+
+ /**
+ * Creates a new point-to-point intent with the supplied ingress/egress
+ * ports.
+ *
+ * @param appId application identifier
+ * @param selector traffic selector
+ * @param treatment treatment
+ * @param ingressPoint ingress port
+ * @param egressPoint egress port
+ * @throws NullPointerException if {@code ingressPoint} or {@code egressPoints} is null.
+ */
+ public PointToPointIntentWithBandwidthConstraint(ApplicationId appId, TrafficSelector selector,
+ TrafficTreatment treatment,
+ ConnectPoint ingressPoint,
+ ConnectPoint egressPoint,
+ BandwidthResourceRequest bandwidthResourceRequest) {
+ super(id(PointToPointIntentWithBandwidthConstraint.class, selector,
+ treatment, ingressPoint, egressPoint, bandwidthResourceRequest.bandwidth()),
+ appId, null, selector, treatment);
+ this.ingressPoint = checkNotNull(ingressPoint);
+ this.egressPoint = checkNotNull(egressPoint);
+ this.bandwidthResourceRequest = bandwidthResourceRequest;
+ }
+
+ /**
+ * Constructor for serializer.
+ */
+ protected PointToPointIntentWithBandwidthConstraint() {
+ super();
+ this.ingressPoint = null;
+ this.egressPoint = null;
+ bandwidthResourceRequest = new BandwidthResourceRequest(0.0);
+ }
+
+ /**
+ * Returns the port on which the ingress traffic should be connected to
+ * the egress.
+ *
+ * @return ingress port
+ */
+ public ConnectPoint ingressPoint() {
+ return ingressPoint;
+ }
+
+ /**
+ * Returns the port on which the traffic should egress.
+ *
+ * @return egress port
+ */
+ public ConnectPoint egressPoint() {
+ return egressPoint;
+ }
+
+ public BandwidthResourceRequest bandwidthRequest() {
+ return this.bandwidthResourceRequest;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass())
+ .add("id", id())
+ .add("appId", appId())
+ .add("selector", selector())
+ .add("treatment", treatment())
+ .add("ingress", ingressPoint)
+ .add("egress", egressPoint)
+ .add("bandwidth", bandwidthResourceRequest.bandwidth().toString())
+ .toString();
+ }
+
+}
diff --git a/core/api/src/test/java/org/onlab/onos/net/intent/PathIntentTest.java b/core/api/src/test/java/org/onlab/onos/net/intent/PathIntentTest.java
index 21efe49..02ca0f5 100644
--- a/core/api/src/test/java/org/onlab/onos/net/intent/PathIntentTest.java
+++ b/core/api/src/test/java/org/onlab/onos/net/intent/PathIntentTest.java
@@ -15,11 +15,12 @@
*/
package org.onlab.onos.net.intent;
-import static org.junit.Assert.assertEquals;
-
import org.junit.Test;
import org.onlab.onos.net.NetTestTools;
import org.onlab.onos.net.Path;
+import org.onlab.onos.net.resource.LinkResourceRequest;
+
+import static org.junit.Assert.assertEquals;
public class PathIntentTest extends ConnectivityIntentTest {
// 111:11 --> 222:22
@@ -39,11 +40,11 @@
@Override
protected PathIntent createOne() {
- return new PathIntent(APPID, MATCH, NOP, PATH1);
+ return new PathIntent(APPID, MATCH, NOP, PATH1, new LinkResourceRequest[0]);
}
@Override
protected PathIntent createAnother() {
- return new PathIntent(APPID, MATCH, NOP, PATH2);
+ return new PathIntent(APPID, MATCH, NOP, PATH2, new LinkResourceRequest[0]);
}
}
diff --git a/core/net/src/main/java/org/onlab/onos/net/intent/impl/HostToHostIntentCompiler.java b/core/net/src/main/java/org/onlab/onos/net/intent/impl/HostToHostIntentCompiler.java
index e045cec..37cf84b 100644
--- a/core/net/src/main/java/org/onlab/onos/net/intent/impl/HostToHostIntentCompiler.java
+++ b/core/net/src/main/java/org/onlab/onos/net/intent/impl/HostToHostIntentCompiler.java
@@ -15,6 +15,10 @@
*/
package org.onlab.onos.net.intent.impl;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Set;
+
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
@@ -32,13 +36,10 @@
import org.onlab.onos.net.intent.IntentExtensionService;
import org.onlab.onos.net.intent.PathIntent;
import org.onlab.onos.net.topology.LinkWeight;
+import org.onlab.onos.net.resource.LinkResourceRequest;
import org.onlab.onos.net.topology.PathService;
import org.onlab.onos.net.topology.TopologyEdge;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Set;
-
import static org.onlab.onos.net.flow.DefaultTrafficSelector.builder;
/**
@@ -85,7 +86,7 @@
TrafficSelector selector = builder(intent.selector())
.matchEthSrc(src.mac()).matchEthDst(dst.mac()).build();
return new PathIntent(intent.appId(), selector, intent.treatment(),
- path);
+ path, new LinkResourceRequest[0]);
}
private Path getPath(HostId one, HostId two) {
diff --git a/core/net/src/main/java/org/onlab/onos/net/intent/impl/PathIntentInstaller.java b/core/net/src/main/java/org/onlab/onos/net/intent/impl/PathIntentInstaller.java
index d0666cc..ad8ea08 100644
--- a/core/net/src/main/java/org/onlab/onos/net/intent/impl/PathIntentInstaller.java
+++ b/core/net/src/main/java/org/onlab/onos/net/intent/impl/PathIntentInstaller.java
@@ -15,9 +15,6 @@
*/
package org.onlab.onos.net.intent.impl;
-import static org.onlab.onos.net.flow.DefaultTrafficTreatment.builder;
-import static org.slf4j.LoggerFactory.getLogger;
-
import java.util.Iterator;
import java.util.List;
@@ -41,10 +38,15 @@
import org.onlab.onos.net.intent.IntentExtensionService;
import org.onlab.onos.net.intent.IntentInstaller;
import org.onlab.onos.net.intent.PathIntent;
+import org.onlab.onos.net.resource.LinkResourceAllocations;
+import org.onlab.onos.net.resource.LinkResourceService;
import org.slf4j.Logger;
import com.google.common.collect.Lists;
+import static org.onlab.onos.net.flow.DefaultTrafficTreatment.builder;
+import static org.slf4j.LoggerFactory.getLogger;
+
/**
* Installer for {@link PathIntent packet path connectivity intents}.
*/
@@ -59,6 +61,9 @@
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected CoreService coreService;
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected LinkResourceService resourceService;
+
private ApplicationId appId;
@Activate
@@ -74,6 +79,11 @@
@Override
public List<FlowRuleBatchOperation> install(PathIntent intent) {
+ LinkResourceAllocations allocations = allocateBandwidth(intent);
+ if (allocations == null) {
+ log.debug("Insufficient bandwidth available to install path intent {}", intent);
+ return null;
+ }
TrafficSelector.Builder builder =
DefaultTrafficSelector.builder(intent.selector());
Iterator<Link> links = intent.path().links().iterator();
@@ -117,6 +127,10 @@
return Lists.newArrayList(new FlowRuleBatchOperation(rules));
}
+ private LinkResourceAllocations allocateBandwidth(PathIntent intent) {
+ return resourceService.requestResources(intent.resourceRequests()[0]);
+ }
+
// TODO refactor below this line... ----------------------------
/**
diff --git a/core/net/src/main/java/org/onlab/onos/net/intent/impl/PointToPointIntentCompiler.java b/core/net/src/main/java/org/onlab/onos/net/intent/impl/PointToPointIntentCompiler.java
index 5c79d5c..893b7ea 100644
--- a/core/net/src/main/java/org/onlab/onos/net/intent/impl/PointToPointIntentCompiler.java
+++ b/core/net/src/main/java/org/onlab/onos/net/intent/impl/PointToPointIntentCompiler.java
@@ -15,6 +15,10 @@
*/
package org.onlab.onos.net.intent.impl;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
@@ -31,15 +35,12 @@
import org.onlab.onos.net.intent.PathIntent;
import org.onlab.onos.net.intent.PointToPointIntent;
import org.onlab.onos.net.provider.ProviderId;
+import org.onlab.onos.net.resource.LinkResourceRequest;
import org.onlab.onos.net.topology.LinkWeight;
import org.onlab.onos.net.topology.Topology;
import org.onlab.onos.net.topology.TopologyEdge;
import org.onlab.onos.net.topology.TopologyService;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Set;
-
import static java.util.Arrays.asList;
/**
@@ -76,7 +77,7 @@
links.add(DefaultEdgeLink.createEdgeLink(intent.egressPoint(), false));
return asList(createPathIntent(new DefaultPath(PID, links, path.cost() + 2,
- path.annotations()), intent));
+ path.annotations()), intent));
}
/**
@@ -89,7 +90,8 @@
private Intent createPathIntent(Path path,
PointToPointIntent intent) {
return new PathIntent(intent.appId(),
- intent.selector(), intent.treatment(), path);
+ intent.selector(), intent.treatment(), path,
+ new LinkResourceRequest[0]);
}
/**
diff --git a/core/net/src/main/java/org/onlab/onos/net/intent/impl/PointToPointIntentWithBandwidthConstraintCompiler.java b/core/net/src/main/java/org/onlab/onos/net/intent/impl/PointToPointIntentWithBandwidthConstraintCompiler.java
new file mode 100644
index 0000000..a192a9f
--- /dev/null
+++ b/core/net/src/main/java/org/onlab/onos/net/intent/impl/PointToPointIntentWithBandwidthConstraintCompiler.java
@@ -0,0 +1,146 @@
+package org.onlab.onos.net.intent.impl;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Set;
+
+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.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.onlab.onos.net.ConnectPoint;
+import org.onlab.onos.net.DefaultEdgeLink;
+import org.onlab.onos.net.DefaultPath;
+import org.onlab.onos.net.Link;
+import org.onlab.onos.net.Path;
+import org.onlab.onos.net.intent.Intent;
+import org.onlab.onos.net.intent.IntentCompiler;
+import org.onlab.onos.net.intent.IntentExtensionService;
+import org.onlab.onos.net.intent.PathIntent;
+import org.onlab.onos.net.intent.PointToPointIntent;
+import org.onlab.onos.net.intent.PointToPointIntentWithBandwidthConstraint;
+import org.onlab.onos.net.provider.ProviderId;
+import org.onlab.onos.net.resource.BandwidthResourceRequest;
+import org.onlab.onos.net.resource.DefaultLinkResourceRequest;
+import org.onlab.onos.net.resource.LinkResourceRequest;
+import org.onlab.onos.net.resource.LinkResourceService;
+import org.onlab.onos.net.resource.ResourceRequest;
+import org.onlab.onos.net.resource.ResourceType;
+import org.onlab.onos.net.topology.LinkWeight;
+import org.onlab.onos.net.topology.Topology;
+import org.onlab.onos.net.topology.TopologyEdge;
+import org.onlab.onos.net.topology.TopologyService;
+
+/**
+ * A intent compiler for {@link org.onlab.onos.net.intent.HostToHostIntent}.
+ */
+@Component(immediate = true)
+public class PointToPointIntentWithBandwidthConstraintCompiler
+ implements IntentCompiler<PointToPointIntentWithBandwidthConstraint> {
+
+ private static final ProviderId PID = new ProviderId("core", "org.onlab.onos.core", true);
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected IntentExtensionService intentManager;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected TopologyService topologyService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected LinkResourceService resourceService;
+
+ @Activate
+ public void activate() {
+ intentManager.registerCompiler(PointToPointIntentWithBandwidthConstraint.class, this);
+ }
+
+ @Deactivate
+ public void deactivate() {
+ intentManager.unregisterCompiler(PointToPointIntent.class);
+ }
+
+ @Override
+ public List<Intent> compile(PointToPointIntentWithBandwidthConstraint intent) {
+ Path path = getPath(intent.ingressPoint(), intent.egressPoint(), intent.bandwidthRequest());
+
+ List<Link> links = new ArrayList<>();
+ links.add(DefaultEdgeLink.createEdgeLink(intent.ingressPoint(), true));
+ links.addAll(path.links());
+ links.add(DefaultEdgeLink.createEdgeLink(intent.egressPoint(), false));
+
+ return Arrays.asList(createPathIntent(new DefaultPath(PID, links, path.cost() + 2,
+ path.annotations()),
+ intent));
+ }
+
+ /**
+ * Creates a path intent from the specified path and original
+ * connectivity intent.
+ *
+ * @param path path to create an intent for
+ * @param intent original intent
+ */
+ private Intent createPathIntent(Path path,
+ PointToPointIntentWithBandwidthConstraint intent) {
+ LinkResourceRequest.Builder request = DefaultLinkResourceRequest.builder(intent.id(),
+ path.links())
+ // TODO - this seems awkward, maybe allow directly attaching a BandwidthRequest
+ .addBandwidthRequest(intent.bandwidthRequest().bandwidth().toDouble());
+ LinkResourceRequest bandwidthRequest = request.build();
+ LinkResourceRequest[] bandwidthRequests = {bandwidthRequest};
+ return new PathIntent(intent.appId(),
+ intent.selector(), intent.treatment(), path,
+ bandwidthRequests);
+ }
+
+ /**
+ * Computes a path between two ConnectPoints.
+ *
+ * @param one start of the path
+ * @param two end of the path
+ * @return Path between the two
+ * @throws org.onlab.onos.net.intent.impl.PathNotFoundException if a path cannot be found
+ */
+ private Path getPath(ConnectPoint one, ConnectPoint two, final BandwidthResourceRequest bandwidthRequest) {
+ Topology topology = topologyService.currentTopology();
+ LinkWeight weight = new LinkWeight() {
+ @Override
+ public double weight(TopologyEdge edge) {
+ if (bandwidthRequest != null) {
+ double allocatedBandwidth = 0.0;
+ Iterable<ResourceRequest> availableResources = resourceService.getAvailableResources(edge.link());
+ for (ResourceRequest availableResource : availableResources) {
+ if (availableResource.type() == ResourceType.BANDWIDTH) {
+ BandwidthResourceRequest bandwidthRequest = (BandwidthResourceRequest) availableResource;
+ allocatedBandwidth += bandwidthRequest.bandwidth().toDouble();
+ }
+ }
+
+ // TODO this needs to be discovered from switch/ports somehow
+ double maxBandwidth = 1000;
+
+ double availableBandwidth = maxBandwidth - allocatedBandwidth;
+ if (availableBandwidth >= bandwidthRequest.bandwidth().toDouble()) {
+ return 1;
+ } else {
+ return -1;
+ }
+ } else {
+ return 1;
+ }
+ }
+ };
+
+ Set<Path> paths = topologyService.getPaths(topology,
+ one.deviceId(),
+ two.deviceId(),
+ weight);
+
+ if (paths.isEmpty()) {
+ throw new PathNotFoundException("No packet path from " + one + " to " + two);
+ }
+ // TODO: let's be more intelligent about this eventually
+ return paths.iterator().next();
+ }
+}
diff --git a/core/net/src/main/java/org/onlab/onos/net/resource/impl/LinkResourceManager.java b/core/net/src/main/java/org/onlab/onos/net/resource/impl/LinkResourceManager.java
index bdd0761..4f84b82 100644
--- a/core/net/src/main/java/org/onlab/onos/net/resource/impl/LinkResourceManager.java
+++ b/core/net/src/main/java/org/onlab/onos/net/resource/impl/LinkResourceManager.java
@@ -17,6 +17,7 @@
import static org.slf4j.LoggerFactory.getLogger;
+import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
@@ -50,6 +51,8 @@
private final Logger log = getLogger(getClass());
+ LinkResourceAllocations savedAllocations;
+
@Activate
public void activate() {
log.info("Started");
@@ -64,6 +67,8 @@
return Sets.newHashSet(Lambda.valueOf(7));
}
+ double usedBandwidth = 0.0;
+
@Override
public LinkResourceAllocations requestResources(LinkResourceRequest req) {
// TODO implement it using a resource data store.
@@ -75,6 +80,7 @@
log.info("requestResources() always returns requested bandwidth");
BandwidthResourceRequest br = (BandwidthResourceRequest) r;
alloc = new BandwidthResourceAllocation(br.bandwidth());
+ usedBandwidth += br.bandwidth().toDouble();
break;
case LAMBDA:
log.info("requestResources() always returns lambda 7");
@@ -92,7 +98,8 @@
for (Link link : req.links()) {
allocations.put(link, Sets.newHashSet(alloc));
}
- return new DefaultLinkResourceAllocations(req, allocations);
+ savedAllocations = new DefaultLinkResourceAllocations(req, allocations);
+ return savedAllocations;
}
@Override
@@ -115,8 +122,11 @@
@Override
public Iterable<LinkResourceAllocations> getAllocations(Link link) {
- // TODO Auto-generated method stub
- return null;
+ ArrayList<LinkResourceAllocations> retval = new ArrayList<>(0);
+ if (savedAllocations != null) {
+ retval.add(savedAllocations);
+ }
+ return retval;
}
@Override
@@ -127,8 +137,10 @@
@Override
public Iterable<ResourceRequest> getAvailableResources(Link link) {
- // TODO Auto-generated method stub
- return null;
+ BandwidthResourceRequest bw = new BandwidthResourceRequest(usedBandwidth);
+ ArrayList<ResourceRequest> result = new ArrayList<>();
+ result.add(bw);
+ return result;
}
@Override