[ONOS] SBI part of label flow.
Change-Id: Id3af26cbf0dd7d02febfe4c13ce6fe496641e043
diff --git a/providers/bgpcep/flow/src/main/java/org/onosproject/provider/bgpcep/flow/impl/BgpcepFlowRuleProvider.java b/providers/bgpcep/flow/src/main/java/org/onosproject/provider/bgpcep/flow/impl/BgpcepFlowRuleProvider.java
index 3afbec4..6d0ad11 100644
--- a/providers/bgpcep/flow/src/main/java/org/onosproject/provider/bgpcep/flow/impl/BgpcepFlowRuleProvider.java
+++ b/providers/bgpcep/flow/src/main/java/org/onosproject/provider/bgpcep/flow/impl/BgpcepFlowRuleProvider.java
@@ -15,25 +15,62 @@
*/
package org.onosproject.provider.bgpcep.flow.impl;
+import java.util.LinkedList;
+import java.util.List;
+
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.onlab.packet.Ip4Address;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.IpPrefix;
import org.onosproject.bgp.controller.BgpController;
import org.onosproject.cfg.ComponentConfigService;
import org.onosproject.core.ApplicationId;
+import org.onosproject.incubator.net.resource.label.LabelResourceId;
+import org.onosproject.incubator.net.tunnel.IpTunnelEndPoint;
+import org.onosproject.incubator.net.tunnel.Tunnel;
+import org.onosproject.incubator.net.tunnel.TunnelId;
+import org.onosproject.incubator.net.tunnel.TunnelService;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Link;
+import org.onosproject.net.Path;
+import org.onosproject.net.PortNumber;
import org.onosproject.net.flow.FlowRule;
import org.onosproject.net.flow.FlowRuleBatchOperation;
import org.onosproject.net.flow.FlowRuleProvider;
import org.onosproject.net.flow.FlowRuleProviderRegistry;
import org.onosproject.net.flow.FlowRuleProviderService;
import org.onosproject.net.flow.criteria.Criterion;
+import org.onosproject.net.flowobjective.Objective;
import org.onosproject.net.provider.AbstractProvider;
import org.onosproject.net.provider.ProviderId;
import org.onosproject.net.resource.ResourceService;
import org.onosproject.pcep.controller.PcepClient;
import org.onosproject.pcep.controller.PcepClientController;
+import org.onosproject.pcepio.exceptions.PcepParseException;
+import org.onosproject.pcepio.protocol.PcepEroObject;
+import org.onosproject.pcepio.protocol.PcepFecObjectIPv4;
+import org.onosproject.pcepio.protocol.PcepFecObjectIPv4Adjacency;
+import org.onosproject.pcepio.protocol.PcepLabelObject;
+import org.onosproject.pcepio.protocol.PcepLabelUpdate;
+import org.onosproject.pcepio.protocol.PcepLabelUpdateMsg;
+import org.onosproject.pcepio.protocol.PcepLspObject;
+import org.onosproject.pcepio.protocol.PcepMsgPath;
+import org.onosproject.pcepio.protocol.PcepSrpObject;
+import org.onosproject.pcepio.protocol.PcepUpdateMsg;
+import org.onosproject.pcepio.protocol.PcepUpdateRequest;
+import org.onosproject.pcepio.types.IPv4SubObject;
+import org.onosproject.pcepio.types.NexthopIPv4addressTlv;
+import org.onosproject.pcepio.types.PcepLabelDownload;
+import org.onosproject.pcepio.types.PcepLabelMap;
+import org.onosproject.pcepio.types.PcepValueType;
+import org.onosproject.pcepio.types.StatefulIPv4LspIdentifiersTlv;
+import org.onosproject.provider.pcep.tunnel.impl.SrpIdGenerators;
+import org.onosproject.provider.pcep.tunnel.impl.PcepAnnotationKeys;
import org.osgi.service.component.ComponentContext;
import org.slf4j.Logger;
@@ -63,7 +100,15 @@
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected ResourceService resourceService;
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected TunnelService tunnelService;
+
private FlowRuleProviderService providerService;
+ private PcepLabelObject labelObj;
+ public static final int OUT_LABEL_TYPE = 0;
+ public static final int IN_LABEL_TYPE = 1;
+ public static final long IDENTIFIER_SET = 0x100000000L;
+ public static final long SET = 0xFFFFFFFFL;
/**
* Creates a BgpFlow host provider.
@@ -120,6 +165,286 @@
});
}
+ /**
+ * Returns PCEP client.
+ *
+ * @return PCEP client
+ */
+ private PcepClient getPcepClient(DeviceId deviceId) {
+ PcepClient pcc;
+ //TODO: commented code has dependency
+ /* Set<TeRouterId> lrsIds = resourceService.getAvailableResourceValues(Resources
+ .discrete(deviceId()).id(), TeRouterId.class);
+
+ lrsIds.forEach(lsrId ->
+ {
+ if (pcepController.getClient(PccId.pccId(lsrId)) != null) {
+ pcc = pcepController.getClient(PccId.pccId(lsrId));
+ return pcc
+ }
+ });*/
+ return null;
+ }
+
+ //Pushes node labels to the specified device.
+ private void pushGlobalNodeLabel(DeviceId deviceId, LabelResourceId labelId,
+ IpPrefix ipPrefix, Objective.Operation type) throws PcepParseException {
+ PcepClient pc = getPcepClient(deviceId);
+ if (pc == null) {
+ log.error("PCEP client not found");
+ return;
+ }
+
+ LinkedList<PcepLabelUpdate> labelUpdateList = new LinkedList<>();
+
+ PcepFecObjectIPv4 fecObject = pc.factory().buildFecObjectIpv4()
+ .setNodeID(ipPrefix.address().getIp4Address().toInt())
+ .build();
+
+ PcepSrpObject srpObj = getSrpObject(pc, type);
+
+ //Global NODE-SID as label object
+ PcepLabelObject labelObject = pc.factory().buildLabelObject()
+ .setLabel((int) labelId.labelId())
+ .build();
+
+ PcepLabelMap labelMap = new PcepLabelMap();
+ labelMap.setFecObject(fecObject);
+ labelMap.setLabelObject(labelObject);
+ labelMap.setSrpObject(srpObj);
+
+ labelUpdateList.add(pc.factory().buildPcepLabelUpdateObject()
+ .setLabelMap(labelMap)
+ .build());
+
+ PcepLabelUpdateMsg labelMsg = pc.factory().buildPcepLabelUpdateMsg()
+ .setPcLabelUpdateList(labelUpdateList)
+ .build();
+
+ pc.sendMessage(labelMsg);
+ }
+
+ private PcepSrpObject getSrpObject(PcepClient pc, Objective.Operation type) throws PcepParseException {
+ PcepSrpObject srpObj;
+ if (type.equals(Objective.Operation.ADD)) {
+ srpObj = pc.factory().buildSrpObject()
+ .setRFlag(false)
+ .setSrpID(SrpIdGenerators.create())
+ .build();
+ } else {
+ //To cleanup labels, R bit is set
+ srpObj = pc.factory().buildSrpObject()
+ .setRFlag(true)
+ .setSrpID(SrpIdGenerators.create())
+ .build();
+ }
+ return srpObj;
+ }
+
+ //Pushes adjacency labels to the specified device.
+ private void pushAdjacencyLabel(DeviceId deviceId, LabelResourceId labelId,
+ PortNumber srcPortNum, PortNumber dstPortNum, Objective.Operation type) throws PcepParseException {
+ PcepClient pc = getPcepClient(deviceId);
+ if (pc == null) {
+ log.error("PCEP client not found");
+ return;
+ }
+
+ LinkedList<PcepLabelUpdate> labelUpdateList = new LinkedList<>();
+
+ long srcPortNo = srcPortNum.toLong();
+ long dstPortNo = dstPortNum.toLong();
+ srcPortNo = ((srcPortNo & IDENTIFIER_SET) == IDENTIFIER_SET) ? srcPortNo & SET : srcPortNo;
+ dstPortNo = ((dstPortNo & IDENTIFIER_SET) == IDENTIFIER_SET) ? dstPortNo & SET : dstPortNo;
+
+ PcepFecObjectIPv4Adjacency fecAdjObject = pc.factory().buildFecIpv4Adjacency()
+ .seRemoteIPv4Address((int) dstPortNo)
+ .seLocalIPv4Address((int) srcPortNo)
+ .build();
+
+ PcepSrpObject srpObj = getSrpObject(pc, type);
+
+ //Adjacency label object
+ PcepLabelObject labelObject = pc.factory().buildLabelObject()
+ .setLabel((int) labelId.labelId())
+ .build();
+
+ PcepLabelMap labelMap = new PcepLabelMap();
+ labelMap.setFecObject(fecAdjObject);
+ labelMap.setLabelObject(labelObject);
+ labelMap.setSrpObject(srpObj);
+
+ labelUpdateList.add(pc.factory().buildPcepLabelUpdateObject()
+ .setLabelMap(labelMap)
+ .build());
+
+ PcepLabelUpdateMsg labelMsg = pc.factory().buildPcepLabelUpdateMsg()
+ .setPcLabelUpdateList(labelUpdateList)
+ .build();
+
+ pc.sendMessage(labelMsg);
+ }
+
+ //Pushes local labels to the device which is specific to path [CR-case].
+ private void pushLocalLabels(DeviceId deviceId, LabelResourceId labelId,
+ PortNumber portNum, TunnelId tunnelId,
+ Boolean isBos, Long labelType, Objective.Operation type) throws PcepParseException {
+
+ PcepClient pc = getPcepClient(deviceId);
+ if (pc == null) {
+ log.error("PCEP client not found");
+ return;
+ }
+
+ PcepLspObject lspObj;
+ LinkedList<PcepLabelUpdate> labelUpdateList = new LinkedList<>();
+ LinkedList<PcepLabelObject> labelObjects = new LinkedList<>();
+ PcepSrpObject srpObj;
+ PcepLabelDownload labelDownload = new PcepLabelDownload();
+ LinkedList<PcepValueType> optionalTlv = new LinkedList<>();
+
+ long portNo = portNum.toLong();
+ portNo = ((portNo & IDENTIFIER_SET) == IDENTIFIER_SET) ? portNo & SET : portNo;
+
+ optionalTlv.add(NexthopIPv4addressTlv.of((int) portNo));
+
+ Tunnel tunnel = tunnelService.queryTunnel(tunnelId);
+
+ PcepLabelObject labelObj = pc.factory().buildLabelObject()
+ .setOFlag(labelType == OUT_LABEL_TYPE ? true : false)
+ .setOptionalTlv(optionalTlv)
+ .setLabel((int) labelId.labelId())
+ .build();
+
+ /**
+ * Check whether transit node or not. For transit node, label update message should include IN and OUT labels.
+ * Hence store IN label object and next when out label comes add IN and OUT label objects and encode label
+ * update message and send to specified client.
+ */
+ if (!deviceId.equals(tunnel.path().src().deviceId()) && !deviceId.equals(tunnel.path().dst().deviceId())) {
+ //Device is transit node
+ if (labelType == IN_LABEL_TYPE) {
+ //Store label object having IN label value
+ this.labelObj = labelObj;
+ return;
+ }
+ //Add IN label object
+ labelObjects.add(this.labelObj);
+ }
+
+ //Add OUT label object in case of transit node
+ labelObjects.add(labelObj);
+
+ srpObj = getSrpObject(pc, type);
+
+ String lspId = tunnel.annotations().value(PcepAnnotationKeys.PLSP_ID);
+ String plspId = tunnel.annotations().value(PcepAnnotationKeys.LOCAL_LSP_ID);
+ String tunnelIdentifier = tunnel.annotations().value(PcepAnnotationKeys.PCC_TUNNEL_ID);
+
+ LinkedList<PcepValueType> tlvs = new LinkedList<>();
+ StatefulIPv4LspIdentifiersTlv lspIdTlv = new StatefulIPv4LspIdentifiersTlv(((IpTunnelEndPoint) tunnel.src())
+ .ip().getIp4Address().toInt(), Short.valueOf(lspId), Short.valueOf(tunnelIdentifier), 0,
+ ((IpTunnelEndPoint) tunnel.dst()).ip().getIp4Address().toInt());
+ tlvs.add(lspIdTlv);
+
+ lspObj = pc.factory().buildLspObject()
+ .setRFlag(false)
+ .setAFlag(true)
+ .setDFlag(true)
+ .setPlspId(Integer.valueOf(plspId))
+ .setOptionalTlv(tlvs)
+ .build();
+
+ labelDownload.setLabelList(labelObjects);
+ labelDownload.setLspObject(lspObj);
+ labelDownload.setSrpObject(srpObj);
+
+ labelUpdateList.add(pc.factory().buildPcepLabelUpdateObject()
+ .setLabelDownload(labelDownload)
+ .build());
+
+ PcepLabelUpdateMsg labelMsg = pc.factory().buildPcepLabelUpdateMsg()
+ .setPcLabelUpdateList(labelUpdateList)
+ .build();
+
+ pc.sendMessage(labelMsg);
+
+ //If isBos is true, label download is done along the LSP, send PCEP update message.
+ if (isBos) {
+ sendPcepUpdateMsg(pc, lspObj, tunnel);
+ }
+ }
+
+ //Sends PCEP update message.
+ private void sendPcepUpdateMsg(PcepClient pc, PcepLspObject lspObj, Tunnel tunnel) throws PcepParseException {
+ LinkedList<PcepUpdateRequest> updateRequestList = new LinkedList<>();
+ LinkedList<PcepValueType> subObjects = createEroSubObj(tunnel.path());
+
+ if (subObjects == null) {
+ log.error("ERO subjects not present");
+ return;
+ }
+
+ PcepSrpObject srpObj = pc.factory().buildSrpObject()
+ .setRFlag(false)
+ .setSrpID(SrpIdGenerators.create())
+ .build();
+
+ PcepEroObject eroObj = pc.factory().buildEroObject()
+ .setSubObjects(subObjects)
+ .build();
+
+ PcepMsgPath msgPath = pc.factory().buildPcepMsgPath()
+ .setEroObject(eroObj)
+ .build();
+
+ PcepUpdateRequest updateReq = pc.factory().buildPcepUpdateRequest()
+ .setSrpObject(srpObj)
+ .setMsgPath(msgPath)
+ .setLspObject(lspObj)
+ .build();
+
+ updateRequestList.add(updateReq);
+
+ //TODO: P = 1 is it P flag in PCEP obj header
+ PcepUpdateMsg updateMsg = pc.factory().buildUpdateMsg()
+ .setUpdateRequestList(updateRequestList)
+ .build();
+
+ pc.sendMessage(updateMsg);
+ }
+
+ private LinkedList<PcepValueType> createEroSubObj(Path path) {
+ LinkedList<PcepValueType> subObjects = new LinkedList<>();
+ List<Link> links = path.links();
+ ConnectPoint source = null;
+ ConnectPoint destination = null;
+ IpAddress ipDstAddress = null;
+ IpAddress ipSrcAddress = null;
+ PcepValueType subObj = null;
+ long portNo;
+
+ for (Link link : links) {
+ source = link.src();
+ if (!(source.equals(destination))) {
+ //set IPv4SubObject for ERO object
+ portNo = source.port().toLong();
+ portNo = ((portNo & IDENTIFIER_SET) == IDENTIFIER_SET) ? portNo & SET : portNo;
+ ipSrcAddress = Ip4Address.valueOf((int) portNo);
+ subObj = new IPv4SubObject(ipSrcAddress.getIp4Address().toInt());
+ subObjects.add(subObj);
+ }
+
+ destination = link.dst();
+ portNo = destination.port().toLong();
+ portNo = ((portNo & IDENTIFIER_SET) == IDENTIFIER_SET) ? portNo & SET : portNo;
+ ipDstAddress = Ip4Address.valueOf((int) portNo);
+ subObj = new IPv4SubObject(ipDstAddress.getIp4Address().toInt());
+ subObjects.add(subObj);
+ }
+ return subObjects;
+ }
+
@Override
public void removeFlowRule(FlowRule... flowRules) {
for (FlowRule flowRule : flowRules) {