ONOS-5304 MDSC TE Tunnel controller
Change-Id: I1edbf3a583966f1389eb167543ced7bd6c4c51b3
ONOS-5304 MDSC TE Tunnel controller
Change-Id: I1edbf3a583966f1389eb167543ced7bd6c4c51b3
diff --git a/apps/actn-mdsc/actn-mdscapp/app.xml b/apps/actn-mdsc/actn-mdscapp/app.xml
new file mode 100644
index 0000000..f97405a
--- /dev/null
+++ b/apps/actn-mdsc/actn-mdscapp/app.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright 2016-present Open Networking Laboratory
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<app name="org.onosproject.actn.mdsc" origin="Huawei" version="${project.version}"
+ category="default" url="http://onosproject.org" title="ACTN MDSC App"
+ featuresRepo="mvn:${project.groupId}/${project.artifactId}/${project.version}/xml/features"
+ features="${project.artifactId}">
+ <description>${project.description}</description>
+ <artifact>mvn:${project.groupId}/onos-actn-mdsc-tetunnel-pce/${project.version}</artifact>
+ <artifact>mvn:${project.groupId}/onos-actn-mdsc-tetunnel-ctl/${project.version}</artifact>
+ <apps>org.onosproject.tetopology, org.onosproject.tetunnel</apps>
+</app>
diff --git a/apps/actn-mdsc/actn-mdscapp/features.xml b/apps/actn-mdsc/actn-mdscapp/features.xml
new file mode 100644
index 0000000..a4fe5a7
--- /dev/null
+++ b/apps/actn-mdsc/actn-mdscapp/features.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+ ~ Copyright 2016-present Open Networking Laboratory
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<features xmlns="http://karaf.apache.org/xmlns/features/v1.2.0" name="${project.artifactId}-${project.version}">
+ <feature name="${project.artifactId}" version="${project.version}"
+ description="${project.description}">
+ <feature>onos-api</feature>
+ <feature>onos-app-tetopology</feature>
+ <feature>onos-app-tetunnel</feature>
+ <bundle>mvn:${project.groupId}/onos-actn-mdsc-tetunnel-pce/${project.version}</bundle>
+ <bundle>mvn:${project.groupId}/onos-actn-mdsc-tetunnel-ctl/${project.version}</bundle>
+ </feature>
+</features>
diff --git a/apps/actn-mdsc/actn-mdscapp/pom.xml b/apps/actn-mdsc/actn-mdscapp/pom.xml
new file mode 100644
index 0000000..6607007
--- /dev/null
+++ b/apps/actn-mdsc/actn-mdscapp/pom.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright 2016-present Open Networking Laboratory
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<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">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <artifactId>onos-actn-mdsc</artifactId>
+ <groupId>org.onosproject</groupId>
+ <version>1.8.0-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>onos-actn-mdscapp</artifactId>
+ <description>ONOS ACTN MDSC Application</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-actn-mdsc-tetunnel-ctl</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+</project>
\ No newline at end of file
diff --git a/apps/actn-mdsc/pom.xml b/apps/actn-mdsc/pom.xml
new file mode 100644
index 0000000..e3b6303
--- /dev/null
+++ b/apps/actn-mdsc/pom.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright 2016 Open Networking Laboratory
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<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">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <artifactId>onos-apps</artifactId>
+ <groupId>org.onosproject</groupId>
+ <version>1.8.0-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>onos-actn-mdsc</artifactId>
+ <packaging>pom</packaging>
+
+ <description>ONOS ACTN MDSC Application</description>
+
+ <modules>
+ <module>tetunnel-pce</module>
+ <module>tetunnel-ctl</module>
+ <module>actn-mdscapp</module>
+ </modules>
+
+ <properties>
+ <!-- Uncomment to generate ONOS app from this module.
+ <onos.app.name>org.onosproject.actn.mdsc</onos.app.name>
+ <onos.app.origin>Huawei</onos.app.origin>
+ <onos.app.category>default</onos.app.category>
+ <onos.app.url>http://onosproject.org</onos.app.url>
+ <onos.app.title>Foo App</onos.app.title>
+ <onos.app.readme>ONOS OSGi bundle archetype.</onos.app.readme>
+ -->
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-incubator-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+</project>
\ No newline at end of file
diff --git a/apps/actn-mdsc/tetunnel-ctl/pom.xml b/apps/actn-mdsc/tetunnel-ctl/pom.xml
new file mode 100644
index 0000000..c2f678f
--- /dev/null
+++ b/apps/actn-mdsc/tetunnel-ctl/pom.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright 2016-present Open Networking Laboratory
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<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">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <artifactId>onos-actn-mdsc</artifactId>
+ <groupId>org.onosproject</groupId>
+ <version>1.8.0-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>onos-actn-mdsc-tetunnel-ctl</artifactId>
+ <description>TE Tunnel controller which manages TE tunnel processing</description>
+ <packaging>bundle</packaging>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-app-tetunnel-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-actn-mdsc-tetunnel-pce</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+</project>
\ No newline at end of file
diff --git a/apps/actn-mdsc/tetunnel-ctl/src/main/java/org/onosproject/actn/mdsc/tetunnelctl/TeTunnelCtl.java b/apps/actn-mdsc/tetunnel-ctl/src/main/java/org/onosproject/actn/mdsc/tetunnelctl/TeTunnelCtl.java
new file mode 100755
index 0000000..5106652
--- /dev/null
+++ b/apps/actn-mdsc/tetunnel-ctl/src/main/java/org/onosproject/actn/mdsc/tetunnelctl/TeTunnelCtl.java
@@ -0,0 +1,347 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.actn.mdsc.tetunnelctl;
+
+import com.google.common.collect.Lists;
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.onosproject.actn.mdsc.pce.TeTunnelPceService;
+import org.onosproject.incubator.net.tunnel.Tunnel;
+import org.onosproject.incubator.net.tunnel.TunnelAdminService;
+import org.onosproject.incubator.net.tunnel.TunnelEvent;
+import org.onosproject.incubator.net.tunnel.TunnelId;
+import org.onosproject.incubator.net.tunnel.TunnelListener;
+import org.onosproject.incubator.net.tunnel.TunnelService;
+import org.onosproject.tetopology.management.api.TeTopology;
+import org.onosproject.tetopology.management.api.TeTopologyKey;
+import org.onosproject.tetopology.management.api.TeTopologyService;
+import org.onosproject.tetopology.management.api.node.TeNodeKey;
+import org.onosproject.tetopology.management.api.node.TtpKey;
+import org.onosproject.tetunnel.api.TeTunnelAdminService;
+import org.onosproject.tetunnel.api.TeTunnelService;
+import org.onosproject.tetunnel.api.tunnel.DefaultTeTunnel;
+import org.onosproject.tetunnel.api.tunnel.TeTunnel;
+import org.onosproject.tetunnel.api.tunnel.TeTunnelKey;
+import org.onosproject.tetunnel.api.tunnel.path.TePath;
+import org.onosproject.tetunnel.api.tunnel.path.TeRouteSubobject;
+import org.onosproject.tetunnel.api.tunnel.path.TeRouteUnnumberedLink;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * TE Tunnel controller/processor which manages TE tunnel processing.
+ * <p>
+ * For example, when creating a cross-domain tunnel from a MDSC, the
+ * processor will call a relevant PCE to get an end-to-end cross-domain path,
+ * then spits the path into segment tunnels(domain tunnels), and then informs
+ * PNCs to setup domain tunnels respectively.
+ */
+@Component(immediate = true)
+public class TeTunnelCtl {
+
+ private static final Logger log = LoggerFactory.getLogger(TeTunnelCtl.class);
+
+ private final TunnelListener tunnelListener = new InternalTunnelListener();
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected TunnelService tunnelService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected TunnelAdminService tunnelAdminService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected TeTunnelService teTunnelService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected TeTunnelAdminService teTunnelAdminService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected TeTopologyService teTopologyService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected TeTunnelPceService teTunnelPceService;
+
+ @Activate
+ protected void activate() {
+ tunnelService.addListener(tunnelListener);
+
+ log.info("Started");
+ }
+
+ @Deactivate
+ protected void deactivate() {
+ tunnelService.removeListener(tunnelListener);
+
+ log.info("Stopped");
+ }
+
+ private void addTeTunnel(TeTunnel teTunnel) {
+ if (teTunnel == null) {
+ return;
+ }
+
+ Tunnel tunnel = tunnelService.queryTunnel(
+ teTunnelService.getTunnelId(teTunnel.teTunnelKey()));
+ if (tunnel == null) {
+ log.error("tunnel does not exist, {}", teTunnel.teTunnelKey());
+ return;
+ }
+ if (tunnel.state() != Tunnel.State.INIT) {
+ log.error("tunnel state error, {}, {}", teTunnel.teTunnelKey(),
+ tunnel.state());
+ return;
+ }
+ tunnelAdminService.updateTunnelState(tunnel, Tunnel.State.ESTABLISHING);
+
+ //TODO support multi-thread
+ if (isTeTunnelCrossDomain(teTunnel)) {
+ if (!addCrossDomainTeTunnel(teTunnel)) {
+ tunnelAdminService.updateTunnelState(tunnel, Tunnel.State.FAILED);
+ }
+ }
+ /*
+ * "else" is to do nothing.
+ * When adding a single domain tunnel, the TunnelManager will call
+ * tunnel providers, then the providers will pass the request to
+ * the domain controller. Nothing to do here.
+ */
+ }
+
+ private boolean isTeTunnelCrossDomain(TeTunnel teTunnel) {
+ TeTopology srcTopo = teTopologyService.teTopology(
+ teTopologyService.teNode(teTunnel.srcNode())
+ .underlayTeTopologyId());
+ TeTopology dstTopo = teTopologyService.teTopology(
+ teTopologyService.teNode(teTunnel.dstNode())
+ .underlayTeTopologyId());
+ return (srcTopo != null && dstTopo != null
+ && srcTopo.ownerId().equals(dstTopo.ownerId()));
+ }
+
+ private boolean addCrossDomainTeTunnel(TeTunnel teTunnel) {
+ List<TeRouteSubobject> route = null;
+ TePath primaryPath = teTunnel.primaryPaths().get(0);
+ if (primaryPath != null &&
+ primaryPath.type() == TePath.Type.EXPLICIT) {
+ route = primaryPath.explicitRoute();
+ } else {
+ Collection<List<TeRouteSubobject>> routes =
+ teTunnelPceService.computePaths(teTunnel);
+ if (routes == null || routes.isEmpty()) {
+ log.error("no available route for {}",
+ teTunnel.teTunnelKey());
+ return false;
+ }
+
+ //FIXME: try other pce when failed?
+ route = routes.iterator().next();
+ }
+
+ if (route == null) {
+ log.error("no available route for {}",
+ teTunnel.teTunnelKey());
+ return false;
+ }
+
+ return spitRoute(teTunnel, route);
+ }
+
+ //spits route to segment tunnels
+ private boolean spitRoute(TeTunnel teTunnel, List<TeRouteSubobject> route) {
+ List<TeTunnelKey> segmentTunnels = Lists.newArrayList();
+ boolean success = true;
+ TeNodeKey srcNode = teTunnel.srcNode();
+ TtpKey srcTp = teTunnel.srcTp();
+ TeNodeKey dstNode = null;
+ TtpKey dstTp = null;
+
+ for (TeRouteSubobject teRouteSubobject : route) {
+ if (!(teRouteSubobject instanceof TeRouteUnnumberedLink)) {
+ log.error("unsupported type {}", teRouteSubobject.type());
+ success = false;
+ break;
+ }
+
+ TeRouteUnnumberedLink teRouteUnnumberedLink =
+ (TeRouteUnnumberedLink) teRouteSubobject;
+ dstNode = teRouteUnnumberedLink.node();
+ dstTp = teRouteUnnumberedLink.ttp();
+ if (Objects.equals(srcNode, dstNode) &&
+ Objects.equals(srcTp, dstTp)) {
+ continue;
+ }
+ if (Objects.equals(srcNode, dstNode)) {
+ if (!addSegmentTunnel(segmentTunnels, teTunnel,
+ srcNode, srcTp, dstNode, dstTp)) {
+ success = false;
+ break;
+ }
+ }
+
+ srcNode = dstNode;
+ srcTp = dstTp;
+ }
+
+ if (success && !(Objects.equals(dstNode, teTunnel.dstNode()) &&
+ Objects.equals(dstTp, teTunnel.dstTp()))) {
+ srcNode = dstNode;
+ srcTp = dstTp;
+ dstNode = teTunnel.dstNode();
+ dstTp = teTunnel.dstTp();
+ if (!addSegmentTunnel(segmentTunnels, teTunnel,
+ srcNode, srcTp, dstNode, dstTp)) {
+ success = false;
+ }
+ }
+
+ if (!success) {
+ // roll back segment tunnels
+ for (TeTunnelKey key : segmentTunnels) {
+ teTunnelAdminService.removeTeTunnel(key);
+ }
+ } else {
+ teTunnelAdminService.setSegmentTunnel(teTunnel.teTunnelKey(),
+ segmentTunnels);
+ }
+ return success;
+ }
+
+ private boolean addSegmentTunnel(List<TeTunnelKey> segmentTunnels,
+ TeTunnel teTunnel,
+ TeNodeKey srcNode, TtpKey srcTp,
+ TeNodeKey dstNode, TtpKey dstTp) {
+ TeTunnelKey teTunnelKey = getNextTeTunnelKey(srcNode.teTopologyKey());
+ TeTunnel teTunnelSegment = DefaultTeTunnel.builder()
+ .teTunnelKey(teTunnelKey)
+ .srcNode(srcNode)
+ .dstNode(dstNode)
+ .srcTp(srcTp)
+ .dstTp(dstTp)
+ .adminState(teTunnel.adminStatus())
+ .lspProtectionType(teTunnel.lspProtectionType())
+ .type(teTunnel.type())
+ .build();
+ TunnelId tunnelId =
+ teTunnelAdminService.createTeTunnel(teTunnelSegment);
+ if (tunnelId == null) {
+ log.error("failed to create segment tunnel: {},{},{},{}",
+ srcNode, srcTp, dstNode, dstTp);
+ return false;
+ }
+ segmentTunnels.add(teTunnelKey);
+ return true;
+ }
+
+ private TeTunnelKey getNextTeTunnelKey(TeTopologyKey key) {
+ //FIXME need a better way to get a te tunnel id
+ long teTunnelId = teTunnelService.getTeTunnels(key).size() + 1;
+ return new TeTunnelKey(key, teTunnelId);
+ }
+
+ private void updateTeTunnel(TeTunnel teTunnel, Tunnel tunnel) {
+ if (teTunnel == null) {
+ return;
+ }
+
+ if (tunnel.state() == Tunnel.State.ESTABLISHED) {
+ tunnelEstablished(teTunnel);
+ } else if (tunnel.state() == Tunnel.State.REMOVING) {
+ removingTunnel(teTunnel);
+ }
+
+ //TODO update TE tunnel content
+ }
+
+ private void tunnelEstablished(TeTunnel teTunnel) {
+ TeTunnel e2eTeTunnel = retriveE2eTunnel(teTunnel);
+ if (e2eTeTunnel != null) {
+ boolean goodToContinue = true;
+ for (TeTunnelKey key : e2eTeTunnel.segmentTunnels()) {
+ goodToContinue = checkSegmentTunnel(key);
+ if (!goodToContinue) {
+ break;
+ }
+ }
+
+ if (goodToContinue) {
+ tunnelAdminService.updateTunnelState(
+ tunnelService.queryTunnel(
+ teTunnelService.getTunnelId(
+ teTunnel.teTunnelKey())),
+ Tunnel.State.ESTABLISHED
+ );
+ }
+ }
+ }
+
+ private TeTunnel retriveE2eTunnel(TeTunnel segmentTunnel) {
+ return teTunnelService.getTeTunnel(segmentTunnel.e2eTunnelKey());
+ }
+
+ private boolean checkSegmentTunnel(TeTunnelKey key) {
+ Tunnel segmentTunnel = tunnelService.queryTunnel(
+ teTunnelService.getTunnelId(key));
+ if (segmentTunnel == null ||
+ segmentTunnel.state() != Tunnel.State.ESTABLISHED) {
+ return false;
+ }
+ return true;
+ }
+
+ private void removingTunnel(TeTunnel teTunnel) {
+ List<TeTunnelKey> segmentTunnels = teTunnel.segmentTunnels();
+ if (segmentTunnels != null && !segmentTunnels.isEmpty()) {
+ for (TeTunnelKey key : segmentTunnels) {
+ teTunnelAdminService.removeTeTunnel(key);
+ }
+ }
+ }
+
+ // Listens on tunnel events.
+ private class InternalTunnelListener implements TunnelListener {
+ @Override
+ public void event(TunnelEvent event) {
+ switch (event.type()) {
+ case TUNNEL_ADDED:
+ addTunnel(event.subject());
+ break;
+ case TUNNEL_UPDATED:
+ updateTunnel(event.subject());
+ break;
+ //TODO: TE Tunnel remove/... event process
+ default:
+ log.warn("unknown event: {}", event.type());
+ break;
+ }
+ }
+
+ private void addTunnel(Tunnel tunnel) {
+ addTeTunnel(teTunnelService.getTeTunnel(tunnel.tunnelId()));
+ }
+
+ private void updateTunnel(Tunnel tunnel) {
+ updateTeTunnel(teTunnelService.getTeTunnel(tunnel.tunnelId()),
+ tunnel);
+ }
+ }
+}
diff --git a/apps/actn-mdsc/tetunnel-ctl/src/main/java/org/onosproject/actn/mdsc/tetunnelctl/package-info.java b/apps/actn-mdsc/tetunnel-ctl/src/main/java/org/onosproject/actn/mdsc/tetunnelctl/package-info.java
new file mode 100644
index 0000000..8de1d14
--- /dev/null
+++ b/apps/actn-mdsc/tetunnel-ctl/src/main/java/org/onosproject/actn/mdsc/tetunnelctl/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * TE Tunnel controller/processor which manages TE tunnel processing.
+ */
+package org.onosproject.actn.mdsc.tetunnelctl;
\ No newline at end of file
diff --git a/apps/actn-mdsc/tetunnel-pce/pom.xml b/apps/actn-mdsc/tetunnel-pce/pom.xml
new file mode 100755
index 0000000..d5ace69
--- /dev/null
+++ b/apps/actn-mdsc/tetunnel-pce/pom.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright 2016-present Open Networking Laboratory
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<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>
+ <artifactId>onos-actn-mdsc</artifactId>
+ <groupId>org.onosproject</groupId>
+ <version>1.8.0-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>onos-actn-mdsc-tetunnel-pce</artifactId>
+ <description>TE Tunnel PCE service</description>
+ <packaging>bundle</packaging>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-app-tetunnel-api</artifactId>
+ <version>1.8.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-app-tetunnel-api</artifactId>
+ <version>1.8.0-SNAPSHOT</version>
+ </dependency>
+ </dependencies>
+</project>
\ No newline at end of file
diff --git a/apps/actn-mdsc/tetunnel-pce/src/main/java/org/onosproject/actn/mdsc/pce/TeTunnelPce.java b/apps/actn-mdsc/tetunnel-pce/src/main/java/org/onosproject/actn/mdsc/pce/TeTunnelPce.java
new file mode 100755
index 0000000..705896f
--- /dev/null
+++ b/apps/actn-mdsc/tetunnel-pce/src/main/java/org/onosproject/actn/mdsc/pce/TeTunnelPce.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.actn.mdsc.pce;
+
+import org.onosproject.tetunnel.api.tunnel.TeTunnel;
+import org.onosproject.tetunnel.api.tunnel.path.TeRouteSubobject;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * PCE which calculates paths for TE tunnels.
+ */
+public interface TeTunnelPce {
+
+ static final int PRIORITY_HIGHEST = 255;
+ static final int PRIORITY_HIGH = PRIORITY_HIGHEST * 3 / 4;
+ static final int PRIORITY_MEDIUM = PRIORITY_HIGHEST / 2;
+ static final int PRIORITY_LOW = PRIORITY_HIGHEST / 4;
+ static final int PRIORITY_LOWEST = 0;
+
+ /**
+ * Returns priority of this PCE.
+ *
+ * @return priority of this PCE
+ */
+ int getPriority();
+
+ /**
+ * Signifies whether this PCE is suitable for the specified TE tunnel.
+ *
+ * @param teTunnel tunnel to check
+ * @return true if this PCE can calculate path for the TE tunnel
+ */
+ boolean isSuitable(TeTunnel teTunnel);
+
+ /**
+ * Calculates available paths for the specified TE tunnel.
+ *
+ * @param teTunnel tunnel information to be calculated
+ * @return available paths for the specified TE tunnel
+ */
+ Collection<List<TeRouteSubobject>> computePaths(TeTunnel teTunnel);
+}
diff --git a/apps/actn-mdsc/tetunnel-pce/src/main/java/org/onosproject/actn/mdsc/pce/TeTunnelPceService.java b/apps/actn-mdsc/tetunnel-pce/src/main/java/org/onosproject/actn/mdsc/pce/TeTunnelPceService.java
new file mode 100755
index 0000000..a3d10f3
--- /dev/null
+++ b/apps/actn-mdsc/tetunnel-pce/src/main/java/org/onosproject/actn/mdsc/pce/TeTunnelPceService.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.actn.mdsc.pce;
+
+import org.onosproject.tetunnel.api.tunnel.TeTunnel;
+import org.onosproject.tetunnel.api.tunnel.path.TeRouteSubobject;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * TE tunnel PCE management API.
+ */
+public interface TeTunnelPceService {
+
+ /**
+ * Calculates available paths for the specified TE tunnel.
+ * <p>
+ * PCE which is suitable for the specified TE tunnel and with the highest
+ * priority will be chosen for the path calculation.
+ *
+ * @param teTunnel tunnel information to be calculated
+ * @return available paths for the specified TE tunnel
+ */
+ Collection<List<TeRouteSubobject>> computePaths(TeTunnel teTunnel);
+
+ /**
+ * Calculates available paths for the specified TE tunnel with specified
+ * PCE.
+ *
+ * @param teTunnel tunnel information to be calculated
+ * @param pce PCE to be used for path calculation
+ * @return available paths for the specified TE tunnel
+ */
+ Collection<List<TeRouteSubobject>> computePaths(TeTunnel teTunnel,
+ TeTunnelPce pce);
+
+ /**
+ * Registers a new pce.
+ *
+ * @param pce new PCE to be registered.
+ */
+ void registerPce(TeTunnelPce pce);
+}
diff --git a/apps/actn-mdsc/tetunnel-pce/src/main/java/org/onosproject/actn/mdsc/pce/impl/DefaultTeTunnelPce.java b/apps/actn-mdsc/tetunnel-pce/src/main/java/org/onosproject/actn/mdsc/pce/impl/DefaultTeTunnelPce.java
new file mode 100755
index 0000000..9afdf89
--- /dev/null
+++ b/apps/actn-mdsc/tetunnel-pce/src/main/java/org/onosproject/actn/mdsc/pce/impl/DefaultTeTunnelPce.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.actn.mdsc.pce.impl;
+
+import org.onosproject.actn.mdsc.pce.TeTunnelPce;
+import org.onosproject.tetunnel.api.tunnel.TeTunnel;
+import org.onosproject.tetunnel.api.tunnel.path.TeRouteSubobject;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * Default implementation of TE tunnel PCE.
+ */
+class DefaultTeTunnelPce implements TeTunnelPce {
+ @Override
+ public int getPriority() {
+ return PRIORITY_LOWEST - 1;
+ }
+
+ @Override
+ public boolean isSuitable(TeTunnel teTunnel) {
+ return true;
+ }
+
+ @Override
+ public Collection<List<TeRouteSubobject>> computePaths(TeTunnel teTunnel) {
+ //TODO
+ return null;
+ }
+}
diff --git a/apps/actn-mdsc/tetunnel-pce/src/main/java/org/onosproject/actn/mdsc/pce/impl/TeTunnelPceManager.java b/apps/actn-mdsc/tetunnel-pce/src/main/java/org/onosproject/actn/mdsc/pce/impl/TeTunnelPceManager.java
new file mode 100755
index 0000000..68c2af5
--- /dev/null
+++ b/apps/actn-mdsc/tetunnel-pce/src/main/java/org/onosproject/actn/mdsc/pce/impl/TeTunnelPceManager.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.actn.mdsc.pce.impl;
+
+import com.google.common.collect.Lists;
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Service;
+import org.onosproject.actn.mdsc.pce.TeTunnelPce;
+import org.onosproject.actn.mdsc.pce.TeTunnelPceService;
+import org.onosproject.tetunnel.api.tunnel.TeTunnel;
+import org.onosproject.tetunnel.api.tunnel.path.TeRouteSubobject;
+import org.slf4j.Logger;
+import static org.slf4j.LoggerFactory.getLogger;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * Implementation of Te Tunnel PCE service.
+ */
+@Component(immediate = true)
+@Service
+public class TeTunnelPceManager implements TeTunnelPceService {
+
+ private static final Logger log = getLogger(TeTunnelPceManager.class);
+
+ private List<TeTunnelPce> pces = Lists.newLinkedList();
+
+ @Activate
+ protected void activate() {
+ pces.add(0, new DefaultTeTunnelPce());
+ log.info("Started");
+ }
+
+ @Deactivate
+ protected void deactivate() {
+ log.info("Stopped");
+ }
+
+ @Override
+ public Collection<List<TeRouteSubobject>> computePaths(TeTunnel teTunnel) {
+ TeTunnelPce pce = null;
+ synchronized (pces) {
+ for (TeTunnelPce p : pces) {
+ if (p.isSuitable(teTunnel)) {
+ pce = p;
+ }
+ }
+ }
+ return pce.computePaths(teTunnel);
+ }
+
+ @Override
+ public Collection<List<TeRouteSubobject>> computePaths(TeTunnel teTunnel,
+ TeTunnelPce pce) {
+ return pce == null ? null : pce.computePaths(teTunnel);
+ }
+
+ @Override
+ public void registerPce(TeTunnelPce pce) {
+ synchronized (pces) {
+ int index = 0;
+ while (pces.get(index).getPriority() > pce.getPriority()) {
+ index++;
+ }
+
+ pces.add(index, pce);
+ }
+ }
+}
diff --git a/apps/actn-mdsc/tetunnel-pce/src/main/java/org/onosproject/actn/mdsc/pce/impl/package-info.java b/apps/actn-mdsc/tetunnel-pce/src/main/java/org/onosproject/actn/mdsc/pce/impl/package-info.java
new file mode 100755
index 0000000..e39e884
--- /dev/null
+++ b/apps/actn-mdsc/tetunnel-pce/src/main/java/org/onosproject/actn/mdsc/pce/impl/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Implementation of TE tunnel PCE service.
+ */
+package org.onosproject.actn.mdsc.pce.impl;
\ No newline at end of file
diff --git a/apps/actn-mdsc/tetunnel-pce/src/main/java/org/onosproject/actn/mdsc/pce/package-info.java b/apps/actn-mdsc/tetunnel-pce/src/main/java/org/onosproject/actn/mdsc/pce/package-info.java
new file mode 100644
index 0000000..3f9fb11
--- /dev/null
+++ b/apps/actn-mdsc/tetunnel-pce/src/main/java/org/onosproject/actn/mdsc/pce/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * PCE service which calculates paths for TE tunnels.
+ */
+package org.onosproject.actn.mdsc.pce;
\ No newline at end of file