blob: bab6098495412cca17c52a2a31544e5392f8379b [file] [log] [blame]
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07001/*
Ray Milkey34c95902015-04-15 09:47:53 -07002 * Copyright 2014-2015 Open Networking Laboratory
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Sho SHIMIZU6c28f832015-02-20 16:12:19 -080016package org.onosproject.net.intent.impl.compiler;
weibitf32383b2014-10-22 10:17:31 -070017
Marc De Leenheer8c2caac2015-05-28 16:37:33 -070018import java.util.Arrays;
19import java.util.HashSet;
Ray Milkeye076c792015-03-24 09:38:30 -070020import java.util.List;
21import java.util.Set;
22
weibitf32383b2014-10-22 10:17:31 -070023import org.apache.felix.scr.annotations.Activate;
24import org.apache.felix.scr.annotations.Component;
25import org.apache.felix.scr.annotations.Deactivate;
26import org.apache.felix.scr.annotations.Reference;
27import org.apache.felix.scr.annotations.ReferenceCardinality;
Marc De Leenheer1afa2a02015-05-13 09:18:07 -070028import org.onlab.util.Frequency;
Marc De Leenheer723f5532015-06-03 20:16:17 -070029import org.onosproject.net.AnnotationKeys;
Brian O'Connorabafb502014-12-02 22:26:20 -080030import org.onosproject.net.ConnectPoint;
Marc De Leenheer723f5532015-06-03 20:16:17 -070031import org.onosproject.net.DeviceId;
Brian O'Connorabafb502014-12-02 22:26:20 -080032import org.onosproject.net.Link;
Marc De Leenheer1afa2a02015-05-13 09:18:07 -070033import org.onosproject.net.OchPort;
34import org.onosproject.net.OchSignal;
Marc De Leenheerd24420f2015-05-27 09:40:59 -070035import org.onosproject.net.OchSignalType;
Marc De Leenheer1afa2a02015-05-13 09:18:07 -070036import org.onosproject.net.OmsPort;
Brian O'Connorabafb502014-12-02 22:26:20 -080037import org.onosproject.net.Path;
Marc De Leenheer1afa2a02015-05-13 09:18:07 -070038import org.onosproject.net.Port;
39import org.onosproject.net.device.DeviceService;
Brian O'Connorabafb502014-12-02 22:26:20 -080040import org.onosproject.net.intent.Intent;
41import org.onosproject.net.intent.IntentCompiler;
42import org.onosproject.net.intent.IntentExtensionService;
43import org.onosproject.net.intent.OpticalConnectivityIntent;
44import org.onosproject.net.intent.OpticalPathIntent;
Marc De Leenheer8c2caac2015-05-28 16:37:33 -070045import org.onosproject.net.intent.impl.IntentCompilationException;
Brian O'Connor6de2e202015-05-21 14:30:41 -070046import org.onosproject.net.resource.link.DefaultLinkResourceRequest;
47import org.onosproject.net.resource.device.DeviceResourceService;
48import org.onosproject.net.resource.link.LambdaResource;
49import org.onosproject.net.resource.link.LambdaResourceAllocation;
50import org.onosproject.net.resource.link.LinkResourceAllocations;
51import org.onosproject.net.resource.link.LinkResourceRequest;
52import org.onosproject.net.resource.link.LinkResourceService;
Marc De Leenheer1afa2a02015-05-13 09:18:07 -070053import org.onosproject.net.resource.ResourceAllocation;
54import org.onosproject.net.resource.ResourceType;
Brian O'Connorabafb502014-12-02 22:26:20 -080055import org.onosproject.net.topology.LinkWeight;
56import org.onosproject.net.topology.Topology;
57import org.onosproject.net.topology.TopologyEdge;
58import org.onosproject.net.topology.TopologyService;
Thomas Vachuska425a2d72014-10-29 11:28:28 -070059
Ray Milkeye076c792015-03-24 09:38:30 -070060import com.google.common.collect.ImmutableList;
Marc De Leenheer8c2caac2015-05-28 16:37:33 -070061import org.slf4j.Logger;
62import org.slf4j.LoggerFactory;
weibitf32383b2014-10-22 10:17:31 -070063
Marc De Leenheer1afa2a02015-05-13 09:18:07 -070064import static com.google.common.base.Preconditions.checkArgument;
65
weibitf32383b2014-10-22 10:17:31 -070066/**
Brian O'Connorabafb502014-12-02 22:26:20 -080067 * An intent compiler for {@link org.onosproject.net.intent.OpticalConnectivityIntent}.
weibitf32383b2014-10-22 10:17:31 -070068 */
69@Component(immediate = true)
70public class OpticalConnectivityIntentCompiler implements IntentCompiler<OpticalConnectivityIntent> {
71
Marc De Leenheer8c2caac2015-05-28 16:37:33 -070072 protected static final Logger log = LoggerFactory.getLogger(OpticalConnectivityIntentCompiler.class);
73
weibitf32383b2014-10-22 10:17:31 -070074 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
75 protected IntentExtensionService intentManager;
76
77 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
weibit7e583462014-10-23 10:14:05 -070078 protected TopologyService topologyService;
weibitf32383b2014-10-22 10:17:31 -070079
Marc De Leenheer1afa2a02015-05-13 09:18:07 -070080 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
81 protected DeviceService deviceService;
82
83 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
84 protected LinkResourceService linkResourceService;
85
86 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
87 protected DeviceResourceService deviceResourceService;
88
weibitf32383b2014-10-22 10:17:31 -070089 @Activate
90 public void activate() {
weibitf32383b2014-10-22 10:17:31 -070091 intentManager.registerCompiler(OpticalConnectivityIntent.class, this);
92 }
93
94 @Deactivate
95 public void deactivate() {
96 intentManager.unregisterCompiler(OpticalConnectivityIntent.class);
97 }
98
99 @Override
Brian O'Connorfa81eae2014-10-30 13:20:05 -0700100 public List<Intent> compile(OpticalConnectivityIntent intent,
101 List<Intent> installable,
102 Set<LinkResourceAllocations> resources) {
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700103 // Check if source and destination are optical OCh ports
104 ConnectPoint src = intent.getSrc();
105 ConnectPoint dst = intent.getDst();
106 Port srcPort = deviceService.getPort(src.deviceId(), src.port());
107 Port dstPort = deviceService.getPort(dst.deviceId(), dst.port());
108 checkArgument(srcPort instanceof OchPort);
109 checkArgument(dstPort instanceof OchPort);
110
Marc De Leenheer8c2caac2015-05-28 16:37:33 -0700111 log.debug("Compiling optical connectivity intent between {} and {}", src, dst);
112
113 // Reserve OCh ports
114 if (!deviceResourceService.requestPorts(new HashSet(Arrays.asList(srcPort, dstPort)), intent)) {
115 throw new IntentCompilationException("Unable to reserve ports for intent " + intent);
116 }
117
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700118 // Calculate available light paths
119 Set<Path> paths = getOpticalPaths(intent);
120
121 // Use first path that can be successfully reserved
122 for (Path path : paths) {
Marc De Leenheer723f5532015-06-03 20:16:17 -0700123
124 // Static or dynamic lambda allocation
Marc De Leenheer723f5532015-06-03 20:16:17 -0700125 String staticLambda = srcPort.annotations().value(AnnotationKeys.STATIC_LAMBDA);
Marc De Leenheerc9733082015-06-04 12:22:38 -0700126 OchPort srcOchPort = (OchPort) srcPort;
127 OchPort dstOchPort = (OchPort) dstPort;
128 OchSignal ochSignal;
129
130 // FIXME: need to actually reserve the lambda for static lambda's
Marc De Leenheer723f5532015-06-03 20:16:17 -0700131 if (staticLambda != null) {
Marc De Leenheerc9733082015-06-04 12:22:38 -0700132 ochSignal = new OchSignal(Frequency.ofHz(Long.valueOf(staticLambda)),
133 srcOchPort.lambda().channelSpacing(),
134 srcOchPort.lambda().slotGranularity());
135 } else if (!srcOchPort.isTunable() || !dstOchPort.isTunable()) {
136 // FIXME: also check OCh port
137 ochSignal = srcOchPort.lambda();
Marc De Leenheer723f5532015-06-03 20:16:17 -0700138 } else {
139 // Request and reserve lambda on path
140 LinkResourceAllocations linkAllocs = assignWavelength(intent, path);
141 if (linkAllocs == null) {
142 continue;
143 }
Marc De Leenheerc9733082015-06-04 12:22:38 -0700144 LambdaResourceAllocation lambdaAlloc = getWavelength(path, linkAllocs);
145 OmsPort omsPort = (OmsPort) deviceService.getPort(path.src().deviceId(), path.src().port());
146 ochSignal = new OchSignal(lambdaAlloc, omsPort.maxFrequency(), omsPort.grid());
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700147 }
148
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700149 // Create installable optical path intent
Marc De Leenheerd24420f2015-05-27 09:40:59 -0700150 // Only support fixed grid for now
151 OchSignalType signalType = OchSignalType.FIXED_GRID;
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700152
153 Intent newIntent = OpticalPathIntent.builder()
154 .appId(intent.appId())
155 .src(intent.getSrc())
156 .dst(intent.getDst())
157 .path(path)
158 .lambda(ochSignal)
Marc De Leenheerd24420f2015-05-27 09:40:59 -0700159 .signalType(signalType)
Marc De Leenheer4a1c1fa2015-06-01 18:08:56 -0700160 .bidirectional(intent.isBidirectional())
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700161 .build();
162
163 return ImmutableList.of(newIntent);
164 }
165
Marc De Leenheer8c2caac2015-05-28 16:37:33 -0700166 // Release port allocations if unsuccessful
167 deviceResourceService.releasePorts(intent.id());
168
169 throw new IntentCompilationException("Unable to find suitable lightpath for intent " + intent);
weibitf32383b2014-10-22 10:17:31 -0700170 }
171
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700172 /**
173 * Find the lambda allocated to the path.
174 *
175 * @param path the path
176 * @param linkAllocs the link allocations
177 * @return
178 */
179 private LambdaResourceAllocation getWavelength(Path path, LinkResourceAllocations linkAllocs) {
180 for (Link link : path.links()) {
181 for (ResourceAllocation alloc : linkAllocs.getResourceAllocation(link)) {
182 if (alloc.type() == ResourceType.LAMBDA) {
183 return (LambdaResourceAllocation) alloc;
184 }
185 }
186 }
187
188 return null;
189 }
190
191 /**
192 * Request and reserve first available wavelength across path.
193 *
194 * @param path path in WDM topology
195 * @return first available lambda resource allocation
196 */
197 private LinkResourceAllocations assignWavelength(Intent intent, Path path) {
198 LinkResourceRequest.Builder request =
199 DefaultLinkResourceRequest.builder(intent.id(), path.links())
200 .addLambdaRequest();
201
202 LinkResourceAllocations allocations = linkResourceService.requestResources(request.build());
203
Marc De Leenheer723f5532015-06-03 20:16:17 -0700204 if (!checkWavelengthContinuity(allocations, path)) {
205 linkResourceService.releaseResources(allocations);
206 return null;
207 }
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700208
209 return allocations;
210 }
211
212 /**
213 * Checks wavelength continuity constraint across path, i.e., an identical lambda is used on all links.
214 * @return true if wavelength continuity is met, false otherwise
215 */
216 private boolean checkWavelengthContinuity(LinkResourceAllocations allocations, Path path) {
217 if (allocations == null) {
218 return false;
219 }
220
221 LambdaResource lambda = null;
222
223 for (Link link : path.links()) {
224 for (ResourceAllocation alloc : allocations.getResourceAllocation(link)) {
225 if (alloc.type() == ResourceType.LAMBDA) {
226 LambdaResource nextLambda = ((LambdaResourceAllocation) alloc).lambda();
227 if (nextLambda == null) {
228 return false;
229 }
230 if (lambda == null) {
231 lambda = nextLambda;
232 continue;
233 }
234 if (!lambda.equals(nextLambda)) {
235 return false;
236 }
237 }
238 }
239 }
240
241 return true;
242 }
243
Marc De Leenheer723f5532015-06-03 20:16:17 -0700244 private ConnectPoint staticPort(ConnectPoint connectPoint) {
245 Port port = deviceService.getPort(connectPoint.deviceId(), connectPoint.port());
246
247 String staticPort = port.annotations().value(AnnotationKeys.STATIC_PORT);
248
249 // FIXME: need a better way to match the port
250 if (staticPort != null) {
251 for (Port p : deviceService.getPorts(connectPoint.deviceId())) {
252 if (staticPort.equals(p.number().name())) {
253 return new ConnectPoint(p.element().id(), p.number());
254 }
255 }
256 }
257
258 return null;
259 }
260
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700261 /**
262 * Calculates optical paths in WDM topology.
263 *
264 * @param intent optical connectivity intent
265 * @return set of paths in WDM topology
266 */
267 private Set<Path> getOpticalPaths(OpticalConnectivityIntent intent) {
268 // Route in WDM topology
weibit7e583462014-10-23 10:14:05 -0700269 Topology topology = topologyService.currentTopology();
270 LinkWeight weight = new LinkWeight() {
271 @Override
272 public double weight(TopologyEdge edge) {
Marc De Leenheer723f5532015-06-03 20:16:17 -0700273 // Disregard inactive or non-optical links
Praseed Balakrishnan00dd1f92014-11-19 17:12:36 -0800274 if (edge.link().state() == Link.State.INACTIVE) {
275 return -1;
276 }
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700277 if (edge.link().type() != Link.Type.OPTICAL) {
278 return -1;
279 }
Marc De Leenheer723f5532015-06-03 20:16:17 -0700280 // Adhere to static port mappings
281 DeviceId srcDeviceId = edge.link().src().deviceId();
282 if (srcDeviceId.equals(intent.getSrc().deviceId())) {
283 ConnectPoint srcStaticPort = staticPort(intent.getSrc());
284 if (srcStaticPort != null) {
285 return srcStaticPort.equals(edge.link().src()) ? 1 : -1;
286 }
287 }
288 DeviceId dstDeviceId = edge.link().dst().deviceId();
289 if (dstDeviceId.equals(intent.getDst().deviceId())) {
290 ConnectPoint dstStaticPort = staticPort(intent.getDst());
291 if (dstStaticPort != null) {
292 return dstStaticPort.equals(edge.link().dst()) ? 1 : -1;
293 }
294 }
295
Marc De Leenheer88194c32015-05-29 22:10:59 -0700296 return 1;
weibit7e583462014-10-23 10:14:05 -0700297 }
298 };
weibitf32383b2014-10-22 10:17:31 -0700299
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700300 ConnectPoint start = intent.getSrc();
301 ConnectPoint end = intent.getDst();
Thomas Vachuska425a2d72014-10-29 11:28:28 -0700302 Set<Path> paths = topologyService.getPaths(topology, start.deviceId(),
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700303 end.deviceId(), weight);
weibit7e583462014-10-23 10:14:05 -0700304
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700305 return paths;
weibitf32383b2014-10-22 10:17:31 -0700306 }
weibitf32383b2014-10-22 10:17:31 -0700307}