import org.opendaylight.bgpcep.pcep.topology.provider.AbstractPCEPSessionTest;
import org.opendaylight.bgpcep.pcep.topology.provider.AbstractTopologySessionListener;
import org.opendaylight.bgpcep.pcep.topology.provider.Stateful07TopologySessionListenerFactory;
+import org.opendaylight.protocol.pcep.PCEPSession;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.Path1;
public class TopologyProviderTest extends AbstractPCEPSessionTest<Stateful07TopologySessionListenerFactory> {
private AbstractTopologySessionListener<SrpIdNumber, PlspId> listener;
+ private PCEPSession session;
@Override
@SuppressWarnings("unchecked")
public void setUp() throws Exception {
super.setUp();
this.listener = (AbstractTopologySessionListener<SrpIdNumber, PlspId>) getSessionListener();
+ this.session = getPCEPSession(getLocalPref(), getRemotePref());
}
@Test
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.pcep.client.attributes.path.computation.client.ReportedLspBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.pcep.client.attributes.path.computation.client.ReportedLspKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.pcep.client.attributes.path.computation.client.reported.lsp.Path;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
import org.opendaylight.yangtools.yang.binding.DataContainer;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
private TopologyNodeState nodeState;
private boolean synced = false;
private PCEPSession session;
+ private SyncOptimization syncOptimization;
private ListenerStateRuntimeRegistration registration;
private final SessionListenerState listenerState;
*/
final InetAddress peerAddress = session.getRemoteAddress();
- final TopologyNodeState state = this.serverSessionManager.takeNodeState(peerAddress, this);
+ syncOptimization = new SyncOptimization(session);
+
+ final TopologyNodeState state = this.serverSessionManager.takeNodeState(peerAddress, this, isLspDbRetreived());
+
+ this.session = session;
+ this.nodeState = state;
LOG.trace("Peer {} resolved to topology node {}", peerAddress, state.getNodeId());
- this.synced = false;
// Our augmentation in the topology node
final PathComputationClientBuilder pccBuilder = new PathComputationClientBuilder();
- pccBuilder.setIpAddress(IpAddressBuilder.getDefaultInstance(peerAddress.getHostAddress()));
onSessionUp(session, pccBuilder);
+ this.synced = isSynchronized();
- final Node1 ta = new Node1Builder().setPathComputationClient(pccBuilder.build()).build();
+ pccBuilder.setIpAddress(IpAddressBuilder.getDefaultInstance(peerAddress.getHostAddress()));
final InstanceIdentifier<Node1> topologyAugment = state.getNodeId().augmentation(Node1.class);
this.pccIdentifier = topologyAugment.child(PathComputationClient.class);
+ final Node initialNodeState = state.getInitialNodeState();
+ final boolean isNodePresent = isLspDbRetreived() && initialNodeState != null;
+ if (isNodePresent) {
+ loadLspData(initialNodeState, lspData, lsps);
+ pccBuilder.setReportedLsp(initialNodeState.getAugmentation(Node1.class).getPathComputationClient().getReportedLsp());
+ }
+ writeNode(pccBuilder, state, topologyAugment);
+ this.listenerState.init(session);
+ if (this.serverSessionManager.getRuntimeRootRegistration().isPresent()) {
+ this.registration = this.serverSessionManager.getRuntimeRootRegistration().get().register(this);
+ }
+ LOG.info("Session with {} attached to topology node {}", session.getRemoteAddress(), state.getNodeId());
+ }
+
+ private void writeNode(final PathComputationClientBuilder pccBuilder, final TopologyNodeState state,
+ final InstanceIdentifier<Node1> topologyAugment) {
+ final Node1 ta = new Node1Builder().setPathComputationClient(pccBuilder.build()).build();
final ReadWriteTransaction trans = state.rwTransaction();
trans.put(LogicalDatastoreType.OPERATIONAL, topologyAugment, ta);
session.close(TerminationReason.UNKNOWN);
}
});
-
- this.session = session;
- this.nodeState = state;
- this.listenerState.init(session);
- if (this.serverSessionManager.getRuntimeRootRegistration().isPresent()) {
- this.registration = this.serverSessionManager.getRuntimeRootRegistration().get().register(this);
- }
- LOG.info("Session with {} attached to topology node {}", session.getRemoteAddress(), state.getNodeId());
}
@GuardedBy("this")
private void tearDown(final PCEPSession session) {
- this.serverSessionManager.releaseNodeState(this.nodeState, session);
+ this.serverSessionManager.releaseNodeState(this.nodeState, session, isLspDbPersisted());
this.nodeState = null;
this.session = null;
+ this.syncOptimization = null;
unregister();
// Clear all requests we know about
// Update synchronization flag
this.synced = true;
- ctx.trans.merge(LogicalDatastoreType.OPERATIONAL, this.pccIdentifier, new PathComputationClientBuilder().setStateSync(PccSyncState.Synchronized).build());
+ updatePccNode(ctx, new PathComputationClientBuilder().setStateSync(PccSyncState.Synchronized).build());
// The node has completed synchronization, cleanup metadata no longer reported back
this.nodeState.cleanupExcept(this.lsps.values());
LOG.debug("Session {} achieved synchronized state", this.session);
}
+ protected final synchronized void updatePccNode(final MessageContext ctx, final PathComputationClient pcc) {
+ ctx.trans.merge(LogicalDatastoreType.OPERATIONAL, this.pccIdentifier, pcc);
+ }
+
protected final InstanceIdentifier<ReportedLsp> lspIdentifier(final String name) {
return this.pccIdentifier.child(ReportedLsp.class, new ReportedLspKey(name));
}
+ protected final InstanceIdentifier<PathComputationClient> getPccIdentifier() {
+ return this.pccIdentifier;
+ }
+
/**
* Remove LSP from the database.
*
protected abstract Object validateReportedLsp(final Optional<ReportedLsp> rep, final LspId input);
+ protected abstract void loadLspData(final Node node, final Map<String, ReportedLsp> lspData, final Map<L, String> lsps);
+
+ protected final boolean isLspDbPersisted() {
+ if (syncOptimization != null) {
+ return syncOptimization.isSyncAvoidanceEnabled();
+ }
+ return false;
+ }
+
+ protected final boolean isLspDbRetreived() {
+ if (syncOptimization != null) {
+ return syncOptimization.isDbVersionPresent();
+ }
+ return false;
+ }
+
+ protected final boolean isSynchronized() {
+ if (syncOptimization != null) {
+ return syncOptimization.doesLspDbMatch();
+ }
+ return false;
+ }
+
protected SessionListenerState getSessionListenerState() {
return this.listenerState;
}
--- /dev/null
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.bgpcep.pcep.topology.provider;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.pcep.sync.optimizations.rev150714.PathComputationClient1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.pcep.sync.optimizations.rev150714.Stateful1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.pcep.sync.optimizations.rev150714.Tlvs3;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.pcep.sync.optimizations.rev150714.Tlvs3Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.pcep.sync.optimizations.rev150714.lsp.db.version.tlv.LspDbVersion;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.Tlvs1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.open.object.open.TlvsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.Node1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.pcep.client.attributes.PathComputationClient;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class PCEPStatefulPeerProposal {
+
+ private static final Logger LOG = LoggerFactory.getLogger(PCEPStatefulPeerProposal.class);
+
+ private final DataBroker dataBroker;
+ private final InstanceIdentifier<Topology> topologyId;
+
+ private PCEPStatefulPeerProposal(final DataBroker dataBroker, final InstanceIdentifier<Topology> topologyId) {
+ this.dataBroker = Preconditions.checkNotNull(dataBroker);
+ this.topologyId = Preconditions.checkNotNull(topologyId);
+ }
+
+ public static PCEPStatefulPeerProposal createStatefulPeerProposal(final DataBroker dataBroker,
+ final InstanceIdentifier<Topology> topologyId) {
+ return new PCEPStatefulPeerProposal(dataBroker, topologyId);
+ }
+
+ void setPeerProposal(final NodeId nodeId, final TlvsBuilder openTlvsBuilder) {
+ if (isSynOptimizationEnabled(openTlvsBuilder)) {
+ final ListenableFuture<Optional<LspDbVersion>> future = this.dataBroker.newReadOnlyTransaction().read(
+ LogicalDatastoreType.OPERATIONAL,
+ topologyId.child(Node.class, new NodeKey(nodeId)).augmentation(Node1.class)
+ .child(PathComputationClient.class).augmentation(PathComputationClient1.class)
+ .child(LspDbVersion.class));
+ Futures.addCallback(future, new FutureCallback<Optional<LspDbVersion>>() {
+ @Override
+ public void onSuccess(final Optional<LspDbVersion> result) {
+ if (result.isPresent()) {
+ openTlvsBuilder.addAugmentation(Tlvs3.class, new Tlvs3Builder().setLspDbVersion(result.get())
+ .build());
+ }
+ }
+
+ @Override
+ public void onFailure(final Throwable t) {
+ LOG.warn("Failed to read toplogy {}.", InstanceIdentifier.keyOf(topologyId), t);
+ }
+ });
+ }
+ }
+
+ private static boolean isSynOptimizationEnabled(final TlvsBuilder openTlvsBuilder) {
+ final Tlvs1 statefulTlv = openTlvsBuilder.getAugmentation(Tlvs1.class);
+ if (statefulTlv != null && statefulTlv.getStateful() != null) {
+ return statefulTlv.getStateful().getAugmentation(Stateful1.class) != null;
+ }
+ return false;
+ }
+
+}
if (runtimeRootRegistrator.isPresent()) {
manager.registerRuntimeRootRegistartion(runtimeRootRegistrator.get());
}
- final ChannelFuture f = dispatcher.createServer(address, keys, manager, null);
+ final ChannelFuture f = dispatcher.createServer(address, keys, manager, manager);
f.get();
final BindingAwareBroker.RoutedRpcRegistration<NetworkTopologyPcepService> element = rpcRegistry.addRoutedRpcImplementation(
import com.google.common.base.Preconditions;
import com.google.common.util.concurrent.ListenableFuture;
import java.net.InetAddress;
+import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.opendaylight.protocol.pcep.PCEPPeerProposal;
import org.opendaylight.protocol.pcep.PCEPSession;
import org.opendaylight.protocol.pcep.PCEPSessionListener;
import org.opendaylight.protocol.pcep.PCEPSessionListenerFactory;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.open.object.open.TlvsBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.AddLspArgs;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.EnsureLspOperationalInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.OperationResult;
/**
*
*/
-final class ServerSessionManager implements PCEPSessionListenerFactory, AutoCloseable, TopologySessionRPCs, PCEPTopologyProviderRuntimeMXBean {
+final class ServerSessionManager implements PCEPSessionListenerFactory, AutoCloseable, TopologySessionRPCs, PCEPTopologyProviderRuntimeMXBean, PCEPPeerProposal {
private static final Logger LOG = LoggerFactory.getLogger(ServerSessionManager.class);
private static final long DEFAULT_HOLD_STATE_NANOS = TimeUnit.MINUTES.toNanos(5);
private final TopologySessionListenerFactory listenerFactory;
private final InstanceIdentifier<Topology> topology;
private final DataBroker broker;
+ private final PCEPStatefulPeerProposal peerProposal;
private Optional<PCEPTopologyProviderRuntimeRegistration> runtimeRootRegistration = Optional.absent();
public ServerSessionManager(final DataBroker broker, final InstanceIdentifier<Topology> topology,
this.broker = Preconditions.checkNotNull(broker);
this.topology = Preconditions.checkNotNull(topology);
this.listenerFactory = Preconditions.checkNotNull(listenerFactory);
+ this.peerProposal = PCEPStatefulPeerProposal.createStatefulPeerProposal(this.broker, this.topology);
// Now create the base topology
final TopologyKey k = InstanceIdentifier.keyOf(topology);
return new NodeId("pcc://" + addr.getHostAddress());
}
- synchronized void releaseNodeState(final TopologyNodeState nodeState, final PCEPSession session) {
+ synchronized void releaseNodeState(final TopologyNodeState nodeState, final PCEPSession session, final boolean persistNode) {
LOG.debug("Node {} unbound", nodeState.getNodeId());
this.nodes.remove(createNodeId(session.getRemoteAddress()));
- nodeState.released();
+ nodeState.released(persistNode);
}
- synchronized TopologyNodeState takeNodeState(final InetAddress address, final TopologySessionListener sessionListener) {
+ synchronized TopologyNodeState takeNodeState(final InetAddress address, final TopologySessionListener sessionListener, final boolean retrieveNode) {
final NodeId id = createNodeId(address);
LOG.debug("Node {} requested by listener {}", id, sessionListener);
}
// FIXME: else check for conflicting session
- ret.taken();
+ ret.taken(retrieveNode);
this.nodes.put(id, sessionListener);
LOG.debug("Node {} bound to listener {}", id, sessionListener);
return ret;
public Optional<PCEPTopologyProviderRuntimeRegistration> getRuntimeRootRegistration() {
return this.runtimeRootRegistration;
}
+
+ @Override
+ public void setPeerSpecificProposal(final InetSocketAddress address, final TlvsBuilder openBuilder) {
+ Preconditions.checkNotNull(address);
+ peerProposal.setPeerProposal(createNodeId(address.getAddress()), openBuilder);
+ }
}
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;
+import javax.annotation.concurrent.GuardedBy;
import org.opendaylight.controller.config.yang.pcep.topology.provider.PeerCapabilities;
import org.opendaylight.protocol.pcep.PCEPSession;
import org.opendaylight.protocol.pcep.spi.PCEPErrors;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.pcep.sync.optimizations.rev150714.PathComputationClient1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.pcep.sync.optimizations.rev150714.PathComputationClient1Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.pcep.sync.optimizations.rev150714.lsp.db.version.tlv.LspDbVersion;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.PcinitiateBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.Srp1;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.Srp1Builder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.AddLspArgs;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.EnsureLspOperationalInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.LspId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.Node1;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.OperationResult;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.PccSyncState;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.RemoveLspArgs;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.UpdateLspArgs;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.pcep.client.attributes.PathComputationClient;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.pcep.client.attributes.PathComputationClientBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.pcep.client.attributes.path.computation.client.ReportedLsp;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.pcep.client.attributes.path.computation.client.ReportedLspBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.pcep.client.attributes.path.computation.client.StatefulTlvBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.pcep.client.attributes.path.computation.client.reported.lsp.Path;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private final AtomicLong requestId = new AtomicLong(1L);
+ @GuardedBy("this")
+ private final List<PlspId> staleLsps = new ArrayList<>();
+
/**
* Creates a new stateful topology session listener for given server session manager.
*
if (stateful != null) {
getSessionListenerState().setPeerCapabilities(getCapabilities(stateful));
pccBuilder.setReportedLsp(Collections.<ReportedLsp> emptyList());
- pccBuilder.setStateSync(PccSyncState.InitialResync);
+ if (isSynchronized()) {
+ pccBuilder.setStateSync(PccSyncState.Synchronized);
+ } else {
+ pccBuilder.setStateSync(PccSyncState.InitialResync);
+ }
pccBuilder.setStatefulTlv(new StatefulTlvBuilder().addAugmentation(StatefulTlv1.class,
new StatefulTlv1Builder(tlvs.getAugmentation(Tlvs1.class)).build()).build());
} else {
final Lsp lsp = report.getLsp();
final PlspId plspid = lsp.getPlspId();
if (!lsp.isSync() && (lsp.getPlspId() == null || plspid.getValue() == 0)) {
+ purgeStaleLsps(ctx);
stateSynchronizationAchieved(ctx);
return true;
}
rlb.setPath(Collections.singletonList(buildPath(report, srp, lsp)));
String name = lookupLspName(plspid);
- if (report.getLsp().getTlvs() != null && report.getLsp().getTlvs().getSymbolicPathName() != null) {
- name = Charsets.UTF_8.decode(ByteBuffer.wrap(report.getLsp().getTlvs().getSymbolicPathName().getPathName().getValue())).toString();
+ if (lsp.getTlvs() != null && lsp.getTlvs().getSymbolicPathName() != null) {
+ name = Charsets.UTF_8.decode(ByteBuffer.wrap(lsp.getTlvs().getSymbolicPathName().getPathName().getValue())).toString();
+ }
+ //get LspDB from LSP and write it to pcc's node
+ final LspDbVersion lspDbVersion = geLspDbVersionTlv(lsp);
+ if (lspDbVersion != null) {
+ updatePccNode(ctx, new PathComputationClientBuilder().addAugmentation(PathComputationClient1.class,
+ new PathComputationClient1Builder().setLspDbVersion(lspDbVersion).build()).build());
}
updateLsp(ctx, plspid, name, rlb, solicited, lsp.isRemove());
+ unmarkStaleLsp(plspid, lsp.isSync());
+
LOG.debug("LSP {} updated", lsp);
return true;
}
+ private static LspDbVersion geLspDbVersionTlv(final Lsp lsp) {
+ final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.lsp.object.lsp.Tlvs tlvs = lsp.getTlvs();
+ if (tlvs != null && tlvs.getAugmentation(org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.pcep.sync.optimizations.rev150714.Tlvs1.class) != null) {
+ return tlvs.getAugmentation(org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.pcep.sync.optimizations.rev150714.Tlvs1.class).getLspDbVersion();
+ }
+ return null;
+ }
+
private Path buildPath(final Reports report, final Srp srp, final Lsp lsp) {
final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.pcep.client.attributes.path.computation.client.reported.lsp.PathBuilder pb = new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.pcep.client.attributes.path.computation.client.reported.lsp.PathBuilder();
if (report.getPath() != null) {
}
return capa;
}
+
+ @Override
+ protected synchronized void loadLspData(final Node node, final Map<String, ReportedLsp> lspData, final Map<PlspId, String> lsps) {
+ //load node's lsps from DS
+ final PathComputationClient pcc = node.getAugmentation(Node1.class).getPathComputationClient();
+ final List<ReportedLsp> reportedLsps = pcc.getReportedLsp();
+ for (final ReportedLsp reportedLsp : reportedLsps) {
+ final String lspName = reportedLsp.getName();
+ lspData.put(lspName, reportedLsp);
+ if (!reportedLsp.getPath().isEmpty()) {
+ final Path1 path1 = reportedLsp.getPath().get(0).getAugmentation(Path1.class);
+ if (path1 != null) {
+ final PlspId plspId = path1.getLsp().getPlspId();
+ staleLsps.add(plspId);
+ lsps.put(plspId, lspName);
+ }
+ }
+ }
+ }
+
+ private synchronized void unmarkStaleLsp(final PlspId plspId, final boolean sync) {
+ if (!sync) {
+ staleLsps.remove(plspId);
+ }
+ }
+
+ private synchronized void purgeStaleLsps(final MessageContext ctx) {
+ for (final PlspId plspId : staleLsps) {
+ removeLsp(ctx, plspId);
+ }
+ staleLsps.clear();
+ }
}
--- /dev/null
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.bgpcep.pcep.topology.provider;
+
+import com.google.common.base.Preconditions;
+import org.opendaylight.protocol.pcep.PCEPSession;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.pcep.sync.optimizations.rev150714.Stateful1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.pcep.sync.optimizations.rev150714.Tlvs3;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.pcep.sync.optimizations.rev150714.lsp.db.version.tlv.LspDbVersion;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.Tlvs1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.open.object.open.Tlvs;
+
+final class SyncOptimization {
+
+ private final boolean dbVersionMatch;
+ private final boolean isSyncAvoidanceEnabled;
+ private final boolean isDbVersionPresent;
+
+ public SyncOptimization(final PCEPSession session) {
+ Preconditions.checkNotNull(session);
+ final Tlvs remote = session.getRemoteTlvs();
+ final Tlvs local = session.localSessionCharacteristics();
+ final LspDbVersion localLspDbVersion = getLspDbVersion(local);
+ final LspDbVersion remoteLspDbVersion = getLspDbVersion(remote);
+ this.dbVersionMatch = compareLspDbVersion(localLspDbVersion, remoteLspDbVersion);
+ this.isSyncAvoidanceEnabled = isSyncAvoidance(local) && isSyncAvoidance(remote);
+ this.isDbVersionPresent = localLspDbVersion != null || remoteLspDbVersion != null;
+ }
+
+ public boolean doesLspDbMatch() {
+ return dbVersionMatch;
+ }
+
+ public boolean isSyncAvoidanceEnabled() {
+ return isSyncAvoidanceEnabled;
+ }
+
+ public boolean isDbVersionPresent() {
+ return isDbVersionPresent;
+ }
+
+ private static LspDbVersion getLspDbVersion(final Tlvs openTlvs) {
+ if (openTlvs != null) {
+ final Tlvs3 tlvs3 = openTlvs.getAugmentation(Tlvs3.class);
+ if (tlvs3 != null && tlvs3.getLspDbVersion() != null
+ && tlvs3.getLspDbVersion().getLspDbVersionValue() != null) {
+ return tlvs3.getLspDbVersion();
+ }
+ }
+ return null;
+ }
+
+ private static boolean compareLspDbVersion(final LspDbVersion local, final LspDbVersion remote) {
+ if (local != null && remote != null) {
+ return local.equals(remote);
+ }
+ return false;
+ }
+
+ private static boolean isSyncAvoidance(final Tlvs openTlvs) {
+ if (openTlvs != null) {
+ final Tlvs1 tlvs1 = openTlvs.getAugmentation(Tlvs1.class);
+ if (tlvs1 != null && tlvs1.getStateful() != null) {
+ final Stateful1 stateful1 = tlvs1.getStateful().getAugmentation(Stateful1.class);
+ if (stateful1 != null && stateful1.isIncludeDbVersion() != null) {
+ return stateful1.isIncludeDbVersion();
+ }
+ }
+ }
+ return false;
+ }
+
+}
private final BindingTransactionChain chain;
private final long holdStateNanos;
private long lastReleased = 0;
+ //cache initial node state, if any node was persisted
+ private Node initialNodeState = null;
public TopologyNodeState(final DataBroker broker, final InstanceIdentifier<Topology> topology, final NodeId id, final long holdStateNanos) {
Preconditions.checkArgument(holdStateNanos >= 0);
}
}
- public synchronized void released() {
+ public synchronized void released(final boolean persist) {
// The session went down. Undo all the Topology changes we have done.
- final WriteTransaction trans = beginTransaction();
-
- trans.delete(LogicalDatastoreType.OPERATIONAL, this.nodeId);
-
- Futures.addCallback(trans.submit(), new FutureCallback<Void>() {
- @Override
- public void onSuccess(final Void result) {
- LOG.trace("Internal state for node {} cleaned up successfully", nodeId);
- }
-
- @Override
- public void onFailure(final Throwable t) {
- LOG.error("Failed to cleanup internal state for session {}", nodeId, t);
- }
- });
+ // We might want to persist topology node for later re-use.
+ if (!persist) {
+ final WriteTransaction trans = beginTransaction();
+ trans.delete(LogicalDatastoreType.OPERATIONAL, this.nodeId);
+ Futures.addCallback(trans.submit(), new FutureCallback<Void>() {
+ @Override
+ public void onSuccess(final Void result) {
+ LOG.trace("Internal state for node {} cleaned up successfully", nodeId);
+ }
+
+ @Override
+ public void onFailure(final Throwable t) {
+ LOG.error("Failed to cleanup internal state for session {}", nodeId, t);
+ }
+ });
+ }
lastReleased = System.nanoTime();
}
- public synchronized void taken() {
+ public synchronized void taken(final boolean retrieveNode) {
final long now = System.nanoTime();
if (now - lastReleased > holdStateNanos) {
metadata.clear();
}
- final Node node = new NodeBuilder().setKey(nodeId.getKey()).setNodeId(nodeId.getKey().getNodeId()).build();
- final WriteTransaction t = chain.newWriteOnlyTransaction();
- t.put(LogicalDatastoreType.OPERATIONAL, nodeId, node);
- t.submit();
+ //try to get the topology's node
+ if (retrieveNode) {
+ Futures.addCallback(readOperationalData(nodeId), new FutureCallback<Optional<Node>>() {
+
+ @Override
+ public void onSuccess(final Optional<Node> result) {
+ if (!result.isPresent()) {
+ putTopologyNode();
+ } else {
+ //cache retrieved node
+ initialNodeState = result.get();
+ }
+ }
+
+ @Override
+ public void onFailure(final Throwable t) {
+ LOG.error("Failed to get topology node {}", nodeId, t);
+ }
+ });
+ } else {
+ putTopologyNode();
+ }
+ }
+
+ public synchronized Node getInitialNodeState() {
+ return initialNodeState;
}
WriteTransaction beginTransaction() {
chain.close();
}
+ private void putTopologyNode() {
+ final Node node = new NodeBuilder().setKey(nodeId.getKey()).setNodeId(nodeId.getKey().getNodeId()).build();
+ final WriteTransaction t = beginTransaction();
+ t.put(LogicalDatastoreType.OPERATIONAL, nodeId, node);
+ t.submit();
+ }
+
}
\ No newline at end of file
import org.opendaylight.controller.md.sal.binding.test.AbstractDataBrokerTest;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.opendaylight.protocol.pcep.PCEPSession;
import org.opendaylight.protocol.pcep.PCEPSessionListener;
import org.opendaylight.protocol.pcep.impl.DefaultPCEPSessionNegotiator;
-import org.opendaylight.protocol.pcep.impl.PCEPSessionImpl;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.explicit.route.object.Ero;
protected List<Notification> receivedMsgs;
- protected PCEPSessionImpl session;
-
@Mock
private EventLoop eventLoop;
private final Open localPrefs = new OpenBuilder().setDeadTimer((short) 30).setKeepalive((short) 10).setSessionId((short) 0).build();
+ private final Open remotePrefs = localPrefs;
+
protected ServerSessionManager manager;
protected NetworkTopologyPcepService topologyRpcs;
+ private DefaultPCEPSessionNegotiator neg;
+
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
this.listenerFactory = (T) ((Class)((ParameterizedType)this.getClass().getGenericSuperclass()).getActualTypeArguments()[0]).newInstance();
this.manager = new ServerSessionManager(getDataBroker(), TOPO_IID, this.listenerFactory);
- final DefaultPCEPSessionNegotiator neg = new DefaultPCEPSessionNegotiator(mock(Promise.class), this.clientListener, this.manager.getSessionListener(), (short) 1, 5, this.localPrefs);
- this.session = neg.createSession(this.clientListener, getLocalPref(), getLocalPref());
+ this.neg = new DefaultPCEPSessionNegotiator(mock(Promise.class), this.clientListener, this.manager.getSessionListener(), (short) 1, 5, this.localPrefs);
this.topologyRpcs = new TopologyRPCs(this.manager);
}
return this.localPrefs;
}
+ protected Open getRemotePref() {
+ return this.remotePrefs;
+ }
+
protected PCEPSessionListener getSessionListener() {
return this.manager.getSessionListener();
}
+
+ protected final PCEPSession getPCEPSession(final Open localOpen, final Open remoteOpen) {
+ return neg.createSession(this.clientListener, localOpen, remoteOpen);
+ }
}
--- /dev/null
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.bgpcep.pcep.topology.provider;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.CheckedFuture;
+import java.math.BigInteger;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.pcep.sync.optimizations.rev150714.Stateful1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.pcep.sync.optimizations.rev150714.Stateful1Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.pcep.sync.optimizations.rev150714.Tlvs3;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.pcep.sync.optimizations.rev150714.lsp.db.version.tlv.LspDbVersion;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.pcep.sync.optimizations.rev150714.lsp.db.version.tlv.LspDbVersionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.Tlvs1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.Tlvs1Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.stateful.capability.tlv.StatefulBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.open.object.open.TlvsBuilder;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class PCEPStatefulPeerProposalTest {
+
+ private static final InstanceIdentifier<Topology> TOPOLOGY_IID = InstanceIdentifier.create(NetworkTopology.class)
+ .child(Topology.class, new TopologyKey(new TopologyId("topology")));
+ private static final NodeId NODE_ID = new NodeId("node");
+ private static final LspDbVersion LSP_DB_VERSION = new LspDbVersionBuilder().setLspDbVersionValue(
+ BigInteger.valueOf(1l)).build();
+
+ @Mock
+ private DataBroker dataBroker;
+ @Mock
+ private CheckedFuture<Optional<LspDbVersion>, ReadFailedException> listenableFutureMock;
+
+ private TlvsBuilder tlvsBuilder;
+
+ @SuppressWarnings("unchecked")
+ @Before
+ public void setUp() throws InterruptedException, ExecutionException {
+ MockitoAnnotations.initMocks(this);
+ this.tlvsBuilder = new TlvsBuilder().addAugmentation(
+ Tlvs1.class,
+ new Tlvs1Builder().setStateful(
+ new StatefulBuilder().addAugmentation(Stateful1.class, new Stateful1Builder().build()).build())
+ .build());
+ final ReadOnlyTransaction rTxMock = Mockito.mock(ReadOnlyTransaction.class);
+ Mockito.doReturn(rTxMock).when(dataBroker).newReadOnlyTransaction();
+ Mockito.doReturn(listenableFutureMock).when(rTxMock)
+ .read(Mockito.any(LogicalDatastoreType.class), Mockito.any(InstanceIdentifier.class));
+
+ Mockito.doAnswer(new Answer<Void>() {
+ @Override
+ public Void answer(final InvocationOnMock invocation) throws Throwable {
+ final Runnable runnable = (Runnable) invocation.getArguments()[0];
+ runnable.run();
+ return null;
+ }
+ }).when(listenableFutureMock).addListener(Mockito.any(Runnable.class), Mockito.any(Executor.class));
+ }
+
+ @Test
+ public void testSetPeerProposalSuccess() throws InterruptedException, ExecutionException {
+ Mockito.doReturn(Optional.of(LSP_DB_VERSION)).when(listenableFutureMock).get();
+ final PCEPStatefulPeerProposal peerProposal = PCEPStatefulPeerProposal.createStatefulPeerProposal(dataBroker,
+ TOPOLOGY_IID);
+ peerProposal.setPeerProposal(NODE_ID, tlvsBuilder);
+ assertEquals(LSP_DB_VERSION, tlvsBuilder.getAugmentation(Tlvs3.class).getLspDbVersion());
+ }
+
+ @Test
+ public void testSetPeerProposalAbsent() throws InterruptedException, ExecutionException {
+ Mockito.doReturn(Optional.absent()).when(listenableFutureMock).get();
+ final PCEPStatefulPeerProposal peerProposal = PCEPStatefulPeerProposal.createStatefulPeerProposal(dataBroker,
+ TOPOLOGY_IID);
+ peerProposal.setPeerProposal(NODE_ID, tlvsBuilder);
+ assertNull(tlvsBuilder.getAugmentation(Tlvs3.class));
+ }
+
+ @Test
+ public void testSetPeerProposalFailure() throws InterruptedException, ExecutionException {
+ Mockito.doThrow(new RuntimeException()).when(listenableFutureMock).get();
+ final PCEPStatefulPeerProposal peerProposal = PCEPStatefulPeerProposal.createStatefulPeerProposal(dataBroker,
+ TOPOLOGY_IID);
+ peerProposal.setPeerProposal(NODE_ID, tlvsBuilder);
+ assertNull(tlvsBuilder.getAugmentation(Tlvs3.class));
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.bgpcep.pcep.topology.provider;
+
+import static org.opendaylight.protocol.pcep.pcc.mock.MsgBuilderUtil.createLsp;
+import static org.opendaylight.protocol.pcep.pcc.mock.MsgBuilderUtil.createPath;
+
+import com.google.common.base.Optional;
+import java.math.BigInteger;
+import java.util.Collections;
+import java.util.concurrent.ExecutionException;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.protocol.pcep.PCEPSession;
+import org.opendaylight.protocol.pcep.pcc.mock.MsgBuilderUtil;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.pcep.sync.optimizations.rev150714.PathComputationClient1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.pcep.sync.optimizations.rev150714.Tlvs3;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.pcep.sync.optimizations.rev150714.Tlvs3Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.pcep.sync.optimizations.rev150714.lsp.db.version.tlv.LspDbVersion;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.pcep.sync.optimizations.rev150714.lsp.db.version.tlv.LspDbVersionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.Stateful1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.Stateful1Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.OperationalStatus;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.Pcrpt;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.PlspId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.SymbolicPathName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.Tlvs1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.Tlvs1Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.lsp.identifiers.tlv.LspIdentifiersBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.lsp.object.LspBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.srp.object.Srp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.stateful.capability.tlv.StatefulBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.symbolic.path.name.tlv.SymbolicPathNameBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.explicit.route.object.ero.Subobject;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.open.object.Open;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.open.object.OpenBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.open.object.open.TlvsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.rsvp.rev150820.LspId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.Node1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.PccSyncState;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.pcep.client.attributes.PathComputationClient;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
+
+public class StateSynchronizationAvoidanceProcedureTest extends AbstractPCEPSessionTest<Stateful07TopologySessionListenerFactory> {
+
+ private Stateful07TopologySessionListener listener;
+
+ private PCEPSession session;
+
+ @Override
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+ this.listener = (Stateful07TopologySessionListener) getSessionListener();
+ }
+
+ @Test
+ public void testNodePersisted() throws InterruptedException, ExecutionException {
+ this.session = getPCEPSession(getOpen(null), getOpen(null));
+ this.listener.onSessionUp(session);
+ //report LSP + LSP-DB version number
+ final Pcrpt pcRpt = MsgBuilderUtil.createPcRtpMessage(new LspBuilder().setTlvs(
+ new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.lsp.object.lsp.TlvsBuilder()
+ .addAugmentation(org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.pcep.sync.optimizations.rev150714.Tlvs1.class,
+ new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.pcep.sync.optimizations.rev150714.Tlvs1Builder().setLspDbVersion(new LspDbVersionBuilder().setLspDbVersionValue(BigInteger.valueOf(1l)).build()).build()).build()).setPlspId(new PlspId(1L)).setSync(false).setRemove(false).setOperational(OperationalStatus.Active).build(), Optional.of(MsgBuilderUtil.createSrp(1l)), null);
+ this.listener.onMessage(session, pcRpt);
+ //check topology
+ final Topology topo1 = getTopology().get();
+ final LspDbVersion lspDb1 = topo1.getNode().get(0).getAugmentation(Node1.class).getPathComputationClient().getAugmentation(PathComputationClient1.class).getLspDbVersion();
+ Assert.assertEquals(1l, lspDb1.getLspDbVersionValue().longValue());
+ //drop session
+ this.listener.onSessionDown(session, new IllegalStateException());
+ //check topology - node is persisted
+ final Topology topo2 = getTopology().get();
+ Assert.assertFalse(topo2.getNode().isEmpty());
+ }
+
+ @Test
+ public void testStateSynchronizationSkipped() throws InterruptedException, ExecutionException {
+ //session up - sync skipped (LSP-DBs match)
+ final LspDbVersion lspDbVersion = new LspDbVersionBuilder().setLspDbVersionValue(BigInteger.valueOf(1l)).build();
+ this.session = getPCEPSession(getOpen(lspDbVersion), getOpen(lspDbVersion));
+ this.listener.onSessionUp(session);
+ //check node - synchronized
+ final Topology topo = getTopology().get();
+ Assert.assertEquals(PccSyncState.Synchronized, topo.getNode().get(0).getAugmentation(Node1.class).getPathComputationClient().getStateSync());
+ }
+
+ @Test
+ public void testStateSynchronizationPerformed() throws InterruptedException, ExecutionException {
+ this.session = getPCEPSession(getOpen(null), getOpen(null));
+ this.listener.onSessionUp(session);
+ //report LSP + LSP-DB version number
+ final Pcrpt pcRpt = MsgBuilderUtil.createPcRtpMessage(new LspBuilder().setPlspId(new PlspId(1l)).setTlvs(
+ new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.lsp.object.lsp.TlvsBuilder().setLspIdentifiers(new LspIdentifiersBuilder().setLspId(new LspId(1l)).build()).setSymbolicPathName(new SymbolicPathNameBuilder().setPathName(new SymbolicPathName("test".getBytes())).build())
+ .addAugmentation(org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.pcep.sync.optimizations.rev150714.Tlvs1.class,
+ new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.pcep.sync.optimizations.rev150714.Tlvs1Builder().setLspDbVersion(new LspDbVersionBuilder().setLspDbVersionValue(BigInteger.valueOf(1l)).build()).build()).build()).setPlspId(new PlspId(1L)).setSync(true).setRemove(false).setOperational(OperationalStatus.Active).build(), Optional.<Srp>absent(), createPath(Collections.<Subobject> emptyList()));
+ this.listener.onMessage(session, pcRpt);
+ final Topology topo = getTopology().get();
+ final PathComputationClient pcc = topo.getNode().get(0).getAugmentation(Node1.class).getPathComputationClient();
+ Assert.assertFalse(pcc.getReportedLsp().isEmpty());
+ this.listener.onSessionDown(session, new IllegalArgumentException());
+ this.listener = (Stateful07TopologySessionListener) getSessionListener();
+
+ //session up - expect sync (LSP-DBs do not match)
+ final LspDbVersion localDbVersion = new LspDbVersionBuilder().setLspDbVersionValue(BigInteger.valueOf(2l)).build();
+ this.session = getPCEPSession(getOpen(localDbVersion), getOpen(null));
+ this.listener.onSessionUp(session);
+
+ final Topology topo2 = getTopology().get();
+ final PathComputationClient pcc2 = topo2.getNode().get(0).getAugmentation(Node1.class).getPathComputationClient();
+ //check node - not synchronized
+ Assert.assertEquals(PccSyncState.InitialResync, pcc2.getStateSync());
+ //check reported LSP - persisted from previous session
+ Assert.assertFalse(pcc2.getReportedLsp().isEmpty());
+ //sync rpt + LSP-DB
+ final Pcrpt syncMsg = MsgBuilderUtil.createPcRtpMessage(createLsp(0, false, Optional.of(
+ new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.lsp.object.lsp.TlvsBuilder().addAugmentation(org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.pcep.sync.optimizations.rev150714.Tlvs1.class,
+ new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.pcep.sync.optimizations.rev150714.Tlvs1Builder().setLspDbVersion(new LspDbVersionBuilder().setLspDbVersionValue(BigInteger.valueOf(2l)).build()).build()).build()), true, false), Optional.<Srp>absent(),
+ createPath(Collections.<Subobject> emptyList()));
+ this.listener.onMessage(session, syncMsg);
+ final Topology topo3 = getTopology().get();
+ final PathComputationClient pcc3 = topo3.getNode().get(0).getAugmentation(Node1.class).getPathComputationClient();
+ //check node - synchronized
+ Assert.assertEquals(PccSyncState.Synchronized, pcc3.getStateSync());
+ //check reported LSP is empty, LSP state from previous session was purged
+ Assert.assertTrue(pcc3.getReportedLsp().isEmpty());
+ }
+
+ protected Open getOpen(final LspDbVersion dbVersion) {
+ return new OpenBuilder(super.getLocalPref()).setTlvs(new TlvsBuilder().addAugmentation(Tlvs1.class, new Tlvs1Builder().setStateful(new StatefulBuilder()
+ .addAugmentation(Stateful1.class, new Stateful1Builder().setInitiation(Boolean.TRUE).build())
+ .addAugmentation(org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.pcep.sync.optimizations.rev150714.Stateful1.class, new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.pcep.sync.optimizations.rev150714.Stateful1Builder().setIncludeDbVersion(Boolean.TRUE).build())
+ .build()).build()).addAugmentation(Tlvs3.class, new Tlvs3Builder().setLspDbVersion(dbVersion).build()).build()).build();
+ }
+
+}
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.opendaylight.protocol.pcep.pcc.mock.MsgBuilderUtil.createLspTlvs;
+
import com.google.common.base.Optional;
import com.google.common.collect.Lists;
import java.net.UnknownHostException;
import org.junit.Test;
import org.opendaylight.controller.config.yang.pcep.topology.provider.SessionState;
import org.opendaylight.protocol.pcep.PCEPCloseTermination;
+import org.opendaylight.protocol.pcep.PCEPSession;
import org.opendaylight.protocol.pcep.TerminationReason;
import org.opendaylight.protocol.pcep.pcc.mock.MsgBuilderUtil;
import org.opendaylight.protocol.pcep.spi.AbstractMessageParser;
private Stateful07TopologySessionListener listener;
+ private PCEPSession session;
+
@Override
@Before
public void setUp() throws Exception {
super.setUp();
this.listener = (Stateful07TopologySessionListener) getSessionListener();
+ this.session = getPCEPSession(getLocalPref(), getRemotePref());
}
@Test
new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.lsp.object.lsp.TlvsBuilder().setLspIdentifiers(new LspIdentifiersBuilder().setLspId(new LspId(1L)).build()).setSymbolicPathName(
new SymbolicPathNameBuilder().setPathName(new SymbolicPathName(new byte[] { 22, 34 })).build()).build()).build()).build());
final Pcrpt rptmsg = new PcrptBuilder().setPcrptMessage(new PcrptMessageBuilder().setReports(reports).build()).build();
- this.session.sessionUp();
- this.session.handleMessage(rptmsg);
+ this.listener.onSessionUp(this.session);
+ this.listener.onMessage(this.session, rptmsg);
final Topology topology = getTopology().get();
assertFalse(topology.getNode().isEmpty());
}
.build()).build()).build()).build();
}
+ @Override
+ protected Open getRemotePref() {
+ return getLocalPref();
+ }
+
private AddLspInput createAddLspInput() {
final ArgumentsBuilder argsBuilder = new ArgumentsBuilder();
final Ipv4CaseBuilder ipv4Builder = new Ipv4CaseBuilder();
--- /dev/null
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.bgpcep.pcep.topology.provider;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.math.BigInteger;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.opendaylight.protocol.pcep.PCEPSession;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.pcep.sync.optimizations.rev150714.Stateful1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.pcep.sync.optimizations.rev150714.Stateful1Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.pcep.sync.optimizations.rev150714.Tlvs3;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.pcep.sync.optimizations.rev150714.Tlvs3Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.pcep.sync.optimizations.rev150714.lsp.db.version.tlv.LspDbVersionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.Tlvs1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.Tlvs1Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.stateful.capability.tlv.StatefulBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.open.object.open.Tlvs;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.open.object.open.TlvsBuilder;
+
+public class SyncOptimizationTest {
+
+ @Mock
+ private PCEPSession pcepSession;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ }
+
+ @Test
+ public void testDoesLspDbMatchPositive() {
+ final Tlvs tlvs = createTlvs(1l, false);
+ Mockito.doReturn(tlvs).when(pcepSession).localSessionCharacteristics();
+ Mockito.doReturn(tlvs).when(pcepSession).getRemoteTlvs();
+ final SyncOptimization syncOpt = new SyncOptimization(pcepSession);
+ assertTrue(syncOpt.doesLspDbMatch());
+ }
+
+ @Test
+ public void testDoesLspDbMatchNegative() {
+ final Tlvs localTlvs = createTlvs(1l, false);
+ final Tlvs remoteTlvs = createTlvs(2l, false);
+ Mockito.doReturn(localTlvs).when(pcepSession).localSessionCharacteristics();
+ Mockito.doReturn(remoteTlvs).when(pcepSession).getRemoteTlvs();
+ final SyncOptimization syncOpt = new SyncOptimization(pcepSession);
+ assertFalse(syncOpt.doesLspDbMatch());
+ }
+
+ @Test
+ public void testIsSyncAvoidanceEnabledPositive() {
+ final Tlvs tlvs = createTlvs(1l, true);
+ Mockito.doReturn(tlvs).when(pcepSession).localSessionCharacteristics();
+ Mockito.doReturn(tlvs).when(pcepSession).getRemoteTlvs();
+ final SyncOptimization syncOpt = new SyncOptimization(pcepSession);
+ assertTrue(syncOpt.isSyncAvoidanceEnabled());
+ }
+
+ @Test
+ public void testIsSyncAvoidanceEnabledNegative() {
+ final Tlvs localTlvs = createTlvs(1l, true);
+ final Tlvs remoteTlvs = createTlvs(2l, false);
+ Mockito.doReturn(localTlvs).when(pcepSession).localSessionCharacteristics();
+ Mockito.doReturn(remoteTlvs).when(pcepSession).getRemoteTlvs();
+ final SyncOptimization syncOpt = new SyncOptimization(pcepSession);
+ assertFalse(syncOpt.isSyncAvoidanceEnabled());
+ }
+
+ @Test
+ public void testIsDbVersionPresentPositive() {
+ final Tlvs localTlvs = createTlvs(null, false);
+ final Tlvs remoteTlvs = createTlvs(2l, false);
+ Mockito.doReturn(localTlvs).when(pcepSession).localSessionCharacteristics();
+ Mockito.doReturn(remoteTlvs).when(pcepSession).getRemoteTlvs();
+ final SyncOptimization syncOpt = new SyncOptimization(pcepSession);
+ assertTrue(syncOpt.isDbVersionPresent());
+ }
+
+ @Test
+ public void testIsDbVersionPresentNegative() {
+ final Tlvs tlvs = createTlvs(null, true);
+ Mockito.doReturn(tlvs).when(pcepSession).localSessionCharacteristics();
+ Mockito.doReturn(tlvs).when(pcepSession).getRemoteTlvs();
+ final SyncOptimization syncOpt = new SyncOptimization(pcepSession);
+ assertFalse(syncOpt.isDbVersionPresent());
+ }
+
+ private static Tlvs createTlvs(final Long lspDbVersion, final boolean includeDbVresion) {
+ return new TlvsBuilder()
+ .addAugmentation(Tlvs1.class, new Tlvs1Builder().setStateful(
+ new StatefulBuilder().addAugmentation(Stateful1.class,
+ new Stateful1Builder()
+ .setIncludeDbVersion(includeDbVresion).build()).build()).build())
+ .addAugmentation(Tlvs3.class, new Tlvs3Builder().setLspDbVersion(
+ new LspDbVersionBuilder().setLspDbVersionValue(lspDbVersion != null ? BigInteger.valueOf(lspDbVersion) : null).build()).build()).build();
+ }
+
+}
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.opendaylight.bgpcep.pcep.topology.provider.TopologyProgrammingTest.MockedTopologySessionListenerFactory;
import org.opendaylight.bgpcep.programming.spi.Instruction;
import org.opendaylight.bgpcep.programming.spi.InstructionScheduler;
+import org.opendaylight.protocol.pcep.PCEPSession;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.Tlvs1;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.Tlvs1Builder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.stateful.capability.tlv.StatefulBuilder;
private TopologyProgramming topologyProgramming;
+ private PCEPSession session;
+
@Override
@Before
public void setUp() throws Exception {
super.setUp();
- MockitoAnnotations.initMocks(this);
Mockito.doReturn(true).when(this.instruction).checkedExecutionStart();
Mockito.doNothing().when(this.instruction).executionCompleted(InstructionStatus.Failed, null);
Mockito.doAnswer(new Answer<Void>() {
Mockito.doNothing().when(this.instruction).executionCompleted(Mockito.any(InstructionStatus.class), Mockito.any(Details.class));
Mockito.doReturn(this.instructionFuture).when(this.scheduler).scheduleInstruction(Mockito.any(SubmitInstructionInput.class));
this.topologyProgramming = new TopologyProgramming(this.scheduler, this.manager);
+ this.session = getPCEPSession(getLocalPref(), getRemotePref());
listener.onSessionUp(this.session);
}