Provide the SPCE module 64/36964/1
authorKai GAO <gaok12@mails.tsinghua.edu.cn>
Thu, 10 Mar 2016 07:33:27 +0000 (15:33 +0800)
committerKai GAO <gaok12@mails.tsinghua.edu.cn>
Thu, 31 Mar 2016 10:32:52 +0000 (18:32 +0800)
Squashed commit of the following:

commit 2c464257d7348d0eaf34469c1832caa5cb7a6178
Merge: fdf3af1 56d6dfa
Author: Kai GAO <gaok12@mails.tsinghua.edu.cn>
Date:   Thu Mar 10 15:11:22 2016 +0800

    Merge branch 'migration' into stable/beryllium

Signed-off-by: Kai GAO <gaok12@mails.tsinghua.edu.cn>
commit 56d6dfae1321bfdf9dc8cfe36fd28ff00c8247ad
Author: Kai GAO <gaok12@mails.tsinghua.edu.cn>
Date:   Thu Mar 10 14:34:34 2016 +0800

    Prepare to import ALTO SPCE

Signed-off-by: Kai GAO <gaok12@mails.tsinghua.edu.cn>
commit 57678f1014a32a1bf4688d91a96141bd93f4f91b
Author: Jensen Zhang <Jingxuan.N.Zhang@gmail.com>
Date:   Thu Mar 3 18:03:37 2016 +0800

    Add section "Try the demo system out"

commit 334690b14f8436ea017c5f533147678391a1dfbc
Author: jensenzhang <jingxuan.n.zhang@gmail.com>
Date:   Wed Mar 2 20:15:53 2016 +0800

    Refine feature dependencies and bump version by 0.0.1

Signed-off-by: jensenzhang <jingxuan.n.zhang@gmail.com>
commit 9b4e591bc8846417aee260ee02bf4a657f28f2c9
Author: Xiao Lin <linxiao9292@outlook.com>
Date:   Thu Nov 19 03:00:15 2015 +0800

    add user guide

commit f9f2a9ed70b5f45ed747bc1fd81756794841bda1
Author: J. Austin Wang <wangjunzhuo200@gmail.com>
Date:   Sat Nov 14 21:35:39 2015 +0800

    fix a bug may cause routing error

commit 4f7465c6e290b82bfba823ccd410f26c8ce1082c
Merge: 35451fc 02cf02c
Author: J. Austin Wang <wangjunzhuo200@gmail.com>
Date:   Sat Nov 14 16:15:43 2015 +0800

    Merge branch 'master' of github.com:snlab/alto-spce

commit 35451fc19786fde84fffa880b02c1a6986b62a9b
Author: J. Austin Wang <wangjunzhuo200@gmail.com>
Date:   Sat Nov 14 16:15:12 2015 +0800

    fix a bug of path computation

commit 02cf02c73088400861534494cd440fbccf58e7e7
Author: jensenzhang <jingxuan.n.zhang@gmail.com>
Date:   Wed Nov 11 23:55:49 2015 +0800

    Refactor README.md

Signed-off-by: jensenzhang <jingxuan.n.zhang@gmail.com>
commit 19d4aead74d766843fe603a5098ef2f6e141a315
Author: J. Austin Wang <wangjunzhuo200@gmail.com>
Date:   Wed Nov 11 22:36:21 2015 +0800

    fix some typo

commit bd9e546a65db386550b2f0fc7a480ab4b364fbb9
Author: shawlinlovelife <linxiao9292@outlook.com>
Date:   Wed Nov 11 22:18:46 2015 +0800

    add Usage in README.md

commit 2ef2146fd816df56356b617aea1a6667d71a4b04
Merge: 4201928 a6df8fe
Author: fno2010 <jingxuan.n.zhang@gmail.com>
Date:   Thu Nov 12 05:54:30 2015 +0800

    Merge branch 'master' of https://github.com/snlab/alto-spce

commit 4201928007a9224cd020740cca5fca0d83df58ce
Author: fno2010 <jingxuan.n.zhang@gmail.com>
Date:   Thu Nov 12 05:49:43 2015 +0800

    Fix: deploy.sh

Signed-off-by: fno2010 <jingxuan.n.zhang@gmail.com>
commit 4943059a36ee99c224f656435554b80cea0fc93f
Merge: c507c46 41c62a2
Author: fno2010 <jingxuan.n.zhang@gmail.com>
Date:   Thu Nov 12 02:28:43 2015 +0800

    Merge branch 'master' of https://github.com/snlab/alto-spce

commit c507c46f2c9d37cc69748887cfd083a256971028
Author: fno2010 <jingxuan.n.zhang@gmail.com>
Date:   Thu Nov 12 02:28:35 2015 +0800

    Fix: Layer3 Match.

Signed-off-by: fno2010 <jingxuan.n.zhang@gmail.com>
commit 272d88976eba9ca47064f0e246e7414724f25e03
Author: fno2010 <jingxuan.n.zhang@gmail.com>
Date:   Thu Nov 12 01:14:30 2015 +0800

    Add some error handlers.

Signed-off-by: fno2010 <jingxuan.n.zhang@gmail.com>
commit a6df8fef18bfff4ad449ce797fb3e0fb7ab441e4
Author: J. Austin Wang <wangjunzhuo200@gmail.com>
Date:   Wed Nov 11 18:42:05 2015 +0800

    change copyright in xml files

commit 41c62a2ad19ec4570975961b8956c6fd906e75c2
Author: J. Austin Wang <wangjunzhuo200@gmail.com>
Date:   Wed Nov 11 17:03:16 2015 +0800

    refine the maxBandwidth algorithm

commit 8fa979a1f60e22b0eb44a617f654c3fd70049fb9
Merge: e054a3c b4bb8ba
Author: fno2010 <jingxuan.n.zhang@gmail.com>
Date:   Wed Nov 11 08:11:49 2015 +0800

    Merge branch 'master' of https://github.com/snlab/alto-spce

commit e054a3c906aa51c6b23d02f38dc3a0f4f21eb5d3
Author: fno2010 <jingxuan.n.zhang@gmail.com>
Date:   Wed Nov 11 08:11:38 2015 +0800

    Fix: Regular Expression.

Signed-off-by: fno2010 <jingxuan.n.zhang@gmail.com>
commit b6d50530747d591568c0588d2a7dcfe3592533a6
Author: fno2010 <jingxuan.n.zhang@gmail.com>
Date:   Wed Nov 11 04:59:57 2015 +0800

    Add ipToIpFlow Writer.

Signed-off-by: fno2010 <jingxuan.n.zhang@gmail.com>
commit b4bb8ba0c737b9d629eaed4afdc7cb3f5f87336d
Merge: c07f6fc b6d5053
Author: J. Austin Wang <wangjunzhuo200@gmail.com>
Date:   Tue Nov 10 23:43:07 2015 +0800

    Merge branch 'master' of github.com:snlab/alto-spce

commit c07f6fc4dd889ffe9bcfe3a41b19a5e2fd73adec
Author: J. Austin Wang <wangjunzhuo200@gmail.com>
Date:   Tue Nov 10 23:10:39 2015 +0800

    add contraint to calculate path

commit 5bf764dfcedaddf3707919c0c592b8da0c694b06
Author: J. Austin Wang <wangjunzhuo200@gmail.com>
Date:   Tue Nov 10 12:14:46 2015 +0800

    fix the bug of maxBW computing

commit 124adfc9aa115c719ae192c42b83b49b05b657ed
Author: J. Austin Wang <wangjunzhuo200@gmail.com>
Date:   Tue Nov 10 02:06:57 2015 +0800

    fix some bugs with OF 13, maxBandwidth algorith needs more review

commit 75685319e1a387aa9a53b02c55d54600f9df1140
Author: J. Austin Wang <wangjunzhuo200@gmail.com>
Date:   Mon Nov 9 21:03:32 2015 +0800

    review copyright segment

commit 7951afdb11e47657d89f17ac74f2c592d8c78a2d
Author: jensenzhang <jingxuan.n.zhang@gmail.com>
Date:   Mon Nov 9 19:23:52 2015 +0800

    Fix: misspelled namespaces in config.

Signed-off-by: jensenzhang <jingxuan.n.zhang@gmail.com>
commit 750f4fcd8d36c0b88d09c103bfbf0a821208b62c
Merge: e9af7ee dbb80a7
Author: J. Austin Wang <wangjunzhuo200@gmail.com>
Date:   Mon Nov 9 17:36:59 2015 +0800

    Merge branch 'master' of github.com:snlab/alto-spce

commit e9af7ee21c12d4bd40316e39e41a5be23e7132f9
Author: J. Austin Wang <wangjunzhuo200@gmail.com>
Date:   Mon Nov 9 17:36:47 2015 +0800

    add MaxBandwidth path calculator

commit dbb80a787cf0410b9fdb5a174b1ba743752672fd
Author: jensenzhang <jingxuan.n.zhang@gmail.com>
Date:   Mon Nov 9 15:49:42 2015 +0800

    Add initial README.md and deployment script.

Signed-off-by: jensenzhang <jingxuan.n.zhang@gmail.com>
commit 39c99dc1054b2d4fc38c0041159f2acd4cbb0a50
Author: J. Austin Wang <wangjunzhuo200@gmail.com>
Date:   Mon Nov 9 15:10:57 2015 +0800

    initial a template of path calculation

commit 6f4c2a1681c1d92d61e1ab5803116fa003f3ade9
Author: fno2010 <jingxuan.n.zhang@gmail.com>
Date:   Mon Nov 9 07:43:35 2015 +0800

    Fix: miss ErrorCode.

Signed-off-by: fno2010 <jingxuan.n.zhang@gmail.com>
commit b0cb1da85d9ac0e4e52df81772c0c2a21106278a
Author: fno2010 <jingxuan.n.zhang@gmail.com>
Date:   Mon Nov 9 07:36:18 2015 +0800

    Wrap getTxBandwidth.

Signed-off-by: fno2010 <jingxuan.n.zhang@gmail.com>
commit e628fd841f04efaf9a143598ab13fbd601f69d7a
Author: fno2010 <jingxuan.n.zhang@gmail.com>
Date:   Mon Nov 9 06:08:16 2015 +0800

    Add Class PathComputation.

Signed-off-by: fno2010 <jingxuan.n.zhang@gmail.com>
commit c1f3c58961b425f4675b7c502911f30a6ac911f7
Author: fno2010 <jingxuan.n.zhang@gmail.com>
Date:   Mon Nov 9 04:57:24 2015 +0800

    Fix feature dependency.

Signed-off-by: fno2010 <jingxuan.n.zhang@gmail.com>
commit 01b50467c7af34ee8f5253aa307db10895c7ca86
Author: fno2010 <jingxuan.n.zhang@gmail.com>
Date:   Mon Nov 9 04:19:24 2015 +0800

    Add FlowManager and InventoryReader.

Signed-off-by: fno2010 <jingxuan.n.zhang@gmail.com>
commit 8d264b2017e35145ac08ba8b4757efbb638540f0
Author: J. Austin Wang <wangjunzhuo200@gmail.com>
Date:   Sun Nov 8 19:38:51 2015 +0800

    fix dependency issue for the feature of network tracker

commit 1c39a0990a6d381deec99cf35e6ceff8bfae6d2f
Author: J. Austin Wang <wangjunzhuo200@gmail.com>
Date:   Sun Nov 8 15:11:49 2015 +0800

    add AddressConverter to map IP and MAC addresses

commit 21ffa6f86e0323b7a4a3f643f4a40a5b42e7935d
Author: jensenzhang <jingxuan.n.zhang@gmail.com>
Date:   Sun Nov 8 12:16:59 2015 +0800

    Remove Flows by Path.

commit f302b80db6047b38002e0a0762ae8d8a6decee20
Author: jensenzhang <jingxuan.n.zhang@gmail.com>
Date:   Sun Nov 8 02:40:38 2015 +0800

    getTopology for SPCE.

Signed-off-by: jensenzhang <jingxuan.n.zhang@gmail.com>
commit 4621ab0408b4948e30be2cd43af93493b69830a3
Author: J. Austin Wang <wangjunzhuo200@gmail.com>
Date:   Sat Nov 7 23:40:14 2015 +0800

    provide RPC to query bandwidth

commit ac1e8f24ff4bdbbdb903c30b6892c7c145d6c124
Author: J. Austin Wang <wangjunzhuo200@gmail.com>
Date:   Sat Nov 7 23:23:58 2015 +0800

    add RPC to query TxBandwidth

commit 412fd18129633d586b9c465601ed2cdeeb1acf66
Author: jensenzhang <jingxuan.n.zhang@gmail.com>
Date:   Sat Nov 7 21:47:59 2015 +0800

    Fix: remove yang/gen from .gitignore

Signed-off-by: jensenzhang <jingxuan.n.zhang@gmail.com>
commit 48edfeef2643cf32730cbf1e2844686cbaf42125
Author: J. Austin Wang <wangjunzhuo200@gmail.com>
Date:   Sat Nov 7 18:38:18 2015 +0800

    fix dependency problem

commit 1c9e0fb4fc5cfe19637103d939ad784032e89c85
Merge: c84a84f 6dcc89f
Author: J. Austin Wang <wangjunzhuo200@gmail.com>
Date:   Sat Nov 7 18:00:54 2015 +0800

    Merge branch 'master' of github.com:snlab/alto-spce

commit c84a84f2e231b9d2c3e72d2e9467b124601b7552
Author: J. Austin Wang <wangjunzhuo200@gmail.com>
Date:   Sat Nov 7 18:00:46 2015 +0800

    add NetworkPortStatisticsService

commit 6dcc89f49fb6606d9ce2c41515736bef544cc16a
Merge: 82bf10e 93d41b1
Author: jensenzhang <jingxuan.n.zhang@gmail.com>
Date:   Sat Nov 7 17:25:17 2015 +0800

    Merge branch 'master' of https://github.com/snlab/alto-spce

commit 82bf10e7b968c1817afa05b464d9f33c1c4183e6
Author: jensenzhang <jingxuan.n.zhang@gmail.com>
Date:   Sat Nov 7 17:23:30 2015 +0800

    Add initial framework for SPCE.

Signed-off-by: jensenzhang <jingxuan.n.zhang@gmail.com>
commit 93d41b1b6d634d444cf38f42fb3fa4a4e692ba68
Author: J. Austin Wang <wangjunzhuo200@gmail.com>
Date:   Sat Nov 7 16:54:30 2015 +0800

    add network-tracker to provide topology and bandwidth

commit ca23d06f1a01dbf0cc18fe78d6680d3ef3b8faa4
Author: jensenzhang <jingxuan.n.zhang@gmail.com>
Date:   Sat Nov 7 14:36:42 2015 +0800

    Fix: YANG Model dependency.

Signed-off-by: jensenzhang <jingxuan.n.zhang@gmail.com>
commit 5e90e0a62a714228783f194e010c127105841193
Author: J. Austin Wang <wangjunzhuo200@gmail.com>
Date:   Sat Nov 7 12:44:55 2015 +0800

    add the RPC for alto-spce

commit 3373a2902bc2958a61645150151d58b10ce297d4
Author: J. Austin Wang <wangjunzhuo200@gmail.com>
Date:   Sat Nov 7 11:22:19 2015 +0800

    initial commit of alto-spec

Change-Id: I86aefda97909dbdd88f6945bbc8a21ede7bf412b
Signed-off-by: Kai GAO <gaok12@mails.tsinghua.edu.cn>
54 files changed:
.gitignore
alto-extensions/pom.xml
alto-extensions/simple-pce/README.md [new file with mode: 0644]
alto-extensions/simple-pce/UserGuide.md [new file with mode: 0644]
alto-extensions/simple-pce/api/pom.xml [new file with mode: 0644]
alto-extensions/simple-pce/api/src/main/yang/alto-spce.yang [new file with mode: 0644]
alto-extensions/simple-pce/artifacts/pom.xml [new file with mode: 0644]
alto-extensions/simple-pce/deploy.sh [new file with mode: 0755]
alto-extensions/simple-pce/features/pom.xml [new file with mode: 0644]
alto-extensions/simple-pce/features/src/main/features/features.xml [new file with mode: 0644]
alto-extensions/simple-pce/impl/pom.xml [new file with mode: 0644]
alto-extensions/simple-pce/impl/src/main/config/default-config.xml [new file with mode: 0644]
alto-extensions/simple-pce/impl/src/main/config/maven-metadata-local.xml [new file with mode: 0644]
alto-extensions/simple-pce/impl/src/main/java/org/opendaylight/alto/spce/impl/AltoSpceImpl.java [new file with mode: 0644]
alto-extensions/simple-pce/impl/src/main/java/org/opendaylight/alto/spce/impl/AltoSpceProvider.java [new file with mode: 0644]
alto-extensions/simple-pce/impl/src/main/java/org/opendaylight/alto/spce/impl/algorithm/PathComputation.java [new file with mode: 0644]
alto-extensions/simple-pce/impl/src/main/java/org/opendaylight/alto/spce/impl/algorithm/RouteViewer.java [new file with mode: 0644]
alto-extensions/simple-pce/impl/src/main/java/org/opendaylight/alto/spce/impl/util/FlowManager.java [new file with mode: 0644]
alto-extensions/simple-pce/impl/src/main/java/org/opendaylight/alto/spce/impl/util/InstanceIdentifierUtils.java [new file with mode: 0644]
alto-extensions/simple-pce/impl/src/main/java/org/opendaylight/alto/spce/impl/util/InventoryReader.java [new file with mode: 0644]
alto-extensions/simple-pce/impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/alto/spce/impl/rev141210/AltoSpceModule.java [new file with mode: 0644]
alto-extensions/simple-pce/impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/alto/spce/impl/rev141210/AltoSpceModuleFactory.java [new file with mode: 0644]
alto-extensions/simple-pce/impl/src/main/yang/alto-spce-impl.yang [new file with mode: 0644]
alto-extensions/simple-pce/impl/src/test/java/org/opendaylight/alto/spce/impl/algorithm/PathComputationTest.java [new file with mode: 0644]
alto-extensions/simple-pce/karaf/pom.xml [new file with mode: 0644]
alto-extensions/simple-pce/network-tracker/api/pom.xml [new file with mode: 0644]
alto-extensions/simple-pce/network-tracker/api/src/main/yang/network-tracker.yang [new file with mode: 0644]
alto-extensions/simple-pce/network-tracker/artifacts/pom.xml [new file with mode: 0644]
alto-extensions/simple-pce/network-tracker/config/pom.xml [new file with mode: 0644]
alto-extensions/simple-pce/network-tracker/config/src/main/config/default-config.xml [new file with mode: 0644]
alto-extensions/simple-pce/network-tracker/config/src/main/config/maven-metadata-local.xml [new file with mode: 0644]
alto-extensions/simple-pce/network-tracker/features/pom.xml [new file with mode: 0644]
alto-extensions/simple-pce/network-tracker/features/src/main/features/features.xml [new file with mode: 0644]
alto-extensions/simple-pce/network-tracker/impl/pom.xml [new file with mode: 0644]
alto-extensions/simple-pce/network-tracker/impl/src/main/config/default-config.xml [new file with mode: 0644]
alto-extensions/simple-pce/network-tracker/impl/src/main/config/maven-metadata-local.xml [new file with mode: 0644]
alto-extensions/simple-pce/network-tracker/impl/src/main/java/org/opendaylight/alto/spce/network/api/AddressConvertService.java [new file with mode: 0644]
alto-extensions/simple-pce/network-tracker/impl/src/main/java/org/opendaylight/alto/spce/network/api/NetworkPortStatisticsService.java [new file with mode: 0644]
alto-extensions/simple-pce/network-tracker/impl/src/main/java/org/opendaylight/alto/spce/network/impl/AddressConvertServiceImpl.java [new file with mode: 0644]
alto-extensions/simple-pce/network-tracker/impl/src/main/java/org/opendaylight/alto/spce/network/impl/NetworkPortStatisticsServiceImpl.java [new file with mode: 0644]
alto-extensions/simple-pce/network-tracker/impl/src/main/java/org/opendaylight/alto/spce/network/impl/NetworkTrackerProvider.java [new file with mode: 0644]
alto-extensions/simple-pce/network-tracker/impl/src/main/java/org/opendaylight/alto/spce/network/impl/NetworkTrackerRpcHandler.java [new file with mode: 0644]
alto-extensions/simple-pce/network-tracker/impl/src/main/java/org/opendaylight/alto/spce/network/util/DataHelper.java [new file with mode: 0644]
alto-extensions/simple-pce/network-tracker/impl/src/main/java/org/opendaylight/alto/spce/network/util/InstanceIdentifierUtils.java [new file with mode: 0644]
alto-extensions/simple-pce/network-tracker/impl/src/main/java/org/opendaylight/alto/spce/network/util/NetworkServiceConstants.java [new file with mode: 0644]
alto-extensions/simple-pce/network-tracker/impl/src/main/java/org/opendaylight/alto/spce/network/util/ReadDataFailedException.java [new file with mode: 0644]
alto-extensions/simple-pce/network-tracker/impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/alto/spce/impl/network/tracker/impl/rev141210/NetworkTrackerModule.java [new file with mode: 0644]
alto-extensions/simple-pce/network-tracker/impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/alto/spce/impl/network/tracker/impl/rev141210/NetworkTrackerModuleFactory.java [new file with mode: 0644]
alto-extensions/simple-pce/network-tracker/impl/src/main/yang/network-tracker-impl.yang [new file with mode: 0644]
alto-extensions/simple-pce/network-tracker/pom.xml [new file with mode: 0644]
alto-extensions/simple-pce/pom.xml [new file with mode: 0644]
alto-release-features/pom.xml
alto-release-features/src/main/features/features.xml
pom.xml

index 178c8cf3db64575e2ecc495e98990c1fba27d70f..f2475ba27c0975fcaf84e143e5cabfcd9031c94b 100644 (file)
@@ -1,40 +1,40 @@
-.NERDTreeBookmarksFile
+**/*.checkstyle
+**/*.swo
+**/*.swp
+**/logs
+**/target
+**/yang-gen-*
 *.class
+*.iml
+*.ipr
+*.iws
 *.swp
-**/target
+*.swp
+*.xmi
+*~
+.DS_STORE
+.NERDTreeBookmarksFile
+.classpath
+.externalToolBuilders
+.helper
+.idea
+.metadata
+.project
+.settings
+.zsh*
+MANIFEST.MF
 bin/
+classes
 dist
-**/logs
+eclimd.log
+maven-eclipse.xml
+out/
 products
 repository
-workspace
-*~
 target
 target-ide
-.classpath
-.project
-.settings
-MANIFEST.MF
-*.ipr
-*.iml
-*.iws
-.idea
+workspace
 xtend-gen
 yang-gen-code
 yang-gen-config
 yang-gen-sal
-yang-gen-code
-classes
-out/
-.externalToolBuilders
-maven-eclipse.xml
-.DS_STORE
-.metadata
-*.swp
-**/*.swp
-**/*.checkstyle
-**/*.swo
-.zsh*
-.helper
-eclimd.log
-*.xmi
index 9b6515a4754cb50297c954f9b708eca068b3ea7d..c73b3153bd237e554d0502df1907695b91a4bf2b 100644 (file)
@@ -16,9 +16,7 @@
   <packaging>pom</packaging>
 
   <modules>
-    <module>fs-map</module>
-    <module>fake</module>
-    <module>cli</module>
+    <module>simple-pce</module>
   </modules>
 
 </project>
diff --git a/alto-extensions/simple-pce/README.md b/alto-extensions/simple-pce/README.md
new file mode 100644 (file)
index 0000000..36b390d
--- /dev/null
@@ -0,0 +1,123 @@
+# ALTO SPCE (Simple Path Computation Engine)
+
+The ALTO SPCE module provides a simple path computation engine for ALTO and other projects. It works in the
+OpenDaylight(ODL) SDN Controller.
+
+## Installation
+
+One prerequisite for installing ALTO SPCE is that the ODL development environment should be setup by
+following [this link](https://wiki.opendaylight.org/view/GettingStarted:Development_Environment_Setup).
+
+With this prerequisite satisfied, execute `mvn clean install` in the directory of alto-spce project
+to start the installation. After the installation, you can execute `./karaf/target/assembly/bin/karaf`
+to start the alto-spce with ODL.
+
+## Deployment
+
+You can also deploy this module into a running ODL controller without stopping the controller, by
+running `./deploy.sh <distribution_directory>`, where `<distribution_directory>` is the path of your own running ODL distribution.
+
+For example, if you start your ODL controller from `/root/distribution-karaf-0.4.0-SNAPSHOT/bin/karaf`, you can use the command `./deploy.sh /root/distribution-karaf-0.4.0-SNAP`.
+
+> **NOTE:** If you have checked out the latest commit in master branch, you will need a `karaf-0.4.1-SNAPSHOT` distribution rather than `karaf-0.4.0-SNAPSHOT`.
+
+And then, you can check whether the features of alto-spce are loaded in your karaf shell as follows:
+
+```
+karaf@root()> feature:list | grep alto-spce
+```
+
+If the features are loaded, you can install them by:
+
+```
+karaf@root()> feature:install odl-alto-spce
+```
+
+**Tip:**
+
+```
+karaf@root()> log:tail
+```
+
+You could use this command to get the tailing log. If you see **AltoSpceProvider Session Initiated!**,
+it means that alto-spce has been installed successfully. 
+
+## Usage
+
+### Prerequisites
+
+Please make sure that your have configured **l2switch** correctly. Two .xml files below could be found in `/karaf/target/assembly/etc/opendaylight/karaf`.
+
+In **54-arphandler.xml**, please set
+
+```
+<is-proactive-flood-mode>false</is-proactive-flood-mode>
+```
+
+In **58-l2switchmain.xml**, please set
+
+```
+<is-learning-only-mode>true</is-learning-only-mode>
+```
+
+### Creating a network using Mininet
+
+```
+sudo mn --controller=remote,ip=<Controller IP> --mac --topo=linear,3 --switch ovsk,protocols=OpenFlow13
+```
+
+The command above will create a virtual network consisting of 3 switches. And one host is attached to each switch.
+
+### Discover hosts
+
+l2switch uses ARP packets to discover hosts. 
+
+If we use mininet, we could use `ping` to let l2switch get the ARP packets it needs. 
+
+```
+mininet> h1 ping h5
+```
+
+After this command, l2switch will discover host1 and host5.
+
+
+### Setup/Remove a path with python-odl library
+
+We have forked [python-odl](https://github.com/SPRACE/python-odl) project to support alto-spce. You could get the code [here](https://github.com/snlab/python-odl).
+
+```
+# Import essential modules.
+>>> import odl.instance
+>>> import odl.altospce
+
+# Initiate a ODLInstance object.
+>>> myodl = odl.instance.ODLInstance("http://127.0.0.1:8181",("admin","admin"))
+
+# Initiate a ALTOSpce object.
+>>> myaltospce = odl.altospce.ALTOSpce(server="http://127.0.0.1:8181",credentials=("admin","admin"),odl_instance=myodl)
+
+# Setup a path between host1(10.0.0.1) and host5(10.0.0.5)
+>>> myaltospce.path_setup(src="10.0.0.1",dst="10.0.0.5",objective_metrics=["bandwidth"])
+{'path': [u'10.0.0.5|openflow:6:3|openflow:5:3|openflow:1:1|openflow:2:1|openflow:3:1|10.0.0.1', u'10.0.0.1|openflow:3:3|openflow:2:3|openflow:1:2|openflow:5:1|openflow:6:1|10.0.0.5'], 'error-code': 'OK'}
+
+# Remove the path between host1(10.0.0.1) and host5(10.0.0.5)
+# To identify the path please use the 'path' indicated in myaltospce.path_setup
+>>> myaltospce.path_remove(["10.0.0.5|openflow:6:3|openflow:5:3|openflow:1:1|openflow:2:1|openflow:3:1|10.0.0.1","10.0.0.1|openflow:3:3|openflow:2:3|openflow:1:2|openflow:5:1|openflow:6:1|10.0.0.5"])
+{'error-code': 'OK'}
+```
+
+Enjoy your alto-spce!
+
+## Try the demo system out
+
+We have deploy a demo system in http://alto.yale.edu:8181/index.html and you can try it out. There is a brief usage:
+
+You can setup or remove a path by using `python-odl` library. Just follow the section ["Setup/Remove a path with python-odl library"](#setupremove-a-path-with-python-odl-library) and replace `127.0.0.1` by `alto.yale.edu`.
+
+Also you can send a HTTP request like the following template to query ALTO Endpoint Cost Service (ECS):
+
+```
+curl -X POST -H "Content-type: application/alto-endpointcostfilter+json" \
+    -d '{"cost-type":{"cost-mode":"numerical","cost-metric":"hopcount"},"endpoints":{"srcs":[<SOURCE_IP_LIST>],"dsts":[<DESTINATION_IP_LIST>]}}' \
+    http://alto.yale.edu:8181/alto/endpointcost/default
+```
diff --git a/alto-extensions/simple-pce/UserGuide.md b/alto-extensions/simple-pce/UserGuide.md
new file mode 100644 (file)
index 0000000..9738c06
--- /dev/null
@@ -0,0 +1,51 @@
+# ALTO SPCE (Simple Path Computation Engine) User Guide
+
+The ALTO SPCE module provides a simple path computation engine for ALTO and other projects. It works in the
+OpenDaylight(ODL) SDN Controller.
+
+## Step 1. Download alto-spce kar
+
+```
+$ wget https://github.com/snlab/alto-spce/releases/download/1.0.0/alto-spce-features-1.0.0-SNAPSHOT.kar
+```
+
+## Step 2. Deploy alto-spce into a running OpenDaylight controller
+```
+$ DISTRO_DIR=<odl_distribution_directory>
+$ cp alto-spce-features-1.0.0-SNAPSHOT.kar $DISTRO_DIR/deploy/
+$ mkdir tmp
+$ unzip alto-spce-features-1.0.0-SNAPSHOT.kar -d tmp
+$ cp -r tmp/repository/org $DISTRO_DIR/system/
+$ rm -rf tmp
+```
+
+## Sept 3. Install the newer version of python-odl to include the two alto-spce methods:
+```
+$ git clone https://github.com/snlab/python-odl
+$ cd python-odl
+$ sudo python setup.py install
+```
+
+## Step 4. Run python-odl
+```
+$ python
+>>> import odl.instance
+>>> import odl.altospce
+
+# setup server
+>>> serverURL = "http://140.221.143.143:8080"
+>>> myodl = odl.instance.ODLInstance(serverURL, ("admin", "admin"))
+>>> myaltospce = odl.altospce.ALTOSpce(server=serverURL, credentials=("admin", "admin"), odl_instance=myodl)
+
+# Set up a path
+>>> srcIP = "198.188.136.11"
+>>> dstIP = "198.188.136.21"
+>>> mypath = myaltospce.path_setup(src=srcIP, dst=dstIP, objective_metrics=["hopcount"], constraint_metric=[{"metric": "hopcount", "min": 1, "max": 3}])
+
+# This command should return the path setup. To see it, 
+>>> print mypath['path']
+# You should see something like ["198.188.136.11|openflow:365545302388672:185|198.188.136.21",  "198.168.136.21|openflow:365545302388672:185|198.168.136.11"]
+
+# Remove the path setup above, for example, after showing the path on UI,
+>>> myaltospce.path_remove(mypath['path'])
+```
diff --git a/alto-extensions/simple-pce/api/pom.xml b/alto-extensions/simple-pce/api/pom.xml
new file mode 100644 (file)
index 0000000..377baa1
--- /dev/null
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2015 SNLAB 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
+-->
+<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.mdsal</groupId>
+    <artifactId>binding-parent</artifactId>
+    <version>0.9.0-SNAPSHOT</version>
+    <relativePath/>
+  </parent>
+
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.opendaylight.alto.ext</groupId>
+  <artifactId>alto-spce-api</artifactId>
+  <version>0.3.0-SNAPSHOT</version>
+  <packaging>bundle</packaging>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.opendaylight.mdsal.model</groupId>
+      <artifactId>yang-ext</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.mdsal.model</groupId>
+      <artifactId>ietf-inet-types</artifactId>
+    </dependency>
+  </dependencies>
+</project>
diff --git a/alto-extensions/simple-pce/api/src/main/yang/alto-spce.yang b/alto-extensions/simple-pce/api/src/main/yang/alto-spce.yang
new file mode 100644 (file)
index 0000000..7b5b883
--- /dev/null
@@ -0,0 +1,92 @@
+module alto-spce {
+    yang-version 1;
+    namespace "urn:opendaylight:alto:spce";
+    prefix "alto-spce";
+
+    import ietf-inet-types {prefix inet;}
+
+    organization "SNLab.";
+    contact "Jensen Zhang <jingxuan.zhang@gmail.com>";
+
+    revision "2015-11-06" {
+        description "Initial revision of alto-spce model. The model is based
+        on PCEP (https://tools.ietf.org/rfc/rfc5440.txt) but with simplifications.
+        A key simplification is that it does not specify whether it is re-optimization
+        or a new request. We expect the next version to fix the issue.";
+    }
+
+    typedef error-code-type {
+        type enumeration {
+            enum OK;
+            enum ERROR;
+        }
+    }
+
+    typedef alto-spce-metric {
+        type enumeration {
+            enum bandwidth;
+            enum hopcount;
+        }
+    }
+
+    rpc alto-spce-setup {
+        description "Given the endpoints, this service computes a path
+           satisfying the constraints; among those satisfying the constraints, 
+           it computes the one with the best object metrics. If a path is 
+           found, the service will setup the path by installing flow rules 
+           in FRM. This service does not handle the complexity of re-route.";
+
+        input {
+            container endpoint {
+                leaf src {
+                    type inet:ipv4-address;
+                    mandatory true;
+                    description "Source IP address";
+                }
+                leaf dst {
+                    type inet:ipv4-address;
+                    mandatory true;
+                    description "Destination IP address";
+                } 
+            }
+            leaf-list objective-metrics {
+                type alto-spce-metric;
+            }
+            list constraint-metric {
+                leaf metric {
+                    type alto-spce-metric;
+                }
+                leaf min {
+                    type uint64;
+                    description "We use min and max to allow more flexible range spec.";
+                }
+                leaf max {
+                    type uint64;
+                }
+            }
+        }
+
+        output {
+           leaf path {
+               type string;
+           }
+           leaf error-code {
+               type error-code-type;
+           }
+        }
+    }
+
+    rpc alto-spce-remove {
+        input {
+            leaf path {
+                type string;
+            }
+        }
+
+        output {
+            leaf error-code {
+                type error-code-type;
+            }
+        }
+    }
+}
diff --git a/alto-extensions/simple-pce/artifacts/pom.xml b/alto-extensions/simple-pce/artifacts/pom.xml
new file mode 100644 (file)
index 0000000..390e523
--- /dev/null
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2015 SNLAB 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
+-->
+
+<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>
+  <groupId>org.opendaylight.alto.ext</groupId>
+  <artifactId>alto-spce-artifacts</artifactId>
+  <version>0.3.0-SNAPSHOT</version>
+  <packaging>pom</packaging>
+
+  <dependencyManagement>
+    <dependencies>
+      <dependency>
+        <groupId>${project.groupId}</groupId>
+        <artifactId>alto-spce-api</artifactId>
+        <version>${project.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>${project.groupId}</groupId>
+        <artifactId>alto-spce-impl</artifactId>
+        <version>${project.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>${project.groupId}</groupId>
+        <artifactId>alto-spce-features</artifactId>
+        <version>${project.version}</version>
+        <classifier>features</classifier>
+        <type>xml</type>
+      </dependency>
+    </dependencies>
+  </dependencyManagement>
+</project>
diff --git a/alto-extensions/simple-pce/deploy.sh b/alto-extensions/simple-pce/deploy.sh
new file mode 100755 (executable)
index 0000000..0c26ec8
--- /dev/null
@@ -0,0 +1,7 @@
+DISTRO_DIR=$1
+
+cp features/target/alto-spce-features-1.0.0-SNAPSHOT.kar $DISTRO_DIR/deploy/
+mkdir tmp
+unzip features/target/alto-spce-features-1.0.0-SNAPSHOT.kar -d tmp
+cp -r tmp/repository/org $DISTRO_DIR/system/
+rm -rf tmp
diff --git a/alto-extensions/simple-pce/features/pom.xml b/alto-extensions/simple-pce/features/pom.xml
new file mode 100644 (file)
index 0000000..761c5fb
--- /dev/null
@@ -0,0 +1,252 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2015 SNLAB 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 INTERNAL
+-->
+<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.odlparent</groupId>
+    <artifactId>features-parent</artifactId>
+    <version>1.7.0-SNAPSHOT</version>
+    <relativePath/>
+  </parent>
+  <groupId>org.opendaylight.alto.ext</groupId>
+  <artifactId>alto-spce-features</artifactId>
+  <version>0.3.0-SNAPSHOT</version>
+  <name>${project.artifactId}</name>
+  <modelVersion>4.0.0</modelVersion>
+  <prerequisites>
+    <maven>3.1.1</maven>
+  </prerequisites>
+  <properties>
+    <mdsal.model.version>0.9.0-SNAPSHOT</mdsal.model.version>
+    <mdsal.version>1.4.0-SNAPSHOT</mdsal.version>
+    <restconf.version>1.4.0-SNAPSHOT</restconf.version>
+    <yangtools.version>0.9.0-SNAPSHOT</yangtools.version>
+    <dlux.version>0.4.0-SNAPSHOT</dlux.version>
+    <openflow.plugin.version>0.3.0-SNAPSHOT</openflow.plugin.version>
+    <l2switch.version>0.4.0-SNAPSHOT</l2switch.version>
+    <configfile.directory>etc/opendaylight/karaf</configfile.directory>
+    <config.packethandler.configfile>50-packethandler.xml</config.packethandler.configfile>
+    <config.loopremover.configfile>52-loopremover.xml</config.loopremover.configfile>
+    <config.arphandler.configfile>54-arphandler.xml</config.arphandler.configfile>
+    <config.addresstracker.configfile>56-addresstracker.xml</config.addresstracker.configfile>
+    <config.hosttracker.configfile>57-hosttracker.xml</config.hosttracker.configfile>
+  </properties>
+  <dependencyManagement>
+    <dependencies>
+      <!-- project specific dependencies -->
+      <dependency>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>mdsal-artifacts</artifactId>
+        <version>${mdsal.version}</version>
+        <type>pom</type>
+        <scope>import</scope>
+      </dependency>
+      <dependency>
+        <groupId>org.opendaylight.netconf</groupId>
+        <artifactId>restconf-artifacts</artifactId>
+        <version>${restconf.version}</version>
+        <type>pom</type>
+        <scope>import</scope>
+      </dependency>
+      <dependency>
+        <groupId>org.opendaylight.l2switch</groupId>
+        <artifactId>l2switch-artifacts</artifactId>
+        <version>${l2switch.version}</version>
+        <scope>import</scope>
+        <type>pom</type>
+      </dependency>
+    </dependencies>
+  </dependencyManagement>
+  <dependencies>
+    <dependency>
+      <groupId>org.opendaylight.yangtools</groupId>
+      <artifactId>features-yangtools</artifactId>
+      <classifier>features</classifier>
+      <version>${yangtools.version}</version>
+      <type>xml</type>
+      <scope>runtime</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.mdsal.model</groupId>
+      <artifactId>features-mdsal-model</artifactId>
+      <version>${mdsal.model.version}</version>
+      <classifier>features</classifier>
+      <type>xml</type>
+      <scope>runtime</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>features-mdsal</artifactId>
+      <classifier>features</classifier>
+      <version>${mdsal.version}</version>
+      <type>xml</type>
+      <scope>runtime</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.netconf</groupId>
+      <artifactId>features-restconf</artifactId>
+      <classifier>features</classifier>
+      <version>${restconf.version}</version>
+      <type>xml</type>
+      <scope>runtime</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.dlux</groupId>
+      <artifactId>features-dlux</artifactId>
+      <classifier>features</classifier>
+      <version>${dlux.version}</version>
+      <type>xml</type>
+      <scope>runtime</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.openflowplugin</groupId>
+      <artifactId>features-openflowplugin</artifactId>
+      <classifier>features</classifier>
+      <version>${openflow.plugin.version}</version>
+      <type>xml</type>
+      <scope>runtime</scope>
+    </dependency>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>alto-spce-impl</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>alto-spce-impl</artifactId>
+      <version>${project.version}</version>
+      <type>xml</type>
+      <classifier>config</classifier>
+    </dependency>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>alto-spce-api</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+
+    <dependency>
+      <groupId>org.opendaylight.l2switch</groupId>
+      <artifactId>features-l2switch</artifactId>
+      <classifier>features</classifier>
+      <version>${l2switch.version}</version>
+      <type>xml</type>
+      <scope>runtime</scope>
+    </dependency>
+
+    <!-- bundles used by features directly -->
+    <dependency>
+      <groupId>org.opendaylight.l2switch.packethandler</groupId>
+      <artifactId>packethandler-model</artifactId>
+      <version>${l2switch.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.l2switch.packethandler</groupId>
+      <artifactId>packethandler-impl</artifactId>
+      <version>${l2switch.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.l2switch.packethandler</groupId>
+      <artifactId>packethandler-config</artifactId>
+      <version>${l2switch.version}</version>
+      <type>xml</type>
+      <classifier>config</classifier>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.l2switch.addresstracker</groupId>
+      <artifactId>addresstracker-model</artifactId>
+      <version>${l2switch.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.l2switch.addresstracker</groupId>
+      <artifactId>addresstracker-config</artifactId>
+      <version>${l2switch.version}</version>
+      <type>xml</type>
+      <classifier>config</classifier>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.l2switch.addresstracker</groupId>
+      <artifactId>addresstracker-impl</artifactId>
+      <version>${l2switch.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.l2switch.loopremover</groupId>
+      <artifactId>loopremover-model</artifactId>
+      <version>${l2switch.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.l2switch.loopremover</groupId>
+      <artifactId>loopremover-impl</artifactId>
+      <version>${l2switch.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.l2switch.loopremover</groupId>
+      <artifactId>loopremover-config</artifactId>
+      <version>${l2switch.version}</version>
+      <type>xml</type>
+      <classifier>config</classifier>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.l2switch.hosttracker</groupId>
+      <artifactId>hosttracker-model</artifactId>
+      <version>${l2switch.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.l2switch.hosttracker</groupId>
+      <artifactId>hosttracker-impl</artifactId>
+      <version>${l2switch.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.l2switch.hosttracker</groupId>
+      <artifactId>hosttracker-config</artifactId>
+      <version>${l2switch.version}</version>
+      <type>xml</type>
+      <classifier>config</classifier>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.l2switch.arphandler</groupId>
+      <artifactId>arphandler-impl</artifactId>
+      <version>${l2switch.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.alto.spce.network</groupId>
+      <artifactId>network-tracker-config</artifactId>
+      <version>${l2switch.version}</version>
+      <type>xml</type>
+      <classifier>config</classifier>
+    </dependency>
+
+    <dependency>
+      <groupId>org.opendaylight.alto.spce.network</groupId>
+      <artifactId>network-tracker-impl</artifactId>
+      <version>${project.version}</version>
+      <scope>runtime</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.alto.spce.network</groupId>
+      <artifactId>network-tracker-impl</artifactId>
+      <version>${project.version}</version>
+      <type>xml</type>
+      <classifier>config</classifier>
+      <scope>runtime</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.alto.spce.network</groupId>
+      <artifactId>network-tracker-api</artifactId>
+      <version>${project.version}</version>
+      <scope>runtime</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.opendaylight.controller.model</groupId>
+      <artifactId>model-inventory</artifactId>
+      <version>${mdsal.version}</version>
+      <type>jar</type>
+    </dependency>
+
+  </dependencies>
+</project>
diff --git a/alto-extensions/simple-pce/features/src/main/features/features.xml b/alto-extensions/simple-pce/features/src/main/features/features.xml
new file mode 100644 (file)
index 0000000..47ec29b
--- /dev/null
@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+Copyright Â© 2015 Copyright (c) 2015 Tongji University 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
+-->
+<features name="odl-alto-spce-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.2.0"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.2.0 http://karaf.apache.org/xmlns/features/v1.2.0">
+  <repository>mvn:org.opendaylight.yangtools/features-yangtools/${yangtools.version}/xml/features</repository>
+  <repository>mvn:org.opendaylight.controller/features-mdsal/${mdsal.version}/xml/features</repository>
+  <repository>mvn:org.opendaylight.mdsal.model/features-mdsal-model/${mdsal.model.version}/xml/features</repository>
+  <repository>mvn:org.opendaylight.netconf/features-restconf/${restconf.version}/xml/features</repository>
+  <repository>mvn:org.opendaylight.dlux/features-dlux/${dlux.version}/xml/features</repository>
+  <repository>mvn:org.opendaylight.openflowplugin/features-openflowplugin/${openflow.plugin.version}/xml/features</repository>
+  <repository>mvn:org.opendaylight.l2switch/features-l2switch/${l2switch.version}/xml/features</repository>
+  <feature name='odl-network-tracker-api' version='${project.version}' description='OpenDaylight :: network-tracker :: api'>
+    <feature version='${mdsal.model.version}'>odl-mdsal-models</feature>
+    <bundle>mvn:org.opendaylight.alto.spce.network/network-tracker-api/${project.version}</bundle>
+  </feature>
+
+  <feature name='odl-network-tracker' version='${project.version}' description='OpenDaylight :: network-tracker'>
+    <feature version='${mdsal.version}'>odl-mdsal-broker</feature>
+    <feature version='${l2switch.version}'>odl-network-tracker-l2switch</feature>
+    <feature version='${project.version}'>odl-network-tracker-api</feature>
+    <bundle>mvn:org.opendaylight.alto.spce.network/network-tracker-impl/${project.version}</bundle>
+    <configfile finalname="${configfile.directory}/network-tracker.xml">mvn:org.opendaylight.alto.spce.network/network-tracker-impl/${project.version}/xml/config</configfile>
+  </feature>
+
+  <feature name='odl-network-tracker-l2switch' version='${l2switch.version}' description='OpenDaylight :: network-tracker :: L2switch Wrapper'>
+    <feature version="${openflow.plugin.version}">odl-openflowplugin-flow-services</feature>
+    <feature version="${openflow.plugin.version}">odl-openflowplugin-southbound</feature>
+    <bundle>mvn:org.opendaylight.l2switch.hosttracker/hosttracker-model/${l2switch.version}</bundle>
+    <bundle>mvn:org.opendaylight.l2switch.hosttracker/hosttracker-impl/${l2switch.version}</bundle>
+    <configfile finalname="${configfile.directory}/${config.hosttracker.configfile}">mvn:org.opendaylight.l2switch.hosttracker/hosttracker-config/${l2switch.version}/xml/config</configfile>
+
+    <bundle>mvn:org.opendaylight.l2switch.addresstracker/addresstracker-model/${l2switch.version}</bundle>
+    <bundle>mvn:org.opendaylight.l2switch.addresstracker/addresstracker-impl/${l2switch.version}</bundle>
+    <configfile finalname="${configfile.directory}/${config.addresstracker.configfile}">mvn:org.opendaylight.l2switch.addresstracker/addresstracker-config/${l2switch.version}/xml/config</configfile>
+
+    <bundle>mvn:org.opendaylight.l2switch.arphandler/arphandler-impl/${l2switch.version}</bundle>
+    <configfile finalname="${configfile.directory}/${config.arphandler.configfile}">mvn:org.opendaylight.alto.spce.network/network-tracker-config/${l2switch.version}/xml/config</configfile>
+
+    <bundle>mvn:org.opendaylight.l2switch.packethandler/packethandler-model/${l2switch.version}</bundle>
+    <bundle>mvn:org.opendaylight.l2switch.packethandler/packethandler-impl/${l2switch.version}</bundle>
+    <configfile finalname="${configfile.directory}/${config.packethandler.configfile}">mvn:org.opendaylight.l2switch.packethandler/packethandler-config/${l2switch.version}/xml/config</configfile>
+
+    <bundle>mvn:org.opendaylight.l2switch.loopremover/loopremover-model/${l2switch.version}</bundle>
+    <bundle>mvn:org.opendaylight.l2switch.loopremover/loopremover-impl/${l2switch.version}</bundle>
+    <bundle>mvn:org.opendaylight.controller.thirdparty/net.sf.jung2/2.0.1</bundle>
+    <configfile finalname="${configfile.directory}/${config.loopremover.configfile}">mvn:org.opendaylight.l2switch.loopremover/loopremover-config/${l2switch.version}/xml/config</configfile>
+  </feature>
+
+  <feature name='odl-network-tracker-rest' version='${project.version}' description='OpenDaylight :: network-tracker :: REST'>
+    <feature version="${project.version}">odl-network-tracker</feature>
+    <feature version="${restconf.version}">odl-restconf</feature>
+  </feature>
+
+  <feature name='odl-network-tracker-ui' version='${project.version}' description='OpenDaylight :: network-tracker :: UI'>
+    <feature version="${project.version}">odl-network-tracker-rest</feature>
+    <feature version="${restconf.version}">odl-mdsal-apidocs</feature>
+    <feature version="${mdsal.version}">odl-mdsal-xsql</feature>
+    <feature version="${dlux.version}">odl-dlux-yangui</feature>
+  </feature>
+
+  <feature name='odl-alto-spce-api' version='${project.version}' description='OpenDaylight :: alto-spce :: api'>
+    <feature version='${mdsal.model.version}'>odl-mdsal-models</feature>
+    <bundle>mvn:org.opendaylight.alto/alto-spce-api/${project.version}</bundle>
+  </feature>
+  <feature name='odl-alto-spce' version='${project.version}' description='OpenDaylight :: alto-spce'>
+    <feature version='${mdsal.version}'>odl-mdsal-broker</feature>
+    <feature version='${openflow.plugin.version}'>odl-openflowplugin-southbound</feature>
+    <feature version='${openflow.plugin.version}'>odl-openflowplugin-flow-services</feature>
+    <feature version='${project.version}'>odl-alto-spce-api</feature>
+    <feature version='${project.version}'>odl-network-tracker</feature>
+    <bundle>mvn:org.opendaylight.alto/alto-spce-impl/${project.version}</bundle>
+    <configfile finalname="${configfile.directory}/alto-spce.xml">mvn:org.opendaylight.alto/alto-spce-impl/${project.version}/xml/config</configfile>
+  </feature>
+  <feature name='odl-alto-spce-rest' version='${project.version}' description='OpenDaylight :: alto-spce :: REST'>
+    <feature version="${project.version}">odl-alto-spce</feature>
+    <feature version="${restconf.version}">odl-restconf</feature>
+  </feature>
+  <feature name='odl-alto-spce-ui' version='${project.version}' description='OpenDaylight :: alto-spce :: UI'>
+    <feature version="${project.version}">odl-alto-spce-rest</feature>
+    <feature version="${restconf.version}">odl-mdsal-apidocs</feature>
+    <feature version="${mdsal.version}">odl-mdsal-xsql</feature>
+    <feature version="${dlux.version}">odl-dlux-yangui</feature>
+  </feature>
+
+</features>
diff --git a/alto-extensions/simple-pce/impl/pom.xml b/alto-extensions/simple-pce/impl/pom.xml
new file mode 100644 (file)
index 0000000..c8248c9
--- /dev/null
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2015 SNLAB 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
+-->
+<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.controller</groupId>
+    <artifactId>config-parent</artifactId>
+    <version>0.5.0-SNAPSHOT</version>
+    <relativePath/>
+  </parent>
+
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.opendaylight.alto.ext</groupId>
+  <artifactId>alto-spce-impl</artifactId>
+  <version>0.3.0-SNAPSHOT</version>
+  <packaging>bundle</packaging>
+
+  <properties>
+    <openflow.plugin.version>0.3.0-SNAPSHOT</openflow.plugin.version>
+    <mdsal.version>1.4.0-SNAPSHOT</mdsal.version>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>alto-spce-api</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.alto.spce.network</groupId>
+      <artifactId>network-tracker-impl</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.alto.spce.network</groupId>
+      <artifactId>network-tracker-api</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.openflowplugin.model</groupId>
+      <artifactId>model-flow-service</artifactId>
+      <version>${openflow.plugin.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller.model</groupId>
+      <artifactId>model-topology</artifactId>
+      <version>${mdsal.version}</version>
+    </dependency>
+
+    <!-- Testing Dependencies -->
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <scope>test</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.mockito</groupId>
+      <artifactId>mockito-all</artifactId>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+
+</project>
diff --git a/alto-extensions/simple-pce/impl/src/main/config/default-config.xml b/alto-extensions/simple-pce/impl/src/main/config/default-config.xml
new file mode 100644 (file)
index 0000000..a233322
--- /dev/null
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+Copyright Â© 2015 Copyright (c) 2015 Tongji University 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
+-->
+<snapshot>
+  <required-capabilities>
+      <capability>urn:opendaylight:alto:spce:impl?module=alto-spce-impl&amp;revision=2014-12-10</capability>
+      <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding?module=opendaylight-md-sal-binding&amp;revision=2013-10-28</capability>
+  </required-capabilities>
+  <configuration>
+
+    <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+      <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+        <module>
+          <type xmlns:prefix="urn:opendaylight:alto:spce:impl">prefix:alto-spce</type>
+          <name>alto-spce-default</name>
+          <broker>
+            <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-broker-osgi-registry</type>
+            <name>binding-osgi-broker</name>
+          </broker>
+        </module>
+      </modules>
+    </data>
+  </configuration>
+</snapshot>
diff --git a/alto-extensions/simple-pce/impl/src/main/config/maven-metadata-local.xml b/alto-extensions/simple-pce/impl/src/main/config/maven-metadata-local.xml
new file mode 100644 (file)
index 0000000..25834ec
--- /dev/null
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<metadata modelVersion="1.1.0">
+  <groupId>org.opendaylight.alto.ext</groupId>
+  <artifactId>alto-spce-impl</artifactId>
+  <version>1.0.0-SNAPSHOT</version>
+  <versioning>
+    <snapshot>
+      <localCopy>true</localCopy>
+    </snapshot>
+    <lastUpdated>20151107031204</lastUpdated>
+    <snapshotVersions>
+      <snapshotVersion>
+        <classifier>config</classifier>
+        <extension>xml</extension>
+        <value>1.0.0-SNAPSHOT</value>
+        <updated>20151107031204</updated>
+      </snapshotVersion>
+    </snapshotVersions>
+  </versioning>
+</metadata>
diff --git a/alto-extensions/simple-pce/impl/src/main/java/org/opendaylight/alto/spce/impl/AltoSpceImpl.java b/alto-extensions/simple-pce/impl/src/main/java/org/opendaylight/alto/spce/impl/AltoSpceImpl.java
new file mode 100644 (file)
index 0000000..4357895
--- /dev/null
@@ -0,0 +1,344 @@
+/*
+ * Copyright (c) 2015 SNLAB 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.alto.spce.impl;
+
+import com.google.common.base.Optional;
+import org.opendaylight.alto.spce.impl.algorithm.PathComputation;
+import org.opendaylight.alto.spce.impl.util.FlowManager;
+import org.opendaylight.alto.spce.impl.util.InventoryReader;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev151106.AltoSpceMetric;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev151106.AltoSpceRemoveInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev151106.AltoSpceRemoveOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev151106.AltoSpceRemoveOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev151106.AltoSpceService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev151106.AltoSpceSetupInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev151106.AltoSpceSetupOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev151106.AltoSpceSetupOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev151106.ErrorCodeType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev151106.alto.spce.setup.input.ConstraintMetric;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev151106.alto.spce.setup.input.ConstraintMetricBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev151106.alto.spce.setup.input.Endpoint;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.EtherType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetDestinationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetSourceBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetTypeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4MatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.tracker.rev151107.AltoSpceGetMacByIpInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.tracker.rev151107.AltoSpceGetMacByIpInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.tracker.rev151107.AltoSpceGetMacByIpOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.tracker.rev151107.NetworkTrackerService;
+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.TpId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.math.BigInteger;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+public class AltoSpceImpl implements AltoSpceService {
+
+    private static final Logger LOG = LoggerFactory.getLogger(FlowManager.class);
+    private SalFlowService salFlowService;
+    private NetworkTrackerService networkTrackerService;
+    private DataBroker dataBroker;
+    private FlowManager flowManager;
+    private InventoryReader inventoryReader;
+    private PathComputation pathComputation;
+
+    public AltoSpceImpl(SalFlowService salFlowService,
+                        NetworkTrackerService networkTrackerService,
+                        DataBroker dataBroker) {
+        this.salFlowService = salFlowService;
+        this.networkTrackerService = networkTrackerService;
+        this.dataBroker = dataBroker;
+        this.flowManager = new FlowManager(salFlowService);
+        this.inventoryReader = new InventoryReader(dataBroker);
+        this.pathComputation = new PathComputation(networkTrackerService);
+    }
+
+    public Future<RpcResult<AltoSpceRemoveOutput>> altoSpceRemove(AltoSpceRemoveInput input) {
+        String path = input.getPath();
+        ErrorCodeType errorCode = removePath(path);
+
+        AltoSpceRemoveOutput output = new AltoSpceRemoveOutputBuilder()
+                .setErrorCode(errorCode)
+                .build();
+        return RpcResultBuilder.success(output).buildFuture();
+    }
+
+    public Future<RpcResult<AltoSpceSetupOutput>> altoSpceSetup(AltoSpceSetupInput input) {
+        Endpoint endpoint = input.getEndpoint();
+        List<AltoSpceMetric> altoSpceMetrics = input.getObjectiveMetrics();
+        List<ConstraintMetric> constraintMetrics = compressConstraint(input.getConstraintMetric());
+        List<TpId> path = null;
+        ErrorCodeType errorCode = ErrorCodeType.ERROR;
+
+        if (constraintMetrics != null) {
+            path = computePath(endpoint, altoSpceMetrics, constraintMetrics);
+            errorCode = setupPath(endpoint, path);
+        }
+
+        AltoSpceSetupOutput output = new AltoSpceSetupOutputBuilder()
+                .setPath(pathToString(endpoint, path))
+                .setErrorCode(errorCode)
+                .build();
+        return RpcResultBuilder.success(output).buildFuture();
+    }
+
+    private List<ConstraintMetric> compressConstraint(List<ConstraintMetric> constraintMetrics) {
+        if (constraintMetrics == null)
+            return null;
+        List<ConstraintMetric> compressedConstraintMetrics = new LinkedList<>();
+        BigInteger minHopcount = BigInteger.ZERO;
+        BigInteger maxHopcount = BigInteger.valueOf(Long.MAX_VALUE);
+        BigInteger minBandwidth = BigInteger.ZERO;
+        BigInteger maxBandwidth = BigInteger.valueOf(Long.MAX_VALUE);
+        for (ConstraintMetric constraintMetric : constraintMetrics) {
+            if (constraintMetric.getMetric() == AltoSpceMetric.Hopcount) {
+                minHopcount = minHopcount.max(constraintMetric.getMin());
+                maxHopcount = maxHopcount.min(constraintMetric.getMax());
+                if (minHopcount.compareTo(maxHopcount) == 1) {
+                    return null;
+                }
+            } else if (constraintMetric.getMetric() == AltoSpceMetric.Bandwidth) {
+                minBandwidth = minBandwidth.max(constraintMetric.getMin());
+                maxBandwidth = maxBandwidth.min(constraintMetric.getMax());
+                if (minBandwidth.compareTo(maxBandwidth) == 1) {
+                    return null;
+                }
+            }
+        }
+        compressedConstraintMetrics.add(new ConstraintMetricBuilder()
+                .setMetric(AltoSpceMetric.Hopcount)
+                .setMin(minHopcount)
+                .setMax(maxHopcount)
+                .build());
+        compressedConstraintMetrics.add(new ConstraintMetricBuilder()
+                .setMetric(AltoSpceMetric.Bandwidth)
+                .setMin(minBandwidth)
+                .setMax(maxBandwidth)
+                .build());
+        return compressedConstraintMetrics;
+    }
+
+    private Match parseMacMatch(String path) {
+        String[] tpList = path.split("\\|");
+        MacAddress srcEth = ipToMac(new Ipv4Address(tpList[0]));
+        MacAddress dstEth = ipToMac(new Ipv4Address(tpList[tpList.length - 1]));
+        if (srcEth == null | dstEth == null) {
+            return null;
+        }
+        return new MatchBuilder()
+                .setEthernetMatch(new EthernetMatchBuilder()
+                        .setEthernetSource(new EthernetSourceBuilder()
+                                .setAddress(srcEth)
+                                .build())
+                        .setEthernetDestination(new EthernetDestinationBuilder()
+                                .setAddress(dstEth)
+                                .build())
+                        .build())
+                .build();
+    }
+
+    private Match parseIpMatch(String path) {
+        String[] tpList = path.split("\\|");
+        Ipv4Prefix srcIp = new Ipv4Prefix(tpList[0] + "/32");
+        Ipv4Prefix dstIp = new Ipv4Prefix(tpList[tpList.length - 1] + "/32");
+        if (srcIp == null | dstIp == null) {
+            return null;
+        }
+        return new MatchBuilder()
+                .setLayer3Match(new Ipv4MatchBuilder()
+                        .setIpv4Source(srcIp)
+                        .setIpv4Destination(dstIp)
+                        .build())
+                .setEthernetMatch(new EthernetMatchBuilder()
+                        .setEthernetType(new EthernetTypeBuilder()
+                                .setType(new EtherType(0x0800L))
+                                .build())
+                        .build())
+                .build();
+    }
+
+    private List<TpId> parseTpIds(String path) {
+        List<TpId> tpIds = new LinkedList<>();
+        String[] tpList = path.split("\\|");
+        for (int i = 1; i < tpList.length -1; i++) {
+            tpIds.add(new TpId(tpList[i]));
+        }
+        return tpIds;
+    }
+
+    private ErrorCodeType removePath(String path) {
+        List<TpId> tpIds = parseTpIds(path);
+        Match macMatch = parseMacMatch(path);
+        Match ipMatch = parseIpMatch(path);
+        if (macMatch == null | ipMatch == null) {
+            return ErrorCodeType.ERROR;
+        }
+        try {
+            for (TpId tpId : tpIds) {
+                NodeRef nodeRef =
+                        new NodeRef(InstanceIdentifier.builder(Nodes.class)
+                                .child(Node.class, new NodeKey(
+                                        new NodeId(tpId.getValue().substring(0, tpId.getValue().lastIndexOf(":")))))
+                                .build());
+                this.salFlowService.removeFlow(new RemoveFlowInputBuilder()
+                        .setMatch(macMatch)
+                        .setNode(nodeRef)
+                        .setTransactionUri(tpId)
+                        .build()
+                );
+                this.salFlowService.removeFlow(new RemoveFlowInputBuilder()
+                        .setMatch(ipMatch)
+                        .setNode(nodeRef)
+                        .build()
+                );
+            }
+        } catch (Exception e) {
+            LOG.info("Exception occurs when remove a path: " + e.getMessage());
+            return ErrorCodeType.ERROR;
+        }
+        return ErrorCodeType.OK;
+    }
+
+    private List<TpId> computePath(Endpoint endpoint,
+                               List<AltoSpceMetric> altoSpceMetrics,
+                               List<ConstraintMetric> constraintMetrics) {
+        List<TpId> path = null;
+        TpId srcTpId = getAttachTp(endpoint.getSrc());
+        TpId dstTpId = getAttachTp(endpoint.getDst());
+        Topology topology = getTopology();
+
+        try {
+            if (altoSpceMetrics.get(0) == AltoSpceMetric.Bandwidth) {
+                path = pathComputation.maxBandwidthPath(srcTpId, dstTpId, topology, constraintMetrics);
+            } else if (altoSpceMetrics.get(0) == AltoSpceMetric.Hopcount) {
+                path = pathComputation.shortestPath(srcTpId, dstTpId, topology, constraintMetrics);
+            }
+        } catch (Exception e) {
+            LOG.info("Exception occurs when compute path: " + e.getMessage());
+        }
+
+        return path;
+    }
+
+    private TpId getAttachTp(Ipv4Address src) {
+        return this.inventoryReader.getNodeConnectorByMac(ipToMac(src));
+    }
+
+    private MacAddress ipToMac(Ipv4Address src) {
+        MacAddress mac = null;
+        AltoSpceGetMacByIpInput input = new AltoSpceGetMacByIpInputBuilder()
+                .setIpAddress(src.getValue())
+                .build();
+        Future<RpcResult<AltoSpceGetMacByIpOutput>> result = this.networkTrackerService.altoSpceGetMacByIp(input);
+        try {
+            AltoSpceGetMacByIpOutput output = result.get().getResult();
+            mac = new MacAddress(output.getMacAddress());
+        } catch (InterruptedException | ExecutionException e) {
+            LOG.info("Exception occurs when convert ip to mac: " + e.getMessage());
+        }
+        return mac;
+    }
+
+    private ErrorCodeType setupPath(Endpoint endpoint, List<TpId> path) {
+        if (path == null) {
+            LOG.info("Setup Error: path is null.");
+            return ErrorCodeType.ERROR;
+        }
+
+        try {
+            Ipv4Address srcIp = endpoint.getSrc();
+            Ipv4Address dstIp = endpoint.getDst();
+            MacAddress srcMac = ipToMac(srcIp);
+            MacAddress dstMac = ipToMac(dstIp);
+            List<NodeConnectorRef> nodeConnectorRefs = new LinkedList<>();
+            for (TpId tpid : path) {
+                String nc_value = tpid.getValue();
+                InstanceIdentifier<NodeConnector> ncid = InstanceIdentifier.builder(Nodes.class)
+                        .child(
+                                Node.class,
+                                new NodeKey(new NodeId(nc_value.substring(0, nc_value.lastIndexOf(':')))))
+                        .child(
+                                NodeConnector.class,
+                                new NodeConnectorKey(new NodeConnectorId(nc_value)))
+                        .build();
+                nodeConnectorRefs.add(new NodeConnectorRef(ncid));
+            }
+            LOG.info("Setup a path: srcIp=" + srcIp.getValue() + ", dstIp=" + dstIp.getValue());
+            LOG.info("Setup a path: srcMac=" + srcMac.getValue() + ", dstMac=" + dstMac.getValue());
+            this.flowManager.addFlowByPath(srcIp, dstIp, nodeConnectorRefs);
+            this.flowManager.addFlowByPath(srcMac, dstMac, nodeConnectorRefs);
+        } catch (Exception e) {
+            LOG.info("Exception occurs when setup a path: " + e.getMessage());
+            return ErrorCodeType.ERROR;
+        }
+        return ErrorCodeType.OK;
+    }
+
+    private String pathToString(Endpoint endpoint, List<TpId> path) {
+        String pathString = endpoint.getSrc().getValue();
+        if (path != null) {
+            for (TpId tpId : path) {
+                pathString += "|" + tpId.getValue();
+            }
+        }
+        pathString += "|" + endpoint.getDst().getValue();
+        return pathString;
+    }
+
+    private Topology getTopology() {
+        try {
+            ReadOnlyTransaction readTx = this.dataBroker.newReadOnlyTransaction();
+
+            InstanceIdentifier<Topology> topologyInstanceIdentifier = InstanceIdentifier
+                    .builder(NetworkTopology.class)
+                    .child(Topology.class, new TopologyKey(new TopologyId("flow:1")))
+                    .build();
+
+            Optional<Topology> dataFuture = readTx.read(LogicalDatastoreType.OPERATIONAL,
+                    topologyInstanceIdentifier).get();
+
+            return dataFuture.get();
+        } catch (Exception e) {
+            LOG.info("Exception occurs when get topology: " + e.getMessage());
+        }
+        return null;
+    }
+}
diff --git a/alto-extensions/simple-pce/impl/src/main/java/org/opendaylight/alto/spce/impl/AltoSpceProvider.java b/alto-extensions/simple-pce/impl/src/main/java/org/opendaylight/alto/spce/impl/AltoSpceProvider.java
new file mode 100644 (file)
index 0000000..9bb5368
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2015 SNLAB 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.alto.spce.impl;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.RpcRegistration;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
+import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev151106.AltoSpceService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.tracker.rev151107.NetworkTrackerService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class AltoSpceProvider implements BindingAwareProvider, AutoCloseable {
+
+    private static final Logger LOG = LoggerFactory.getLogger(AltoSpceProvider.class);
+    private RpcRegistration<AltoSpceService> altoSpceService;
+
+    @Override
+    public void onSessionInitiated(ProviderContext session) {
+        LOG.info("AltoSpceProvider Session Initiated!");
+        SalFlowService salFlowService = session.getRpcService(SalFlowService.class);
+        NetworkTrackerService networkTrackerService = session.getRpcService(NetworkTrackerService.class);
+        DataBroker dataBroker = session.getSALService(DataBroker.class);
+        altoSpceService = session.addRpcImplementation(AltoSpceService.class, new AltoSpceImpl(salFlowService, networkTrackerService, dataBroker));
+    }
+
+    @Override
+    public void close() throws Exception {
+        LOG.info("AltoSpceProvider Closed!");
+        if (altoSpceService != null) {
+            altoSpceService.close();
+        }
+    }
+}
diff --git a/alto-extensions/simple-pce/impl/src/main/java/org/opendaylight/alto/spce/impl/algorithm/PathComputation.java b/alto-extensions/simple-pce/impl/src/main/java/org/opendaylight/alto/spce/impl/algorithm/PathComputation.java
new file mode 100644 (file)
index 0000000..6cb18e2
--- /dev/null
@@ -0,0 +1,320 @@
+/*
+ * Copyright (c) 2015 SNLAB 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.alto.spce.impl.algorithm;
+
+import edu.uci.ics.jung.algorithms.shortestpath.DijkstraShortestPath;
+import edu.uci.ics.jung.graph.Graph;
+import edu.uci.ics.jung.graph.SparseMultigraph;
+import edu.uci.ics.jung.graph.util.EdgeType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev151106.AltoSpceMetric;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.rev151106.alto.spce.setup.input.ConstraintMetric;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.tracker.rev151107.AltoSpceGetTxBandwidthInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.tracker.rev151107.AltoSpceGetTxBandwidthInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.tracker.rev151107.AltoSpceGetTxBandwidthOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.tracker.rev151107.NetworkTrackerService;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TpId;
+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.Link;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+public class PathComputation {
+
+    private NetworkTrackerService networkTrackerService;
+    private static final Logger logger = LoggerFactory.getLogger(PathComputation.class);
+    public PathComputation(NetworkTrackerService networkTrackerService) {
+        this.networkTrackerService = networkTrackerService;
+    }
+
+    public List<TpId> shortestPath(TpId srcTpId, TpId dstTpId, Topology topology,
+                                   final List<ConstraintMetric> constraintMetrics) {
+        final RouteViewer.Path finalPath = new RouteViewer.Path();
+        finalPath.src = dstTpId;
+        finalPath.bandwidth = getBandwidthByTp(dstTpId.getValue()).longValue();
+        RouteViewer.RouteChecker checker = new RouteViewer.RouteChecker() {
+            private List<RouteViewer.Path> result;
+            private long hopcount = Long.MAX_VALUE;
+            @Override
+            public boolean isStop(List<RouteViewer.Path> pathList) {
+                LinkedList<RouteViewer.Path> tmp = new LinkedList<>(pathList);
+                tmp.add(finalPath);
+                long hopcount = tmp.size();
+                long bandwidth = getBandwidth(tmp);
+                if (constraintMetrics != null) {
+                    for (ConstraintMetric eachConstraint : constraintMetrics) {
+                        if (eachConstraint.getMetric() == null) {
+                            continue;
+                        }
+                        long max = (eachConstraint.getMax() != null) ?
+                                eachConstraint.getMax().longValue() : Long.MAX_VALUE;
+                        long min = (eachConstraint.getMin() != null) ?
+                                eachConstraint.getMin().longValue() : 0;
+                        long value = 0;
+                        if (eachConstraint.getMetric().equals(AltoSpceMetric.Bandwidth)) {
+                            value = bandwidth;
+                        } else {
+                            value = hopcount;
+                        }
+                        if (value < min || value > max) {
+                            return false;
+                        }
+                    }
+                }
+                if (hopcount < this.hopcount) {
+                    this.hopcount = hopcount;
+                    result = tmp;
+                }
+                return false;
+            }
+
+            @Override
+            public List<RouteViewer.Path> getResult() {
+                return result;
+            }
+        };
+
+        RouteViewer rv = new RouteViewer(getGraphFromTopology(topology, (long) 0), checker);
+        List<RouteViewer.Path> result = rv.viewRoutes(
+                    RouteViewer.extractNodeId(srcTpId),
+                    RouteViewer.extractNodeId(dstTpId))
+                .getResult();
+        logger.info(result.toString());
+        List<TpId> output = new LinkedList<>();
+        for (RouteViewer.Path eachPath : result) {
+            output.add(eachPath.src);
+        }
+        return output;
+    }
+
+    public List<TpId> maxBandwidthPath(TpId srcTpId, TpId dstTpId, Topology topology,
+                                       final List<ConstraintMetric> constraintMetrics) {
+        final RouteViewer.Path finalPath = new RouteViewer.Path();
+        finalPath.src = dstTpId;
+        finalPath.bandwidth = getBandwidthByTp(dstTpId.getValue()).longValue();
+        RouteViewer.RouteChecker checker = new RouteViewer.RouteChecker() {
+            private List<RouteViewer.Path> result;
+            private long bandwidth = 0;
+            @Override
+            public boolean isStop(List<RouteViewer.Path> pathList) {
+                LinkedList<RouteViewer.Path> tmp = new LinkedList<>(pathList);
+                tmp.add(finalPath);
+                long hopcount = tmp.size();
+                long bandwidth = getBandwidth(tmp);
+                if (constraintMetrics != null) {
+                    for (ConstraintMetric eachConstraint : constraintMetrics) {
+                        if (eachConstraint.getMetric() == null) {
+                            continue;
+                        }
+                        long max = (eachConstraint.getMax() != null) ?
+                                eachConstraint.getMax().longValue() : Long.MAX_VALUE;
+                        long min = (eachConstraint.getMin() != null) ?
+                                eachConstraint.getMin().longValue() : 0;
+                        long value = 0;
+                        if (eachConstraint.getMetric().equals(AltoSpceMetric.Bandwidth)) {
+                            value = bandwidth;
+                        } else {
+                            value = hopcount;
+                        }
+                        if (value < min || value > max) {
+                            return false;
+                        }
+                    }
+                }
+                if (bandwidth > this.bandwidth) {
+                    this.bandwidth = bandwidth;
+                    result = tmp;
+                }
+                return false;
+            }
+
+            @Override
+            public List<RouteViewer.Path> getResult() {
+                return result;
+            }
+        };
+
+        RouteViewer rv = new RouteViewer(getGraphFromTopology(topology, (long) 0), checker);
+        List<RouteViewer.Path> result = rv.viewRoutes(
+                RouteViewer.extractNodeId(srcTpId),
+                RouteViewer.extractNodeId(dstTpId))
+                .getResult();
+
+        List<TpId> output = new LinkedList<>();
+        for (RouteViewer.Path eachPath : result) {
+            output.add(eachPath.src);
+        }
+        return output;
+    }
+
+    long getBandwidth(List<RouteViewer.Path> pathList) {
+        Long result = Long.MAX_VALUE;
+        for (RouteViewer.Path eachPath : pathList) {
+            result = (result < eachPath.bandwidth) ? result : eachPath.bandwidth;
+        }
+        return result;
+    }
+
+    public List<TpId> shortestPathOpti(TpId srcTpId, TpId dstTpId, Topology topology, List<ConstraintMetric> constraintMetrics) {
+        String src = srcTpId.getValue();
+        String dst = dstTpId.getValue();
+        Long minBw = (long) 0;
+        for (ConstraintMetric eachConstraint : constraintMetrics) {
+            if (AltoSpceMetric.Bandwidth == eachConstraint.getMetric() && eachConstraint.getMin() != null) {
+                minBw = (minBw > eachConstraint.getMin().longValue()) ?
+                        minBw : eachConstraint.getMin().longValue();
+            }
+        }
+        Graph<String, RouteViewer.Path> networkGraph = getGraphFromTopology(topology, minBw);
+        DijkstraShortestPath<String, RouteViewer.Path> shortestPath = new DijkstraShortestPath<>(networkGraph);
+        List<RouteViewer.Path> path = shortestPath.getPath(extractNodeId(src), extractNodeId(dst));
+        List<TpId> output = new LinkedList<>();
+        for (RouteViewer.Path eachPath : path) {
+            output.add(eachPath.src);
+        }
+        return output;
+    }
+
+    public List<TpId> maxBandwidthPathOpti(TpId srcTpId, TpId dstTpId, Topology topology, List<ConstraintMetric> constraintMetrics) {
+        String src = srcTpId.getValue();
+        String dst = dstTpId.getValue();
+        Graph<String, RouteViewer.Path> networkGraph = getGraphFromTopology(topology, null);
+        Long maxHop = Long.MAX_VALUE;
+        for (ConstraintMetric eachConstraint : constraintMetrics) {
+            if (AltoSpceMetric.Hopcount == eachConstraint.getMetric() && eachConstraint.getMax() != null) {
+                maxHop = (maxHop < eachConstraint.getMax().longValue()) ?
+                        maxHop : eachConstraint.getMax().longValue();
+            }
+        }
+        List<RouteViewer.Path> path = maxBandwidth(networkGraph, extractNodeId(src), extractNodeId(dst), maxHop);
+        List<TpId> output = new LinkedList<>();
+        for (RouteViewer.Path eachPath : path) {
+            output.add(eachPath.src);
+        }
+        return output;
+    }
+
+    /** (1) add edges by the bandwidth, high bandwidth edge be added into the graph first;
+     ** (2) if this adding create a route, which is not longer than max hopcount, between src and dst:
+     **       return this route;
+     ** (3) else: continue the adding.
+     **/
+    public List<RouteViewer.Path> maxBandwidth(Graph<String, RouteViewer.Path> networkGraph, String src, String dst, Long maxHop) {
+        Map<String, Long> hopCount = new HashMap<>();
+        Map<String, RouteViewer.Path> pre = new HashMap<>();
+        hopCount.put(src, (long) 0);
+        List<RouteViewer.Path> paths = new ArrayList<>(networkGraph.getEdges());
+        Collections.sort(paths, new Comparator<RouteViewer.Path>() {
+            @Override
+            public int compare(RouteViewer.Path x, RouteViewer.Path y) {
+                return (Objects.equals(x.bandwidth, y.bandwidth) ? 0 : (x.bandwidth > y.bandwidth ? -1 : 1));
+            }
+        });
+        Graph<String, RouteViewer.Path> graph = new SparseMultigraph<>();
+        // add every node into the graph
+        for (String eachNode : networkGraph.getVertices())
+            graph.addVertex(eachNode);
+        for (RouteViewer.Path eachPath : paths) {
+            String srcNode = extractNodeId(eachPath.src.getValue());
+            String dstNode = extractNodeId(eachPath.dst.getValue());
+            graph.addEdge(eachPath, srcNode, dstNode, EdgeType.DIRECTED);
+            //update hopcount
+            if (hopCount.containsKey(srcNode)) {
+                LinkedList<String> queue = new LinkedList<>();
+                queue.add(srcNode);
+                while (!queue.isEmpty()) {
+                    srcNode = queue.pop();
+                    if (graph.getOutEdges(srcNode) != null) {
+                        for (RouteViewer.Path outPath : graph.getOutEdges(srcNode)) {
+                            dstNode = extractNodeId(outPath.dst.getValue());
+                            if (!hopCount.containsKey(dstNode) ||
+                                    (hopCount.get(dstNode) > hopCount.get(srcNode) + 1)) {
+                                queue.push(dstNode);
+                                hopCount.put(dstNode, hopCount.get(srcNode) + 1);
+                                pre.put(dstNode, outPath);
+                            }
+                        }
+                    }
+                }
+                if (hopCount.containsKey(dst) && hopCount.get(dst) <= maxHop) {
+                    // finally, build the route
+                    List<RouteViewer.Path> output = new LinkedList<>();
+                    output.add(0, pre.get(dst));
+                    while (!extractNodeId(output.get(0).src.getValue()).equals(src)) {
+                        dst = extractNodeId(output.get(0).src.getValue());
+                        output.add(0, pre.get(dst));
+                    }
+                    return output;
+                }
+            }
+        }
+        return null;
+    }
+
+    private Graph<String, RouteViewer.Path> getGraphFromTopology(Topology topology, Long minBw) {
+        Graph<String, RouteViewer.Path> networkGraph = new SparseMultigraph();
+        if (minBw == null) {
+            minBw = (long) 0;
+        }
+        for (Node eachNode : topology.getNode()) {
+            networkGraph.addVertex(eachNode.getNodeId().getValue());
+        }
+        for (Link eachLink : topology.getLink()) {
+            String linkSrcNode = extractNodeId(eachLink.getSource().getSourceNode().getValue());
+            String linkDstNode = extractNodeId(eachLink.getDestination().getDestNode().getValue());
+            if (linkSrcNode.contains("host") || linkDstNode.contains("host")) {
+                continue;
+            }
+            TpId linkSrcTp = eachLink.getSource().getSourceTp();
+            TpId linkDstTp = eachLink.getDestination().getDestTp();
+            RouteViewer.Path srcPath = new RouteViewer.Path();
+            srcPath.src = linkSrcTp;
+            srcPath.dst = linkDstTp;
+            srcPath.bandwidth = getBandwidthByTp(srcPath.src.getValue()).longValue();
+            if (srcPath.bandwidth < minBw) {
+                continue;
+            }
+            networkGraph.addEdge(srcPath, linkSrcNode, linkDstNode, EdgeType.DIRECTED);
+        }
+        return networkGraph;
+    }
+
+    private BigInteger getBandwidthByTp(String txTpId) {
+        BigInteger availableBandwidth = null;
+        AltoSpceGetTxBandwidthInput input = new AltoSpceGetTxBandwidthInputBuilder().setTpId(txTpId).build();
+        Future<RpcResult<AltoSpceGetTxBandwidthOutput>> result = this.networkTrackerService.altoSpceGetTxBandwidth(input);
+        try {
+            AltoSpceGetTxBandwidthOutput output = result.get().getResult();
+            availableBandwidth = output.getSpeed();
+        } catch (InterruptedException | ExecutionException e) {
+            return BigInteger.valueOf(0);
+        }
+        return availableBandwidth;
+    }
+
+    public static String extractNodeId(String nodeConnectorId) {
+        String output =
+            nodeConnectorId.split(":")[0] + ":" + nodeConnectorId.split(":")[1];
+        return output;
+    }
+
+}
diff --git a/alto-extensions/simple-pce/impl/src/main/java/org/opendaylight/alto/spce/impl/algorithm/RouteViewer.java b/alto-extensions/simple-pce/impl/src/main/java/org/opendaylight/alto/spce/impl/algorithm/RouteViewer.java
new file mode 100644 (file)
index 0000000..6ea0781
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2015 SNLAB 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.alto.spce.impl.algorithm;
+
+
+import edu.uci.ics.jung.graph.Graph;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TpId;
+
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+public class RouteViewer {
+    static public interface RouteChecker {
+        boolean isStop(List<Path> pathList);
+        List<Path> getResult();
+    }
+
+    static public class Path {
+        TpId src;
+        TpId dst;
+        Long bandwidth;
+
+        @Override
+        public String toString() {
+            return "" + src + "->" + dst + "@" + bandwidth;
+        }
+    }
+
+    private RouteChecker routeChecker;
+    private Map<String, Boolean> hasVisited;
+    private Graph<String, Path> networkGraph;
+    private LinkedList<Path> route;
+
+    RouteViewer(Graph<String, Path> networkGraph, RouteChecker routeChecker) {
+        this.networkGraph = networkGraph;
+        this.routeChecker = routeChecker;
+    }
+
+    RouteChecker viewRoutes(String srcNode, String dstNode) {
+        this.hasVisited = new HashMap<>();
+        this.route = new LinkedList<>();
+        for (String eachNode : networkGraph.getVertices()) {
+            this.hasVisited.put(eachNode, false);
+        }
+        visitor(srcNode, dstNode);
+        return this.routeChecker;
+    }
+
+    private boolean visitor(String srcNode, String dstNode) {
+        if (hasVisited.get(srcNode)) {
+            return false;
+        } else if (Objects.equals(srcNode, dstNode)) {
+            return this.routeChecker.isStop(this.route);
+        }
+        else {
+            hasVisited.put(srcNode, true);
+            for (Path eachPath : this.networkGraph.getOutEdges(srcNode)) {
+                route.addLast(eachPath);
+                if (visitor(extractNodeId(eachPath.dst), dstNode))
+                    return true;
+                route.removeLast();
+            }
+            hasVisited.put(srcNode, false);
+        }
+        return false;
+    }
+
+    public static String extractNodeId(TpId tpId) {
+        String nodeConnectorId = tpId.getValue();
+        return nodeConnectorId.replaceAll(":[0-9]+$", "");
+    }
+}
diff --git a/alto-extensions/simple-pce/impl/src/main/java/org/opendaylight/alto/spce/impl/util/FlowManager.java b/alto-extensions/simple-pce/impl/src/main/java/org/opendaylight/alto/spce/impl/util/FlowManager.java
new file mode 100644 (file)
index 0000000..bb13c5a
--- /dev/null
@@ -0,0 +1,310 @@
+/*
+ * Copyright Â© 2015 Copyright (c) 2015 SNLAB 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.alto.spce.impl.util;
+
+import com.google.common.collect.ImmutableList;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.OutputActionCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.output.action._case.OutputActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowTableRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowCookie;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowModFlags;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActions;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.EtherType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetDestinationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetSourceBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetTypeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatch;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Layer3Match;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4MatchBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.math.BigInteger;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.concurrent.atomic.AtomicLong;
+
+public class FlowManager {
+    private static final Logger LOG = LoggerFactory.getLogger(FlowManager.class);
+    private SalFlowService salFlowService;
+    private short flowTableId;
+    private int flowPriority;
+    private int flowIdleTimeout;
+    private int flowHardTimeout;
+
+    private AtomicLong flowIdInc = new AtomicLong();
+    private AtomicLong flowCookieInc = new AtomicLong(0x2a00000000000000L);
+    private final short DEFAULT_TABLE_ID = 0;
+    private final Integer DEFAULT_PRIORITY = 20;
+    private final Integer DEFAULT_HARD_TIMEOUT = 3600;
+    private final Integer DEFAULT_IDLE_TIMEOUT = 1800;
+    private final Long OFP_NO_BUFFER = Long.valueOf(4294967295L);
+
+    public FlowManager(SalFlowService salFLowService) {
+        this.salFlowService = salFLowService;
+        setFlowTableId(DEFAULT_TABLE_ID);
+        setFlowPriority(DEFAULT_PRIORITY);
+        setFlowIdleTimeout(DEFAULT_IDLE_TIMEOUT);
+        setFlowHardTimeout(DEFAULT_HARD_TIMEOUT);
+       }
+
+    public void setFlowTableId(short flowTableId) {
+        this.flowTableId = flowTableId;
+    }
+
+    public void setFlowPriority(int flowPriority) {
+        this.flowPriority = flowPriority;
+    }
+
+    public void setFlowIdleTimeout(int flowIdleTimeout) {
+        this.flowIdleTimeout = flowIdleTimeout;
+    }
+
+    public void setFlowHardTimeout(int flowHardTimeout) {
+        this.flowHardTimeout = flowHardTimeout;
+    }
+
+    public void addMacToMacFlow(MacAddress sourceMac, MacAddress destMac, NodeConnectorRef destNodeConnectorRef) {
+
+        if(sourceMac != null && destMac.equals(sourceMac)) {
+            LOG.info("In addMacToMacFlow: No flows added. Source and Destination mac are same.");
+            return;
+        }
+
+        TableKey flowTableKey = new TableKey((short) flowTableId);
+
+        InstanceIdentifier<Flow> flowPath = buildFlowPath(destNodeConnectorRef, flowTableKey);
+
+        Flow flowBody = createMacToMacFlow(flowTableKey.getId(), flowPriority, sourceMac, destMac, destNodeConnectorRef);
+
+        writeFlowToConfigData(flowPath, flowBody);
+    }
+
+    public void addIpToIpFlow(Ipv4Address sourceIp, Ipv4Address destIp, NodeConnectorRef destNodeConnectorRef) {
+
+        if(sourceIp != null && destIp.equals(sourceIp)) {
+            LOG.info("In addMacToMacFlow: No flows added. Source and Destination mac are same.");
+            return;
+        }
+
+        TableKey flowTableKey = new TableKey((short) flowTableId);
+
+        InstanceIdentifier<Flow> flowPath = buildFlowPath(destNodeConnectorRef, flowTableKey);
+
+        Flow flowBody = createIpv4ToIpv4Flow(flowTableKey.getId(), flowPriority, sourceIp, destIp, destNodeConnectorRef);
+
+        LOG.info("writeFlow: " + flowBody.toString());
+
+        try {
+            Future<RpcResult<AddFlowOutput>> result = writeFlowToConfigData(flowPath, flowBody);
+            AddFlowOutput output = result.get().getResult();
+        } catch (InterruptedException | ExecutionException e) {
+            LOG.info("WriteFlow Error: " + e.getMessage());
+        }
+    }
+
+    public void addFlowByPath(MacAddress sourceMac, MacAddress destMac, List<NodeConnectorRef> path) {
+
+        if(sourceMac != null && destMac.equals(sourceMac)) {
+            LOG.info("In addMacToMacFlow: No flows added. Source and Destination mac are same.");
+            return;
+        }
+
+        for (NodeConnectorRef nc : path) {
+            addMacToMacFlow(sourceMac, destMac, nc);
+        }
+    }
+
+    public void addFlowByPath(Ipv4Address sourceIp, Ipv4Address destIp, List<NodeConnectorRef> path) {
+
+        if(sourceIp != null && destIp.equals(sourceIp)) {
+            LOG.info("In addMacToMacFlow: No flows added. Source and Destination mac are same.");
+            return;
+        }
+
+        for (NodeConnectorRef nc : path) {
+            addIpToIpFlow(sourceIp, destIp, nc);
+        }
+    }
+
+    private InstanceIdentifier<Flow> buildFlowPath(NodeConnectorRef nodeConnectorRef, TableKey flowTableKey) {
+
+        FlowId flowId = new FlowId(String.valueOf(flowIdInc.getAndIncrement()));
+        FlowKey flowKey = new FlowKey(flowId);
+
+        return InstanceIdentifierUtils.generateFlowInstanceIdentifier(nodeConnectorRef, flowTableKey, flowKey);
+    }
+
+    private Flow createMacToMacFlow(Short tableId, int priority,
+                                    MacAddress sourceMac, MacAddress destMac, NodeConnectorRef destPort) {
+
+        FlowBuilder macToMacFlow = new FlowBuilder() //
+                .setTableId(tableId) //
+                .setFlowName("mac2mac");
+
+        macToMacFlow.setId(new FlowId(Long.toString(macToMacFlow.hashCode())));
+
+        EthernetMatchBuilder ethernetMatchBuilder = new EthernetMatchBuilder() //
+                .setEthernetDestination(new EthernetDestinationBuilder() //
+                        .setAddress(destMac) //
+                        .build());
+        if(sourceMac != null) {
+            ethernetMatchBuilder.setEthernetSource(new EthernetSourceBuilder()
+                    .setAddress(sourceMac)
+                    .build());
+        }
+        EthernetMatch ethernetMatch = ethernetMatchBuilder.build();
+        Match match = new MatchBuilder()
+                .setEthernetMatch(ethernetMatch)
+                .build();
+
+
+        Uri destPortUri = destPort.getValue().firstKeyOf(NodeConnector.class, NodeConnectorKey.class).getId();
+
+        Action outputToControllerAction = new ActionBuilder() //
+                .setOrder(0)
+                .setAction(new OutputActionCaseBuilder() //
+                        .setOutputAction(new OutputActionBuilder() //
+                                .setMaxLength(0xffff) //
+                                .setOutputNodeConnector(destPortUri) //
+                                .build()) //
+                        .build()) //
+                .build();
+
+        ApplyActions applyActions = new ApplyActionsBuilder().setAction(ImmutableList.of(outputToControllerAction))
+                .build();
+
+        Instruction applyActionsInstruction = new InstructionBuilder() //
+                .setOrder(0)
+                .setInstruction(new ApplyActionsCaseBuilder()//
+                        .setApplyActions(applyActions) //
+                        .build()) //
+                .build();
+
+        macToMacFlow
+                .setMatch(match) //
+                .setInstructions(new InstructionsBuilder() //
+                        .setInstruction(ImmutableList.of(applyActionsInstruction)) //
+                        .build()) //
+                .setPriority(priority) //
+                .setBufferId(OFP_NO_BUFFER) //
+                .setHardTimeout(flowHardTimeout) //
+                .setIdleTimeout(flowIdleTimeout) //
+                .setCookie(new FlowCookie(BigInteger.valueOf(flowCookieInc.getAndIncrement())))
+                .setFlags(new FlowModFlags(false, false, false, false, false));
+
+        return macToMacFlow.build();
+    }
+
+    private Flow createIpv4ToIpv4Flow(Short tableId, int priority,
+                                      Ipv4Address sourceIp, Ipv4Address destIp, NodeConnectorRef destPort) {
+
+        FlowBuilder ipToIpFlow = new FlowBuilder() //
+                .setTableId(tableId) //
+                .setFlowName("ip2ip");
+
+        ipToIpFlow.setId(new FlowId(Long.toString(ipToIpFlow.hashCode())));
+
+        Ipv4MatchBuilder ipv4MatchBuilder = new Ipv4MatchBuilder() //
+                    .setIpv4Destination(new Ipv4Prefix(destIp.getValue() + "/32"));
+        if(sourceIp != null) {
+            ipv4MatchBuilder.setIpv4Source(new Ipv4Prefix(sourceIp.getValue() + "/32"));
+        }
+        Layer3Match layer3Match = ipv4MatchBuilder.build();
+        Match match = new MatchBuilder()
+                .setLayer3Match(layer3Match)
+                .setEthernetMatch(new EthernetMatchBuilder()
+                        .setEthernetType(new EthernetTypeBuilder()
+                                .setType(new EtherType(0x0800L))
+                                .build())
+                        .build())
+                .build();
+
+
+        Uri destPortUri = destPort.getValue().firstKeyOf(NodeConnector.class, NodeConnectorKey.class).getId();
+
+        Action outputToControllerAction = new ActionBuilder() //
+                .setOrder(0)
+                .setAction(new OutputActionCaseBuilder() //
+                        .setOutputAction(new OutputActionBuilder() //
+                                .setMaxLength(0xffff) //
+                                .setOutputNodeConnector(destPortUri) //
+                                .build()) //
+                        .build()) //
+                .build();
+
+        ApplyActions applyActions = new ApplyActionsBuilder().setAction(ImmutableList.of(outputToControllerAction))
+                .build();
+
+        Instruction applyActionsInstruction = new InstructionBuilder() //
+                .setOrder(0)
+                .setInstruction(new ApplyActionsCaseBuilder()//
+                        .setApplyActions(applyActions) //
+                        .build()) //
+                .build();
+
+        ipToIpFlow
+                .setMatch(match) //
+                .setInstructions(new InstructionsBuilder() //
+                        .setInstruction(ImmutableList.of(applyActionsInstruction)) //
+                        .build()) //
+                .setPriority(priority) //
+                .setBufferId(OFP_NO_BUFFER) //
+                .setHardTimeout(flowHardTimeout) //
+                .setIdleTimeout(flowIdleTimeout) //
+                .setCookie(new FlowCookie(BigInteger.valueOf(flowCookieInc.getAndIncrement())))
+                .setFlags(new FlowModFlags(false, false, false, false, false));
+
+        return ipToIpFlow.build();
+    }
+
+    private Future<RpcResult<AddFlowOutput>> writeFlowToConfigData(InstanceIdentifier<Flow> flowPath,
+                                                                   Flow flow) {
+        final InstanceIdentifier<Table> tableInstanceId = flowPath.<Table>firstIdentifierOf(Table.class);
+        final InstanceIdentifier<Node> nodeInstanceId = flowPath.<Node>firstIdentifierOf(Node.class);
+        final AddFlowInputBuilder builder = new AddFlowInputBuilder(flow);
+        builder.setNode(new NodeRef(nodeInstanceId));
+        builder.setFlowRef(new FlowRef(flowPath));
+        builder.setFlowTable(new FlowTableRef(tableInstanceId));
+        builder.setTransactionUri(new Uri(flow.getId().getValue()));
+        return salFlowService.addFlow(builder.build());
+    }
+}
diff --git a/alto-extensions/simple-pce/impl/src/main/java/org/opendaylight/alto/spce/impl/util/InstanceIdentifierUtils.java b/alto-extensions/simple-pce/impl/src/main/java/org/opendaylight/alto/spce/impl/util/InstanceIdentifierUtils.java
new file mode 100644 (file)
index 0000000..7a03e8d
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright Â© 2015 Copyright (c) 2015 SNLAB 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.alto.spce.impl.util;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public final class InstanceIdentifierUtils {
+
+    private InstanceIdentifierUtils() {
+        throw new UnsupportedOperationException("Utility class should never be instantiated");
+    }
+
+    /**
+     * @param nodeConnectorRef
+     * @return
+     */
+    public static InstanceIdentifier<Node> generateNodeInstanceIdentifier(final NodeConnectorRef nodeConnectorRef) {
+        return nodeConnectorRef.getValue().firstIdentifierOf(Node.class);
+    }
+
+    /**
+     * @param nodeConnectorRef
+     * @param flowTableKey
+     * @return
+     */
+    public static InstanceIdentifier<Table> generateFlowTableInstanceIdentifier(final NodeConnectorRef nodeConnectorRef, final TableKey flowTableKey) {
+        return generateNodeInstanceIdentifier(nodeConnectorRef).builder()
+                .augmentation(FlowCapableNode.class)
+                .child(Table.class, flowTableKey)
+                .build();
+    }
+
+    /**
+     * @param nodeConnectorRef
+     * @param flowTableKey
+     * @param flowKey
+     * @return
+     */
+    public static InstanceIdentifier<Flow> generateFlowInstanceIdentifier(final NodeConnectorRef nodeConnectorRef,
+                                                                          final TableKey flowTableKey,
+                                                                          final FlowKey flowKey) {
+        return generateFlowTableInstanceIdentifier(nodeConnectorRef, flowTableKey).child(Flow.class, flowKey);
+    }
+}
diff --git a/alto-extensions/simple-pce/impl/src/main/java/org/opendaylight/alto/spce/impl/util/InventoryReader.java b/alto-extensions/simple-pce/impl/src/main/java/org/opendaylight/alto/spce/impl/util/InventoryReader.java
new file mode 100644 (file)
index 0000000..5e7f8f0
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright Â© 2015 Copyright (c) 2015 SNLAB 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.alto.spce.impl.util;
+
+import com.google.common.base.Optional;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.host.tracker.rev140624.HostNode;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TpId;
+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.Node;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.concurrent.ExecutionException;
+
+public class InventoryReader {
+
+    private Logger LOG = LoggerFactory.getLogger(InventoryReader.class);
+    private DataBroker dataBroker;
+
+    public InventoryReader(DataBroker dataBroker) {
+        this.dataBroker = dataBroker;
+    }
+
+    public TpId getNodeConnectorByMac(MacAddress macAddress) {
+        TpId tpId = null;
+        InstanceIdentifier<HostNode> hostId = InstanceIdentifier.builder(NetworkTopology.class)
+                .child(Topology.class, new TopologyKey(new TopologyId("flow:1")))
+                .child(Node.class,
+                    new NodeKey(
+                    new NodeId("host:"+macAddress.getValue())))
+                .augmentation(HostNode.class)
+                .build();
+
+        ReadOnlyTransaction readOnlyTransaction = dataBroker.newReadOnlyTransaction();
+        try {
+            Optional<HostNode> dataObjectOptional = null;
+            dataObjectOptional = readOnlyTransaction.read(LogicalDatastoreType.OPERATIONAL, hostId).get();
+            if (dataObjectOptional.isPresent()) {
+                HostNode hostNode = dataObjectOptional.get();
+                String attPoint = hostNode.getAttachmentPoints().get(0).getKey().getTpId().getValue();
+                tpId = new TpId(attPoint);
+            }
+        } catch (InterruptedException | ExecutionException e) {
+            LOG.error("Failed to read nodes from Operation data store.");
+            readOnlyTransaction.close();
+        }
+
+        readOnlyTransaction.close();
+        return tpId;
+    }
+}
diff --git a/alto-extensions/simple-pce/impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/alto/spce/impl/rev141210/AltoSpceModule.java b/alto-extensions/simple-pce/impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/alto/spce/impl/rev141210/AltoSpceModule.java
new file mode 100644 (file)
index 0000000..1b86346
--- /dev/null
@@ -0,0 +1,28 @@
+package org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.impl.rev141210;
+
+import org.opendaylight.alto.spce.impl.AltoSpceProvider;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
+
+public class AltoSpceModule extends org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.impl.rev141210.AbstractAltoSpceModule {
+    public AltoSpceModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+        super(identifier, dependencyResolver);
+    }
+
+    public AltoSpceModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.impl.rev141210.AltoSpceModule oldModule, java.lang.AutoCloseable oldInstance) {
+        super(identifier, dependencyResolver, oldModule, oldInstance);
+    }
+
+    @Override
+    public void customValidation() {
+        // add custom validation form module attributes here.
+    }
+
+    @Override
+    public java.lang.AutoCloseable createInstance() {
+        AltoSpceProvider provider = new AltoSpceProvider();
+        BindingAwareBroker broker = getBrokerDependency();
+        broker.registerProvider(provider);
+        return provider;
+    }
+
+}
diff --git a/alto-extensions/simple-pce/impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/alto/spce/impl/rev141210/AltoSpceModuleFactory.java b/alto-extensions/simple-pce/impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/alto/spce/impl/rev141210/AltoSpceModuleFactory.java
new file mode 100644 (file)
index 0000000..39420b3
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+* Generated file
+*
+* Generated from: yang module name: alto-spce-impl yang module local name: alto-spce
+* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+* Generated at: Sat Nov 07 17:59:08 CST 2015
+*
+* Do not modify this file unless it is present under src/main directory
+*/
+package org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.impl.rev141210;
+public class AltoSpceModuleFactory extends org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.impl.rev141210.AbstractAltoSpceModuleFactory {
+
+}
diff --git a/alto-extensions/simple-pce/impl/src/main/yang/alto-spce-impl.yang b/alto-extensions/simple-pce/impl/src/main/yang/alto-spce-impl.yang
new file mode 100644 (file)
index 0000000..db25acb
--- /dev/null
@@ -0,0 +1,35 @@
+module alto-spce-impl {
+    yang-version 1;
+    namespace "urn:opendaylight:alto:spce:impl";
+    prefix "alto-spce-impl";
+
+    import config { prefix config; revision-date 2013-04-05; }
+    import opendaylight-md-sal-binding { prefix md-sal-binding; revision-date 2013-10-28;}
+
+    description
+        "Service definition for alto-spce project";
+
+    revision "2014-12-10" {
+        description
+            "Initial revision";
+    }
+
+    identity alto-spce {
+        base config:module-type;
+        config:java-name-prefix AltoSpce;
+    }
+
+    augment "/config:modules/config:module/config:configuration" {
+        case alto-spce {
+            when "/config:modules/config:module/config:type = 'alto-spce'";
+            container broker {
+                uses config:service-ref {
+                    refine type {
+                        mandatory true;
+                        config:required-identity md-sal-binding:binding-broker-osgi-registry;
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/alto-extensions/simple-pce/impl/src/test/java/org/opendaylight/alto/spce/impl/algorithm/PathComputationTest.java b/alto-extensions/simple-pce/impl/src/test/java/org/opendaylight/alto/spce/impl/algorithm/PathComputationTest.java
new file mode 100644 (file)
index 0000000..3ffd1f5
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2015 SNLAB 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.alto.spce.impl.algorithm;
+
+import edu.uci.ics.jung.graph.Graph;
+import edu.uci.ics.jung.graph.SparseMultigraph;
+import edu.uci.ics.jung.graph.util.EdgeType;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.Assert;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TpId;
+
+import java.util.LinkedList;
+import java.util.List;
+
+public class PathComputationTest {
+    private PathComputation pathComputer;
+
+    @Before
+    public void prepare() {
+        pathComputer = new PathComputation(null);
+    }
+
+    @Test
+    public void onTestMaxBandwidth() {
+        Graph<String, RouteViewer.Path> networkGraph = new SparseMultigraph<>();
+        for (int i = 0; i < 5; ++i) {
+            networkGraph.addVertex("openflow:"+i);
+        }
+        addEdge(networkGraph, getTp(0, 0), getTp(1, 0), (long) 10);
+        addEdge(networkGraph, getTp(1, 1), getTp(2, 0), (long) 100);
+        addEdge(networkGraph, getTp(2, 1), getTp(3, 0), (long) 100);
+        addEdge(networkGraph, getTp(3, 1), getTp(4, 0), (long) 100);
+        addEdge(networkGraph, getTp(4, 1), getTp(5, 0), (long) 10);
+        addEdge(networkGraph, getTp(1, 2), getTp(6, 0), (long) 5);
+        addEdge(networkGraph, getTp(6, 1), getTp(4, 2), (long) 5);
+        List<RouteViewer.Path> output
+                = pathComputer.maxBandwidth(networkGraph, getNode(0), getNode(5), (long) 4);
+        LinkedList<String> result = new LinkedList<>();
+        result.add(getTp(0, 0));
+        result.add(getTp(1, 2));
+        result.add(getTp(6, 1));
+        result.add(getTp(4, 1));
+        Assert.assertEquals(4, output.size());
+        for (int i = 0; i < 4; ++i) {
+            Assert.assertEquals(result.get(i), output.get(i).src.getValue());
+        }
+    }
+
+    private <T> String getTp(T i, T j) {
+        return "openflow:" + i + ":" + j;
+    }
+
+    private <T> String getNode(T i) {
+        return "openflow:" + i;
+    }
+
+    private RouteViewer.Path addEdge (Graph<String, RouteViewer.Path> networkGraph,
+                          String src, String dst, Long bw) {
+        RouteViewer.Path p = new RouteViewer.Path();
+        p.src = TpId.getDefaultInstance(src);
+        p.dst = TpId.getDefaultInstance(dst);
+        p.bandwidth = bw;
+        networkGraph.addEdge(p, PathComputation.extractNodeId(src), PathComputation.extractNodeId(dst),
+                EdgeType.DIRECTED);
+        p = new RouteViewer.Path();
+        p.src = TpId.getDefaultInstance(dst);
+        p.dst = TpId.getDefaultInstance(src);
+        p.bandwidth = bw;
+        networkGraph.addEdge(p, PathComputation.extractNodeId(dst), PathComputation.extractNodeId(src),
+                EdgeType.DIRECTED);
+        return p;
+    }
+
+}
diff --git a/alto-extensions/simple-pce/karaf/pom.xml b/alto-extensions/simple-pce/karaf/pom.xml
new file mode 100644 (file)
index 0000000..7b095ba
--- /dev/null
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2015 SNLAB 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 INTERNAL
+-->
+<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.controller</groupId>
+    <artifactId>karaf-parent</artifactId>
+    <version>1.7.0-SNAPSHOT</version>
+    <relativePath/>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.opendaylight.alto.ext</groupId>
+  <artifactId>alto-spce-karaf</artifactId>
+  <version>0.3.0-SNAPSHOT</version>
+  <name>${project.artifactId}</name>
+  <prerequisites>
+    <maven>3.1.1</maven>
+  </prerequisites>
+  <properties>
+    <karaf.localFeature>odl-alto-spce-ui</karaf.localFeature>
+  </properties>
+  <dependencyManagement>
+    <dependencies>
+      <dependency>
+        <groupId>${project.groupId}</groupId>
+        <artifactId>alto-spce-artifacts</artifactId>
+        <version>${project.version}</version>
+        <type>pom</type>
+        <scope>import</scope>
+      </dependency>
+    </dependencies>
+  </dependencyManagement>
+  <dependencies>
+    <dependency>
+      <!-- scope is compile so all features (there is only one) are installed
+      into startup.properties and the feature repo itself is not installed -->
+      <groupId>org.apache.karaf.features</groupId>
+      <artifactId>framework</artifactId>
+      <type>kar</type>
+    </dependency>
+
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>alto-spce-features</artifactId>
+      <classifier>features</classifier>
+      <type>xml</type>
+      <scope>runtime</scope>
+    </dependency>
+
+  </dependencies>
+  <!-- DO NOT install or deploy the karaf artifact -->
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-deploy-plugin</artifactId>
+        <configuration>
+          <skip>true</skip>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+</project>
diff --git a/alto-extensions/simple-pce/network-tracker/api/pom.xml b/alto-extensions/simple-pce/network-tracker/api/pom.xml
new file mode 100644 (file)
index 0000000..8292fdd
--- /dev/null
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2015 SNLAB 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
+-->
+<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.mdsal</groupId>
+    <artifactId>binding-parent</artifactId>
+    <version>0.9.0-SNAPSHOT</version>
+    <relativePath/>
+  </parent>
+
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.opendaylight.alto.spce.network</groupId>
+  <artifactId>network-tracker-api</artifactId>
+  <version>0.3.0-SNAPSHOT</version>
+  <packaging>bundle</packaging>
+
+</project>
diff --git a/alto-extensions/simple-pce/network-tracker/api/src/main/yang/network-tracker.yang b/alto-extensions/simple-pce/network-tracker/api/src/main/yang/network-tracker.yang
new file mode 100644 (file)
index 0000000..c32fe3e
--- /dev/null
@@ -0,0 +1,89 @@
+module network-tracker {
+    yang-version 1;
+    namespace "urn:opendaylight:params:xml:ns:yang:network-tracker";
+    prefix "network-tracker";
+
+    revision "2015-11-07" {
+        description "Initial revision of network-tracker model";
+    }
+
+    rpc alto-spce-get-tx-bandwidth {
+        description "";
+
+        input {
+            leaf tp-id {
+                type string;
+            }
+        }
+
+        output {
+           leaf speed {
+               type uint64;
+           }
+        }
+    }
+
+    rpc alto-spce-get-tx-speed {
+        description "";
+
+        input {
+            leaf tp-id {
+                type string;
+            }
+        }
+
+        output {
+           leaf speed {
+               type uint64;
+           }
+        }
+    }
+
+    rpc alto-spce-get-rx-speed {
+        description "";
+
+        input {
+            leaf tp-id {
+                type string;
+            }
+        }
+
+        output {
+           leaf speed {
+               type uint64;
+           }
+        }
+    }
+
+    rpc alto-spce-get-mac-by-ip {
+        description "";
+
+        input {
+            leaf ip-address {
+                type string;
+            }
+        }
+
+        output {
+            leaf mac-address {
+                type string;
+            }
+        }
+    }
+
+    rpc alto-spce-get-ip-by-mac {
+        description "";
+
+        input {
+            leaf mac-address {
+                type string;
+            }
+        }
+
+        output {
+            leaf ip-address {
+                type string;
+            }
+        }
+    }
+}
diff --git a/alto-extensions/simple-pce/network-tracker/artifacts/pom.xml b/alto-extensions/simple-pce/network-tracker/artifacts/pom.xml
new file mode 100644 (file)
index 0000000..34828ec
--- /dev/null
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2015 SNLAB 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
+-->
+
+<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>
+  <groupId>org.opendaylight.alto.spce.network</groupId>
+  <artifactId>network-tracker-artifacts</artifactId>
+  <version>0.3.0-SNAPSHOT</version>
+  <packaging>pom</packaging>
+
+  <dependencyManagement>
+    <dependencies>
+      <dependency>
+        <groupId>${project.groupId}</groupId>
+        <artifactId>network-tracker-api</artifactId>
+        <version>${project.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>${project.groupId}</groupId>
+        <artifactId>network-tracker-impl</artifactId>
+        <version>${project.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>${project.groupId}</groupId>
+        <artifactId>network-tracker-features</artifactId>
+        <version>${project.version}</version>
+        <classifier>features</classifier>
+        <type>xml</type>
+      </dependency>
+    </dependencies>
+  </dependencyManagement>
+</project>
diff --git a/alto-extensions/simple-pce/network-tracker/config/pom.xml b/alto-extensions/simple-pce/network-tracker/config/pom.xml
new file mode 100644 (file)
index 0000000..50c5027
--- /dev/null
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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>
+    <groupId>org.opendaylight.controller</groupId>
+    <artifactId>config-parent</artifactId>
+    <version>0.5.0-SNAPSHOT</version>
+    <relativePath/>
+  </parent>
+
+  <groupId>org.opendaylight.alto.spce.network</groupId>
+  <artifactId>network-tracker-config</artifactId>
+  <version>0.3.0-SNAPSHOT</version>
+  <packaging>jar</packaging>
+</project>
diff --git a/alto-extensions/simple-pce/network-tracker/config/src/main/config/default-config.xml b/alto-extensions/simple-pce/network-tracker/config/src/main/config/default-config.xml
new file mode 100644 (file)
index 0000000..954c068
--- /dev/null
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+ Copyright (c) 2014 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
+-->
+<snapshot>
+  <configuration>
+    <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+      <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+        <module>
+          <type xmlns:prefix="urn:opendaylight:packet:arp-handler-impl">
+            prefix:arp-handler-impl
+          </type>
+          <name>arp-handler-impl</name>
+          <arp-flow-table-id>0</arp-flow-table-id>
+          <arp-flow-priority>1</arp-flow-priority>
+          <arp-flow-idle-timeout>0</arp-flow-idle-timeout>
+          <arp-flow-hard-timeout>0</arp-flow-hard-timeout>
+          <flood-flow-table-id>0</flood-flow-table-id>
+          <flood-flow-priority>2</flood-flow-priority>
+          <flood-flow-idle-timeout>0</flood-flow-idle-timeout>
+          <flood-flow-hard-timeout>0</flood-flow-hard-timeout>
+          <flood-flow-installation-delay>2000</flood-flow-installation-delay>
+          <is-proactive-flood-mode>false</is-proactive-flood-mode>
+          <is-hybrid-mode>false</is-hybrid-mode>
+
+          <notification-service>
+            <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">
+              binding:binding-notification-service
+            </type>
+            <name>binding-notification-broker</name>
+          </notification-service>
+          <data-broker>
+            <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-async-data-broker</type>
+            <name>binding-data-broker</name>
+          </data-broker>
+          <rpc-registry>
+            <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-rpc-registry</type>
+            <name>binding-rpc-broker</name>
+          </rpc-registry>
+        </module>
+      </modules>
+    </data>
+  </configuration>
+
+  <required-capabilities>
+    <capability>urn:opendaylight:packet:arp-handler-impl?module=arp-handler-impl&amp;revision=2014-05-28</capability>
+    <capability>urn:opendaylight:l2switch:loopremover?module=stp-status-aware-node-connector&amp;revision=2014-07-14</capability>
+  </required-capabilities>
+</snapshot>
+
diff --git a/alto-extensions/simple-pce/network-tracker/config/src/main/config/maven-metadata-local.xml b/alto-extensions/simple-pce/network-tracker/config/src/main/config/maven-metadata-local.xml
new file mode 100644 (file)
index 0000000..eb00eaa
--- /dev/null
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<metadata modelVersion="1.1.0">
+  <groupId>org.opendaylight.alto.spce.network</groupId>
+  <artifactId>network-tracker-config</artifactId>
+  <version>0.2.1-SNAPSHOT</version>
+  <versioning>
+    <snapshot>
+      <localCopy>true</localCopy>
+    </snapshot>
+    <lastUpdated>20160311080419</lastUpdated>
+    <snapshotVersions>
+      <snapshotVersion>
+        <classifier>config</classifier>
+        <extension>xml</extension>
+        <value>0.2.1-SNAPSHOT</value>
+        <updated>20160311080419</updated>
+      </snapshotVersion>
+    </snapshotVersions>
+  </versioning>
+</metadata>
diff --git a/alto-extensions/simple-pce/network-tracker/features/pom.xml b/alto-extensions/simple-pce/network-tracker/features/pom.xml
new file mode 100644 (file)
index 0000000..5617edd
--- /dev/null
@@ -0,0 +1,141 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2015 SNLAB 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 INTERNAL
+-->
+<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.odlparent</groupId>
+    <artifactId>features-parent</artifactId>
+    <version>1.7.0-SNAPSHOT</version>
+    <relativePath/>
+  </parent>
+  <groupId>org.opendaylight.alto.spce.network</groupId>
+  <artifactId>network-tracker-features</artifactId>
+  <version>0.3.0-SNAPSHOT</version>
+  <name>${project.artifactId}</name>
+  <modelVersion>4.0.0</modelVersion>
+  <prerequisites>
+    <maven>3.1.1</maven>
+  </prerequisites>
+  <properties>
+    <mdsal.model.version>0.9.0-SNAPSHOT</mdsal.model.version>
+    <mdsal.version>1.4.0-SNAPSHOT</mdsal.version>
+    <restconf.version>1.4.0-SNAPSHOT</restconf.version>
+    <yangtools.version>0.9.0-SNAPSHOT</yangtools.version>
+    <dlux.version>0.4.0-SNAPSHOT</dlux.version>
+    <configfile.directory>etc/opendaylight/karaf</configfile.directory>
+    <l2switch.version>0.4.0-SNAPSHOT</l2switch.version>
+  </properties>
+  <dependencyManagement>
+    <dependencies>
+      <!-- project specific dependencies -->
+      <dependency>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>mdsal-artifacts</artifactId>
+        <version>${mdsal.version}</version>
+        <type>pom</type>
+        <scope>import</scope>
+      </dependency>
+      <dependency>
+        <groupId>org.opendaylight.netconf</groupId>
+        <artifactId>restconf-artifacts</artifactId>
+        <version>${restconf.version}</version>
+        <type>pom</type>
+        <scope>import</scope>
+      </dependency>
+    </dependencies>
+  </dependencyManagement>
+  <dependencies>
+    <dependency>
+      <groupId>org.opendaylight.yangtools</groupId>
+      <artifactId>features-yangtools</artifactId>
+      <classifier>features</classifier>
+      <version>${yangtools.version}</version>
+      <type>xml</type>
+      <scope>runtime</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.mdsal.model</groupId>
+      <artifactId>features-mdsal-model</artifactId>
+      <version>${mdsal.model.version}</version>
+      <classifier>features</classifier>
+      <type>xml</type>
+      <scope>runtime</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>features-mdsal</artifactId>
+      <classifier>features</classifier>
+      <version>${mdsal.version}</version>
+      <type>xml</type>
+      <scope>runtime</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.netconf</groupId>
+      <artifactId>features-restconf</artifactId>
+      <classifier>features</classifier>
+      <version>${restconf.version}</version>
+      <type>xml</type>
+      <scope>runtime</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.dlux</groupId>
+      <artifactId>features-dlux</artifactId>
+      <classifier>features</classifier>
+      <version>${dlux.version}</version>
+      <type>xml</type>
+      <scope>runtime</scope>
+    </dependency>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>network-tracker-impl</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>network-tracker-impl</artifactId>
+      <version>${project.version}</version>
+      <type>xml</type>
+      <classifier>config</classifier>
+    </dependency>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>network-tracker-api</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+
+    <dependency>
+      <groupId>org.opendaylight.controller.model</groupId>
+      <artifactId>model-inventory</artifactId>
+      <type>jar</type>
+    </dependency>
+
+    <dependency>
+      <groupId>org.opendaylight.l2switch</groupId>
+      <artifactId>features-l2switch</artifactId>
+      <classifier>features</classifier>
+      <version>${l2switch.version}</version>
+      <type>xml</type>
+      <scope>runtime</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.opendaylight.l2switch.addresstracker</groupId>
+      <artifactId>addresstracker-model</artifactId>
+      <version>${l2switch.version}</version>
+      <type>jar</type>
+    </dependency>
+
+    <dependency>
+      <groupId>org.opendaylight.l2switch.hosttracker</groupId>
+      <artifactId>hosttracker-model</artifactId>
+      <version>${l2switch.version}</version>
+      <type>jar</type>
+    </dependency>
+
+  </dependencies>
+</project>
diff --git a/alto-extensions/simple-pce/network-tracker/features/src/main/features/features.xml b/alto-extensions/simple-pce/network-tracker/features/src/main/features/features.xml
new file mode 100644 (file)
index 0000000..f8244b4
--- /dev/null
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+Copyright Â© 2015 Tongji University 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
+-->
+<features name="odl-network-tracker-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.2.0"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.2.0 http://karaf.apache.org/xmlns/features/v1.2.0">
+  <repository>mvn:org.opendaylight.yangtools/features-yangtools/${yangtools.version}/xml/features</repository>
+  <repository>mvn:org.opendaylight.controller/features-mdsal/${mdsal.version}/xml/features</repository>
+  <repository>mvn:org.opendaylight.mdsal.model/features-mdsal-model/${mdsal.model.version}/xml/features</repository>
+  <repository>mvn:org.opendaylight.netconf/features-restconf/${restconf.version}/xml/features</repository>
+  <repository>mvn:org.opendaylight.dlux/features-dlux/${dlux.version}/xml/features</repository>
+  <repository>mvn:org.opendaylight.l2switch/features-l2switch/${l2switch.version}/xml/features</repository>
+  <feature name='odl-network-tracker-api' version='${project.version}' description='OpenDaylight :: network-tracker :: api'>
+    <feature version='${mdsal.model.version}'>odl-mdsal-models</feature>
+    <bundle>mvn:org.opendaylight.alto.spce.network/network-tracker-api/${project.version}</bundle>
+  </feature>
+  <feature name='odl-network-tracker' version='${project.version}' description='OpenDaylight :: network-tracker'>
+    <feature version='${mdsal.version}'>odl-mdsal-broker</feature>
+    <feature version='${l2switch.version}'>odl-l2switch-all</feature>
+    <feature version='${project.version}'>odl-network-tracker-api</feature>
+    <bundle>mvn:org.opendaylight.alto.spce.network/network-tracker-impl/${project.version}</bundle>
+    <configfile finalname="${configfile.directory}/network-tracker.xml">mvn:org.opendaylight.alto.spce.network/network-tracker-impl/${project.version}/xml/config</configfile>
+  </feature>
+  <feature name='odl-network-tracker-rest' version='${project.version}' description='OpenDaylight :: network-tracker :: REST'>
+    <feature version="${project.version}">odl-network-tracker</feature>
+    <feature version="${restconf.version}">odl-restconf</feature>
+  </feature>
+  <feature name='odl-network-tracker-ui' version='${project.version}' description='OpenDaylight :: network-tracker :: UI'>
+    <feature version="${project.version}">odl-network-tracker-rest</feature>
+    <feature version="${restconf.version}">odl-mdsal-apidocs</feature>
+    <feature version="${mdsal.version}">odl-mdsal-xsql</feature>
+    <feature version="${dlux.version}">odl-dlux-yangui</feature>
+  </feature>
+
+</features>
diff --git a/alto-extensions/simple-pce/network-tracker/impl/pom.xml b/alto-extensions/simple-pce/network-tracker/impl/pom.xml
new file mode 100644 (file)
index 0000000..454929b
--- /dev/null
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+Copyright (c) 2015 SNLAB 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
+-->
+<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.controller</groupId>
+    <artifactId>config-parent</artifactId>
+    <version>0.5.0-SNAPSHOT</version>
+    <relativePath/>
+  </parent>
+
+  <properties>
+    <l2switch.version>0.4.0-SNAPSHOT</l2switch.version>
+  </properties>
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.opendaylight.alto.spce.network</groupId>
+  <artifactId>network-tracker-impl</artifactId>
+  <version>0.3.0-SNAPSHOT</version>
+  <packaging>bundle</packaging>
+  <dependencies>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>network-tracker-api</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+
+    <!-- Testing Dependencies -->
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <scope>test</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.mockito</groupId>
+      <artifactId>mockito-all</artifactId>
+      <scope>test</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.opendaylight.controller.model</groupId>
+      <artifactId>model-inventory</artifactId>
+      <type>jar</type>
+    </dependency>
+
+    <dependency>
+      <groupId>org.opendaylight.l2switch.addresstracker</groupId>
+      <artifactId>addresstracker-model</artifactId>
+      <version>${l2switch.version}</version>
+      <type>jar</type>
+    </dependency>
+
+    <dependency>
+      <groupId>org.opendaylight.l2switch.hosttracker</groupId>
+      <artifactId>hosttracker-model</artifactId>
+      <version>${l2switch.version}</version>
+      <type>jar</type>
+    </dependency>
+
+    <dependency>
+      <groupId>org.opendaylight.l2switch.loopremover</groupId>
+      <artifactId>loopremover-impl</artifactId>
+      <version>${l2switch.version}</version>
+      <type>jar</type>
+    </dependency>
+  </dependencies>
+
+</project>
diff --git a/alto-extensions/simple-pce/network-tracker/impl/src/main/config/default-config.xml b/alto-extensions/simple-pce/network-tracker/impl/src/main/config/default-config.xml
new file mode 100644 (file)
index 0000000..f303a61
--- /dev/null
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+Copyright Â© 2015 Tongji University 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
+-->
+<snapshot>
+  <required-capabilities>
+      <capability>urn:opendaylight:alto:spce:impl:network-tracker:impl?module=network-tracker-impl&amp;revision=2014-12-10</capability>
+      <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding?module=opendaylight-md-sal-binding&amp;revision=2013-10-28</capability>
+  </required-capabilities>
+  <configuration>
+
+    <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+      <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+        <module>
+          <type xmlns:prefix="urn:opendaylight:alto:spce:impl:network-tracker:impl">prefix:network-tracker</type>
+          <name>network-tracker-default</name>
+          <broker>
+            <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-broker-osgi-registry</type>
+            <name>binding-osgi-broker</name>
+          </broker>
+        </module>
+      </modules>
+    </data>
+  </configuration>
+</snapshot>
diff --git a/alto-extensions/simple-pce/network-tracker/impl/src/main/config/maven-metadata-local.xml b/alto-extensions/simple-pce/network-tracker/impl/src/main/config/maven-metadata-local.xml
new file mode 100644 (file)
index 0000000..8f50e19
--- /dev/null
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<metadata modelVersion="1.1.0">
+  <groupId>org.opendaylight.alto.spce.network</groupId>
+  <artifactId>network-tracker-impl</artifactId>
+  <version>1.0.0-SNAPSHOT</version>
+  <versioning>
+    <snapshot>
+      <localCopy>true</localCopy>
+    </snapshot>
+    <lastUpdated>20151107084951</lastUpdated>
+    <snapshotVersions>
+      <snapshotVersion>
+        <classifier>config</classifier>
+        <extension>xml</extension>
+        <value>1.0.0-SNAPSHOT</value>
+        <updated>20151107084951</updated>
+      </snapshotVersion>
+    </snapshotVersions>
+  </versioning>
+</metadata>
diff --git a/alto-extensions/simple-pce/network-tracker/impl/src/main/java/org/opendaylight/alto/spce/network/api/AddressConvertService.java b/alto-extensions/simple-pce/network-tracker/impl/src/main/java/org/opendaylight/alto/spce/network/api/AddressConvertService.java
new file mode 100644 (file)
index 0000000..bf1d9f9
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2015 SNLAB 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.alto.spce.network.api;
+
+public interface AddressConvertService {
+
+    String getIpByMac(String macAddress);
+
+
+    String getMacByIp(String ipAddress);
+
+}
diff --git a/alto-extensions/simple-pce/network-tracker/impl/src/main/java/org/opendaylight/alto/spce/network/api/NetworkPortStatisticsService.java b/alto-extensions/simple-pce/network-tracker/impl/src/main/java/org/opendaylight/alto/spce/network/api/NetworkPortStatisticsService.java
new file mode 100644 (file)
index 0000000..77e611a
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2015 SNLAB 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.alto.spce.network.api;
+
+public interface NetworkPortStatisticsService {
+    /**
+     * @param tpId
+     * @param metric
+     * @return current Tx speed in bps or Bps.
+     */
+    Long getCurrentTxSpeed(String tpId, Metric metric);
+
+    /**
+     * @param tpId
+     * @param metric
+     * @return current Rx speed in bps of Bps.
+     */
+    Long getCurrentRxSpeed(String tpId, Metric metric);
+
+    Long getAvailableTxBandwidth(String tpId, Long meterId);
+
+    enum Metric {BITSPERSECOND, BYTESPERSECOND};
+}
diff --git a/alto-extensions/simple-pce/network-tracker/impl/src/main/java/org/opendaylight/alto/spce/network/impl/AddressConvertServiceImpl.java b/alto-extensions/simple-pce/network-tracker/impl/src/main/java/org/opendaylight/alto/spce/network/impl/AddressConvertServiceImpl.java
new file mode 100644 (file)
index 0000000..2234f7f
--- /dev/null
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2015 SNLAB 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.alto.spce.network.impl;
+
+import org.opendaylight.alto.spce.network.api.AddressConvertService;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.address.tracker.rev140617.address.node.connector.Addresses;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.host.tracker.rev140624.HostNode;
+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.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.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+public class AddressConvertServiceImpl implements AddressConvertService, DataChangeListener, AutoCloseable {
+
+    private static final Logger logger = LoggerFactory
+            .getLogger(AddressConvertServiceImpl.class);
+    private static final int CPUS = Runtime.getRuntime().availableProcessors();
+    private ExecutorService exec = Executors.newFixedThreadPool(CPUS);
+    private DataBroker dataBroker = null;
+
+    private Map<String, String> macToIp;
+    private Map<String, String> ipToMac;
+
+    private ListenerRegistration<DataChangeListener> hostListener = null;
+
+    public AddressConvertServiceImpl(DataBroker dataBroker) {
+        this.logger.info("AddressConvertServiceImpl initial.");
+        this.dataBroker = dataBroker;
+        macToIp = new HashMap<>();
+        ipToMac = new HashMap<>();
+        registerPortListener();
+    }
+
+    private void registerPortListener() {
+        InstanceIdentifier<HostNode> hostNodes = InstanceIdentifier
+                .builder(NetworkTopology.class)
+                .child(Topology.class)
+                .child(Node.class).augmentation(HostNode.class).build();
+        this.hostListener = this.dataBroker
+                .registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
+                        hostNodes, this, AsyncDataBroker.DataChangeScope.SUBTREE);
+    }
+
+    @Override
+    public String getIpByMac(String macAddress) {
+        return this.macToIp.get(macAddress);
+    }
+
+    @Override
+    public String getMacByIp(String ipAddress) {
+        return this.ipToMac.get(ipAddress);
+    }
+
+    @Override
+    public void close() throws Exception {
+        this.hostListener.close();
+    }
+
+    @Override
+    public void onDataChanged(
+            final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
+        exec.submit(new Runnable() {
+            @Override
+            public void run() {
+                if (change == null) {
+                    logger.info("In onDataChanged: No processing done as change even is null.");
+                    return;
+                }
+                Map<InstanceIdentifier<?>, DataObject> updatedData = change
+                        .getUpdatedData();
+                Map<InstanceIdentifier<?>, DataObject> createdData = change
+                        .getCreatedData();
+                Map<InstanceIdentifier<?>, DataObject> originalData = change
+                        .getOriginalData();
+                Set<InstanceIdentifier<?>> deletedData = change
+                        .getRemovedPaths();
+
+                for (InstanceIdentifier<?> iid : deletedData) {
+                    logger.info("deletedData");
+                    if (iid.getTargetType().equals(Node.class)) {
+                        Node node = ((Node) originalData.get(iid));
+                        HostNode hostNode = node
+                                .getAugmentation(HostNode.class);
+                        if (hostNode != null) {
+                            List<Addresses> addrList = hostNode.getAddresses();
+                            for (Addresses eachAddress : addrList) {
+                                macToIp.remove(eachAddress.getMac().getValue());
+                                ipToMac.remove(eachAddress.getIp().getIpv4Address().getValue());
+                            }
+                        }
+                    }
+                }
+
+                for (Map.Entry<InstanceIdentifier<?>, DataObject> entrySet : updatedData
+                        .entrySet()) {
+                    InstanceIdentifier<?> iiD = entrySet.getKey();
+                    final DataObject dataObject = entrySet.getValue();
+                    if (dataObject instanceof Addresses) {
+                        Addresses addrs = (Addresses) dataObject;
+                        Addresses origAddr = (Addresses) originalData.get(iiD);
+                        logger.info("updatedData addresses:" + addrs + "~~" + origAddr);
+                        macToIp.remove(origAddr.getMac().getValue());
+                        macToIp.put(addrs.getMac().getValue(), addrs.getIp().getIpv4Address().getValue());
+                        ipToMac.remove(origAddr.getIp().getIpv4Address().getValue());
+                        ipToMac.put(addrs.getIp().getIpv4Address().getValue(), addrs.getMac().getValue());
+                    }
+                }
+
+                for (Map.Entry<InstanceIdentifier<?>, DataObject> entrySet : createdData
+                        .entrySet()) {
+                    InstanceIdentifier<?> iiD = entrySet.getKey();
+                    final DataObject dataObject = entrySet.getValue();
+                    if (dataObject instanceof Addresses) {
+                        Addresses addrs = (Addresses) dataObject;
+                        logger.info("createdData addresses:" + addrs);
+                        macToIp.put(addrs.getMac().getValue(), addrs.getIp().getIpv4Address().getValue());
+                        ipToMac.put(addrs.getIp().getIpv4Address().getValue(), addrs.getMac().getValue());
+                    }
+                }
+            }
+        });
+    }
+}
diff --git a/alto-extensions/simple-pce/network-tracker/impl/src/main/java/org/opendaylight/alto/spce/network/impl/NetworkPortStatisticsServiceImpl.java b/alto-extensions/simple-pce/network-tracker/impl/src/main/java/org/opendaylight/alto/spce/network/impl/NetworkPortStatisticsServiceImpl.java
new file mode 100644 (file)
index 0000000..2d7e500
--- /dev/null
@@ -0,0 +1,237 @@
+/*
+ * Copyright (c) 2015 SNLAB 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.alto.spce.network.impl;
+
+import org.opendaylight.alto.spce.network.api.NetworkPortStatisticsService;
+import org.opendaylight.alto.spce.network.util.DataHelper;
+import org.opendaylight.alto.spce.network.util.InstanceIdentifierUtils;
+import org.opendaylight.alto.spce.network.util.NetworkServiceConstants;
+import org.opendaylight.alto.spce.network.util.ReadDataFailedException;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.meter.band.headers.MeterBandHeader;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.statistics.types.rev130925.node.connector.statistics.Bytes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.FlowCapableNodeConnectorStatisticsData;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+
+public class NetworkPortStatisticsServiceImpl implements NetworkPortStatisticsService, DataChangeListener, AutoCloseable{
+    private static final Logger logger = LoggerFactory
+            .getLogger(NetworkPortStatisticsServiceImpl.class);
+    private static final int CPUS = Runtime.getRuntime().availableProcessors();
+    private ExecutorService exec = Executors.newFixedThreadPool(CPUS);
+    private DataBroker dataBroker = null;
+
+    private class nodeStatistic {
+        public Long rxHistory = (long) 0;
+        public Long txHistory = (long) 0;
+        public Long rxSpeed = (long) 0;
+        public Long txSpeed = (long) 0;
+        public Long timestamp = (long) 0;
+
+        @Override
+        public String toString() {
+            return "rxSpeed=" + rxSpeed.toString()
+                    + ";txSpeed=" + txSpeed.toString()
+                    + ";timestamp=" + timestamp.toString();
+        }
+    }
+
+    private Map<String, nodeStatistic> nodeStatisticData = null;
+    private ListenerRegistration<DataChangeListener> portListener = null;
+
+
+    public NetworkPortStatisticsServiceImpl(DataBroker dataBroker) {
+        this.logger.info("NetworkPortStatisticsServiceImpl initial.");
+        this.dataBroker = dataBroker;
+        nodeStatisticData = new HashMap<>();
+        registerPortListener();
+    }
+
+    private void registerPortListener() {
+        this.portListener = this.dataBroker.registerDataChangeListener(
+                LogicalDatastoreType.OPERATIONAL, InstanceIdentifierUtils.STATISTICS,
+                this, AsyncDataBroker.DataChangeScope.SUBTREE
+        );
+    }
+
+    @Override
+    public Long getAvailableTxBandwidth(String tpId, Long meterId) {
+        FlowCapableNodeConnector nodeConnector = getFlowCapableNodeConnector(tpId);
+        Long capacity = getCapacity(nodeConnector, readMeter(tpId, meterId));
+        Long consumedBandwidth = getConsumedBandwidth(tpId, isHalfDuplex(nodeConnector));
+        if (capacity == null || consumedBandwidth == null) return Long.valueOf(0);
+        return capacity - consumedBandwidth;
+    }
+
+    private FlowCapableNodeConnector getFlowCapableNodeConnector(String tpId) {
+        logger.info("Reading flow capable node connector for " + tpId);
+        try {
+            return DataHelper.readOperational(dataBroker,
+                    InstanceIdentifierUtils.flowCapableNodeConnector(tpId));
+        } catch (ReadDataFailedException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    private Long getCapacity(FlowCapableNodeConnector nodeConnector, Meter meter) {
+        if (nodeConnector == null) return null;
+        Long currentSpeed = nodeConnector.getCurrentSpeed();
+        if (meter == null) return currentSpeed;
+        long bandRate = -1;
+        for (MeterBandHeader band : meter.getMeterBandHeaders().getMeterBandHeader()) {
+            if (bandRate > band.getBandRate() && bandRate < currentSpeed) {
+                bandRate = band.getBandRate();
+            }
+        }
+        return (bandRate == -1) ? currentSpeed : bandRate;
+    }
+
+    private Meter readMeter(String tpId, Long meterId) {
+        String nodeId = InstanceIdentifierUtils.extractNodeId(tpId);
+        try {
+            return DataHelper.readOperational(this.dataBroker,
+                    InstanceIdentifierUtils.flowCapableNodeMeter(nodeId, meterId));
+        } catch (ReadDataFailedException e) {
+            e.printStackTrace();
+        } catch (NullPointerException e) {
+            return null;
+        }
+        return null;
+    }
+
+    private Long getConsumedBandwidth(String tpId, boolean isHalfDuplex) {
+        try {
+            long transmitted = getCurrentTxSpeed(tpId, NetworkPortStatisticsService.Metric.BITSPERSECOND)
+                    / 1000;
+            long received = getCurrentRxSpeed(tpId, NetworkPortStatisticsService.Metric.BITSPERSECOND)
+                    / 1000;
+            if (isHalfDuplex) {
+                return transmitted + received;
+            } else {
+                return transmitted;
+            }
+        } catch (Exception e) {
+            logger.error("TpId is: " + tpId);
+            e.printStackTrace();
+            return Long.valueOf(0);
+        }
+    }
+
+    private boolean isHalfDuplex(FlowCapableNodeConnector nodeConnector) {
+        if (nodeConnector == null) return false;
+        boolean[] portFeatures = nodeConnector.getCurrentFeature().getValue();
+        return portFeatures[NetworkServiceConstants.PORT_FEATURES.get(NetworkServiceConstants.TEN_MB_HD)]
+                || portFeatures[NetworkServiceConstants.PORT_FEATURES.get(NetworkServiceConstants.HUNDRED_MD_HD)]
+                || portFeatures[NetworkServiceConstants.PORT_FEATURES.get(NetworkServiceConstants.ONE_GB_HD)];
+    }
+
+    @Override
+    public void onDataChanged(
+            final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
+        exec.submit(new Runnable() {
+            @Override
+            public void run() {
+                onDataUpdated(change);
+                onDataDeleted(change);
+            }
+
+            private void onDataUpdated(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
+                Map<InstanceIdentifier<?>, DataObject> updated = change.getUpdatedData();
+
+                for (Map.Entry<InstanceIdentifier<?>, DataObject> eachEntry : updated.entrySet()) {
+                    final DataObject dataObject = eachEntry.getValue();
+                    if (dataObject instanceof FlowCapableNodeConnectorStatisticsData) {
+                        final FlowCapableNodeConnectorStatisticsData statistic =
+                                (FlowCapableNodeConnectorStatisticsData) dataObject;
+                        Bytes bytes = statistic.getFlowCapableNodeConnectorStatistics().getBytes();
+                        if (bytes != null) {
+                            String id = eachEntry.getKey()
+                                    .firstKeyOf(NodeConnector.class, NodeConnectorKey.class)
+                                    .getId().getValue();
+                            nodeStatistic ns = null;
+                            if (nodeStatisticData.containsKey(id)) {
+                                ns = nodeStatisticData.get(id);
+                            } else {
+                                ns = new nodeStatistic();
+                                nodeStatisticData.put(id, ns);
+                            }
+                            ns.rxSpeed = (bytes.getReceived().longValue() - ns.rxHistory) /
+                                    (statistic.getFlowCapableNodeConnectorStatistics()
+                                            .getDuration().getSecond().getValue() - ns.timestamp);
+                            ns.txSpeed = (bytes.getTransmitted().longValue() - ns.txHistory) /
+                                    (statistic.getFlowCapableNodeConnectorStatistics()
+                                            .getDuration().getSecond().getValue() - ns.timestamp);
+                            ns.rxHistory = bytes.getReceived().longValue();
+                            ns.txHistory = bytes.getTransmitted().longValue();
+                            ns.timestamp =
+                                    statistic.getFlowCapableNodeConnectorStatistics()
+                                            .getDuration().getSecond().getValue();
+                        }
+                    }
+                }
+            }
+
+            private void onDataDeleted(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
+                Set<InstanceIdentifier<?>> removed = change.getRemovedPaths();
+                for (InstanceIdentifier<?> eachPath : removed) {
+                    if (eachPath.getTargetType() == FlowCapableNodeConnectorStatisticsData.class) {
+                        String name =
+                                eachPath.firstKeyOf(NodeConnector.class, NodeConnectorKey.class).getId().getValue();
+                        nodeStatisticData.remove(name);
+                    }
+                }
+            }
+        });
+    }
+
+    @Override
+    public void close() throws Exception {
+        portListener.close();
+    }
+
+    @Override
+    public Long getCurrentTxSpeed(String tpId, Metric metric) {
+        if (nodeStatisticData.containsKey(tpId)) {
+            if (metric == Metric.BITSPERSECOND)
+                return nodeStatisticData.get(tpId).txSpeed * 8;
+            else if (metric == Metric.BYTESPERSECOND)
+                return nodeStatisticData.get(tpId).txSpeed;
+        }
+        return null;
+    }
+
+    @Override
+    public Long getCurrentRxSpeed(String tpId, Metric metric) {
+        if (nodeStatisticData.containsKey(tpId)) {
+            if (metric == Metric.BITSPERSECOND)
+                return nodeStatisticData.get(tpId).rxSpeed * 8;
+            else if (metric == Metric.BYTESPERSECOND)
+                return nodeStatisticData.get(tpId).rxSpeed;
+        }
+        return null;
+    }
+}
diff --git a/alto-extensions/simple-pce/network-tracker/impl/src/main/java/org/opendaylight/alto/spce/network/impl/NetworkTrackerProvider.java b/alto-extensions/simple-pce/network-tracker/impl/src/main/java/org/opendaylight/alto/spce/network/impl/NetworkTrackerProvider.java
new file mode 100644 (file)
index 0000000..438ef8e
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2015 SNLAB 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.alto.spce.network.impl;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.RpcRegistration;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
+import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.tracker.rev151107.NetworkTrackerService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class NetworkTrackerProvider implements BindingAwareProvider, AutoCloseable {
+
+    private static final Logger LOG = LoggerFactory.getLogger(NetworkTrackerProvider.class);
+    private DataBroker dataBroker;
+    private NetworkTrackerRpcHandler networkTrackerRpcHandler;
+    private RpcRegistration<NetworkTrackerService> networkTrackerService;
+
+    @Override
+    public void onSessionInitiated(ProviderContext session) {
+        LOG.info("NetworkTrackerProvider Session Initiated");
+        dataBroker = session.getSALService(DataBroker.class);
+        networkTrackerRpcHandler = new NetworkTrackerRpcHandler(dataBroker);
+        networkTrackerService = session.addRpcImplementation(NetworkTrackerService.class, networkTrackerRpcHandler);
+    }
+
+    @Override
+    public void close() throws Exception {
+        LOG.info("NetworkTrackerProvider Closed");
+    }
+
+}
diff --git a/alto-extensions/simple-pce/network-tracker/impl/src/main/java/org/opendaylight/alto/spce/network/impl/NetworkTrackerRpcHandler.java b/alto-extensions/simple-pce/network-tracker/impl/src/main/java/org/opendaylight/alto/spce/network/impl/NetworkTrackerRpcHandler.java
new file mode 100644 (file)
index 0000000..e5eb50c
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2015 SNLAB 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.alto.spce.network.impl;
+
+import org.opendaylight.alto.spce.network.api.AddressConvertService;
+import org.opendaylight.alto.spce.network.api.NetworkPortStatisticsService;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.tracker.rev151107.AltoSpceGetIpByMacInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.tracker.rev151107.AltoSpceGetIpByMacOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.tracker.rev151107.AltoSpceGetIpByMacOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.tracker.rev151107.AltoSpceGetMacByIpInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.tracker.rev151107.AltoSpceGetMacByIpOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.tracker.rev151107.AltoSpceGetMacByIpOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.tracker.rev151107.AltoSpceGetRxSpeedInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.tracker.rev151107.AltoSpceGetRxSpeedOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.tracker.rev151107.AltoSpceGetRxSpeedOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.tracker.rev151107.AltoSpceGetTxBandwidthInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.tracker.rev151107.AltoSpceGetTxBandwidthOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.tracker.rev151107.AltoSpceGetTxBandwidthOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.tracker.rev151107.AltoSpceGetTxSpeedInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.tracker.rev151107.AltoSpceGetTxSpeedOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.tracker.rev151107.AltoSpceGetTxSpeedOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.tracker.rev151107.NetworkTrackerService;
+
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.math.BigInteger;
+import java.util.concurrent.Future;
+
+public class NetworkTrackerRpcHandler implements NetworkTrackerService {
+
+    private static final Logger logger = LoggerFactory
+            .getLogger(NetworkTrackerRpcHandler.class);
+    private DataBroker dataBroker = null;
+    private NetworkPortStatisticsService networkPortStatisticsService;
+    private AddressConvertService addressConvertService;
+
+    NetworkTrackerRpcHandler(DataBroker dataBroker) {
+        this.dataBroker = dataBroker;
+        this.networkPortStatisticsService = new NetworkPortStatisticsServiceImpl(this.dataBroker);
+        this.addressConvertService = new AddressConvertServiceImpl(this.dataBroker);
+    }
+
+    @Override
+    public Future<RpcResult<AltoSpceGetRxSpeedOutput>> altoSpceGetRxSpeed(AltoSpceGetRxSpeedInput input) {
+        String tpId = input.getTpId();
+        AltoSpceGetRxSpeedOutput output = new AltoSpceGetRxSpeedOutputBuilder()
+                .setSpeed(BigInteger.valueOf(this.networkPortStatisticsService.getCurrentRxSpeed(tpId, NetworkPortStatisticsService.Metric.BITSPERSECOND)))
+                .build();
+        return RpcResultBuilder.success(output).buildFuture();
+    }
+
+    @Override
+    public Future<RpcResult<AltoSpceGetTxBandwidthOutput>> altoSpceGetTxBandwidth(AltoSpceGetTxBandwidthInput input) {
+        String tpId = input.getTpId();
+        AltoSpceGetTxBandwidthOutput output = new AltoSpceGetTxBandwidthOutputBuilder()
+                .setSpeed(BigInteger.valueOf(this.networkPortStatisticsService.getAvailableTxBandwidth(tpId, null)))
+                .build();
+        return RpcResultBuilder.success(output).buildFuture();
+    }
+
+    @Override
+    public Future<RpcResult<AltoSpceGetTxSpeedOutput>> altoSpceGetTxSpeed(AltoSpceGetTxSpeedInput input) {
+        String tpId = input.getTpId();
+        AltoSpceGetTxSpeedOutput output = new AltoSpceGetTxSpeedOutputBuilder()
+                .setSpeed(BigInteger.valueOf(this.networkPortStatisticsService.getCurrentTxSpeed(tpId, NetworkPortStatisticsService.Metric.BITSPERSECOND)))
+                .build();
+        return RpcResultBuilder.success(output).buildFuture();
+    }
+
+    @Override
+    public Future<RpcResult<AltoSpceGetIpByMacOutput>> altoSpceGetIpByMac(AltoSpceGetIpByMacInput input) {
+        String mac = input.getMacAddress();
+        AltoSpceGetIpByMacOutput output = new AltoSpceGetIpByMacOutputBuilder()
+                .setIpAddress(this.addressConvertService.getIpByMac(mac)).build();
+        return RpcResultBuilder.success(output).buildFuture();
+    }
+
+    @Override
+    public Future<RpcResult<AltoSpceGetMacByIpOutput>> altoSpceGetMacByIp(AltoSpceGetMacByIpInput input) {
+        String ip = input.getIpAddress();
+        AltoSpceGetMacByIpOutput output = new AltoSpceGetMacByIpOutputBuilder()
+                .setMacAddress(this.addressConvertService.getMacByIp(ip)).build();
+        return RpcResultBuilder.success(output).buildFuture();
+    }
+}
diff --git a/alto-extensions/simple-pce/network-tracker/impl/src/main/java/org/opendaylight/alto/spce/network/util/DataHelper.java b/alto-extensions/simple-pce/network-tracker/impl/src/main/java/org/opendaylight/alto/spce/network/util/DataHelper.java
new file mode 100644 (file)
index 0000000..add7e4e
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2015 SNLAB University 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.alto.spce.network.util;
+
+import com.google.common.base.Optional;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+public class DataHelper {    /**
+ * @param dataBroker
+ * @param iid
+ * @param <T>
+ * @return The configuration of iid
+ * @throws ReadDataFailedException
+ */
+public static <T extends DataObject> T readConfiguration(
+        DataBroker dataBroker, InstanceIdentifier<T> iid) throws ReadDataFailedException {
+    return readFromDataStore(dataBroker, iid, LogicalDatastoreType.CONFIGURATION);
+}
+
+    /**
+     * @param dataBroker
+     * @param iid
+     * @param <T>
+     * @return The operational data of iid
+     * @throws ReadDataFailedException
+     */
+    public static <T extends DataObject> T readOperational(
+            DataBroker dataBroker, InstanceIdentifier<T> iid) throws ReadDataFailedException {
+        T data = readFromDataStore(dataBroker, iid, LogicalDatastoreType.OPERATIONAL);
+        return data;
+    }
+
+    /**
+     * @param dataBroker
+     * @param iid
+     * @param type
+     * @param <T>
+     * @return The data of iid
+     * @throws ReadDataFailedException
+     */
+    public static <T extends DataObject> T readFromDataStore(
+            DataBroker dataBroker, InstanceIdentifier<T> iid, LogicalDatastoreType type) throws ReadDataFailedException {
+        ReadOnlyTransaction tx = dataBroker.newReadOnlyTransaction();
+        Future<Optional<T>> future = tx.read(type, iid);
+        try {
+            if (future != null) {
+                Optional<T> optional = future.get();
+                if (optional.isPresent()) {
+                    return optional.get();
+                }
+            }
+        } catch (InterruptedException | ExecutionException e) {
+            e.printStackTrace();
+        } finally {
+            tx.close();
+        }
+        throw new ReadDataFailedException();
+    }
+}
diff --git a/alto-extensions/simple-pce/network-tracker/impl/src/main/java/org/opendaylight/alto/spce/network/util/InstanceIdentifierUtils.java b/alto-extensions/simple-pce/network-tracker/impl/src/main/java/org/opendaylight/alto/spce/network/util/InstanceIdentifierUtils.java
new file mode 100644 (file)
index 0000000..19631ff
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2015 SNLAB 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.alto.spce.network.util;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.MeterKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.host.tracker.rev140624.HostNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.FlowCapableNodeConnectorStatisticsData;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.LinkId;
+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.Link;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.LinkKey;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class InstanceIdentifierUtils {
+    public static final String TOPOLOGY_NAME = "flow:1";
+    public static final InstanceIdentifier<Topology> TOPOLOGY = InstanceIdentifier
+            .builder(NetworkTopology.class)
+            .child(Topology.class, new TopologyKey(new TopologyId(TOPOLOGY_NAME)))
+            .build();
+
+    public static final InstanceIdentifier<HostNode> HOSTNODE = InstanceIdentifier
+            .builder(NetworkTopology.class)
+            .child(Topology.class, new TopologyKey(new TopologyId(TOPOLOGY_NAME)))
+            .child(Node.class)
+            .augmentation(HostNode.class)
+            .build();
+
+    public static final InstanceIdentifier<Link> LINK = InstanceIdentifier
+            .builder(NetworkTopology.class)
+            .child(Topology.class, new TopologyKey(new TopologyId(TOPOLOGY_NAME)))
+            .child(Link.class)
+            .build();
+
+    public static final InstanceIdentifier<FlowCapableNodeConnectorStatisticsData> STATISTICS = InstanceIdentifier
+            .builder(Nodes.class)
+            .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node.class)
+            .child(NodeConnector.class).augmentation(FlowCapableNodeConnectorStatisticsData.class).build();
+
+    public static InstanceIdentifier<FlowCapableNode> flowCapableNode(String nodeId) {
+        return InstanceIdentifier
+                .builder(Nodes.class)
+                .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node.class,
+                        new NodeKey(new NodeId(nodeId)))
+                .augmentation(FlowCapableNode.class)
+                .build();
+    }
+
+    /**
+     * @param nodeId
+     * @param meterId
+     * @return iid of {@link Meter}.
+     */
+    public static InstanceIdentifier<Meter> flowCapableNodeMeter(String nodeId, long meterId) {
+        return InstanceIdentifier
+                .builder(Nodes.class)
+                .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node.class,
+                        new NodeKey(new NodeId(nodeId)))
+                .augmentation(FlowCapableNode.class)
+                .child(Meter.class, new MeterKey(new MeterId(meterId)))
+                .build();
+    }
+
+    /**
+     * @param linkId
+     * @return iid of {@link Link}
+     */
+    public static InstanceIdentifier<Link> linkPath(String linkId) {
+        return InstanceIdentifier
+                .builder(NetworkTopology.class)
+                .child(Topology.class, new TopologyKey(new TopologyId(TOPOLOGY_NAME)))
+                .child(Link.class, new LinkKey(new LinkId(linkId)))
+                .build();
+    }
+
+    /**
+     * @param nodeConnectorId
+     * @return iid of {@link FlowCapableNodeConnector}.
+     */
+    public static InstanceIdentifier<FlowCapableNodeConnector> flowCapableNodeConnector(String nodeConnectorId) {
+        String nodeId = extractNodeId(nodeConnectorId);
+        return InstanceIdentifier
+                .builder(Nodes.class)
+                .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node.class,
+                        new NodeKey(new NodeId(nodeId)))
+                .child(NodeConnector.class, new NodeConnectorKey(new NodeConnectorId(nodeConnectorId)))
+                .augmentation(FlowCapableNodeConnector.class)
+                .build();
+    }
+
+    public static String extractNodeId(String nodeConnectorId) {
+        return nodeConnectorId.replaceAll(":[0-9]+$", "");
+    }
+
+}
+
diff --git a/alto-extensions/simple-pce/network-tracker/impl/src/main/java/org/opendaylight/alto/spce/network/util/NetworkServiceConstants.java b/alto-extensions/simple-pce/network-tracker/impl/src/main/java/org/opendaylight/alto/spce/network/util/NetworkServiceConstants.java
new file mode 100644 (file)
index 0000000..9151147
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2015 SNLAB 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.alto.spce.network.util;
+
+import java.util.Map;
+
+import com.google.common.collect.ImmutableMap;
+
+public class NetworkServiceConstants {
+
+    public static final String TEN_MB_HD = "ten-mb-hd";
+    public static final String TEN_MB_FD = "ten-mb-fd";
+    public static final String HUNDRED_MD_HD = "hundred-mb-hd";
+    public static final String HUNDRED_MD_FD = "hundred-mb-fd";
+    public static final String ONE_GB_HD = "one-gb-hd";
+    public static final String ONE_MD_FD = "one-gb-fd";
+    public static final String TEN_GB_FD = "ten-gb-fd";
+    public static final String FORTY_GB_FD = "forty-gb-fd";
+    public static final String HUNDRED_GB_FD = "hundred-gb-fd";
+    public static final String ONE_TB_FD = "one-tb-fd";
+    public static final String OTHER = "other";
+    public static final String COPPER = "copper";
+    public static final String FIBER = "fiber";
+    public static final String AUTOENG = "autoeng";
+    public static final String PAUSE = "pause";
+    public static final String PAUSE_ASYM = "pause-asym";
+
+    public static final Map<String, Integer> PORT_FEATURES = ImmutableMap.<String, Integer>builder()
+            .put(TEN_MB_HD, 0)
+            .put(TEN_MB_FD, 1)
+            .put(HUNDRED_MD_HD, 2)
+            .put(HUNDRED_MD_FD, 3)
+            .put(ONE_GB_HD, 4)
+            .put(ONE_MD_FD, 5)
+            .put(TEN_GB_FD, 6)
+            .put(FORTY_GB_FD, 7)
+            .put(HUNDRED_GB_FD, 8)
+            .put(ONE_TB_FD, 9)
+            .put(OTHER, 10)
+            .put(COPPER, 11)
+            .put(FIBER, 12)
+            .put(AUTOENG, 13)
+            .put(PAUSE, 14)
+            .put(PAUSE_ASYM, 15)
+            .build();
+}
+
diff --git a/alto-extensions/simple-pce/network-tracker/impl/src/main/java/org/opendaylight/alto/spce/network/util/ReadDataFailedException.java b/alto-extensions/simple-pce/network-tracker/impl/src/main/java/org/opendaylight/alto/spce/network/util/ReadDataFailedException.java
new file mode 100644 (file)
index 0000000..184fcba
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2015 SNLAB 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.alto.spce.network.util;
+
+public class ReadDataFailedException extends Exception {
+    private static final long serialVersionUID = 1L;
+
+    public void printMessage(String message) {
+        System.out.println(message);
+    }
+}
diff --git a/alto-extensions/simple-pce/network-tracker/impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/alto/spce/impl/network/tracker/impl/rev141210/NetworkTrackerModule.java b/alto-extensions/simple-pce/network-tracker/impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/alto/spce/impl/network/tracker/impl/rev141210/NetworkTrackerModule.java
new file mode 100644 (file)
index 0000000..54594e5
--- /dev/null
@@ -0,0 +1,30 @@
+package org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.impl.network.tracker.impl.rev141210;
+
+import org.opendaylight.alto.spce.network.impl.NetworkTrackerProvider;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
+
+public class NetworkTrackerModule extends org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.impl.network.tracker.impl.rev141210.AbstractNetworkTrackerModule {
+    public NetworkTrackerModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+        super(identifier, dependencyResolver);
+    }
+
+    public NetworkTrackerModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.impl.network.tracker.impl.rev141210.NetworkTrackerModule oldModule, java.lang.AutoCloseable oldInstance) {
+        super(identifier, dependencyResolver, oldModule, oldInstance);
+    }
+
+    @Override
+    public void customValidation() {
+        // add custom validation form module attributes here.
+    }
+
+    @Override
+    public java.lang.AutoCloseable createInstance() {
+        // TODO:implement
+        // throw new java.lang.UnsupportedOperationException();
+        BindingAwareBroker broker = getBrokerDependency();
+        NetworkTrackerProvider provider = new NetworkTrackerProvider();
+        broker.registerProvider(provider);
+        return provider;
+    }
+
+}
diff --git a/alto-extensions/simple-pce/network-tracker/impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/alto/spce/impl/network/tracker/impl/rev141210/NetworkTrackerModuleFactory.java b/alto-extensions/simple-pce/network-tracker/impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/alto/spce/impl/network/tracker/impl/rev141210/NetworkTrackerModuleFactory.java
new file mode 100644 (file)
index 0000000..6fcb19a
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+* Generated file
+*
+* Generated from: yang module name: network-tracker-impl yang module local name: network-tracker
+* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+* Generated at: Sat Nov 07 21:31:25 CST 2015
+*
+* Do not modify this file unless it is present under src/main directory
+*/
+package org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.impl.network.tracker.impl.rev141210;
+public class NetworkTrackerModuleFactory extends org.opendaylight.yang.gen.v1.urn.opendaylight.alto.spce.impl.network.tracker.impl.rev141210.AbstractNetworkTrackerModuleFactory {
+
+}
diff --git a/alto-extensions/simple-pce/network-tracker/impl/src/main/yang/network-tracker-impl.yang b/alto-extensions/simple-pce/network-tracker/impl/src/main/yang/network-tracker-impl.yang
new file mode 100644 (file)
index 0000000..27a2bb5
--- /dev/null
@@ -0,0 +1,35 @@
+module network-tracker-impl {
+    yang-version 1;
+    namespace "urn:opendaylight:alto:spce:impl:network-tracker:impl";
+    prefix "network-tracker-impl";
+
+    import config { prefix config; revision-date 2013-04-05; }
+    import opendaylight-md-sal-binding { prefix md-sal-binding; revision-date 2013-10-28;}
+
+    description
+        "Service definition for network-tracker project";
+
+    revision "2014-12-10" {
+        description
+            "Initial revision";
+    }
+
+    identity network-tracker {
+        base config:module-type;
+        config:java-name-prefix NetworkTracker;
+    }
+
+    augment "/config:modules/config:module/config:configuration" {
+        case network-tracker {
+            when "/config:modules/config:module/config:type = 'network-tracker'";
+            container broker {
+                uses config:service-ref {
+                    refine type {
+                        mandatory true;
+                        config:required-identity md-sal-binding:binding-broker-osgi-registry;
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/alto-extensions/simple-pce/network-tracker/pom.xml b/alto-extensions/simple-pce/network-tracker/pom.xml
new file mode 100644 (file)
index 0000000..38d4185
--- /dev/null
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2015 SNLAB 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 INTERNAL
+-->
+<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.odlparent</groupId>
+    <artifactId>odlparent</artifactId>
+    <version>1.7.0-SNAPSHOT</version>
+  </parent>
+
+  <groupId>org.opendaylight.alto.spce.network</groupId>
+  <artifactId>network-tracker-aggregator</artifactId>
+  <version>0.3.0-SNAPSHOT</version>
+  <name>network-tracker</name>
+  <packaging>pom</packaging>
+  <modelVersion>4.0.0</modelVersion>
+  <prerequisites>
+    <maven>3.1.1</maven>
+  </prerequisites>
+  <modules>
+    <module>api</module>
+    <module>impl</module>
+    <module>config</module>
+    <!--module>features</module-->
+    <module>artifacts</module>
+  </modules>
+  <!-- DO NOT install or deploy the repo root pom as it's only needed to initiate a build -->
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-deploy-plugin</artifactId>
+        <configuration>
+          <skip>true</skip>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-install-plugin</artifactId>
+        <configuration>
+          <skip>true</skip>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+
+  <scm>
+    <connection>scm:git:ssh://git.opendaylight.org:29418/network-tracker.git</connection>
+    <developerConnection>scm:git:ssh://git.opendaylight.org:29418/network-tracker.git</developerConnection>
+    <tag>HEAD</tag>
+    <url>https://wiki.opendaylight.org/view/network-tracker:Main</url>
+  </scm>
+</project>
diff --git a/alto-extensions/simple-pce/pom.xml b/alto-extensions/simple-pce/pom.xml
new file mode 100644 (file)
index 0000000..490f59b
--- /dev/null
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2015 SNLAB 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 INTERNAL
+--><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.odlparent</groupId>
+    <artifactId>odlparent</artifactId>
+    <version>1.7.0-SNAPSHOT</version>
+  </parent>
+
+  <groupId>org.opendaylight.alto.ext</groupId>
+  <artifactId>alto-spce-aggregator</artifactId>
+  <version>0.3.0-SNAPSHOT</version>
+  <name>alto-spce</name>
+  <packaging>pom</packaging>
+  <modelVersion>4.0.0</modelVersion>
+  <prerequisites>
+    <maven>3.1.1</maven>
+  </prerequisites>
+  <modules>
+    <module>network-tracker</module>
+    <module>api</module>
+    <module>impl</module>
+  </modules>
+  <!-- DO NOT install or deploy the repo root pom as it's only needed to initiate a build -->
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-deploy-plugin</artifactId>
+        <configuration>
+          <skip>true</skip>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-install-plugin</artifactId>
+        <configuration>
+          <skip>true</skip>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+
+  <scm>
+    <connection>scm:git:ssh://git.opendaylight.org:29418/alto-spce.git</connection>
+    <developerConnection>scm:git:ssh://git.opendaylight.org:29418/alto-spce.git</developerConnection>
+    <tag>HEAD</tag>
+    <url>https://wiki.opendaylight.org/view/alto-spce:Main</url>
+  </scm>
+</project>
index ced9df105802f1c3f93fb7bcd40b1540624e6288..7d920686e260e2374dbe493070fd1fa30ffc6056 100644 (file)
@@ -28,6 +28,10 @@ and is available at http://www.eclipse.org/legal/epl-v10.html INTERNAL
     <configfile.directory>etc/opendaylight/karaf</configfile.directory>
     <l2switch.version>0.4.0-SNAPSHOT</l2switch.version>
     <openflow.plugin.version>0.3.0-SNAPSHOT</openflow.plugin.version>
+    <l2switch.packethandler.configfile>50-packethandler.xml</l2switch.packethandler.configfile>
+    <l2switch.loopremover.configfile>52-loopremover.xml</l2switch.loopremover.configfile>
+    <l2switch.addresstracker.configfile>56-addresstracker.xml</l2switch.addresstracker.configfile>
+    <l2switch.hosttracker.configfile>57-hosttracker.xml</l2switch.hosttracker.configfile>
   </properties>
 
   <dependencyManagement>
@@ -312,12 +316,124 @@ and is available at http://www.eclipse.org/legal/epl-v10.html INTERNAL
       <version>${l2switch.version}</version>
       <type>jar</type>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.l2switch.packethandler</groupId>
+      <artifactId>packethandler-model</artifactId>
+      <version>${l2switch.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.l2switch.packethandler</groupId>
+      <artifactId>packethandler-impl</artifactId>
+      <version>${l2switch.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.l2switch.packethandler</groupId>
+      <artifactId>packethandler-config</artifactId>
+      <version>${l2switch.version}</version>
+      <type>xml</type>
+      <classifier>config</classifier>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.l2switch.addresstracker</groupId>
+      <artifactId>addresstracker-model</artifactId>
+      <version>${l2switch.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.l2switch.addresstracker</groupId>
+      <artifactId>addresstracker-config</artifactId>
+      <version>${l2switch.version}</version>
+      <type>xml</type>
+      <classifier>config</classifier>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.l2switch.addresstracker</groupId>
+      <artifactId>addresstracker-impl</artifactId>
+      <version>${l2switch.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.l2switch.loopremover</groupId>
+      <artifactId>loopremover-model</artifactId>
+      <version>${l2switch.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.l2switch.loopremover</groupId>
+      <artifactId>loopremover-impl</artifactId>
+      <version>${l2switch.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.l2switch.loopremover</groupId>
+      <artifactId>loopremover-config</artifactId>
+      <version>${l2switch.version}</version>
+      <type>xml</type>
+      <classifier>config</classifier>
+    </dependency>
     <dependency>
       <groupId>org.opendaylight.l2switch.hosttracker</groupId>
       <artifactId>hosttracker-model</artifactId>
       <version>${l2switch.version}</version>
-      <type>jar</type>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.l2switch.hosttracker</groupId>
+      <artifactId>hosttracker-impl</artifactId>
+      <version>${l2switch.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.l2switch.hosttracker</groupId>
+      <artifactId>hosttracker-config</artifactId>
+      <version>${l2switch.version}</version>
+      <type>xml</type>
+      <classifier>config</classifier>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.l2switch.arphandler</groupId>
+      <artifactId>arphandler-impl</artifactId>
+      <version>${l2switch.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.alto.spce.network</groupId>
+      <artifactId>network-tracker-config</artifactId>
+      <version>${project.version}</version>
+      <type>xml</type>
+      <classifier>config</classifier>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.alto.spce.network</groupId>
+      <artifactId>network-tracker-impl</artifactId>
+      <version>${project.version}</version>
+      <scope>runtime</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.alto.spce.network</groupId>
+      <artifactId>network-tracker-impl</artifactId>
+      <version>${project.version}</version>
+      <type>xml</type>
+      <classifier>config</classifier>
+      <scope>runtime</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.alto.spce.network</groupId>
+      <artifactId>network-tracker-api</artifactId>
+      <version>${project.version}</version>
+      <scope>runtime</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.alto.ext</groupId>
+      <artifactId>alto-spce-impl</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.alto.ext</groupId>
+      <artifactId>alto-spce-impl</artifactId>
+      <version>${project.version}</version>
+      <type>xml</type>
+      <classifier>config</classifier>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.alto.ext</groupId>
+      <artifactId>alto-spce-api</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+
     <dependency>
       <groupId>${project.groupId}.basic</groupId>
       <artifactId>endpointcostservice-impl</artifactId>
index 3c3dd8f189fedb915fda890bd10c76e3da77e295..99dedc16b257f681cc68a07459e1897799ae18b6 100644 (file)
@@ -46,6 +46,57 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
     <feature version='${project.version}'>odl-alto-nonstandard-types</feature>
     <feature version='${project.version}'>odl-alto-nonstandard-service-models</feature>
     <feature version='${project.version}'>odl-alto-nonstandard-northbound-route</feature>
+    <feature version='${project.version}'>odl-alto-spce</feature>
+  </feature>
+
+  <feature name='odl-alto-spce' version='${project.version}'
+            description='OpenDaylight :: alto :: SPCE'>
+    <feature version='${mdsal.model.version}'>odl-mdsal-models</feature>
+    <feature version='${mdsal.version}'>odl-mdsal-broker</feature>
+    <feature version="${openflow.plugin.version}">odl-openflowplugin-flow-services</feature>
+    <feature version="${openflow.plugin.version}">odl-openflowplugin-southbound</feature>
+
+    <bundle>mvn:org.opendaylight.l2switch.packethandler/packethandler-model/${l2switch.version}</bundle>
+    <bundle>mvn:org.opendaylight.l2switch.packethandler/packethandler-impl/${l2switch.version}</bundle>
+    <configfile finalname="${configfile.directory}/${l2switch.packethandler.configfile}">
+      mvn:org.opendaylight.l2switch.packethandler/packethandler-config/${l2switch.version}/xml/config
+    </configfile>
+
+    <bundle>mvn:org.opendaylight.l2switch.loopremover/loopremover-model/${l2switch.version}</bundle>
+    <bundle>mvn:org.opendaylight.l2switch.loopremover/loopremover-impl/${l2switch.version}</bundle>
+    <bundle>mvn:org.opendaylight.controller.thirdparty/net.sf.jung2/2.0.1</bundle>
+    <configfile finalname="${configfile.directory}/${l2switch.loopremover.configfile}">
+      mvn:org.opendaylight.l2switch.loopremover/loopremover-config/${l2switch.version}/xml/config
+    </configfile>
+
+    <bundle>mvn:org.opendaylight.l2switch.hosttracker/hosttracker-model/${l2switch.version}</bundle>
+    <bundle>mvn:org.opendaylight.l2switch.hosttracker/hosttracker-impl/${l2switch.version}</bundle>
+    <configfile finalname="${configfile.directory}/${l2switch.hosttracker.configfile}">
+      mvn:org.opendaylight.l2switch.hosttracker/hosttracker-config/${l2switch.version}/xml/config
+    </configfile>
+
+    <bundle>mvn:org.opendaylight.l2switch.addresstracker/addresstracker-model/${l2switch.version}</bundle>
+    <bundle>mvn:org.opendaylight.l2switch.arphandler/arphandler-impl/${l2switch.version}</bundle>
+    <configfile finalname="${configfile.directory}/54-alto-arphandler.xml">
+      mvn:org.opendaylight.alto.spce.network/network-tracker-config/${project.version}/xml/config
+    </configfile>
+
+    <bundle>mvn:org.opendaylight.l2switch.addresstracker/addresstracker-impl/${l2switch.version}</bundle>
+    <configfile finalname="${configfile.directory}/${l2switch.addresstracker.configfile}">
+      mvn:org.opendaylight.l2switch.addresstracker/addresstracker-config/${l2switch.version}/xml/config
+    </configfile>
+
+    <bundle>mvn:org.opendaylight.alto.spce.network/network-tracker-api/${project.version}</bundle>
+    <bundle>mvn:org.opendaylight.alto.spce.network/network-tracker-impl/${project.version}</bundle>
+    <configfile finalname="${configfile.directory}/network-tracker.xml">
+      mvn:org.opendaylight.alto.spce.network/network-tracker-impl/${project.version}/xml/config
+    </configfile>
+
+    <bundle>mvn:org.opendaylight.alto.ext/alto-spce-api/${project.version}</bundle>
+    <bundle>mvn:org.opendaylight.alto.ext/alto-spce-impl/${project.version}</bundle>
+    <configfile finalname="${configfile.directory}/alto-spce.xml">
+      mvn:org.opendaylight.alto.ext/alto-spce-impl/${project.version}/xml/config
+    </configfile>
   </feature>
 
   <feature name='odl-alto-standard-types' version='${project.version}'
diff --git a/pom.xml b/pom.xml
index 2cbb90f15a4d79d48764155617024ea185b0502c..4a178c6d39c7850d24ddfdf87dc3f51ae61f6b29 100644 (file)
--- a/pom.xml
+++ b/pom.xml
@@ -37,6 +37,7 @@ and is available at http://www.eclipse.org/legal/epl-v10.html INTERNAL
   <modules>
     <module>alto-core</module>
     <module>alto-basic</module>
+    <module>alto-extensions</module>
     <module>alto-release-features</module>
   </modules>