blob: aa16f80761d2ff0ad89ea820559fc667cb755c1a [file] [log] [blame]
Avantika-Huawei73862d42016-05-12 18:58:06 +05301/*
2 * Copyright 2016-present Open Networking Laboratory
3 *
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
18import static com.google.common.base.Preconditions.checkNotNull;
Avantika-Huawei73862d42016-05-12 18:58:06 +053019
Avantika-Huaweidbdf7722016-05-21 14:20:31 +053020import java.util.Collection;
Priyanka Bb6963582016-05-20 20:21:20 +053021import java.util.Collections;
Avantika-Huawei73862d42016-05-12 18:58:06 +053022import java.util.Iterator;
Avantika-Huaweidbdf7722016-05-21 14:20:31 +053023import java.util.LinkedList;
Avantika-Huawei73862d42016-05-12 18:58:06 +053024import java.util.List;
Avantika-Huaweidbdf7722016-05-21 14:20:31 +053025import java.util.Map;
26import java.util.Optional;
27import java.util.Map.Entry;
Priyanka Bb6963582016-05-20 20:21:20 +053028import java.util.Set;
Priyanka B9fa4ed32016-05-27 11:59:24 +053029import java.util.concurrent.Executors;
30import java.util.concurrent.ScheduledExecutorService;
31import java.util.concurrent.TimeUnit;
Avantika-Huawei73862d42016-05-12 18:58:06 +053032
Avantika-Huaweid1e36bd2016-05-26 12:47:16 +053033import org.onlab.packet.Ethernet;
34import org.onlab.packet.IPv4;
35
Avantika-Huawei73862d42016-05-12 18:58:06 +053036import org.apache.felix.scr.annotations.Activate;
37import org.apache.felix.scr.annotations.Component;
38import org.apache.felix.scr.annotations.Deactivate;
39import org.apache.felix.scr.annotations.Reference;
40import org.apache.felix.scr.annotations.ReferenceCardinality;
41import org.apache.felix.scr.annotations.Service;
Avantika-Huaweidbdf7722016-05-21 14:20:31 +053042import org.onlab.packet.IpAddress;
43import org.onlab.packet.IpPrefix;
Avantika-Huaweid1e36bd2016-05-26 12:47:16 +053044import org.onlab.packet.TCP;
Avantika-Huaweidbdf7722016-05-21 14:20:31 +053045import org.onlab.util.Bandwidth;
Avantika-Huawei73862d42016-05-12 18:58:06 +053046import org.onosproject.core.ApplicationId;
47import org.onosproject.core.CoreService;
Avantika-Huaweidbdf7722016-05-21 14:20:31 +053048import org.onosproject.incubator.net.resource.label.LabelResourceAdminService;
49import org.onosproject.incubator.net.resource.label.LabelResourceId;
50import org.onosproject.incubator.net.resource.label.LabelResourceService;
Avantika-Huawei73862d42016-05-12 18:58:06 +053051import org.onosproject.core.IdGenerator;
Avantika-Huaweidbdf7722016-05-21 14:20:31 +053052import org.onosproject.incubator.net.tunnel.DefaultTunnel;
53import org.onosproject.incubator.net.tunnel.IpTunnelEndPoint;
54import org.onosproject.incubator.net.tunnel.LabelStack;
Avantika-Huawei73862d42016-05-12 18:58:06 +053055import org.onosproject.incubator.net.tunnel.Tunnel;
Avantika-Huaweidbdf7722016-05-21 14:20:31 +053056import org.onosproject.incubator.net.tunnel.TunnelEndPoint;
57import org.onosproject.incubator.net.tunnel.TunnelEvent;
Avantika-Huawei73862d42016-05-12 18:58:06 +053058import org.onosproject.incubator.net.tunnel.TunnelId;
Avantika-Huaweidbdf7722016-05-21 14:20:31 +053059import org.onosproject.incubator.net.tunnel.TunnelListener;
60import org.onosproject.incubator.net.tunnel.TunnelName;
Avantika-Huawei73862d42016-05-12 18:58:06 +053061import org.onosproject.incubator.net.tunnel.TunnelService;
Priyanka B3f92c5a2016-05-27 10:14:16 +053062import org.onosproject.mastership.MastershipService;
Avantika-Huawei032a9872016-05-27 22:57:38 +053063import org.onosproject.net.config.NetworkConfigService;
Avantika-Huaweidbdf7722016-05-21 14:20:31 +053064import org.onosproject.net.DefaultAnnotations;
65import org.onosproject.net.DefaultAnnotations.Builder;
66import org.onosproject.net.Device;
Avantika-Huawei73862d42016-05-12 18:58:06 +053067import org.onosproject.net.DeviceId;
Avantika-Huaweidbdf7722016-05-21 14:20:31 +053068import org.onosproject.net.Link;
Priyanka Bb6963582016-05-20 20:21:20 +053069import org.onosproject.net.Path;
Priyanka Bb6963582016-05-20 20:21:20 +053070import org.onosproject.net.device.DeviceService;
Avantika-Huaweidbdf7722016-05-21 14:20:31 +053071import org.onosproject.net.flowobjective.FlowObjectiveService;
72import org.onosproject.net.flowobjective.Objective;
73import org.onosproject.net.intent.Constraint;
74import org.onosproject.net.intent.constraint.BandwidthConstraint;
Priyanka B3f92c5a2016-05-27 10:14:16 +053075import org.onosproject.net.link.LinkEvent;
Avantika-Huaweidbdf7722016-05-21 14:20:31 +053076import org.onosproject.pce.pceservice.constraint.CapabilityConstraint;
77import org.onosproject.pce.pceservice.constraint.CapabilityConstraint.CapabilityType;
78import org.onosproject.pce.pceservice.constraint.CostConstraint;
79import org.onosproject.pce.pceservice.constraint.SharedBandwidthConstraint;
80import org.onosproject.net.resource.Resource;
81import org.onosproject.net.resource.ResourceAllocation;
82import org.onosproject.net.resource.ResourceConsumer;
83import org.onosproject.net.resource.ResourceQueryService;
Priyanka Bb6963582016-05-20 20:21:20 +053084import org.onosproject.net.resource.ResourceService;
Avantika-Huaweidbdf7722016-05-21 14:20:31 +053085import org.onosproject.net.resource.Resources;
Priyanka Bb6963582016-05-20 20:21:20 +053086import org.onosproject.net.topology.LinkWeight;
87import org.onosproject.net.topology.PathService;
88import org.onosproject.net.topology.TopologyEdge;
Priyanka B3f92c5a2016-05-27 10:14:16 +053089import org.onosproject.net.topology.TopologyEvent;
90import org.onosproject.net.topology.TopologyListener;
91import org.onosproject.net.topology.TopologyService;
Avantika-Huawei73862d42016-05-12 18:58:06 +053092import org.onosproject.pce.pceservice.api.PceService;
Avantika-Huaweidbdf7722016-05-21 14:20:31 +053093import org.onosproject.pce.pcestore.PcePathInfo;
94import org.onosproject.pce.pcestore.PceccTunnelInfo;
95import org.onosproject.pce.pcestore.api.PceStore;
Avantika-Huawei032a9872016-05-27 22:57:38 +053096import org.onosproject.pcep.api.DeviceCapability;
Avantika-Huawei73862d42016-05-12 18:58:06 +053097import org.onosproject.store.serializers.KryoNamespaces;
98import org.onosproject.store.service.DistributedSet;
99import org.onosproject.store.service.Serializer;
100import org.onosproject.store.service.StorageService;
101import org.slf4j.Logger;
102import org.slf4j.LoggerFactory;
103
Priyanka Bb6963582016-05-20 20:21:20 +0530104import com.google.common.collect.ImmutableList;
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530105import com.google.common.collect.ImmutableSet;
106
107import static org.onosproject.incubator.net.tunnel.Tunnel.Type.MPLS;
108import static org.onosproject.incubator.net.tunnel.Tunnel.State.INIT;
109import static org.onosproject.incubator.net.tunnel.Tunnel.State.ESTABLISHED;
110import static org.onosproject.incubator.net.tunnel.Tunnel.State.UNSTABLE;
111import static org.onosproject.pce.pceservice.LspType.WITH_SIGNALLING;
112import static org.onosproject.pce.pceservice.LspType.SR_WITHOUT_SIGNALLING;
113import static org.onosproject.pce.pceservice.LspType.WITHOUT_SIGNALLING_AND_WITHOUT_SR;
114
115import static org.onosproject.pce.pceservice.PcepAnnotationKeys.BANDWIDTH;
116import static org.onosproject.pce.pceservice.PcepAnnotationKeys.LOCAL_LSP_ID;
117import static org.onosproject.pce.pceservice.PcepAnnotationKeys.LSP_SIG_TYPE;
118import static org.onosproject.pce.pceservice.PcepAnnotationKeys.PCE_INIT;
119import static org.onosproject.pce.pceservice.PcepAnnotationKeys.PLSP_ID;
120import static org.onosproject.pce.pceservice.PcepAnnotationKeys.PCC_TUNNEL_ID;
121import static org.onosproject.pce.pceservice.PcepAnnotationKeys.DELEGATE;
122import static org.onosproject.pce.pceservice.PcepAnnotationKeys.COST_TYPE;
123
124import org.onosproject.net.packet.InboundPacket;
125import org.onosproject.net.packet.PacketContext;
126import org.onosproject.net.packet.PacketProcessor;
127import org.onosproject.net.packet.PacketService;
Priyanka Bb6963582016-05-20 20:21:20 +0530128
Avantika-Huawei73862d42016-05-12 18:58:06 +0530129/**
130 * Implementation of PCE service.
131 */
132@Component(immediate = true)
133@Service
134public class PceManager implements PceService {
135 private static final Logger log = LoggerFactory.getLogger(PceManager.class);
136
137 public static final String PCE_SERVICE_APP = "org.onosproject.pce";
Avantika-Huawei73862d42016-05-12 18:58:06 +0530138 private static final String LOCAL_LSP_ID_GEN_TOPIC = "pcep-local-lsp-id";
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530139 private static final int PREFIX_LENGTH = 32;
140
141 private static final String TUNNEL_CONSUMER_ID_GEN_TOPIC = "pcep-tunnel-consumer-id";
142 private IdGenerator tunnelConsumerIdGen;
143
144 private static final String LSRID = "lsrId";
145 private static final String TRUE = "true";
146 private static final String FALSE = "false";
147 private static final String END_OF_SYNC_IP_PREFIX = "0.0.0.0/32";
Avantika-Huaweid1e36bd2016-05-26 12:47:16 +0530148 public static final int PCEP_PORT = 4189;
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530149
Avantika-Huawei73862d42016-05-12 18:58:06 +0530150 private IdGenerator localLspIdIdGen;
151 protected DistributedSet<Short> localLspIdFreeList;
152
153 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
154 protected CoreService coreService;
155
156 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530157 protected ResourceService resourceService;
158
159 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
160 protected ResourceQueryService resourceQueryService;
161
162 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
163 protected PathService pathService;
164
165 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
166 protected PceStore pceStore;
167
168 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Avantika-Huawei73862d42016-05-12 18:58:06 +0530169 protected TunnelService tunnelService;
170
171 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
172 protected StorageService storageService;
173
Priyanka Bb6963582016-05-20 20:21:20 +0530174 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530175 protected PacketService packetService;
Priyanka Bb6963582016-05-20 20:21:20 +0530176
177 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
178 protected DeviceService deviceService;
179
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530180 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Avantika-Huawei032a9872016-05-27 22:57:38 +0530181 protected NetworkConfigService netCfgService;
182
183 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530184 protected LabelResourceAdminService labelRsrcAdminService;
185
186 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
187 protected LabelResourceService labelRsrcService;
188
189 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
190 protected FlowObjectiveService flowObjectiveService;
191
Priyanka B3f92c5a2016-05-27 10:14:16 +0530192 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
193 protected MastershipService mastershipService;
194
195 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
196 protected TopologyService topologyService;
197
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530198 private TunnelListener listener = new InnerTunnelListener();
199 private BasicPceccHandler crHandler;
200 private PceccSrTeBeHandler srTeHandler;
Avantika-Huawei73862d42016-05-12 18:58:06 +0530201 private ApplicationId appId;
202
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530203 private final PcepPacketProcessor processor = new PcepPacketProcessor();
Priyanka B3f92c5a2016-05-27 10:14:16 +0530204 private final TopologyListener topologyListener = new InternalTopologyListener();
Priyanka B9fa4ed32016-05-27 11:59:24 +0530205 private ScheduledExecutorService executor;
206
207 public static final int INITIAL_DELAY = 30;
208 public static final int PERIODIC_DELAY = 30;
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530209
Avantika-Huawei73862d42016-05-12 18:58:06 +0530210 /**
211 * Creates new instance of PceManager.
212 */
213 public PceManager() {
214 }
215
216 @Activate
217 protected void activate() {
218 appId = coreService.registerApplication(PCE_SERVICE_APP);
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530219 crHandler = BasicPceccHandler.getInstance();
220 crHandler.initialize(labelRsrcService, flowObjectiveService, appId, pceStore);
Avantika-Huawei73862d42016-05-12 18:58:06 +0530221
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530222 srTeHandler = PceccSrTeBeHandler.getInstance();
223 srTeHandler.initialize(labelRsrcAdminService, labelRsrcService, flowObjectiveService, appId, pceStore);
224
225 tunnelService.addListener(listener);
226
227 tunnelConsumerIdGen = coreService.getIdGenerator(TUNNEL_CONSUMER_ID_GEN_TOPIC);
Avantika-Huawei73862d42016-05-12 18:58:06 +0530228 localLspIdIdGen = coreService.getIdGenerator(LOCAL_LSP_ID_GEN_TOPIC);
229 localLspIdFreeList = storageService.<Short>setBuilder()
230 .withName("pcepLocalLspIdDeletedList")
231 .withSerializer(Serializer.using(KryoNamespaces.API))
232 .build()
233 .asDistributedSet();
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530234
235 packetService.addProcessor(processor, PacketProcessor.director(4));
Priyanka B3f92c5a2016-05-27 10:14:16 +0530236 topologyService.addListener(topologyListener);
Priyanka B9fa4ed32016-05-27 11:59:24 +0530237 executor = Executors.newSingleThreadScheduledExecutor();
238 //Start a timer when the component is up, with initial delay of 30min and periodic delays at 30min
239 executor.scheduleAtFixedRate(new GlobalOptimizationTimer(), INITIAL_DELAY, PERIODIC_DELAY, TimeUnit.MINUTES);
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530240 log.info("Started");
Avantika-Huawei73862d42016-05-12 18:58:06 +0530241 }
242
243 @Deactivate
244 protected void deactivate() {
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530245 tunnelService.removeListener(listener);
246 packetService.removeProcessor(processor);
Priyanka B3f92c5a2016-05-27 10:14:16 +0530247 topologyService.removeListener(topologyListener);
Priyanka B9fa4ed32016-05-27 11:59:24 +0530248 //Shutdown the thread when component is deactivated
249 executor.shutdown();
Avantika-Huawei73862d42016-05-12 18:58:06 +0530250 log.info("Stopped");
251 }
252
Priyanka Bb6963582016-05-20 20:21:20 +0530253 /**
254 * Returns an edge-weight capable of evaluating links on the basis of the
255 * specified constraints.
256 *
257 * @param constraints path constraints
258 * @return edge-weight function
259 */
260 private LinkWeight weight(List<Constraint> constraints) {
261 return new TeConstraintBasedLinkWeight(constraints);
262 }
263
264 /**
265 * Computes a path between two devices.
266 *
267 * @param src ingress device
268 * @param dst egress device
269 * @param constraints path constraints
270 * @return computed path based on constraints
271 */
272 protected Set<Path> computePath(DeviceId src, DeviceId dst, List<Constraint> constraints) {
273 if (pathService == null) {
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530274 return ImmutableSet.of();
Priyanka Bb6963582016-05-20 20:21:20 +0530275 }
276 Set<Path> paths = pathService.getPaths(src, dst, weight(constraints));
277 if (!paths.isEmpty()) {
278 return paths;
279 }
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530280 return ImmutableSet.of();
Priyanka Bb6963582016-05-20 20:21:20 +0530281 }
282
Avantika-Huawei73862d42016-05-12 18:58:06 +0530283 //[TODO:] handle requests in queue
284 @Override
285 public boolean setupPath(DeviceId src, DeviceId dst, String tunnelName, List<Constraint> constraints,
286 LspType lspType) {
287 checkNotNull(src);
288 checkNotNull(dst);
289 checkNotNull(tunnelName);
Avantika-Huawei73862d42016-05-12 18:58:06 +0530290 checkNotNull(lspType);
291
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530292 // Convert from DeviceId to TunnelEndPoint
293 Device srcDevice = deviceService.getDevice(src);
294 Device dstDevice = deviceService.getDevice(dst);
Avantika-Huawei73862d42016-05-12 18:58:06 +0530295
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530296 if (srcDevice == null || dstDevice == null) {
297 // Device is not known.
298 pceStore.addFailedPathInfo(new PcePathInfo(src, dst, tunnelName, constraints, lspType));
299 return false;
300 }
301
302 // In future projections instead of annotations will be used to fetch LSR ID.
303 String srcLsrId = srcDevice.annotations().value(LSRID);
304 String dstLsrId = dstDevice.annotations().value(LSRID);
305
306 if (srcLsrId == null || dstLsrId == null) {
307 // LSR id is not known.
308 pceStore.addFailedPathInfo(new PcePathInfo(src, dst, tunnelName, constraints, lspType));
309 return false;
310 }
311
Avantika-Huawei032a9872016-05-27 22:57:38 +0530312 // Get device config from netconfig, to ascertain that session with ingress is present.
313 DeviceCapability cfg = netCfgService.getConfig(DeviceId.deviceId(srcLsrId), DeviceCapability.class);
314 if (cfg == null) {
315 log.debug("No session to ingress.");
316 pceStore.addFailedPathInfo(new PcePathInfo(src, dst, tunnelName, constraints, lspType));
317 return false;
318 }
319
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530320 TunnelEndPoint srcEndPoint = IpTunnelEndPoint.ipTunnelPoint(IpAddress.valueOf(srcLsrId));
321 TunnelEndPoint dstEndPoint = IpTunnelEndPoint.ipTunnelPoint(IpAddress.valueOf(dstLsrId));
322
323 double bwConstraintValue = 0;
324 CostConstraint costConstraint = null;
325 if (constraints != null) {
326 constraints.add(CapabilityConstraint.of(CapabilityType.valueOf(lspType.name())));
327 Iterator<Constraint> iterator = constraints.iterator();
328
329 while (iterator.hasNext()) {
330 Constraint constraint = iterator.next();
331 if (constraint instanceof BandwidthConstraint) {
332 bwConstraintValue = ((BandwidthConstraint) constraint).bandwidth().bps();
333 } else if (constraint instanceof CostConstraint) {
334 costConstraint = (CostConstraint) constraint;
335 }
336 }
337
338 /*
339 * Add cost at the end of the list of constraints. The path computation algorithm also computes cumulative
340 * cost. The function which checks the limiting/capability constraints also returns per link cost. This
341 * function can either return the result of limiting/capability constraint validation or the value of link
342 * cost, depending upon what is the last constraint in the loop.
343 */
344 if (costConstraint != null) {
345 constraints.remove(costConstraint);
346 constraints.add(costConstraint);
347 }
348 } else {
349 constraints = new LinkedList<>();
350 constraints.add(CapabilityConstraint.of(CapabilityType.valueOf(lspType.name())));
351 }
352
353 Set<Path> computedPathSet = computePath(src, dst, constraints);
354
355 // NO-PATH
356 if (computedPathSet.isEmpty()) {
357 pceStore.addFailedPathInfo(new PcePathInfo(src, dst, tunnelName, constraints, lspType));
358 return false;
359 }
360
361 Builder annotationBuilder = DefaultAnnotations.builder();
362 if (bwConstraintValue != 0) {
363 annotationBuilder.set(BANDWIDTH, String.valueOf(bwConstraintValue));
364 }
365 if (costConstraint != null) {
366 annotationBuilder.set(COST_TYPE, String.valueOf(costConstraint.type()));
367 }
368 annotationBuilder.set(LSP_SIG_TYPE, lspType.name());
369 annotationBuilder.set(PCE_INIT, TRUE);
370 annotationBuilder.set(DELEGATE, TRUE);
371
372 Path computedPath = computedPathSet.iterator().next();
373 LabelStack labelStack = null;
374
375 if (lspType == SR_WITHOUT_SIGNALLING) {
376 labelStack = srTeHandler.computeLabelStack(computedPath);
377 // Failed to form a label stack.
378 if (labelStack == null) {
379 pceStore.addFailedPathInfo(new PcePathInfo(src, dst, tunnelName, constraints, lspType));
380 return false;
381 }
382 }
383
384 if (lspType != WITH_SIGNALLING) {
385 /*
386 * Local LSP id which is assigned by RSVP for RSVP signalled LSPs, will be assigned by
387 * PCE for non-RSVP signalled LSPs.
388 */
389 annotationBuilder.set(LOCAL_LSP_ID, String.valueOf(getNextLocalLspId()));
390 }
391
392 // For SR-TE tunnels, call SR manager for label stack and put it inside tunnel.
393 Tunnel tunnel = new DefaultTunnel(null, srcEndPoint, dstEndPoint, MPLS, INIT, null, null,
394 TunnelName.tunnelName(tunnelName), computedPath,
395 labelStack, annotationBuilder.build());
396
397 // Allocate bandwidth.
398 TunnelConsumerId consumerId = null;
399 if (bwConstraintValue != 0) {
400 consumerId = reserveBandwidth(computedPath, bwConstraintValue, null);
401 if (consumerId == null) {
402 pceStore.addFailedPathInfo(new PcePathInfo(src, dst, tunnelName, constraints, lspType));
403 return false;
404 }
405 }
406
407 TunnelId tunnelId = tunnelService.setupTunnel(appId, src, tunnel, computedPath);
408 if (tunnelId == null) {
409 pceStore.addFailedPathInfo(new PcePathInfo(src, dst, tunnelName, constraints, lspType));
410 if (consumerId != null) {
411 resourceService.release(consumerId);
412 }
413 return false;
414 }
415
416 if (consumerId != null) {
417 // Store tunnel consumer id in LSP-Label store.
418 PceccTunnelInfo pceccTunnelInfo = new PceccTunnelInfo(null, consumerId);
419 pceStore.addTunnelInfo(tunnelId, pceccTunnelInfo);
420 }
421 return true;
422 }
Avantika-Huawei73862d42016-05-12 18:58:06 +0530423
424 @Override
425 public boolean updatePath(TunnelId tunnelId, List<Constraint> constraints) {
426 checkNotNull(tunnelId);
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530427 Set<Path> computedPathSet = null;
428 Tunnel tunnel = tunnelService.queryTunnel(tunnelId);
Avantika-Huawei73862d42016-05-12 18:58:06 +0530429
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530430 if (tunnel == null) {
431 return false;
432 }
Avantika-Huawei73862d42016-05-12 18:58:06 +0530433
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530434 if (tunnel.type() != MPLS || FALSE.equalsIgnoreCase(tunnel.annotations().value(DELEGATE))) {
435 // Only delegated LSPs can be updated.
436 return false;
437 }
438
439 List<Link> links = tunnel.path().links();
440 String lspSigType = tunnel.annotations().value(LSP_SIG_TYPE);
441 double bwConstraintValue = 0;
Priyanka B3f92c5a2016-05-27 10:14:16 +0530442 String costType = null;
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530443 SharedBandwidthConstraint shBwConstraint = null;
444 BandwidthConstraint bwConstraint = null;
445 CostConstraint costConstraint = null;
446
447 if (constraints != null) {
448 // Call path computation in shared bandwidth mode.
449 Iterator<Constraint> iterator = constraints.iterator();
450 while (iterator.hasNext()) {
451 Constraint constraint = iterator.next();
452 if (constraint instanceof BandwidthConstraint) {
453 bwConstraint = (BandwidthConstraint) constraint;
454 bwConstraintValue = bwConstraint.bandwidth().bps();
455 } else if (constraint instanceof CostConstraint) {
456 costConstraint = (CostConstraint) constraint;
Avantika-Huawei032a9872016-05-27 22:57:38 +0530457 costType = costConstraint.type().name();
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530458 }
459 }
460
461 // Remove and keep the cost constraint at the end of the list of constraints.
462 if (costConstraint != null) {
463 constraints.remove(costConstraint);
464 }
465
466 Bandwidth existingBwValue = null;
467 String existingBwAnnotation = tunnel.annotations().value(BANDWIDTH);
468 if (existingBwAnnotation != null) {
469 existingBwValue = Bandwidth.bps(Double.parseDouble(existingBwAnnotation));
470
471 /*
472 * The computation is a shared bandwidth constraint based, so need to remove bandwidth constraint which
473 * has been utilized to create shared bandwidth constraint.
474 */
475 if (bwConstraint != null) {
476 constraints.remove(bwConstraint);
477 }
478 }
479
480 if (existingBwValue != null) {
481 shBwConstraint = new SharedBandwidthConstraint(links, existingBwValue, bwConstraint.bandwidth());
482 constraints.add(shBwConstraint);
483 }
484 } else {
485 constraints = new LinkedList<>();
486 }
487
488 constraints.add(CapabilityConstraint.of(CapabilityType.valueOf(lspSigType)));
489 if (costConstraint != null) {
490 constraints.add(costConstraint);
491 }
492
493 computedPathSet = computePath(links.get(0).src().deviceId(), links.get(links.size() - 1).dst().deviceId(),
494 constraints);
495
496 // NO-PATH
497 if (computedPathSet.isEmpty()) {
498 return false;
499 }
500
501 Builder annotationBuilder = DefaultAnnotations.builder();
502 annotationBuilder.set(BANDWIDTH, String.valueOf(bwConstraintValue));
Priyanka B3f92c5a2016-05-27 10:14:16 +0530503 if (costType != null) {
504 annotationBuilder.set(COST_TYPE, costType);
505 }
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530506 annotationBuilder.set(LSP_SIG_TYPE, lspSigType);
507 annotationBuilder.set(PCE_INIT, TRUE);
508 annotationBuilder.set(DELEGATE, TRUE);
509 annotationBuilder.set(PLSP_ID, tunnel.annotations().value(PLSP_ID));
510 annotationBuilder.set(PCC_TUNNEL_ID, tunnel.annotations().value(PCC_TUNNEL_ID));
511
512 Path computedPath = computedPathSet.iterator().next();
513 LabelStack labelStack = null;
514 TunnelConsumerId consumerId = null;
515 LspType lspType = LspType.valueOf(lspSigType);
516 long localLspId = 0;
517 if (lspType != WITH_SIGNALLING) {
518 /*
519 * Local LSP id which is assigned by RSVP for RSVP signalled LSPs, will be assigned by
520 * PCE for non-RSVP signalled LSPs.
521 */
522 localLspId = getNextLocalLspId();
523 annotationBuilder.set(LOCAL_LSP_ID, String.valueOf(localLspId));
524
525 if (lspType == SR_WITHOUT_SIGNALLING) {
526 labelStack = srTeHandler.computeLabelStack(computedPath);
527 // Failed to form a label stack.
528 if (labelStack == null) {
529 return false;
530 }
531 }
532 }
533
534 Tunnel updatedTunnel = new DefaultTunnel(null, tunnel.src(), tunnel.dst(), MPLS, INIT, null, null,
535 tunnel.tunnelName(), computedPath,
536 labelStack, annotationBuilder.build());
537
538 // Allocate shared bandwidth.
539 if (bwConstraintValue != 0) {
540 consumerId = reserveBandwidth(computedPath, bwConstraintValue, shBwConstraint);
541 if (consumerId == null) {
542 return false;
543 }
544 }
545
546 TunnelId updatedTunnelId = tunnelService.setupTunnel(appId, links.get(0).src().deviceId(), updatedTunnel,
547 computedPath);
548
549 if (updatedTunnelId == null) {
550 if (consumerId != null) {
551 resourceService.release(consumerId);
552 }
553 return false;
554 }
555
556 if (consumerId != null) {
557 // Store tunnel consumer id in LSP-Label store.
558 PceccTunnelInfo pceccTunnelInfo = new PceccTunnelInfo(null, consumerId);
559 pceStore.addTunnelInfo(updatedTunnelId, pceccTunnelInfo);
560 }
Avantika-Huawei73862d42016-05-12 18:58:06 +0530561 return true;
562 }
563
564 @Override
565 public boolean releasePath(TunnelId tunnelId) {
566 checkNotNull(tunnelId);
567 // 1. Query Tunnel from Tunnel manager.
568 Tunnel tunnel = tunnelService.queryTunnel(tunnelId);
569
570 if (tunnel == null) {
571 return false;
572 }
573
574 // 2. Call tunnel service.
575 return tunnelService.downTunnel(appId, tunnel.tunnelId());
576 }
577
578 @Override
579 public Iterable<Tunnel> queryAllPath() {
580 return tunnelService.queryTunnel(MPLS);
581 }
582
583 @Override
584 public Tunnel queryPath(TunnelId tunnelId) {
585 return tunnelService.queryTunnel(tunnelId);
586 }
587
588 /**
589 * Returns the next local LSP identifier to be used either by getting from
590 * freed list if available otherwise generating a new one.
591 *
592 * @return value of local LSP identifier
593 */
594 private short getNextLocalLspId() {
595 // If there is any free id use it. Otherwise generate new id.
596 if (localLspIdFreeList.isEmpty()) {
597 return (short) localLspIdIdGen.getNewId();
598 }
599 Iterator<Short> it = localLspIdFreeList.iterator();
600 Short value = it.next();
601 localLspIdFreeList.remove(value);
602 return value;
603 }
604
Priyanka Bb6963582016-05-20 20:21:20 +0530605 protected class TeConstraintBasedLinkWeight implements LinkWeight {
606
607 private final List<Constraint> constraints;
608
609 /**
610 * Creates a new edge-weight function capable of evaluating links
611 * on the basis of the specified constraints.
612 *
613 * @param constraints path constraints
614 */
615 public TeConstraintBasedLinkWeight(List<Constraint> constraints) {
616 if (constraints == null) {
617 this.constraints = Collections.emptyList();
618 } else {
619 this.constraints = ImmutableList.copyOf(constraints);
620 }
621 }
622
623 @Override
624 public double weight(TopologyEdge edge) {
625 if (!constraints.iterator().hasNext()) {
626 //Takes default cost/hopcount as 1 if no constraints specified
627 return 1.0;
628 }
629
630 Iterator<Constraint> it = constraints.iterator();
631 double cost = 1;
632
633 //If any constraint fails return -1 also value of cost returned from cost constraint can't be negative
634 while (it.hasNext() && cost > 0) {
635 Constraint constraint = it.next();
636 if (constraint instanceof CapabilityConstraint) {
Avantika-Huawei032a9872016-05-27 22:57:38 +0530637 cost = ((CapabilityConstraint) constraint).isValidLink(edge.link(), deviceService,
638 netCfgService) ? 1 : -1;
Priyanka Bb6963582016-05-20 20:21:20 +0530639 } else {
640 cost = constraint.cost(edge.link(), resourceService::isAvailable);
641 }
642 }
643 return cost;
644 }
645 }
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530646
Priyanka B3f92c5a2016-05-27 10:14:16 +0530647 //TODO: annotations used for temporarily later projection/network config will be used
648 private class InternalTopologyListener implements TopologyListener {
649 @Override
650 public void event(TopologyEvent event) {
651 event.reasons().forEach(e -> {
652 //If event type is link removed, get the impacted tunnel
653 if (e instanceof LinkEvent) {
654 LinkEvent linkEvent = (LinkEvent) e;
655 if (linkEvent.type() == LinkEvent.Type.LINK_REMOVED) {
656 tunnelService.queryTunnel(MPLS).forEach(t -> {
Avantika-Huaweid1e36bd2016-05-26 12:47:16 +0530657 if (t.path().links().contains((e.subject()))) {
Priyanka B3f92c5a2016-05-27 10:14:16 +0530658 // Check whether this ONOS instance is master for ingress device if yes,
659 // recompute and send update
660 checkForMasterAndUpdateTunnel(t.path().src().deviceId(), t);
661 }
662 });
663 }
664 }
665 });
666 }
667 }
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530668
Priyanka B3f92c5a2016-05-27 10:14:16 +0530669 private boolean checkForMasterAndUpdateTunnel(DeviceId src, Tunnel tunnel) {
670 /**
671 * Master of ingress node will recompute and also delegation flag must be set.
672 */
673 if (mastershipService.isLocalMaster(src)
674 && Boolean.valueOf(tunnel.annotations().value(DELEGATE)) != null) {
675 LinkedList<Constraint> constraintList = new LinkedList<>();
676
677 if (tunnel.annotations().value(BANDWIDTH) != null) {
678 //Requested bandwidth will be same as previous allocated bandwidth for the tunnel
679 BandwidthConstraint localConst = new BandwidthConstraint(Bandwidth.bps(Double.parseDouble(tunnel
680 .annotations().value(BANDWIDTH))));
681 constraintList.add(localConst);
682 }
683 if (tunnel.annotations().value(COST_TYPE) != null) {
684 constraintList.add(CostConstraint.of(CostConstraint.Type.valueOf(tunnel.annotations().value(
685 COST_TYPE))));
686 }
Priyanka B9fa4ed32016-05-27 11:59:24 +0530687
688 /*
689 * If tunnel was UP after recomputation failed then store failed path in PCE store send PCIntiate(remove)
690 * and If tunnel is failed and computation fails nothing to do because tunnel status will be same[Failed]
691 */
692 if (!updatePath(tunnel.tunnelId(), constraintList) && !tunnel.state().equals(Tunnel.State.FAILED)) {
Priyanka B3f92c5a2016-05-27 10:14:16 +0530693 // If updation fails store in PCE store as failed path
694 // then PCInitiate (Remove)
695 pceStore.addFailedPathInfo(new PcePathInfo(tunnel.path().src().deviceId(), tunnel
696 .path().dst().deviceId(), tunnel.tunnelName().value(), constraintList,
697 LspType.valueOf(tunnel.annotations().value(LSP_SIG_TYPE))));
698 //Release that tunnel calling PCInitiate
699 releasePath(tunnel.tunnelId());
700 }
701 }
702
703 return false;
704 }
705
706 // Allocates the bandwidth locally for PCECC tunnels.
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530707 private TunnelConsumerId reserveBandwidth(Path computedPath, double bandwidthConstraint,
708 SharedBandwidthConstraint shBwConstraint) {
709 checkNotNull(computedPath);
710 checkNotNull(bandwidthConstraint);
711 Resource resource = null;
712 double bwToAllocate = 0;
713
714 TunnelConsumerId consumer = TunnelConsumerId.valueOf(tunnelConsumerIdGen.getNewId());
715
716 /**
717 * Shared bandwidth sub-case : Lesser bandwidth required than original -
718 * No reservation required.
719 */
720 Double additionalBwValue = null;
721 if (shBwConstraint != null) {
722 additionalBwValue = ((bandwidthConstraint - shBwConstraint.sharedBwValue().bps()) <= 0) ? null
723 : (bandwidthConstraint - shBwConstraint.sharedBwValue().bps());
724 }
725
726 Optional<ResourceAllocation> resAlloc = null;
727 for (Link link : computedPath.links()) {
728 bwToAllocate = 0;
729 if ((shBwConstraint != null) && (shBwConstraint.links().contains(link))) {
730 if (additionalBwValue != null) {
731 bwToAllocate = bandwidthConstraint - additionalBwValue;
732 }
733 } else {
734 bwToAllocate = bandwidthConstraint;
735 }
736
737 /**
738 * In shared bandwidth cases, where new BW is lesser than old BW, it
739 * is not required to allocate anything.
740 */
741 if (bwToAllocate != 0) {
742 resource = Resources.continuous(link.src().deviceId(), link.src().port(), Bandwidth.class)
743 .resource(bwToAllocate);
744 resAlloc = resourceService.allocate(consumer, resource);
745
746 // If allocation for any link fails, then release the partially allocated bandwidth.
747 if (!resAlloc.isPresent()) {
748 resourceService.release(consumer);
749 return null;
750 }
751 }
752 }
753
754 /*
755 * Note: Storing of tunnel consumer id is done by caller of bandwidth reservation function. So deleting tunnel
756 * consumer id should be done by caller of bandwidth releasing function. This will prevent ambiguities related
757 * to who is supposed to store/delete.
758 */
759 return consumer;
760 }
761
762 /*
763 * Deallocates the bandwidth which is reserved locally for PCECC tunnels.
764 */
765 private void releaseBandwidth(Tunnel tunnel) {
766 // Between same source and destination, search the tunnel with same symbolic path name.
767 Collection<Tunnel> tunnelQueryResult = tunnelService.queryTunnel(tunnel.src(), tunnel.dst());
768 Tunnel newTunnel = null;
769 for (Tunnel tunnelObj : tunnelQueryResult) {
770 if (tunnel.tunnelName().value().equals(tunnelObj.tunnelName().value())) {
771 newTunnel = tunnelObj;
772 break;
773 }
774 }
775
776 // Even if one link is shared, the bandwidth release should happen based on shared mechanism.
777 boolean isLinkShared = false;
778 if (newTunnel != null) {
779 for (Link link : tunnel.path().links()) {
780 if (newTunnel.path().links().contains(link)) {
781 isLinkShared = true;
782 break;
783 }
784 }
785 }
786
787 if (isLinkShared) {
788 releaseSharedBandwidth(newTunnel, tunnel);
789 return;
790 }
791
792 resourceService.release(pceStore.getTunnelInfo(tunnel.tunnelId()).tunnelConsumerId());
793 return;
794
795 /*
796 * Note: Storing of tunnel consumer id is done by caller of bandwidth reservation function. So deleting tunnel
797 * consumer id should be done by caller of bandwidth releasing function. This will prevent ambiguities related
798 * to who is supposed to store/delete.
799 */
800 }
801
802 /**
803 * Re-allocates the bandwidth for the tunnel for which the bandwidth was
804 * allocated in shared mode initially.
805 */
806 private synchronized void releaseSharedBandwidth(Tunnel newTunnel, Tunnel oldTunnel) {
807 // 1. Release old tunnel's bandwidth.
808 resourceService.release(pceStore.getTunnelInfo(oldTunnel.tunnelId()).tunnelConsumerId());
809
810 // 2. Release new tunnel's bandwidth
811 ResourceConsumer consumer = pceStore.getTunnelInfo(newTunnel.tunnelId()).tunnelConsumerId();
812 resourceService.release(consumer);
813
814 // 3. Allocate new tunnel's complete bandwidth.
815 double bandwidth = Double.parseDouble(newTunnel.annotations().value(BANDWIDTH));
816 Resource resource;
817
818 for (Link link : newTunnel.path().links()) {
819 resource = Resources.continuous(link.src().deviceId(), link.src().port(), Bandwidth.class)
820 .resource(bandwidth);
821 resourceService.allocate(consumer, resource); // Reusing new tunnel's TunnelConsumerId intentionally.
822 }
823 }
824
825 // Listens on tunnel events.
826 private class InnerTunnelListener implements TunnelListener {
827 @Override
828 public void event(TunnelEvent event) {
829 // Event gets generated with old tunnel object.
830 Tunnel tunnel = event.subject();
831 if (tunnel.type() != MPLS) {
832 return;
833 }
834
835 LspType lspType = LspType.valueOf(tunnel.annotations().value(LSP_SIG_TYPE));
836 String tunnelBandwidth = tunnel.annotations().value(BANDWIDTH);
837 double bwConstraintValue = 0;
838 if (tunnelBandwidth != null) {
839 bwConstraintValue = Double.parseDouble(tunnelBandwidth);
840 }
841
842 switch (event.type()) {
843 case TUNNEL_ADDED:
844 // Allocate bandwidth for non-initiated, delegated LSPs with non-zero bandwidth (learned LSPs).
845 String pceInit = tunnel.annotations().value(PCE_INIT);
846 if (FALSE.equalsIgnoreCase(pceInit)
847 && bwConstraintValue != 0) {
848 reserveBandwidth(tunnel.path(), bwConstraintValue, null);
849 }
850 break;
851
852 case TUNNEL_UPDATED:
853 // Allocate/send labels for basic PCECC tunnels.
854 if ((tunnel.state() == ESTABLISHED) && (lspType == WITHOUT_SIGNALLING_AND_WITHOUT_SR)) {
855 crHandler.allocateLabel(tunnel);
856 }
857
858 if (tunnel.state() == UNSTABLE) {
859 /*
860 * During LSP DB sync if PCC doesn't report LSP which was PCE initiated, it's state is turned into
861 * unstable so that it can be setup again. Add into failed path store so that it can be recomputed
862 * and setup while global reoptimization.
863 */
864
865 List<Constraint> constraints = new LinkedList<>();
866 String bandwidth = tunnel.annotations().value(BANDWIDTH);
867 if (bandwidth != null) {
868 constraints.add(new BandwidthConstraint(Bandwidth
869 .bps(Double.parseDouble(bandwidth))));
870 }
871
872 String costType = tunnel.annotations().value(COST_TYPE);
873 if (costType != null) {
874 CostConstraint costConstraint = new CostConstraint(CostConstraint.Type.valueOf(costType));
875 constraints.add(costConstraint);
876 }
877
878 constraints.add(CapabilityConstraint
879 .of(CapabilityType.valueOf(tunnel.annotations().value(LSP_SIG_TYPE))));
880
881 List<Link> links = tunnel.path().links();
882 pceStore.addFailedPathInfo(new PcePathInfo(links.get(0).src().deviceId(),
883 links.get(links.size() - 1).dst().deviceId(),
884 tunnel.tunnelName().value(), constraints, lspType));
885 }
886 break;
887
888 case TUNNEL_REMOVED:
889 if (lspType != WITH_SIGNALLING) {
890 localLspIdFreeList.add(Short.valueOf(tunnel.annotations().value(LOCAL_LSP_ID)));
891 }
892
893 // If not zero bandwidth, and delegated (initiated LSPs will also be delegated).
894 if (bwConstraintValue != 0) {
895 releaseBandwidth(event.subject());
896
897 // Release basic PCECC labels.
898 if (lspType == WITHOUT_SIGNALLING_AND_WITHOUT_SR) {
899 // Delete stored tunnel consumer id from PCE store (while still retaining label list.)
900 PceccTunnelInfo pceccTunnelInfo = pceStore.getTunnelInfo(tunnel.tunnelId());
901 pceccTunnelInfo.tunnelConsumerId(null);
902 crHandler.releaseLabel(tunnel);
903 } else {
904 pceStore.removeTunnelInfo(tunnel.tunnelId());
905 }
906 }
907 break;
908
909 default:
910 break;
911
912 }
913 return;
914 }
915 }
916
917 private boolean syncLabelDb(DeviceId deviceId) {
918 checkNotNull(deviceId);
919 Map<DeviceId, LabelResourceId> globalNodeLabelMap = pceStore.getGlobalNodeLabels();
920
921 for (Entry<DeviceId, LabelResourceId> entry : globalNodeLabelMap.entrySet()) {
922
923 // Convert from DeviceId to TunnelEndPoint
924 Device srcDevice = deviceService.getDevice(entry.getKey());
925
926 /*
927 * If there is a slight difference in timing such that if device subsystem has removed the device but PCE
928 * store still has it, just ignore such devices.
929 */
930 if (srcDevice == null) {
931 continue;
932 }
933
934 String srcLsrId = srcDevice.annotations().value(LSRID);
935 if (srcLsrId == null) {
936 continue;
937 }
938
939 srTeHandler.advertiseNodeLabelRule(deviceId,
940 entry.getValue(),
941 IpPrefix.valueOf(IpAddress.valueOf(srcLsrId), PREFIX_LENGTH),
942 Objective.Operation.ADD, false);
943 }
944
945 Map<Link, LabelResourceId> adjLabelMap = pceStore.getAdjLabels();
946 for (Entry<Link, LabelResourceId> entry : adjLabelMap.entrySet()) {
947 if (entry.getKey().src().deviceId().equals(deviceId)) {
948 srTeHandler.installAdjLabelRule(deviceId,
949 entry.getValue(),
950 entry.getKey().src().port(),
951 entry.getKey().dst().port(),
952 Objective.Operation.ADD);
953 }
954 }
955
956 srTeHandler.advertiseNodeLabelRule(deviceId,
957 LabelResourceId.labelResourceId(0),
958 IpPrefix.valueOf(END_OF_SYNC_IP_PREFIX),
959 Objective.Operation.ADD, true);
960
961 return true;
962 }
963
964 // Process the packet received.
965 private class PcepPacketProcessor implements PacketProcessor {
966 // Process the packet received and in our case initiates the label DB sync.
967 @Override
968 public void process(PacketContext context) {
969 // Stop processing if the packet has been handled, since we
970 // can't do any more to it.
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530971 if (context.isHandled()) {
972 return;
973 }
974
975 InboundPacket pkt = context.inPacket();
Avantika-Huaweid1e36bd2016-05-26 12:47:16 +0530976 if (pkt == null) {
977 return;
978 }
979
980 Ethernet ethernet = pkt.parsed();
981 if (ethernet == null || ethernet.getEtherType() != Ethernet.TYPE_IPV4) {
982 return;
983 }
984
985 IPv4 ipPacket = (IPv4) ethernet.getPayload();
986 if (ipPacket == null || ipPacket.getProtocol() != IPv4.PROTOCOL_TCP) {
987 return;
988 }
989
990 TCP tcp = (TCP) ipPacket.getPayload();
991 if (tcp == null || tcp.getDestinationPort() != PCEP_PORT) {
992 return;
993 }
994
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530995 syncLabelDb(pkt.receivedFrom().deviceId());
996 }
997 }
998
Priyanka B9fa4ed32016-05-27 11:59:24 +0530999 //Computes path from tunnel store and also path failed to setup.
1000 private void callForOptimization() {
1001 //Recompute the LSPs which it was delegated [LSPs stored in PCE store (failed paths)]
1002 for (PcePathInfo failedPathInfo : pceStore.getFailedPathInfos()) {
1003 checkForMasterAndSetupPath(failedPathInfo);
1004 }
1005
1006 //Recompute the LSPs for which it was delegated [LSPs stored in tunnel store]
1007 tunnelService.queryTunnel(MPLS).forEach(t -> {
1008 checkForMasterAndUpdateTunnel(t.path().src().deviceId(), t);
1009 });
1010 }
1011
1012 private boolean checkForMasterAndSetupPath(PcePathInfo failedPathInfo) {
1013 /**
1014 * Master of ingress node will setup the path failed stored in PCE store.
1015 */
1016 if (mastershipService.isLocalMaster(failedPathInfo.src())) {
1017 if (setupPath(failedPathInfo.src(), failedPathInfo.dst(), failedPathInfo.name(),
1018 failedPathInfo.constraints(), failedPathInfo.lspType())) {
1019 // If computation is success remove that path
1020 pceStore.removeFailedPathInfo(failedPathInfo);
1021 return true;
1022 }
1023 }
1024
1025 return false;
1026 }
1027
1028 //Timer to call global optimization
1029 private class GlobalOptimizationTimer implements Runnable {
1030
1031 public GlobalOptimizationTimer() {
1032 }
1033
1034 @Override
1035 public void run() {
1036 callForOptimization();
1037 }
1038 }
Avantika-Huawei73862d42016-05-12 18:58:06 +05301039}