blob: d9a61f0b6b73318d901cd88b8f1ae226fc7dc16d [file] [log] [blame]
Avantika-Huawei73862d42016-05-12 18:58:06 +05301/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2016-present Open Networking Foundation
Avantika-Huawei73862d42016-05-12 18:58:06 +05303 *
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 */
16package org.onosproject.pce.pceservice;
17
Ray Milkeyd84f89b2018-08-17 14:54:17 -070018import com.google.common.collect.ImmutableList;
19import com.google.common.collect.ImmutableSet;
20import com.google.common.collect.Sets;
Ray Milkeya7cf8c82018-02-08 15:07:06 -080021import org.onlab.graph.ScalarWeight;
Ray Milkey7483e1b2018-02-07 15:43:01 -080022import org.onlab.graph.Weight;
Avantika-Huaweidbdf7722016-05-21 14:20:31 +053023import org.onlab.packet.IpAddress;
Avantika-Huaweidbdf7722016-05-21 14:20:31 +053024import org.onlab.util.Bandwidth;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070025import org.onosproject.bandwidthmgr.api.BandwidthMgmtService;
Avantika-Huawei73862d42016-05-12 18:58:06 +053026import org.onosproject.core.ApplicationId;
27import org.onosproject.core.CoreService;
28import org.onosproject.core.IdGenerator;
Avantika-Huaweidbdf7722016-05-21 14:20:31 +053029import org.onosproject.incubator.net.tunnel.DefaultTunnel;
30import org.onosproject.incubator.net.tunnel.IpTunnelEndPoint;
Avantika-Huawei73862d42016-05-12 18:58:06 +053031import org.onosproject.incubator.net.tunnel.Tunnel;
Avantika-Huaweidbdf7722016-05-21 14:20:31 +053032import org.onosproject.incubator.net.tunnel.TunnelEndPoint;
33import org.onosproject.incubator.net.tunnel.TunnelEvent;
Avantika-Huawei73862d42016-05-12 18:58:06 +053034import org.onosproject.incubator.net.tunnel.TunnelId;
Avantika-Huaweidbdf7722016-05-21 14:20:31 +053035import org.onosproject.incubator.net.tunnel.TunnelListener;
36import org.onosproject.incubator.net.tunnel.TunnelName;
Avantika-Huawei73862d42016-05-12 18:58:06 +053037import org.onosproject.incubator.net.tunnel.TunnelService;
Priyanka B3f92c5a2016-05-27 10:14:16 +053038import org.onosproject.mastership.MastershipService;
Avantika-Huaweidbdf7722016-05-21 14:20:31 +053039import org.onosproject.net.DefaultAnnotations;
40import org.onosproject.net.DefaultAnnotations.Builder;
Priyanka Bbae0eeb12016-11-30 11:59:48 +053041import org.onosproject.net.DefaultPath;
Avantika-Huaweidbdf7722016-05-21 14:20:31 +053042import org.onosproject.net.Device;
Avantika-Huawei73862d42016-05-12 18:58:06 +053043import org.onosproject.net.DeviceId;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070044import org.onosproject.net.DisjointPath;
Avantika-Huaweidbdf7722016-05-21 14:20:31 +053045import org.onosproject.net.Link;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070046import org.onosproject.net.LinkKey;
47import org.onosproject.net.MastershipRole;
Priyanka Bbae0eeb12016-11-30 11:59:48 +053048import org.onosproject.net.NetworkResource;
Priyanka Bb6963582016-05-20 20:21:20 +053049import org.onosproject.net.Path;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070050import org.onosproject.net.config.ConfigFactory;
51import org.onosproject.net.config.NetworkConfigRegistry;
52import org.onosproject.net.config.NetworkConfigService;
Satish K2eb5d842017-04-04 16:28:37 +053053import org.onosproject.net.config.basics.SubjectFactories;
Priyanka Bb6963582016-05-20 20:21:20 +053054import org.onosproject.net.device.DeviceService;
Avantika-Huaweidbdf7722016-05-21 14:20:31 +053055import org.onosproject.net.intent.Constraint;
Priyanka B3f92c5a2016-05-27 10:14:16 +053056import org.onosproject.net.link.LinkEvent;
Avantika-Huaweidbdf7722016-05-21 14:20:31 +053057import org.onosproject.net.resource.Resource;
58import org.onosproject.net.resource.ResourceAllocation;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070059import org.onosproject.net.topology.LinkWeigher;
Priyanka Bb6963582016-05-20 20:21:20 +053060import org.onosproject.net.topology.PathService;
61import org.onosproject.net.topology.TopologyEdge;
Priyanka B3f92c5a2016-05-27 10:14:16 +053062import org.onosproject.net.topology.TopologyEvent;
63import org.onosproject.net.topology.TopologyListener;
64import org.onosproject.net.topology.TopologyService;
Avantika-Huawei73862d42016-05-12 18:58:06 +053065import org.onosproject.pce.pceservice.api.PceService;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070066import org.onosproject.pce.pceservice.constraint.CapabilityConstraint;
67import org.onosproject.pce.pceservice.constraint.CapabilityConstraint.CapabilityType;
68import org.onosproject.pce.pceservice.constraint.CostConstraint;
69import org.onosproject.pce.pceservice.constraint.PceBandwidthConstraint;
70import org.onosproject.pce.pceservice.constraint.SharedBandwidthConstraint;
Avantika-Huaweidbdf7722016-05-21 14:20:31 +053071import org.onosproject.pce.pcestore.PcePathInfo;
Avantika-Huaweidbdf7722016-05-21 14:20:31 +053072import org.onosproject.pce.pcestore.api.PceStore;
Avantika-Huawei032a9872016-05-27 22:57:38 +053073import org.onosproject.pcep.api.DeviceCapability;
Satish K2eb5d842017-04-04 16:28:37 +053074import org.onosproject.pcep.api.TeLinkConfig;
Avantika-Huawei73862d42016-05-12 18:58:06 +053075import org.onosproject.store.serializers.KryoNamespaces;
76import org.onosproject.store.service.DistributedSet;
77import org.onosproject.store.service.Serializer;
78import org.onosproject.store.service.StorageService;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070079import org.osgi.service.component.annotations.Activate;
80import org.osgi.service.component.annotations.Component;
81import org.osgi.service.component.annotations.Deactivate;
82import org.osgi.service.component.annotations.Reference;
83import org.osgi.service.component.annotations.ReferenceCardinality;
Avantika-Huawei73862d42016-05-12 18:58:06 +053084import org.slf4j.Logger;
85import org.slf4j.LoggerFactory;
86
Ray Milkeyd84f89b2018-08-17 14:54:17 -070087import java.util.ArrayList;
88import java.util.Collection;
89import java.util.Collections;
90import java.util.HashMap;
91import java.util.Iterator;
92import java.util.LinkedList;
93import java.util.List;
94import java.util.Map;
95import java.util.Optional;
96import java.util.Set;
Avantika-Huaweidbdf7722016-05-21 14:20:31 +053097
Ray Milkeyd84f89b2018-08-17 14:54:17 -070098import static com.google.common.base.Preconditions.checkNotNull;
Avantika-Huaweidbdf7722016-05-21 14:20:31 +053099import static org.onosproject.incubator.net.tunnel.Tunnel.State.INIT;
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530100import static org.onosproject.incubator.net.tunnel.Tunnel.State.UNSTABLE;
Priyanka B4c3b4512016-07-22 11:41:49 +0530101import static org.onosproject.incubator.net.tunnel.Tunnel.Type.MPLS;
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530102import static org.onosproject.pce.pceservice.LspType.WITH_SIGNALLING;
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530103import static org.onosproject.pce.pceservice.PcepAnnotationKeys.BANDWIDTH;
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700104import static org.onosproject.pce.pceservice.PcepAnnotationKeys.COST_TYPE;
105import static org.onosproject.pce.pceservice.PcepAnnotationKeys.DELEGATE;
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530106import static org.onosproject.pce.pceservice.PcepAnnotationKeys.LOCAL_LSP_ID;
107import static org.onosproject.pce.pceservice.PcepAnnotationKeys.LSP_SIG_TYPE;
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700108import static org.onosproject.pce.pceservice.PcepAnnotationKeys.PCC_TUNNEL_ID;
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530109import static org.onosproject.pce.pceservice.PcepAnnotationKeys.PCE_INIT;
110import static org.onosproject.pce.pceservice.PcepAnnotationKeys.PLSP_ID;
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530111
Avantika-Huawei73862d42016-05-12 18:58:06 +0530112/**
113 * Implementation of PCE service.
114 */
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700115@Component(immediate = true, service = PceManager.class)
Avantika-Huawei73862d42016-05-12 18:58:06 +0530116public class PceManager implements PceService {
117 private static final Logger log = LoggerFactory.getLogger(PceManager.class);
118
Mahesh Poojary Huawei1d17cad2016-06-02 12:53:41 +0530119 public static final long GLOBAL_LABEL_SPACE_MIN = 4097;
120 public static final long GLOBAL_LABEL_SPACE_MAX = 5121;
Avantika-Huawei73862d42016-05-12 18:58:06 +0530121 public static final String PCE_SERVICE_APP = "org.onosproject.pce";
Avantika-Huawei73862d42016-05-12 18:58:06 +0530122 private static final String LOCAL_LSP_ID_GEN_TOPIC = "pcep-local-lsp-id";
Mahesh Poojary Huawei1d17cad2016-06-02 12:53:41 +0530123 public static final String DEVICE_TYPE = "type";
124 public static final String L3_DEVICE = "L3";
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530125
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530126 private static final String LSRID = "lsrId";
127 private static final String TRUE = "true";
128 private static final String FALSE = "false";
Avantika-Huaweid1e36bd2016-05-26 12:47:16 +0530129 public static final int PCEP_PORT = 4189;
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530130
Avantika-Huawei73862d42016-05-12 18:58:06 +0530131 private IdGenerator localLspIdIdGen;
132 protected DistributedSet<Short> localLspIdFreeList;
133
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700134 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Avantika-Huawei73862d42016-05-12 18:58:06 +0530135 protected CoreService coreService;
136
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700137 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530138 protected PathService pathService;
139
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700140 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530141 protected PceStore pceStore;
142
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700143 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Avantika-Huawei73862d42016-05-12 18:58:06 +0530144 protected TunnelService tunnelService;
145
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700146 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Priyanka Bb6963582016-05-20 20:21:20 +0530147 protected DeviceService deviceService;
148
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700149 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Avantika-Huawei9e848e82016-09-01 12:12:42 +0530150 protected StorageService storageService;
Mahesh Poojary Huawei1d17cad2016-06-02 12:53:41 +0530151
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700152 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Avantika-Huawei032a9872016-05-27 22:57:38 +0530153 protected NetworkConfigService netCfgService;
154
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700155 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Priyanka B3f92c5a2016-05-27 10:14:16 +0530156 protected MastershipService mastershipService;
157
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700158 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Priyanka B3f92c5a2016-05-27 10:14:16 +0530159 protected TopologyService topologyService;
160
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700161 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Satish K2eb5d842017-04-04 16:28:37 +0530162 protected BandwidthMgmtService bandwidthMgmtService;
163
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700164 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Satish K2eb5d842017-04-04 16:28:37 +0530165 protected NetworkConfigRegistry netConfigRegistry;
166
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530167 private TunnelListener listener = new InnerTunnelListener();
Avantika-Huawei73862d42016-05-12 18:58:06 +0530168 private ApplicationId appId;
169
Priyanka B3f92c5a2016-05-27 10:14:16 +0530170 private final TopologyListener topologyListener = new InternalTopologyListener();
Satish Kba1c9122017-04-05 15:27:23 +0530171 public static final String LOAD_BALANCING_PATH_NAME = "loadBalancingPathName";
Priyanka B9fa4ed32016-05-27 11:59:24 +0530172
Satish K2eb5d842017-04-04 16:28:37 +0530173 private List<TunnelId> rsvpTunnelsWithLocalBw = new ArrayList<>();
174
175 private final ConfigFactory<LinkKey, TeLinkConfig> configFactory =
176 new ConfigFactory<LinkKey, TeLinkConfig>(SubjectFactories.LINK_SUBJECT_FACTORY,
177 TeLinkConfig.class, "teLinkConfig") {
178 @Override
179 public TeLinkConfig createConfig() {
180 return new TeLinkConfig();
181 }
182 };
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530183
Avantika-Huawei73862d42016-05-12 18:58:06 +0530184 /**
185 * Creates new instance of PceManager.
186 */
187 public PceManager() {
188 }
189
190 @Activate
191 protected void activate() {
192 appId = coreService.registerApplication(PCE_SERVICE_APP);
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530193
194 tunnelService.addListener(listener);
195
Avantika-Huawei73862d42016-05-12 18:58:06 +0530196 localLspIdIdGen = coreService.getIdGenerator(LOCAL_LSP_ID_GEN_TOPIC);
Avantika-Huaweif849aab2016-06-21 22:29:15 +0530197 localLspIdIdGen.getNewId(); // To prevent 0, the 1st value generated from being used in protocol.
Avantika-Huawei73862d42016-05-12 18:58:06 +0530198 localLspIdFreeList = storageService.<Short>setBuilder()
199 .withName("pcepLocalLspIdDeletedList")
200 .withSerializer(Serializer.using(KryoNamespaces.API))
201 .build()
202 .asDistributedSet();
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530203
Priyanka B3f92c5a2016-05-27 10:14:16 +0530204 topologyService.addListener(topologyListener);
Satish K2eb5d842017-04-04 16:28:37 +0530205 netConfigRegistry.registerConfigFactory(configFactory);
Mahesh Poojary Huawei1d17cad2016-06-02 12:53:41 +0530206
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530207 log.info("Started");
Avantika-Huawei73862d42016-05-12 18:58:06 +0530208 }
209
210 @Deactivate
211 protected void deactivate() {
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530212 tunnelService.removeListener(listener);
Priyanka B3f92c5a2016-05-27 10:14:16 +0530213 topologyService.removeListener(topologyListener);
Satish K2eb5d842017-04-04 16:28:37 +0530214 netConfigRegistry.unregisterConfigFactory(configFactory);
215
Avantika-Huawei73862d42016-05-12 18:58:06 +0530216 log.info("Stopped");
217 }
218
Priyanka Bb6963582016-05-20 20:21:20 +0530219 /**
220 * Returns an edge-weight capable of evaluating links on the basis of the
221 * specified constraints.
222 *
223 * @param constraints path constraints
224 * @return edge-weight function
225 */
Ray Milkey7483e1b2018-02-07 15:43:01 -0800226 private LinkWeigher weight(List<Constraint> constraints) {
Priyanka Bb6963582016-05-20 20:21:20 +0530227 return new TeConstraintBasedLinkWeight(constraints);
228 }
229
230 /**
231 * Computes a path between two devices.
232 *
233 * @param src ingress device
234 * @param dst egress device
235 * @param constraints path constraints
236 * @return computed path based on constraints
237 */
238 protected Set<Path> computePath(DeviceId src, DeviceId dst, List<Constraint> constraints) {
239 if (pathService == null) {
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530240 return ImmutableSet.of();
Priyanka Bb6963582016-05-20 20:21:20 +0530241 }
Priyanka Bbae0eeb12016-11-30 11:59:48 +0530242
Priyanka Bb6963582016-05-20 20:21:20 +0530243 Set<Path> paths = pathService.getPaths(src, dst, weight(constraints));
Priyanka Bbae0eeb12016-11-30 11:59:48 +0530244 log.info("paths in computePath ::" + paths);
Priyanka Bb6963582016-05-20 20:21:20 +0530245 if (!paths.isEmpty()) {
246 return paths;
247 }
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530248 return ImmutableSet.of();
Priyanka Bb6963582016-05-20 20:21:20 +0530249 }
250
Priyanka Bbae0eeb12016-11-30 11:59:48 +0530251 //Computes the partial path from partial computed path to specified dst.
252 private List<Path> computePartialPath(List<Path> computedPath, DeviceId src, DeviceId dst,
253 List<Constraint> constraints) {
254 int size = computedPath.size();
255 Path path = null;
256 DeviceId deviceId = size == 0 ? src :
257 computedPath.get(size - 1).dst().deviceId();
258
259 Set<Path> tempComputePath = computePath(deviceId, dst, constraints);
260
261 if (tempComputePath.isEmpty()) {
262 return null;
263 }
264
265 //if path validation fails return null
266 //Validate computed path to avoid loop in the path
267 for (Path p : tempComputePath) {
268 if (pathValidation(computedPath, p)) {
269 path = p;
270 break;
271 }
272 }
273 if (path == null) {
274 return null;
275 }
276
277 //Store the partial path result in a list
278 computedPath.add(path);
279 return computedPath;
280 }
281
282 private List<DeviceId> createListOfDeviceIds(List<? extends NetworkResource> list) {
283 List<Link> links = new LinkedList<>();
284 if (!list.isEmpty() && list.iterator().next() instanceof Path) {
285 for (Path path : (List<Path>) list) {
286 links.addAll(path.links());
287 }
288 } else if (!list.isEmpty() && list.iterator().next() instanceof Link) {
289 links.addAll((List<Link>) list);
290 }
291
292 //List of devices for new path computed
293 DeviceId source = null;
294 DeviceId destination = null;
295 List<DeviceId> devList = new LinkedList<>();
296
297 for (Link l : links) {
298 if (!devList.contains(l.src().deviceId())) {
299 devList.add(l.src().deviceId());
300 }
301 if (!devList.contains(l.dst().deviceId())) {
302 devList.add(l.dst().deviceId());
303 }
304 }
305
306 return devList;
307 }
308
Ray Milkeyc108a6b2017-08-23 15:23:50 -0700309 //To detect loops in the path i.e if the partial paths has intersection node avoid it.
Priyanka Bbae0eeb12016-11-30 11:59:48 +0530310 private boolean pathValidation(List<Path> partialPath, Path path) {
311
312 //List of devices in new path computed
313 List<DeviceId> newPartialPathDevList;
314 newPartialPathDevList = createListOfDeviceIds(path.links());
315
316 //List of devices in partial computed path
317 List<DeviceId> partialComputedPathDevList;
318 partialComputedPathDevList = createListOfDeviceIds(partialPath);
319
320 for (DeviceId deviceId : newPartialPathDevList) {
321 for (DeviceId devId : partialComputedPathDevList) {
322 if (!newPartialPathDevList.get(0).equals(deviceId) &&
323 !partialComputedPathDevList.get(partialComputedPathDevList.size() - 1).equals(devId)
324 && deviceId.equals(devId)) {
325 return false;
326 }
327 }
328 }
329 return true;
330 }
331
332 //Returns final computed explicit path (list of partial computed paths).
333 private List<Path> computeExplicitPath(List<ExplicitPathInfo> explicitPathInfo, DeviceId src, DeviceId dst,
334 List<Constraint> constraints) {
335 List<Path> finalComputedPath = new LinkedList<>();
336 for (ExplicitPathInfo info : explicitPathInfo) {
337 /*
338 * If explicit path object is LOOSE,
339 * 1) If specified as DeviceId (node) :
340 * If it is source , compute from source to destination (partial computation not required),
341 * otherwise compute from specified source to specified device
342 * 2) If specified as Link :
343 * Compute partial path from source to link's source , if path exists compute from link's source to dst
344 */
345 if (info.type().equals(ExplicitPathInfo.Type.LOOSE)) {
346 if (info.value() instanceof DeviceId) {
347 // If deviceId is source no need to compute
348 if (!(info.value()).equals(src)) {
349 log.debug("computeExplicitPath :: Loose , device");
350 finalComputedPath = computePartialPath(finalComputedPath, src, (DeviceId) info.value(),
351 constraints);
352 log.debug("finalComputedPath in computeExplicitPath ::" + finalComputedPath);
353 }
354
355 } else if (info.value() instanceof Link) {
356 if ((((Link) info.value()).src().deviceId().equals(src))
357 || (!finalComputedPath.isEmpty()
358 && finalComputedPath.get(finalComputedPath.size() - 1).dst().deviceId().equals(
359 ((Link) info.value()).src().deviceId()))) {
360
361 finalComputedPath = computePartialPath(finalComputedPath, src, ((Link) info.value()).dst()
362 .deviceId(), constraints);
363 } else {
364
365 finalComputedPath = computePartialPath(finalComputedPath, src, ((Link) info.value()).src()
366 .deviceId(), constraints) != null ? computePartialPath(finalComputedPath, src,
367 ((Link) info.value()).dst().deviceId(), constraints) : null;
368 }
369 }
370 /*
371 * If explicit path object is STRICT,
372 * 1) If specified as DeviceId (node) :
373 * Check whether partial computed path has reachable to strict specified node orde
374 * strict node is the source, if no set path as null else do nothing
375 * 2) If specified as Link :
376 * Check whether partial computed path has reachable to strict link's src, if yes compute
377 * path from strict link's src to link's dst (to include specified link)
378 */
379 } else if (info.type().equals(ExplicitPathInfo.Type.STRICT)) {
380 if (info.value() instanceof DeviceId) {
381 log.debug("computeExplicitPath :: Strict , device");
382 if (!(!finalComputedPath.isEmpty() && finalComputedPath.get(finalComputedPath.size() - 1).dst()
383 .deviceId().equals(info.value()))
384 && !info.value().equals(src)) {
385 finalComputedPath = null;
386 }
387
388 } else if (info.value() instanceof Link) {
389 log.info("computeExplicitPath :: Strict");
390 finalComputedPath = ((Link) info.value()).src().deviceId().equals(src)
391 || !finalComputedPath.isEmpty()
392 && finalComputedPath.get(finalComputedPath.size() - 1).dst().deviceId()
393 .equals(((Link) info.value()).src().deviceId()) ? computePartialPath(
394 finalComputedPath, src, ((Link) info.value()).dst().deviceId(), constraints) : null;
395
396 //Log.info("computeExplicitPath :: (Link) info.value() " + (Link) info.value());
397 //Log.info("computeExplicitPath :: finalComputedPath " + finalComputedPath);
398
399 if (finalComputedPath != null && !finalComputedPath.get(finalComputedPath.size() - 1).links()
Yuta HIGUCHI488a94c2018-01-26 17:24:09 -0800400 .contains(info.value())) {
Priyanka Bbae0eeb12016-11-30 11:59:48 +0530401 finalComputedPath = null;
402 }
403 }
404 }
405 if (finalComputedPath == null) {
406 return null;
407 }
408 }
409 // Destination is not reached in Partial computed path then compute till destination
410 if (finalComputedPath.isEmpty() || !finalComputedPath.isEmpty()
411 && !finalComputedPath.get(finalComputedPath.size() - 1).dst().deviceId().equals(dst)) {
412
413 finalComputedPath = computePartialPath(finalComputedPath, src, dst, constraints);
414 if (finalComputedPath == null) {
415 return null;
416 }
417 }
418
419 return finalComputedPath;
420 }
421
Priyanka Ba32f6da2016-09-02 16:10:21 +0530422 @Override
423 public boolean setupPath(DeviceId src, DeviceId dst, String tunnelName, List<Constraint> constraints,
Priyankab-Huawei3946d732016-10-11 06:24:38 +0000424 LspType lspType) {
Satish Kba1c9122017-04-05 15:27:23 +0530425 return setupPath(src, dst, tunnelName, constraints, lspType, null, false);
Priyanka Bbae0eeb12016-11-30 11:59:48 +0530426 }
427
428 //[TODO:] handle requests in queue
429 @Override
430 public boolean setupPath(DeviceId src, DeviceId dst, String tunnelName, List<Constraint> constraints,
431 LspType lspType, List<ExplicitPathInfo> explicitPathInfo) {
Satish Kba1c9122017-04-05 15:27:23 +0530432 return setupPath(src, dst, tunnelName, constraints, lspType, explicitPathInfo, false);
433
434 }
435
436 @Override
437 public boolean setupPath(DeviceId src, DeviceId dst, String tunnelName, List<Constraint> constraints,
438 LspType lspType, boolean loadBalancing) {
439 return setupPath(src, dst, tunnelName, constraints, lspType, null, loadBalancing);
440 }
441
442 @Override
443 public boolean setupPath(DeviceId src, DeviceId dst, String tunnelName, List<Constraint> constraints,
444 LspType lspType, List<ExplicitPathInfo> explicitPathInfo, boolean loadBalancing) {
Avantika-Huawei73862d42016-05-12 18:58:06 +0530445 checkNotNull(src);
446 checkNotNull(dst);
447 checkNotNull(tunnelName);
Avantika-Huawei73862d42016-05-12 18:58:06 +0530448 checkNotNull(lspType);
449
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530450 // Convert from DeviceId to TunnelEndPoint
451 Device srcDevice = deviceService.getDevice(src);
452 Device dstDevice = deviceService.getDevice(dst);
Avantika-Huawei73862d42016-05-12 18:58:06 +0530453
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530454 if (srcDevice == null || dstDevice == null) {
455 // Device is not known.
Satish Kba1c9122017-04-05 15:27:23 +0530456 pceStore.addFailedPathInfo(new PcePathInfo(src, dst, tunnelName, constraints, lspType, explicitPathInfo,
457 loadBalancing));
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530458 return false;
459 }
460
461 // In future projections instead of annotations will be used to fetch LSR ID.
462 String srcLsrId = srcDevice.annotations().value(LSRID);
463 String dstLsrId = dstDevice.annotations().value(LSRID);
464
465 if (srcLsrId == null || dstLsrId == null) {
466 // LSR id is not known.
Satish Kba1c9122017-04-05 15:27:23 +0530467 pceStore.addFailedPathInfo(new PcePathInfo(src, dst, tunnelName, constraints, lspType, explicitPathInfo,
468 loadBalancing));
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530469 return false;
470 }
471
Avantika-Huawei032a9872016-05-27 22:57:38 +0530472 // Get device config from netconfig, to ascertain that session with ingress is present.
473 DeviceCapability cfg = netCfgService.getConfig(DeviceId.deviceId(srcLsrId), DeviceCapability.class);
474 if (cfg == null) {
475 log.debug("No session to ingress.");
Satish Kba1c9122017-04-05 15:27:23 +0530476 pceStore.addFailedPathInfo(new PcePathInfo(src, dst, tunnelName, constraints, lspType, explicitPathInfo,
477 loadBalancing));
Avantika-Huawei032a9872016-05-27 22:57:38 +0530478 return false;
479 }
480
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530481 TunnelEndPoint srcEndPoint = IpTunnelEndPoint.ipTunnelPoint(IpAddress.valueOf(srcLsrId));
482 TunnelEndPoint dstEndPoint = IpTunnelEndPoint.ipTunnelPoint(IpAddress.valueOf(dstLsrId));
483
484 double bwConstraintValue = 0;
485 CostConstraint costConstraint = null;
486 if (constraints != null) {
487 constraints.add(CapabilityConstraint.of(CapabilityType.valueOf(lspType.name())));
488 Iterator<Constraint> iterator = constraints.iterator();
489
490 while (iterator.hasNext()) {
491 Constraint constraint = iterator.next();
Satish K2eb5d842017-04-04 16:28:37 +0530492 if (constraint instanceof PceBandwidthConstraint) {
493 bwConstraintValue = ((PceBandwidthConstraint) constraint).bandwidth().bps();
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530494 } else if (constraint instanceof CostConstraint) {
495 costConstraint = (CostConstraint) constraint;
496 }
497 }
498
499 /*
500 * Add cost at the end of the list of constraints. The path computation algorithm also computes cumulative
501 * cost. The function which checks the limiting/capability constraints also returns per link cost. This
502 * function can either return the result of limiting/capability constraint validation or the value of link
503 * cost, depending upon what is the last constraint in the loop.
504 */
505 if (costConstraint != null) {
506 constraints.remove(costConstraint);
507 constraints.add(costConstraint);
508 }
509 } else {
510 constraints = new LinkedList<>();
511 constraints.add(CapabilityConstraint.of(CapabilityType.valueOf(lspType.name())));
512 }
Priyanka Bbae0eeb12016-11-30 11:59:48 +0530513 Set<Path> computedPathSet = Sets.newLinkedHashSet();
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530514
Satish Kba1c9122017-04-05 15:27:23 +0530515 if (loadBalancing) {
516 return setupDisjointPaths(src, dst, constraints, tunnelName, bwConstraintValue, lspType, costConstraint,
517 srcEndPoint, dstEndPoint);
518 }
519
Priyanka Bbae0eeb12016-11-30 11:59:48 +0530520 if (explicitPathInfo != null && !explicitPathInfo.isEmpty()) {
521 List<Path> finalComputedPath = computeExplicitPath(explicitPathInfo, src, dst, constraints);
522 if (finalComputedPath == null) {
523 return false;
524 }
525
526 pceStore.tunnelNameExplicitPathInfoMap(tunnelName, explicitPathInfo);
527 List<Link> links = new LinkedList<>();
528 double totalCost = 0;
529 // Add all partial computed paths
530 for (Path path : finalComputedPath) {
531 links.addAll(path.links());
532 totalCost = totalCost + path.cost();
533 }
Ray Milkeya7cf8c82018-02-08 15:07:06 -0800534 computedPathSet.add(new DefaultPath(finalComputedPath.iterator().next().providerId(), links,
535 ScalarWeight.toWeight(totalCost)));
Priyanka Bbae0eeb12016-11-30 11:59:48 +0530536 } else {
537 computedPathSet = computePath(src, dst, constraints);
538 }
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530539
540 // NO-PATH
541 if (computedPathSet.isEmpty()) {
Satish Kba1c9122017-04-05 15:27:23 +0530542 pceStore.addFailedPathInfo(new PcePathInfo(src, dst, tunnelName, constraints, lspType, explicitPathInfo,
543 loadBalancing));
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530544 return false;
545 }
546
547 Builder annotationBuilder = DefaultAnnotations.builder();
548 if (bwConstraintValue != 0) {
549 annotationBuilder.set(BANDWIDTH, String.valueOf(bwConstraintValue));
550 }
551 if (costConstraint != null) {
552 annotationBuilder.set(COST_TYPE, String.valueOf(costConstraint.type()));
553 }
554 annotationBuilder.set(LSP_SIG_TYPE, lspType.name());
555 annotationBuilder.set(PCE_INIT, TRUE);
556 annotationBuilder.set(DELEGATE, TRUE);
557
558 Path computedPath = computedPathSet.iterator().next();
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530559
560 if (lspType != WITH_SIGNALLING) {
561 /*
562 * Local LSP id which is assigned by RSVP for RSVP signalled LSPs, will be assigned by
563 * PCE for non-RSVP signalled LSPs.
564 */
565 annotationBuilder.set(LOCAL_LSP_ID, String.valueOf(getNextLocalLspId()));
566 }
567
568 // For SR-TE tunnels, call SR manager for label stack and put it inside tunnel.
569 Tunnel tunnel = new DefaultTunnel(null, srcEndPoint, dstEndPoint, MPLS, INIT, null, null,
570 TunnelName.tunnelName(tunnelName), computedPath,
Avantika-Huawei9e848e82016-09-01 12:12:42 +0530571 annotationBuilder.build());
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530572
Satish K2eb5d842017-04-04 16:28:37 +0530573 // Allocate bandwidth for all tunnels.
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530574 if (bwConstraintValue != 0) {
Satish K2eb5d842017-04-04 16:28:37 +0530575 if (!reserveBandwidth(computedPath, bwConstraintValue, null)) {
Priyanka Bbae0eeb12016-11-30 11:59:48 +0530576 pceStore.addFailedPathInfo(new PcePathInfo(src, dst, tunnelName, constraints,
Satish Kba1c9122017-04-05 15:27:23 +0530577 lspType, explicitPathInfo, loadBalancing));
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530578 return false;
579 }
580 }
581
582 TunnelId tunnelId = tunnelService.setupTunnel(appId, src, tunnel, computedPath);
583 if (tunnelId == null) {
Satish Kba1c9122017-04-05 15:27:23 +0530584 pceStore.addFailedPathInfo(new PcePathInfo(src, dst, tunnelName, constraints, lspType, explicitPathInfo,
585 loadBalancing));
Satish K2eb5d842017-04-04 16:28:37 +0530586
587 if (bwConstraintValue != 0) {
588 computedPath.links().forEach(ln -> bandwidthMgmtService.releaseLocalReservedBw(LinkKey.linkKey(ln),
589 Double.parseDouble(tunnel.annotations().value(BANDWIDTH))));
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530590 }
Satish K2eb5d842017-04-04 16:28:37 +0530591
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530592 return false;
593 }
594
Satish K2eb5d842017-04-04 16:28:37 +0530595 if (bwConstraintValue != 0 && lspType == WITH_SIGNALLING) {
596 rsvpTunnelsWithLocalBw.add(tunnelId);
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530597 }
Satish K2eb5d842017-04-04 16:28:37 +0530598
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530599 return true;
600 }
Avantika-Huawei73862d42016-05-12 18:58:06 +0530601
Satish Kba1c9122017-04-05 15:27:23 +0530602 private boolean setupDisjointPaths(DeviceId src, DeviceId dst, List<Constraint> constraints, String tunnelName,
603 double bwConstraintValue, LspType lspType, CostConstraint costConstraint,
604 TunnelEndPoint srcEndPoint, TunnelEndPoint dstEndPoint) {
605 Set<DisjointPath> paths = pathService.getDisjointPaths(src, dst, weight(constraints));
606
607 // NO-PATH
608 if (paths.isEmpty()) {
609 pceStore.addFailedPathInfo(new PcePathInfo(src, dst, tunnelName, constraints, lspType, null, true));
610 return false;
611 }
612
Ray Milkey74e59132018-01-17 15:24:52 -0800613 DisjointPath path = paths.iterator().next();
Satish Kba1c9122017-04-05 15:27:23 +0530614
615 Builder annotationBuilder = DefaultAnnotations.builder();
616 double bw = 0;
617 if (bwConstraintValue != 0) {
618 //TODO: BW needs to be divided by 2 :: bwConstraintValue/2
619 bw = bwConstraintValue / 2;
620 annotationBuilder.set(BANDWIDTH, String.valueOf(bw));
621 }
622 if (costConstraint != null) {
623 annotationBuilder.set(COST_TYPE, String.valueOf(costConstraint.type()));
624 }
625 annotationBuilder.set(LSP_SIG_TYPE, lspType.name());
626 annotationBuilder.set(PCE_INIT, TRUE);
627 annotationBuilder.set(DELEGATE, TRUE);
628 annotationBuilder.set(LOAD_BALANCING_PATH_NAME, tunnelName);
629
630 //Path computedPath = computedPathSet.iterator().next();
631
632 if (lspType != WITH_SIGNALLING) {
633 /*
634 * Local LSP id which is assigned by RSVP for RSVP signalled LSPs, will be assigned by
635 * PCE for non-RSVP signalled LSPs.
636 */
637 annotationBuilder.set(LOCAL_LSP_ID, String.valueOf(getNextLocalLspId()));
638 }
639
640 //Generate different tunnel name for disjoint paths
641 String tunnel1 = (new StringBuilder()).append(tunnelName).append("_1").toString();
642 String tunnel2 = (new StringBuilder()).append(tunnelName).append("_2").toString();
643
644 // For SR-TE tunnels, call SR manager for label stack and put it inside tunnel.
645 Tunnel tunnelPrimary = new DefaultTunnel(null, srcEndPoint, dstEndPoint, MPLS, INIT, null, null,
646 TunnelName.tunnelName(tunnel1), path.primary(),
647 annotationBuilder.build());
648
649 Tunnel tunnelBackup = new DefaultTunnel(null, srcEndPoint, dstEndPoint, MPLS, INIT, null, null,
650 TunnelName.tunnelName(tunnel2), path.backup(),
651 annotationBuilder.build());
652
653 // Allocate bandwidth.
654 if (bwConstraintValue != 0) {
655 if (!reserveBandwidth(path.primary(), bw, null)) {
656 pceStore.addFailedPathInfo(new PcePathInfo(src, dst, tunnel1, constraints,
657 lspType, null, true));
658 return false;
659 }
660
661 if (!reserveBandwidth(path.backup(), bw, null)) {
662 //Release bandwidth resource for tunnel1
663 if (bwConstraintValue != 0) {
664 path.primary().links().forEach(ln ->
665 bandwidthMgmtService.releaseLocalReservedBw(LinkKey.linkKey(ln),
666 Double.parseDouble(tunnelPrimary.annotations().value(BANDWIDTH))));
667 }
668
669 pceStore.addFailedPathInfo(new PcePathInfo(src, dst, tunnel2, constraints,
670 lspType, null, true));
671 return false;
672 }
673 }
674
675 TunnelId tunnelId1 = tunnelService.setupTunnel(appId, src, tunnelPrimary, path.primary());
676 if (tunnelId1 == null) {
677 pceStore.addFailedPathInfo(new PcePathInfo(src, dst, tunnelName, constraints, lspType, null, true));
678
679 if (bwConstraintValue != 0) {
680 path.primary().links().forEach(ln -> bandwidthMgmtService.releaseLocalReservedBw(LinkKey.linkKey(ln),
681 Double.parseDouble(tunnelPrimary.annotations().value(BANDWIDTH))));
682 }
683
684 return false;
685 }
686
687 TunnelId tunnelId2 = tunnelService.setupTunnel(appId, src, tunnelBackup, path.backup());
688 if (tunnelId2 == null) {
689 //Release 1st tunnel
rohitsharan483bed42017-04-12 19:04:57 +0530690 releasePath(tunnelId1);
Satish Kba1c9122017-04-05 15:27:23 +0530691
692 pceStore.addFailedPathInfo(new PcePathInfo(src, dst, tunnelName, constraints, lspType, null, true));
693
694 if (bwConstraintValue != 0) {
695 path.backup().links().forEach(ln -> bandwidthMgmtService.releaseLocalReservedBw(LinkKey.linkKey(ln),
696 Double.parseDouble(tunnelBackup.annotations().value(BANDWIDTH))));
697 }
698
699 return false;
700 }
701
702 pceStore.addLoadBalancingTunnelIdsInfo(tunnelName, tunnelId1, tunnelId2);
703 //pceStore.addDisjointPathInfo(tunnelName, path);
704 return true;
705 }
706
Avantika-Huawei73862d42016-05-12 18:58:06 +0530707 @Override
708 public boolean updatePath(TunnelId tunnelId, List<Constraint> constraints) {
709 checkNotNull(tunnelId);
Priyanka Bbae0eeb12016-11-30 11:59:48 +0530710 Set<Path> computedPathSet = Sets.newLinkedHashSet();
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530711 Tunnel tunnel = tunnelService.queryTunnel(tunnelId);
Avantika-Huawei73862d42016-05-12 18:58:06 +0530712
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530713 if (tunnel == null) {
714 return false;
715 }
Avantika-Huawei73862d42016-05-12 18:58:06 +0530716
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530717 if (tunnel.type() != MPLS || FALSE.equalsIgnoreCase(tunnel.annotations().value(DELEGATE))) {
718 // Only delegated LSPs can be updated.
719 return false;
720 }
721
722 List<Link> links = tunnel.path().links();
723 String lspSigType = tunnel.annotations().value(LSP_SIG_TYPE);
724 double bwConstraintValue = 0;
Priyanka B3f92c5a2016-05-27 10:14:16 +0530725 String costType = null;
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530726 SharedBandwidthConstraint shBwConstraint = null;
Satish K2eb5d842017-04-04 16:28:37 +0530727 PceBandwidthConstraint bwConstraint = null;
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530728 CostConstraint costConstraint = null;
729
730 if (constraints != null) {
731 // Call path computation in shared bandwidth mode.
732 Iterator<Constraint> iterator = constraints.iterator();
733 while (iterator.hasNext()) {
734 Constraint constraint = iterator.next();
Satish K2eb5d842017-04-04 16:28:37 +0530735 if (constraint instanceof PceBandwidthConstraint) {
736 bwConstraint = (PceBandwidthConstraint) constraint;
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530737 bwConstraintValue = bwConstraint.bandwidth().bps();
738 } else if (constraint instanceof CostConstraint) {
739 costConstraint = (CostConstraint) constraint;
Avantika-Huawei032a9872016-05-27 22:57:38 +0530740 costType = costConstraint.type().name();
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530741 }
742 }
743
744 // Remove and keep the cost constraint at the end of the list of constraints.
745 if (costConstraint != null) {
746 constraints.remove(costConstraint);
747 }
748
749 Bandwidth existingBwValue = null;
750 String existingBwAnnotation = tunnel.annotations().value(BANDWIDTH);
751 if (existingBwAnnotation != null) {
752 existingBwValue = Bandwidth.bps(Double.parseDouble(existingBwAnnotation));
753
754 /*
755 * The computation is a shared bandwidth constraint based, so need to remove bandwidth constraint which
756 * has been utilized to create shared bandwidth constraint.
757 */
758 if (bwConstraint != null) {
759 constraints.remove(bwConstraint);
760 }
761 }
762
763 if (existingBwValue != null) {
Priyanka B3fdb9dd2016-08-08 10:47:24 +0530764 if (bwConstraint == null) {
Priyanka B4c3cef02016-06-14 20:27:53 +0530765 bwConstraintValue = existingBwValue.bps();
766 }
767 //If bandwidth constraints not specified , take existing bandwidth for shared bandwidth calculation
768 shBwConstraint = bwConstraint != null ? new SharedBandwidthConstraint(links,
769 existingBwValue, bwConstraint.bandwidth()) : new SharedBandwidthConstraint(links,
770 existingBwValue, existingBwValue);
771
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530772 constraints.add(shBwConstraint);
773 }
774 } else {
775 constraints = new LinkedList<>();
776 }
777
778 constraints.add(CapabilityConstraint.of(CapabilityType.valueOf(lspSigType)));
779 if (costConstraint != null) {
780 constraints.add(costConstraint);
Priyanka B3fdb9dd2016-08-08 10:47:24 +0530781 } else {
782 //Take cost constraint from old tunnel if it is not specified in update flow
783 costType = tunnel.annotations().value(COST_TYPE);
784 costConstraint = CostConstraint.of(CostConstraint.Type.valueOf(costType));
785 constraints.add(costConstraint);
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530786 }
787
Priyanka Bbae0eeb12016-11-30 11:59:48 +0530788 List<ExplicitPathInfo> explicitPathInfo = pceStore
789 .getTunnelNameExplicitPathInfoMap(tunnel.tunnelName().value());
790 if (explicitPathInfo != null) {
791 List<Path> finalComputedPath = computeExplicitPath(explicitPathInfo,
792 tunnel.path().src().deviceId(), tunnel.path().dst().deviceId(),
793 constraints);
794
795 if (finalComputedPath == null) {
796 return false;
797 }
798
799 List<Link> totalLinks = new LinkedList<>();
800 double totalCost = 0;
801 //Add all partial computed paths
802 for (Path path : finalComputedPath) {
803 totalLinks.addAll(path.links());
804 totalCost = totalCost + path.cost();
805 }
806 computedPathSet.add(new DefaultPath(finalComputedPath.iterator().next().providerId(),
Ray Milkeya7cf8c82018-02-08 15:07:06 -0800807 totalLinks, ScalarWeight.toWeight(totalCost)));
Priyanka Bbae0eeb12016-11-30 11:59:48 +0530808 } else {
809 computedPathSet = computePath(tunnel.path().src().deviceId(), tunnel.path().dst().deviceId(),
810 constraints);
811 }
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530812
813 // NO-PATH
814 if (computedPathSet.isEmpty()) {
815 return false;
816 }
817
818 Builder annotationBuilder = DefaultAnnotations.builder();
819 annotationBuilder.set(BANDWIDTH, String.valueOf(bwConstraintValue));
Priyanka B3f92c5a2016-05-27 10:14:16 +0530820 if (costType != null) {
821 annotationBuilder.set(COST_TYPE, costType);
822 }
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530823 annotationBuilder.set(LSP_SIG_TYPE, lspSigType);
824 annotationBuilder.set(PCE_INIT, TRUE);
825 annotationBuilder.set(DELEGATE, TRUE);
826 annotationBuilder.set(PLSP_ID, tunnel.annotations().value(PLSP_ID));
827 annotationBuilder.set(PCC_TUNNEL_ID, tunnel.annotations().value(PCC_TUNNEL_ID));
828
829 Path computedPath = computedPathSet.iterator().next();
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530830 LspType lspType = LspType.valueOf(lspSigType);
831 long localLspId = 0;
832 if (lspType != WITH_SIGNALLING) {
833 /*
834 * Local LSP id which is assigned by RSVP for RSVP signalled LSPs, will be assigned by
835 * PCE for non-RSVP signalled LSPs.
836 */
837 localLspId = getNextLocalLspId();
838 annotationBuilder.set(LOCAL_LSP_ID, String.valueOf(localLspId));
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530839 }
840
841 Tunnel updatedTunnel = new DefaultTunnel(null, tunnel.src(), tunnel.dst(), MPLS, INIT, null, null,
842 tunnel.tunnelName(), computedPath,
Avantika-Huawei9e848e82016-09-01 12:12:42 +0530843 annotationBuilder.build());
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530844
Satish K2eb5d842017-04-04 16:28:37 +0530845 // Allocate shared bandwidth for all tunnels.
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530846 if (bwConstraintValue != 0) {
Satish K2eb5d842017-04-04 16:28:37 +0530847 if (!reserveBandwidth(computedPath, bwConstraintValue, shBwConstraint)) {
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530848 return false;
849 }
850 }
851
852 TunnelId updatedTunnelId = tunnelService.setupTunnel(appId, links.get(0).src().deviceId(), updatedTunnel,
853 computedPath);
854
855 if (updatedTunnelId == null) {
Satish K2eb5d842017-04-04 16:28:37 +0530856 if (bwConstraintValue != 0) {
857 releaseSharedBwForNewTunnel(computedPath, bwConstraintValue, shBwConstraint);
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530858 }
859 return false;
860 }
861
Satish K2eb5d842017-04-04 16:28:37 +0530862 if (bwConstraintValue != 0 && lspType == WITH_SIGNALLING) {
863 rsvpTunnelsWithLocalBw.add(updatedTunnelId);
Avantika-Huawei3c2d3eb2016-06-22 09:34:00 +0530864 }
865
Avantika-Huawei73862d42016-05-12 18:58:06 +0530866 return true;
867 }
868
869 @Override
870 public boolean releasePath(TunnelId tunnelId) {
871 checkNotNull(tunnelId);
872 // 1. Query Tunnel from Tunnel manager.
873 Tunnel tunnel = tunnelService.queryTunnel(tunnelId);
874
875 if (tunnel == null) {
876 return false;
877 }
878
879 // 2. Call tunnel service.
880 return tunnelService.downTunnel(appId, tunnel.tunnelId());
881 }
882
883 @Override
Satish Kba1c9122017-04-05 15:27:23 +0530884 public boolean releasePath(String loadBalancingPathName) {
885 checkNotNull(loadBalancingPathName);
886
887 List<TunnelId> tunnelIds = pceStore.getLoadBalancingTunnelIds(loadBalancingPathName);
888 if (tunnelIds != null && !tunnelIds.isEmpty()) {
889 for (TunnelId id : tunnelIds) {
890 if (!tunnelService.downTunnel(appId, id)) {
891 return false;
892 }
893 }
894
895 //pceStore.removeDisjointPathInfo(loadBalancedPathName);
896 pceStore.removeLoadBalancingTunnelIdsInfo(loadBalancingPathName);
897 return true;
898 }
899
900 return false;
901 }
902
903 @Override
Avantika-Huawei73862d42016-05-12 18:58:06 +0530904 public Iterable<Tunnel> queryAllPath() {
905 return tunnelService.queryTunnel(MPLS);
906 }
907
908 @Override
909 public Tunnel queryPath(TunnelId tunnelId) {
910 return tunnelService.queryTunnel(tunnelId);
911 }
912
Satish K2eb5d842017-04-04 16:28:37 +0530913 private boolean releaseSharedBwForNewTunnel(Path computedPath, double bandwidthConstraint,
914 SharedBandwidthConstraint shBwConstraint) {
915 checkNotNull(computedPath);
Satish K2eb5d842017-04-04 16:28:37 +0530916 double bwToAllocate;
917
918 Double additionalBwValue = null;
919 if (shBwConstraint != null) {
920 additionalBwValue = ((bandwidthConstraint - shBwConstraint.sharedBwValue().bps()) <= 0) ? null
921 : (bandwidthConstraint - shBwConstraint.sharedBwValue().bps());
922 }
923
924 for (Link link : computedPath.links()) {
925 bwToAllocate = 0;
926 if ((shBwConstraint != null) && (shBwConstraint.links().contains(link))) {
927 if (additionalBwValue != null) {
928 bwToAllocate = additionalBwValue;
929 }
930 } else {
931 bwToAllocate = bandwidthConstraint;
932 }
933
934 if (bwToAllocate != 0) {
935 bandwidthMgmtService.releaseLocalReservedBw(LinkKey.linkKey(link), bwToAllocate);
936 }
937 }
938 return true;
939 }
940
Avantika-Huawei73862d42016-05-12 18:58:06 +0530941 /**
942 * Returns the next local LSP identifier to be used either by getting from
943 * freed list if available otherwise generating a new one.
944 *
945 * @return value of local LSP identifier
946 */
Priyanka B4c3b4512016-07-22 11:41:49 +0530947 private synchronized short getNextLocalLspId() {
Avantika-Huawei73862d42016-05-12 18:58:06 +0530948 // If there is any free id use it. Otherwise generate new id.
949 if (localLspIdFreeList.isEmpty()) {
950 return (short) localLspIdIdGen.getNewId();
951 }
952 Iterator<Short> it = localLspIdFreeList.iterator();
953 Short value = it.next();
954 localLspIdFreeList.remove(value);
955 return value;
956 }
957
Ray Milkey7483e1b2018-02-07 15:43:01 -0800958 protected class TeConstraintBasedLinkWeight implements LinkWeigher {
Priyanka Bb6963582016-05-20 20:21:20 +0530959
960 private final List<Constraint> constraints;
961
962 /**
963 * Creates a new edge-weight function capable of evaluating links
964 * on the basis of the specified constraints.
965 *
966 * @param constraints path constraints
967 */
968 public TeConstraintBasedLinkWeight(List<Constraint> constraints) {
969 if (constraints == null) {
970 this.constraints = Collections.emptyList();
971 } else {
972 this.constraints = ImmutableList.copyOf(constraints);
973 }
974 }
975
976 @Override
Ray Milkey7483e1b2018-02-07 15:43:01 -0800977 public Weight getInitialWeight() {
978 return ScalarWeight.toWeight(0.0);
979 }
980
981 @Override
982 public Weight getNonViableWeight() {
983 return ScalarWeight.toWeight(0.0);
984 }
985
986 @Override
987 public Weight weight(TopologyEdge edge) {
Priyanka Bb6963582016-05-20 20:21:20 +0530988 if (!constraints.iterator().hasNext()) {
989 //Takes default cost/hopcount as 1 if no constraints specified
Ray Milkey7483e1b2018-02-07 15:43:01 -0800990 return ScalarWeight.toWeight(1.0);
Priyanka Bb6963582016-05-20 20:21:20 +0530991 }
992
993 Iterator<Constraint> it = constraints.iterator();
994 double cost = 1;
995
996 //If any constraint fails return -1 also value of cost returned from cost constraint can't be negative
997 while (it.hasNext() && cost > 0) {
998 Constraint constraint = it.next();
999 if (constraint instanceof CapabilityConstraint) {
Avantika-Huawei032a9872016-05-27 22:57:38 +05301000 cost = ((CapabilityConstraint) constraint).isValidLink(edge.link(), deviceService,
1001 netCfgService) ? 1 : -1;
Satish K2eb5d842017-04-04 16:28:37 +05301002 } else if (constraint instanceof PceBandwidthConstraint) {
1003 cost = ((PceBandwidthConstraint) constraint).isValidLink(edge.link(),
1004 bandwidthMgmtService) ? 1 : -1;
1005 } else if (constraint instanceof SharedBandwidthConstraint) {
1006 cost = ((SharedBandwidthConstraint) constraint).isValidLink(edge.link(),
1007 bandwidthMgmtService) ? 1 : -1;
1008 } else if (constraint instanceof CostConstraint) {
1009 cost = ((CostConstraint) constraint).isValidLink(edge.link(), netCfgService);
Priyanka Bb6963582016-05-20 20:21:20 +05301010 } else {
Satish K2eb5d842017-04-04 16:28:37 +05301011 cost = constraint.cost(edge.link(), null);
Priyanka Bb6963582016-05-20 20:21:20 +05301012 }
1013 }
Ray Milkey7483e1b2018-02-07 15:43:01 -08001014 return ScalarWeight.toWeight(cost);
Priyanka Bb6963582016-05-20 20:21:20 +05301015 }
1016 }
Avantika-Huaweidbdf7722016-05-21 14:20:31 +05301017
Priyanka B3f92c5a2016-05-27 10:14:16 +05301018 //TODO: annotations used for temporarily later projection/network config will be used
1019 private class InternalTopologyListener implements TopologyListener {
1020 @Override
1021 public void event(TopologyEvent event) {
1022 event.reasons().forEach(e -> {
1023 //If event type is link removed, get the impacted tunnel
1024 if (e instanceof LinkEvent) {
1025 LinkEvent linkEvent = (LinkEvent) e;
1026 if (linkEvent.type() == LinkEvent.Type.LINK_REMOVED) {
1027 tunnelService.queryTunnel(MPLS).forEach(t -> {
Avantika-Huaweid1e36bd2016-05-26 12:47:16 +05301028 if (t.path().links().contains((e.subject()))) {
Priyanka B3f92c5a2016-05-27 10:14:16 +05301029 // Check whether this ONOS instance is master for ingress device if yes,
1030 // recompute and send update
1031 checkForMasterAndUpdateTunnel(t.path().src().deviceId(), t);
1032 }
1033 });
1034 }
1035 }
1036 });
1037 }
1038 }
Avantika-Huaweidbdf7722016-05-21 14:20:31 +05301039
Priyanka B3f92c5a2016-05-27 10:14:16 +05301040 private boolean checkForMasterAndUpdateTunnel(DeviceId src, Tunnel tunnel) {
1041 /**
1042 * Master of ingress node will recompute and also delegation flag must be set.
1043 */
1044 if (mastershipService.isLocalMaster(src)
1045 && Boolean.valueOf(tunnel.annotations().value(DELEGATE)) != null) {
1046 LinkedList<Constraint> constraintList = new LinkedList<>();
1047
1048 if (tunnel.annotations().value(BANDWIDTH) != null) {
1049 //Requested bandwidth will be same as previous allocated bandwidth for the tunnel
Satish K2eb5d842017-04-04 16:28:37 +05301050 PceBandwidthConstraint localConst = new PceBandwidthConstraint(Bandwidth.bps(Double.parseDouble(tunnel
Priyanka B3f92c5a2016-05-27 10:14:16 +05301051 .annotations().value(BANDWIDTH))));
1052 constraintList.add(localConst);
1053 }
1054 if (tunnel.annotations().value(COST_TYPE) != null) {
1055 constraintList.add(CostConstraint.of(CostConstraint.Type.valueOf(tunnel.annotations().value(
1056 COST_TYPE))));
1057 }
Priyanka B9fa4ed32016-05-27 11:59:24 +05301058
1059 /*
1060 * If tunnel was UP after recomputation failed then store failed path in PCE store send PCIntiate(remove)
1061 * and If tunnel is failed and computation fails nothing to do because tunnel status will be same[Failed]
1062 */
1063 if (!updatePath(tunnel.tunnelId(), constraintList) && !tunnel.state().equals(Tunnel.State.FAILED)) {
Priyanka B3f92c5a2016-05-27 10:14:16 +05301064 // If updation fails store in PCE store as failed path
1065 // then PCInitiate (Remove)
1066 pceStore.addFailedPathInfo(new PcePathInfo(tunnel.path().src().deviceId(), tunnel
1067 .path().dst().deviceId(), tunnel.tunnelName().value(), constraintList,
Priyanka Bbae0eeb12016-11-30 11:59:48 +05301068 LspType.valueOf(tunnel.annotations().value(LSP_SIG_TYPE)),
Satish Kba1c9122017-04-05 15:27:23 +05301069 pceStore.getTunnelNameExplicitPathInfoMap(tunnel.tunnelName().value()),
1070 tunnel.annotations().value(LOAD_BALANCING_PATH_NAME) != null ? true : false));
Priyanka B3f92c5a2016-05-27 10:14:16 +05301071 //Release that tunnel calling PCInitiate
1072 releasePath(tunnel.tunnelId());
1073 }
1074 }
1075
1076 return false;
1077 }
1078
1079 // Allocates the bandwidth locally for PCECC tunnels.
Satish K2eb5d842017-04-04 16:28:37 +05301080 private boolean reserveBandwidth(Path computedPath, double bandwidthConstraint,
Avantika-Huaweidbdf7722016-05-21 14:20:31 +05301081 SharedBandwidthConstraint shBwConstraint) {
1082 checkNotNull(computedPath);
Avantika-Huaweidbdf7722016-05-21 14:20:31 +05301083 Resource resource = null;
1084 double bwToAllocate = 0;
Satish K2eb5d842017-04-04 16:28:37 +05301085 Map<Link, Double> linkMap = new HashMap<>();
Avantika-Huaweidbdf7722016-05-21 14:20:31 +05301086
1087 /**
1088 * Shared bandwidth sub-case : Lesser bandwidth required than original -
1089 * No reservation required.
1090 */
1091 Double additionalBwValue = null;
1092 if (shBwConstraint != null) {
1093 additionalBwValue = ((bandwidthConstraint - shBwConstraint.sharedBwValue().bps()) <= 0) ? null
1094 : (bandwidthConstraint - shBwConstraint.sharedBwValue().bps());
1095 }
1096
1097 Optional<ResourceAllocation> resAlloc = null;
1098 for (Link link : computedPath.links()) {
1099 bwToAllocate = 0;
1100 if ((shBwConstraint != null) && (shBwConstraint.links().contains(link))) {
1101 if (additionalBwValue != null) {
Priyanka B4c3b4512016-07-22 11:41:49 +05301102 bwToAllocate = additionalBwValue;
Avantika-Huaweidbdf7722016-05-21 14:20:31 +05301103 }
1104 } else {
1105 bwToAllocate = bandwidthConstraint;
1106 }
1107
1108 /**
1109 * In shared bandwidth cases, where new BW is lesser than old BW, it
1110 * is not required to allocate anything.
1111 */
1112 if (bwToAllocate != 0) {
Satish K2eb5d842017-04-04 16:28:37 +05301113 if (!bandwidthMgmtService.allocLocalReservedBw(LinkKey.linkKey(link.src(), link.dst()),
1114 bwToAllocate)) {
1115 // If allocation for any link fails, then release the partially allocated bandwidth
1116 // for all links allocated
1117 linkMap.forEach((ln, aDouble) -> bandwidthMgmtService
1118 .releaseLocalReservedBw(LinkKey.linkKey(ln), aDouble));
1119 return false;
Avantika-Huaweidbdf7722016-05-21 14:20:31 +05301120 }
Satish K2eb5d842017-04-04 16:28:37 +05301121
1122 linkMap.put(link, bwToAllocate);
Avantika-Huaweidbdf7722016-05-21 14:20:31 +05301123 }
1124 }
1125
Satish K2eb5d842017-04-04 16:28:37 +05301126 return true;
Avantika-Huaweidbdf7722016-05-21 14:20:31 +05301127 }
1128
1129 /*
1130 * Deallocates the bandwidth which is reserved locally for PCECC tunnels.
1131 */
1132 private void releaseBandwidth(Tunnel tunnel) {
1133 // Between same source and destination, search the tunnel with same symbolic path name.
1134 Collection<Tunnel> tunnelQueryResult = tunnelService.queryTunnel(tunnel.src(), tunnel.dst());
1135 Tunnel newTunnel = null;
1136 for (Tunnel tunnelObj : tunnelQueryResult) {
1137 if (tunnel.tunnelName().value().equals(tunnelObj.tunnelName().value())) {
1138 newTunnel = tunnelObj;
1139 break;
1140 }
1141 }
1142
1143 // Even if one link is shared, the bandwidth release should happen based on shared mechanism.
1144 boolean isLinkShared = false;
1145 if (newTunnel != null) {
1146 for (Link link : tunnel.path().links()) {
1147 if (newTunnel.path().links().contains(link)) {
1148 isLinkShared = true;
1149 break;
1150 }
1151 }
1152 }
1153
1154 if (isLinkShared) {
1155 releaseSharedBandwidth(newTunnel, tunnel);
1156 return;
1157 }
1158
Satish K2eb5d842017-04-04 16:28:37 +05301159 tunnel.path().links().forEach(tn -> bandwidthMgmtService.releaseLocalReservedBw(LinkKey.linkKey(tn),
1160 Double.parseDouble(tunnel.annotations().value(BANDWIDTH))));
Avantika-Huaweidbdf7722016-05-21 14:20:31 +05301161 }
1162
1163 /**
1164 * Re-allocates the bandwidth for the tunnel for which the bandwidth was
1165 * allocated in shared mode initially.
1166 */
1167 private synchronized void releaseSharedBandwidth(Tunnel newTunnel, Tunnel oldTunnel) {
Avantika-Huaweidbdf7722016-05-21 14:20:31 +05301168
Satish K2eb5d842017-04-04 16:28:37 +05301169 boolean isAllocate = false;
1170 Double oldTunnelBw = Double.parseDouble(oldTunnel.annotations().value(BANDWIDTH));
1171 Double newTunnelBw = Double.parseDouble(newTunnel.annotations().value(BANDWIDTH));
1172
1173 if (newTunnelBw > oldTunnelBw) {
1174 isAllocate = true;
Priyanka B4c3b4512016-07-22 11:41:49 +05301175 }
1176
Avantika-Huaweidbdf7722016-05-21 14:20:31 +05301177 for (Link link : newTunnel.path().links()) {
Satish K2eb5d842017-04-04 16:28:37 +05301178 if (oldTunnel.path().links().contains(link)) {
1179 if (!isAllocate) {
1180 bandwidthMgmtService.releaseLocalReservedBw(LinkKey.linkKey(link),
1181 oldTunnelBw - newTunnelBw);
1182 }
1183 } else {
1184 bandwidthMgmtService.releaseLocalReservedBw(LinkKey.linkKey(link), oldTunnelBw);
1185 }
Mahesh Poojary Huawei1d17cad2016-06-02 12:53:41 +05301186 }
1187 }
1188
Avantika-Huaweidbdf7722016-05-21 14:20:31 +05301189 // Listens on tunnel events.
1190 private class InnerTunnelListener implements TunnelListener {
1191 @Override
1192 public void event(TunnelEvent event) {
1193 // Event gets generated with old tunnel object.
1194 Tunnel tunnel = event.subject();
1195 if (tunnel.type() != MPLS) {
1196 return;
1197 }
1198
1199 LspType lspType = LspType.valueOf(tunnel.annotations().value(LSP_SIG_TYPE));
1200 String tunnelBandwidth = tunnel.annotations().value(BANDWIDTH);
1201 double bwConstraintValue = 0;
1202 if (tunnelBandwidth != null) {
1203 bwConstraintValue = Double.parseDouble(tunnelBandwidth);
1204 }
1205
1206 switch (event.type()) {
Avantika-Huaweidbdf7722016-05-21 14:20:31 +05301207 case TUNNEL_UPDATED:
Satish K2eb5d842017-04-04 16:28:37 +05301208 if (rsvpTunnelsWithLocalBw.contains(tunnel.tunnelId())) {
1209 releaseBandwidth(event.subject());
1210 rsvpTunnelsWithLocalBw.remove(tunnel.tunnelId());
1211 }
1212
Avantika-Huaweidbdf7722016-05-21 14:20:31 +05301213 if (tunnel.state() == UNSTABLE) {
1214 /*
1215 * During LSP DB sync if PCC doesn't report LSP which was PCE initiated, it's state is turned into
1216 * unstable so that it can be setup again. Add into failed path store so that it can be recomputed
1217 * and setup while global reoptimization.
1218 */
1219
1220 List<Constraint> constraints = new LinkedList<>();
1221 String bandwidth = tunnel.annotations().value(BANDWIDTH);
1222 if (bandwidth != null) {
Satish K2eb5d842017-04-04 16:28:37 +05301223 constraints.add(new PceBandwidthConstraint(Bandwidth
Avantika-Huaweidbdf7722016-05-21 14:20:31 +05301224 .bps(Double.parseDouble(bandwidth))));
1225 }
1226
1227 String costType = tunnel.annotations().value(COST_TYPE);
1228 if (costType != null) {
1229 CostConstraint costConstraint = new CostConstraint(CostConstraint.Type.valueOf(costType));
1230 constraints.add(costConstraint);
1231 }
1232
1233 constraints.add(CapabilityConstraint
1234 .of(CapabilityType.valueOf(tunnel.annotations().value(LSP_SIG_TYPE))));
1235
1236 List<Link> links = tunnel.path().links();
1237 pceStore.addFailedPathInfo(new PcePathInfo(links.get(0).src().deviceId(),
1238 links.get(links.size() - 1).dst().deviceId(),
Priyanka Bbae0eeb12016-11-30 11:59:48 +05301239 tunnel.tunnelName().value(), constraints, lspType,
1240 pceStore.getTunnelNameExplicitPathInfoMap(tunnel
Satish Kba1c9122017-04-05 15:27:23 +05301241 .tunnelName().value()), tunnel.annotations()
1242 .value(LOAD_BALANCING_PATH_NAME) != null ? true : false));
Avantika-Huaweidbdf7722016-05-21 14:20:31 +05301243 }
Avantika-Huawei3c2d3eb2016-06-22 09:34:00 +05301244
Avantika-Huaweidbdf7722016-05-21 14:20:31 +05301245 break;
1246
1247 case TUNNEL_REMOVED:
1248 if (lspType != WITH_SIGNALLING) {
1249 localLspIdFreeList.add(Short.valueOf(tunnel.annotations().value(LOCAL_LSP_ID)));
1250 }
Avantika-Huaweidbdf7722016-05-21 14:20:31 +05301251 // If not zero bandwidth, and delegated (initiated LSPs will also be delegated).
Satish K2eb5d842017-04-04 16:28:37 +05301252 if (bwConstraintValue != 0 && mastershipService.getLocalRole(tunnel.path().src()
1253 .deviceId()) == MastershipRole.MASTER) {
1254 if (lspType != WITH_SIGNALLING) {
1255 releaseBandwidth(tunnel);
1256 }
Avantika-Huaweidbdf7722016-05-21 14:20:31 +05301257 }
Priyanka B4c3b4512016-07-22 11:41:49 +05301258
Satish K2eb5d842017-04-04 16:28:37 +05301259 /*if (pceStore.getTunnelInfo(tunnel.tunnelId()) != null) {
Priyanka B4c3b4512016-07-22 11:41:49 +05301260 pceStore.removeTunnelInfo(tunnel.tunnelId());
Satish K2eb5d842017-04-04 16:28:37 +05301261 }*/
Priyanka B4c3b4512016-07-22 11:41:49 +05301262
Avantika-Huaweidbdf7722016-05-21 14:20:31 +05301263 break;
1264
1265 default:
1266 break;
1267
1268 }
1269 return;
1270 }
1271 }
1272
Priyanka Bbae0eeb12016-11-30 11:59:48 +05301273 @Override
1274 public List<ExplicitPathInfo> explicitPathInfoList(String tunnelName) {
1275 return pceStore.getTunnelNameExplicitPathInfoMap(tunnelName);
1276 }
1277
Satish Kba1c9122017-04-05 15:27:23 +05301278 @Override
1279 public List<TunnelId> queryLoadBalancingPath(String pathName) {
1280 return pceStore.getLoadBalancingTunnelIds(pathName);
1281 }
1282
Priyanka B9fa4ed32016-05-27 11:59:24 +05301283 //Computes path from tunnel store and also path failed to setup.
1284 private void callForOptimization() {
1285 //Recompute the LSPs which it was delegated [LSPs stored in PCE store (failed paths)]
1286 for (PcePathInfo failedPathInfo : pceStore.getFailedPathInfos()) {
1287 checkForMasterAndSetupPath(failedPathInfo);
1288 }
1289
1290 //Recompute the LSPs for which it was delegated [LSPs stored in tunnel store]
1291 tunnelService.queryTunnel(MPLS).forEach(t -> {
1292 checkForMasterAndUpdateTunnel(t.path().src().deviceId(), t);
1293 });
1294 }
1295
1296 private boolean checkForMasterAndSetupPath(PcePathInfo failedPathInfo) {
1297 /**
1298 * Master of ingress node will setup the path failed stored in PCE store.
1299 */
1300 if (mastershipService.isLocalMaster(failedPathInfo.src())) {
1301 if (setupPath(failedPathInfo.src(), failedPathInfo.dst(), failedPathInfo.name(),
Priyanka Bbae0eeb12016-11-30 11:59:48 +05301302 failedPathInfo.constraints(), failedPathInfo.lspType(), failedPathInfo.explicitPathInfo())) {
Priyanka B9fa4ed32016-05-27 11:59:24 +05301303 // If computation is success remove that path
1304 pceStore.removeFailedPathInfo(failedPathInfo);
1305 return true;
1306 }
1307 }
1308
1309 return false;
1310 }
1311
1312 //Timer to call global optimization
1313 private class GlobalOptimizationTimer implements Runnable {
1314
1315 public GlobalOptimizationTimer() {
1316 }
1317
1318 @Override
1319 public void run() {
1320 callForOptimization();
1321 }
1322 }
rohitsharan483bed42017-04-12 19:04:57 +05301323}