blob: f8c3ec0f450cb360f145e30c7ffe4f10c9ebdfb6 [file] [log] [blame]
Priyanka B9bee0802016-04-27 22:06:02 +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.provider.bgpcep.flow.impl;
17
Priyanka Bbd455ca2016-05-05 22:13:25 +053018import java.util.LinkedList;
19import java.util.List;
20
Priyanka B9bee0802016-04-27 22:06:02 +053021import org.apache.felix.scr.annotations.Activate;
22import org.apache.felix.scr.annotations.Component;
23import org.apache.felix.scr.annotations.Deactivate;
24import org.apache.felix.scr.annotations.Reference;
25import org.apache.felix.scr.annotations.ReferenceCardinality;
Priyanka Bbd455ca2016-05-05 22:13:25 +053026import org.onlab.packet.Ip4Address;
27import org.onlab.packet.IpAddress;
28import org.onlab.packet.IpPrefix;
Priyanka B9bee0802016-04-27 22:06:02 +053029import org.onosproject.bgp.controller.BgpController;
30import org.onosproject.cfg.ComponentConfigService;
31import org.onosproject.core.ApplicationId;
Priyanka Bbd455ca2016-05-05 22:13:25 +053032import org.onosproject.incubator.net.resource.label.LabelResourceId;
33import org.onosproject.incubator.net.tunnel.IpTunnelEndPoint;
34import org.onosproject.incubator.net.tunnel.Tunnel;
35import org.onosproject.incubator.net.tunnel.TunnelId;
36import org.onosproject.incubator.net.tunnel.TunnelService;
37import org.onosproject.net.ConnectPoint;
38import org.onosproject.net.DeviceId;
39import org.onosproject.net.Link;
40import org.onosproject.net.Path;
41import org.onosproject.net.PortNumber;
Priyanka B9bee0802016-04-27 22:06:02 +053042import org.onosproject.net.flow.FlowRule;
43import org.onosproject.net.flow.FlowRuleBatchOperation;
44import org.onosproject.net.flow.FlowRuleProvider;
45import org.onosproject.net.flow.FlowRuleProviderRegistry;
46import org.onosproject.net.flow.FlowRuleProviderService;
47import org.onosproject.net.flow.criteria.Criterion;
Priyanka Bbd455ca2016-05-05 22:13:25 +053048import org.onosproject.net.flowobjective.Objective;
Priyanka B9bee0802016-04-27 22:06:02 +053049import org.onosproject.net.provider.AbstractProvider;
50import org.onosproject.net.provider.ProviderId;
51import org.onosproject.net.resource.ResourceService;
52import org.onosproject.pcep.controller.PcepClient;
53import org.onosproject.pcep.controller.PcepClientController;
Priyanka Bbd455ca2016-05-05 22:13:25 +053054import org.onosproject.pcepio.exceptions.PcepParseException;
55import org.onosproject.pcepio.protocol.PcepEroObject;
56import org.onosproject.pcepio.protocol.PcepFecObjectIPv4;
57import org.onosproject.pcepio.protocol.PcepFecObjectIPv4Adjacency;
58import org.onosproject.pcepio.protocol.PcepLabelObject;
59import org.onosproject.pcepio.protocol.PcepLabelUpdate;
60import org.onosproject.pcepio.protocol.PcepLabelUpdateMsg;
61import org.onosproject.pcepio.protocol.PcepLspObject;
62import org.onosproject.pcepio.protocol.PcepMsgPath;
63import org.onosproject.pcepio.protocol.PcepSrpObject;
64import org.onosproject.pcepio.protocol.PcepUpdateMsg;
65import org.onosproject.pcepio.protocol.PcepUpdateRequest;
66import org.onosproject.pcepio.types.IPv4SubObject;
67import org.onosproject.pcepio.types.NexthopIPv4addressTlv;
68import org.onosproject.pcepio.types.PcepLabelDownload;
69import org.onosproject.pcepio.types.PcepLabelMap;
70import org.onosproject.pcepio.types.PcepValueType;
71import org.onosproject.pcepio.types.StatefulIPv4LspIdentifiersTlv;
72import org.onosproject.provider.pcep.tunnel.impl.SrpIdGenerators;
73import org.onosproject.provider.pcep.tunnel.impl.PcepAnnotationKeys;
Priyanka B9bee0802016-04-27 22:06:02 +053074import org.osgi.service.component.ComponentContext;
75import org.slf4j.Logger;
76
Avantika-Huawei7c14e662016-05-16 19:13:34 +053077import static org.onosproject.pcep.controller.PcepSyncStatus.IN_SYNC;
78import static org.onosproject.pcep.controller.PcepSyncStatus.SYNCED;
79import static com.google.common.base.Preconditions.checkNotNull;
Priyanka B9bee0802016-04-27 22:06:02 +053080import static org.slf4j.LoggerFactory.getLogger;
81
82/**
83 * Implementation of BGP-PCEP flow provider.
84 */
85@Component(immediate = true)
86public class BgpcepFlowRuleProvider extends AbstractProvider
87 implements FlowRuleProvider {
88
89 private final Logger log = getLogger(getClass());
90
91 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
92 protected FlowRuleProviderRegistry providerRegistry;
93
94 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
95 protected ComponentConfigService cfgService;
96
97 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
98 protected BgpController bgpController;
99
100 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
101 protected PcepClientController pcepController;
102
103 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
104 protected ResourceService resourceService;
105
Priyanka Bbd455ca2016-05-05 22:13:25 +0530106 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
107 protected TunnelService tunnelService;
108
Priyanka B9bee0802016-04-27 22:06:02 +0530109 private FlowRuleProviderService providerService;
Priyanka Bbd455ca2016-05-05 22:13:25 +0530110 private PcepLabelObject labelObj;
111 public static final int OUT_LABEL_TYPE = 0;
112 public static final int IN_LABEL_TYPE = 1;
113 public static final long IDENTIFIER_SET = 0x100000000L;
114 public static final long SET = 0xFFFFFFFFL;
Priyanka B9bee0802016-04-27 22:06:02 +0530115
116 /**
117 * Creates a BgpFlow host provider.
118 */
119 public BgpcepFlowRuleProvider() {
120 super(new ProviderId("l3", "org.onosproject.provider.bgpcep"));
121 }
122
123 @Activate
124 public void activate(ComponentContext context) {
125 cfgService.registerProperties(getClass());
126 providerService = providerRegistry.register(this);
127 log.info("Started");
128 }
129
130 @Deactivate
131 public void deactivate(ComponentContext context) {
132 cfgService.unregisterProperties(getClass(), false);
133 providerRegistry.unregister(this);
134 providerService = null;
135 log.info("Stopped");
136 }
137
138 @Override
139 public void applyFlowRule(FlowRule... flowRules) {
140 for (FlowRule flowRule : flowRules) {
141 applyRule(flowRule);
142 }
143 }
144
145 private void applyRule(FlowRule flowRule) {
146 flowRule.selector().criteria()
147 .forEach(c -> {
148 // If Criterion type is MPLS_LABEL, push labels through PCEP client
149 if (c.type() == Criterion.Type.MPLS_LABEL) {
150 PcepClient pcc;
151 /** PCC client session is based on LSR ID, get the LSR ID for a specific device to
152 push the flows */
153
154 //TODO: commented code has dependency with other patch
155 /* Set<TeRouterId> lrsIds = resourceService.getAvailableResourceValues(Resources
156 .discrete(flowRule.deviceId()).id(), TeRouterId.class);
157
158 lrsIds.forEach(lsrId ->
159 {
160 if (pcepController.getClient(PccId.pccId(lsrId)) != null) {
161 pcc = pcepController.getClient(PccId.pccId(lsrId));
162 }
163 });*/
164 // TODO: Build message and send the PCEP label message via PCEP client
165 } else {
166 // TODO: Get the BGP peer based on deviceId and send the message
167 }
168 });
169 }
170
Priyanka Bbd455ca2016-05-05 22:13:25 +0530171 /**
172 * Returns PCEP client.
173 *
174 * @return PCEP client
175 */
176 private PcepClient getPcepClient(DeviceId deviceId) {
177 PcepClient pcc;
178 //TODO: commented code has dependency
179 /* Set<TeRouterId> lrsIds = resourceService.getAvailableResourceValues(Resources
180 .discrete(deviceId()).id(), TeRouterId.class);
181
182 lrsIds.forEach(lsrId ->
183 {
184 if (pcepController.getClient(PccId.pccId(lsrId)) != null) {
185 pcc = pcepController.getClient(PccId.pccId(lsrId));
186 return pcc
187 }
188 });*/
189 return null;
190 }
191
192 //Pushes node labels to the specified device.
193 private void pushGlobalNodeLabel(DeviceId deviceId, LabelResourceId labelId,
Avantika-Huawei7c14e662016-05-16 19:13:34 +0530194 IpPrefix ipPrefix, Objective.Operation type, boolean isBos) throws PcepParseException {
195
196 checkNotNull(deviceId);
197 checkNotNull(labelId);
198 checkNotNull(ipPrefix);
199 checkNotNull(type);
200
Priyanka Bbd455ca2016-05-05 22:13:25 +0530201 PcepClient pc = getPcepClient(deviceId);
202 if (pc == null) {
203 log.error("PCEP client not found");
204 return;
205 }
206
207 LinkedList<PcepLabelUpdate> labelUpdateList = new LinkedList<>();
208
209 PcepFecObjectIPv4 fecObject = pc.factory().buildFecObjectIpv4()
210 .setNodeID(ipPrefix.address().getIp4Address().toInt())
211 .build();
212
Avantika-Huawei7c14e662016-05-16 19:13:34 +0530213 boolean bSFlag = false;
214 if (pc.labelDbSyncStatus() == IN_SYNC) {
215 if (isBos) {
216 /*
217 * Now the sync is completed.
218 * Need to send label DB end-of-sync msg, i.e. S flag in SRP id is reset.
219 */
220 pc.setLabelDbSyncStatus(SYNCED);
221 } else {
222 bSFlag = true;
223 }
224 }
225
226 PcepSrpObject srpObj = getSrpObject(pc, type, bSFlag);
Priyanka Bbd455ca2016-05-05 22:13:25 +0530227
228 //Global NODE-SID as label object
229 PcepLabelObject labelObject = pc.factory().buildLabelObject()
230 .setLabel((int) labelId.labelId())
231 .build();
232
233 PcepLabelMap labelMap = new PcepLabelMap();
234 labelMap.setFecObject(fecObject);
235 labelMap.setLabelObject(labelObject);
236 labelMap.setSrpObject(srpObj);
237
238 labelUpdateList.add(pc.factory().buildPcepLabelUpdateObject()
239 .setLabelMap(labelMap)
240 .build());
241
242 PcepLabelUpdateMsg labelMsg = pc.factory().buildPcepLabelUpdateMsg()
243 .setPcLabelUpdateList(labelUpdateList)
244 .build();
245
246 pc.sendMessage(labelMsg);
247 }
248
Avantika-Huawei7c14e662016-05-16 19:13:34 +0530249 private PcepSrpObject getSrpObject(PcepClient pc, Objective.Operation type, boolean bSFlag)
250 throws PcepParseException {
Priyanka Bbd455ca2016-05-05 22:13:25 +0530251 PcepSrpObject srpObj;
Avantika-Huawei7c14e662016-05-16 19:13:34 +0530252 boolean bRFlag = false;
253
254 if (!type.equals(Objective.Operation.ADD)) {
255 // To cleanup labels, R bit is set
256 bRFlag = true;
Priyanka Bbd455ca2016-05-05 22:13:25 +0530257 }
Avantika-Huawei7c14e662016-05-16 19:13:34 +0530258
259 srpObj = pc.factory().buildSrpObject()
260 .setRFlag(bRFlag)
261 .setSFlag(bSFlag)
262 .setSrpID(SrpIdGenerators.create())
263 .build();
264
Priyanka Bbd455ca2016-05-05 22:13:25 +0530265 return srpObj;
266 }
267
268 //Pushes adjacency labels to the specified device.
269 private void pushAdjacencyLabel(DeviceId deviceId, LabelResourceId labelId,
270 PortNumber srcPortNum, PortNumber dstPortNum, Objective.Operation type) throws PcepParseException {
Avantika-Huawei7c14e662016-05-16 19:13:34 +0530271
272 checkNotNull(deviceId);
273 checkNotNull(labelId);
274 checkNotNull(srcPortNum);
275 checkNotNull(dstPortNum);
276 checkNotNull(type);
277
Priyanka Bbd455ca2016-05-05 22:13:25 +0530278 PcepClient pc = getPcepClient(deviceId);
279 if (pc == null) {
280 log.error("PCEP client not found");
281 return;
282 }
283
284 LinkedList<PcepLabelUpdate> labelUpdateList = new LinkedList<>();
285
286 long srcPortNo = srcPortNum.toLong();
287 long dstPortNo = dstPortNum.toLong();
288 srcPortNo = ((srcPortNo & IDENTIFIER_SET) == IDENTIFIER_SET) ? srcPortNo & SET : srcPortNo;
289 dstPortNo = ((dstPortNo & IDENTIFIER_SET) == IDENTIFIER_SET) ? dstPortNo & SET : dstPortNo;
290
291 PcepFecObjectIPv4Adjacency fecAdjObject = pc.factory().buildFecIpv4Adjacency()
292 .seRemoteIPv4Address((int) dstPortNo)
293 .seLocalIPv4Address((int) srcPortNo)
294 .build();
295
Avantika-Huawei7c14e662016-05-16 19:13:34 +0530296 PcepSrpObject srpObj = getSrpObject(pc, type, false);
Priyanka Bbd455ca2016-05-05 22:13:25 +0530297
298 //Adjacency label object
299 PcepLabelObject labelObject = pc.factory().buildLabelObject()
300 .setLabel((int) labelId.labelId())
301 .build();
302
303 PcepLabelMap labelMap = new PcepLabelMap();
304 labelMap.setFecObject(fecAdjObject);
305 labelMap.setLabelObject(labelObject);
306 labelMap.setSrpObject(srpObj);
307
308 labelUpdateList.add(pc.factory().buildPcepLabelUpdateObject()
309 .setLabelMap(labelMap)
310 .build());
311
312 PcepLabelUpdateMsg labelMsg = pc.factory().buildPcepLabelUpdateMsg()
313 .setPcLabelUpdateList(labelUpdateList)
314 .build();
315
316 pc.sendMessage(labelMsg);
317 }
318
319 //Pushes local labels to the device which is specific to path [CR-case].
320 private void pushLocalLabels(DeviceId deviceId, LabelResourceId labelId,
321 PortNumber portNum, TunnelId tunnelId,
322 Boolean isBos, Long labelType, Objective.Operation type) throws PcepParseException {
323
Avantika-Huawei7c14e662016-05-16 19:13:34 +0530324 checkNotNull(deviceId);
325 checkNotNull(labelId);
326 checkNotNull(portNum);
327 checkNotNull(tunnelId);
328 checkNotNull(labelType);
329 checkNotNull(type);
330
Priyanka Bbd455ca2016-05-05 22:13:25 +0530331 PcepClient pc = getPcepClient(deviceId);
332 if (pc == null) {
333 log.error("PCEP client not found");
334 return;
335 }
336
337 PcepLspObject lspObj;
338 LinkedList<PcepLabelUpdate> labelUpdateList = new LinkedList<>();
339 LinkedList<PcepLabelObject> labelObjects = new LinkedList<>();
340 PcepSrpObject srpObj;
341 PcepLabelDownload labelDownload = new PcepLabelDownload();
342 LinkedList<PcepValueType> optionalTlv = new LinkedList<>();
343
344 long portNo = portNum.toLong();
345 portNo = ((portNo & IDENTIFIER_SET) == IDENTIFIER_SET) ? portNo & SET : portNo;
346
347 optionalTlv.add(NexthopIPv4addressTlv.of((int) portNo));
348
349 Tunnel tunnel = tunnelService.queryTunnel(tunnelId);
350
351 PcepLabelObject labelObj = pc.factory().buildLabelObject()
352 .setOFlag(labelType == OUT_LABEL_TYPE ? true : false)
353 .setOptionalTlv(optionalTlv)
354 .setLabel((int) labelId.labelId())
355 .build();
356
357 /**
358 * Check whether transit node or not. For transit node, label update message should include IN and OUT labels.
359 * Hence store IN label object and next when out label comes add IN and OUT label objects and encode label
360 * update message and send to specified client.
361 */
362 if (!deviceId.equals(tunnel.path().src().deviceId()) && !deviceId.equals(tunnel.path().dst().deviceId())) {
363 //Device is transit node
364 if (labelType == IN_LABEL_TYPE) {
365 //Store label object having IN label value
366 this.labelObj = labelObj;
367 return;
368 }
369 //Add IN label object
370 labelObjects.add(this.labelObj);
371 }
372
373 //Add OUT label object in case of transit node
374 labelObjects.add(labelObj);
375
Avantika-Huawei7c14e662016-05-16 19:13:34 +0530376 srpObj = getSrpObject(pc, type, false);
Priyanka Bbd455ca2016-05-05 22:13:25 +0530377
378 String lspId = tunnel.annotations().value(PcepAnnotationKeys.PLSP_ID);
379 String plspId = tunnel.annotations().value(PcepAnnotationKeys.LOCAL_LSP_ID);
380 String tunnelIdentifier = tunnel.annotations().value(PcepAnnotationKeys.PCC_TUNNEL_ID);
381
382 LinkedList<PcepValueType> tlvs = new LinkedList<>();
383 StatefulIPv4LspIdentifiersTlv lspIdTlv = new StatefulIPv4LspIdentifiersTlv(((IpTunnelEndPoint) tunnel.src())
384 .ip().getIp4Address().toInt(), Short.valueOf(lspId), Short.valueOf(tunnelIdentifier), 0,
385 ((IpTunnelEndPoint) tunnel.dst()).ip().getIp4Address().toInt());
386 tlvs.add(lspIdTlv);
387
388 lspObj = pc.factory().buildLspObject()
389 .setRFlag(false)
390 .setAFlag(true)
391 .setDFlag(true)
392 .setPlspId(Integer.valueOf(plspId))
393 .setOptionalTlv(tlvs)
394 .build();
395
396 labelDownload.setLabelList(labelObjects);
397 labelDownload.setLspObject(lspObj);
398 labelDownload.setSrpObject(srpObj);
399
400 labelUpdateList.add(pc.factory().buildPcepLabelUpdateObject()
401 .setLabelDownload(labelDownload)
402 .build());
403
404 PcepLabelUpdateMsg labelMsg = pc.factory().buildPcepLabelUpdateMsg()
405 .setPcLabelUpdateList(labelUpdateList)
406 .build();
407
408 pc.sendMessage(labelMsg);
409
410 //If isBos is true, label download is done along the LSP, send PCEP update message.
411 if (isBos) {
412 sendPcepUpdateMsg(pc, lspObj, tunnel);
413 }
414 }
415
416 //Sends PCEP update message.
417 private void sendPcepUpdateMsg(PcepClient pc, PcepLspObject lspObj, Tunnel tunnel) throws PcepParseException {
418 LinkedList<PcepUpdateRequest> updateRequestList = new LinkedList<>();
419 LinkedList<PcepValueType> subObjects = createEroSubObj(tunnel.path());
420
421 if (subObjects == null) {
422 log.error("ERO subjects not present");
423 return;
424 }
425
426 PcepSrpObject srpObj = pc.factory().buildSrpObject()
427 .setRFlag(false)
428 .setSrpID(SrpIdGenerators.create())
429 .build();
430
431 PcepEroObject eroObj = pc.factory().buildEroObject()
432 .setSubObjects(subObjects)
433 .build();
434
435 PcepMsgPath msgPath = pc.factory().buildPcepMsgPath()
436 .setEroObject(eroObj)
437 .build();
438
439 PcepUpdateRequest updateReq = pc.factory().buildPcepUpdateRequest()
440 .setSrpObject(srpObj)
441 .setMsgPath(msgPath)
442 .setLspObject(lspObj)
443 .build();
444
445 updateRequestList.add(updateReq);
446
447 //TODO: P = 1 is it P flag in PCEP obj header
448 PcepUpdateMsg updateMsg = pc.factory().buildUpdateMsg()
449 .setUpdateRequestList(updateRequestList)
450 .build();
451
452 pc.sendMessage(updateMsg);
453 }
454
455 private LinkedList<PcepValueType> createEroSubObj(Path path) {
456 LinkedList<PcepValueType> subObjects = new LinkedList<>();
457 List<Link> links = path.links();
458 ConnectPoint source = null;
459 ConnectPoint destination = null;
460 IpAddress ipDstAddress = null;
461 IpAddress ipSrcAddress = null;
462 PcepValueType subObj = null;
463 long portNo;
464
465 for (Link link : links) {
466 source = link.src();
467 if (!(source.equals(destination))) {
468 //set IPv4SubObject for ERO object
469 portNo = source.port().toLong();
470 portNo = ((portNo & IDENTIFIER_SET) == IDENTIFIER_SET) ? portNo & SET : portNo;
471 ipSrcAddress = Ip4Address.valueOf((int) portNo);
472 subObj = new IPv4SubObject(ipSrcAddress.getIp4Address().toInt());
473 subObjects.add(subObj);
474 }
475
476 destination = link.dst();
477 portNo = destination.port().toLong();
478 portNo = ((portNo & IDENTIFIER_SET) == IDENTIFIER_SET) ? portNo & SET : portNo;
479 ipDstAddress = Ip4Address.valueOf((int) portNo);
480 subObj = new IPv4SubObject(ipDstAddress.getIp4Address().toInt());
481 subObjects.add(subObj);
482 }
483 return subObjects;
484 }
485
Priyanka B9bee0802016-04-27 22:06:02 +0530486 @Override
487 public void removeFlowRule(FlowRule... flowRules) {
488 for (FlowRule flowRule : flowRules) {
489 removeRule(flowRule);
490 }
491 }
492
493 private void removeRule(FlowRule flowRule) {
494 flowRule.selector().criteria()
495 .forEach(c -> {
496 // If Criterion type is MPLS_LABEL, remove the specified flow rules
497 if (c.type() == Criterion.Type.MPLS_LABEL) {
498 PcepClient pcc;
499 /** PCC client session is based on LSR ID, get the LSR ID for a specific device to
500 push the flows */
501
502 //TODO: commented code has dependency with other patch
503 /* Set<TeRouterId> lrsIds = resourceService.getAvailableResourceValues(Resources
504 .discrete(flowRule.deviceId()).id(), TeRouterId.class);
505
506 lrsIds.forEach(lsrId ->
507 {
508 if (pcepController.getClient(PccId.pccId(lsrId)) != null) {
509 pcc = pcepController.getClient(PccId.pccId(lsrId));
510 }
511 });*/
512 // TODO: Build message and send the PCEP label message via PCEP client
513 } else {
514 // TODO: Get the BGP peer based on deviceId and send the message
515 }
516 });
517 }
518
519 @Override
520 public void removeRulesById(ApplicationId id, FlowRule... flowRules) {
521 // TODO
522 removeFlowRule(flowRules);
523 }
524
525 @Override
526 public void executeBatch(FlowRuleBatchOperation batch) {
527 //TODO
528 }
529}