import org.opendaylight.protocol.pcep.PCEPPeerProposal;
import org.opendaylight.protocol.pcep.PCEPSessionListenerFactory;
-public final class PCEPDispatcherDependenciesImpl implements PCEPDispatcherDependencies {
- private final @NonNull ServerSessionManager manager;
+final class PCEPDispatcherDependenciesImpl implements PCEPDispatcherDependencies {
+ private final @NonNull PCEPSessionListenerFactory listenerFactory;
+ private final @NonNull PCEPPeerProposal peerProposal;
+
private final @NonNull PCEPTopologyConfiguration topologyConfig;
- public PCEPDispatcherDependenciesImpl(final ServerSessionManager manager,
- final PCEPTopologyConfiguration topologyConfig) {
- this.manager = requireNonNull(manager);
+ PCEPDispatcherDependenciesImpl(final PCEPSessionListenerFactory listenerFactory,
+ final PCEPPeerProposal peerProposal, final PCEPTopologyConfiguration topologyConfig) {
+ this.listenerFactory = requireNonNull(listenerFactory);
+ this.peerProposal = requireNonNull(peerProposal);
this.topologyConfig = requireNonNull(topologyConfig);
}
@Override
- public InetSocketAddress getAddress() {
- return topologyConfig.getAddress();
+ public PCEPSessionListenerFactory getListenerFactory() {
+ return listenerFactory;
}
@Override
- public KeyMapping getKeys() {
- return topologyConfig.getKeys();
+ public PCEPPeerProposal getPeerProposal() {
+ return peerProposal;
}
@Override
- public PCEPSessionListenerFactory getListenerFactory() {
- return manager;
+ public InetSocketAddress getAddress() {
+ return topologyConfig.getAddress();
}
@Override
- public PCEPPeerProposal getPeerProposal() {
- return manager;
+ public KeyMapping getKeys() {
+ return topologyConfig.getKeys();
}
}
import static java.util.Objects.requireNonNull;
import com.google.common.util.concurrent.ListenableFuture;
+import java.net.InetSocketAddress;
import java.util.Optional;
import java.util.concurrent.ExecutionException;
import org.opendaylight.mdsal.binding.api.DataBroker;
import org.opendaylight.mdsal.binding.api.ReadTransaction;
import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
+import org.opendaylight.protocol.pcep.PCEPPeerProposal;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.pcep.sync.optimizations.rev200720.PathComputationClient1;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.pcep.sync.optimizations.rev200720.Stateful1;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.pcep.sync.optimizations.rev200720.Tlvs3Builder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.open.object.open.TlvsBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev200120.Node1;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev200120.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.slf4j.Logger;
import org.slf4j.LoggerFactory;
-final class PCEPStatefulPeerProposal {
+final class PCEPStatefulPeerProposal implements PCEPPeerProposal {
private static final Logger LOG = LoggerFactory.getLogger(PCEPStatefulPeerProposal.class);
private final DataBroker dataBroker;
private final InstanceIdentifier<Topology> topologyId;
+ private final SpeakerIdMapping speakerIds;
- PCEPStatefulPeerProposal(final DataBroker dataBroker, final InstanceIdentifier<Topology> topologyId) {
+ PCEPStatefulPeerProposal(final DataBroker dataBroker, final InstanceIdentifier<Topology> topologyId,
+ final SpeakerIdMapping speakerIds) {
this.dataBroker = requireNonNull(dataBroker);
this.topologyId = requireNonNull(topologyId);
+ // FIXME: BGPCEP-989: once we have DTCL, we certainly should be able to maintain this mapping as well
+ this.speakerIds = requireNonNull(speakerIds);
}
- void setPeerProposal(final NodeId nodeId, final TlvsBuilder openTlvsBuilder, final byte[] speakerId) {
- if (isSynOptimizationEnabled(openTlvsBuilder)) {
- Optional<LspDbVersion> result = Optional.empty();
- try (ReadTransaction rTx = dataBroker.newReadOnlyTransaction()) {
- // FIXME: we should be listening for this configuration and keep a proper cache
- final ListenableFuture<Optional<LspDbVersion>> future = rTx.read(LogicalDatastoreType.OPERATIONAL,
- topologyId.child(Node.class, new NodeKey(nodeId)).augmentation(Node1.class)
- .child(PathComputationClient.class).augmentation(PathComputationClient1.class)
- .child(LspDbVersion.class));
- try {
- result = future.get();
- } catch (final InterruptedException | ExecutionException e) {
- LOG.warn("Failed to read toplogy {}.", InstanceIdentifier.keyOf(
- PCEPStatefulPeerProposal.this.topologyId), e);
+ @Override
+ public void setPeerSpecificProposal(final InetSocketAddress address, final TlvsBuilder openBuilder) {
+ // Check if we are dealing with synchronization optimization
+ final var statefulTlv = openBuilder.augmentation(Tlvs1.class);
+ if (statefulTlv == null) {
+ return;
+ }
+ final var stateful = statefulTlv.getStateful();
+ if (stateful == null || stateful.augmentation(Stateful1.class) == null) {
+ return;
+ }
- }
- }
- if (speakerId == null && !result.isPresent()) {
- return;
- }
- final Tlvs3Builder syncBuilder = new Tlvs3Builder();
+ // FIXME: BGPCEP-989: acquire this information via a DTCL and perform a simple lookup only
+ final var addr = address.getAddress();
+ Optional<LspDbVersion> result = Optional.empty();
+
+ try (ReadTransaction rTx = dataBroker.newReadOnlyTransaction()) {
+ // FIXME: we should be listening for this configuration and keep a proper cache
+ final ListenableFuture<Optional<LspDbVersion>> future = rTx.read(LogicalDatastoreType.OPERATIONAL,
+ topologyId.child(Node.class, new NodeKey(ServerSessionManager.createNodeId(addr)))
+ .augmentation(Node1.class).child(PathComputationClient.class)
+ .augmentation(PathComputationClient1.class).child(LspDbVersion.class));
+ try {
+ result = future.get();
+ } catch (final InterruptedException | ExecutionException e) {
+ LOG.warn("Failed to read toplogy {}.", InstanceIdentifier.keyOf(topologyId), e);
- if (result.isPresent()) {
- syncBuilder.setLspDbVersion(result.get());
- }
- if (speakerId != null) {
- syncBuilder.setSpeakerEntityId(new SpeakerEntityIdBuilder().setSpeakerEntityIdValue(speakerId).build());
}
- openTlvsBuilder.addAugmentation(syncBuilder.build()).build();
}
- }
- private static boolean isSynOptimizationEnabled(final TlvsBuilder openTlvsBuilder) {
- final var statefulTlv = openTlvsBuilder.augmentation(Tlvs1.class);
- if (statefulTlv != null) {
- final var stateful = statefulTlv.getStateful();
- if (stateful != null) {
- return stateful.augmentation(Stateful1.class) != null;
- }
+ final var speakerId = speakerIds.speakerIdForAddress(addr);
+ if (speakerId == null && !result.isPresent()) {
+ return;
+ }
+ final Tlvs3Builder syncBuilder = new Tlvs3Builder();
+
+ if (result.isPresent()) {
+ syncBuilder.setLspDbVersion(result.get());
+ }
+ if (speakerId != null) {
+ syncBuilder.setSpeakerEntityId(new SpeakerEntityIdBuilder().setSpeakerEntityIdValue(speakerId).build());
}
- return false;
+ openBuilder.addAugmentation(syncBuilder.build()).build();
}
}
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.MoreExecutors;
import java.net.InetAddress;
-import java.net.InetSocketAddress;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import org.checkerframework.checker.lock.qual.GuardedBy;
+import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.bgpcep.pcep.topology.provider.config.PCEPTopologyConfiguration;
import org.opendaylight.bgpcep.pcep.topology.provider.config.PCEPTopologyProviderDependencies;
import org.opendaylight.bgpcep.pcep.topology.spi.stats.TopologySessionStatsRegistry;
import org.opendaylight.mdsal.common.api.CommitInfo;
import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
import org.opendaylight.protocol.pcep.PCEPDispatcherDependencies;
-import org.opendaylight.protocol.pcep.PCEPPeerProposal;
import org.opendaylight.protocol.pcep.PCEPSession;
import org.opendaylight.protocol.pcep.PCEPSessionListenerFactory;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.stats.rev171113.PcepSessionState;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.open.object.open.TlvsBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev200120.AddLspArgs;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev200120.EnsureLspOperationalInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev200120.OperationResult;
import org.slf4j.LoggerFactory;
// Non-final for testing
-class ServerSessionManager implements PCEPSessionListenerFactory, TopologySessionRPCs, PCEPPeerProposal,
- TopologySessionStatsRegistry {
+class ServerSessionManager implements PCEPSessionListenerFactory, TopologySessionRPCs, TopologySessionStatsRegistry {
private static final Logger LOG = LoggerFactory.getLogger(ServerSessionManager.class);
private static final long DEFAULT_HOLD_STATE_NANOS = TimeUnit.MINUTES.toNanos(5);
@GuardedBy("this")
private final Map<NodeId, TopologyNodeState> state = new HashMap<>();
private final InstanceIdentifier<Topology> topology;
- private final PCEPStatefulPeerProposal peerProposal;
private final short rpcTimeout;
- private final PCEPTopologyProviderDependencies dependenciesProvider;
+ private final PCEPTopologyProviderDependencies dependencies;
private final PCEPDispatcherDependencies pcepDispatcherDependencies;
- private final SpeakerIdMapping speakerIds;
ServerSessionManager(
- final PCEPTopologyProviderDependencies dependenciesProvider,
- final PCEPTopologyConfiguration configDependencies) {
- this.dependenciesProvider = requireNonNull(dependenciesProvider);
- topology = requireNonNull(configDependencies.getTopology());
- peerProposal = new PCEPStatefulPeerProposal(dependenciesProvider.getDataBroker(), topology);
- rpcTimeout = configDependencies.getRpcTimeout();
- speakerIds = configDependencies.getSpeakerIds();
- pcepDispatcherDependencies = new PCEPDispatcherDependenciesImpl(this, configDependencies);
- }
-
- private static NodeId createNodeId(final InetAddress addr) {
- return new NodeId("pcc://" + addr.getHostAddress());
+ final PCEPTopologyProviderDependencies dependencies,
+ final PCEPTopologyConfiguration configuration) {
+ this.dependencies = requireNonNull(dependencies);
+ topology = requireNonNull(configuration.getTopology());
+ rpcTimeout = configuration.getRpcTimeout();
+ pcepDispatcherDependencies = new PCEPDispatcherDependenciesImpl(this,
+ new PCEPStatefulPeerProposal(dependencies.getDataBroker(), topology, configuration.getSpeakerIds()),
+ configuration);
}
/**
final synchronized void instantiateServiceInstance() {
final TopologyKey key = InstanceIdentifier.keyOf(topology);
final TopologyId topologyId = key.getTopologyId();
- final WriteTransaction tx = dependenciesProvider.getDataBroker().newWriteOnlyTransaction();
+ final WriteTransaction tx = dependencies.getDataBroker().newWriteOnlyTransaction();
tx.mergeParentStructurePut(LogicalDatastoreType.OPERATIONAL, topology, new TopologyBuilder()
.withKey(key)
.setTopologyId(topologyId).setTopologyTypes(new TopologyTypesBuilder()
TopologyNodeState ret = state.get(id);
if (ret == null) {
- ret = new TopologyNodeState(dependenciesProvider.getDataBroker(), topology, id, DEFAULT_HOLD_STATE_NANOS);
+ ret = new TopologyNodeState(dependencies.getDataBroker(), topology, id, DEFAULT_HOLD_STATE_NANOS);
LOG.debug("Created topology node {} for id {} at {}", ret, id, ret.getNodeId());
state.put(id, ret);
}
}
state.clear();
- final WriteTransaction t = dependenciesProvider.getDataBroker().newWriteOnlyTransaction();
+ final WriteTransaction t = dependencies.getDataBroker().newWriteOnlyTransaction();
t.delete(LogicalDatastoreType.OPERATIONAL, topology);
final FluentFuture<? extends CommitInfo> future = t.commit();
future.addCallback(new FutureCallback<CommitInfo>() {
return future;
}
- @Override
- public final void setPeerSpecificProposal(final InetSocketAddress address, final TlvsBuilder openBuilder) {
- requireNonNull(address);
- peerProposal.setPeerProposal(createNodeId(address.getAddress()), openBuilder,
- speakerIds.speakerIdForAddress(address.getAddress()));
- }
-
final short getRpcTimeout() {
return rpcTimeout;
}
@Override
public final synchronized void bind(final KeyedInstanceIdentifier<Node, NodeKey> nodeId,
final PcepSessionState sessionState) {
- dependenciesProvider.getStateRegistry().bind(nodeId, sessionState);
+ dependencies.getStateRegistry().bind(nodeId, sessionState);
}
@Override
public final synchronized void unbind(final KeyedInstanceIdentifier<Node, NodeKey> nodeId) {
- dependenciesProvider.getStateRegistry().unbind(nodeId);
+ dependencies.getStateRegistry().unbind(nodeId);
}
final PCEPDispatcherDependencies getPCEPDispatcherDependencies() {
}
final PCEPTopologyProviderDependencies getPCEPTopologyProviderDependencies() {
- return dependenciesProvider;
+ return dependencies;
+ }
+
+ static @NonNull NodeId createNodeId(final InetAddress addr) {
+ return new NodeId("pcc://" + addr.getHostAddress());
}
}
\ No newline at end of file
import static org.mockito.Mockito.doThrow;
import com.google.common.util.concurrent.FluentFuture;
+import java.net.InetSocketAddress;
+import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev200720.stateful.capability.tlv.StatefulBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.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.common.Uint64;
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(Uint64.ONE)
- .build();
+ private static final LspDbVersion LSP_DB_VERSION = new LspDbVersionBuilder()
+ .setLspDbVersionValue(Uint64.ONE)
+ .build();
private static final byte[] SPEAKER_ID = {0x01, 0x02, 0x03, 0x04};
+ private static final InetSocketAddress ADDRESS = new InetSocketAddress(4321);
@Mock
private DataBroker dataBroker;
@Test
public void testSetPeerProposalSuccess() throws InterruptedException, ExecutionException {
doReturn(Optional.of(LSP_DB_VERSION)).when(listenableFutureMock).get();
- final PCEPStatefulPeerProposal peerProposal = new PCEPStatefulPeerProposal(dataBroker, TOPOLOGY_IID);
- peerProposal.setPeerProposal(NODE_ID, tlvsBuilder, null);
+ final PCEPStatefulPeerProposal peerProposal = new PCEPStatefulPeerProposal(dataBroker, TOPOLOGY_IID,
+ SpeakerIdMapping.of());
+ peerProposal.setPeerSpecificProposal(ADDRESS, tlvsBuilder);
assertEquals(LSP_DB_VERSION, tlvsBuilder.augmentation(Tlvs3.class).getLspDbVersion());
}
@Test
public void testSetPeerProposalWithEntityIdSuccess() throws InterruptedException, ExecutionException {
doReturn(Optional.of(LSP_DB_VERSION)).when(listenableFutureMock).get();
- final PCEPStatefulPeerProposal peerProposal = new PCEPStatefulPeerProposal(dataBroker, TOPOLOGY_IID);
- peerProposal.setPeerProposal(NODE_ID, tlvsBuilder, SPEAKER_ID);
+ final PCEPStatefulPeerProposal peerProposal = new PCEPStatefulPeerProposal(dataBroker, TOPOLOGY_IID,
+ SpeakerIdMapping.copyOf(Map.of(ADDRESS.getAddress(), SPEAKER_ID)));
+ peerProposal.setPeerSpecificProposal(ADDRESS, tlvsBuilder);
final Tlvs3 aug = tlvsBuilder.augmentation(Tlvs3.class);
assertEquals(LSP_DB_VERSION, aug.getLspDbVersion());
assertArrayEquals(SPEAKER_ID, aug.getSpeakerEntityId().getSpeakerEntityIdValue());
@Test
public void testSetPeerProposalAbsent() throws InterruptedException, ExecutionException {
doReturn(Optional.empty()).when(listenableFutureMock).get();
- final PCEPStatefulPeerProposal peerProposal = new PCEPStatefulPeerProposal(dataBroker, TOPOLOGY_IID);
- peerProposal.setPeerProposal(NODE_ID, tlvsBuilder, null);
+ final PCEPStatefulPeerProposal peerProposal = new PCEPStatefulPeerProposal(dataBroker, TOPOLOGY_IID,
+ SpeakerIdMapping.of());
+ peerProposal.setPeerSpecificProposal(ADDRESS, tlvsBuilder);
assertNull(tlvsBuilder.augmentation(Tlvs3.class));
}
@Test
public void testSetPeerProposalFailure() throws InterruptedException, ExecutionException {
doThrow(new InterruptedException()).when(listenableFutureMock).get();
- final PCEPStatefulPeerProposal peerProposal = new PCEPStatefulPeerProposal(dataBroker, TOPOLOGY_IID);
- peerProposal.setPeerProposal(NODE_ID, tlvsBuilder, null);
+ final PCEPStatefulPeerProposal peerProposal = new PCEPStatefulPeerProposal(dataBroker, TOPOLOGY_IID,
+ SpeakerIdMapping.of());
+ peerProposal.setPeerSpecificProposal(ADDRESS, tlvsBuilder);
assertNull(tlvsBuilder.augmentation(Tlvs3.class));
}
}