blob: 6d0ad11f60dc8ca8affba8476f2d38f089274ed0 [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
77import static org.slf4j.LoggerFactory.getLogger;
78
79/**
80 * Implementation of BGP-PCEP flow provider.
81 */
82@Component(immediate = true)
83public class BgpcepFlowRuleProvider extends AbstractProvider
84 implements FlowRuleProvider {
85
86 private final Logger log = getLogger(getClass());
87
88 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
89 protected FlowRuleProviderRegistry providerRegistry;
90
91 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
92 protected ComponentConfigService cfgService;
93
94 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
95 protected BgpController bgpController;
96
97 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
98 protected PcepClientController pcepController;
99
100 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
101 protected ResourceService resourceService;
102
Priyanka Bbd455ca2016-05-05 22:13:25 +0530103 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
104 protected TunnelService tunnelService;
105
Priyanka B9bee0802016-04-27 22:06:02 +0530106 private FlowRuleProviderService providerService;
Priyanka Bbd455ca2016-05-05 22:13:25 +0530107 private PcepLabelObject labelObj;
108 public static final int OUT_LABEL_TYPE = 0;
109 public static final int IN_LABEL_TYPE = 1;
110 public static final long IDENTIFIER_SET = 0x100000000L;
111 public static final long SET = 0xFFFFFFFFL;
Priyanka B9bee0802016-04-27 22:06:02 +0530112
113 /**
114 * Creates a BgpFlow host provider.
115 */
116 public BgpcepFlowRuleProvider() {
117 super(new ProviderId("l3", "org.onosproject.provider.bgpcep"));
118 }
119
120 @Activate
121 public void activate(ComponentContext context) {
122 cfgService.registerProperties(getClass());
123 providerService = providerRegistry.register(this);
124 log.info("Started");
125 }
126
127 @Deactivate
128 public void deactivate(ComponentContext context) {
129 cfgService.unregisterProperties(getClass(), false);
130 providerRegistry.unregister(this);
131 providerService = null;
132 log.info("Stopped");
133 }
134
135 @Override
136 public void applyFlowRule(FlowRule... flowRules) {
137 for (FlowRule flowRule : flowRules) {
138 applyRule(flowRule);
139 }
140 }
141
142 private void applyRule(FlowRule flowRule) {
143 flowRule.selector().criteria()
144 .forEach(c -> {
145 // If Criterion type is MPLS_LABEL, push labels through PCEP client
146 if (c.type() == Criterion.Type.MPLS_LABEL) {
147 PcepClient pcc;
148 /** PCC client session is based on LSR ID, get the LSR ID for a specific device to
149 push the flows */
150
151 //TODO: commented code has dependency with other patch
152 /* Set<TeRouterId> lrsIds = resourceService.getAvailableResourceValues(Resources
153 .discrete(flowRule.deviceId()).id(), TeRouterId.class);
154
155 lrsIds.forEach(lsrId ->
156 {
157 if (pcepController.getClient(PccId.pccId(lsrId)) != null) {
158 pcc = pcepController.getClient(PccId.pccId(lsrId));
159 }
160 });*/
161 // TODO: Build message and send the PCEP label message via PCEP client
162 } else {
163 // TODO: Get the BGP peer based on deviceId and send the message
164 }
165 });
166 }
167
Priyanka Bbd455ca2016-05-05 22:13:25 +0530168 /**
169 * Returns PCEP client.
170 *
171 * @return PCEP client
172 */
173 private PcepClient getPcepClient(DeviceId deviceId) {
174 PcepClient pcc;
175 //TODO: commented code has dependency
176 /* Set<TeRouterId> lrsIds = resourceService.getAvailableResourceValues(Resources
177 .discrete(deviceId()).id(), TeRouterId.class);
178
179 lrsIds.forEach(lsrId ->
180 {
181 if (pcepController.getClient(PccId.pccId(lsrId)) != null) {
182 pcc = pcepController.getClient(PccId.pccId(lsrId));
183 return pcc
184 }
185 });*/
186 return null;
187 }
188
189 //Pushes node labels to the specified device.
190 private void pushGlobalNodeLabel(DeviceId deviceId, LabelResourceId labelId,
191 IpPrefix ipPrefix, Objective.Operation type) throws PcepParseException {
192 PcepClient pc = getPcepClient(deviceId);
193 if (pc == null) {
194 log.error("PCEP client not found");
195 return;
196 }
197
198 LinkedList<PcepLabelUpdate> labelUpdateList = new LinkedList<>();
199
200 PcepFecObjectIPv4 fecObject = pc.factory().buildFecObjectIpv4()
201 .setNodeID(ipPrefix.address().getIp4Address().toInt())
202 .build();
203
204 PcepSrpObject srpObj = getSrpObject(pc, type);
205
206 //Global NODE-SID as label object
207 PcepLabelObject labelObject = pc.factory().buildLabelObject()
208 .setLabel((int) labelId.labelId())
209 .build();
210
211 PcepLabelMap labelMap = new PcepLabelMap();
212 labelMap.setFecObject(fecObject);
213 labelMap.setLabelObject(labelObject);
214 labelMap.setSrpObject(srpObj);
215
216 labelUpdateList.add(pc.factory().buildPcepLabelUpdateObject()
217 .setLabelMap(labelMap)
218 .build());
219
220 PcepLabelUpdateMsg labelMsg = pc.factory().buildPcepLabelUpdateMsg()
221 .setPcLabelUpdateList(labelUpdateList)
222 .build();
223
224 pc.sendMessage(labelMsg);
225 }
226
227 private PcepSrpObject getSrpObject(PcepClient pc, Objective.Operation type) throws PcepParseException {
228 PcepSrpObject srpObj;
229 if (type.equals(Objective.Operation.ADD)) {
230 srpObj = pc.factory().buildSrpObject()
231 .setRFlag(false)
232 .setSrpID(SrpIdGenerators.create())
233 .build();
234 } else {
235 //To cleanup labels, R bit is set
236 srpObj = pc.factory().buildSrpObject()
237 .setRFlag(true)
238 .setSrpID(SrpIdGenerators.create())
239 .build();
240 }
241 return srpObj;
242 }
243
244 //Pushes adjacency labels to the specified device.
245 private void pushAdjacencyLabel(DeviceId deviceId, LabelResourceId labelId,
246 PortNumber srcPortNum, PortNumber dstPortNum, Objective.Operation type) throws PcepParseException {
247 PcepClient pc = getPcepClient(deviceId);
248 if (pc == null) {
249 log.error("PCEP client not found");
250 return;
251 }
252
253 LinkedList<PcepLabelUpdate> labelUpdateList = new LinkedList<>();
254
255 long srcPortNo = srcPortNum.toLong();
256 long dstPortNo = dstPortNum.toLong();
257 srcPortNo = ((srcPortNo & IDENTIFIER_SET) == IDENTIFIER_SET) ? srcPortNo & SET : srcPortNo;
258 dstPortNo = ((dstPortNo & IDENTIFIER_SET) == IDENTIFIER_SET) ? dstPortNo & SET : dstPortNo;
259
260 PcepFecObjectIPv4Adjacency fecAdjObject = pc.factory().buildFecIpv4Adjacency()
261 .seRemoteIPv4Address((int) dstPortNo)
262 .seLocalIPv4Address((int) srcPortNo)
263 .build();
264
265 PcepSrpObject srpObj = getSrpObject(pc, type);
266
267 //Adjacency label object
268 PcepLabelObject labelObject = pc.factory().buildLabelObject()
269 .setLabel((int) labelId.labelId())
270 .build();
271
272 PcepLabelMap labelMap = new PcepLabelMap();
273 labelMap.setFecObject(fecAdjObject);
274 labelMap.setLabelObject(labelObject);
275 labelMap.setSrpObject(srpObj);
276
277 labelUpdateList.add(pc.factory().buildPcepLabelUpdateObject()
278 .setLabelMap(labelMap)
279 .build());
280
281 PcepLabelUpdateMsg labelMsg = pc.factory().buildPcepLabelUpdateMsg()
282 .setPcLabelUpdateList(labelUpdateList)
283 .build();
284
285 pc.sendMessage(labelMsg);
286 }
287
288 //Pushes local labels to the device which is specific to path [CR-case].
289 private void pushLocalLabels(DeviceId deviceId, LabelResourceId labelId,
290 PortNumber portNum, TunnelId tunnelId,
291 Boolean isBos, Long labelType, Objective.Operation type) throws PcepParseException {
292
293 PcepClient pc = getPcepClient(deviceId);
294 if (pc == null) {
295 log.error("PCEP client not found");
296 return;
297 }
298
299 PcepLspObject lspObj;
300 LinkedList<PcepLabelUpdate> labelUpdateList = new LinkedList<>();
301 LinkedList<PcepLabelObject> labelObjects = new LinkedList<>();
302 PcepSrpObject srpObj;
303 PcepLabelDownload labelDownload = new PcepLabelDownload();
304 LinkedList<PcepValueType> optionalTlv = new LinkedList<>();
305
306 long portNo = portNum.toLong();
307 portNo = ((portNo & IDENTIFIER_SET) == IDENTIFIER_SET) ? portNo & SET : portNo;
308
309 optionalTlv.add(NexthopIPv4addressTlv.of((int) portNo));
310
311 Tunnel tunnel = tunnelService.queryTunnel(tunnelId);
312
313 PcepLabelObject labelObj = pc.factory().buildLabelObject()
314 .setOFlag(labelType == OUT_LABEL_TYPE ? true : false)
315 .setOptionalTlv(optionalTlv)
316 .setLabel((int) labelId.labelId())
317 .build();
318
319 /**
320 * Check whether transit node or not. For transit node, label update message should include IN and OUT labels.
321 * Hence store IN label object and next when out label comes add IN and OUT label objects and encode label
322 * update message and send to specified client.
323 */
324 if (!deviceId.equals(tunnel.path().src().deviceId()) && !deviceId.equals(tunnel.path().dst().deviceId())) {
325 //Device is transit node
326 if (labelType == IN_LABEL_TYPE) {
327 //Store label object having IN label value
328 this.labelObj = labelObj;
329 return;
330 }
331 //Add IN label object
332 labelObjects.add(this.labelObj);
333 }
334
335 //Add OUT label object in case of transit node
336 labelObjects.add(labelObj);
337
338 srpObj = getSrpObject(pc, type);
339
340 String lspId = tunnel.annotations().value(PcepAnnotationKeys.PLSP_ID);
341 String plspId = tunnel.annotations().value(PcepAnnotationKeys.LOCAL_LSP_ID);
342 String tunnelIdentifier = tunnel.annotations().value(PcepAnnotationKeys.PCC_TUNNEL_ID);
343
344 LinkedList<PcepValueType> tlvs = new LinkedList<>();
345 StatefulIPv4LspIdentifiersTlv lspIdTlv = new StatefulIPv4LspIdentifiersTlv(((IpTunnelEndPoint) tunnel.src())
346 .ip().getIp4Address().toInt(), Short.valueOf(lspId), Short.valueOf(tunnelIdentifier), 0,
347 ((IpTunnelEndPoint) tunnel.dst()).ip().getIp4Address().toInt());
348 tlvs.add(lspIdTlv);
349
350 lspObj = pc.factory().buildLspObject()
351 .setRFlag(false)
352 .setAFlag(true)
353 .setDFlag(true)
354 .setPlspId(Integer.valueOf(plspId))
355 .setOptionalTlv(tlvs)
356 .build();
357
358 labelDownload.setLabelList(labelObjects);
359 labelDownload.setLspObject(lspObj);
360 labelDownload.setSrpObject(srpObj);
361
362 labelUpdateList.add(pc.factory().buildPcepLabelUpdateObject()
363 .setLabelDownload(labelDownload)
364 .build());
365
366 PcepLabelUpdateMsg labelMsg = pc.factory().buildPcepLabelUpdateMsg()
367 .setPcLabelUpdateList(labelUpdateList)
368 .build();
369
370 pc.sendMessage(labelMsg);
371
372 //If isBos is true, label download is done along the LSP, send PCEP update message.
373 if (isBos) {
374 sendPcepUpdateMsg(pc, lspObj, tunnel);
375 }
376 }
377
378 //Sends PCEP update message.
379 private void sendPcepUpdateMsg(PcepClient pc, PcepLspObject lspObj, Tunnel tunnel) throws PcepParseException {
380 LinkedList<PcepUpdateRequest> updateRequestList = new LinkedList<>();
381 LinkedList<PcepValueType> subObjects = createEroSubObj(tunnel.path());
382
383 if (subObjects == null) {
384 log.error("ERO subjects not present");
385 return;
386 }
387
388 PcepSrpObject srpObj = pc.factory().buildSrpObject()
389 .setRFlag(false)
390 .setSrpID(SrpIdGenerators.create())
391 .build();
392
393 PcepEroObject eroObj = pc.factory().buildEroObject()
394 .setSubObjects(subObjects)
395 .build();
396
397 PcepMsgPath msgPath = pc.factory().buildPcepMsgPath()
398 .setEroObject(eroObj)
399 .build();
400
401 PcepUpdateRequest updateReq = pc.factory().buildPcepUpdateRequest()
402 .setSrpObject(srpObj)
403 .setMsgPath(msgPath)
404 .setLspObject(lspObj)
405 .build();
406
407 updateRequestList.add(updateReq);
408
409 //TODO: P = 1 is it P flag in PCEP obj header
410 PcepUpdateMsg updateMsg = pc.factory().buildUpdateMsg()
411 .setUpdateRequestList(updateRequestList)
412 .build();
413
414 pc.sendMessage(updateMsg);
415 }
416
417 private LinkedList<PcepValueType> createEroSubObj(Path path) {
418 LinkedList<PcepValueType> subObjects = new LinkedList<>();
419 List<Link> links = path.links();
420 ConnectPoint source = null;
421 ConnectPoint destination = null;
422 IpAddress ipDstAddress = null;
423 IpAddress ipSrcAddress = null;
424 PcepValueType subObj = null;
425 long portNo;
426
427 for (Link link : links) {
428 source = link.src();
429 if (!(source.equals(destination))) {
430 //set IPv4SubObject for ERO object
431 portNo = source.port().toLong();
432 portNo = ((portNo & IDENTIFIER_SET) == IDENTIFIER_SET) ? portNo & SET : portNo;
433 ipSrcAddress = Ip4Address.valueOf((int) portNo);
434 subObj = new IPv4SubObject(ipSrcAddress.getIp4Address().toInt());
435 subObjects.add(subObj);
436 }
437
438 destination = link.dst();
439 portNo = destination.port().toLong();
440 portNo = ((portNo & IDENTIFIER_SET) == IDENTIFIER_SET) ? portNo & SET : portNo;
441 ipDstAddress = Ip4Address.valueOf((int) portNo);
442 subObj = new IPv4SubObject(ipDstAddress.getIp4Address().toInt());
443 subObjects.add(subObj);
444 }
445 return subObjects;
446 }
447
Priyanka B9bee0802016-04-27 22:06:02 +0530448 @Override
449 public void removeFlowRule(FlowRule... flowRules) {
450 for (FlowRule flowRule : flowRules) {
451 removeRule(flowRule);
452 }
453 }
454
455 private void removeRule(FlowRule flowRule) {
456 flowRule.selector().criteria()
457 .forEach(c -> {
458 // If Criterion type is MPLS_LABEL, remove the specified flow rules
459 if (c.type() == Criterion.Type.MPLS_LABEL) {
460 PcepClient pcc;
461 /** PCC client session is based on LSR ID, get the LSR ID for a specific device to
462 push the flows */
463
464 //TODO: commented code has dependency with other patch
465 /* Set<TeRouterId> lrsIds = resourceService.getAvailableResourceValues(Resources
466 .discrete(flowRule.deviceId()).id(), TeRouterId.class);
467
468 lrsIds.forEach(lsrId ->
469 {
470 if (pcepController.getClient(PccId.pccId(lsrId)) != null) {
471 pcc = pcepController.getClient(PccId.pccId(lsrId));
472 }
473 });*/
474 // TODO: Build message and send the PCEP label message via PCEP client
475 } else {
476 // TODO: Get the BGP peer based on deviceId and send the message
477 }
478 });
479 }
480
481 @Override
482 public void removeRulesById(ApplicationId id, FlowRule... flowRules) {
483 // TODO
484 removeFlowRule(flowRules);
485 }
486
487 @Override
488 public void executeBatch(FlowRuleBatchOperation batch) {
489 //TODO
490 }
491}