[ONOS-4170] LSP-DB sync
Change-Id: Icda3afd9cca8d1fb8c58b44da6bc26064b300388
diff --git a/providers/pcep/tunnel/src/main/java/org/onosproject/provider/pcep/tunnel/impl/PcepLspStatus.java b/providers/pcep/tunnel/src/main/java/org/onosproject/provider/pcep/tunnel/impl/PcepLspStatus.java
deleted file mode 100644
index ef628ed..0000000
--- a/providers/pcep/tunnel/src/main/java/org/onosproject/provider/pcep/tunnel/impl/PcepLspStatus.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright 2016-present Open Networking Laboratory
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.onosproject.provider.pcep.tunnel.impl;
-
-import org.onosproject.incubator.net.tunnel.Tunnel.State;
-
-/**
- * Representation of the PCEP LSP state.
- */
-public enum PcepLspStatus {
-
- /**
- * Signifies that the LSP is not active.
- */
- DOWN,
-
- /**
- * Signifies that the LSP is signalled.
- */
- UP,
-
- /**
- * Signifies that the LSP is up and carrying traffic.
- */
- ACTIVE,
-
- /**
- * Signifies that the LSP is being torn down, resources are being released.
- */
- GOING_DOWN,
-
- /**
- * Signifies that the LSP is being signalled.
- */
- GOING_UP;
-
- /**
- * Returns the applicable PCEP LSP status corresponding to ONOS tunnel state.
- *
- * @param tunnelState ONOS tunnel state
- */
- public static PcepLspStatus getLspStatusFromTunnelStatus(State tunnelState) {
-
- switch (tunnelState) {
-
- case INIT:
- return PcepLspStatus.DOWN;
-
- case ESTABLISHED:
- return PcepLspStatus.GOING_UP;
-
- case ACTIVE:
- return PcepLspStatus.UP;
-
- case FAILED: // fall through
- case INACTIVE: // LSP is administratively down.
- default:
- return PcepLspStatus.DOWN;
- }
- }
-
- /**
- * Returns the applicable ONOS tunnel state corresponding to PCEP LSP status.
- *
- * @param lspState PCEP LSP status
- */
- public static State getTunnelStatusFromLspStatus(PcepLspStatus lspState) {
-
- switch (lspState) {
-
- case DOWN:
- return State.FAILED;
-
- case UP: // fall through
- case ACTIVE:
- return State.ACTIVE;
-
- case GOING_DOWN:
- return State.FAILED;
-
- case GOING_UP:
- return State.ESTABLISHED;
-
- default:
- return State.FAILED;
- }
- }
-}
diff --git a/providers/pcep/tunnel/src/main/java/org/onosproject/provider/pcep/tunnel/impl/PcepTunnelProvider.java b/providers/pcep/tunnel/src/main/java/org/onosproject/provider/pcep/tunnel/impl/PcepTunnelProvider.java
index fbfeda7..c77187a 100644
--- a/providers/pcep/tunnel/src/main/java/org/onosproject/provider/pcep/tunnel/impl/PcepTunnelProvider.java
+++ b/providers/pcep/tunnel/src/main/java/org/onosproject/provider/pcep/tunnel/impl/PcepTunnelProvider.java
@@ -79,7 +79,8 @@
import org.onosproject.pcep.controller.PcepClientController;
import org.onosproject.pcep.controller.PcepClientListener;
import org.onosproject.pcep.controller.PcepEventListener;
-import org.onosproject.pcep.controller.PcepSyncStatus;
+import org.onosproject.pcep.controller.PcepLspSyncAction;
+import org.onosproject.pcep.controller.impl.PcepLspStatus;
import org.onosproject.pcepio.exceptions.PcepParseException;
import org.onosproject.pcepio.protocol.PcInitiatedLspRequest;
import org.onosproject.pcepio.protocol.PcepAttribute;
@@ -89,6 +90,7 @@
import org.onosproject.pcepio.protocol.PcepInitiateMsg;
import org.onosproject.pcepio.protocol.PcepLspObject;
import org.onosproject.pcepio.protocol.PcepMessage;
+import org.onosproject.pcepio.protocol.PcepMetricObject;
import org.onosproject.pcepio.protocol.PcepMsgPath;
import org.onosproject.pcepio.protocol.PcepReportMsg;
import org.onosproject.pcepio.protocol.PcepSrpObject;
@@ -113,7 +115,6 @@
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
-import java.util.Map;
import java.util.Optional;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
@@ -134,15 +135,18 @@
import static org.onosproject.provider.pcep.tunnel.impl.PcepAnnotationKeys.LSP_SIG_TYPE;
import static org.onosproject.provider.pcep.tunnel.impl.PcepAnnotationKeys.PCC_TUNNEL_ID;
import static org.onosproject.provider.pcep.tunnel.impl.PcepAnnotationKeys.PLSP_ID;
-import static org.onosproject.provider.pcep.tunnel.impl.PcepAnnotationKeys.PCE_INIT;
import static org.onosproject.provider.pcep.tunnel.impl.PcepAnnotationKeys.DELEGATE;
+import static org.onosproject.provider.pcep.tunnel.impl.PcepAnnotationKeys.COST_TYPE;
import static org.onosproject.provider.pcep.tunnel.impl.RequestType.CREATE;
import static org.onosproject.provider.pcep.tunnel.impl.RequestType.DELETE;
import static org.onosproject.provider.pcep.tunnel.impl.RequestType.LSP_STATE_RPT;
import static org.onosproject.provider.pcep.tunnel.impl.RequestType.UPDATE;
-import static org.onosproject.pcep.controller.PcepSyncStatus.IN_SYNC;
-import static org.onosproject.pcep.controller.PcepSyncStatus.SYNCED;
import static org.onosproject.incubator.net.tunnel.Tunnel.State.UNSTABLE;
+import static org.onosproject.pcep.controller.PcepLspSyncAction.REMOVE;
+import static org.onosproject.pcep.controller.PcepLspSyncAction.SEND_UPDATE;
+import static org.onosproject.pcep.controller.PcepLspSyncAction.SEND_DELETE;
+import static org.onosproject.pcepio.protocol.ver1.PcepMetricObjectVer1.IGP_METRIC;
+import static org.onosproject.pcepio.protocol.ver1.PcepMetricObjectVer1.TE_METRIC;
import static org.slf4j.LoggerFactory.getLogger;
/**
@@ -206,10 +210,6 @@
protected PcepTunnelApiMapper pcepTunnelApiMapper = new PcepTunnelApiMapper();
private static final int DEFAULT_BANDWIDTH_VALUE = 10;
- private Map<IpAddress, Map<TunnelId, Tunnel>> preSyncLspDbMap = new HashMap<>();
- private Map<IpAddress, List<Tunnel>> syncCompleteDeleteList = new HashMap<>();
- private Map<IpAddress, List<Tunnel>> syncCompleteUpdateList = new HashMap<>();
-
/**
* Creates a Tunnel provider.
*/
@@ -760,7 +760,6 @@
path,
annotations);
return tunnel;
-
}
/**
@@ -1177,41 +1176,8 @@
log.debug("SRP ID in handle message " + srpId);
if (!(pcepTunnelApiMapper.checkFromTunnelRequestQueue(srpId))) {
-
- // Check the sync status
- if (lspObj.getSFlag()) {
- if (pcepClientController.getClient(pccId).lspDbSyncStatus() != IN_SYNC) {
- pcepClientController.getClient(pccId).setLspDbSyncStatus(IN_SYNC);
-
- // On starting LSP-DB sync, store LSP DB locally for this PCC.
- Map<TunnelId, Tunnel> preSyncLspDb = new HashMap<>();
- Collection<Tunnel> queriedTunnels = tunnelService.queryTunnel(MPLS);
-
- for (Tunnel tunnel : queriedTunnels) {
- if (((IpTunnelEndPoint) tunnel.src()).ip().equals(pccId.ipAddress())) {
- preSyncLspDb.put(tunnel.tunnelId(), tunnel);
- }
- }
-
- preSyncLspDbMap.put(pccId.ipAddress(), preSyncLspDb);
- syncCompleteDeleteList.put(pccId.ipAddress(), new LinkedList<>());
- syncCompleteUpdateList.put(pccId.ipAddress(), new LinkedList<>());
- }
- handleRptWithoutSrpId(stateRpt, pccId, IN_SYNC);
- continue;
-
- } else if (pcepClientController.getClient(pccId).lspDbSyncStatus() == IN_SYNC) {
- // If sync flag is not set in the msg, and the
- // previous state was "in sync" means this is
- // end of sync message. PCRpt for end of sync
- // does not carry any LSP report.
- pcepClientController.getClient(pccId).setLspDbSyncStatus(SYNCED);
- handleEndOfSyncAction(pccId);
- continue;
- }
-
- // For PCRpt without matching SRP id not during LSPDB sync.
- handleRptWithoutSrpId(stateRpt, pccId, SYNCED);
+ // For PCRpt without matching SRP id.
+ handleRptWithoutSrpId(stateRpt, pccId);
continue;
}
@@ -1306,8 +1272,19 @@
}
private SparseAnnotations getAnnotations(PcepLspObject lspObj, StatefulIPv4LspIdentifiersTlv ipv4LspIdenTlv,
- float bandwidth, LspType lspType) {
- SparseAnnotations annotations = DefaultAnnotations.builder()
+ float bandwidth, LspType lspType, String costType) {
+
+ Builder builder = DefaultAnnotations.builder();
+
+ /*
+ * [RFC 5440] The absence of the METRIC object MUST be interpreted by the PCE as a path computation request
+ * for which no constraints need be applied to any of the metrics.
+ */
+ if (costType != null) {
+ builder.set(COST_TYPE, costType);
+ }
+
+ SparseAnnotations annotations = builder
.set(BANDWIDTH, (new Float(bandwidth)).toString()).set(LSP_SIG_TYPE, lspType.name())
.set(PCC_TUNNEL_ID, String.valueOf(ipv4LspIdenTlv.getTunnelId()))
.set(PLSP_ID, String.valueOf(lspObj.getPlspId()))
@@ -1340,8 +1317,9 @@
return lspType;
}
- private void handleRptWithoutSrpId(PcepStateReport stateRpt, PccId pccId, PcepSyncStatus syncStatus) {
+ private void handleRptWithoutSrpId(PcepStateReport stateRpt, PccId pccId) {
ProviderId providerId = new ProviderId("pcep", PROVIDER_ID);
+ String costType = null;
PcepStateReport.PcepMsgPath msgPath = stateRpt.getMsgPath();
checkNotNull(msgPath);
PcepEroObject eroObj = msgPath.getEroObject();
@@ -1349,7 +1327,30 @@
log.error("ERO object is null in report message.");
return;
}
- Path path = buildPathFromEroObj(eroObj, providerId);
+
+ PcepAttribute attributes = msgPath.getPcepAttribute();
+ int cost = 0;
+ if (attributes != null && attributes.getMetricObjectList() != null) {
+ ListIterator<PcepMetricObject> iterator = attributes.getMetricObjectList().listIterator();
+ PcepMetricObject metricObj = iterator.next();
+
+ while (metricObj != null) {
+ if (metricObj.getBType() == IGP_METRIC) {
+ costType = "COST";
+ } else if (metricObj.getBType() == TE_METRIC) {
+ costType = "TE_COST";
+ }
+
+ if (costType != null) {
+ cost = metricObj.getMetricVal();
+ log.debug("Path cost {}", cost);
+ break;
+ }
+ metricObj = iterator.next();
+ }
+ }
+
+ Path path = buildPathFromEroObj(eroObj, providerId, cost);
float bandwidth = 0;
if (msgPath.getBandwidthObject() != null) {
@@ -1443,48 +1444,23 @@
return;
}
- if (lspObj.getCFlag()) {
- /*
- * While in sync, if PCRpt is received for PCE init LSP and PCE doesn't have entry, mark to send
- * delete message on end of sync.
- */
- annotations = getAnnotations(lspObj, ipv4LspIdenTlv, bandwidth, lspType);
-
- // Generate tunnel id for the temporary tunnel.
- String onosTunnelId = "PCC" + String.valueOf(ipv4LspIdenTlv.getTunnelId());
- Tunnel tunnelToBeDeleted = new DefaultTunnel(providerId, tunnelEndPointSrc, tunnelEndPointDst, MPLS,
- new DefaultGroupId(0), TunnelId.valueOf(onosTunnelId),
- TunnelName.tunnelName(String
- .valueOf(pathNameTlv.getValue())),
- path, annotations);
- /*
- * Need to send PCInitiate delete msg for a tunnel which does not exist at PCE. For that some dummy
- * data-structures need to be populated.
- */
- PcepTunnelData pcepTunnelData = new PcepTunnelData(tunnelToBeDeleted, path, RequestType.DELETE);
- pcepTunnelData.setPlspId(lspObj.getPlspId());
- pcepTunnelData.setStatefulIpv4IndentifierTlv(ipv4LspIdenTlv);
- pcepTunnelApiMapper.addToTunnelIdMap(pcepTunnelData);
- pcepTunnelApiMapper.handleCreateTunnelRequestQueue(0, pcepTunnelData);
-
- /*
- * Add to the list of tunnels for which PCInit delete will be sent at the end of sync.
- */
- List<Tunnel> tunnelToBeDeletedList = syncCompleteDeleteList.get(pccId.ipAddress());
- tunnelToBeDeletedList.add(tunnelToBeDeleted);
- syncCompleteDeleteList.put(pccId.ipAddress(), tunnelToBeDeletedList);
- return;
- }
DeviceId deviceId = getDevice(pccId);
if (deviceId == null) {
log.error("Ingress deviceId not found");
return;
}
- annotations = getAnnotations(lspObj, ipv4LspIdenTlv, bandwidth, lspType);
+ annotations = getAnnotations(lspObj, ipv4LspIdenTlv, bandwidth, lspType, costType);
td = new DefaultTunnelDescription(null, tunnelEndPointSrc, tunnelEndPointDst, MPLS, new DefaultGroupId(
0), providerId, TunnelName.tunnelName(new String(pathNameTlv.getValue())), path,
annotations);
+
+ // Do not support PCC initiated LSP after LSP DB sync is completed.
+ if (!lspObj.getSFlag() && !lspObj.getCFlag()) {
+ log.error("Received PCC initiated LSP while not in sync.");
+ return;
+ }
+
/*
* If ONOS instance is master for PCC then set delegated flag as annotation and add the tunnel to store.
* Because all LSPs need not be delegated, hence mastership for the PCC is confirmed whereas not the
@@ -1523,35 +1499,24 @@
//delegated owner will update can be a master or non-master
if (lspObj.getDFlag()) {
- annotations = getAnnotations(lspObj, ipv4LspIdenTlv, bandwidth, lspType);
+ annotations = getAnnotations(lspObj, ipv4LspIdenTlv, bandwidth, lspType, costType);
td = new DefaultTunnelDescription(null, tunnelEndPointSrc, tunnelEndPointDst, MPLS, new DefaultGroupId(
0), providerId, TunnelName.tunnelName(new String(pathNameTlv.getValue())), path,
annotations);
tunnelUpdateInDelegatedCase(pccId, annotations, td, providerId);
}
-
- if ((syncStatus == IN_SYNC) && (lspObj.getCFlag()) && (tunnelState != tunnel.state())) {
- // Mark to send PCUpd msg with state known at PCE.
- List<Tunnel> tunnelToBeUpdateList = syncCompleteUpdateList.get(pccId.ipAddress());
- tunnelToBeUpdateList.add(tunnel);
- syncCompleteUpdateList.put(pccId.ipAddress(), tunnelToBeUpdateList);
- return;
- }
- removeOrUpdatetunnel(tunnel, pccId, lspObj, providerId, syncStatus, tunnelState);
+ removeOrUpdatetunnel(tunnel, pccId, lspObj, providerId, tunnelState);
return;
}
private void removeOrUpdatetunnel(Tunnel tunnel, PccId pccId, PcepLspObject lspObj, ProviderId providerId,
- PcepSyncStatus syncStatus, State tunnelState) {
+ State tunnelState) {
DefaultTunnelDescription td = new DefaultTunnelDescription(tunnel.tunnelId(), tunnel.src(), tunnel.dst(),
tunnel.type(), tunnel.groupId(), providerId, tunnel.tunnelName(), tunnel.path(),
(SparseAnnotations) tunnel.annotations());
if (lspObj.getRFlag()) {
tunnelRemoved(td);
} else {
- if (syncStatus == IN_SYNC) {
- markLspDbEntryAsLatest(pccId, tunnel.tunnelId());
- }
tunnelUpdated(td, tunnelState);
}
}
@@ -1576,9 +1541,10 @@
*
* @param eroObj ERO object
* @param providerId provider id
+ * @param cost cost of path
* @return path object
*/
- private Path buildPathFromEroObj(PcepEroObject eroObj, ProviderId providerId) {
+ private Path buildPathFromEroObj(PcepEroObject eroObj, ProviderId providerId, int cost) {
checkNotNull(eroObj);
List<Link> links = new ArrayList<Link>();
LinkedList<PcepValueType> llSubObj = eroObj.getSubObjects();
@@ -1618,7 +1584,8 @@
// the other sub objects are not required
}
}
- return new DefaultPath(providerId, links, 0, EMPTY);
+
+ return new DefaultPath(providerId, links, cost, EMPTY);
}
@Override
@@ -1637,44 +1604,14 @@
TunnelStatistics tunnelStatistics = buildTunnelStatistics(pcepTunnelStatistics);
tunnelStatisticsMap.put(id, tunnelStatistics);
}
- }
- @Override
- public Tunnel tunnelQueryById(TunnelId tunnelId) {
- return service.tunnelQueryById(tunnelId);
- }
+ @Override
+ public void handleEndOfSyncAction(Tunnel tunnel, PcepLspSyncAction endOfSyncAction) {
- /**
- * Removes the entry from temporary copy of LSPDB, signifying its status as upto date.
- *
- * @param pccId the key for temporary LSPDB
- * @param tunnelId the tunnel id for which information is updated.
- */
- private void markLspDbEntryAsLatest(PccId pccId, TunnelId tunnelId) {
- checkNotNull(pccId);
- checkNotNull(tunnelId);
-
- Map<TunnelId, Tunnel> preSyncLspDb = preSyncLspDbMap.get(pccId.ipAddress());
- checkNotNull(preSyncLspDb);
-
- preSyncLspDb.remove(tunnelId);
- preSyncLspDbMap.put(pccId.ipAddress(), preSyncLspDb);
- }
-
- /**
- * Sends PCInit, PCInit(R) or PCUpd messages for initiated LSPs at the end
- * of LSP DB sync based on actions decided while sync was in progress. Also
- * triggers label DB sync.
- *
- * @param pccId the key for temporary DBs storing required end of sync
- * actions.
- */
- private void handleEndOfSyncAction(PccId pccId) {
-
- Map<TunnelId, Tunnel> preSyncLspDb = preSyncLspDbMap.get(pccId.ipAddress());
- checkNotNull(preSyncLspDb);
-
- for (Tunnel tunnel : preSyncLspDb.values()) {
+ if (endOfSyncAction == SEND_UPDATE) {
+ updateTunnel(tunnel, tunnel.path());
+ return;
+ }
TunnelDescription td = new DefaultTunnelDescription(tunnel.tunnelId(),
tunnel.src(), tunnel.dst(),
@@ -1685,43 +1622,56 @@
tunnel.path(),
(SparseAnnotations) tunnel.annotations());
- if ((tunnel.annotations().value(PCE_INIT) == null)
- || (tunnel.annotations().value(PCE_INIT).equals("false"))) {
- tunnelRemoved(td);
- } else {
+ if (endOfSyncAction == PcepLspSyncAction.UNSTABLE) {
+
// Send PCInit msg again after global reoptimization.
tunnelUpdated(td, UNSTABLE);
// To remove the old tunnel from store whose PLSPID is not
// recognized by ingress PCC.
tunnelRemoved(td);
+
+ } else if (endOfSyncAction == REMOVE) {
+ tunnelRemoved(td);
}
}
- List<Tunnel> tunnelsToBeDeletedList = syncCompleteDeleteList.get(pccId.ipAddress());
- checkNotNull(tunnelsToBeDeletedList);
- for (Tunnel tunnel: tunnelsToBeDeletedList) {
- releaseTunnel(tunnel);
- }
+ @Override
+ public void handleEndOfSyncAction(PccId pccId, PcepMessage msg, PcepLspSyncAction endOfSyncAction) {
+ try {
+ if ((msg instanceof PcepInitiateMsg) && (endOfSyncAction == SEND_DELETE)) {
+ PcepClient pc = pcepClientController.getClient(pccId);
+ LinkedList<PcInitiatedLspRequest> llPcInitiatedLspRequestList = ((PcepInitiateMsg) msg)
+ .getPcInitiatedLspRequestList();
+ PcInitiatedLspRequest pcInitMsg = llPcInitiatedLspRequestList.iterator().next();
- List<Tunnel> tunnelsToBeUpdatedList = syncCompleteUpdateList.get(pccId.ipAddress());
- checkNotNull(tunnelsToBeUpdatedList);
- for (Tunnel tunnel: tunnelsToBeUpdatedList) {
- updateTunnel(tunnel, tunnel.path());
- }
+ if (pcInitMsg != null) {
+ PcepSrpObject srpobj = pc.factory().buildSrpObject().setSrpID(SrpIdGenerators.create())
+ .setRFlag(true).build();
- /* On end of sync, empty all temporary data structures. */
- preSyncLspDbMap.remove(pccId.ipAddress());
- syncCompleteDeleteList.remove(pccId.ipAddress());
- syncCompleteUpdateList.remove(pccId.ipAddress());
+ PcInitiatedLspRequest releaseLspRequest = pc.factory().buildPcInitiatedLspRequest()
+ .setLspObject(pcInitMsg.getLspObject()).setSrpObject(srpobj).build();
- // TODO: If SR capable, send a notification to
- // PCE APP to start label DB sync.
- if (true) {
- pcepClientController.getClient(pccId).setLabelDbSyncStatus(IN_SYNC);
+ llPcInitiatedLspRequestList.remove(pcInitMsg);
+ llPcInitiatedLspRequestList.add(releaseLspRequest);
+
+ PcepInitiateMsg pcInitiateMsg = pc.factory().buildPcepInitiateMsg()
+ .setPcInitiatedLspRequestList(llPcInitiatedLspRequestList).build();
+
+ pc.sendMessage(Collections.singletonList(pcInitiateMsg));
+ }
+ }
+ } catch (PcepParseException e) {
+ log.error("Exception occured while sending initiate delete message {}", e.getMessage());
+ }
}
}
+ @Override
+ public Tunnel tunnelQueryById(TunnelId tunnelId) {
+ return service.tunnelQueryById(tunnelId);
+ }
+
private DeviceId getDevice(PccId pccId) {
// Get lsrId of the PCEP client from the PCC ID. Session info is based on lsrID.