blob: a192a9fdf9ff7cb05784c27f1017fdac80cc1de8 [file] [log] [blame]
Ray Milkeycaa450b2014-10-29 15:54:24 -07001package org.onlab.onos.net.intent.impl;
2
3import java.util.ArrayList;
4import java.util.Arrays;
5import java.util.List;
6import java.util.Set;
7
8import org.apache.felix.scr.annotations.Activate;
9import org.apache.felix.scr.annotations.Component;
10import org.apache.felix.scr.annotations.Deactivate;
11import org.apache.felix.scr.annotations.Reference;
12import org.apache.felix.scr.annotations.ReferenceCardinality;
13import org.onlab.onos.net.ConnectPoint;
14import org.onlab.onos.net.DefaultEdgeLink;
15import org.onlab.onos.net.DefaultPath;
16import org.onlab.onos.net.Link;
17import org.onlab.onos.net.Path;
18import org.onlab.onos.net.intent.Intent;
19import org.onlab.onos.net.intent.IntentCompiler;
20import org.onlab.onos.net.intent.IntentExtensionService;
21import org.onlab.onos.net.intent.PathIntent;
22import org.onlab.onos.net.intent.PointToPointIntent;
23import org.onlab.onos.net.intent.PointToPointIntentWithBandwidthConstraint;
24import org.onlab.onos.net.provider.ProviderId;
25import org.onlab.onos.net.resource.BandwidthResourceRequest;
26import org.onlab.onos.net.resource.DefaultLinkResourceRequest;
27import org.onlab.onos.net.resource.LinkResourceRequest;
28import org.onlab.onos.net.resource.LinkResourceService;
29import org.onlab.onos.net.resource.ResourceRequest;
30import org.onlab.onos.net.resource.ResourceType;
31import org.onlab.onos.net.topology.LinkWeight;
32import org.onlab.onos.net.topology.Topology;
33import org.onlab.onos.net.topology.TopologyEdge;
34import org.onlab.onos.net.topology.TopologyService;
35
36/**
37 * A intent compiler for {@link org.onlab.onos.net.intent.HostToHostIntent}.
38 */
39@Component(immediate = true)
40public class PointToPointIntentWithBandwidthConstraintCompiler
41 implements IntentCompiler<PointToPointIntentWithBandwidthConstraint> {
42
43 private static final ProviderId PID = new ProviderId("core", "org.onlab.onos.core", true);
44 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
45 protected IntentExtensionService intentManager;
46
47 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
48 protected TopologyService topologyService;
49
50 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
51 protected LinkResourceService resourceService;
52
53 @Activate
54 public void activate() {
55 intentManager.registerCompiler(PointToPointIntentWithBandwidthConstraint.class, this);
56 }
57
58 @Deactivate
59 public void deactivate() {
60 intentManager.unregisterCompiler(PointToPointIntent.class);
61 }
62
63 @Override
64 public List<Intent> compile(PointToPointIntentWithBandwidthConstraint intent) {
65 Path path = getPath(intent.ingressPoint(), intent.egressPoint(), intent.bandwidthRequest());
66
67 List<Link> links = new ArrayList<>();
68 links.add(DefaultEdgeLink.createEdgeLink(intent.ingressPoint(), true));
69 links.addAll(path.links());
70 links.add(DefaultEdgeLink.createEdgeLink(intent.egressPoint(), false));
71
72 return Arrays.asList(createPathIntent(new DefaultPath(PID, links, path.cost() + 2,
73 path.annotations()),
74 intent));
75 }
76
77 /**
78 * Creates a path intent from the specified path and original
79 * connectivity intent.
80 *
81 * @param path path to create an intent for
82 * @param intent original intent
83 */
84 private Intent createPathIntent(Path path,
85 PointToPointIntentWithBandwidthConstraint intent) {
86 LinkResourceRequest.Builder request = DefaultLinkResourceRequest.builder(intent.id(),
87 path.links())
88 // TODO - this seems awkward, maybe allow directly attaching a BandwidthRequest
89 .addBandwidthRequest(intent.bandwidthRequest().bandwidth().toDouble());
90 LinkResourceRequest bandwidthRequest = request.build();
91 LinkResourceRequest[] bandwidthRequests = {bandwidthRequest};
92 return new PathIntent(intent.appId(),
93 intent.selector(), intent.treatment(), path,
94 bandwidthRequests);
95 }
96
97 /**
98 * Computes a path between two ConnectPoints.
99 *
100 * @param one start of the path
101 * @param two end of the path
102 * @return Path between the two
103 * @throws org.onlab.onos.net.intent.impl.PathNotFoundException if a path cannot be found
104 */
105 private Path getPath(ConnectPoint one, ConnectPoint two, final BandwidthResourceRequest bandwidthRequest) {
106 Topology topology = topologyService.currentTopology();
107 LinkWeight weight = new LinkWeight() {
108 @Override
109 public double weight(TopologyEdge edge) {
110 if (bandwidthRequest != null) {
111 double allocatedBandwidth = 0.0;
112 Iterable<ResourceRequest> availableResources = resourceService.getAvailableResources(edge.link());
113 for (ResourceRequest availableResource : availableResources) {
114 if (availableResource.type() == ResourceType.BANDWIDTH) {
115 BandwidthResourceRequest bandwidthRequest = (BandwidthResourceRequest) availableResource;
116 allocatedBandwidth += bandwidthRequest.bandwidth().toDouble();
117 }
118 }
119
120 // TODO this needs to be discovered from switch/ports somehow
121 double maxBandwidth = 1000;
122
123 double availableBandwidth = maxBandwidth - allocatedBandwidth;
124 if (availableBandwidth >= bandwidthRequest.bandwidth().toDouble()) {
125 return 1;
126 } else {
127 return -1;
128 }
129 } else {
130 return 1;
131 }
132 }
133 };
134
135 Set<Path> paths = topologyService.getPaths(topology,
136 one.deviceId(),
137 two.deviceId(),
138 weight);
139
140 if (paths.isEmpty()) {
141 throw new PathNotFoundException("No packet path from " + one + " to " + two);
142 }
143 // TODO: let's be more intelligent about this eventually
144 return paths.iterator().next();
145 }
146}