blob: 4f8527efd6e89774a7acec7b34f9bb8f06e39fb0 [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 Leenheer1afa2a02015-05-13 09:18:07 -070018import java.util.Collections;
Ray Milkeye076c792015-03-24 09:38:30 -070019import java.util.List;
20import java.util.Set;
21
weibitf32383b2014-10-22 10:17:31 -070022import org.apache.felix.scr.annotations.Activate;
23import org.apache.felix.scr.annotations.Component;
24import org.apache.felix.scr.annotations.Deactivate;
25import org.apache.felix.scr.annotations.Reference;
26import org.apache.felix.scr.annotations.ReferenceCardinality;
Marc De Leenheer1afa2a02015-05-13 09:18:07 -070027import org.onlab.util.Frequency;
28import org.onosproject.net.ChannelSpacing;
Brian O'Connorabafb502014-12-02 22:26:20 -080029import org.onosproject.net.ConnectPoint;
Marc De Leenheer1afa2a02015-05-13 09:18:07 -070030import org.onosproject.net.GridType;
Brian O'Connorabafb502014-12-02 22:26:20 -080031import org.onosproject.net.Link;
Marc De Leenheer1afa2a02015-05-13 09:18:07 -070032import org.onosproject.net.OchPort;
33import org.onosproject.net.OchSignal;
34import org.onosproject.net.OmsPort;
Brian O'Connorabafb502014-12-02 22:26:20 -080035import org.onosproject.net.Path;
Marc De Leenheer1afa2a02015-05-13 09:18:07 -070036import org.onosproject.net.Port;
37import org.onosproject.net.device.DeviceService;
Brian O'Connorabafb502014-12-02 22:26:20 -080038import org.onosproject.net.intent.Intent;
39import org.onosproject.net.intent.IntentCompiler;
40import org.onosproject.net.intent.IntentExtensionService;
41import org.onosproject.net.intent.OpticalConnectivityIntent;
42import org.onosproject.net.intent.OpticalPathIntent;
Brian O'Connor6de2e202015-05-21 14:30:41 -070043import org.onosproject.net.resource.link.DefaultLinkResourceRequest;
44import org.onosproject.net.resource.device.DeviceResourceService;
45import org.onosproject.net.resource.link.LambdaResource;
46import org.onosproject.net.resource.link.LambdaResourceAllocation;
47import org.onosproject.net.resource.link.LinkResourceAllocations;
48import org.onosproject.net.resource.link.LinkResourceRequest;
49import org.onosproject.net.resource.link.LinkResourceService;
Marc De Leenheer1afa2a02015-05-13 09:18:07 -070050import org.onosproject.net.resource.ResourceAllocation;
51import org.onosproject.net.resource.ResourceType;
Brian O'Connorabafb502014-12-02 22:26:20 -080052import org.onosproject.net.topology.LinkWeight;
53import org.onosproject.net.topology.Topology;
54import org.onosproject.net.topology.TopologyEdge;
55import org.onosproject.net.topology.TopologyService;
Thomas Vachuska425a2d72014-10-29 11:28:28 -070056
Ray Milkeye076c792015-03-24 09:38:30 -070057import com.google.common.collect.ImmutableList;
weibitf32383b2014-10-22 10:17:31 -070058
Marc De Leenheer1afa2a02015-05-13 09:18:07 -070059import static com.google.common.base.Preconditions.checkArgument;
60
weibitf32383b2014-10-22 10:17:31 -070061/**
Brian O'Connorabafb502014-12-02 22:26:20 -080062 * An intent compiler for {@link org.onosproject.net.intent.OpticalConnectivityIntent}.
weibitf32383b2014-10-22 10:17:31 -070063 */
64@Component(immediate = true)
65public class OpticalConnectivityIntentCompiler implements IntentCompiler<OpticalConnectivityIntent> {
66
Marc De Leenheer1afa2a02015-05-13 09:18:07 -070067 private static final GridType DEFAULT_OCH_GRIDTYPE = GridType.DWDM;
68 private static final ChannelSpacing DEFAULT_CHANNEL_SPACING = ChannelSpacing.CHL_50GHZ;
69
weibitf32383b2014-10-22 10:17:31 -070070 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
71 protected IntentExtensionService intentManager;
72
73 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
weibit7e583462014-10-23 10:14:05 -070074 protected TopologyService topologyService;
weibitf32383b2014-10-22 10:17:31 -070075
Marc De Leenheer1afa2a02015-05-13 09:18:07 -070076 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
77 protected DeviceService deviceService;
78
79 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
80 protected LinkResourceService linkResourceService;
81
82 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
83 protected DeviceResourceService deviceResourceService;
84
weibitf32383b2014-10-22 10:17:31 -070085 @Activate
86 public void activate() {
weibitf32383b2014-10-22 10:17:31 -070087 intentManager.registerCompiler(OpticalConnectivityIntent.class, this);
88 }
89
90 @Deactivate
91 public void deactivate() {
92 intentManager.unregisterCompiler(OpticalConnectivityIntent.class);
93 }
94
95 @Override
Brian O'Connorfa81eae2014-10-30 13:20:05 -070096 public List<Intent> compile(OpticalConnectivityIntent intent,
97 List<Intent> installable,
98 Set<LinkResourceAllocations> resources) {
Marc De Leenheer1afa2a02015-05-13 09:18:07 -070099 // Check if source and destination are optical OCh ports
100 ConnectPoint src = intent.getSrc();
101 ConnectPoint dst = intent.getDst();
102 Port srcPort = deviceService.getPort(src.deviceId(), src.port());
103 Port dstPort = deviceService.getPort(dst.deviceId(), dst.port());
104 checkArgument(srcPort instanceof OchPort);
105 checkArgument(dstPort instanceof OchPort);
106
107 // Calculate available light paths
108 Set<Path> paths = getOpticalPaths(intent);
109
110 // Use first path that can be successfully reserved
111 for (Path path : paths) {
112 // Request and reserve lambda on path
113 LinkResourceAllocations linkAllocs = assignWavelength(intent, path);
114 if (linkAllocs == null) {
115 continue;
116 }
117
118 OmsPort omsPort = (OmsPort) deviceService.getPort(path.src().deviceId(), path.src().port());
119
120 // Try to reserve port resources, roll back if unsuccessful
121 Set<Port> portAllocs = deviceResourceService.requestPorts(intent);
122 if (portAllocs == null) {
123 linkResourceService.releaseResources(linkAllocs);
124 continue;
125 }
126
127 // Create installable optical path intent
128 LambdaResourceAllocation lambdaAlloc = getWavelength(path, linkAllocs);
129 OchSignal ochSignal = getOchSignal(lambdaAlloc, omsPort.minFrequency(), omsPort.grid());
130
131 Intent newIntent = OpticalPathIntent.builder()
132 .appId(intent.appId())
133 .src(intent.getSrc())
134 .dst(intent.getDst())
135 .path(path)
136 .lambda(ochSignal)
137 .build();
138
139 return ImmutableList.of(newIntent);
140 }
141
142 return Collections.emptyList();
weibitf32383b2014-10-22 10:17:31 -0700143 }
144
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700145 /**
146 * Find the lambda allocated to the path.
147 *
148 * @param path the path
149 * @param linkAllocs the link allocations
150 * @return
151 */
152 private LambdaResourceAllocation getWavelength(Path path, LinkResourceAllocations linkAllocs) {
153 for (Link link : path.links()) {
154 for (ResourceAllocation alloc : linkAllocs.getResourceAllocation(link)) {
155 if (alloc.type() == ResourceType.LAMBDA) {
156 return (LambdaResourceAllocation) alloc;
157 }
158 }
159 }
160
161 return null;
162 }
163
164 /**
165 * Request and reserve first available wavelength across path.
166 *
167 * @param path path in WDM topology
168 * @return first available lambda resource allocation
169 */
170 private LinkResourceAllocations assignWavelength(Intent intent, Path path) {
171 LinkResourceRequest.Builder request =
172 DefaultLinkResourceRequest.builder(intent.id(), path.links())
173 .addLambdaRequest();
174
175 LinkResourceAllocations allocations = linkResourceService.requestResources(request.build());
176
177 checkWavelengthContinuity(allocations, path);
178
179 return allocations;
180 }
181
182 /**
183 * Checks wavelength continuity constraint across path, i.e., an identical lambda is used on all links.
184 * @return true if wavelength continuity is met, false otherwise
185 */
186 private boolean checkWavelengthContinuity(LinkResourceAllocations allocations, Path path) {
187 if (allocations == null) {
188 return false;
189 }
190
191 LambdaResource lambda = null;
192
193 for (Link link : path.links()) {
194 for (ResourceAllocation alloc : allocations.getResourceAllocation(link)) {
195 if (alloc.type() == ResourceType.LAMBDA) {
196 LambdaResource nextLambda = ((LambdaResourceAllocation) alloc).lambda();
197 if (nextLambda == null) {
198 return false;
199 }
200 if (lambda == null) {
201 lambda = nextLambda;
202 continue;
203 }
204 if (!lambda.equals(nextLambda)) {
205 return false;
206 }
207 }
208 }
209 }
210
211 return true;
212 }
213
214 /**
215 * Convert lambda resource allocation in OCh signal.
216 *
217 * @param alloc lambda resource allocation
218 * @param minFrequency minimum frequency
219 * @param grid grid spacing frequency
220 * @return OCh signal
221 */
222 private OchSignal getOchSignal(LambdaResourceAllocation alloc, Frequency minFrequency, Frequency grid) {
223 int channel = alloc.lambda().toInt();
224
225 // Calculate center frequency
226 Frequency centerFrequency = minFrequency.add(grid.multiply(channel)).add(grid.floorDivision(2));
227
228 // Build OCh signal object
229 int spacingMultiplier = (int) (centerFrequency.subtract(OchSignal.CENTER_FREQUENCY).asHz() / grid.asHz());
230 int slotGranularity = (int) (grid.asHz() / ChannelSpacing.CHL_12P5GHZ.frequency().asHz());
231 OchSignal ochSignal = new OchSignal(DEFAULT_OCH_GRIDTYPE, DEFAULT_CHANNEL_SPACING,
232 spacingMultiplier, slotGranularity);
233
234 return ochSignal;
235 }
236
237 /**
238 * Calculates optical paths in WDM topology.
239 *
240 * @param intent optical connectivity intent
241 * @return set of paths in WDM topology
242 */
243 private Set<Path> getOpticalPaths(OpticalConnectivityIntent intent) {
244 // Route in WDM topology
weibit7e583462014-10-23 10:14:05 -0700245 Topology topology = topologyService.currentTopology();
246 LinkWeight weight = new LinkWeight() {
247 @Override
248 public double weight(TopologyEdge edge) {
Praseed Balakrishnan00dd1f92014-11-19 17:12:36 -0800249 if (edge.link().state() == Link.State.INACTIVE) {
250 return -1;
251 }
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700252 if (edge.link().type() != Link.Type.OPTICAL) {
253 return -1;
254 }
255 return edge.link().annotations().value("optical.type").equals("WDM") ? +1 : -1;
weibit7e583462014-10-23 10:14:05 -0700256 }
257 };
weibitf32383b2014-10-22 10:17:31 -0700258
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700259 ConnectPoint start = intent.getSrc();
260 ConnectPoint end = intent.getDst();
Thomas Vachuska425a2d72014-10-29 11:28:28 -0700261 Set<Path> paths = topologyService.getPaths(topology, start.deviceId(),
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700262 end.deviceId(), weight);
weibit7e583462014-10-23 10:14:05 -0700263
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700264 return paths;
weibitf32383b2014-10-22 10:17:31 -0700265 }
weibitf32383b2014-10-22 10:17:31 -0700266}