-.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
<packaging>pom</packaging>
<modules>
- <module>fs-map</module>
- <module>fake</module>
- <module>cli</module>
+ <module>simple-pce</module>
</modules>
</project>
--- /dev/null
+# 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
+```
--- /dev/null
+# 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'])
+```
--- /dev/null
+<?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>
--- /dev/null
+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;
+ }
+ }
+ }
+}
--- /dev/null
+<?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>
--- /dev/null
+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
--- /dev/null
+<?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>
--- /dev/null
+<?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>
--- /dev/null
+<?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>
--- /dev/null
+<?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&revision=2014-12-10</capability>
+ <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding?module=opendaylight-md-sal-binding&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>
--- /dev/null
+<?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>
--- /dev/null
+/*
+ * 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;
+ }
+}
--- /dev/null
+/*
+ * 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();
+ }
+ }
+}
--- /dev/null
+/*
+ * 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;
+ }
+
+}
--- /dev/null
+/*
+ * 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]+$", "");
+ }
+}
--- /dev/null
+/*
+ * 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());
+ }
+}
--- /dev/null
+/*
+ * 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);
+ }
+}
--- /dev/null
+/*
+ * 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;
+ }
+}
--- /dev/null
+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;
+ }
+
+}
--- /dev/null
+/*
+* 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 {
+
+}
--- /dev/null
+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;
+ }
+ }
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ * 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;
+ }
+
+}
--- /dev/null
+<?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>
--- /dev/null
+<?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>
--- /dev/null
+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;
+ }
+ }
+ }
+}
--- /dev/null
+<?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>
--- /dev/null
+<?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>
--- /dev/null
+<?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&revision=2014-05-28</capability>
+ <capability>urn:opendaylight:l2switch:loopremover?module=stp-status-aware-node-connector&revision=2014-07-14</capability>
+ </required-capabilities>
+</snapshot>
+
--- /dev/null
+<?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>
--- /dev/null
+<?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>
--- /dev/null
+<?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>
--- /dev/null
+<?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>
--- /dev/null
+<?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&revision=2014-12-10</capability>
+ <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding?module=opendaylight-md-sal-binding&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>
--- /dev/null
+<?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>
--- /dev/null
+/*
+ * 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);
+
+}
--- /dev/null
+/*
+ * 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};
+}
--- /dev/null
+/*
+ * 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());
+ }
+ }
+ }
+ });
+ }
+}
--- /dev/null
+/*
+ * 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;
+ }
+}
--- /dev/null
+/*
+ * 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");
+ }
+
+}
--- /dev/null
+/*
+ * 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();
+ }
+}
--- /dev/null
+/*
+ * 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();
+ }
+}
--- /dev/null
+/*
+ * 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]+$", "");
+ }
+
+}
+
--- /dev/null
+/*
+ * 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();
+}
+
--- /dev/null
+/*
+ * 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);
+ }
+}
--- /dev/null
+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;
+ }
+
+}
--- /dev/null
+/*
+* 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 {
+
+}
--- /dev/null
+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;
+ }
+ }
+ }
+ }
+ }
+}
--- /dev/null
+<?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>
--- /dev/null
+<?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>
<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>
<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>
<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}'
<modules>
<module>alto-core</module>
<module>alto-basic</module>
+ <module>alto-extensions</module>
<module>alto-release-features</module>
</modules>