blob: 144f2dfc4951954aedeefa5c6c5eae4b0316ac42 [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;
29import org.onosproject.net.ChannelSpacing;
Brian O'Connorabafb502014-12-02 22:26:20 -080030import org.onosproject.net.ConnectPoint;
Marc De Leenheer1afa2a02015-05-13 09:18:07 -070031import org.onosproject.net.GridType;
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
Marc De Leenheer1afa2a02015-05-13 09:18:07 -070074 private static final GridType DEFAULT_OCH_GRIDTYPE = GridType.DWDM;
75 private static final ChannelSpacing DEFAULT_CHANNEL_SPACING = ChannelSpacing.CHL_50GHZ;
76
weibitf32383b2014-10-22 10:17:31 -070077 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
78 protected IntentExtensionService intentManager;
79
80 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
weibit7e583462014-10-23 10:14:05 -070081 protected TopologyService topologyService;
weibitf32383b2014-10-22 10:17:31 -070082
Marc De Leenheer1afa2a02015-05-13 09:18:07 -070083 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
84 protected DeviceService deviceService;
85
86 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
87 protected LinkResourceService linkResourceService;
88
89 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
90 protected DeviceResourceService deviceResourceService;
91
weibitf32383b2014-10-22 10:17:31 -070092 @Activate
93 public void activate() {
weibitf32383b2014-10-22 10:17:31 -070094 intentManager.registerCompiler(OpticalConnectivityIntent.class, this);
95 }
96
97 @Deactivate
98 public void deactivate() {
99 intentManager.unregisterCompiler(OpticalConnectivityIntent.class);
100 }
101
102 @Override
Brian O'Connorfa81eae2014-10-30 13:20:05 -0700103 public List<Intent> compile(OpticalConnectivityIntent intent,
104 List<Intent> installable,
105 Set<LinkResourceAllocations> resources) {
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700106 // Check if source and destination are optical OCh ports
107 ConnectPoint src = intent.getSrc();
108 ConnectPoint dst = intent.getDst();
109 Port srcPort = deviceService.getPort(src.deviceId(), src.port());
110 Port dstPort = deviceService.getPort(dst.deviceId(), dst.port());
111 checkArgument(srcPort instanceof OchPort);
112 checkArgument(dstPort instanceof OchPort);
113
Marc De Leenheer8c2caac2015-05-28 16:37:33 -0700114 log.debug("Compiling optical connectivity intent between {} and {}", src, dst);
115
116 // Reserve OCh ports
117 if (!deviceResourceService.requestPorts(new HashSet(Arrays.asList(srcPort, dstPort)), intent)) {
118 throw new IntentCompilationException("Unable to reserve ports for intent " + intent);
119 }
120
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700121 // Calculate available light paths
122 Set<Path> paths = getOpticalPaths(intent);
123
124 // Use first path that can be successfully reserved
125 for (Path path : paths) {
126 // Request and reserve lambda on path
127 LinkResourceAllocations linkAllocs = assignWavelength(intent, path);
128 if (linkAllocs == null) {
129 continue;
130 }
131
132 OmsPort omsPort = (OmsPort) deviceService.getPort(path.src().deviceId(), path.src().port());
133
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700134 // Create installable optical path intent
135 LambdaResourceAllocation lambdaAlloc = getWavelength(path, linkAllocs);
136 OchSignal ochSignal = getOchSignal(lambdaAlloc, omsPort.minFrequency(), omsPort.grid());
Marc De Leenheerd24420f2015-05-27 09:40:59 -0700137 // Only support fixed grid for now
138 OchSignalType signalType = OchSignalType.FIXED_GRID;
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700139
140 Intent newIntent = OpticalPathIntent.builder()
141 .appId(intent.appId())
142 .src(intent.getSrc())
143 .dst(intent.getDst())
144 .path(path)
145 .lambda(ochSignal)
Marc De Leenheerd24420f2015-05-27 09:40:59 -0700146 .signalType(signalType)
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700147 .build();
148
149 return ImmutableList.of(newIntent);
150 }
151
Marc De Leenheer8c2caac2015-05-28 16:37:33 -0700152 // Release port allocations if unsuccessful
153 deviceResourceService.releasePorts(intent.id());
154
155 throw new IntentCompilationException("Unable to find suitable lightpath for intent " + intent);
weibitf32383b2014-10-22 10:17:31 -0700156 }
157
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700158 /**
159 * Find the lambda allocated to the path.
160 *
161 * @param path the path
162 * @param linkAllocs the link allocations
163 * @return
164 */
165 private LambdaResourceAllocation getWavelength(Path path, LinkResourceAllocations linkAllocs) {
166 for (Link link : path.links()) {
167 for (ResourceAllocation alloc : linkAllocs.getResourceAllocation(link)) {
168 if (alloc.type() == ResourceType.LAMBDA) {
169 return (LambdaResourceAllocation) alloc;
170 }
171 }
172 }
173
174 return null;
175 }
176
177 /**
178 * Request and reserve first available wavelength across path.
179 *
180 * @param path path in WDM topology
181 * @return first available lambda resource allocation
182 */
183 private LinkResourceAllocations assignWavelength(Intent intent, Path path) {
184 LinkResourceRequest.Builder request =
185 DefaultLinkResourceRequest.builder(intent.id(), path.links())
186 .addLambdaRequest();
187
188 LinkResourceAllocations allocations = linkResourceService.requestResources(request.build());
189
190 checkWavelengthContinuity(allocations, path);
191
192 return allocations;
193 }
194
195 /**
196 * Checks wavelength continuity constraint across path, i.e., an identical lambda is used on all links.
197 * @return true if wavelength continuity is met, false otherwise
198 */
199 private boolean checkWavelengthContinuity(LinkResourceAllocations allocations, Path path) {
200 if (allocations == null) {
201 return false;
202 }
203
204 LambdaResource lambda = null;
205
206 for (Link link : path.links()) {
207 for (ResourceAllocation alloc : allocations.getResourceAllocation(link)) {
208 if (alloc.type() == ResourceType.LAMBDA) {
209 LambdaResource nextLambda = ((LambdaResourceAllocation) alloc).lambda();
210 if (nextLambda == null) {
211 return false;
212 }
213 if (lambda == null) {
214 lambda = nextLambda;
215 continue;
216 }
217 if (!lambda.equals(nextLambda)) {
218 return false;
219 }
220 }
221 }
222 }
223
224 return true;
225 }
226
227 /**
228 * Convert lambda resource allocation in OCh signal.
229 *
230 * @param alloc lambda resource allocation
231 * @param minFrequency minimum frequency
232 * @param grid grid spacing frequency
233 * @return OCh signal
234 */
235 private OchSignal getOchSignal(LambdaResourceAllocation alloc, Frequency minFrequency, Frequency grid) {
236 int channel = alloc.lambda().toInt();
237
238 // Calculate center frequency
239 Frequency centerFrequency = minFrequency.add(grid.multiply(channel)).add(grid.floorDivision(2));
240
241 // Build OCh signal object
242 int spacingMultiplier = (int) (centerFrequency.subtract(OchSignal.CENTER_FREQUENCY).asHz() / grid.asHz());
243 int slotGranularity = (int) (grid.asHz() / ChannelSpacing.CHL_12P5GHZ.frequency().asHz());
244 OchSignal ochSignal = new OchSignal(DEFAULT_OCH_GRIDTYPE, DEFAULT_CHANNEL_SPACING,
245 spacingMultiplier, slotGranularity);
246
247 return ochSignal;
248 }
249
250 /**
251 * Calculates optical paths in WDM topology.
252 *
253 * @param intent optical connectivity intent
254 * @return set of paths in WDM topology
255 */
256 private Set<Path> getOpticalPaths(OpticalConnectivityIntent intent) {
257 // Route in WDM topology
weibit7e583462014-10-23 10:14:05 -0700258 Topology topology = topologyService.currentTopology();
259 LinkWeight weight = new LinkWeight() {
260 @Override
261 public double weight(TopologyEdge edge) {
Praseed Balakrishnan00dd1f92014-11-19 17:12:36 -0800262 if (edge.link().state() == Link.State.INACTIVE) {
263 return -1;
264 }
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700265 if (edge.link().type() != Link.Type.OPTICAL) {
266 return -1;
267 }
Marc De Leenheer88194c32015-05-29 22:10:59 -0700268 //return edge.link().annotations().value("optical.type").equals("WDM") ? +1 : -1;
269 return 1;
weibit7e583462014-10-23 10:14:05 -0700270 }
271 };
weibitf32383b2014-10-22 10:17:31 -0700272
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700273 ConnectPoint start = intent.getSrc();
274 ConnectPoint end = intent.getDst();
Thomas Vachuska425a2d72014-10-29 11:28:28 -0700275 Set<Path> paths = topologyService.getPaths(topology, start.deviceId(),
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700276 end.deviceId(), weight);
weibit7e583462014-10-23 10:14:05 -0700277
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700278 return paths;
weibitf32383b2014-10-22 10:17:31 -0700279 }
weibitf32383b2014-10-22 10:17:31 -0700280}