--- /dev/null
+<?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>
--- /dev/null
+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";
+ }
+}
--- /dev/null
+<?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>
--- /dev/null
+<?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>
--- /dev/null
+<?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>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <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
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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());
+ }
+ }
+ }
+ });
+ }
+
+}
--- /dev/null
+<?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>
--- /dev/null
+<?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&revision=2014-12-10</capability>
+ <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding?module=opendaylight-md-sal-binding&revision=2013-10-28</capability>
+ </required-capabilities>
+ <configuration>
+
+ <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+ <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+ <module>
+ <type xmlns:prefix="urn:opendaylight: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>
--- /dev/null
+<?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>
--- /dev/null
+/*
+ * 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);
+ }
+}
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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;
+ }
+}
--- /dev/null
+/*
+ * 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();
+ }
+}
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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;
+ }
+}
--- /dev/null
+/*
+ * 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;
+ }
+}
--- /dev/null
+/*
+ * 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));
+ }
+
+}
--- /dev/null
+/*
+ * 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);
+ }
+
+}
--- /dev/null
+/*
+ * 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();
+ }
+}
--- /dev/null
+/*
+ * 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);
+ }
+}
--- /dev/null
+/*
+ * 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());
+ }
+ }
+ }
+ });
+ }
+}
--- /dev/null
+/*
+ * 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;
+ }
+}
--- /dev/null
+/*
+ * 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);
+ }
+}
--- /dev/null
+/*
+ * 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;
+ }
+}
--- /dev/null
+/*
+ * 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;
+ }
+}
--- /dev/null
+/*
+ * 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;
+ }
+}
--- /dev/null
+/*
+ * 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);
+ }
+}
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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();
+}
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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};
+}
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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();
+ }
+}
--- /dev/null
+/*
+ * 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;}
+}
--- /dev/null
+/*
+ * 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;
+ }
+}
--- /dev/null
+/*
+ * 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();
+}
--- /dev/null
+/*
+ * 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;
+ }
+}
--- /dev/null
+/*
+ * 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;
+ }
+
+}
--- /dev/null
+/*
+ * 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 {
+
+}
--- /dev/null
+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;
+ }
+ }
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ * 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();
+ }
+}
--- /dev/null
+/*
+ * 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();
+ }
+}
--- /dev/null
+<?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>
--- /dev/null
+/*
+ * 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);
+ }
+}
--- /dev/null
+<?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>
--- /dev/null
+<?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>
</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>