}
}
- grouping endpoints-object {
- description "END-POINTS Object";
- reference "https://tools.ietf.org/html/rfc5440#section-7.6";
-
- uses object;
-
+ grouping endpoints {
choice address-family {
+ mandatory true;
+
case ipv4 {
leaf source-ipv4-address {
type inet:ipv4-address;
}
}
+ grouping endpoints-object {
+ description "END-POINTS Object";
+ reference "https://tools.ietf.org/html/rfc5440#section-7.6";
+
+ uses object;
+ uses endpoints;
+ }
+
grouping bandwidth-object {
description "BANDWIDTH Object";
reference "https://tools.ietf.org/html/rfc5440#section-7.7";
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.message.rev131007.PcerrBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.Message;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.OpenObject;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.endpoints.object.AddressFamily;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.endpoints.object.address.family.Ipv4;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.endpoints.AddressFamily;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.endpoints.address.family.Ipv4;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcerr.message.PcerrMessageBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcerr.message.pcerr.message.ErrorType;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcerr.message.pcerr.message.Errors;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.Object;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.ObjectHeader;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.Tlv;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.endpoints.object.AddressFamily;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.endpoints.object.address.family.Ipv4;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.endpoints.object.address.family.Ipv4Builder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.endpoints.object.address.family.Ipv6;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.endpoints.object.address.family.Ipv6Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.endpoints.AddressFamily;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.endpoints.address.family.Ipv4;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.endpoints.address.family.Ipv4Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.endpoints.address.family.Ipv6;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.endpoints.address.family.Ipv6Builder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcinitiate.message.pcinitiate.message.requests.EndpointsBuilder;
/**
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.RequestId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.SrpIdNumber;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.close.message.c.close.message.CCloseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.endpoints.object.address.family.Ipv4Builder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.endpoints.object.address.family.Ipv6Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.endpoints.address.family.Ipv4Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.endpoints.address.family.Ipv6Builder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.exclude.route.object.Subobjects;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.exclude.route.object.SubobjectsBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.lsp.attributes.ClassTypeBuilder;
<module>impl</module>
<module>spi</module>
<module>testtool</module>
+ <module>topology-api</module>
+ <module>topology-provider</module>
+ <module>tunnel-api</module>
+ <module>tunnel-provider</module>
</modules>
</project>
<parent>
<groupId>org.opendaylight.bgpcep</groupId>
- <artifactId>topology-parent</artifactId>
+ <artifactId>pcep-parent</artifactId>
<version>0.3.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
- <artifactId>topology-pcep-api</artifactId>
- <description>Topology PCEP API</description>
+ <artifactId>pcep-topology-api</artifactId>
+ <description>PCEP Topology API</description>
<packaging>bundle</packaging>
<name>${project.artifactId}</name>
<prerequisites>
<artifactId>topology-api</artifactId>
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>programming-topology-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>yang-binding</artifactId>
<artifactId>yang-common</artifactId>
<version>${yangtools.version}</version>
</dependency>
-
- <dependency>
- <groupId>org.opendaylight.controller.model</groupId>
- <artifactId>model-inventory</artifactId>
- <version>1.0-SNAPSHOT</version>
- </dependency>
</dependencies>
<build>
<instructions>
<Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
<Export-Package>
- org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.pcep.rev131024,
- org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024,
+ org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.*,
</Export-Package>
</instructions>
</configuration>
<distributionManagement>
<site>
<id>${project.artifactId}</id>
- <name>TOPOLOGY-PCEP-API Module site</name>
+ <name>PCEP-TOPOLOGY-API Module site</name>
<url>${basedir}/target/site/${project.artifactId}</url>
</site>
</distributionManagement>
--- /dev/null
+module network-topology-pcep {
+ // vi: set et smarttab sw=4 tabstop=4:
+ yang-version 1;
+ namespace "urn:opendaylight:params:xml:ns:yang:topology:pcep";
+ prefix "pn";
+
+ import network-topology { prefix nt; revision-date 2013-10-21; }
+ import network-topology-programming { prefix ntp; revision-date 2013-11-02; }
+ import pcep-types { prefix pcep; revision-date 2013-10-05; }
+
+ organization "Cisco Systems, Inc.";
+ contact "Robert Varga <rovarga@cisco.com>";
+
+ description
+ "This module contains the PCEP extensions to base topology model. It
+ exposes the LSPs for which a particular node is the head end.
+
+ Copyright (c)2013 Cisco Systems, Inc. All rights reserved.";
+
+ revision "2013-10-24" {
+ description
+ "Initial revision.";
+ reference "";
+ }
+
+ typedef pcc-sync-state {
+ type enumeration {
+ enum initial-resync {
+ description
+ "Initial state resynchronization is being performed.";
+ }
+ enum synchronized {
+ description
+ "State synchronization has been achieved.";
+ }
+ }
+ }
+
+ grouping topology-pcep-type {
+ container topology-pcep {
+ presence "indicates a PCEP-aware topology";
+ }
+ }
+
+ augment "/nt:network-topology/nt:topology/nt:topology-types" {
+ uses topology-pcep-type;
+ }
+
+ grouping pcep-client-attributes {
+ description "Data present in a node which is a PCEP client (PCC).";
+
+ container path-computation-client {
+ description
+ "PCC-related run-time information. This container is only
+ present when the node is connected through PCEP in a PCC
+ role.";
+ config false;
+
+ container stateful-tlv {
+ uses pcep:stateful-capability-tlv;
+ }
+
+ leaf state-sync {
+ when "../stateful-tlv";
+ type pcc-sync-state;
+ }
+
+ list reported-lsps {
+ leaf name {
+ type pcep:symbolic-path-name;
+ }
+ key name;
+
+ // FIXME: hide protocol-specific?
+ uses pcep:lsp-object;
+ }
+
+ list requested-lsps {
+ leaf name {
+ type pcep:symbolic-path-name;
+ }
+ key name;
+
+ // FIXME: hide protocol-specific?
+ uses pcep:lsp-object;
+ }
+ }
+ }
+
+ augment "/nt:network-topology/nt:topology/nt:node" {
+ when "../../nt:topology-types/topology-pcep";
+
+ uses pcep-client-attributes;
+ }
+
+ rpc add-lsp {
+ input {
+ uses ntp:topology-instruction-input;
+
+ leaf node {
+ type nt:node-ref;
+ mandatory true;
+ }
+
+ leaf name {
+ type pcep:symbolic-path-name;
+ mandatory true;
+ }
+
+ // FIXME: hide protocol-specific?
+ uses pcep:lsp-object;
+ }
+ output {
+ uses ntp:topology-instruction-output;
+ }
+ }
+
+ rpc remove-lsp {
+ input {
+ uses ntp:topology-instruction-input;
+
+ leaf node {
+ type nt:node-ref;
+ mandatory true;
+ }
+
+ leaf name {
+ type pcep:symbolic-path-name;
+ mandatory true;
+ }
+ }
+ output {
+ uses ntp:topology-instruction-output;
+ }
+ }
+
+ rpc update-lsp {
+ input {
+ uses ntp:topology-instruction-input;
+
+ leaf node {
+ type nt:node-ref;
+ mandatory true;
+ }
+
+ leaf name {
+ type pcep:symbolic-path-name;
+ mandatory true;
+ }
+
+ // FIXME: hide protocol-specific?
+ uses pcep:lsp-object;
+ }
+ output {
+ uses ntp:topology-instruction-output;
+ }
+ }
+}
+
<parent>
<groupId>org.opendaylight.bgpcep</groupId>
- <artifactId>topology-parent</artifactId>
+ <artifactId>pcep-parent</artifactId>
<version>0.3.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
- <artifactId>topology-tunnel-provider-pcep</artifactId>
+ <artifactId>pcep-topology-provider</artifactId>
<description>PCEP Topology Provider</description>
<packaging>bundle</packaging>
<name>${project.artifactId}</name>
</prerequisites>
<dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>pcep-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>topology-api</artifactId>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
- <artifactId>topology-pcep-api</artifactId>
+ <artifactId>programming-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
- <artifactId>topology-tunnel-api</artifactId>
+ <artifactId>programming-spi</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
- <artifactId>topology-tunnel-pcep-api</artifactId>
+ <artifactId>pcep-topology-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
+
+ <!-- FIXME: integrate with config to get rid of this -->
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>pcep-impl</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>pcep-spi</artifactId>
+ <version>${project.version}</version>
+ </dependency>
</dependencies>
<build>
<instructions>
<Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
<Private-Package>
- org.opendaylight.bgpcep.topology.tunnel.provider.pcep
+ org.opendaylight.bgpcep.pcep.topology.provider
</Private-Package>
- <Bundle-Activator>org.opendaylight.bgpcep.topology.tunnel.provider.pcep.BundleActivator</Bundle-Activator>
+ <Bundle-Activator>org.opendaylight.bgpcep.pcep.topology.provider.BundleActivator</Bundle-Activator>
</instructions>
</configuration>
</plugin>
<distributionManagement>
<site>
<id>${project.artifactId}</id>
- <name>TOPOLOGY-PROVIDER-PCEP Module site</name>
+ <name>PCEP-TOPOLOGY-PROVIDER Module site</name>
<url>${basedir}/target/site/${project.artifactId}</url>
</site>
</distributionManagement>
* 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.topology.provider.pcep;
+package org.opendaylight.bgpcep.pcep.topology.provider;
import io.netty.channel.ChannelFuture;
import io.netty.util.HashedWheelTimer;
new DefaultPCEPSessionNegotiatorFactory(new HashedWheelTimer(), prefs, 5));
final InstanceIdentifier<Topology> topology = InstanceIdentifier.builder().node(Topology.class).toInstance();
- final TopologyExporter exp = new TopologyExporter(dispatcher, dps, topology);
+ final PCEPTopologyProvider exp = new PCEPTopologyProvider(dispatcher, null, dps, topology);
final ChannelFuture s = exp.startServer(address);
try {
s.get();
* 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.topology.provider.pcep;
+package org.opendaylight.bgpcep.pcep.topology.provider;
import io.netty.channel.ChannelFuture;
import java.net.InetSocketAddress;
+import org.opendaylight.bgpcep.programming.spi.InstructionScheduler;
import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
import org.opendaylight.protocol.pcep.PCEPDispatcher;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import com.google.common.base.Preconditions;
-public final class TopologyExporter {
- private static final InstanceIdentifier<Nodes> inventory = new InstanceIdentifier<Nodes>(Nodes.class);
+public final class PCEPTopologyProvider {
private final PCEPDispatcher dispatcher;
private final DataProviderService dataProvider;
private final InstanceIdentifier<Topology> topology;
+ private final InstructionScheduler scheduler;
- public TopologyExporter(final PCEPDispatcher dispatcher,
+ public PCEPTopologyProvider(final PCEPDispatcher dispatcher,
+ final InstructionScheduler scheduler,
final DataProviderService dataService,
final InstanceIdentifier<Topology> topology) {
this.dispatcher = Preconditions.checkNotNull(dispatcher);
this.dataProvider = Preconditions.checkNotNull(dataService);
this.topology = Preconditions.checkNotNull(topology);
+ this.scheduler = Preconditions.checkNotNull(scheduler);
}
public ChannelFuture startServer(final InetSocketAddress address) {
- return dispatcher.createServer(address, new ServerSessionManager(dataProvider, inventory, topology));
+ return dispatcher.createServer(address, new ServerSessionManager(scheduler, dataProvider, topology));
}
}
--- /dev/null
+/*
+ * Copyright (c) 2013 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 io.netty.util.concurrent.EventExecutor;
+import io.netty.util.concurrent.GlobalEventExecutor;
+
+import java.net.InetAddress;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+import org.opendaylight.bgpcep.programming.spi.ExecutionResult;
+import org.opendaylight.bgpcep.programming.spi.InstructionExecutor;
+import org.opendaylight.bgpcep.programming.spi.InstructionScheduler;
+import org.opendaylight.bgpcep.programming.spi.SuccessfulRpcResult;
+import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
+import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
+import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
+import org.opendaylight.protocol.framework.SessionListenerFactory;
+import org.opendaylight.protocol.pcep.PCEPSession;
+import org.opendaylight.protocol.pcep.PCEPSessionListener;
+import org.opendaylight.protocol.pcep.PCEPTerminationReason;
+import org.opendaylight.protocol.pcep.TerminationReason;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.message.rev131007.Pcerr;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.message.rev131007.PcerrBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.Message;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.PcrptMessage;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.PlspId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.open.object.Tlvs;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcerr.message.PcerrMessageBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcrpt.message.pcrpt.message.Reports;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcrpt.message.pcrpt.message.reports.Lsp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.stateful.capability.tlv.Stateful;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.symbolic.path.name.tlv.SymbolicPathName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.submit.instruction.output.result.FailureBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.submit.instruction.output.result.failure.Failure;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.AddLspInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.AddLspOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.AddLspOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.NetworkTopologyPcepService;
+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.Node1Builder;
+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.RemoveLspInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.RemoveLspOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.RemoveLspOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.UpdateLspInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.UpdateLspOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.UpdateLspOutputBuilder;
+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.ReportedLsps;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.pcep.client.attributes.path.computation.client.ReportedLspsKey;
+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.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.NodeBuilder;
+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.opendaylight.yangtools.yang.common.RpcResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Preconditions;
+
+/**
+ *
+ */
+final class ServerSessionManager implements SessionListenerFactory<PCEPSessionListener>, NetworkTopologyPcepService {
+ private static String createNodeId(final InetAddress addr) {
+ return "pcc://" + addr.getHostAddress();
+ }
+
+ private final class SessionListener implements PCEPSessionListener {
+ private final Map<PlspId, SymbolicPathName> lsps = new HashMap<>();
+ private PathComputationClientBuilder pccBuilder;
+ private boolean synced = false;
+
+ private boolean ownsTopology = false;
+ private InstanceIdentifier<Node> topologyNodeId;
+ private InstanceIdentifier<Node1> topologyAugmentId;
+ private Node1Builder topologyAugmentBuilder;
+
+ final Node topologyNode(final DataModificationTransaction trans, final InetAddress address) {
+ final String pccId = createNodeId(address);
+
+ // FIXME: after 0.6 yangtools, this cast should not be needed
+ final Topology topo = (Topology)trans.readOperationalData(topology);
+
+ for (final Node n : topo.getNode()) {
+ LOG.debug("Matching topology node {} to id {}", n, pccId);
+ if (n.getNodeId().getValue().equals(pccId)) {
+ return n;
+ }
+ }
+
+ /*
+ * We failed to find a matching node. Let's create a dynamic one
+ * and note that we are the owner (so we clean it up afterwards).
+ */
+ final NodeId id = new NodeId(pccId);
+ final NodeKey nk = new NodeKey(id);
+ final InstanceIdentifier<Node> nti = InstanceIdentifier.builder(topology).node(Node.class, nk).toInstance();
+
+ final Node ret = new NodeBuilder().setKey(nk).setNodeId(id).build();
+
+ trans.putRuntimeData(nti, ret);
+ this.ownsTopology = true;
+ this.topologyNodeId = nti;
+ return ret;
+ }
+
+ @Override
+ public void onSessionUp(final PCEPSession session) {
+ /*
+ * The session went up. Look up the router in Inventory model,
+ * create it if it is not there (marking that fact for later
+ * deletion), and mark it as synchronizing. Also create it in
+ * the topology model, with empty LSP list.
+ */
+ final InetAddress peerAddress = session.getRemoteAddress();
+ final DataModificationTransaction trans = ServerSessionManager.this.dataProvider.beginTransaction();
+
+ final Node topoNode = topologyNode(trans, peerAddress);
+ LOG.debug("Peer {} resolved to topology node {}", peerAddress, topoNode);
+
+ // Our augmentation in the topology node
+ pccBuilder = new PathComputationClientBuilder();
+
+ final Tlvs tlvs = session.getRemoteTlvs();
+ final Stateful stateful = tlvs.getStateful();
+ if (stateful != null) {
+ // FIXME: rework once groupings can be used in builders
+ this.pccBuilder.setStatefulTlv(new StatefulTlvBuilder().setStateful(stateful).build());
+ this.pccBuilder.setStateSync(PccSyncState.InitialResync);
+ }
+
+ topologyAugmentBuilder = new Node1Builder().setPathComputationClient(pccBuilder.build());
+ topologyAugmentId = InstanceIdentifier.builder(topologyNodeId).node(Node1.class).toInstance();
+ trans.putRuntimeData(topologyAugmentId, topologyAugmentBuilder.build());
+
+ // All set, commit the modifications
+ final Future<RpcResult<TransactionStatus>> s = trans.commit();
+
+ /*
+ * FIXME: once this Future is listenable, attach to it so we can
+ * do cleanup if the commit fails. For now we force a commit.
+ */
+ try {
+ s.get();
+ } catch (InterruptedException | ExecutionException e) {
+ LOG.error("Failed to update internal state for session {}, terminating it", session, e);
+ session.close(TerminationReason.Unknown);
+ }
+
+ LOG.info("Session with {} attached to topology node {}", session.getRemoteAddress(), topoNode.getNodeId());
+ }
+
+ private void tearDown(final PCEPSession session) {
+ final DataModificationTransaction trans = ServerSessionManager.this.dataProvider.beginTransaction();
+
+ // The session went down. Undo all the Topology changes we have done.
+ trans.removeRuntimeData(topologyAugmentId);
+ if (ownsTopology) {
+ trans.removeRuntimeData(topologyNodeId);
+ }
+
+ /*
+ * FIXME: once this Future is listenable, attach to it so we can
+ * do cleanup if the commit fails. For now we force a commit.
+ */
+ final Future<RpcResult<TransactionStatus>> s = trans.commit();
+ try {
+ s.get();
+ } catch (InterruptedException | ExecutionException e) {
+ LOG.error("Failed to cleanup internal state for session {}", session, e);
+ }
+ }
+
+ @Override
+ public void onSessionDown(final PCEPSession session, final Exception e) {
+ LOG.warn("Session {} went down unexpectedly", e);
+ tearDown(session);
+ }
+
+ @Override
+ public void onSessionTerminated(final PCEPSession session, final PCEPTerminationReason reason) {
+ LOG.info("Session {} terminated by peer with reason {}", session, reason);
+ tearDown(session);
+ }
+
+ private InstanceIdentifier<ReportedLsps> lspIdentifier(final SymbolicPathName name) {
+ return InstanceIdentifier.builder(topologyAugmentId).
+ node(ReportedLsps.class, new ReportedLspsKey(name.getPathName())).toInstance();
+ }
+
+ @Override
+ public void onMessage(final PCEPSession session, final Message message) {
+ if (!(message instanceof PcrptMessage)) {
+ LOG.info("Unhandled message {} on session {}", message, session);
+ session.sendMessage(unhandledMessageError);
+ }
+
+ final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcrpt.message.PcrptMessage rpt = ((PcrptMessage) message).getPcrptMessage();
+
+ final DataModificationTransaction trans = ServerSessionManager.this.dataProvider.beginTransaction();
+
+ for (final Reports r : rpt.getReports()) {
+ final Lsp lsp = r.getLsp();
+
+ if (lsp.isSync() && !this.synced) {
+ // Update synchronization flag
+ synced = true;
+ topologyAugmentBuilder.setPathComputationClient(pccBuilder.setStateSync(PccSyncState.Synchronized).build());
+ trans.putRuntimeData(topologyAugmentId, topologyAugmentBuilder.build());
+ LOG.debug("Session {} achieved synchronized state", session);
+ }
+
+ final PlspId id = lsp.getPlspId();
+ if (lsp.isRemove()) {
+ final SymbolicPathName name = this.lsps.remove(id);
+ if (name != null) {
+ trans.removeRuntimeData(lspIdentifier(name));
+ }
+
+ LOG.debug("LSP {} removed", lsp);
+ } else {
+ if (!this.lsps.containsKey(id)) {
+ LOG.debug("PLSPID {} not known yet, looking for a symbolic name", id);
+
+ final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.lsp.object.Tlvs tlvs = r.getLsp().getTlvs();
+ final SymbolicPathName name = tlvs.getSymbolicPathName();
+ if (name == null) {
+ LOG.error("PLSPID {} seen for the first time, not reporting the LSP");
+ // TODO: what should we do here?
+ continue;
+ }
+ }
+
+ final SymbolicPathName name = this.lsps.get(id);
+ trans.putRuntimeData(lspIdentifier(name), lsp);
+
+ LOG.debug("LSP {} updated");
+ }
+ }
+
+ /*
+ * FIXME: once this Future is listenable, attach to it so we can
+ * do cleanup if the commit fails. For now we force a commit.
+ */
+ final Future<RpcResult<TransactionStatus>> s = trans.commit();
+ try {
+ s.get();
+ } catch (InterruptedException | ExecutionException e) {
+ LOG.error("Failed to update internal state for session {}, closing it", session, e);
+ session.close(TerminationReason.Unknown);
+ }
+ }
+ }
+
+ private static final Logger LOG = LoggerFactory.getLogger(ServerSessionManager.class);
+ private static final Pcerr unhandledMessageError = new PcerrBuilder().setPcerrMessage(
+ new PcerrMessageBuilder().setErrorType(null).build()).build();
+ private static final EventExecutor exec = GlobalEventExecutor.INSTANCE;
+ private final InstanceIdentifier<Topology> topology;
+ private final DataProviderService dataProvider;
+ private final InstructionScheduler scheduler;
+
+ public ServerSessionManager(final InstructionScheduler scheduler,
+ final DataProviderService dataProvider, final InstanceIdentifier<Topology> topology) {
+ this.dataProvider = Preconditions.checkNotNull(dataProvider);
+ this.topology = Preconditions.checkNotNull(topology);
+ this.scheduler = Preconditions.checkNotNull(scheduler);
+ }
+
+ @Override
+ public PCEPSessionListener getSessionListener() {
+ return new SessionListener();
+ }
+
+ private synchronized io.netty.util.concurrent.Future<ExecutionResult<?>> realAddLsp(final AddLspInput input) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ private synchronized io.netty.util.concurrent.Future<ExecutionResult<?>> realRemoveLsp(final RemoveLspInput input) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ private synchronized io.netty.util.concurrent.Future<ExecutionResult<?>> realUpdateLsp(final UpdateLspInput input) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public Future<RpcResult<AddLspOutput>> addLsp(final AddLspInput input) {
+ final InstructionExecutor e = new InstructionExecutor() {
+ @Override
+ public io.netty.util.concurrent.Future<ExecutionResult<?>> execute() {
+ return realAddLsp(input);
+ }
+ };
+
+ final Failure f = scheduler.submitInstruction(input, e);
+ final AddLspOutputBuilder b = new AddLspOutputBuilder();
+ if (f != null) {
+ b.setResult(new FailureBuilder().setFailure(f).build());
+ }
+
+ final RpcResult<AddLspOutput> res = SuccessfulRpcResult.create(b.build());
+ return exec.newSucceededFuture(res);
+ }
+
+ @Override
+ public Future<RpcResult<RemoveLspOutput>> removeLsp(final RemoveLspInput input) {
+ final InstructionExecutor e = new InstructionExecutor() {
+ @Override
+ public io.netty.util.concurrent.Future<ExecutionResult<?>> execute() {
+ return realRemoveLsp(input);
+ }
+ };
+
+ final Failure f = scheduler.submitInstruction(input, e);
+ final RemoveLspOutputBuilder b = new RemoveLspOutputBuilder();
+ if (f != null) {
+ b.setResult(new FailureBuilder().setFailure(f).build());
+ }
+
+ final RpcResult<RemoveLspOutput> res = SuccessfulRpcResult.create(b.build());
+ return exec.newSucceededFuture(res);
+ }
+
+ @Override
+ public Future<RpcResult<UpdateLspOutput>> updateLsp(final UpdateLspInput input) {
+ final InstructionExecutor e = new InstructionExecutor() {
+ @Override
+ public io.netty.util.concurrent.Future<ExecutionResult<?>> execute() {
+ return realUpdateLsp(input);
+ }
+ };
+
+ final Failure f = scheduler.submitInstruction(input, e);
+ final UpdateLspOutputBuilder b = new UpdateLspOutputBuilder();
+ if (f != null) {
+ b.setResult(new FailureBuilder().setFailure(f).build());
+ }
+
+ final RpcResult<UpdateLspOutput> res = SuccessfulRpcResult.create(b.build());
+ return exec.newSucceededFuture(res);
+ }
+}
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
- <name>topology-tunnel-pcep</name>
+ <name>programming-tunnel-pcep-api</name>
<comment></comment>
<projects>
</projects>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <parent>
+ <groupId>org.opendaylight.bgpcep</groupId>
+ <artifactId>pcep-parent</artifactId>
+ <version>0.3.0-SNAPSHOT</version>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>pcep-tunnel-api</artifactId>
+ <description>Tunnel API for PCEP</description>
+ <packaging>bundle</packaging>
+ <name>${project.artifactId}</name>
+ <prerequisites>
+ <maven>3.0.4</maven>
+ </prerequisites>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>programming-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>programming-tunnel-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>topology-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>topology-tunnel-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>pcep-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-binding</artifactId>
+ <version>${yang.binding.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-common</artifactId>
+ <version>${yangtools.version}</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-maven-plugin</artifactId>
+ <version>${yangtools.version}</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>generate-sources</goal>
+ </goals>
+ <configuration>
+ <yangFilesRootDir>src/main/yang</yangFilesRootDir>
+ <codeGenerators>
+ <generator>
+ <codeGeneratorClass>
+ org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl
+ </codeGeneratorClass>
+ <outputBaseDir>
+ target/generated-sources/sal
+ </outputBaseDir>
+ </generator>
+ </codeGenerators>
+ <inspectDependencies>true</inspectDependencies>
+ </configuration>
+ </execution>
+ </executions>
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>maven-sal-api-gen-plugin</artifactId>
+ <version>${yang.binding.version}</version>
+ <type>jar</type>
+ </dependency>
+ </dependencies>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <version>${maven.bundle.version}</version>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
+ <Export-Package>
+ org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.tunnel.programming.rev130930.*,
+ </Export-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <distributionManagement>
+ <site>
+ <id>${project.artifactId}</id>
+ <name>PROGRAMMING-TUNNEL-PCEP-API Module site</name>
+ <url>${basedir}/target/site/${project.artifactId}</url>
+ </site>
+ </distributionManagement>
+
+</project>
--- /dev/null
+module topology-tunnel-pcep-programming {
+ yang-version 1;
+ namespace "urn:opendaylight:params:xml:ns:yang:topology:tunnel:pcep:programming";
+ prefix "ttpp";
+
+ import network-topology { prefix nt; revision-date 2013-10-21; }
+ import pcep-types { prefix pcep; revision-date 2013-10-05; }
+ import programming { prefix pgm; revision-date 2013-09-30; }
+ import topology-tunnel { prefix tt; revision-date 2013-08-19; }
+ import topology-tunnel-programming { prefix ttp; revision-date 2013-09-30; }
+
+ organization "Cisco Systems, Inc.";
+ contact "Robert Varga <rovarga@cisco.com>";
+
+ description
+ "This module contains the programming extensions for tunnel
+ topologies.
+
+ Copyright (c)2013 Cisco Systems, Inc. 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";
+
+ revision "2013-10-30" {
+ description
+ "Initial revision.";
+ reference "";
+ }
+
+ rpc pcep-create-tunnel {
+ input {
+ uses ttp:create-tunnel-input;
+
+ leaf symbolic-path-name {
+ type pcep:symbolic-path-name;
+ mandatory true;
+ }
+
+ container endpoints {
+ uses pcep:endpoints;
+ }
+
+ leaf signaling-type {
+ // FIXME: dedicated type in PCEP
+ type uint8;
+ default 0;
+ }
+
+ leaf administrative {
+ type boolean;
+ default true;
+ }
+
+ // FIXME: ERO
+ // FIXME: attribute-list
+ }
+ output {
+ uses ttp:create-tunnel-output;
+ }
+ }
+
+ rpc pcep-destroy-tunnel {
+ input {
+ uses ttp:destroy-tunnel-input;
+ }
+ output {
+ uses ttp:destroy-tunnel-output;
+ }
+ }
+
+ rpc pcep-update-tunnel {
+ input {
+ container update-tunnel {
+ leaf topology-id {
+ type nt:topology-id;
+ mandatory true;
+ }
+ leaf link-id {
+ type nt:link-id;
+ mandatory true;
+ }
+
+ // FIXME: all that PCUpd jazz
+ }
+ }
+
+ output {
+ uses pgm:submit-instruction-output;
+ }
+ }
+}
+
<parent>
<groupId>org.opendaylight.bgpcep</groupId>
- <artifactId>topology-parent</artifactId>
+ <artifactId>pcep-parent</artifactId>
<version>0.3.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
- <artifactId>topology-provider-pcep</artifactId>
- <description>PCEP Topology Provider</description>
+ <artifactId>pcep-tunnel-provider</artifactId>
+ <description>PCEP Tunnel Topology Provider</description>
<packaging>bundle</packaging>
<name>${project.artifactId}</name>
<prerequisites>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
- <artifactId>pcep-api</artifactId>
+ <artifactId>programming-spi</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
- <artifactId>topology-pcep-api</artifactId>
+ <artifactId>topology-tunnel-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>pcep-topology-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>pcep-tunnel-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
-
- <!-- FIXME: integrate with config to get rid of this -->
- <dependency>
- <groupId>${project.groupId}</groupId>
- <artifactId>pcep-impl</artifactId>
- <version>${project.version}</version>
- </dependency>
- <dependency>
- <groupId>${project.groupId}</groupId>
- <artifactId>pcep-spi</artifactId>
- <version>${project.version}</version>
- </dependency>
</dependencies>
<build>
<instructions>
<Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
<Private-Package>
- org.opendaylight.bgpcep.topology.provider.pcep
+ org.opendaylight.bgpcep.pcep.tunnel.provider
</Private-Package>
- <Bundle-Activator>org.opendaylight.bgpcep.topology.provider.pcep.BundleActivator</Bundle-Activator>
+ <Bundle-Activator>org.opendaylight.bgpcep.pcep.tunnel.provider.BundleActivator</Bundle-Activator>
</instructions>
</configuration>
</plugin>
<distributionManagement>
<site>
<id>${project.artifactId}</id>
- <name>TOPOLOGY-PROVIDER-PCEP Module site</name>
+ <name>PCEP-TUNNEL-PROVIDER Module site</name>
<url>${basedir}/target/site/${project.artifactId}</url>
</site>
</distributionManagement>
-package org.opendaylight.bgpcep.topology.tunnel.provider.pcep;
+package org.opendaylight.bgpcep.pcep.tunnel.provider;
import org.opendaylight.controller.sal.binding.api.AbstractBindingAwareProvider;
import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
* 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.topology.tunnel.provider.pcep;
+package org.opendaylight.bgpcep.pcep.tunnel.provider;
import java.util.Map.Entry;
import java.util.concurrent.ExecutionException;
import org.opendaylight.controller.sal.binding.api.data.DataChangeListener;
import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.pcep.client.attributes.pcc.Lsps;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.pcep.client.attributes.path.computation.client.ReportedLsps;
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.yangtools.yang.binding.DataObject;
private void remove(final DataModificationTransaction trans, final InstanceIdentifier<?> id) {
if (Node.class.equals(id.getTargetType())) {
// FIXME: implement this
- } else if (Lsps.class.equals(id.getTargetType())) {
+ } else if (ReportedLsps.class.equals(id.getTargetType())) {
// FIXME: implement this
} else {
LOG.debug("Ignoring changed instance {}", id);
--- /dev/null
+/*
+ * Copyright (c) 2013 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.tunnel.provider;
+
+import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.topology.pcep.type.TopologyPcep;
+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.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.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.TopologyTypes;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Preconditions;
+
+public final class PCEPTunnelInstructionExecutor {
+ private static final Logger LOG = LoggerFactory.getLogger(PCEPTunnelInstructionExecutor.class);
+ private final InstanceIdentifier<Topology> underlay;
+ private final InstanceIdentifier<Topology> target;
+ private final DataProviderService dps;
+
+ private PCEPTunnelInstructionExecutor(final DataProviderService dps, final InstanceIdentifier<Topology> underlay,
+ final InstanceIdentifier<Topology> target, final TopologyId topologyId) {
+ this.dps = Preconditions.checkNotNull(dps);
+ this.underlay = Preconditions.checkNotNull(underlay);
+ this.target = Preconditions.checkNotNull(target);
+ }
+
+ public static PCEPTunnelInstructionExecutor create(final DataProviderService dps, final InstanceIdentifier<Topology> underlay,
+ final TopologyId targetId) {
+ Preconditions.checkNotNull(dps);
+ Preconditions.checkNotNull(targetId);
+
+ // Topology pointer
+ final InstanceIdentifier<Topology> target = InstanceIdentifier.builder().node(NetworkTopology.class).
+ node(Topology.class, new TopologyKey(targetId)).toInstance();
+
+ // Now check if there is a container identifying the topology as PCEP-aware
+ final InstanceIdentifier<TopologyPcep> i = InstanceIdentifier.builder(target).node(TopologyTypes.class).node(TopologyPcep.class).toInstance();
+ final DataObject ttt = dps.readOperationalData(i);
+ Preconditions.checkArgument(ttt != null, "Specified topology does not list topology-pcep as its type");
+
+ return new PCEPTunnelInstructionExecutor(dps, underlay, target, targetId);
+ }
+}
* 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.topology.tunnel.provider.pcep;
+package org.opendaylight.bgpcep.pcep.tunnel.provider;
import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
base submit-failure;
}
- identity instruction-type {
- description
- "Base intruction type. This identity should be
- extended for each individual instruction defined.";
- }
-
- rpc submit-instruction {
- input {
- leaf id {
- type instruction-id;
- mandatory true;
- }
-
- leaf type {
- type identityref {
- base instruction-type;
- }
- mandatory true;
- }
-
- leaf deadline {
- type nanotime;
- mandatory true;
- }
-
- leaf-list preconditions {
- type instruction-id;
- }
+ grouping submit-instruction-input {
+ leaf id {
+ type instruction-id;
+ mandatory true;
+ }
- choice arguments {
+ leaf deadline {
+ type nanotime;
+ mandatory true;
+ }
- }
+ leaf-list preconditions {
+ type instruction-id;
}
+ }
- output {
- choice result {
- case failure {
- container failure {
- leaf type {
- type identityref {
- base submit-failure;
- }
- mandatory true;
+ grouping submit-instruction-output {
+ choice result {
+ case failure {
+ container failure {
+ leaf type {
+ type identityref {
+ base submit-failure;
}
+ mandatory true;
+ }
- leaf-list failed-preconditions {
- when "../type = dead-on-arrival";
- type instruction-id;
- }
+ leaf-list failed-preconditions {
+ when "../type = dead-on-arrival";
+ type instruction-id;
}
}
}
package org.opendaylight.bgpcep.programming.impl;
import io.netty.util.Timeout;
+import io.netty.util.concurrent.Future;
import java.util.ArrayList;
import java.util.List;
+import org.opendaylight.bgpcep.programming.spi.ExecutionResult;
+import org.opendaylight.bgpcep.programming.spi.InstructionExecutor;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.InstructionId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.InstructionStatus;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.SubmitInstructionInput;
import com.google.common.base.Preconditions;
final class Instruction {
private final List<Instruction> dependants = new ArrayList<>();
+ private final InstructionExecutor executor;
private final List<Instruction> dependencies;
- private final SubmitInstructionInput input;
+ private final InstructionId id;
private volatile InstructionStatus status = InstructionStatus.Queued;
private Timeout timeout;
- Instruction(final SubmitInstructionInput input, final List<Instruction> dependencies, final Timeout timeout) {
- this.input = Preconditions.checkNotNull(input);
+ Instruction(final InstructionId id, final InstructionExecutor executor, final List<Instruction> dependencies, final Timeout timeout) {
+ this.id = Preconditions.checkNotNull(id);
+ this.executor = Preconditions.checkNotNull(executor);
this.dependencies = Preconditions.checkNotNull(dependencies);
this.timeout = Preconditions.checkNotNull(timeout);
}
- SubmitInstructionInput getInput() {
- return input;
+ InstructionId getId() {
+ return id;
}
InstructionStatus getStatus() {
return status;
}
+ Future<ExecutionResult<?>> execute() {
+ return executor.execute();
+ }
+
void setStatus(final InstructionStatus status) {
this.status = status;
}
import java.math.BigInteger;
import java.util.ArrayDeque;
import java.util.ArrayList;
-import java.util.Collection;
import java.util.Deque;
import java.util.HashMap;
-import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import org.opendaylight.bgpcep.programming.spi.ExecutionResult;
import org.opendaylight.bgpcep.programming.spi.InstructionExecutor;
-import org.opendaylight.bgpcep.programming.spi.InstructionExecutorRegistry;
+import org.opendaylight.bgpcep.programming.spi.InstructionScheduler;
+import org.opendaylight.bgpcep.programming.spi.SuccessfulRpcResult;
import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.CancelInstructionInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.CancelInstructionOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.InstructionId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.InstructionStatus;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.InstructionStatusChangedBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.InstructionType;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.ProgrammingService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.SubmitInstructionInput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.SubmitInstructionOutput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.SubmitInstructionOutputBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.UncancellableInstruction;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.UnknownInstruction;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.UnknownPreconditionId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.instruction.status.changed.DetailsBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.submit.instruction.output.result.failure.Failure;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.submit.instruction.output.result.failure.FailureBuilder;
-import org.opendaylight.yangtools.concepts.Registration;
import org.opendaylight.yangtools.yang.common.RpcResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.base.Preconditions;
-import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Multimap;
-final class ProgrammingServiceImpl implements InstructionExecutorRegistry, ProgrammingService {
+final class ProgrammingServiceImpl implements InstructionScheduler, ProgrammingService {
private static final Logger LOG = LoggerFactory.getLogger(ProgrammingServiceImpl.class);
private static final BigInteger MILLION = BigInteger.valueOf(1000000);
@GuardedBy("this")
private final Deque<Instruction> readyQueue = new ArrayDeque<>();
- @GuardedBy("this")
- private final Deque<Instruction> deferredQueue = new ArrayDeque<>();
-
- @GuardedBy("this")
- private final Multimap<Class<? extends InstructionType>, InstructionExecutor> executors = ArrayListMultimap.create();
-
private final NotificationProviderService notifs;
private final ExecutorService executor;
private final Timer timer;
private ExecutorService exec;
ProgrammingServiceImpl(final NotificationProviderService notifs, final ExecutorService executor,
- final Timer timer, final InstructionExecutorRegistry registry) {
+ final Timer timer, final InstructionScheduler registry) {
this.notifs = Preconditions.checkNotNull(notifs);
this.executor = Preconditions.checkNotNull(executor);
this.timer = Preconditions.checkNotNull(timer);
});
}
- @Override
- public java.util.concurrent.Future<RpcResult<SubmitInstructionOutput>> submitInstruction(final SubmitInstructionInput input) {
- return executor.submit(new Callable<RpcResult<SubmitInstructionOutput>>() {
- @Override
- public RpcResult<SubmitInstructionOutput> call() {
- return realSubmitInstruction(input);
- }
- });
- }
-
- @Override
- public synchronized Registration<InstructionExecutor> registerInstructionExecutor(final Class<? extends InstructionType> type, final InstructionExecutor executor) {
- Preconditions.checkNotNull(type);
- Preconditions.checkNotNull(executor);
-
- executors.put(type, executor);
-
- /*
- * Walk the deferred instructions back to front, check if they have
- * the same type as the executor we have just registered. If they do,
- * we move them to the head of readyQueue. This approach should retain
- * submission order of the instructions.
- */
- final Iterator<Instruction> it = deferredQueue.descendingIterator();
- while (it.hasNext()) {
- final Instruction i = it.next();
- if (type.equals(i.getInput().getType())) {
- it.remove();
- readyQueue.addFirst(i);
- }
- }
-
- notify();
-
- final Object lock = this;
- return new Registration<InstructionExecutor>() {
- @Override
- public void close() throws Exception {
- synchronized (lock) {
- executors.remove(type, executor);
- }
- }
-
- @Override
- public InstructionExecutor getInstance() {
- return executor;
- }
- };
- }
-
- private static final RpcResult<SubmitInstructionOutput> failedSubmit(final Failure f) {
- return SuccessfulRpcResult.create(
- new SubmitInstructionOutputBuilder().setResult(
- new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.submit.instruction.output.result.FailureBuilder()
- .setFailure(f).build()).build());
- }
-
private synchronized RpcResult<CancelInstructionOutput> realCancelInstruction(final CancelInstructionInput input) {
final Instruction i = insns.get(input.getId());
if (i == null) {
return SuccessfulRpcResult.create(new CancelInstructionOutputBuilder().build());
}
- private synchronized RpcResult<SubmitInstructionOutput> realSubmitInstruction(final SubmitInstructionInput input) {
+ @Override
+ public Failure submitInstruction(final SubmitInstructionInput input, final InstructionExecutor executor) {
final InstructionId id = input.getId();
if (insns.get(id) != null) {
LOG.info("Instruction ID {} already present", id);
- return failedSubmit(new FailureBuilder().setType(DuplicateInstructionId.class).build());
+ return new FailureBuilder().setType(DuplicateInstructionId.class).build();
}
// First things first: check the deadline
if (left.compareTo(BigInteger.ZERO) <= 0) {
LOG.debug("Instruction {} deadline has already passed by {}ns", id, left);
- return failedSubmit(new FailureBuilder().setType(DeadOnArrival.class).build());
+ return new FailureBuilder().setType(DeadOnArrival.class).build();
}
// Resolve dependencies
final Instruction i = insns.get(pid);
if (i == null) {
LOG.info("Instruction {} depends on {}, which is not a known instruction", id, pid);
- return failedSubmit(new FailureBuilder().setType(UnknownPreconditionId.class).build());
+ return new FailureBuilder().setType(UnknownPreconditionId.class).build();
}
dependencies.add(i);
case Cancelled:
case Failed:
case Unknown:
- unmet.add(d.getInput().getId());
+ unmet.add(d.getId());
break;
case Executing:
case Queued:
* and fail the operation.
*/
if (!unmet.isEmpty()) {
- return failedSubmit(new FailureBuilder().setType(DeadOnArrival.class).setFailedPreconditions(unmet).build());
+ return new FailureBuilder().setType(DeadOnArrival.class).setFailedPreconditions(unmet).build();
}
/*
}, left.longValue(), TimeUnit.NANOSECONDS);
// Put it into the instruction list
- final Instruction i = new Instruction(input, dependencies, t);
+ final Instruction i = new Instruction(input.getId(), executor, dependencies, t);
insns.put(id, i);
// Attach it into its dependencies
* This task should be ingress-weighed, so we reinsert it into the
* same execution service.
*/
- executor.submit(new Runnable() {
+ this.executor.submit(new Runnable() {
@Override
public void run() {
tryScheduleInstruction(i);
}
});
- return SuccessfulRpcResult.create(new SubmitInstructionOutputBuilder().build());
+ return null;
}
@GuardedBy("this")
// Set the status
v.setStatus(status);
- LOG.debug("Instruction {} transitioned to status {}", v.getInput().getId(), status);
+ LOG.debug("Instruction {} transitioned to status {}", v.getId(), status);
// Send out a notification
notifs.publish(new InstructionStatusChangedBuilder().
- setId(v.getInput().getId()).setStatus(status).setDetails(details).build());
+ setId(v.getId()).setStatus(status).setDetails(details).build());
}
@GuardedBy("this")
@GuardedBy("this")
private void cancelDependants(final Instruction v) {
- final Details details = new DetailsBuilder().setUnmetDependencies(ImmutableList.of(v.getInput().getId())).build();
+ final Details details = new DetailsBuilder().setUnmetDependencies(ImmutableList.of(v.getId())).build();
for (final Instruction d : v.getDependants()) {
switch (d.getStatus()) {
case Cancelled:
}
private synchronized void cancelInstruction(final Instruction i, final Details details) {
- deferredQueue.remove(i);
readyQueue.remove(i);
cancelSingle(i, details);
cancelDependants(i);
final List<InstructionId> ids = new ArrayList<>();
for (final Instruction d : i.getDependencies()) {
if (d.getStatus() != InstructionStatus.Successful) {
- ids.add(d.getInput().getId());
+ ids.add(d.getId());
}
}
cancelInstruction(i, new DetailsBuilder().setUnmetDependencies(ids).build());
break;
case Scheduled:
- LOG.debug("Instruction {} timed out while Scheduled, cancelling it", i.getInput().getId());
+ LOG.debug("Instruction {} timed out while Scheduled, cancelling it", i.getId());
// FIXME: we should provide details why it timed out while scheduled
cancelInstruction(i, null);
break;
case Cancelled:
case Failed:
case Unknown:
- unmet.add(d.getInput().getId());
+ unmet.add(d.getId());
break;
case Executing:
case Queued:
}
if (!unmet.isEmpty()) {
- LOG.debug("Instruction {} was Queued, while some dependencies were resolved unsuccessfully, cancelling it", i.getInput().getId());
+ LOG.debug("Instruction {} was Queued, while some dependencies were resolved unsuccessfully, cancelling it", i.getId());
cancelSingle(i, new DetailsBuilder().setUnmetDependencies(unmet).build());
cancelDependants(i);
return;
}
if (ready) {
- LOG.debug("Instruction {} is ready for execution", i.getInput().getId());
+ LOG.debug("Instruction {} is ready for execution", i.getId());
transitionInstruction(i, InstructionStatus.Scheduled, null);
readyQueue.add(i);
}
private synchronized void executionFailed(final Instruction i, final Throwable cause) {
- LOG.error("Instruction {} failed to execute", i.getInput().getId(), cause);
+ LOG.error("Instruction {} failed to execute", i.getId(), cause);
transitionInstruction(i, InstructionStatus.Failed, null);
cancelDependants(i);
}
final Instruction i = readyQueue.poll();
Preconditions.checkState(i.getStatus().equals(InstructionStatus.Scheduled));
- final SubmitInstructionInput input = i.getInput();
-
- /*
- * Walk all the registered executors for a particular type and
- * offer them the chance to execute the instruction. The first
- * one to accept it wins.
- */
- Future<ExecutionResult<?>> f = null;
- final Collection<InstructionExecutor> el = executors.get(input.getType());
-
- for (final InstructionExecutor e : el) {
- f = e.offerInstruction(input.getArguments());
- if (f != null) {
- break;
- }
- }
-
- // We did not find an executor -- defer the instruction
- if (f == null) {
- deferredQueue.add(i);
- continue;
- }
transitionInstruction(i, InstructionStatus.Executing, null);
+ final Future<ExecutionResult<?>> f = i.execute();
f.addListener(new FutureListener<ExecutionResult<?>>() {
@Override
public void operationComplete(final Future<ExecutionResult<?>> future) {
<module>api</module>
<module>impl</module>
<module>spi</module>
+ <module>topology-api</module>
<module>tunnel-api</module>
</modules>
</project>
import io.netty.util.concurrent.Future;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.submit.instruction.input.Arguments;
-
public interface InstructionExecutor {
- Future<ExecutionResult<?>> offerInstruction(Arguments arguments);
+ Future<ExecutionResult<?>> execute();
}
*/
package org.opendaylight.bgpcep.programming.spi;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.InstructionType;
-import org.opendaylight.yangtools.concepts.Registration;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.SubmitInstructionInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.submit.instruction.output.result.failure.Failure;
-public interface InstructionExecutorRegistry {
- Registration<InstructionExecutor> registerInstructionExecutor(Class<? extends InstructionType> type, InstructionExecutor executor);
+public interface InstructionScheduler {
+ Failure submitInstruction(SubmitInstructionInput input, InstructionExecutor executor);
}
+
* 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.programming.impl;
+package org.opendaylight.bgpcep.programming.spi;
import java.util.Collection;
import java.util.Collections;
import org.opendaylight.yangtools.yang.common.RpcError;
import org.opendaylight.yangtools.yang.common.RpcResult;
-final class SuccessfulRpcResult<T> implements RpcResult<T> {
+public final class SuccessfulRpcResult<T> implements RpcResult<T> {
private final T value;
private SuccessfulRpcResult(final T value) {
this.value = value;
}
- static <T> SuccessfulRpcResult<T> create(final T value) {
+ public static <T> SuccessfulRpcResult<T> create(final T value) {
return new SuccessfulRpcResult<T>(value);
}
<parent>
<groupId>org.opendaylight.bgpcep</groupId>
- <artifactId>topology-parent</artifactId>
+ <artifactId>programming-parent</artifactId>
<version>0.3.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
- <artifactId>topology-tunnel-pcep-api</artifactId>
- <description>Topology Tunnel PCEP binding</description>
+ <artifactId>programming-topology-api</artifactId>
+ <description>Topology Programming API</description>
<packaging>bundle</packaging>
<name>${project.artifactId}</name>
<prerequisites>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
- <artifactId>pcep-api</artifactId>
+ <artifactId>programming-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
- <artifactId>topology-tunnel-api</artifactId>
+ <artifactId>topology-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<instructions>
<Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
<Export-Package>
- org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.tunnel.pcep.rev130820.*,
+ org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.tunnel.programming.rev130930.*,
</Export-Package>
</instructions>
</configuration>
<distributionManagement>
<site>
<id>${project.artifactId}</id>
- <name>TOPOLOGY-TUNNEL-PCEP Module site</name>
+ <name>PROGRAMMING-TOPOLOGY-API Module site</name>
<url>${basedir}/target/site/${project.artifactId}</url>
</site>
</distributionManagement>
--- /dev/null
+module network-topology-programming {
+ yang-version 1;
+ namespace "urn:opendaylight:params:xml:ns:yang:topology:programming";
+ prefix "tp";
+
+ import network-topology { prefix nt; revision-date 2013-10-21; }
+ import programming { prefix pgm; revision-date 2013-09-30; }
+
+ organization "Cisco Systems, Inc.";
+ contact "Robert Varga <rovarga@cisco.com>";
+
+ description
+ "This module contains the programming extensions for tunnel
+ topologies.
+
+ Copyright (c)2013 Cisco Systems, Inc. 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";
+
+ revision "2013-11-02" {
+ description
+ "Initial revision.";
+ reference "";
+ }
+
+ grouping topology-instruction-input {
+ uses pgm:submit-instruction-input;
+
+ leaf topology-id {
+ type nt:topology-id;
+ mandatory true;
+ }
+ }
+
+ grouping topology-instruction-output {
+ uses pgm:submit-instruction-output;
+ }
+}
+
<modelVersion>4.0.0</modelVersion>
<artifactId>programming-tunnel-api</artifactId>
- <description>Programming API</description>
+ <description>Tunnel Programming API</description>
<packaging>bundle</packaging>
<name>${project.artifactId}</name>
<prerequisites>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
- <artifactId>programming-api</artifactId>
+ <artifactId>programming-topology-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
prefix "ttp";
import network-topology { prefix nt; revision-date 2013-10-21; }
+ import network-topology-programming { prefix tp; revision-date 2013-11-02; }
import topology-tunnel { prefix tt; revision-date 2013-08-19; }
- import programming { prefix pgm; revision-date 2013-09-30; }
organization "Cisco Systems, Inc.";
contact "Robert Varga <rovarga@cisco.com>";
reference "";
}
- identity attach-path-instruction {
- base pgm:instruction-type;
- }
-
- identity create-path-instruction {
- base pgm:instruction-type;
- }
-
- identity destroy-path-instruction {
- base pgm:instruction-type;
- }
-
- identity detach-path-instruction {
- base pgm:instruction-type;
- }
-
- augment "/pgm:submit-instruction/pgm:input/pgm:arguments" {
- when "../type = attach-path-instruction";
-
- case attach-path {
- container attach-path {
- leaf link-id {
- type nt:link-id;
- mandatory true;
- }
- leaf path-id {
- type tt:path-id;
- mandatory true;
- }
- }
- }
- }
-
- augment "/pgm:submit-instruction/pgm:input/pgm:arguments" {
- when "../type = create-path-instruction";
+ grouping create-tunnel-input {
+ uses tp:topology-instruction-input;
- case create-path {
- container create-path {
- leaf path-id {
- type tt:path-id;
- mandatory true;
- }
- }
+ leaf link-id {
+ type nt:link-id;
+ mandatory true;
}
}
- augment "/pgm:submit-instruction/pgm:input/pgm:arguments" {
- when "../type = destroy-path-instruction";
-
- case destroy-path {
- container destroy-path {
- leaf path-id {
- type tt:path-id;
- mandatory true;
- }
- }
- }
- }
-
- augment "/pgm:submit-instruction/pgm:input/pgm:arguments" {
- when "../type = detach-path-instruction";
-
- case detach-path {
- container detach-path {
- leaf link-id {
- type nt:link-id;
- mandatory true;
- }
- leaf path-id {
- type tt:path-id;
- mandatory true;
- }
- }
- }
+ grouping create-tunnel-output {
+ uses tp:topology-instruction-output;
}
- identity create-tunnel-instruction {
- base pgm:instruction-type;
- }
-
- identity destroy-tunnel-instruction {
- base pgm:instruction-type;
- }
+ grouping destroy-tunnel-input {
+ uses tp:topology-instruction-input;
- augment "/pgm:submit-instruction/pgm:input/pgm:arguments" {
- when "../type = create-tunnel-instruction";
-
- case create-tunnel {
- container create-tunnel {
- leaf link-id {
- type nt:link-id;
- mandatory true;
- }
- }
+ leaf link-id {
+ type nt:link-id;
+ mandatory true;
}
}
- augment "/pgm:submit-instruction/pgm:input/pgm:arguments" {
- when "../type = destroy-tunnel-instruction";
-
- case destroy-tunnel {
- container destroy-tunnel {
- leaf link-id {
- type nt:link-id;
- mandatory true;
- }
- }
- }
+ grouping destroy-tunnel-output {
+ uses tp:topology-instruction-output;
}
}
+++ /dev/null
-module inventory-pcep {
- // vi: set et smarttab sw=4 tabstop=4:
- yang-version 1;
- namespace "urn:opendaylight:inventory:pcep";
- prefix "inv-pcep";
-
- import network-topology { prefix nt; revision-date 2013-10-21; }
- import opendaylight-inventory { prefix inv; revision-date 2013-08-19; }
- import pcep-types { prefix pcep; revision-date 2013-10-05; }
-
- organization "Cisco Systems, Inc.";
- contact "Robert Varga <rovarga@cisco.com>";
-
- description
- "This module contains the PCEP extensions to base inventory
- model.
-
- Copyright (c)2013 Cisco Systems, Inc. All rights reserved.";
-
- revision "2013-10-24" {
- description
- "Initial revision.";
- reference "";
- }
-
- typedef pcc-sync-state {
- type enumeration {
- enum initial-resync {
- description
- "Initial state resynchronization is being performed.";
- }
- enum synchronized {
- description
- "State synchronization has been achieved.";
- }
- }
- }
-
- augment "/inv:nodes/inv:node" {
- container path-computation-client {
- description
- "PCC-related run-time information. This container is only
- present when the node is connected through PCEP in a PCC
- role.";
-
- container stateful-tlv {
- uses pcep:stateful-capability-tlv;
- }
-
- leaf state-sync {
- when "../stateful-tlv";
- type pcc-sync-state;
- }
-
- leaf topology-node {
- type nt:node-ref;
- }
- }
- }
-}
-
+++ /dev/null
-module network-topology-pcep {
- // vi: set et smarttab sw=4 tabstop=4:
- yang-version 1;
- namespace "urn:opendaylight:params:xml:ns:yang:topology:pcep";
- prefix "pn";
-
- import network-topology { prefix nt; revision-date 2013-10-21; }
- import pcep-types { prefix pcep; revision-date 2013-10-05; }
-
- organization "Cisco Systems, Inc.";
- contact "Robert Varga <rovarga@cisco.com>";
-
- description
- "This module contains the PCEP extensions to base topology model. It
- exposes the LSPs for which a particular node is the head end.
-
- Copyright (c)2013 Cisco Systems, Inc. All rights reserved.";
-
- revision "2013-10-24" {
- description
- "Initial revision.";
- reference "";
- }
-
- grouping pcep-client-attributes {
- description "Data present in a node which is a PCEP client (PCC).";
-
- container pcc {
- config false;
-
- list lsps {
- leaf name {
- type pcep:symbolic-path-name;
- }
- key name;
-
- // FIXME: hide protocol-specific?
- uses pcep:lsp-object;
- }
- }
- }
-
- augment "/nt:network-topology/nt:topology/nt:node" {
- uses pcep-client-attributes;
- }
-}
-
<modules>
<module>api</module>
- <module>pcep-api</module>
<module>provider-bgp</module>
- <module>provider-pcep</module>
<module>tunnel-api</module>
- <module>tunnel-pcep-api</module>
- <module>tunnel-provider-pcep</module>
<module>segment-routing</module>
</modules>
</project>
+++ /dev/null
-/*
- * Copyright (c) 2013 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.topology.provider.pcep;
-
-import java.net.InetAddress;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Future;
-
-import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
-import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
-import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
-import org.opendaylight.protocol.framework.SessionListenerFactory;
-import org.opendaylight.protocol.pcep.PCEPSession;
-import org.opendaylight.protocol.pcep.PCEPSessionListener;
-import org.opendaylight.protocol.pcep.PCEPTerminationReason;
-import org.opendaylight.protocol.pcep.TerminationReason;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.pcep.rev131024.PccSyncState;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.pcep.rev131024.nodes.node.PathComputationClientBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.pcep.rev131024.nodes.node.path.computation.client.StatefulTlvBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.message.rev131007.Pcerr;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.message.rev131007.PcerrBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.Message;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.PcrptMessage;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.PlspId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.open.object.Tlvs;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcerr.message.PcerrMessageBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcrpt.message.pcrpt.message.Reports;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcrpt.message.pcrpt.message.reports.Lsp;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.stateful.capability.tlv.Stateful;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.symbolic.path.name.tlv.SymbolicPathName;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.pcep.client.attributes.PccBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.pcep.client.attributes.pcc.Lsps;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.pcep.client.attributes.pcc.LspsKey;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.base.Preconditions;
-
-/**
- *
- */
-final class ServerSessionManager implements SessionListenerFactory<PCEPSessionListener> {
- private static String createNodeId(final InetAddress addr) {
- return "pcc://" + addr.getHostAddress();
- }
-
- private final class SessionListener implements PCEPSessionListener {
- private org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node inventoryNode(
- final DataModificationTransaction trans, final InetAddress address) {
- final String pccId = createNodeId(address);
-
- // FIXME: after 0.6 yangtools, this cast should not be needed
- final Nodes nodes = (Nodes) trans.readOperationalData(ServerSessionManager.this.inventory);
-
- for (final org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node n : nodes.getNode()) {
- LOG.debug("Matching inventory node {} to peer {}", n, address);
- if (n.getId().getValue().equals(pccId)) {
- return n;
- }
-
- // FIXME: locate the node by its management IP address
- }
-
- /*
- * We failed to find a matching node. Let's create a dynamic one
- * to have a backer. Note that this node will be created in the
- * Runtime data space.
- */
- LOG.debug("Failed to find inventory node for peer {}, creating a new one at {}", address, pccId);
-
- final org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId id = new org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId(pccId);
- final org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey nk = new org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey(id);
- final InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node> nii = InstanceIdentifier.builder(
- ServerSessionManager.this.inventory).node(
- org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node.class, nk).toInstance();
- final org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node ret = new org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder().setId(
- id).setKey(nk).build();
-
- trans.putRuntimeData(nii, ret);
- ServerSessionManager.this.ownsInventory = true;
- ServerSessionManager.this.inventoryNodeId = nii;
- return ret;
- }
-
- final org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node topologyNode(
- final DataModificationTransaction trans,
- final org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node invNode) {
- // FIXME: after 0.6 yangtools, this cast should not be needed
- final Topology topo = (Topology) trans.readOperationalData(ServerSessionManager.this.topology);
-
- for (final org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node n : topo.getNode()) {
- LOG.debug("Matching topology node {} to inventory node {}", n, invNode);
- if (n.getNodeId().getValue().equals(invNode.getId().getValue())) {
- return n;
- }
- }
-
- /*
- * We failed to find a matching node. Let's create a dynamic one
- * and note that we are the owner (so we clean it up afterwards).
- */
- final org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId id = new org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId(invNode.getId().getValue());
- final org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey nk = new org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey(id);
- final InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node> nti = InstanceIdentifier.builder(
- ServerSessionManager.this.topology).node(
- org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node.class,
- nk).toInstance();
-
- final org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node ret = new org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder().setKey(
- nk).setNodeId(id).build();
-
- trans.putRuntimeData(nti, ret);
- ServerSessionManager.this.ownsTopology = true;
- ServerSessionManager.this.topologyNodeId = nti;
- return ret;
- }
-
- @Override
- public void onSessionUp(final PCEPSession session) {
- /*
- * The session went up. Look up the router in Inventory model,
- * create it if it is not there (marking that fact for later
- * deletion), and mark it as synchronizing. Also create it in
- * the topology model, with empty LSP list.
- */
- final InetAddress peerAddress = session.getRemoteAddress();
- final DataModificationTransaction trans = ServerSessionManager.this.dataProvider.beginTransaction();
-
- final org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node invNode = inventoryNode(trans, peerAddress);
- LOG.debug("Peer {} resolved to inventory node {}", peerAddress, invNode);
-
- final org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node topoNode = topologyNode(
- trans, invNode);
- LOG.debug("Peer {} resolved to topology node {}", peerAddress, topoNode);
-
- // Our augmentation in the topology node
- final PccBuilder pb = new PccBuilder();
-
- final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.Node1 topoAugment = new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.Node1Builder().setPcc(
- pb.build()).build();
- ServerSessionManager.this.topologyAugmentId = InstanceIdentifier.builder(ServerSessionManager.this.topologyNodeId).node(
- org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.Node1.class).toInstance();
- trans.putRuntimeData(ServerSessionManager.this.topologyAugmentId, topoAugment);
-
- // Our augmentation in the inventory node
- ServerSessionManager.this.pccBuilder = new PathComputationClientBuilder();
-
- final Tlvs tlvs = session.getRemoteTlvs();
- final Stateful stateful = tlvs.getStateful();
- if (stateful != null) {
- // FIXME: rework once groupings can be used in builders
- ServerSessionManager.this.pccBuilder.setStatefulTlv(new StatefulTlvBuilder().setStateful(stateful).build());
- ServerSessionManager.this.pccBuilder.setStateSync(PccSyncState.InitialResync);
- }
-
- ServerSessionManager.this.pccBuilder.setTopologyNode(topoNode.getNodeId());
-
- ServerSessionManager.this.inventoryAugmentBuilder = new org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.pcep.rev131024.Node1Builder().setPathComputationClient(ServerSessionManager.this.pccBuilder.build());
- ServerSessionManager.this.inventoryAugmentId = InstanceIdentifier.builder(ServerSessionManager.this.inventoryNodeId).node(
- org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.pcep.rev131024.Node1.class).toInstance();
- trans.putRuntimeData(ServerSessionManager.this.inventoryAugmentId, ServerSessionManager.this.inventoryAugmentBuilder.build());
-
- // All set, commit the modifications
- final Future<RpcResult<TransactionStatus>> s = trans.commit();
-
- /*
- * FIXME: once this Future is listenable, attach to it so we can
- * do cleanup if the commit fails. For now we force a commit.
- */
- try {
- s.get();
- } catch (InterruptedException | ExecutionException e) {
- LOG.error("Failed to update internal state for session {}, terminating it", session, e);
- session.close(TerminationReason.Unknown);
- }
-
- LOG.info("Session with {} attached to inventory node {} and topology node {}", session.getRemoteAddress(), invNode.getId(),
- topoNode.getNodeId());
- }
-
- private void tearDown(final PCEPSession session) {
- final DataModificationTransaction trans = ServerSessionManager.this.dataProvider.beginTransaction();
-
- /*
- * The session went down. Undo all the Inventory and Topology
- * changes we have done.
- */
- trans.removeRuntimeData(ServerSessionManager.this.inventoryAugmentId);
- if (ServerSessionManager.this.ownsInventory) {
- trans.removeRuntimeData(ServerSessionManager.this.inventoryNodeId);
- }
- trans.removeRuntimeData(ServerSessionManager.this.topologyAugmentId);
- if (ServerSessionManager.this.ownsTopology) {
- trans.removeRuntimeData(ServerSessionManager.this.topologyNodeId);
- }
-
- /*
- * FIXME: once this Future is listenable, attach to it so we can
- * do cleanup if the commit fails. For now we force a commit.
- */
- final Future<RpcResult<TransactionStatus>> s = trans.commit();
- try {
- s.get();
- } catch (InterruptedException | ExecutionException e) {
- LOG.error("Failed to cleanup internal state for session {}", session, e);
- }
- }
-
- @Override
- public void onSessionDown(final PCEPSession session, final Exception e) {
- LOG.warn("Session {} went down unexpectedly", e);
- tearDown(session);
- }
-
- @Override
- public void onSessionTerminated(final PCEPSession session, final PCEPTerminationReason reason) {
- LOG.info("Session {} terminated by peer with reason {}", session, reason);
- tearDown(session);
- }
-
- private InstanceIdentifier<Lsps> lspIdentifier(final SymbolicPathName name) {
- return InstanceIdentifier.builder(ServerSessionManager.this.topologyAugmentId).node(Lsps.class, new LspsKey(name.getPathName())).toInstance();
- }
-
- @Override
- public void onMessage(final PCEPSession session, final Message message) {
- if (!(message instanceof PcrptMessage)) {
- LOG.info("Unhandled message {} on session {}", message, session);
- session.sendMessage(unhandledMessageError);
- }
-
- final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcrpt.message.PcrptMessage rpt = ((PcrptMessage) message).getPcrptMessage();
-
- final DataModificationTransaction trans = ServerSessionManager.this.dataProvider.beginTransaction();
-
- for (final Reports r : rpt.getReports()) {
- final Lsp lsp = r.getLsp();
-
- if (lsp.isSync() && !ServerSessionManager.this.synced) {
- // Update synchronization flag
- ServerSessionManager.this.synced = true;
- ServerSessionManager.this.inventoryAugmentBuilder.setPathComputationClient(ServerSessionManager.this.pccBuilder.setStateSync(
- PccSyncState.Synchronized).build());
- trans.putRuntimeData(ServerSessionManager.this.inventoryAugmentId,
- ServerSessionManager.this.inventoryAugmentBuilder.build());
- LOG.debug("Session {} achieved synchronized state", session);
- }
-
- final PlspId id = lsp.getPlspId();
- if (lsp.isRemove()) {
- final SymbolicPathName name = ServerSessionManager.this.lsps.remove(id);
- if (name != null) {
- trans.removeRuntimeData(lspIdentifier(name));
- }
-
- LOG.debug("LSP {} removed", lsp);
- } else {
- if (!ServerSessionManager.this.lsps.containsKey(id)) {
- LOG.debug("PLSPID {} not known yet, looking for a symbolic name", id);
-
- final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.lsp.object.Tlvs tlvs = r.getLsp().getTlvs();
- final SymbolicPathName name = tlvs.getSymbolicPathName();
- if (name == null) {
- LOG.error("PLSPID {} seen for the first time, not reporting the LSP");
- // TODO: what should we do here?
- continue;
- }
- }
-
- final SymbolicPathName name = ServerSessionManager.this.lsps.get(id);
- trans.putRuntimeData(lspIdentifier(name), lsp);
-
- LOG.debug("LSP {} updated");
- }
- }
-
- /*
- * FIXME: once this Future is listenable, attach to it so we can
- * do cleanup if the commit fails. For now we force a commit.
- */
- final Future<RpcResult<TransactionStatus>> s = trans.commit();
- try {
- s.get();
- } catch (InterruptedException | ExecutionException e) {
- LOG.error("Failed to update internal state for session {}, closing it", session, e);
- session.close(TerminationReason.Unknown);
- }
- }
- }
-
- private static final Logger LOG = LoggerFactory.getLogger(ServerSessionManager.class);
- private static final Pcerr unhandledMessageError = new PcerrBuilder().setPcerrMessage(
- new PcerrMessageBuilder().setErrorType(null).build()).build();
- private final Map<PlspId, SymbolicPathName> lsps = new HashMap<>();
- private final InstanceIdentifier<Nodes> inventory;
- private final InstanceIdentifier<Topology> topology;
- private final DataProviderService dataProvider;
-
- private boolean ownsInventory = false;
- private InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node> inventoryNodeId;
- private InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.pcep.rev131024.Node1> inventoryAugmentId;
- private org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.pcep.rev131024.Node1Builder inventoryAugmentBuilder;
- private PathComputationClientBuilder pccBuilder;
- private boolean synced = false;
-
- private boolean ownsTopology = false;
- private InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node> topologyNodeId;
- private InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.Node1> topologyAugmentId;
-
- public ServerSessionManager(final DataProviderService dataProvider, final InstanceIdentifier<Nodes> inventory,
- final InstanceIdentifier<Topology> topology) {
- this.dataProvider = Preconditions.checkNotNull(dataProvider);
- this.inventory = Preconditions.checkNotNull(inventory);
- this.topology = Preconditions.checkNotNull(topology);
- }
-
- @Override
- public PCEPSessionListener getSessionListener() {
- return new SessionListener();
- }
-}