Endpointcost Service Impl 71/31971/1
authorSheldenShen <shenxvdong1@gmail.com>
Thu, 31 Dec 2015 11:10:52 +0000 (19:10 +0800)
committerSheldenShen <shenxvdong1@gmail.com>
Thu, 31 Dec 2015 11:16:27 +0000 (19:16 +0800)
Change-Id: I7f37775b2975fb22339dc4479008c10d265150ae
Signed-off-by: SheldenShen <shenxvdong1@gmail.com>
51 files changed:
alto-basic/endpointcostservice/api/pom.xml [new file with mode: 0644]
alto-basic/endpointcostservice/api/src/main/yang/endpointcostservice.yang [new file with mode: 0644]
alto-basic/endpointcostservice/artifacts/pom.xml [new file with mode: 0644]
alto-basic/endpointcostservice/features/pom.xml [new file with mode: 0644]
alto-basic/endpointcostservice/features/src/main/features/features.xml [new file with mode: 0644]
alto-basic/endpointcostservice/hostnodetracker/pom.xml [new file with mode: 0644]
alto-basic/endpointcostservice/hostnodetracker/src/main/java/org/opendaylight/alto/basic/hostnode/tracker/topology/api/HostNodeTrackerService.java [new file with mode: 0644]
alto-basic/endpointcostservice/hostnodetracker/src/main/java/org/opendaylight/alto/basic/hostnode/tracker/topology/impl/HostNodeTrackerImpl.java [new file with mode: 0644]
alto-basic/endpointcostservice/impl/pom.xml [new file with mode: 0644]
alto-basic/endpointcostservice/impl/src/main/config/default-config.xml [new file with mode: 0644]
alto-basic/endpointcostservice/impl/src/main/config/maven-metadata-local.xml [new file with mode: 0644]
alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/flow/FlowEntryMatcher.java [new file with mode: 0644]
alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/flow/FlowTableMatcher.java [new file with mode: 0644]
alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/flow/MatchFields.java [new file with mode: 0644]
alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/helper/DataStoreHelper.java [new file with mode: 0644]
alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/helper/IPPrefixHelper.java [new file with mode: 0644]
alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/helper/ServiceHelper.java [new file with mode: 0644]
alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/helper/UtilHelper.java [new file with mode: 0644]
alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/impl/BasicECSImplementation.java [new file with mode: 0644]
alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/impl/EndpointcostserviceProvider.java [new file with mode: 0644]
alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/impl/base/BaseECSImplementation.java [new file with mode: 0644]
alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/suportservice/exception/ReadDataFailedException.java [new file with mode: 0644]
alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/suportservice/impl/HostNodeTrackerImpl.java [new file with mode: 0644]
alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/suportservice/impl/LinkServiceImpl.java [new file with mode: 0644]
alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/suportservice/impl/NetworkElementImpl.java [new file with mode: 0644]
alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/suportservice/impl/NetworkFlowCapableNodeImpl.java [new file with mode: 0644]
alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/suportservice/impl/NetworkHostNodeImpl.java [new file with mode: 0644]
alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/suportservice/impl/NetworkPortStatisticsServiceImpl.java [new file with mode: 0644]
alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/suportservice/impl/RoutingServiceImpl.java [new file with mode: 0644]
alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/suportservice/service/HostNodeTrackerService.java [new file with mode: 0644]
alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/suportservice/service/LinkService.java [new file with mode: 0644]
alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/suportservice/service/NetworkElementService.java [new file with mode: 0644]
alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/suportservice/service/NetworkFlowCapableNodeService.java [new file with mode: 0644]
alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/suportservice/service/NetworkHostNodeService.java [new file with mode: 0644]
alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/suportservice/service/NetworkPortStatisticsService.java [new file with mode: 0644]
alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/suportservice/service/RoutingService.java [new file with mode: 0644]
alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/util/InstanceIdentifierUtils.java [new file with mode: 0644]
alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/util/LinkNode.java [new file with mode: 0644]
alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/util/NameConverter.java [new file with mode: 0644]
alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/util/NetworkServiceConstants.java [new file with mode: 0644]
alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/util/RouteServiceConstants.java [new file with mode: 0644]
alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/endpointcostservice/impl/rev141210/EndpointcostserviceModule.java [new file with mode: 0644]
alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/endpointcostservice/impl/rev141210/EndpointcostserviceModuleFactory.java [new file with mode: 0644]
alto-basic/endpointcostservice/impl/src/main/yang/endpointcostservice-impl.yang [new file with mode: 0644]
alto-basic/endpointcostservice/impl/src/test/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/endpointcostservice/impl/rev141210/EndpointcostserviceModuleFactoryTest.java [new file with mode: 0644]
alto-basic/endpointcostservice/impl/src/test/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/endpointcostservice/impl/rev141210/EndpointcostserviceModuleTest.java [new file with mode: 0644]
alto-basic/endpointcostservice/it/pom.xml [new file with mode: 0644]
alto-basic/endpointcostservice/it/src/test/java/org/opendaylight/alto/basic/endpointcostservice/it/EndpointcostserviceIT.java [new file with mode: 0644]
alto-basic/endpointcostservice/karaf/pom.xml [new file with mode: 0644]
alto-basic/endpointcostservice/pom.xml [new file with mode: 0644]
alto-basic/pom.xml

diff --git a/alto-basic/endpointcostservice/api/pom.xml b/alto-basic/endpointcostservice/api/pom.xml
new file mode 100644 (file)
index 0000000..897939f
--- /dev/null
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright © 2015 Yale 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
+-->
+<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.8.0-SNAPSHOT</version>
+    <relativePath/>
+  </parent>
+
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.opendaylight.alto.basic</groupId>
+  <artifactId>endpointcostservice-api</artifactId>
+  <version>0.2.0-SNAPSHOT</version>
+  <packaging>bundle</packaging>
+
+</project>
diff --git a/alto-basic/endpointcostservice/api/src/main/yang/endpointcostservice.yang b/alto-basic/endpointcostservice/api/src/main/yang/endpointcostservice.yang
new file mode 100644 (file)
index 0000000..9a2103e
--- /dev/null
@@ -0,0 +1,9 @@
+module endpointcostservice {
+    yang-version 1;
+    namespace "urn:opendaylight:params:xml:ns:yang:endpointcostservice";
+    prefix "endpointcostservice";
+
+    revision "2015-01-05" {
+        description "Initial revision of endpointcostservice model";
+    }
+}
diff --git a/alto-basic/endpointcostservice/artifacts/pom.xml b/alto-basic/endpointcostservice/artifacts/pom.xml
new file mode 100644 (file)
index 0000000..0062a09
--- /dev/null
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright © 2015 Yale 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
+-->
+
+<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.alto</groupId>
+    <artifactId>alto-parent</artifactId>
+    <version>0.2.0-SNAPSHOT</version>
+    <relativePath>../../../</relativePath>
+  </parent>
+
+  <groupId>org.opendaylight.alto.basic</groupId>
+  <artifactId>endpointcostservice-artifacts</artifactId>
+  <version>0.2.0-SNAPSHOT</version>
+  <packaging>pom</packaging>
+
+  <dependencyManagement>
+    <dependencies>
+      <dependency>
+        <groupId>${project.groupId}</groupId>
+        <artifactId>endpointcostservice-api</artifactId>
+        <version>${project.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>${project.groupId}</groupId>
+        <artifactId>endpointcostservice-impl</artifactId>
+        <version>${project.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>${project.groupId}</groupId>
+        <artifactId>endpointcostservice-features</artifactId>
+        <version>${project.version}</version>
+        <classifier>features</classifier>
+        <type>xml</type>
+      </dependency>
+    </dependencies>
+  </dependencyManagement>
+</project>
diff --git a/alto-basic/endpointcostservice/features/pom.xml b/alto-basic/endpointcostservice/features/pom.xml
new file mode 100644 (file)
index 0000000..271072f
--- /dev/null
@@ -0,0 +1,197 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright © 2015 Yale 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 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.6.0-SNAPSHOT</version>
+    <relativePath/>
+  </parent>
+  <groupId>org.opendaylight.alto.basic</groupId>
+  <artifactId>endpointcostservice-features</artifactId>
+  <version>0.2.0-SNAPSHOT</version>
+  <name>${project.artifactId}</name>
+  <modelVersion>4.0.0</modelVersion>
+  <prerequisites>
+    <maven>3.1.1</maven>
+  </prerequisites>
+  <properties>
+    <mdsal.model.version>0.8.0-SNAPSHOT</mdsal.model.version>
+    <mdsal.version>1.3.0-SNAPSHOT</mdsal.version>
+    <restconf.version>1.3.0-SNAPSHOT</restconf.version>
+    <yangtools.version>0.8.0-SNAPSHOT</yangtools.version>
+    <dlux.version>0.3.0-SNAPSHOT</dlux.version>
+    <configfile.directory>etc/opendaylight/karaf</configfile.directory>
+    <l2switch.version>0.3.0-SNAPSHOT</l2switch.version>
+    <openflow.plugin.version>0.2.0-SNAPSHOT</openflow.plugin.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>org.opendaylight.alto.core</groupId>
+      <artifactId>alto-northbound-features</artifactId>
+      <version>${project.version}</version>
+      <classifier>features</classifier>
+      <type>xml</type>
+      <scope>runtime</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.alto.core</groupId>
+      <artifactId>alto-resourcepool-features</artifactId>
+      <classifier>features</classifier>
+      <version>${project.version}</version>
+      <type>xml</type>
+      <scope>runtime</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.alto.core</groupId>
+      <artifactId>alto-service-model-networkmap-features</artifactId>
+      <classifier>features</classifier>
+      <version>${project.version}</version>
+      <type>xml</type>
+      <scope>runtime</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.alto.core</groupId>
+      <artifactId>alto-service-model-endpointcost-features</artifactId>
+      <classifier>features</classifier>
+      <version>${project.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>org.opendaylight.alto.core</groupId>
+      <artifactId>alto-service-model-base-api</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.alto.core</groupId>
+      <artifactId>alto-service-model-ird-api</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>endpointcostservice-impl</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>endpointcostservice-impl</artifactId>
+      <version>${project.version}</version>
+      <type>xml</type>
+      <classifier>config</classifier>
+    </dependency>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>endpointcostservice-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.openflowplugin.model</groupId>
+      <artifactId>model-flow-statistics</artifactId>
+      <version>${openflow.plugin.version}</version>
+      <type>jar</type>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.l2switch</groupId>
+      <artifactId>features-l2switch</artifactId>
+      <classifier>features</classifier>
+      <version>${l2switch.version}</version>
+      <type>xml</type>
+      <scope>runtime</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.l2switch.addresstracker</groupId>
+      <artifactId>addresstracker-model</artifactId>
+      <version>${l2switch.version}</version>
+      <type>jar</type>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.l2switch.hosttracker</groupId>
+      <artifactId>hosttracker-model</artifactId>
+      <version>${l2switch.version}</version>
+      <type>jar</type>
+    </dependency>
+  </dependencies>
+</project>
diff --git a/alto-basic/endpointcostservice/features/src/main/features/features.xml b/alto-basic/endpointcostservice/features/src/main/features/features.xml
new file mode 100644 (file)
index 0000000..f4253ac
--- /dev/null
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+Copyright © 2015 Yale 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-endpointcostservice-${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.alto.core/alto-resourcepool-features/${project.version}/xml/features</repository>
+  <repository>mvn:org.opendaylight.alto.core/alto-northbound-features/${project.version}/xml/features</repository>
+  <repository>mvn:org.opendaylight.alto.core/alto-service-model-networkmap-features/${project.version}/xml/features</repository>
+  <repository>mvn:org.opendaylight.alto.core/alto-service-model-endpointcost-features/${project.version}/xml/features</repository>
+  <repository>mvn:org.opendaylight.l2switch/features-l2switch/${l2switch.version}/xml/features</repository>
+  <repository>mvn:org.opendaylight.openflowplugin/features-openflowplugin/${openflow.plugin.version}/xml/features</repository>
+
+  <feature name='odl-endpointcostservice-api' version='${project.version}' description='OpenDaylight :: endpointcostservice :: api'>
+    <feature version='${mdsal.model.version}'>odl-mdsal-models</feature>
+    <feature version='${project.version}'>odl-alto-resourcepool-api</feature>
+    <bundle>mvn:org.opendaylight.alto.core/alto-service-model-base-api/${project.version}</bundle>
+    <bundle>mvn:org.opendaylight.alto.core/alto-service-model-networkmap-api/${project.version}</bundle>
+    <bundle>mvn:org.opendaylight.alto.core/alto-service-model-endpointcost-api/${project.version}</bundle>
+    <bundle>mvn:org.opendaylight.alto.basic/endpointcostservice-api/${project.version}</bundle>
+  </feature>
+  <feature name='odl-endpointcostservice' version='${project.version}' description='OpenDaylight :: endpointcostservice'>
+    <feature version='${mdsal.version}'>odl-mdsal-broker</feature>
+    <feature version='${project.version}'>odl-endpointcostservice-api</feature>
+    <feature version='${project.version}'>odl-alto-northbound</feature>
+    <feature version='${project.version}'>odl-alto-resourcepool</feature>
+    <feature version='${project.version}'>odl-alto-service-model-networkmap</feature>
+    <feature version='${project.version}'>odl-alto-service-model-endpointcost</feature>
+    <feature version='${l2switch.version}'>odl-l2switch-hosttracker</feature>
+    <feature version='${l2switch.version}'>odl-l2switch-addresstracker</feature>
+    <feature version='${openflow.plugin.version}'>odl-openflowplugin-flow-services</feature>
+    <bundle>mvn:org.opendaylight.alto.basic/endpointcostservice-impl/${project.version}</bundle>
+    <configfile finalname="${configfile.directory}/endpointcostservice.xml">mvn:org.opendaylight.alto.basic/endpointcostservice-impl/${project.version}/xml/config</configfile>
+  </feature>
+  <feature name='odl-endpointcostservice-rest' version='${project.version}' description='OpenDaylight :: endpointcostservice :: REST'>
+    <feature version="${project.version}">odl-endpointcostservice</feature>
+    <feature version="${restconf.version}">odl-restconf</feature>
+  </feature>
+  <feature name='odl-endpointcostservice-ui' version='${project.version}' description='OpenDaylight :: endpointcostservice :: UI'>
+    <feature version="${project.version}">odl-endpointcostservice-rest</feature>
+    <feature version="${restconf.version}">odl-mdsal-apidocs</feature>
+    <feature version="${mdsal.version}">odl-mdsal-xsql</feature>
+    <feature version="${dlux.version}">odl-dlux-yangui</feature>
+  </feature>
+
+</features>
diff --git a/alto-basic/endpointcostservice/hostnodetracker/pom.xml b/alto-basic/endpointcostservice/hostnodetracker/pom.xml
new file mode 100644 (file)
index 0000000..31e7542
--- /dev/null
@@ -0,0 +1,62 @@
+<?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">
+    <parent>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>config-parent</artifactId>
+        <version>0.4.0-SNAPSHOT</version>
+        <relativePath/>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>org.opendaylight.alto.basic.endpointcostservice</groupId>
+    <artifactId>hostnodetracker</artifactId>
+    <version>0.2.0-SNAPSHOT</version>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <source>1.6</source>
+                    <target>1.6</target>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+    <packaging>bundle</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.opendaylight.l2switch.hosttracker</groupId>
+            <artifactId>hosttracker-model</artifactId>
+            <version>0.4.0-SNAPSHOT</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.opendaylight.l2switch.addresstracker</groupId>
+            <artifactId>addresstracker-model</artifactId>
+            <version>0.4.0-SNAPSHOT</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.opendaylight.alto.core</groupId>
+            <artifactId>alto-service-model-base-api</artifactId>
+            <version>0.2.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.alto.core</groupId>
+            <artifactId>alto-service-model-endpointcost-api</artifactId>
+            <version>0.2.0-SNAPSHOT</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-binding-api</artifactId>
+            <version>1.4.0-SNAPSHOT</version>
+        </dependency>
+    </dependencies>
+
+</project>
\ No newline at end of file
diff --git a/alto-basic/endpointcostservice/hostnodetracker/src/main/java/org/opendaylight/alto/basic/hostnode/tracker/topology/api/HostNodeTrackerService.java b/alto-basic/endpointcostservice/hostnodetracker/src/main/java/org/opendaylight/alto/basic/hostnode/tracker/topology/api/HostNodeTrackerService.java
new file mode 100644 (file)
index 0000000..c453c65
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * Copyright © 2015 Yale 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.basic.hostnode.tracker.topology.api;
+
+public interface HostNodeTrackerService {
+    String getIpByMac(String macAddress);
+
+    String getMacByIp(String ipAddress);
+
+    Boolean isValidHost(String ipAddress);
+}
diff --git a/alto-basic/endpointcostservice/hostnodetracker/src/main/java/org/opendaylight/alto/basic/hostnode/tracker/topology/impl/HostNodeTrackerImpl.java b/alto-basic/endpointcostservice/hostnodetracker/src/main/java/org/opendaylight/alto/basic/hostnode/tracker/topology/impl/HostNodeTrackerImpl.java
new file mode 100644 (file)
index 0000000..7e574ce
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * Copyright © 2015 Yale 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.basic.hostnode.tracker.topology.impl;
+
+import org.opendaylight.alto.basic.hostnode.tracker.topology.api.HostNodeTrackerService;
+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 HostNodeTrackerImpl implements HostNodeTrackerService,DataChangeListener{
+    private static final Logger log = LoggerFactory
+            .getLogger(HostNodeTrackerImpl.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 HostNodeTrackerImpl  (DataBroker dataBroker) {
+        this.log.info("AddressConvertServiceImpl initial.");
+        this.dataBroker = dataBroker;
+        macToIp = new HashMap<String,String>();
+        ipToMac = new HashMap<String,String>();
+        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);
+    }
+    public String getIpByMac(String macAddress) {
+        return this.macToIp.get(macAddress);
+    }
+
+    public String getMacByIp(String ipAddress) {
+        return this.ipToMac.get(ipAddress);
+    }
+
+    public Boolean isValidHost(String ipAddress) {
+        return this.ipToMac.containsKey(ipAddress);
+    }
+
+    public void onDataChanged(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
+        exec.submit(new Runnable() {
+            @Override
+            public void run() {
+                if (change == null) {
+                    log.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) {
+                    log.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);
+                        log.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;
+                        log.info("createdData addresses:" + addrs);
+                        macToIp.put(addrs.getMac().getValue(), addrs.getIp().getIpv4Address().getValue());
+                        ipToMac.put(addrs.getIp().getIpv4Address().getValue(), addrs.getMac().getValue());
+                    }
+                }
+            }
+        });
+    }
+
+}
diff --git a/alto-basic/endpointcostservice/impl/pom.xml b/alto-basic/endpointcostservice/impl/pom.xml
new file mode 100644 (file)
index 0000000..826f617
--- /dev/null
@@ -0,0 +1,94 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+Copyright © 2015 Yale 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
+-->
+<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.4.0-SNAPSHOT</version>
+    <relativePath/>
+  </parent>
+
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.opendaylight.alto.basic</groupId>
+  <artifactId>endpointcostservice-impl</artifactId>
+  <version>0.2.0-SNAPSHOT</version>
+  <packaging>bundle</packaging>
+  <dependencies>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>endpointcostservice-api</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+
+    <dependency>
+      <groupId>org.opendaylight.alto.core</groupId>
+      <artifactId>alto-resourcepool-api</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+
+    <dependency>
+      <groupId>org.opendaylight.alto.core</groupId>
+      <artifactId>alto-service-model-networkmap-api</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+
+    <dependency>
+      <groupId>org.opendaylight.alto.core</groupId>
+      <artifactId>alto-service-model-endpointcost-api</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+
+    <dependency>
+      <groupId>org.opendaylight.alto.core</groupId>
+      <artifactId>alto-northbound-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.l2switch.hosttracker</groupId>
+      <artifactId>hosttracker-model</artifactId>
+      <version>0.3.0-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.l2switch.addresstracker</groupId>
+      <artifactId>addresstracker-model</artifactId>
+      <version>0.3.0-SNAPSHOT</version>
+    </dependency>
+
+    <dependency>
+      <groupId>org.opendaylight.controller.model</groupId>
+      <artifactId>model-inventory</artifactId>
+      <version>${mdsal.version}</version>
+      <type>jar</type>
+    </dependency>
+
+    <dependency>
+      <groupId>org.opendaylight.openflowplugin.model</groupId>
+      <artifactId>model-flow-statistics</artifactId>
+      <version>0.2.0-SNAPSHOT</version>
+    </dependency>
+  </dependencies>
+
+</project>
diff --git a/alto-basic/endpointcostservice/impl/src/main/config/default-config.xml b/alto-basic/endpointcostservice/impl/src/main/config/default-config.xml
new file mode 100644 (file)
index 0000000..6e6ba33
--- /dev/null
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+Copyright © 2015 Yale 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:params:xml:ns:yang:endpointcostservice:impl?module=endpointcostservice-impl&amp;revision=2014-12-10</capability>
+      <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding?module=opendaylight-md-sal-binding&amp;revision=2013-10-28</capability>
+  </required-capabilities>
+  <configuration>
+
+    <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+      <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+        <module>
+          <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:endpointcostservice:impl">prefix:endpointcostservice</type>
+          <name>endpointcostservice-default</name>
+          <broker>
+            <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-broker-osgi-registry</type>
+            <name>binding-osgi-broker</name>
+          </broker>
+        </module>
+      </modules>
+    </data>
+  </configuration>
+</snapshot>
diff --git a/alto-basic/endpointcostservice/impl/src/main/config/maven-metadata-local.xml b/alto-basic/endpointcostservice/impl/src/main/config/maven-metadata-local.xml
new file mode 100644 (file)
index 0000000..49bc7a3
--- /dev/null
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<metadata modelVersion="1.1.0">
+  <groupId>org.opendaylight.alto.basic.endpointcostservice</groupId>
+  <artifactId>endpointcostservice-impl</artifactId>
+  <version>1.0.0-SNAPSHOT</version>
+  <versioning>
+    <snapshot>
+      <localCopy>true</localCopy>
+    </snapshot>
+    <lastUpdated>20151224114708</lastUpdated>
+    <snapshotVersions>
+      <snapshotVersion>
+        <classifier>config</classifier>
+        <extension>xml</extension>
+        <value>1.0.0-SNAPSHOT</value>
+        <updated>20151224114708</updated>
+      </snapshotVersion>
+    </snapshotVersions>
+  </versioning>
+</metadata>
diff --git a/alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/flow/FlowEntryMatcher.java b/alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/flow/FlowEntryMatcher.java
new file mode 100644 (file)
index 0000000..51b47c3
--- /dev/null
@@ -0,0 +1,427 @@
+/*
+ * Copyright (c) 2015 Yale 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.basic.endpointcostservice.flow;
+
+import org.opendaylight.alto.basic.endpointcostservice.helper.IPPrefixHelper;
+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.inet.types.rev100924.Ipv6Prefix;
+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.service.model.endpointcost.rfc7285.rev151021.TypedAddressData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetDestination;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetSource;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ipv6.match.fields.Ipv6ExtHeader;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ipv6.match.fields.Ipv6Label;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.IpMatch;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Metadata;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Tunnel;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatch;
+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.ProtocolMatchFields;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.TcpFlagMatch;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Icmpv4Match;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Icmpv6Match;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Layer4Match;
+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.ArpMatch;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4Match;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv6Match;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.TunnelIpv4Match;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.SctpMatch;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.TcpMatch;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.UdpMatch;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.protocol.match.fields.Pbb;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.vlan.match.fields.VlanId;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.net.UnknownHostException;
+
+public class FlowEntryMatcher {
+    private static final Logger log = LoggerFactory
+            .getLogger(FlowEntryMatcher.class);
+
+    /**
+     * @param match is the original fields should be matched.
+     * @param matchFields are the target fields should be compared.
+     * @return the result of match.
+     */
+    public boolean match(Match match, MatchFields matchFields) {
+        log.info("Flow Entry Matching Start");
+        return (match == null) ||
+                ((matchInPort(match.getInPort(), matchFields)
+                        && matchInPhyPort(match.getInPhyPort(), matchFields)
+                        && matchIp(match.getIpMatch(), matchFields)
+                        && matchVlan(match.getVlanMatch(), matchFields)
+                        && matchTunnel(match.getTunnel(), matchFields)
+                        && matchMetadata(match.getMetadata(), matchFields)
+                        && matchEthernet(match.getEthernetMatch(), matchFields)
+                        && matchLayer3(match.getLayer3Match(), matchFields)
+                        && matchLayer4(match.getLayer4Match(), matchFields)
+                        && matchIcmpv4Match(match.getIcmpv4Match(), matchFields)
+                        && matchIcmpv6Match(match.getIcmpv6Match(), matchFields)
+                        && matchProtocolMatchFields(match.getProtocolMatchFields(), matchFields)
+                        && matchTcpFlag(match.getTcpFlagMatch(), matchFields)));
+    }
+
+    /**
+     * Match if port is equal.
+     * @param port is the port filed in a flow entry.
+     * @param matchFields are the target fields should be compared.
+     * @return the result of match.
+     */
+    public boolean matchInPort(NodeConnectorId port, MatchFields matchFields) {
+        if (port == null) return true;
+        String flowInPort = port.getValue();
+        return flowInPort.equals(matchFields.inPort);
+    }
+
+    /**
+     * Match if port is a physical port.
+     * @param port is the port field in a flow entry.
+     * @param matchFields are the target fields should be compared.
+     * @return the result of match.
+     */
+    public boolean matchInPhyPort(NodeConnectorId port, MatchFields matchFields) {
+        return (port == null);
+    }
+
+    /**
+     * Match if IP is equal.
+     * @param ipMatch is the IP address in the flow entry.
+     * @param matchFields are the target fields should be compared.
+     * @return the result of match.
+     */
+    public boolean matchIp(IpMatch ipMatch, MatchFields matchFields) {
+        return (ipMatch == null) ||
+                (ipMatch.getIpProtocol() == null && ipMatch.getIpDscp() == null
+                        && ipMatch.getIpEcn() == null && ipMatch.getIpProto() == null);
+    }
+
+    /**
+     * Match if VLAN is equal.
+     * @param match is the VLAN field in flow entry.
+     * @param matchFields are the target fields should be compared.
+     * @return the result of match.
+     */
+    public boolean matchVlan(VlanMatch match, MatchFields matchFields) {
+        return (match == null) || (match.getVlanPcp() == null
+                && matchVlanId(match.getVlanId()));
+    }
+
+    private boolean matchVlanId(VlanId id) {
+        return (id == null) || (!id.isVlanIdPresent());
+    }
+
+    /**
+     * Match if tunnel is equal.
+     * @param tunnel is the tunnel field in flow entry.
+     * @param matchFields are the target fields should be compared.
+     * @return the result of match.
+     */
+    public boolean matchTunnel(Tunnel tunnel, MatchFields matchFields) {
+        return (tunnel == null) ||
+                (tunnel.getTunnelId() == null && tunnel.getTunnelMask() == null);
+    }
+
+    /**
+     * Match if metadata is equal.
+     * @param meta is the metadata in flow entry.
+     * @param matchFields are the target fields should be compared.
+     * @return the result of match.
+     */
+    public boolean matchMetadata(Metadata meta, MatchFields matchFields) {
+        return (meta == null) ||
+                (meta.getMetadata() == null && meta.getMetadataMask() == null);
+    }
+
+    /**
+     * Match if ethernet is equal.
+     * @param match is the ethernet in flow entry.
+     * @param matchFields are the target fields should be compared.
+     * @return the result of match.
+     */
+    public boolean matchEthernet(EthernetMatch match, MatchFields matchFields) {
+        return (match == null)
+                || (matchEthernetSrc(match.getEthernetSource(), matchFields)
+                && matchEthernetDst(match.getEthernetDestination(), matchFields)
+                && matchEthernetType(match.getEthernetType(), matchFields));
+    }
+
+    private boolean matchEthernetSrc(EthernetSource ethSrc, MatchFields matchFields) {
+        return (ethSrc == null) ||
+                matchMacAddressWithMask(ethSrc.getAddress(), matchFields.srcMac, ethSrc.getMask());
+    }
+
+    private boolean matchEthernetDst(EthernetDestination ethDest, MatchFields matchFields) {
+        return (ethDest == null) ||
+                matchMacAddressWithMask(ethDest.getAddress(), matchFields.dstMac, ethDest.getMask());
+    }
+
+    private String normalizeMacAddress(MacAddress mac) {
+        return mac.getValue().replaceAll(":|-", "").toLowerCase();
+    }
+
+    private long getMaskedMacAddress(String macAddress, String mask) {
+        long macLong = (Long.parseLong(macAddress,16));
+        long maskLong = Long.parseLong(mask,16);
+        return macLong & maskLong;
+    }
+
+    /**
+     * Match the MAC address with a mask.
+     * @param macA MAC address A.
+     * @param macB MAC address B.
+     * @param mask to XOR with MAC address.
+     * @return the result of match.
+     */
+    public boolean matchMacAddressWithMask(MacAddress macA, MacAddress macB, MacAddress mask) {
+        return (mask == null && normalizeMacAddress(macA).equals(normalizeMacAddress(macB)))
+                || (mask != null && getMaskedMacAddress(normalizeMacAddress(macA), normalizeMacAddress(mask))
+                == getMaskedMacAddress(normalizeMacAddress(macB), normalizeMacAddress(mask)));
+    }
+
+    private boolean matchEthernetType(EthernetType ethernetType, MatchFields matchFields) {
+        return (ethernetType == null) || (matchFields.ethernetType != null
+                && ethernetType.getType().getValue().longValue()
+                == matchFields.ethernetType.longValue());
+    }
+
+    /**
+     * Match if layer 3 routing information is equal.
+     * @param match is the layer 3 match.
+     * @param matchFields are the target fields should be compared.
+     * @return the result of match.
+     */
+    public boolean matchLayer3(Layer3Match match, MatchFields matchFields) {
+        if (match == null) {
+            return true;
+        } else if (match instanceof Ipv4Match) {
+            return matchIpv4((Ipv4Match) match, matchFields);
+        } else if (match instanceof Ipv6Match) {
+            return matchIpv6((Ipv6Match) match, matchFields);
+        } else if (match instanceof ArpMatch) {
+            return matchArp((ArpMatch) match, matchFields);
+        } else if (match instanceof TunnelIpv4Match) {
+            return matchTunnelIpv4((TunnelIpv4Match) match, matchFields);
+        }
+        return false;
+    }
+
+    /**
+     * Match by IPv4 address.
+     * @param match is the original IPv4 address.
+     * @param matchFields are the target fields should be compared.
+     * @return the result of match.
+     */
+    public boolean matchIpv4(Ipv4Match match, MatchFields matchFields) {
+        return (match == null) || (matchIpv4Address(match.getIpv4Source(), matchFields.srcIp)
+                && matchIpv4Address(match.getIpv4Destination(), matchFields.dstIp));
+    }
+
+    /**
+     * @param prefix
+     * @param address
+     * @return the result of match.
+     */
+    public boolean matchIpv4Address(Ipv4Prefix prefix, TypedAddressData address) {
+        try {
+            return (prefix == null) || new IPPrefixHelper(prefix).match(address);
+        } catch (UnknownHostException e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    /**
+     * @param match
+     * @param matchFields
+     * @return the result of match.
+     */
+    public boolean matchIpv6(Ipv6Match match, MatchFields matchFields) {
+        return (match == null) || (matchIpv6Address(match.getIpv6Source(), matchFields.srcIp)
+                && matchIpv6Address(match.getIpv6Destination(), matchFields.dstIp)
+                && matchIpv6ExtHeader(match.getIpv6ExtHeader())
+                && matchIpv6Label(match.getIpv6Label())
+                && (match.getIpv6NdSll() == null)
+                && (match.getIpv6NdTarget() == null)
+                && (match.getIpv6NdTll() == null));
+    }
+
+    /**
+     * @param ipv6ExtHeader
+     * @return the result of match.
+     */
+    public boolean matchIpv6ExtHeader(Ipv6ExtHeader ipv6ExtHeader) {
+        return (ipv6ExtHeader == null) ||
+                (ipv6ExtHeader.getIpv6Exthdr() == null
+                        && ipv6ExtHeader.getIpv6ExthdrMask() == null);
+    }
+
+    /**
+     * @param ipv6Label
+     * @return the result of match.
+     */
+    public boolean matchIpv6Label(Ipv6Label ipv6Label) {
+        return (ipv6Label == null) ||
+                (ipv6Label.getIpv6Flabel() == null
+                        && ipv6Label.getFlabelMask() == null);
+    }
+
+    /**
+     * @param prefix
+     * @param address
+     * @return the result of match.
+     */
+    public boolean matchIpv6Address(Ipv6Prefix prefix, TypedAddressData address) {
+        try {
+            return (prefix == null) || new IPPrefixHelper(prefix).match(address);
+        } catch (UnknownHostException e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    /**
+     * Match by ARP protocol.
+     * @param match
+     * @param matchFields are the target fields should be compared.
+     * @return the result of match.
+     */
+    public boolean matchArp(ArpMatch match, MatchFields matchFields) {
+        return (match == null) || (match.getArpOp() == null
+                && match.getArpSourceHardwareAddress() == null
+                && match.getArpSourceTransportAddress() == null
+                && match.getArpTargetHardwareAddress() == null
+                && match.getArpTargetTransportAddress() == null);
+    }
+
+    /**
+     * Match by tunnel IPv4.
+     * @param match
+     * @param matchFields
+     * @return the result of match.
+     */
+    public boolean matchTunnelIpv4(TunnelIpv4Match match, MatchFields matchFields) {
+        return (match == null) ||
+                (match.getTunnelIpv4Source() == null
+                        && match.getTunnelIpv4Destination() == null);
+    }
+
+    /**
+     * Match by layer 4 routing information.
+     * @param match
+     * @param matchFields
+     * @return the result of match.
+     */
+    public boolean matchLayer4(Layer4Match match, MatchFields matchFields) {
+        if (match == null) {
+            return true;
+        } else if (match instanceof UdpMatch) {
+            return mathcUdp((UdpMatch) match);
+        } else if (match instanceof TcpMatch) {
+            return matchTcp((TcpMatch) match);
+        } else if (match instanceof SctpMatch) {
+            return matchSctp((SctpMatch) match);
+        }
+        return false;
+    }
+
+    /**
+     * Match by UDP.
+     * @param match
+     * @return the result of match.
+     */
+    public boolean mathcUdp(UdpMatch match) {
+        return (match == null) ||
+                (match.getUdpSourcePort() == null
+                        && match.getUdpDestinationPort() == null);
+    }
+
+    /**
+     * Match by TCP.
+     * @param match
+     * @return the result of match.
+     */
+    public boolean matchTcp(TcpMatch match) {
+        return (match == null) ||
+                (match.getTcpSourcePort() == null
+                        && match.getTcpDestinationPort() == null);
+    }
+
+    /**
+     * Match by SCTP.
+     * @param match
+     * @return the result of match.
+     */
+    public boolean matchSctp(SctpMatch match) {
+        return (match == null) ||
+                (match.getSctpSourcePort() == null
+                        && match.getSctpDestinationPort() == null);
+    }
+
+    /**
+     * Match by ICMP.
+     * @param match
+     * @param matchFields
+     * @return the result of match.
+     */
+    public boolean matchIcmpv4Match(Icmpv4Match match, MatchFields matchFields) {
+        return (match == null) || (match.getIcmpv4Code() == null
+                && match.getIcmpv4Type() == null);
+    }
+
+    /**
+     * Match by ICMPv6.
+     * @param match
+     * @param matchFields
+     * @return the result of match.
+     */
+    public boolean matchIcmpv6Match(Icmpv6Match match, MatchFields matchFields) {
+        return (match == null) || (match.getIcmpv6Code() == null
+                && match.getIcmpv6Type() == null);
+    }
+
+    /**
+     * Match by multiple protocol fields.
+     * @param match
+     * @param matchFields
+     * @return the result of match.
+     */
+    public boolean matchProtocolMatchFields(ProtocolMatchFields match, MatchFields matchFields) {
+        return (match == null) || (match.getMplsBos() == null
+                && match.getMplsLabel() == null
+                && match.getMplsTc() == null
+                && matchPbb(match.getPbb(), matchFields));
+    }
+
+    /**
+     * Match by PBB protocol.
+     * @param pbb
+     * @param matchFields
+     * @return the result of match.
+     */
+    public boolean matchPbb(Pbb pbb, MatchFields matchFields) {
+        return (pbb == null) ||
+                (pbb.getPbbIsid() == null && pbb.getPbbMask() == null);
+    }
+
+    /**
+     * Match by TCP flag.
+     * @param match
+     * @param matchFields
+     * @return the result of match.
+     */
+    public boolean matchTcpFlag(TcpFlagMatch match, MatchFields matchFields) {
+        return (match == null) || (match.getTcpFlag() == null);
+    }
+}
diff --git a/alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/flow/FlowTableMatcher.java b/alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/flow/FlowTableMatcher.java
new file mode 100644 (file)
index 0000000..4e2b71a
--- /dev/null
@@ -0,0 +1,297 @@
+/*
+ * Copyright (c) 2015 Yale 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.basic.endpointcostservice.flow;
+
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.GroupActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.OutputActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.group.action._case.GroupAction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
+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.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Instructions;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ClearActionsCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.GoToTableCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.MeterCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.WriteActionsCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.WriteMetadataCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.meter._case.Meter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.Bucket;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class FlowTableMatcher {
+    private static final Logger log = LoggerFactory
+            .getLogger(FlowTableMatcher.class);
+
+    private Map<Short, Table> indexTables = new HashMap<Short, Table>();
+    private Map<Long, Group> indexedGroups = new HashMap<Long, Group>();
+
+    private List<Action> applyActions = new ArrayList<Action>();
+    private List<Action> pipelineActions = new ArrayList<Action>();
+    private Long meterId;
+
+    private FlowEntryMatcher flowEntryMatcher = new FlowEntryMatcher();
+
+    public class FlowTableLookUpResult {
+        public List<Uri> outputNodeConnectors = new ArrayList<Uri>();
+        public boolean sendToController = false;
+        public long meterId = -1;
+    }
+
+    private void prepare(FlowCapableNode node) {
+        applyActions.clear();
+        pipelineActions.clear();
+        //meterId = null;
+        meterId = 123L;
+        indexTables.clear();
+        indexTables = indexByTableId(node.getTable());
+        indexedGroups = indexByGroupId(node.getGroup());
+    }
+
+    /**
+     * Look up flow table by given fields in a certain switch.
+     * @param node define the node where to search.
+     * @param matchFields define the given fields to find.
+     * @return the result of look up.
+     */
+    public FlowTableLookUpResult lookUpFlowTables(FlowCapableNode node, MatchFields matchFields) {
+        log.info("Looking up flow table for " + matchFields.inPort);
+        prepare(node);
+        short currentTableId = 0;
+        short nextTableId = 0;
+        do {
+            currentTableId = nextTableId;
+            nextTableId = lookUpFlowTable(currentTableId, matchFields);
+        } while (nextTableId != currentTableId);
+        return processActions(node);
+    }
+
+    private short lookUpFlowTable(short tableId, MatchFields matchFields) {
+        List<Flow> flows = indexTables.get(tableId).getFlow();
+        sortFlowByPriority(flows);
+        for (Flow flow : flows) {
+            if (flowEntryMatcher.match(flow.getMatch(), matchFields)) {
+                log.info("Priority: " + flow.getPriority());
+                Instructions inss = flow.getInstructions();
+                if (inss == null) {
+                    return tableId;
+                }
+                short nextTableId = lookUpInstructions(inss.getInstruction());
+                return (nextTableId != -1) ? nextTableId : tableId;
+            }
+        }
+        return tableId;
+    }
+
+    private FlowTableLookUpResult processActions(FlowCapableNode node) {
+        FlowTableLookUpResult result = new FlowTableLookUpResult();
+        processActionList(applyActions, result);
+        processActionSet(pipelineActions, result);
+        processMeterResult(result);
+        log.info("FlowTableLookUpResult: " + result.outputNodeConnectors.size());
+        return result;
+    }
+
+    private short lookUpInstructions(List<Instruction> inns) {
+        short nextTableId = -1;
+        Map<Integer, Instruction> indexedInss = sortAndIndexInstructionsByOrder(inns);
+        for (int i = 0; i < indexedInss.size(); i++) {
+            org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction ins = indexedInss.get(i).getInstruction();
+            if (ins instanceof MeterCase) {
+                meterCase((MeterCase) ins);
+            }else if (ins instanceof ApplyActionsCase) {
+                applyActionsCase((ApplyActionsCase) ins);
+            } else if (ins instanceof ClearActionsCase) {
+                clearActionsCase((ClearActionsCase) ins);
+            } else if (ins instanceof WriteActionsCase) {
+                writeActionsCase((WriteActionsCase) ins);
+            } else if (ins instanceof WriteMetadataCase) {
+                writeMetadataCase((WriteMetadataCase) ins);
+            } else if (ins instanceof GoToTableCase) {
+                nextTableId = ((GoToTableCase) ins).getGoToTable().getTableId();
+            }
+        }
+        return nextTableId;
+    }
+
+    private void applyActionsCase(ApplyActionsCase applyActionCase) {
+        List<Action> applyActions = applyActionCase.getApplyActions().getAction();
+        sortActionsByOrder(applyActions);
+        this.applyActions.addAll(applyActions);
+    }
+
+    private void clearActionsCase(ClearActionsCase clearActions) {
+        this.pipelineActions.clear();
+    }
+
+    private void writeActionsCase(WriteActionsCase writeActionCase) {
+        List<Action> writeActions = writeActionCase.getWriteActions().getAction();
+        sortActionsByOrder(writeActions);
+        this.pipelineActions.addAll(writeActions);
+    }
+
+    private void writeMetadataCase(WriteMetadataCase writeMetadata) {}
+
+    private void meterCase(MeterCase meterCase) {
+        Meter meter = meterCase.getMeter();
+        this.meterId = meter.getMeterId().getValue();
+    }
+
+    private void processActionSet(List<Action> actions, FlowTableLookUpResult result) {
+        List<Action> actionsToProcess = selectValidActions(actions);
+        processActionList(actionsToProcess, result);
+    }
+
+    private List<Action> selectValidActions(List<Action> actions) {
+        boolean groupActionCase = false;
+        List<Action> actionsToProcess = new ArrayList<Action>();
+        for (Action action : actions) {
+            org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action actionValue = action.getAction();
+            if (actionValue instanceof GroupActionCase) {
+                actionsToProcess.clear();
+                actionsToProcess.add(action);
+                groupActionCase = true;
+            } else if (actionValue instanceof OutputActionCase) {
+                if (!groupActionCase) {
+                    actionsToProcess.add(action);
+                }
+            }
+        }
+        return actionsToProcess;
+    }
+
+    private void processActionList(List<Action> actionList, FlowTableLookUpResult result) {
+        for (Action act : actionList) {
+            org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action action = act.getAction();
+            if (action instanceof GroupActionCase) {
+                processGroupAction((GroupActionCase) action, result);
+            } else if (action instanceof OutputActionCase) {
+                processOutputAction((OutputActionCase) action, result);
+            }
+        }
+    }
+
+    private void processOutputAction(OutputActionCase action, FlowTableLookUpResult result) {
+        Uri nodeConnector = action.getOutputAction().getOutputNodeConnector();
+        if (nodeConnector.getValue().matches("\\d+")) {
+            result.outputNodeConnectors.add(nodeConnector);
+        } else if (nodeConnector.getValue().matches("CONTROLLER")) {
+            result.sendToController = true;
+        }
+    }
+
+    private void processGroupAction(GroupActionCase actionCase, FlowTableLookUpResult result) {
+        GroupAction groupAction = actionCase.getGroupAction();
+        Group group = indexedGroups.get(groupAction.getGroupId());
+        GroupTypes groupType = group.getGroupType();
+        List<Bucket> buckets = group.getBuckets().getBucket();
+        if (groupType.equals(GroupTypes.GroupAll)) {
+            for (Bucket bucket : buckets) {
+                processActionSet(bucket.getAction(), result);
+            }
+        } else if (groupType.equals(GroupTypes.GroupIndirect) && buckets.size() == 1) {
+            processActionSet(buckets.get(0).getAction(), result);
+        }
+    }
+
+    private void processMeterResult(FlowTableLookUpResult result) {
+        result.meterId = this.meterId;
+    }
+
+    private Map<Short, Table> indexByTableId(List<Table> tables) {
+        Map<Short, Table> indexedTables = new HashMap<Short, Table>();
+        for (Table table : tables) {
+            short id = table.getId();
+            indexedTables.put(id, table);
+        }
+        return indexedTables;
+    }
+
+    private Map<Integer, Instruction> sortAndIndexInstructionsByOrder(List<Instruction> inns) {
+        sortInstructionByOrder(inns);
+        return indexInstructionsByOrder(inns);
+    }
+
+    private Map<Integer, Instruction> indexInstructionsByOrder(List<Instruction> inns) {
+        Map<Integer, Instruction> indexedInss = new HashMap<Integer, Instruction>();
+        for (Instruction ins : inns) {
+            int id = ins.getOrder();
+            indexedInss.put(id, ins);
+        }
+        return indexedInss;
+    }
+
+    private void sortInstructionByOrder(List<Instruction> inns) {
+        Collections.sort(inns, new Comparator<Instruction>() {
+            @Override
+            public int compare(Instruction i1, Instruction i2) {
+                if (i1.getOrder() < i2.getOrder()){
+                    return -1;
+                }else if (i1.getOrder() > i2.getOrder()){
+                    return 1;
+                } else {
+                    return 0;
+                }
+            }
+        });
+    }
+
+    private Map<Long, Group> indexByGroupId(List<Group> groups) {
+        Map<Long, Group> groupMaps = new HashMap<Long, Group>();
+        if (groups == null) {
+            return groupMaps;
+        }
+        for (Group group: groups) {
+            groupMaps.put(group.getGroupId().getValue(), group);
+        }
+        return groupMaps;
+    }
+
+    private void sortFlowByPriority(List<Flow> flows) {
+        Collections.sort(flows, new Comparator<Flow>() {
+            @Override
+            public int compare(Flow f1, Flow f2) {
+                if (f1.getPriority() < f2.getPriority()){
+                    return 1;
+                } else if (f1.getPriority() > f2.getPriority()) {
+                    return -1;
+                } else {
+                    return 0;
+                }
+            }
+        });
+    }
+
+    private void sortActionsByOrder(List<Action> actions) {
+        Collections.sort(actions, new Comparator<Action>() {
+            @Override
+            public int compare(Action a1, Action a2) {
+                if (a1.getOrder() < a2.getOrder()){
+                    return -1;
+                }else if (a1.getOrder() > a2.getOrder()){
+                    return 1;
+                } else {
+                    return 0;
+                }
+            }
+        });
+    }
+}
\ No newline at end of file
diff --git a/alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/flow/MatchFields.java b/alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/flow/MatchFields.java
new file mode 100644 (file)
index 0000000..e2ca9e6
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright © 2015 Yale 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.basic.endpointcostservice.flow;
+
+import org.opendaylight.alto.basic.endpointcostservice.util.RouteServiceConstants;
+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.service.model.endpointcost.rfc7285.rev151021.Ipv4AddressData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointcost.rfc7285.rev151021.Ipv6AddressData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointcost.rfc7285.rev151021.TypedAddressData;
+
+public class MatchFields {
+    public String inPort;
+    public TypedAddressData srcIp;
+    public TypedAddressData dstIp;
+    public MacAddress srcMac;
+    public MacAddress dstMac;
+    public Long ethernetType;
+
+    public MatchFields(TypedAddressData srcIp, TypedAddressData dstIp) {
+        this.srcIp = srcIp;
+        this.dstIp = dstIp;
+        this.ethernetType = getEthernetType(srcIp);
+    }
+
+    public MatchFields(MacAddress srcMac, MacAddress dstMac,
+                       TypedAddressData srcIp, TypedAddressData dstIp) {
+        this(srcIp, dstIp);
+        this.srcMac = srcMac;
+        this.dstMac = dstMac;
+    }
+    private Long getEthernetType(TypedAddressData Ip) {
+        if(Ip.getAddress() instanceof Ipv4AddressData){
+            return RouteServiceConstants.ETHERNET_TYPE.IPV4;
+        }
+        if(Ip.getAddress() instanceof Ipv6AddressData){
+            return RouteServiceConstants.ETHERNET_TYPE.IPV6;
+        }
+        return null;
+    }
+}
diff --git a/alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/helper/DataStoreHelper.java b/alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/helper/DataStoreHelper.java
new file mode 100644 (file)
index 0000000..fb4c4e3
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright © 2015 Yale 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.basic.endpointcostservice.helper;
+
+import com.google.common.base.Optional;
+import org.opendaylight.alto.basic.endpointcostservice.suportservice.exception.ReadDataFailedException;
+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 DataStoreHelper {
+    /**
+     * @param dataBroker
+     * @param iid
+     * @param <T>
+     * @return The configuration of iid
+     * @throws ReadDataFailedException
+     */
+    public static <T extends DataObject> T readConfiguration(
+            DataBroker dataBroker, InstanceIdentifier<T> iid) throws ReadDataFailedException {
+        return readFromDataStore(dataBroker, iid, LogicalDatastoreType.CONFIGURATION);
+    }
+
+    /**
+     * @param dataBroker
+     * @param iid
+     * @param <T>
+     * @return The operational data of iid
+     * @throws ReadDataFailedException
+     */
+    public static <T extends DataObject> T readOperational(
+            DataBroker dataBroker, InstanceIdentifier<T> iid) throws ReadDataFailedException {
+        T data = readFromDataStore(dataBroker, iid, LogicalDatastoreType.OPERATIONAL);
+        return data;
+    }
+
+    /**
+     * @param dataBroker
+     * @param iid
+     * @param type
+     * @param <T>
+     * @return The data of iid
+     * @throws ReadDataFailedException
+     */
+    public static <T extends DataObject> T readFromDataStore(
+            DataBroker dataBroker, InstanceIdentifier<T> iid, LogicalDatastoreType type) throws ReadDataFailedException {
+        ReadOnlyTransaction tx = dataBroker.newReadOnlyTransaction();
+        Future<Optional<T>> future = tx.read(type, iid);
+        try {
+            if (future != null) {
+                Optional<T> optional = future.get();
+                if (optional.isPresent()) {
+                    return optional.get();
+                }
+            }
+        } catch (InterruptedException | ExecutionException e) {
+            e.printStackTrace();
+        } finally {
+            tx.close();
+        }
+        throw new ReadDataFailedException();
+    }
+}
diff --git a/alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/helper/IPPrefixHelper.java b/alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/helper/IPPrefixHelper.java
new file mode 100644 (file)
index 0000000..22d7b26
--- /dev/null
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 2015 Yale 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.basic.endpointcostservice.helper;
+
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
+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.inet.types.rev100924.Ipv6Prefix;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointcost.rfc7285.rev151021.Ipv4AddressData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointcost.rfc7285.rev151021.Ipv6AddressData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointcost.rfc7285.rev151021.TypedAddressData;
+
+import java.net.Inet4Address;
+import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+public class IPPrefixHelper {
+    private int bits;
+    private int ipv4Subnet;
+    private int ipv4Mask;
+    private int[] ipv6Subnet = new int[4];
+    private int[] ipv6Mask = new int[4];
+    private String prefix;
+    private boolean initialized = false;
+
+    /**
+     * Initial IPPrefixHelper.
+     * @param ipPrefix
+     * @throws UnknownHostException
+     */
+    public IPPrefixHelper(IpPrefix ipPrefix) throws UnknownHostException {
+        initializeIpv4(ipPrefix.getIpv4Prefix());
+        initializeIpv6(ipPrefix.getIpv6Prefix());
+    }
+
+    /**
+     * Initial IPPrefixHelper
+     * @param ipv4Prefix
+     * @throws UnknownHostException
+     */
+    public IPPrefixHelper(Ipv4Prefix ipv4Prefix) throws UnknownHostException {
+        initializeIpv4(ipv4Prefix);
+    }
+
+    private void initializeIpv4(Ipv4Prefix ipv4Prefix) throws UnknownHostException {
+        if (ipv4Prefix != null) {
+            subNet(ipv4Prefix);
+            this.prefix = ipv4Prefix.getValue();
+            this.initialized = true;
+        }
+    }
+
+    /**
+     * Initial IPPrefixHelper
+     * @param ipv6Prefix
+     * @throws UnknownHostException
+     */
+    public IPPrefixHelper(Ipv6Prefix ipv6Prefix) throws UnknownHostException {
+        initializeIpv6(ipv6Prefix);
+    }
+
+    private void initializeIpv6(Ipv6Prefix ipv6Prefix) throws UnknownHostException {
+        if (ipv6Prefix != null) {
+            subNet(ipv6Prefix);
+            this.prefix = ipv6Prefix.getValue();
+            this.initialized = true;
+        }
+    }
+
+    private void subNet(Ipv6Prefix ipv6Prefix) throws UnknownHostException {
+        String[] value = ipv6Prefix.getValue().split("[/]");
+        this.bits = Integer.parseInt(value[1]);
+        ipv6Mask();
+        this.ipv6Subnet = ipv6ToInt(value[0]);
+    }
+
+    public static int[] ipv6ToInt(String address) throws UnknownHostException {
+        byte[] b = toBytes(address);
+        int addr1 = ((b[0] & 0xFF) << 24) | ((b[1] & 0xFF) << 16)
+                | ((b[2] & 0xFF) << 8) | ((b[3] & 0xFF) << 0);
+
+        int addr2 = ((b[4] & 0xFF) << 24) | ((b[5] & 0xFF) << 16)
+                | ((b[6] & 0xFF) << 8) | ((b[7] & 0xFF) << 0);
+
+        int addr3 = ((b[8] & 0xFF) << 24) | ((b[9] & 0xFF) << 16)
+                | ((b[10] & 0xFF) << 8) | ((b[11] & 0xFF) << 0);
+
+        int addr4 = ((b[12] & 0xFF) << 24) | ((b[13] & 0xFF) << 16)
+                | ((b[14] & 0xFF) << 8) | ((b[15] & 0xFF) << 0);
+        int[] addrs = { addr1, addr2, addr3, addr4 };
+        return addrs;
+    }
+    public static int ipv4ToInt(String addr) throws UnknownHostException {
+        Inet4Address a = (Inet4Address) InetAddress.getByName(addr);
+        byte[] b = a.getAddress();
+        int addrInt = ((b[0] & 0xFF) << 24) | ((b[1] & 0xFF) << 16)
+                | ((b[2] & 0xFF) << 8) | ((b[3] & 0xFF) << 0);
+        return addrInt;
+    }
+
+    private static byte[] toBytes(String address) throws UnknownHostException {
+        Inet6Address addr = (Inet6Address) InetAddress.getByName(address);
+        return addr.getAddress();
+    }
+
+    private void ipv6Mask() {
+        if (this.bits <= 32) {
+            this.ipv6Mask[0] = -1 << (32 - this.bits);
+            this.ipv6Mask[1] = 0;
+            this.ipv6Mask[2] = 0;
+            this.ipv6Mask[3] = 0;
+        }
+
+        if (this.bits > 32 && this.bits <= 64) {
+            this.ipv6Mask[0] = -1;
+            this.ipv6Mask[1] = -1 << (64 - this.bits);
+            this.ipv6Mask[2] = 0;
+            this.ipv6Mask[3] = 0;
+        }
+
+        if (this.bits > 64 && this.bits <= 96) {
+            this.ipv6Mask[0] = -1;
+            this.ipv6Mask[1] = -1;
+            this.ipv6Mask[2] = -1 << (96 - this.bits);
+            this.ipv6Mask[3] = 0;
+        }
+
+        if (this.bits > 96 && this.bits <= 128) {
+            this.ipv6Mask[0] = -1;
+            this.ipv6Mask[1] = -1;
+            this.ipv6Mask[2] = -1;
+            this.ipv6Mask[3] = -1 << (128 - this.bits);
+        }
+    }
+
+    private void subNet(Ipv4Prefix ipv4Prefix) throws UnknownHostException {
+        String[] value = ipv4Prefix.getValue().split("/");
+        this.bits = Integer.parseInt(value[1]);
+        this.ipv4Mask = -1 << (32 - this.bits);
+        this.ipv4Subnet = ipv4ToInt(value[0]);
+    }
+
+    /**
+     * Check if two address are matches
+     * @param address
+     * @return the result of match
+     * @throws UnknownHostException
+     */
+    public boolean match(TypedAddressData address)
+            throws UnknownHostException {
+        if (this.initialized == false) {
+            return this.initialized;
+        }
+
+        if (address.getAddress() instanceof Ipv4AddressData) {
+            int addr = ipv4ToInt(((Ipv4AddressData) address.getAddress()).getIpv4().getValue().replace("ipv4:", ""));
+            return ((ipv4Subnet & ipv4Mask) == (addr & ipv4Mask));
+        }
+
+        if (address.getAddress() instanceof Ipv6AddressData) {
+            int[] addr = ipv6ToInt(((Ipv6AddressData) address.getAddress()).getIpv6().getValue().replace("ipv6:", ""));
+            return ((ipv6Subnet[0] & ipv6Mask[0]) == (addr[0] & ipv6Mask[0]))
+                    && ((ipv6Subnet[1] & ipv6Mask[1]) == (addr[1] & ipv6Mask[1]))
+                    && ((ipv6Subnet[2] & ipv6Mask[2]) == (addr[2] & ipv6Mask[2]))
+                    && ((ipv6Subnet[3] & ipv6Mask[3]) == (addr[3] & ipv6Mask[3]));
+        }
+        return false;
+    }
+
+    public int getSubnetLength() {
+        return this.bits;
+    }
+
+    public String getIpPrefix() {
+        return this.prefix;
+    }
+}
\ No newline at end of file
diff --git a/alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/helper/ServiceHelper.java b/alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/helper/ServiceHelper.java
new file mode 100644 (file)
index 0000000..fd32bed
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * Copyright © 2015 Yale 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.basic.endpointcostservice.helper;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Dictionary;
+
+public class ServiceHelper {
+    private static final Logger logger = LoggerFactory
+            .getLogger(ServiceHelper.class);
+
+    /**
+     * Register a Global Service in the OSGi service registry
+     *
+     * @param clazz
+     *          The target class
+     * @param instance
+     *          of the object exporting the service, be careful the object must
+     *          implement/extend clazz else the registration will fail unless a
+     *          ServiceFactory is passed as parameter
+     * @param properties
+     *          The properties to be attached to the service registration
+     * @return the ServiceRegistration if registration happened, null otherwise
+     */
+    public static ServiceRegistration registerGlobalServiceWReg(Class<?> clazz,
+                                                                Object instance, Dictionary<String, Object> properties) {
+        try {
+            BundleContext bCtx = FrameworkUtil.getBundle(instance.getClass())
+                    .getBundleContext();
+            if (bCtx == null) {
+                logger.error("Could not retrieve the BundleContext");
+                return null;
+            }
+
+            ServiceRegistration registration = bCtx.registerService(clazz.getName(),
+                    instance, properties);
+            return registration;
+        } catch (Exception e) {
+            logger.error("Exception {} while registering the service {}",
+                    e.getMessage(), instance.toString());
+        }
+        return null;
+    }
+
+    /**
+     * Retrieve global instance of a class via OSGI registry, if there are many
+     * only the first is returned.
+     *
+     * @param clazz
+     *          The target class
+     * @param bundle
+     *          The caller
+     */
+    public static Object getGlobalInstance(Class<?> clazz, Object bundle) {
+        return getGlobalInstance(clazz, bundle, null);
+    }
+
+
+    /**
+     * Retrieve global instance of a class via OSGI registry, if there are many
+     * only the first is returned. On this version an LDAP type of filter is
+     * applied
+     *
+     * @param clazz
+     *          The target class
+     * @param bundle
+     *          The caller
+     * @param serviceFilter
+     *          LDAP filter to be applied in the search
+     */
+    public static Object getGlobalInstance(Class<?> clazz, Object bundle,
+                                           String serviceFilter) {
+        Object[] instances = getGlobalInstances(clazz, bundle, serviceFilter);
+        if (instances != null) {
+            return instances[0];
+        }
+        return null;
+    }
+
+    /**
+     * Retrieve all the Instances of a Service, optionally filtered via
+     * serviceFilter if non-null else all the results are returned if null
+     *
+     * @param clazz
+     *          The target class
+     * @param bundle
+     *          The caller
+     * @param serviceFilter
+     *          LDAP filter to be applied in the search
+     */
+    @SuppressWarnings("unchecked")
+    public static Object[] getGlobalInstances(Class<?> clazz, Object bundle,
+                                              String serviceFilter) {
+        Object instances[] = null;
+        try {
+            BundleContext bCtx = FrameworkUtil.getBundle(bundle.getClass())
+                    .getBundleContext();
+
+            ServiceReference[] services = bCtx.getServiceReferences(clazz.getName(),
+                    serviceFilter);
+
+            if (services != null) {
+                instances = new Object[services.length];
+                for (int i = 0; i < services.length; i++) {
+                    instances[i] = bCtx.getService(services[i]);
+                }
+            }
+        } catch (Exception e) {
+            logger.error("Instance reference is NULL");
+        }
+        return instances;
+    }
+}
diff --git a/alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/helper/UtilHelper.java b/alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/helper/UtilHelper.java
new file mode 100644 (file)
index 0000000..0e70d98
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright © 2015 Yale 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.basic.endpointcostservice.helper;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointcost.rfc7285.rev151021.TypedAddressData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointcost.rfc7285.rev151021.query.input.request.endpointcost.request.endpointcost.params.filter.endpoint.filter.data.endpoint.filter.source.address.Ipv4;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointcost.rfc7285.rev151021.query.input.request.endpointcost.request.endpointcost.params.filter.endpoint.filter.data.endpoint.filter.source.address.Ipv6;
+
+public class UtilHelper {
+    public static String getIpFromTypedAddressData(TypedAddressData addressData){
+        if(addressData.getAddress() instanceof Ipv4){
+            return ((Ipv4) addressData.getAddress()).getIpv4().getValue();
+        }
+        else if(addressData.getAddress() instanceof org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointcost.rfc7285.rev151021.query.input.request.endpointcost.request.endpointcost.params.filter.endpoint.filter.data.endpoint.filter.destination.address.Ipv4){
+            return ((org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointcost.rfc7285.rev151021.query.input.request.endpointcost.request.endpointcost.params.filter.endpoint.filter.data.endpoint.filter.destination.address.Ipv4) addressData.getAddress()).getIpv4().getValue();
+        }
+        else if(addressData.getAddress() instanceof Ipv6){
+            return  ((Ipv6) addressData.getAddress()).getIpv6().getValue();
+        }
+        else if(addressData.getAddress() instanceof org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointcost.rfc7285.rev151021.query.input.request.endpointcost.request.endpointcost.params.filter.endpoint.filter.data.endpoint.filter.destination.address.Ipv6){
+            return ((org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointcost.rfc7285.rev151021.query.input.request.endpointcost.request.endpointcost.params.filter.endpoint.filter.data.endpoint.filter.destination.address.Ipv6) addressData.getAddress()).getIpv6().getValue();
+        }
+        return null;
+    }
+}
diff --git a/alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/impl/BasicECSImplementation.java b/alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/impl/BasicECSImplementation.java
new file mode 100644 (file)
index 0000000..df5b71e
--- /dev/null
@@ -0,0 +1,175 @@
+/*
+ * Copyright © 2015 Yale 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.basic.endpointcostservice.impl;
+
+import org.opendaylight.alto.basic.endpointcostservice.suportservice.impl.HostNodeTrackerImpl;
+import org.opendaylight.alto.basic.endpointcostservice.suportservice.impl.NetworkElementImpl;
+import org.opendaylight.alto.basic.endpointcostservice.suportservice.impl.RoutingServiceImpl;
+import org.opendaylight.alto.basic.endpointcostservice.suportservice.service.HostNodeTrackerService;
+import org.opendaylight.alto.basic.endpointcostservice.suportservice.service.NetworkElementService;
+import org.opendaylight.alto.basic.endpointcostservice.suportservice.service.RoutingService;
+import org.opendaylight.alto.basic.endpointcostservice.impl.base.BaseECSImplementation;
+import org.opendaylight.alto.basic.endpointcostservice.flow.MatchFields;
+import org.opendaylight.alto.basic.endpointcostservice.util.LinkNode;
+import org.opendaylight.alto.basic.endpointcostservice.helper.UtilHelper;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+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.core.types.rev150921.CostMetric;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.core.types.rev150921.CostTypeData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointcost.rfc7285.rev151021.TypedAddressData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointcost.rfc7285.rev151021.endpointcostmap.response.data.endpoint.cost.map.endpoint.cost.Cost;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointcost.rfc7285.rev151021.query.output.response.endpointcost.response.endpointcost.data.endpoint.costmap.data.endpoint.cost.map.endpoint.cost.cost.Numerical;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointcost.rfc7285.rev151021.query.output.response.endpointcost.response.endpointcost.data.endpoint.costmap.data.endpoint.cost.map.endpoint.cost.cost.NumericalBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.math.BigDecimal;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+public class BasicECSImplementation extends BaseECSImplementation{
+    private static final Logger log = LoggerFactory.getLogger(BasicECSImplementation.class);
+    private RoutingService routingService;
+    private NetworkElementService hostNetworkService;
+    private HostNodeTrackerService hostNodeTrackerService;
+
+    public BasicECSImplementation(DataBroker dataBroker){
+        this.dataBroker = dataBroker;
+        this.hostNodeTrackerService= new HostNodeTrackerImpl(dataBroker);
+        this.hostNetworkService = new NetworkElementImpl(dataBroker);
+        this.routingService = new RoutingServiceImpl(hostNetworkService);
+    }
+
+    @Override
+    protected Cost computeCost(TypedAddressData src, TypedAddressData dst, CostTypeData costType) {
+        NumericalBuilder numericalBuilder = new NumericalBuilder();
+        if (validSourceAndDest(src, dst)) {
+                if (isAddressEqual(src,dst)) {
+                return numericalBuilder.setCost(new BigDecimal(0)).build();
+            }
+            MatchFields matchFields = createMatchField(src,dst);
+            LinkNode head = routingService.buildRoutePath(matchFields);
+            if (head != null) {
+                return computeCostBasedOnCostType(head, costType);
+            }
+        }
+        return null;
+    }
+
+    private Cost computeCostBasedOnCostType(LinkNode head, CostTypeData costType) {
+        CostMetric costMetric = costType.getCostMetric();
+        if (hasLoop(head, new HashMap<LinkNode, Integer>())) {
+            return null;
+        }
+        if(costMetric.getValue().toString().equals(new String("hopcount"))){
+            log.info("hopcpunt");
+            Numerical cost = computeHopCountECS(head);
+            return (cost == null) ? null : cost;
+        }else if(costMetric.getValue().toString().equals(new String("routingcost"))){
+            log.info("routingcost");
+//            Numerical cost = computeRoutingcostECS(head);
+//            return (cost == null) ? null : cost;
+            return null;
+        }else if(costMetric.getValue().toString().equals(new String("bandwidth"))){
+             log.info("bandwidth");
+//            Numerical cost = computeBandwidthECS(head);
+//            return (cost == null) ? null : cost;
+            return null;
+        }
+        return null;
+    }
+
+    private boolean hasLoop(LinkNode head, Map<LinkNode, Integer> status) {
+        if (status.containsKey(head)) {
+            return status.get(head) == -1;
+        } else {
+            status.put(head, -1);
+            for (LinkNode eachNode : head.children()) {
+                if (hasLoop(eachNode, status)) {
+                    return true;
+                }
+            }
+            status.put(head, 1);
+            return false;
+        }
+    }
+
+    private Numerical computeHopCountECS(LinkNode head) {
+        List<LinkNode> path = computeShortestLinkNodePath(head);
+        if (path == null)
+            return null;
+        else {
+            NumericalBuilder result = new NumericalBuilder();
+            BigDecimal cost = new BigDecimal(path.size());
+            return result.setCost(cost).build();
+        }
+    }
+    private List<LinkNode> computeShortestLinkNodePath(LinkNode head) {
+        LinkedList<LinkNode> queue = new LinkedList<LinkNode>();
+        HashMap<LinkNode, Integer> hopCounts = new HashMap<LinkNode, Integer>();
+        HashMap<LinkNode, LinkNode> prior = new HashMap<LinkNode, LinkNode>();
+        hopCounts.put(head, 0);
+        queue.addLast(head);
+        int maxIter = 500;
+        while (!queue.isEmpty()) {
+            if (maxIter <= 0) {
+                break;
+            }
+            --maxIter;
+            LinkNode now = queue.pop();
+            if (now.isDestHost()) {
+                LinkedList<LinkNode> res = new LinkedList<LinkNode>();
+                while (!now.equals(head)) {
+                    res.addFirst(now);
+                    now = prior.get(now);
+                }
+                res.addFirst(head);
+                return res;
+            } else {
+                int hopCountNow = hopCounts.get(now) + 1;
+                for (LinkNode eachNode : now.children()) {
+                    if (addHopCountToMap(hopCounts, eachNode, hopCountNow)) {
+                        prior.put(eachNode, now);
+                        queue.addLast(eachNode);
+                    }
+                }
+            }
+        }
+        return null;
+    }
+
+    private Boolean addHopCountToMap(HashMap<LinkNode, Integer> map, LinkNode key, int value) {
+        if (map.containsKey(key)) {
+            int tmp = map.get(key);
+            map.put(key, tmp < value ? tmp : value);
+            if (tmp < value) {
+                return false;
+            }
+        } else {
+            map.put(key, value);
+        }
+        return true;
+    }
+
+    private MatchFields createMatchField(TypedAddressData src, TypedAddressData dst) {
+        MacAddress srcMac = new MacAddress(hostNodeTrackerService.getMacByIp(UtilHelper.getIpFromTypedAddressData(src)));
+        MacAddress dstMac = new MacAddress(hostNodeTrackerService.getMacByIp(UtilHelper.getIpFromTypedAddressData(dst)));
+        return new MatchFields(srcMac,dstMac,src,dst);
+    }
+
+    private boolean isAddressEqual(TypedAddressData src, TypedAddressData dst) {
+        return UtilHelper.getIpFromTypedAddressData(src).equals(UtilHelper.getIpFromTypedAddressData(dst));
+    }
+
+    private boolean validSourceAndDest(TypedAddressData src, TypedAddressData dst) {
+        return hostNodeTrackerService.isValidHost(UtilHelper.getIpFromTypedAddressData(src)) && hostNodeTrackerService.isValidHost(UtilHelper.getIpFromTypedAddressData(dst));
+    }
+
+}
diff --git a/alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/impl/EndpointcostserviceProvider.java b/alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/impl/EndpointcostserviceProvider.java
new file mode 100644 (file)
index 0000000..9300047
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * Copyright © 2015 Yale 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.basic.endpointcostservice.impl;
+
+import org.opendaylight.alto.core.resourcepool.ResourcepoolUtils;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
+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.core.resourcepool.rev150921.context.Resource;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.core.types.rev150921.ResourceId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointcost.rev151021.AltoModelEndpointcostService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointcost.rev151021.QueryInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointcost.rev151021.QueryOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointcost.rev151021.ResourceTypeEndpointcost;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+public class EndpointcostserviceProvider implements BindingAwareProvider, AutoCloseable,AltoModelEndpointcostService {
+
+    private static final Logger LOG = LoggerFactory.getLogger(EndpointcostserviceProvider.class);
+
+    private DataBroker m_dataBroker = null;
+    private BindingAwareBroker.RoutedRpcRegistration<AltoModelEndpointcostService> m_serviceReg = null;
+    private ListenerRegistration<DataChangeListener> m_listener = null;
+
+    private static final String SERVICE_ENDPOINTCOST_NAME = "service-endpointcost";
+    private static final ResourceId SERVICE_ENDPOINTCOST_RID = new ResourceId(SERVICE_ENDPOINTCOST_NAME);
+    private InstanceIdentifier<Resource> m_testIID = null;
+
+    private BasicECSImplementation basicEcsImpl;
+
+    protected void createContextTag()
+            throws InterruptedException, ExecutionException, TransactionCommitFailedException {
+        WriteTransaction wx = m_dataBroker.newWriteOnlyTransaction();
+
+        ResourcepoolUtils.createResourceWithCapabilities(ResourcepoolUtils.DEFAULT_CONTEXT,
+                SERVICE_ENDPOINTCOST_NAME,
+                ResourceTypeEndpointcost.class,
+                null, wx);
+
+        ResourcepoolUtils.lazyUpdateResource(ResourcepoolUtils.DEFAULT_CONTEXT,
+                SERVICE_ENDPOINTCOST_NAME, wx);
+
+        wx.submit().get();
+    }
+
+    protected void removeContextTag()
+            throws InterruptedException, ExecutionException, TransactionCommitFailedException  {
+        WriteTransaction wx = m_dataBroker.newWriteOnlyTransaction();
+
+        ResourcepoolUtils.deleteResource(ResourcepoolUtils.DEFAULT_CONTEXT,
+                SERVICE_ENDPOINTCOST_NAME, wx);
+
+        wx.submit().get();
+    }
+
+    protected void setupListener() {
+        ResourcepoolUtils.ContextTagListener listener = new ResourcepoolUtils.ContextTagListener(m_testIID, m_serviceReg);
+        m_listener = m_dataBroker.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
+                m_testIID,listener, AsyncDataBroker.DataChangeScope.SUBTREE);
+
+        assert m_listener != null;
+    }
+
+    @Override
+    public void onSessionInitiated(ProviderContext session) {
+        LOG.info("EndpointcostserviceProvider Session Initiated");
+
+        m_dataBroker = session.getSALService(DataBroker.class);
+        m_testIID = ResourcepoolUtils.getResourceIID(ResourcepoolUtils.DEFAULT_CONTEXT,
+                SERVICE_ENDPOINTCOST_NAME);
+        m_serviceReg = session.addRoutedRpcImplementation(AltoModelEndpointcostService.class, this);
+        basicEcsImpl = new BasicECSImplementation(m_dataBroker);
+        try {
+            setupListener();
+            createContextTag();
+        } catch (Exception e) {
+        }
+    }
+
+    @Override
+    public void close() throws Exception {
+        LOG.info("EndpointcostserviceProvider Closed");
+
+        if (m_serviceReg != null) {
+            m_serviceReg.close();
+        }
+        try {
+            removeContextTag();
+        } catch (Exception e) {
+        }
+    }
+
+    @Override
+    public Future<RpcResult<QueryOutput>> query(QueryInput input) {
+        return basicEcsImpl.getECS(input);
+    }
+
+}
diff --git a/alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/impl/base/BaseECSImplementation.java b/alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/impl/base/BaseECSImplementation.java
new file mode 100644 (file)
index 0000000..81696a4
--- /dev/null
@@ -0,0 +1,152 @@
+/*
+ * Copyright © 2015 Yale 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.basic.endpointcostservice.impl.base;
+
+
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.core.types.rev150921.CostTypeData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointcost.rev151021.QueryInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointcost.rev151021.QueryOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointcost.rev151021.QueryOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointcost.rev151021.ResourceTypeEndpointcost;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointcost.rev151021.alto.request.endpointcost.request.EndpointcostRequest;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointcost.rev151021.alto.response.endpointcost.response.EndpointcostResponseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointcost.rev151021.endpointcost.request.data.EndpointcostParams;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointcost.rfc7285.rev151021.TypedAddressData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointcost.rfc7285.rev151021.endpoint.filter.data.EndpointFilter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointcost.rfc7285.rev151021.endpointcostmap.response.data.EndpointCostMapBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointcost.rfc7285.rev151021.endpointcostmap.response.data.endpoint.cost.map.EndpointCost;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointcost.rfc7285.rev151021.endpointcostmap.response.data.endpoint.cost.map.EndpointCostBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointcost.rfc7285.rev151021.endpointcostmap.response.data.endpoint.cost.map.endpoint.cost.Cost;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointcost.rfc7285.rev151021.endpointcostmap.response.data.endpoint.cost.map.endpoint.cost.DestinationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointcost.rfc7285.rev151021.endpointcostmap.response.data.endpoint.cost.map.endpoint.cost.SourceBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointcost.rfc7285.rev151021.query.input.request.endpointcost.request.endpointcost.params.filter.EndpointFilterData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointcost.rfc7285.rev151021.query.output.response.endpointcost.response.endpointcost.data.EndpointCostmapDataBuilder;
+import org.opendaylight.yangtools.yang.common.RpcError;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public abstract class BaseECSImplementation {
+    protected DataBroker dataBroker;
+    private RpcResult<QueryOutput> ecsOutput;
+
+    protected EndpointcostRequest request;
+    protected EndpointcostParams params;
+    protected CostTypeData costType;
+    protected EndpointFilter filter;
+
+    public ListenableFuture<RpcResult<QueryOutput>> getECS(QueryInput input){
+        if (checkInput(input) && postCheck(input)) {
+            buildEndpointCostServiceOutput(input);
+        }
+        return Futures.immediateFuture(ecsOutput);
+    }
+
+    private void buildEndpointCostServiceOutput(QueryInput input) {
+        request = (EndpointcostRequest)input.getRequest();
+        params = request.getEndpointcostParams();
+        costType = params.getCostType();
+        filter = ((EndpointFilterData)params.getFilter()).getEndpointFilter();
+        List<EndpointCost> ecmList = buildEndpointCostMapList(filter.getSource(), filter.getDestination(), costType);
+        buildEndpointCostServiceOutput(ecmList);
+    }
+
+    private void buildEndpointCostServiceOutput(List<EndpointCost> ecmList) {
+        EndpointCostMapBuilder endpointCostMapBuilder = new EndpointCostMapBuilder().setEndpointCost(ecmList);
+        EndpointCostmapDataBuilder endpointCostmapDataBuilder = new EndpointCostmapDataBuilder().setEndpointCostMap(endpointCostMapBuilder.build());
+        EndpointcostResponseBuilder endpointcostResponseBuilder = new EndpointcostResponseBuilder().setEndpointcostData(endpointCostmapDataBuilder.build());
+        QueryOutputBuilder queryOutputBuilder = new QueryOutputBuilder().setResponse(endpointcostResponseBuilder.build()).setType(ResourceTypeEndpointcost.class);
+        if (queryOutputBuilder != null) {
+            this.ecsOutput = RpcResultBuilder.success(queryOutputBuilder).build();
+        } else {
+            this.ecsOutput = buildErrorRpcResult("Invalid output value ",
+                    "output is null");
+        }
+    }
+
+    private List<EndpointCost> buildEndpointCostMapList(List<? extends TypedAddressData> source, List<? extends TypedAddressData> destination, CostTypeData costType) {
+        List<EndpointCost> ecmList = new ArrayList<EndpointCost>();
+        for (TypedAddressData src : source){
+            for(TypedAddressData dst:destination){
+                Cost cost = getCost(src, dst, costType);
+                ecmList.add(buildEndpointCost(src,dst,cost));
+            }
+        }
+        //TODO  operate oridinal
+        return ecmList;
+    }
+
+    private EndpointCost buildEndpointCost(TypedAddressData src, TypedAddressData dst, Cost cost) {
+        EndpointCost endpointCost = null;
+        SourceBuilder sourceBuilder = new SourceBuilder();
+        DestinationBuilder destinationBuilder = new DestinationBuilder();
+        endpointCost = new EndpointCostBuilder().setCost(cost)
+                .setSource(sourceBuilder.setAddress(src.getAddress()).build())
+                .setDestination(destinationBuilder.setAddress(dst.getAddress()).build())
+                .build();
+        return endpointCost;
+    }
+
+    private Cost getCost(TypedAddressData src, TypedAddressData dst, CostTypeData costType) {
+        if (validSrcDstIpPair(src, dst)) {
+            return computeCost(src, dst, costType);
+        }
+        return null;
+    }
+
+    protected abstract Cost computeCost(TypedAddressData src, TypedAddressData dst, CostTypeData costType);
+
+
+    private boolean validSrcDstIpPair(TypedAddressData src, TypedAddressData dst) {
+        return true;
+    }
+
+    /**
+     * @param input is the input of ECS.
+     * @return true if input is validate.
+     */
+    public boolean checkInput(QueryInput input) {
+        request = (EndpointcostRequest)input.getRequest();
+        params = request.getEndpointcostParams();
+        costType = params.getCostType();
+        filter = ((EndpointFilterData)params.getFilter()).getEndpointFilter();
+
+        if(costType == null){
+            ecsOutput = buildErrorRpcResult("Invalid cost-type value ",
+                    "CostType is null");
+            return false;
+        }
+        if(!(params.getFilter() instanceof EndpointFilterData) || filter == null){
+            ecsOutput = buildErrorRpcResult("Invalid endpoints value ",
+                    "Endpoints is null");
+            return false;
+        }
+        return true;
+    }
+
+    protected boolean postCheck(QueryInput input) {
+        return true;
+    }
+
+    /**
+     * @param errorCode
+     * @param errorMessage
+     * @return built RPC error result.
+     */
+    protected RpcResult<QueryOutput> buildErrorRpcResult(
+            String errorCode, String errorMessage) {
+        return RpcResultBuilder.<QueryOutput> failed()
+                .withError(RpcError.ErrorType.APPLICATION, errorCode, errorMessage)
+                .build();
+    }
+}
diff --git a/alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/suportservice/exception/ReadDataFailedException.java b/alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/suportservice/exception/ReadDataFailedException.java
new file mode 100644 (file)
index 0000000..7993444
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * Copyright © 2015 Yale 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.basic.endpointcostservice.suportservice.exception;
+
+public class ReadDataFailedException extends Exception {
+    private static final long serialVersionUID = 1L;
+
+    public void printMessage(String message) {
+        System.out.println(message);
+    }
+}
diff --git a/alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/suportservice/impl/HostNodeTrackerImpl.java b/alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/suportservice/impl/HostNodeTrackerImpl.java
new file mode 100644 (file)
index 0000000..ac77f89
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ * Copyright © 2015 Yale 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.basic.endpointcostservice.suportservice.impl;
+
+
+import org.opendaylight.alto.basic.endpointcostservice.suportservice.service.HostNodeTrackerService;
+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 HostNodeTrackerImpl implements HostNodeTrackerService,DataChangeListener {
+
+    private static final Logger log = LoggerFactory
+            .getLogger(HostNodeTrackerImpl.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 HostNodeTrackerImpl  (DataBroker dataBroker) {
+        this.log.info("AddressConvertServiceImpl initial.");
+        this.dataBroker = dataBroker;
+        macToIp = new HashMap<String,String>();
+        ipToMac = new HashMap<String,String>();
+        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);
+    }
+    public String getIpByMac(String macAddress) {
+        return this.macToIp.get(macAddress);
+    }
+
+    public String getMacByIp(String ipAddress) {
+        return this.ipToMac.get(ipAddress);
+    }
+
+    public Boolean isValidHost(String ipAddress) {
+        if(ipAddress != null) {
+            return this.ipToMac.containsKey(ipAddress);
+        }
+        else {
+            return false;
+        }
+    }
+
+    public void onDataChanged(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
+        exec.submit(new Runnable() {
+            @Override
+            public void run() {
+                if (change == null) {
+                    log.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) {
+                    log.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);
+                        log.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;
+                        log.info("createdData addresses:" + addrs);
+                        macToIp.put(addrs.getMac().getValue(), addrs.getIp().getIpv4Address().getValue());
+                        ipToMac.put(addrs.getIp().getIpv4Address().getValue(), addrs.getMac().getValue());
+                    }
+                }
+            }
+        });
+    }
+}
diff --git a/alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/suportservice/impl/LinkServiceImpl.java b/alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/suportservice/impl/LinkServiceImpl.java
new file mode 100644 (file)
index 0000000..79a12f2
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ * Copyright © 2015 Yale 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.basic.endpointcostservice.suportservice.impl;
+
+import org.opendaylight.alto.basic.endpointcostservice.suportservice.service.LinkService;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Link;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.ArrayList;
+import java.util.concurrent.ConcurrentHashMap;
+
+public class LinkServiceImpl implements LinkService {
+    private static final Logger log = LoggerFactory
+            .getLogger(LinkServiceImpl.class);
+    private Map<String, Set<String>> srcTpIdIndexedLinks = new ConcurrentHashMap<String, Set<String>>();
+    private Map<String, Set<String>> dstTpIdIndexedLinks = new ConcurrentHashMap<String, Set<String>>();
+    private Map<String, Set<String>> srcNodeIdIndexedLinks = new ConcurrentHashMap<String, Set<String>>();
+    private Map<String, Set<String>> dstNodeIdIndexedLinks = new ConcurrentHashMap<String, Set<String>>();
+    private Map<String, Link> linkIdIndexedLinks = new ConcurrentHashMap<String, Link>();
+    @Override
+    public void addLink(Link link) {
+        synchronized (this) {
+            this.linkIdIndexedLinks.put(link.getLinkId().getValue(), link);
+            addLinkToTpIdIndexedLinks(srcTpIdIndexedLinks, link);
+            addLinkToTpIdIndexedLinks(dstTpIdIndexedLinks, link);
+            addLinkToNodeIdIndexedLinks(srcNodeIdIndexedLinks, link);
+            addLinkToNodeIdIndexedLinks(dstNodeIdIndexedLinks, link);
+            log.info("Adding link with source as " + link.getSource().getSourceTp().getValue()
+                    + " and link id as " + link.getLinkId().getValue());
+        }
+    }
+
+    @Override
+    public void deleteLink(Link link) {
+        synchronized (this) {
+            this.linkIdIndexedLinks.remove(link.getLinkId().getValue());
+            deleteLinkFromTpIdIndexedLinks(srcTpIdIndexedLinks, link);
+            deleteLinkFromTpIdIndexedLinks(dstTpIdIndexedLinks, link);
+            deleteLinkFromNodeIdIndexedLinks(srcNodeIdIndexedLinks, link);
+            deleteLinkFromNodeIdIndexedLinks(dstNodeIdIndexedLinks, link);
+            log.info("Remove link with source as " + link.getSource().getSourceTp().getValue()
+                    + " and link id as "+ link.getLinkId().getValue());
+        }
+    }
+
+    @Override
+    public Link getLinkByLinkId(String linkId) {
+        return linkIdIndexedLinks.get(linkId);
+    }
+
+    @Override
+    public List<Link> getLinksBySourceNodeId(String srcNodeId) {
+        return getLinksByNodeId(srcNodeIdIndexedLinks, srcNodeId);
+    }
+
+    @Override
+    public List<Link> getLinksByDestinationNodeId(String dstNodeId) {
+        return getLinksByNodeId(dstNodeIdIndexedLinks, dstNodeId);
+    }
+
+    @Override
+    public Link getLinkBySourceTpId(String srcTpId) {
+        return getLinksByNodeConnectorTpId(srcTpIdIndexedLinks, srcTpId).get(0);
+    }
+
+    @Override
+    public Link getLinkByDestinationTpId(String dstTpId) {
+        return getLinksByNodeConnectorTpId(dstTpIdIndexedLinks, dstTpId).get(0);
+    }
+
+    @Override
+    public Link getRevertedLink(Link link) {
+        return null;
+    }
+
+
+    private void addLinkToTpIdIndexedLinks(Map<String, Set<String>> tpIdIndexedLinks, Link link) {
+        String key = link.getSource().getSourceTp().getValue();
+        String value = link.getLinkId().getValue();
+        addLinkToIndexedLinks(tpIdIndexedLinks, key, value);
+    }
+
+    private void addLinkToNodeIdIndexedLinks(Map<String, Set<String>> nodeIdIndexedLinks, Link link) {
+        String key = link.getSource().getSourceNode().getValue();
+        String value = link.getLinkId().getValue();
+        addLinkToIndexedLinks(nodeIdIndexedLinks, key, value);
+    }
+
+    private void addLinkToIndexedLinks(Map<String, Set<String>> indexedLinks, String key, String value) {
+        if (!indexedLinks.containsKey(key)) {
+            Set<String> linkIdSet = new HashSet<String>();
+            indexedLinks.put(key, linkIdSet);
+        }
+        indexedLinks.get(key).add(value);
+    }
+
+    private void deleteLinkFromTpIdIndexedLinks(Map<String, Set<String>> tpIdIndexedLinks, Link link) {
+        String key = link.getSource().getSourceTp().getValue();
+        String value = link.getLinkId().getValue();
+        deleteLinkFromIndexedLinks(tpIdIndexedLinks, key, value);
+    }
+
+    private void deleteLinkFromNodeIdIndexedLinks(Map<String, Set<String>> nodeIdIndexedLinks, Link link) {
+        String key = link.getSource().getSourceNode().getValue();
+        String value = link.getLinkId().getValue();
+        deleteLinkFromIndexedLinks(nodeIdIndexedLinks, key, value);
+    }
+
+    private void deleteLinkFromIndexedLinks(Map<String, Set<String>> indexedLinks, String key, String value) {
+        if (indexedLinks.containsKey(key)) {
+            indexedLinks.get(key).remove(value);
+        }
+    }
+
+    private List<Link> getLinksByNodeConnectorTpId(Map<String, Set<String>> tpIdIndexedLinks, String tpId) {
+        return getLinks(tpIdIndexedLinks, tpId);
+    }
+
+    private List<Link> getLinksByNodeId(Map<String, Set<String>> nodeIdIndexedLinks, String nodeId) {
+        return getLinks(nodeIdIndexedLinks, nodeId);
+    }
+
+    private List<Link> getLinks(Map<String, Set<String>> indexedLinks, String key) {
+        List<Link> links = new ArrayList<Link>();
+        if (indexedLinks.containsKey(key)) {
+            for (String linkId : indexedLinks.get(key)) {
+                links.add(getLinkByLinkId(linkId));
+            }
+        }
+        return links;
+    }
+}
diff --git a/alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/suportservice/impl/NetworkElementImpl.java b/alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/suportservice/impl/NetworkElementImpl.java
new file mode 100644 (file)
index 0000000..ed69689
--- /dev/null
@@ -0,0 +1,206 @@
+/*
+ * Copyright © 2015 Yale 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.basic.endpointcostservice.suportservice.impl;
+
+import org.opendaylight.alto.basic.endpointcostservice.suportservice.exception.ReadDataFailedException;
+import org.opendaylight.alto.basic.endpointcostservice.suportservice.service.LinkService;
+import org.opendaylight.alto.basic.endpointcostservice.suportservice.service.NetworkElementService;
+import org.opendaylight.alto.basic.endpointcostservice.suportservice.service.NetworkFlowCapableNodeService;
+import org.opendaylight.alto.basic.endpointcostservice.suportservice.service.NetworkHostNodeService;
+import org.opendaylight.alto.basic.endpointcostservice.helper.DataStoreHelper;
+import org.opendaylight.alto.basic.endpointcostservice.util.InstanceIdentifierUtils;
+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.host.tracker.rev140624.HostNode;
+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.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.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+public class NetworkElementImpl implements NetworkElementService, DataChangeListener, AutoCloseable {
+    private static final Logger log = LoggerFactory
+            .getLogger(NetworkElementImpl.class);
+    private static final int CPUS = Runtime.getRuntime().availableProcessors();
+    private ExecutorService exec = Executors.newFixedThreadPool(CPUS);
+
+    private DataBroker dataBroker;
+    private ListenerRegistration<DataChangeListener> hostNodeListRegistration;
+    private ListenerRegistration<DataChangeListener> linkListRegistration;
+
+    private NetworkHostNodeService hostNodeService;
+    private LinkService linkService;
+    private NetworkFlowCapableNodeService flowCapableNodeService;
+
+
+    public NetworkElementImpl(DataBroker dataBroker) {
+        this.dataBroker = dataBroker;
+        this.linkService = new LinkServiceImpl();
+        this.hostNodeService = new NetworkHostNodeImpl();
+        this.flowCapableNodeService = new NetworkFlowCapableNodeImpl(dataBroker);
+        registerAsDataChangeListener();
+    }
+
+    public void registerAsDataChangeListener() {
+        addExistingNodes();
+        registerHostNodeListener();
+        registerLinkListener();
+    }
+
+    private void addExistingNodes() {
+        try {
+            Topology topology = DataStoreHelper.readOperational(this.dataBroker, InstanceIdentifierUtils.TOPOLOGY);
+            addExistingHostNodes(topology);
+            addExistingLinks(topology);
+        } catch (ReadDataFailedException e) {
+            e.printMessage("Read topology failed");
+            e.printStackTrace();
+        }
+    }
+    private void addExistingHostNodes(Topology topology) {
+        log.info("Topology Null Check: " + (topology == null));
+        List<Node> nodeList = topology.getNode();
+        log.info("Node List Null Check: " + (nodeList == null));
+        if (topology != null && nodeList != null) {
+            for (int i = 0; i < nodeList.size(); ++i) {
+                Node node = nodeList.get(i);
+                HostNode hostNode = node.getAugmentation(HostNode.class);
+                log.info("Processing node " + i + ", " + hostNode);
+                hostNodeService.addHostNode(hostNode);
+            }
+        }
+    }
+
+    private void addExistingLinks(Topology topology) {
+        log.info("Topology Null Check: " + (topology == null));
+        List<Link> linkList = topology.getLink();
+        log.info("Link List Null Check: " + (linkList == null));
+        if (topology != null && linkList != null) {
+            for (int i = 0; i < linkList.size(); i++) {
+                Link link = linkList.get(i);
+                log.info("Processing link " + i + ", " + link.getLinkId().getValue());
+                linkService.addLink(link);
+            }
+        }
+    }
+    @Override
+    public void close() throws Exception {
+        this.hostNodeListRegistration.close();
+        this.linkListRegistration.close();
+    }
+
+    @Override
+    public void onDataChanged(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
+        exec.submit(new Runnable() {
+            @Override
+            public void run() {
+                if (change == null) {
+                    log.info("In onDataChanged: Change event is null.");
+                    return;
+                }
+                onDataUpdated(change);
+                onDataCreated(change);
+                onDataDeleted(change);
+            }
+
+            private void onDataUpdated(
+                    AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
+                Map<InstanceIdentifier<?>, DataObject> updatedData = change
+                        .getUpdatedData();
+                if (updatedData.size() > 0) {
+                    log.info("In onDataUpdated");
+                    processUpdatedOrCreatedData(updatedData);
+                }
+            }
+
+            private void onDataCreated(
+                    AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
+                Map<InstanceIdentifier<?>, DataObject> createdData = change
+                        .getCreatedData();
+                if (createdData.size() > 0) {
+                    log.info("In onDataCreated");
+                    processUpdatedOrCreatedData(createdData);
+                }
+            }
+
+            private void processUpdatedOrCreatedData(
+                    Map<InstanceIdentifier<?>, DataObject> data) {
+                for (Map.Entry<InstanceIdentifier<?>, DataObject> entrySet : data
+                        .entrySet()) {
+                    final DataObject dataObject = entrySet.getValue();
+                    if (dataObject instanceof HostNode) {
+                        log.info("Mapping host nodes to switch");
+                        hostNodeService.addHostNode((HostNode) dataObject);
+                    } else if (dataObject instanceof Link) {
+                        log.info("Updating Links");
+                        linkService.addLink((Link) dataObject);
+                    }
+                }
+            }
+
+            private void onDataDeleted(
+                    AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
+                Map<InstanceIdentifier<?>, DataObject> originalData = change
+                        .getOriginalData();
+                Set<InstanceIdentifier<?>> deletedData = change
+                        .getRemovedPaths();
+                if (deletedData.size() > 0) {
+                    log.info("In onDataDeleted");
+                    processDeletedData(originalData, deletedData);
+                }
+            }
+
+            private void processDeletedData(
+                    Map<InstanceIdentifier<?>, DataObject> originalData,
+                    Set<InstanceIdentifier<?>> deletedData) {
+                for (InstanceIdentifier<?> iid : deletedData) {
+                    if (iid.getTargetType().equals(HostNode.class)) {
+                        hostNodeService.deleteHostNode((HostNode) originalData.get(iid));
+                    } else if (iid.getTargetType().equals(Link.class)) {
+                        linkService.deleteLink((Link) originalData.get(iid));
+                    }
+                }
+            }
+        });
+
+    }
+
+    @Override
+    public LinkService getLinkService() {
+        return linkService;
+    }
+
+    @Override
+    public NetworkHostNodeService getHostNodeService() {
+        return hostNodeService;
+    }
+
+    @Override
+    public NetworkFlowCapableNodeService getFlowCapableNodeService() {
+        return flowCapableNodeService;
+    }
+
+    private void registerHostNodeListener() {
+        this.hostNodeListRegistration = this.dataBroker.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL, InstanceIdentifierUtils.HOSTNODE, this, AsyncDataBroker.DataChangeScope.BASE);
+    }
+    private void registerLinkListener() {
+        this.linkListRegistration = this.dataBroker.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,InstanceIdentifierUtils.LINK,this, AsyncDataBroker.DataChangeScope.BASE);
+    }
+}
diff --git a/alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/suportservice/impl/NetworkFlowCapableNodeImpl.java b/alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/suportservice/impl/NetworkFlowCapableNodeImpl.java
new file mode 100644 (file)
index 0000000..01be96c
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ * Copyright © 2015 Yale 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.basic.endpointcostservice.suportservice.impl;
+
+import org.opendaylight.alto.basic.endpointcostservice.suportservice.exception.ReadDataFailedException;
+import org.opendaylight.alto.basic.endpointcostservice.suportservice.service.NetworkFlowCapableNodeService;
+import org.opendaylight.alto.basic.endpointcostservice.suportservice.service.NetworkPortStatisticsService;
+import org.opendaylight.alto.basic.endpointcostservice.helper.DataStoreHelper;
+import org.opendaylight.alto.basic.endpointcostservice.util.InstanceIdentifierUtils;
+import org.opendaylight.alto.basic.endpointcostservice.util.NameConverter;
+import org.opendaylight.alto.basic.endpointcostservice.util.NetworkServiceConstants;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+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.meter.types.rev130918.meter.meter.band.headers.MeterBandHeader;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.flow.capable.node.connector.statistics.FlowCapableNodeConnectorStatistics;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class NetworkFlowCapableNodeImpl implements NetworkFlowCapableNodeService{
+    private static final Logger log = LoggerFactory
+            .getLogger(NetworkFlowCapableNodeImpl.class);
+    private DataBroker dataBroker;
+    private NetworkPortStatisticsService portStatistics;
+
+    public NetworkFlowCapableNodeImpl(DataBroker dataBroker) {
+        this.dataBroker = dataBroker;
+        this.portStatistics = new NetworkPortStatisticsServiceImpl(dataBroker);
+    }
+
+    @Override
+    public void addFlowCapableNode(FlowCapableNode node) {}
+
+    @Override
+    public void deleteFlowCapableNode(FlowCapableNode node) {}
+
+    @Override
+    public FlowCapableNode getFlowCapableNode(String nodeId) {
+        log.info("Reading flow capable node for " + nodeId);
+        try {
+            return DataStoreHelper.readOperational(dataBroker,
+                    InstanceIdentifierUtils.flowCapableNode(nodeId));
+        } catch (ReadDataFailedException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    @Override
+    public FlowCapableNodeConnector getFlowCapableNodeConnector(String tpId) {
+        log.info("Reading flow capable node connector for " + tpId);
+        try {
+            return DataStoreHelper.readOperational(dataBroker,
+                    InstanceIdentifierUtils.flowCapableNodeConnector(tpId));
+        } catch (ReadDataFailedException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    @Override
+    public FlowCapableNodeConnectorStatistics getFlowCapableNodeConnectorStatistics(String tpId) {
+        log.info("Reading flow capable node connector statistics data for + " + tpId);
+        try {
+            return DataStoreHelper.readOperational(dataBroker,
+                    InstanceIdentifierUtils.flowCapableNodeConnectorStatisticsData(tpId))
+                    .getFlowCapableNodeConnectorStatistics();
+        } catch (ReadDataFailedException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    @Override
+    public Long getConsumedBandwidth(String tpId) {
+        FlowCapableNodeConnector nodeConnector = getFlowCapableNodeConnector(tpId);
+        return getConsumedBandwidth(tpId, isHalfDuplex(nodeConnector));
+    }
+
+    @Override
+    public Long getAvailableBandwidth(String tpId) {
+        return getAvailableBandwidth(tpId, null);
+    }
+
+    @Override
+    public Long getAvailableBandwidth(String tpId, Long meterId) {
+        FlowCapableNodeConnector nodeConnector = getFlowCapableNodeConnector(tpId);
+        Long capacity = getCapacity(nodeConnector, readMeter(tpId, meterId));
+        Long consumedBandwidth = getConsumedBandwidth(tpId, isHalfDuplex(nodeConnector));
+        log.info("capacity: " + capacity);
+        log.info("consumedBandwidth: " + consumedBandwidth);
+        if (capacity == null || consumedBandwidth == null) return null;
+        return capacity - consumedBandwidth;
+    }
+
+
+    @Override
+    public Long getCapacity(String tpId) {
+        return getCapacity(tpId, null);
+    }
+
+    @Override
+    public Long getCapacity(String tpId, Long meterId) {
+        FlowCapableNodeConnector nodeConnector = getFlowCapableNodeConnector(tpId);
+        return getCapacity(nodeConnector, readMeter(tpId, meterId));
+    }
+
+    private long getConsumedBandwidth(String tpId, boolean isHalfDuplex) {
+        long transmitted = portStatistics.getCurrentTxSpeed(tpId, NetworkPortStatisticsService.Metric.BITSPERSECOND)
+                / 1000;
+        long received = portStatistics.getCurrentRxSpeed(tpId, NetworkPortStatisticsService.Metric.BITSPERSECOND)
+                / 1000;
+        if (isHalfDuplex) {
+            return transmitted + received;
+        } else {
+            return transmitted;
+        }
+    }
+    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)];
+    }
+
+    private Meter readMeter(String tpId, long meterId) {
+        String nodeId = NameConverter.extractNodeId(tpId);
+        try {
+            return DataStoreHelper.readOperational(this.dataBroker,
+                    InstanceIdentifierUtils.flowCapableNodeMeter(nodeId, meterId));
+        } catch (ReadDataFailedException e) {
+            e.printStackTrace();
+        } catch (NullPointerException e) {
+            return null;
+        }
+        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;
+    }
+}
diff --git a/alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/suportservice/impl/NetworkHostNodeImpl.java b/alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/suportservice/impl/NetworkHostNodeImpl.java
new file mode 100644 (file)
index 0000000..0724bf5
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * Copyright © 2015 Yale 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.basic.endpointcostservice.suportservice.impl;
+
+import org.opendaylight.alto.basic.endpointcostservice.suportservice.service.NetworkHostNodeService;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
+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.Ipv6Address;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.address.tracker.rev140617.address.node.connector.Addresses;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointcost.rfc7285.rev151021.Ipv4AddressData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointcost.rfc7285.rev151021.Ipv6AddressData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointcost.rfc7285.rev151021.TypedAddressData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.host.tracker.rev140624.HostNode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.ArrayList;
+import java.util.concurrent.ConcurrentHashMap;
+
+public class NetworkHostNodeImpl implements NetworkHostNodeService {
+    private static final Logger log = LoggerFactory
+            .getLogger(NetworkHostNodeImpl.class);
+
+    private Map<String, Set<String>> ipIndexedHostNode = new ConcurrentHashMap<String, Set<String>>();
+    private Map<String, HostNode> hostNodes = new ConcurrentHashMap<String, HostNode>();
+
+    @Override
+    public void addHostNode(HostNode node) {
+        synchronized (this) {
+            this.hostNodes.put(node.getId().getValue(), node);
+            addToIpIndexedHostNodeMaps(node);
+            log.info("Adding hostnode " + node.getId().getValue());
+        }
+    }
+
+    private void addToIpIndexedHostNodeMaps(HostNode node) {
+        String uniqueIp = uniqueIpAddress(node);
+        if (!this.ipIndexedHostNode.containsKey(uniqueIp)) {
+            Set<String> linkIdSet = new HashSet<String>();
+            ipIndexedHostNode.put(uniqueIp, linkIdSet);
+        }
+        ipIndexedHostNode.get(uniqueIp).add(node.getId().getValue());
+    }
+
+    private String uniqueIpAddress(HostNode node) {
+        Addresses address = node.getAddresses().get(0);
+        return touniqueIpAddress(address.getIp());
+    }
+
+    private String touniqueIpAddress(IpAddress ipAddress) {
+        Ipv4Address ipv4 = ipAddress.getIpv4Address();
+        if (ipv4 != null) {
+            return ipv4.getValue();
+        }
+        Ipv6Address ipv6 = ipAddress.getIpv6Address();
+        if (ipv6 != null) {
+            return uniqueIpv6String(ipv6.getValue());
+        }
+        return null;
+    }
+    private static String uniqueIpv6String(String ipv6) {
+        try {
+            return ipv6ToUniqueString(ipv6);
+        } catch (UnknownHostException e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+    public static String ipv6ToUniqueString(String address) throws UnknownHostException {
+        byte[] b = toBytes(address);
+        return toHexString(b);
+    }
+
+    private static byte[] toBytes(String address) throws UnknownHostException {
+        Inet6Address addr = (Inet6Address) InetAddress.getByName(address);
+        return addr.getAddress();
+    }
+
+    private static String toHexString(byte[] bytes) {
+        StringBuilder sb = new StringBuilder();
+        for (byte b : bytes) {
+            sb.append(String.format("%02X", b));
+        }
+        return sb.toString();
+    }
+
+    @Override
+    public void deleteHostNode(HostNode node) {
+        String uniqueId = uniqueIpAddress(node);
+        synchronized (this) {
+            this.ipIndexedHostNode.remove(uniqueId);
+            removeFromIpIndexedHostNodeMaps(node);
+            log.info("Removing host node " + node.getId().getValue());
+        }
+
+    }
+
+    private void removeFromIpIndexedHostNodeMaps(HostNode node) {
+        String uniqueIp = uniqueIpAddress(node);
+        if (this.ipIndexedHostNode.containsKey(uniqueIp)) {
+            ipIndexedHostNode.get(uniqueIp).remove(node.getId().getValue());
+        }
+    }
+
+    @Override
+    public HostNode getHostNodeByHostIP(TypedAddressData ip) {
+        return getHostNodes(ip).get(0);
+    }
+
+    private List<HostNode> getHostNodes(TypedAddressData ip) {
+        String uniqueIp = touniqueIpAddress(ip);
+        List<HostNode> hosts = new ArrayList<HostNode>();
+        if (ipIndexedHostNode.containsKey(uniqueIp)) {
+            for (String hostId : ipIndexedHostNode.get(uniqueIp)) {
+                hosts.add(getHostNodeByHostId(hostId));
+            }
+        }
+        return hosts;
+    }
+
+    @Override
+    public HostNode getHostNodeByHostId(String hostId) {
+        return hostNodes.get(hostId);
+    }
+
+    @Override
+    public boolean isValidHost(TypedAddressData ip) {
+        return this.ipIndexedHostNode.containsKey(touniqueIpAddress(ip));
+    }
+
+    public static String touniqueIpAddress(TypedAddressData ipAddress) {
+        if (ipAddress.getAddress() instanceof Ipv4AddressData) {
+            return ((Ipv4AddressData) ipAddress.getAddress()).getIpv4().getValue().replaceAll("^ipv4:", "");
+        }
+        if (ipAddress.getAddress() instanceof Ipv6AddressData) {
+            return uniqueIpv6String(
+                    ((Ipv6AddressData) ipAddress.getAddress()).getIpv6().
+                            getValue().replaceAll("^ipv6:", ""));
+        }
+        return null;
+    }
+}
diff --git a/alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/suportservice/impl/NetworkPortStatisticsServiceImpl.java b/alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/suportservice/impl/NetworkPortStatisticsServiceImpl.java
new file mode 100644 (file)
index 0000000..ee2c46b
--- /dev/null
@@ -0,0 +1,154 @@
+/*
+ * Copyright © 2015 Yale 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.basic.endpointcostservice.suportservice.impl;
+
+import org.opendaylight.alto.basic.endpointcostservice.suportservice.service.NetworkPortStatisticsService;
+import org.opendaylight.alto.basic.endpointcostservice.util.InstanceIdentifierUtils;
+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.inventory.rev130819.node.NodeConnector;
+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;
+
+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;
+
+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<String, nodeStatistic>();
+        registerPortListener();
+    }
+
+    private void registerPortListener() {
+        this.portListener = this.dataBroker.registerDataChangeListener(
+                LogicalDatastoreType.OPERATIONAL, InstanceIdentifierUtils.STATISTICS,
+                this, AsyncDataBroker.DataChangeScope.SUBTREE
+        );
+    }
+    @Override
+    public void close() throws Exception {
+        portListener.close();
+    }
+
+    @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)
+                                    .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).getId().getValue();
+                        nodeStatisticData.remove(name);
+                    }
+                }
+            }
+        });
+    }
+
+    @Override
+    public Long getCurrentTxSpeed(String tpId, Metric metric) {
+        if (nodeStatisticData.containsKey(tpId)) {
+            if (metric == Metric.BITSPERSECOND)
+                return nodeStatisticData.get(tpId).txSpeed * 8;
+            else if (metric == Metric.BYTESPERSECOND)
+                return nodeStatisticData.get(tpId).txSpeed;
+        }
+        return null;
+    }
+
+    @Override
+    public Long getCurrentRxSpeed(String tpId, Metric metric) {
+        if (nodeStatisticData.containsKey(tpId)) {
+            if (metric == Metric.BITSPERSECOND)
+                return nodeStatisticData.get(tpId).rxSpeed * 8;
+            else if (metric == Metric.BYTESPERSECOND)
+                return nodeStatisticData.get(tpId).rxSpeed;
+        }
+        return null;
+    }
+}
diff --git a/alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/suportservice/impl/RoutingServiceImpl.java b/alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/suportservice/impl/RoutingServiceImpl.java
new file mode 100644 (file)
index 0000000..73afcff
--- /dev/null
@@ -0,0 +1,165 @@
+/*
+ * Copyright © 2015 Yale 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.basic.endpointcostservice.suportservice.impl;
+
+import org.opendaylight.alto.basic.endpointcostservice.flow.FlowTableMatcher;
+import org.opendaylight.alto.basic.endpointcostservice.suportservice.service.LinkService;
+import org.opendaylight.alto.basic.endpointcostservice.suportservice.service.NetworkElementService;
+import org.opendaylight.alto.basic.endpointcostservice.suportservice.service.NetworkFlowCapableNodeService;
+import org.opendaylight.alto.basic.endpointcostservice.suportservice.service.NetworkHostNodeService;
+import org.opendaylight.alto.basic.endpointcostservice.suportservice.service.RoutingService;
+import org.opendaylight.alto.basic.endpointcostservice.util.LinkNode;
+import org.opendaylight.alto.basic.endpointcostservice.flow.MatchFields;
+import org.opendaylight.alto.basic.endpointcostservice.util.NameConverter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointcost.rfc7285.rev151021.TypedAddressData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.host.tracker.rev140624.host.AttachmentPoints;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Link;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class RoutingServiceImpl implements RoutingService {
+    private static final Logger log = LoggerFactory
+            .getLogger(RoutingServiceImpl.class);
+
+    private LinkService linkService;
+    private NetworkHostNodeService hostNodeService;
+    private NetworkFlowCapableNodeService flowCapableNodeService;
+
+    private FlowTableMatcher flowTableMatcher = new FlowTableMatcher();
+    private List<LinkNode> pathStack = new ArrayList<LinkNode>();
+    private Map<String, LinkNode> visitedInPort = new HashMap<String, LinkNode>();
+
+    public RoutingServiceImpl(NetworkElementService networkService) {
+        this.linkService = networkService.getLinkService();
+        this.hostNodeService = networkService.getHostNodeService();
+        this.flowCapableNodeService = networkService.getFlowCapableNodeService();
+    }
+
+    @Override
+    public LinkNode buildRoutePath(MatchFields matchFields) {
+        pathStack.clear();
+        visitedInPort.clear();
+        return buildRoutePathByLookingUpFRM(matchFields);
+    }
+
+    private LinkNode buildRoutePathByLookingUpFRM(MatchFields matchFields) {
+        log.info("Building Routing Path by looking up FRM");
+        LinkNode head = new LinkNode(getLinkByHostIp(matchFields.srcIp));
+        pathStack.add(head);
+        while (!pathStack.isEmpty()) {
+            LinkNode linkNode = pathStack.remove(pathStack.size() - 1);
+            visitNode(linkNode, matchFields);
+        }
+        logRoutePath(head,matchFields);
+        return head;
+    }
+
+    private void visitNode(LinkNode node, MatchFields matchFields) {
+        if (!node.endWithHost()) {
+            matchFields.inPort = node.dstTpId();
+            visitSwitchNode(node, matchFields);
+            visitedInPort.put(node.dstTpId(), node);
+        }
+    }
+    private void visitSwitchNode(LinkNode node, MatchFields matchFields) {
+        FlowTableMatcher.FlowTableLookUpResult result = lookUpFlowTable(node, matchFields);
+        if (needReComputePath(result)) {
+            //TODO: complete recomputePath function
+            recomputePath(node, matchFields);
+        } else if (result != null) {
+            pushChildren(node, result);
+        }
+    }
+
+    private FlowTableMatcher.FlowTableLookUpResult lookUpFlowTable(LinkNode node, MatchFields matchFields) {
+        FlowCapableNode flowNode = flowCapableNodeService.getFlowCapableNode(node.dstNodeId());
+        if (flowNode != null) {
+            return flowTableMatcher.lookUpFlowTables(flowNode, matchFields);
+        }
+        return null;
+    }
+    private boolean needReComputePath(FlowTableMatcher.FlowTableLookUpResult result) {
+//        return result != null &&
+//                result.sendToController && result.outputNodeConnectors.size() == 0;
+        return false;
+    }
+
+    private LinkNode recomputePath(LinkNode node, MatchFields matchFields) {
+        return null;
+    }
+
+    private void pushChildren(LinkNode node, FlowTableMatcher.FlowTableLookUpResult result) {
+        for (int i = 0; i < result.outputNodeConnectors.size(); i++) {
+            String srcTpId = NameConverter.buildNodeConnectorId(
+                    node.dstNodeId(), result.outputNodeConnectors.get(i).getValue());
+            Link link = linkService.getLinkBySourceTpId(srcTpId);
+            if (link != null) {
+                LinkNode childNode = createLinkNode(link, result.meterId);
+                node.addChild(childNode);
+                if (!visitedInPort.containsKey(childNode.dstTpId())) {
+                    pathStack.add(childNode);
+                }
+            }
+        }
+    }
+
+    private LinkNode createLinkNode(Link link) {
+        return createLinkNode(link, null);
+    }
+
+    private LinkNode createLinkNode(Link link, Long meterId) {
+        String nextInPort = link.getDestination().getDestTp().getValue();
+        if (visitedInPort.containsKey(nextInPort)) {
+            return visitedInPort.get(nextInPort);
+        } else {
+            LinkNode node = new LinkNode(link);
+            String srcTpId = link.getSource().getSourceTp().getValue();
+            //Long bandwidth = this.flowCapableNodeService.getAvailableBandwidth(srcTpId, meterId);
+            //log.info("createLinkNode: " + link + ":" + bandwidth);
+            //node.setAvailableBandwidth(bandwidth);
+            node.setAvailableBandwidth(123L);
+            return node;
+        }
+    }
+
+    private void logRoutePath(LinkNode head,MatchFields matchFields) {
+        String path = "Paths: \n";
+        ArrayList<LinkNode> pathStack = new ArrayList<LinkNode>();
+        pathStack.add(head);
+        while (!pathStack.isEmpty()) {
+            LinkNode top = pathStack.remove(pathStack.size() - 1);
+            //////////////////////////
+            if(top.children().size() == 0 && top.getLink().getDestination().getDestTp().equals(getLinkByHostIp(matchFields.dstIp).getSource().getSourceTp())){
+                top.setAsDestHost();
+            }
+            pathStack.addAll(top.children());
+            path += top.srcTpId() + ", " + top.dstTpId() + "\n";
+        }
+        log.info(path);
+    }
+
+    private Link getLinkByHostIp(TypedAddressData ipAddr) {
+        AttachmentPoints points = getAttachmentPoint(ipAddr);
+        if (points != null && points.getCorrespondingTp() != null) {
+            Link link = linkService.getLinkBySourceTpId(
+                    points.getCorrespondingTp().getValue());
+            log.info("Getting Link: " + link.getSource() + "," + link.getDestination());
+            return link;
+        }
+        return null;
+    }
+    private AttachmentPoints getAttachmentPoint(TypedAddressData ip) {
+        return hostNodeService.getHostNodeByHostIP(ip).getAttachmentPoints().get(0);
+    }
+}
diff --git a/alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/suportservice/service/HostNodeTrackerService.java b/alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/suportservice/service/HostNodeTrackerService.java
new file mode 100644 (file)
index 0000000..42392c0
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * Copyright © 2015 Yale 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.basic.endpointcostservice.suportservice.service;
+
+public interface HostNodeTrackerService {
+    String getIpByMac(String macAddress);
+
+    String getMacByIp(String ipAddress);
+
+    Boolean isValidHost(String ipAddress);
+}
diff --git a/alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/suportservice/service/LinkService.java b/alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/suportservice/service/LinkService.java
new file mode 100644 (file)
index 0000000..1253c92
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright © 2015 Yale 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.basic.endpointcostservice.suportservice.service;
+
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Link;
+
+import java.util.List;
+
+public interface LinkService {
+
+    public void addLink(Link link);
+
+    public void deleteLink(Link link);
+
+    public Link getLinkByLinkId(String linkId);
+
+    public List<Link> getLinksBySourceNodeId(String srcNodeId);
+
+    public List<Link> getLinksByDestinationNodeId(String dstNodeId);
+
+    public Link getLinkBySourceTpId(String srcTpId);
+
+    public Link getLinkByDestinationTpId(String dstTpId);
+
+    public Link getRevertedLink(Link link);
+}
diff --git a/alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/suportservice/service/NetworkElementService.java b/alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/suportservice/service/NetworkElementService.java
new file mode 100644 (file)
index 0000000..b19239a
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * Copyright © 2015 Yale 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.basic.endpointcostservice.suportservice.service;
+
+public interface NetworkElementService {
+    public LinkService getLinkService();
+
+    public NetworkHostNodeService getHostNodeService();
+
+    public NetworkFlowCapableNodeService getFlowCapableNodeService();
+}
diff --git a/alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/suportservice/service/NetworkFlowCapableNodeService.java b/alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/suportservice/service/NetworkFlowCapableNodeService.java
new file mode 100644 (file)
index 0000000..4a2ebde
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright © 2015 Yale 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.basic.endpointcostservice.suportservice.service;
+
+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.port.statistics.rev131214.flow.capable.node.connector.statistics.FlowCapableNodeConnectorStatistics;
+
+public interface NetworkFlowCapableNodeService {
+    public void addFlowCapableNode(FlowCapableNode node);
+
+    public void deleteFlowCapableNode(FlowCapableNode node);
+
+    public FlowCapableNode getFlowCapableNode(String nodeId);
+
+    public FlowCapableNodeConnector getFlowCapableNodeConnector(String tpId);
+
+    /**
+     * Get the statistics by tpid.
+     * @param tpId
+     * @return a {@link FlowCapableNodeConnectorStatistics}.
+     */
+    public FlowCapableNodeConnectorStatistics getFlowCapableNodeConnectorStatistics(String tpId);
+
+    /**
+     * Get the consumed bandwidth by tpid.
+     * @param tpId
+     * @return the consumed bandwidth in kbps.
+     */
+    public Long getConsumedBandwidth(String tpId);
+
+    /**
+     * Get the available bandwidth by tpid.
+     * @param tpId
+     * @return the available bandwidth in kbps.
+     */
+    public Long getAvailableBandwidth(String tpId);
+
+    /**
+     * Get the available bandwidth by tpid and meter id.
+     * @param tpId
+     * @param meterId
+     * @return the available bandwidth in kbps.
+     */
+    public Long getAvailableBandwidth(String tpId, Long meterId);
+
+    /**
+     * Get the capacity by tpid.
+     * @param tpId
+     * @return the capacity bandwidth in kbps.
+     */
+    public Long getCapacity(String tpId);
+
+    /**
+     * Get the capacity by tpid and meter id.
+     * @param tpId
+     * @param meterId
+     * @return the capacity bandwidth in kbps.
+     */
+    public Long getCapacity(String tpId, Long meterId);
+}
diff --git a/alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/suportservice/service/NetworkHostNodeService.java b/alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/suportservice/service/NetworkHostNodeService.java
new file mode 100644 (file)
index 0000000..f5b2336
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Copyright © 2015 Yale 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.basic.endpointcostservice.suportservice.service;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointcost.rfc7285.rev151021.TypedAddressData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.host.tracker.rev140624.HostNode;
+
+public interface NetworkHostNodeService {
+    public void addHostNode(HostNode node);
+
+    public void deleteHostNode(HostNode node);
+
+    public HostNode getHostNodeByHostIP(TypedAddressData ip);
+
+    public HostNode getHostNodeByHostId(String hostId);
+
+    public boolean isValidHost(TypedAddressData ip);
+}
diff --git a/alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/suportservice/service/NetworkPortStatisticsService.java b/alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/suportservice/service/NetworkPortStatisticsService.java
new file mode 100644 (file)
index 0000000..cd9f855
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * Copyright © 2015 Yale 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.basic.endpointcostservice.suportservice.service;
+
+public interface NetworkPortStatisticsService {
+
+    Long getCurrentTxSpeed(String tpId, Metric metric);
+
+    Long getCurrentRxSpeed(String tpId, Metric metric);
+
+    enum Metric {BITSPERSECOND, BYTESPERSECOND};
+}
diff --git a/alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/suportservice/service/RoutingService.java b/alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/suportservice/service/RoutingService.java
new file mode 100644 (file)
index 0000000..57d0261
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * Copyright © 2015 Yale 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.basic.endpointcostservice.suportservice.service;
+
+import org.opendaylight.alto.basic.endpointcostservice.util.LinkNode;
+import org.opendaylight.alto.basic.endpointcostservice.flow.MatchFields;
+
+public interface RoutingService {
+    /**
+     * Find route path in RFM by match fields.
+     * @param matchFields
+     * @return the actual routing path.
+     */
+    public LinkNode buildRoutePath(MatchFields matchFields);
+}
diff --git a/alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/util/InstanceIdentifierUtils.java b/alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/util/InstanceIdentifierUtils.java
new file mode 100644 (file)
index 0000000..d99498a
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * Copyright © 2015 Yale 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.basic.endpointcostservice.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();
+    }
+
+    public static InstanceIdentifier<FlowCapableNodeConnectorStatisticsData>
+    flowCapableNodeConnectorStatisticsData(String nodeConnectorId) {
+        String nodeId = NameConverter.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(FlowCapableNodeConnectorStatisticsData.class)
+                .build();
+    }
+
+
+    /**
+     * @param nodeConnectorId
+     * @return iid of {@link FlowCapableNodeConnector}.
+     */
+    public static InstanceIdentifier<FlowCapableNodeConnector> flowCapableNodeConnector(String nodeConnectorId) {
+        String nodeId = NameConverter.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();
+    }
+
+    /**
+     * @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();
+    }
+}
diff --git a/alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/util/LinkNode.java b/alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/util/LinkNode.java
new file mode 100644 (file)
index 0000000..c69047a
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * Copyright © 2015 Yale 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.basic.endpointcostservice.util;
+
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Link;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class LinkNode {
+    private Link link;
+    private boolean isDestHost = false;
+    private Long bandwidth;
+    private List<LinkNode> children = new ArrayList<LinkNode>();
+
+    public LinkNode(Link link) {
+        this.link = link;
+    }
+
+    public LinkNode(Link link, LinkNode child) {
+        this(link);
+        this.children.add(child);
+    }
+
+    public LinkNode(String inPort, Link link, List<LinkNode> children) {
+        this(link);
+        this.children.addAll(children);
+    }
+
+    public String id() {
+        return this.link.getLinkId().getValue();
+    }
+
+    public String srcTpId() {
+        return this.link.getSource().getSourceTp().getValue();
+    }
+
+    public String dstTpId() {
+        return this.link.getDestination().getDestTp().getValue();
+    }
+
+    public String srcNodeId() {
+        return this.link.getSource().getSourceNode().getValue();
+    }
+
+    public String dstNodeId() {
+        return this.link.getDestination().getDestNode().getValue();
+    }
+
+    public boolean startWithHost() {
+        return this.srcTpId().toLowerCase().startsWith("host:");
+    }
+
+    public boolean endWithHost() {
+        return this.dstTpId().toLowerCase().startsWith("host:");
+    }
+
+    public boolean isDestHost() {
+        return this.isDestHost;
+    }
+
+    public List<LinkNode> children() {
+        return this.children;
+    }
+
+    public void addChild(LinkNode child) {
+        this.children.add(child);
+    }
+
+    public void addChildren(List<LinkNode> children) {
+        this.children.addAll(children);
+    }
+
+    public void setAsDestHost() {
+        this.isDestHost = true;
+    }
+
+    public Long availableBandwidth() {
+        return this.bandwidth;
+    }
+
+    public void setAvailableBandwidth(Long bandwidth) {
+        this.bandwidth = bandwidth;
+    }
+
+    public Link getLink(){return this.link;}
+}
diff --git a/alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/util/NameConverter.java b/alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/util/NameConverter.java
new file mode 100644 (file)
index 0000000..042179e
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright © 2015 Yale 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.basic.endpointcostservice.util;
+
+public class NameConverter {
+    /**
+     * @param nodeConnectorId
+     * @return node id of nodeConnectorId.
+     */
+    public static String extractNodeId(String nodeConnectorId) {
+        return nodeConnectorId.replaceAll(":[0-9]+$", "");
+    }
+
+    /**
+     * @param switchId
+     * @param outputNodeConnector
+     * @return node connector id with switch id and node connector.
+     */
+    public static String buildNodeConnectorId(String switchId,
+                                              String outputNodeConnector) {
+        return switchId + ":" + outputNodeConnector;
+    }
+}
diff --git a/alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/util/NetworkServiceConstants.java b/alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/util/NetworkServiceConstants.java
new file mode 100644 (file)
index 0000000..bf0aefe
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright © 2015 Yale 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.basic.endpointcostservice.util;
+
+import com.google.common.collect.ImmutableMap;
+
+import java.util.Map;
+
+public class NetworkServiceConstants {
+    public static final String TEN_MB_HD = "ten-mb-hd";
+    public static final String TEN_MB_FD = "ten-mb-fd";
+    public static final String HUNDRED_MD_HD = "hundred-mb-hd";
+    public static final String HUNDRED_MD_FD = "hundred-mb-fd";
+    public static final String ONE_GB_HD = "one-gb-hd";
+    public static final String ONE_MD_FD = "one-gb-fd";
+    public static final String TEN_GB_FD = "ten-gb-fd";
+    public static final String FORTY_GB_FD = "forty-gb-fd";
+    public static final String HUNDRED_GB_FD = "hundred-gb-fd";
+    public static final String ONE_TB_FD = "one-tb-fd";
+    public static final String OTHER = "other";
+    public static final String COPPER = "copper";
+    public static final String FIBER = "fiber";
+    public static final String AUTOENG = "autoeng";
+    public static final String PAUSE = "pause";
+    public static final String PAUSE_ASYM = "pause-asym";
+
+    public static final Map<String, Integer> PORT_FEATURES = ImmutableMap.<String, Integer>builder()
+            .put(TEN_MB_HD, 0)
+            .put(TEN_MB_FD, 1)
+            .put(HUNDRED_MD_HD, 2)
+            .put(HUNDRED_MD_FD, 3)
+            .put(ONE_GB_HD, 4)
+            .put(ONE_MD_FD, 5)
+            .put(TEN_GB_FD, 6)
+            .put(FORTY_GB_FD, 7)
+            .put(HUNDRED_GB_FD, 8)
+            .put(ONE_TB_FD, 9)
+            .put(OTHER, 10)
+            .put(COPPER, 11)
+            .put(FIBER, 12)
+            .put(AUTOENG, 13)
+            .put(PAUSE, 14)
+            .put(PAUSE_ASYM, 15)
+            .build();
+}
diff --git a/alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/util/RouteServiceConstants.java b/alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/alto/basic/endpointcostservice/util/RouteServiceConstants.java
new file mode 100644 (file)
index 0000000..e612bae
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright © 2015 Yale 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.basic.endpointcostservice.util;
+
+public class RouteServiceConstants {
+    public static class IP_PROTOCOL {
+        public static short ICMP4 = 1;
+        public static short ICMP6 = 58;
+        public static short TCP4 = 6;
+        public static short TCP6 = 6;
+        public static short UDP4 = 17;
+        public static short UDP6 = 17;
+        public static short SCTP4 = 132;
+        public static short SCTP6 = 132;
+    }
+
+    public static class ETHERNET_TYPE {
+        public static Long IPV4 = (long) 0x0800;
+        public static Long IPV6 = (long) 0x86dd;
+        public static Long LLDP = (long) 0x88cc;
+        public static Long ARP = (long) 0x0806;
+        public static Long RARP = (long) 0x8035;
+    }
+}
diff --git a/alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/endpointcostservice/impl/rev141210/EndpointcostserviceModule.java b/alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/endpointcostservice/impl/rev141210/EndpointcostserviceModule.java
new file mode 100644 (file)
index 0000000..c7fc008
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright © 2015 Yale 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.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.endpointcostservice.impl.rev141210;
+
+import org.opendaylight.alto.basic.endpointcostservice.impl.EndpointcostserviceProvider;
+
+
+public class EndpointcostserviceModule extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.endpointcostservice.impl.rev141210.AbstractEndpointcostserviceModule {
+    public EndpointcostserviceModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+        super(identifier, dependencyResolver);
+    }
+
+    public EndpointcostserviceModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.endpointcostservice.impl.rev141210.EndpointcostserviceModule 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() {
+        final EndpointcostserviceProvider provider = new EndpointcostserviceProvider();
+        try {
+            getBrokerDependency().registerProvider(provider);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+        return provider;
+    }
+
+}
diff --git a/alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/endpointcostservice/impl/rev141210/EndpointcostserviceModuleFactory.java b/alto-basic/endpointcostservice/impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/endpointcostservice/impl/rev141210/EndpointcostserviceModuleFactory.java
new file mode 100644 (file)
index 0000000..0c3e47c
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * Copyright © 2015 Yale 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
+ */
+/*
+* Generated file
+*
+* Generated from: yang module name: endpointcostservice yang module local name: endpointcostservice
+* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+* Generated at: Fri Jan 02 13:49:24 CST 2015
+*
+* Do not modify this file unless it is present under src/main directory
+*/
+package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.endpointcostservice.impl.rev141210;
+public class EndpointcostserviceModuleFactory extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.endpointcostservice.impl.rev141210.AbstractEndpointcostserviceModuleFactory {
+
+}
diff --git a/alto-basic/endpointcostservice/impl/src/main/yang/endpointcostservice-impl.yang b/alto-basic/endpointcostservice/impl/src/main/yang/endpointcostservice-impl.yang
new file mode 100644 (file)
index 0000000..040efe5
--- /dev/null
@@ -0,0 +1,35 @@
+module endpointcostservice-impl {
+    yang-version 1;
+    namespace "urn:opendaylight:params:xml:ns:yang:endpointcostservice:impl";
+    prefix "endpointcostservice-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 endpointcostservice project";
+
+    revision "2014-12-10" {
+        description
+            "Initial revision";
+    }
+
+    identity endpointcostservice {
+        base config:module-type;
+        config:java-name-prefix Endpointcostservice;
+    }
+
+    augment "/config:modules/config:module/config:configuration" {
+        case endpointcostservice {
+            when "/config:modules/config:module/config:type = 'endpointcostservice'";
+            container broker {
+                uses config:service-ref {
+                    refine type {
+                        mandatory true;
+                        config:required-identity md-sal-binding:binding-broker-osgi-registry;
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/alto-basic/endpointcostservice/impl/src/test/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/endpointcostservice/impl/rev141210/EndpointcostserviceModuleFactoryTest.java b/alto-basic/endpointcostservice/impl/src/test/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/endpointcostservice/impl/rev141210/EndpointcostserviceModuleFactoryTest.java
new file mode 100644 (file)
index 0000000..7f808fd
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * Copyright © 2015 Yale 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.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.endpointcostservice.impl.rev141210;
+
+import org.junit.Test;
+
+public class EndpointcostserviceModuleFactoryTest {
+    @Test
+    public void testFactoryConstructor() {
+        // ensure no exceptions on construction
+        new EndpointcostserviceModuleFactory();
+    }
+}
diff --git a/alto-basic/endpointcostservice/impl/src/test/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/endpointcostservice/impl/rev141210/EndpointcostserviceModuleTest.java b/alto-basic/endpointcostservice/impl/src/test/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/endpointcostservice/impl/rev141210/EndpointcostserviceModuleTest.java
new file mode 100644 (file)
index 0000000..b906c15
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright © 2015 Yale 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.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.endpointcostservice.impl.rev141210;
+
+import org.junit.Test;
+import org.opendaylight.controller.config.api.DependencyResolver;
+import org.opendaylight.controller.config.api.JmxAttribute;
+import org.opendaylight.controller.config.api.ModuleIdentifier;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
+import org.opendaylight.alto.basic.endpointcostservice.impl.EndpointcostserviceProvider;
+
+import javax.management.ObjectName;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+public class EndpointcostserviceModuleTest {
+    @Test
+    public void testCustomValidation() {
+        EndpointcostserviceModule module = new EndpointcostserviceModule(mock(ModuleIdentifier.class), mock(DependencyResolver.class));
+
+        // ensure no exceptions on validation
+        // currently this method is empty
+        module.customValidation();
+    }
+
+    @Test
+    public void testCreateInstance() throws Exception {
+        // configure mocks
+        DependencyResolver dependencyResolver = mock(DependencyResolver.class);
+        BindingAwareBroker broker = mock(BindingAwareBroker.class);
+        when(dependencyResolver.resolveInstance(eq(BindingAwareBroker.class), any(ObjectName.class), any(JmxAttribute.class))).thenReturn(broker);
+
+        // create instance of module with injected mocks
+        EndpointcostserviceModule module = new EndpointcostserviceModule(mock(ModuleIdentifier.class), dependencyResolver);
+
+        // getInstance calls resolveInstance to get the broker dependency and then calls createInstance
+        AutoCloseable closeable = module.getInstance();
+
+        // verify that the module registered the returned provider with the broker
+        verify(broker).registerProvider((EndpointcostserviceProvider)closeable);
+
+        // ensure no exceptions on close
+        closeable.close();
+    }
+}
diff --git a/alto-basic/endpointcostservice/it/pom.xml b/alto-basic/endpointcostservice/it/pom.xml
new file mode 100644 (file)
index 0000000..0da61b7
--- /dev/null
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright © 2015 Yale 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
+-->
+
+<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>mdsal-it-parent</artifactId>
+    <version>1.3.0-SNAPSHOT</version>
+    <relativePath/>
+  </parent>
+
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.opendaylight.alto.basic</groupId>
+  <artifactId>endpointcostservice-it</artifactId>
+  <version>0.2.0-SNAPSHOT</version>
+  <packaging>bundle</packaging>
+
+  <properties>
+    <skipITs>false</skipITs>
+    <karaf.distro.groupId>org.opendaylight.alto.basic</karaf.distro.groupId>
+    <karaf.distro.artifactId>endpointcostservice-karaf</karaf.distro.artifactId>
+    <karaf.distro.version>0.2.0-SNAPSHOT</karaf.distro.version>
+    <karaf.distro.type>zip</karaf.distro.type>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>endpointcostservice-features</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+  </dependencies>
+
+</project>
diff --git a/alto-basic/endpointcostservice/it/src/test/java/org/opendaylight/alto/basic/endpointcostservice/it/EndpointcostserviceIT.java b/alto-basic/endpointcostservice/it/src/test/java/org/opendaylight/alto/basic/endpointcostservice/it/EndpointcostserviceIT.java
new file mode 100644 (file)
index 0000000..4fd3355
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright © 2015 Yale 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.basic.endpointcostservice.it;
+
+import static org.ops4j.pax.exam.CoreOptions.composite;
+import static org.ops4j.pax.exam.CoreOptions.maven;
+import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.editConfigurationFilePut;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.opendaylight.controller.mdsal.it.base.AbstractMdsalTestBase;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.PaxExam;
+import org.ops4j.pax.exam.karaf.options.LogLevelOption.LogLevel;
+import org.ops4j.pax.exam.options.MavenUrlReference;
+import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
+import org.ops4j.pax.exam.spi.reactors.PerClass;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@RunWith(PaxExam.class)
+@ExamReactorStrategy(PerClass.class)
+public class EndpointcostserviceIT extends AbstractMdsalTestBase {
+    private static final Logger LOG = LoggerFactory.getLogger(EndpointcostserviceIT.class);
+
+    @Override
+    public String getModuleName() {
+        return "endpointcostservice";
+    }
+
+    @Override
+    public String getInstanceName() {
+        return "endpointcostservice-default";
+    }
+
+    @Override
+    public MavenUrlReference getFeatureRepo() {
+        return maven()
+                .groupId("org.opendaylight.alto.basic")
+                .artifactId("endpointcostservice-features")
+                .classifier("features")
+                .type("xml")
+                .versionAsInProject();
+    }
+
+    @Override
+    public String getFeatureName() {
+        return "odl-endpointcostservice-ui";
+    }
+
+    @Override
+    public Option getLoggingOption() {
+        Option option = editConfigurationFilePut(ORG_OPS4J_PAX_LOGGING_CFG,
+                logConfiguration(EndpointcostserviceIT.class),
+                LogLevel.INFO.name());
+        option = composite(option, super.getLoggingOption());
+        return option;
+    }
+
+    @Test
+    public void testendpointcostserviceFeatureLoad() {
+        Assert.assertTrue(true);
+    }
+}
diff --git a/alto-basic/endpointcostservice/karaf/pom.xml b/alto-basic/endpointcostservice/karaf/pom.xml
new file mode 100644 (file)
index 0000000..97de8f9
--- /dev/null
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright © 2015 Yale 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 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.6.0-SNAPSHOT</version>
+    <relativePath/>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.opendaylight.alto.basic</groupId>
+  <artifactId>endpointcostservice-karaf</artifactId>
+  <version>0.2.0-SNAPSHOT</version>
+  <name>${project.artifactId}</name>
+  <prerequisites>
+    <maven>3.1.1</maven>
+  </prerequisites>
+  <properties>
+    <karaf.localFeature>odl-endpointcostservice-ui</karaf.localFeature>
+  </properties>
+  <dependencyManagement>
+    <dependencies>
+      <dependency>
+        <groupId>${project.groupId}</groupId>
+        <artifactId>endpointcostservice-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>endpointcostservice-features</artifactId>
+      <classifier>features</classifier>
+      <type>xml</type>
+      <scope>runtime</scope>
+    </dependency>
+  </dependencies>
+  <!-- DO NOT install or deploy the karaf artifact -->
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-deploy-plugin</artifactId>
+        <configuration>
+          <skip>true</skip>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+</project>
diff --git a/alto-basic/endpointcostservice/pom.xml b/alto-basic/endpointcostservice/pom.xml
new file mode 100644 (file)
index 0000000..15e1570
--- /dev/null
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright © 2015 Yale 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 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.6.0-SNAPSHOT</version>
+  </parent>
+
+  <groupId>org.opendaylight.alto.basic.endpointcostservice</groupId>
+  <artifactId>endpointcostservice-aggregator</artifactId>
+  <version>0.2.0-SNAPSHOT</version>
+  <name>endpointcostservice</name>
+  <packaging>pom</packaging>
+  <modelVersion>4.0.0</modelVersion>
+  <prerequisites>
+    <maven>3.1.1</maven>
+  </prerequisites>
+  <profiles>
+    <profile>
+      <id>minimal</id>
+      <activation>
+        <activeByDefault>true</activeByDefault>
+      </activation>
+      <modules>
+        <module>api</module>
+        <module>impl</module>
+      </modules>
+    </profile>
+
+    <profile>
+      <id>alto-dev</id>
+      <modules>
+        <module>api</module>
+        <module>impl</module>
+        <module>features</module>
+        <module>artifacts</module>
+      </modules>
+    </profile>
+
+    <profile>
+      <id>alto-test</id>
+      <modules>
+        <module>api</module>
+        <module>impl</module>
+        <module>features</module>
+        <module>artifacts</module>
+        <module>karaf</module>
+        <module>it</module>
+      </modules>
+    </profile>
+  </profiles>
+  <!-- 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/endpointcostservice.git</connection>
+    <developerConnection>scm:git:ssh://git.opendaylight.org:29418/endpointcostservice.git</developerConnection>
+    <tag>HEAD</tag>
+    <url>https://wiki.opendaylight.org/view/endpointcostservice:Main</url>
+  </scm>
+</project>
index fb174aa5c15d61cc276893f1c76649445d634417..4193d2ffbaca71521cf59a590e8f13394854b313 100644 (file)
@@ -24,6 +24,7 @@ and is available at http://www.eclipse.org/legal/epl-v10.html INTERNAL
   </prerequisites>
   <modules>
     <module>simple-ird</module>
+    <module>endpointcostservice</module>
   </modules>
   <!-- DO NOT install or deploy the repo root pom as it's only needed to initiate a build -->
   <build>