blob: 13a2b6b53b43304d8d94417397b5c395bc02a662 [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 Leenheer4a1c1fa2015-06-01 18:08:56 -0700147 .bidirectional(intent.isBidirectional())
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700148 .build();
149
150 return ImmutableList.of(newIntent);
151 }
152
Marc De Leenheer8c2caac2015-05-28 16:37:33 -0700153 // Release port allocations if unsuccessful
154 deviceResourceService.releasePorts(intent.id());
155
156 throw new IntentCompilationException("Unable to find suitable lightpath for intent " + intent);
weibitf32383b2014-10-22 10:17:31 -0700157 }
158
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700159 /**
160 * Find the lambda allocated to the path.
161 *
162 * @param path the path
163 * @param linkAllocs the link allocations
164 * @return
165 */
166 private LambdaResourceAllocation getWavelength(Path path, LinkResourceAllocations linkAllocs) {
167 for (Link link : path.links()) {
168 for (ResourceAllocation alloc : linkAllocs.getResourceAllocation(link)) {
169 if (alloc.type() == ResourceType.LAMBDA) {
170 return (LambdaResourceAllocation) alloc;
171 }
172 }
173 }
174
175 return null;
176 }
177
178 /**
179 * Request and reserve first available wavelength across path.
180 *
181 * @param path path in WDM topology
182 * @return first available lambda resource allocation
183 */
184 private LinkResourceAllocations assignWavelength(Intent intent, Path path) {
185 LinkResourceRequest.Builder request =
186 DefaultLinkResourceRequest.builder(intent.id(), path.links())
187 .addLambdaRequest();
188
189 LinkResourceAllocations allocations = linkResourceService.requestResources(request.build());
190
191 checkWavelengthContinuity(allocations, path);
192
193 return allocations;
194 }
195
196 /**
197 * Checks wavelength continuity constraint across path, i.e., an identical lambda is used on all links.
198 * @return true if wavelength continuity is met, false otherwise
199 */
200 private boolean checkWavelengthContinuity(LinkResourceAllocations allocations, Path path) {
201 if (allocations == null) {
202 return false;
203 }
204
205 LambdaResource lambda = null;
206
207 for (Link link : path.links()) {
208 for (ResourceAllocation alloc : allocations.getResourceAllocation(link)) {
209 if (alloc.type() == ResourceType.LAMBDA) {
210 LambdaResource nextLambda = ((LambdaResourceAllocation) alloc).lambda();
211 if (nextLambda == null) {
212 return false;
213 }
214 if (lambda == null) {
215 lambda = nextLambda;
216 continue;
217 }
218 if (!lambda.equals(nextLambda)) {
219 return false;
220 }
221 }
222 }
223 }
224
225 return true;
226 }
227
228 /**
229 * Convert lambda resource allocation in OCh signal.
230 *
231 * @param alloc lambda resource allocation
232 * @param minFrequency minimum frequency
233 * @param grid grid spacing frequency
234 * @return OCh signal
235 */
236 private OchSignal getOchSignal(LambdaResourceAllocation alloc, Frequency minFrequency, Frequency grid) {
237 int channel = alloc.lambda().toInt();
238
239 // Calculate center frequency
240 Frequency centerFrequency = minFrequency.add(grid.multiply(channel)).add(grid.floorDivision(2));
241
242 // Build OCh signal object
243 int spacingMultiplier = (int) (centerFrequency.subtract(OchSignal.CENTER_FREQUENCY).asHz() / grid.asHz());
244 int slotGranularity = (int) (grid.asHz() / ChannelSpacing.CHL_12P5GHZ.frequency().asHz());
245 OchSignal ochSignal = new OchSignal(DEFAULT_OCH_GRIDTYPE, DEFAULT_CHANNEL_SPACING,
246 spacingMultiplier, slotGranularity);
247
248 return ochSignal;
249 }
250
251 /**
252 * Calculates optical paths in WDM topology.
253 *
254 * @param intent optical connectivity intent
255 * @return set of paths in WDM topology
256 */
257 private Set<Path> getOpticalPaths(OpticalConnectivityIntent intent) {
258 // Route in WDM topology
weibit7e583462014-10-23 10:14:05 -0700259 Topology topology = topologyService.currentTopology();
260 LinkWeight weight = new LinkWeight() {
261 @Override
262 public double weight(TopologyEdge edge) {
Praseed Balakrishnan00dd1f92014-11-19 17:12:36 -0800263 if (edge.link().state() == Link.State.INACTIVE) {
264 return -1;
265 }
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700266 if (edge.link().type() != Link.Type.OPTICAL) {
267 return -1;
268 }
Marc De Leenheer88194c32015-05-29 22:10:59 -0700269 //return edge.link().annotations().value("optical.type").equals("WDM") ? +1 : -1;
270 return 1;
weibit7e583462014-10-23 10:14:05 -0700271 }
272 };
weibitf32383b2014-10-22 10:17:31 -0700273
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700274 ConnectPoint start = intent.getSrc();
275 ConnectPoint end = intent.getDst();
Thomas Vachuska425a2d72014-10-29 11:28:28 -0700276 Set<Path> paths = topologyService.getPaths(topology, start.deviceId(),
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700277 end.deviceId(), weight);
weibit7e583462014-10-23 10:14:05 -0700278
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700279 return paths;
weibitf32383b2014-10-22 10:17:31 -0700280 }
weibitf32383b2014-10-22 10:17:31 -0700281}