blob: 2a10dcf298ff8c84b5cea72a8fc051ba9dd617da [file] [log] [blame]
Mahesh Poojary Sa4df1aa2016-05-13 08:53:53 +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;
19
20import java.util.Collection;
21import java.util.Iterator;
22import java.util.HashSet;
23import java.util.List;
24import java.util.LinkedList;
25import java.util.Map;
26import java.util.Set;
27
28import org.onosproject.incubator.net.resource.label.DefaultLabelResource;
29import org.onosproject.incubator.net.resource.label.LabelResource;
30import org.onosproject.incubator.net.resource.label.LabelResourceId;
31import org.onosproject.incubator.net.resource.label.LabelResourceAdminService;
32import org.onosproject.incubator.net.resource.label.LabelResourceService;
33import org.onosproject.incubator.net.tunnel.DefaultLabelStack;
34import org.onosproject.incubator.net.tunnel.LabelStack;
35import org.onosproject.net.DeviceId;
36import org.onosproject.pce.pcestore.api.PceStore;
37import org.onosproject.net.Link;
38import org.onosproject.net.Path;
39
40import org.slf4j.Logger;
41import org.slf4j.LoggerFactory;
42
43import com.google.common.collect.ArrayListMultimap;
44import com.google.common.collect.Multimap;
45
46/**
47 * PCE SR-BE and SR-TE functionality.
48 * SR-BE: Each node (PCC) is allocated a node-SID (label) by the PCECC. The PCECC sends PCLabelUpd to
49 * update the label map of each node to all the nodes in the domain.
50 * SR-TE: apart from node-SID, Adj-SID is used where each adjacency is allocated an Adj-SID (label) by the PCECC.
51 * The PCECC sends PCLabelUpd to update the label map of each Adj to the corresponding nodes in the domain.
52 */
53public final class PceccSrTeBeHandler {
54 private static final Logger log = LoggerFactory.getLogger(PceccSrTeBeHandler.class);
55
56 private static final String LABEL_RESOURCE_ADMIN_SERVICE_NULL = "Label Resource Admin Service cannot be null";
57 private static final String LABEL_RESOURCE_SERVICE_NULL = "Label Resource Service cannot be null";
58 private static final String PCE_STORE_NULL = "PCE Store cannot be null";
59 private static final String DEVICE_SERVICE_NULL = "Device Service cannot be null";
60 private static final String DEVICE_ID_NULL = "Device-Id cannot be null";
61 private static final String LSR_ID_NULL = "LSR-Id cannot be null";
62 private static final String DEVICE_ID_LSR_ID_MAP_NULL = "Device-Id and LSR-Id map cannot be null";
63 private static final String LINK_NULL = "Link cannot be null";
64 private static final String PATH_NULL = "Path cannot be null";
65 private static final String LSR_ID = "lsrId";
66 private static final int PREFIX_LENGTH = 32;
67 private static PceccSrTeBeHandler srTeHandlerInstance = null;
68 private LabelResourceAdminService labelRsrcAdminService;
69 private LabelResourceService labelRsrcService;
70 private PceStore pceStore;
71
72 /**
73 * Initializes default values.
74 */
75 private PceccSrTeBeHandler() {
76 }
77
78 /**
79 * Returns single instance of this class.
80 *
81 * @return this class single instance
82 */
83 public static PceccSrTeBeHandler getInstance() {
84 if (srTeHandlerInstance == null) {
85 srTeHandlerInstance = new PceccSrTeBeHandler();
86 }
87 return srTeHandlerInstance;
88 }
89
90 /**
91 * Initialization of label manager interfaces and pce store.
92 *
93 * @param labelRsrcAdminService label resource admin service
94 * @param labelRsrcService label resource service
95 * @param pceStore PCE label store
96 */
97 public void initialize(LabelResourceAdminService labelRsrcAdminService,
98 LabelResourceService labelRsrcService, PceStore pceStore) {
99 this.labelRsrcAdminService = labelRsrcAdminService;
100 this.labelRsrcService = labelRsrcService;
101 this.pceStore = pceStore;
102 }
103
104 /**
105 * Reserves the global label pool.
106 *
107 * @param beginLabel minimum value of global label space
108 * @param endLabel maximum value of global label space
109 * @return success or failure
110 */
111 public boolean reserveGlobalPool(long beginLabel, long endLabel) {
112 checkNotNull(labelRsrcAdminService, LABEL_RESOURCE_ADMIN_SERVICE_NULL);
113 return labelRsrcAdminService.createGlobalPool(LabelResourceId.labelResourceId(beginLabel),
114 LabelResourceId.labelResourceId(endLabel));
115 }
116
117 /**
118 * Allocates node label from global node label pool to specific device.
119 * Configure this device with labels and lsrid mapping of all other devices and vice versa.
120 *
121 * @param specificDeviceId node label needs to be allocated to specific device
122 * @param specificLsrId lsrid of specific device
123 * @param deviceIdLsrIdMap deviceid and lsrid mapping
124 * @return success or failure
125 */
126 public boolean allocateNodeLabel(DeviceId specificDeviceId, String specificLsrId,
127 Map<DeviceId, String> deviceIdLsrIdMap) {
128 long applyNum = 1; // For each node only one node label
129 LabelResourceId specificLabelId = null;
130
131 checkNotNull(specificDeviceId, DEVICE_ID_NULL);
132 checkNotNull(specificLsrId, LSR_ID_NULL);
133 checkNotNull(deviceIdLsrIdMap, DEVICE_ID_LSR_ID_MAP_NULL);
134 checkNotNull(labelRsrcService, LABEL_RESOURCE_SERVICE_NULL);
135 checkNotNull(pceStore, PCE_STORE_NULL);
136
137 // The specificDeviceId is the new device and is not there in the deviceIdLsrIdMap.
138 // So, first generate its label and configure label and its lsr-id to it.
139 Collection<LabelResource> result = labelRsrcService.applyFromGlobalPool(applyNum);
140 if (result.size() > 0) {
141 // Only one element (label-id) to retrieve
142 Iterator<LabelResource> iterator = result.iterator();
143 DefaultLabelResource defaultLabelResource = (DefaultLabelResource) iterator.next();
144 specificLabelId = defaultLabelResource.labelResourceId();
145 if (specificLabelId == null) {
146 log.error("Unable to retrieve global node label for a device id {}.", specificDeviceId.toString());
147 return false;
148 }
149 } else {
150 log.error("Unable to allocate global node label for a device id {}.", specificDeviceId.toString());
151 return false;
152 }
153
154 pceStore.addGlobalNodeLabel(specificDeviceId, specificLabelId);
155 //TODO: uncomment below line once advertiseNodeLabelRule() is ready
156 // Push its label information into specificDeviceId
157 //advertiseNodeLabelRule(specificDeviceId, specificLabelId,
158 // IpPrefix.valueOf(IpAddress.valueOf(specificLsrId), PREFIX_LENGTH),
159
160 // Configure (node-label, lsr-id) mapping of each devices in list to specific device and vice versa.
161 for (Map.Entry element:deviceIdLsrIdMap.entrySet()) {
162 DeviceId otherDevId = (DeviceId) element.getKey();
163 String otherLsrId = (String) element.getValue();
164 if (otherLsrId == null) {
165 log.error("The lsr-id of device id {} is null.", otherDevId.toString());
166 releaseNodeLabel(specificDeviceId, specificLsrId, deviceIdLsrIdMap);
167 return false;
168 }
169
170 // Label for other device in list should be already allocated.
171 LabelResourceId otherLabelId = pceStore.getGlobalNodeLabel(otherDevId);
172 if (otherLabelId == null) {
173 log.error("Unable to find global node label in store for a device id {}.", otherDevId.toString());
174 releaseNodeLabel(specificDeviceId, specificLsrId, deviceIdLsrIdMap);
175 return false;
176 }
177
178 // Push to device
179 // TODO: uncomment below line once advertiseNodeLabelRule() is ready
180 // Push label information of specificDeviceId to otherDevId in list and vice versa.
181 //advertiseNodeLabelRule(otherDevId, specificLabelId, IpPrefix.valueOf(IpAddress.valueOf(specificLsrId),
182 // PREFIX_LENGTH), Objective.Operation.ADD);
183 //advertiseNodeLabelRule(specificDeviceId, otherLabelId, IpPrefix.valueOf(IpAddress.valueOf(otherLsrId),
184 // PREFIX_LENGTH), Objective.Operation.ADD);
185 }
186
187 return true;
188 }
189
190 /**
191 * Releases assigned node label of specific device from global node label pool and pce store.
192 * and remove configured this node label from all other devices.
193 *
194 * @param specificDeviceId node label needs to be released for specific device
195 * @param specificLsrId lsrid of specific device
196 * @param deviceIdLsrIdMap deviceid and lsrid mapping
197 * @return success or failure
198 */
199 public boolean releaseNodeLabel(DeviceId specificDeviceId, String specificLsrId,
200 Map<DeviceId, String> deviceIdLsrIdMap) {
201 checkNotNull(specificDeviceId, DEVICE_ID_NULL);
202 checkNotNull(specificLsrId, LSR_ID_NULL);
203 checkNotNull(deviceIdLsrIdMap, DEVICE_ID_LSR_ID_MAP_NULL);
204 checkNotNull(labelRsrcService, LABEL_RESOURCE_SERVICE_NULL);
205 checkNotNull(pceStore, PCE_STORE_NULL);
206 boolean retValue = true;
207
208 // Release node label entry of this specific device from all other devices
209 // Retrieve node label of this specific device from store
210 LabelResourceId labelId = pceStore.getGlobalNodeLabel(specificDeviceId);
211 if (labelId == null) {
212 log.error("Unable to retrieve label of a device id {} from store.", specificDeviceId.toString());
213 return false;
214 }
215
216 // Go through all devices in the map and remove label entry
217 for (Map.Entry element:deviceIdLsrIdMap.entrySet()) {
218 DeviceId otherDevId = (DeviceId) element.getKey();
219
220 // Remove this specific device label information from all other nodes except
221 // this specific node where connection already lost.
222 if (!specificDeviceId.equals(otherDevId)) {
223 //TODO: uncomment below lines once advertiseNodeLabelRule() is ready
224 //advertiseNodeLabelRule(otherDevId, labelId, IpPrefix.valueOf(IpAddress.valueOf(specificLsrId),
225 // PREFIX_LENGTH), Objective.Operation.REMOVE);
226 }
227 }
228
229 // Release from label manager
230 Set<LabelResourceId> release = new HashSet<>();
231 release.add(labelId);
232 if (!labelRsrcService.releaseToGlobalPool(release)) {
233 log.error("Unable to release label id {} from label manager.", labelId.toString());
234 retValue = false;
235 }
236
237 // Remove from store
238 if (!pceStore.removeGlobalNodeLabel(specificDeviceId)) {
239 log.error("Unable to remove global node label id {} from store.", labelId.toString());
240 retValue = false;
241 }
242
243 return retValue;
244 }
245
246 /**
247 * Allocates adjacency label to a link from local resource pool by a specific device id.
248 *
249 * @param link between devices
250 * @return success or failure
251 */
252 public boolean allocateAdjacencyLabel(Link link) {
253 long applyNum = 1; // Single label to each link.
254 DeviceId srcDeviceId = link.src().deviceId();
255 Collection<LabelResource> labelList;
256
257 checkNotNull(link, LINK_NULL);
258 checkNotNull(labelRsrcService, LABEL_RESOURCE_SERVICE_NULL);
259 checkNotNull(pceStore, PCE_STORE_NULL);
260
261 // Allocate adjacency label to a link from label manager.
262 // Take label from source device pool to allocate.
263 labelList = labelRsrcService.applyFromDevicePool(srcDeviceId, applyNum);
264 if (labelList.size() <= 0) {
265 log.error("Unable to allocate label to a device id {}.", srcDeviceId.toString());
266 return false;
267 }
268
269 // Currently only one label to a device. So, no need to iterate through list
270 Iterator<LabelResource> iterator = labelList.iterator();
271 DefaultLabelResource defaultLabelResource = (DefaultLabelResource) iterator.next();
272 LabelResourceId labelId = defaultLabelResource.labelResourceId();
273 if (labelId == null) {
274 log.error("Unable to allocate label to a device id {}.", srcDeviceId.toString());
275 return false;
276 }
277 log.debug("Allocated adjacency label {} to a link {}.", labelId.toString(),
278 link.toString());
279
280 // Push adjacency label to device
281 //TODO: uncomment below line once installAdjLabelRule() method is ready
282 //installAdjLabelRule(srcDeviceId, labelId, link.src().port(), link.dst().port(), Objective.Operation.ADD);
283
284 // Save in store
285 pceStore.addAdjLabel(link, labelId);
286 return true;
287 }
288
289 /**
290 * Releases unused adjacency labels from device pools.
291 *
292 * @param link between devices
293 * @return success or failure
294 */
295 public boolean releaseAdjacencyLabel(Link link) {
296 checkNotNull(link, LINK_NULL);
297 checkNotNull(labelRsrcService, LABEL_RESOURCE_SERVICE_NULL);
298 checkNotNull(pceStore, PCE_STORE_NULL);
299 boolean retValue = true;
300
301 // Retrieve link label from store
302 LabelResourceId labelId = pceStore.getAdjLabel(link);
303 if (labelId == null) {
304 log.error("Unabel to retrieve label for a link {} from store.", link.toString());
305 return false;
306 }
307
308 // Device
309 DeviceId srcDeviceId = link.src().deviceId();
310
311 // Release adjacency label from device
312 //TODO: uncomment below line once installAdjLabelRule() method is ready
313 //installAdjLabelRule(srcDeviceId, labelId, link.src().port(), link.dst().port(), Objective.Operation.REMOVE);
314
315 // Release link label from label manager
316 Multimap<DeviceId, LabelResource> release = ArrayListMultimap.create();
317 DefaultLabelResource defaultLabelResource = new DefaultLabelResource(srcDeviceId, labelId);
318 release.put(srcDeviceId, defaultLabelResource);
319 if (!labelRsrcService.releaseToDevicePool(release)) {
320 log.error("Unable to release label id {} from label manager.", labelId.toString());
321 retValue = false;
322 }
323
324 // Remove adjacency label from store
325 if (!pceStore.removeAdjLabel(link)) {
326 log.error("Unable to remove adjacency label id {} from store.", labelId.toString());
327 retValue = false;
328 }
329 return retValue;
330 }
331
332 /**
333 * Computes label stack for a path.
334 *
335 * @param path lsp path
336 * @return label stack
337 */
338 public LabelStack computeLabelStack(Path path) {
339 checkNotNull(path, PATH_NULL);
340 // Label stack is linked list to make labels in order.
341 List<LabelResourceId> labelStack = new LinkedList<>();
342 List<Link> linkList = path.links();
343 if ((linkList != null) && (linkList.size() > 0)) {
344 // Path: [x] ---- [y] ---- [z]
345 // For other than last link, add only source[x] device label.
346 // For the last link, add both source[y] and destination[z] device labels.
347 // For all links add adjacency label
348 Link link = null;
349 LabelResourceId nodeLabelId = null;
350 LabelResourceId adjLabelId = null;
351 DeviceId deviceId = null;
352 for (Iterator<Link> iterator = linkList.iterator(); iterator.hasNext();) {
353 link = (Link) iterator.next();
354 // Add source device label now
355 deviceId = link.src().deviceId();
356 nodeLabelId = pceStore.getGlobalNodeLabel(deviceId);
357 if (nodeLabelId == null) {
358 log.error("Unable to find node label for a device id {} in store.", deviceId.toString());
359 return null;
360 }
361 labelStack.add(nodeLabelId);
362
363 // Add adjacency label for this link
364 adjLabelId = pceStore.getAdjLabel(link);
365 if (adjLabelId == null) {
366 log.error("Adjacency label id is null for a link {}.", link.toString());
367 return null;
368 }
369 labelStack.add(adjLabelId);
370 }
371
372 // This is the last link in path
373 // Add destination device label now.
374 if (link != null) {
375 deviceId = link.dst().deviceId();
376 nodeLabelId = pceStore.getGlobalNodeLabel(deviceId);
377 if (nodeLabelId == null) {
378 log.error("Unable to find node label for a device id {} in store.", deviceId.toString());
379 return null;
380 }
381 labelStack.add(nodeLabelId);
382 }
383 } else {
384 log.debug("Empty link in path.");
385 return null;
386 }
387 return new DefaultLabelStack(labelStack);
388 }
389}