ONOS-4489 - Initial ICONA provider development
- Southbound APIs definition
- Stubs of implementation classes
Change-Id: I5a9b76510ea8d6b43fa615c94db191439555ddc2
diff --git a/icona/app/app.xml b/icona/app/app.xml
new file mode 100644
index 0000000..8fb0322
--- /dev/null
+++ b/icona/app/app.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ ~ Copyright 2016-present Open Networking Laboratory
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<app name="org.onosproject.icona" origin="ON.Lab" version="${project.version}"
+ category="Utility" url="http://onosproject.org" title="Inter-Cluster ONOS Application"
+ featuresRepo="mvn:${project.groupId}/${project.artifactId}/${project.version}/xml/features"
+ features="${project.artifactId}">
+ <description>${project.description}</description>
+ <artifact>mvn:${project.groupId}/onos-app-icona-domain-manager/${project.version}</artifact>
+ <artifact>mvn:${project.groupId}/onos-app-icona-domain-provider/${project.version}</artifact>
+</app>
diff --git a/icona/app/features.xml b/icona/app/features.xml
new file mode 100644
index 0000000..74fa9c8
--- /dev/null
+++ b/icona/app/features.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+
+<!--
+ ~ Copyright 2016-present Open Networking Laboratory
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<features xmlns="http://karaf.apache.org/xmlns/features/v1.2.0" name="${project.artifactId}-${project.version}">
+ <feature name="${project.artifactId}" version="${project.version}"
+ description="${project.description}">
+ <feature>onos-api</feature>
+ <bundle>mvn:${project.groupId}/onos-app-icona-domain-manager/${project.version}</bundle>
+ <bundle>mvn:${project.groupId}/onos-app-icona-domain-provider/${project.version}</bundle>
+ </feature>
+</features>
\ No newline at end of file
diff --git a/icona/app/pom.xml b/icona/app/pom.xml
new file mode 100644
index 0000000..63611ed
--- /dev/null
+++ b/icona/app/pom.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright 2016-present Open Networking Laboratory
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-icona</artifactId>
+ <version>1.7.0-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>onos-app-icona</artifactId>
+ <packaging>pom</packaging>
+
+ <description>Inter-Cluster ONOS App</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-app-icona-domain-manager</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-app-icona-domain-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/icona/domainmgr/pom.xml b/icona/domainmgr/pom.xml
new file mode 100644
index 0000000..29e3f3c
--- /dev/null
+++ b/icona/domainmgr/pom.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright 2016-present Open Networking Laboratory
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-icona</artifactId>
+ <version>1.7.0-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>onos-app-icona-domain-manager</artifactId>
+ <packaging>bundle</packaging>
+
+
+ <description>Inter Cluster Onos Network App</description>
+
+ <properties>
+ <onos.app.name>org.onosproject.icona.domainmgr</onos.app.name>
+ </properties>
+
+
+ <dependencies>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.compendium</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-api</artifactId>
+ <version>${onos.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-core-serializers</artifactId>
+ <version>${onos.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onlab-osgi</artifactId>
+ <version>${onos.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onlab-misc</artifactId>
+ <version>${onos.version}</version>
+ </dependency>
+
+ </dependencies>
+</project>
diff --git a/icona/domainmgr/src/main/java/org/onosproject/icona/domainmgr/api/DomainEvent.java b/icona/domainmgr/src/main/java/org/onosproject/icona/domainmgr/api/DomainEvent.java
new file mode 100644
index 0000000..0ac8358
--- /dev/null
+++ b/icona/domainmgr/src/main/java/org/onosproject/icona/domainmgr/api/DomainEvent.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.icona.domainmgr.api;
+
+import org.onosproject.event.AbstractEvent;
+
+/**
+ * Domain event class. The event notifies the presence of a new domain or its disappearance.
+ * Apps can listen for such events and then retrieve the domain topologies through {@link DomainService}
+ */
+public class DomainEvent extends AbstractEvent<DomainEvent.Type, DomainId> {
+
+ /**
+ * Domain event type.
+ */
+ public enum Type {
+
+ /**
+ * Indicates that a new domain ID has been added to the distributed store.
+ */
+ DOMAIN_ADDED,
+
+ /**
+ * Indicates that a domain ID has been removed from the store.
+ */
+ DOMAIN_REMOVED
+
+ // TODO: other state-related event types
+ }
+
+ public DomainEvent(DomainEvent.Type type, DomainId domainId) {
+ super(type, domainId);
+ }
+}
diff --git a/icona/domainmgr/src/main/java/org/onosproject/icona/domainmgr/api/DomainId.java b/icona/domainmgr/src/main/java/org/onosproject/icona/domainmgr/api/DomainId.java
new file mode 100644
index 0000000..e031952
--- /dev/null
+++ b/icona/domainmgr/src/main/java/org/onosproject/icona/domainmgr/api/DomainId.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.icona.domainmgr.api;
+
+import org.onlab.util.Identifier;
+
+/**
+ * Representation of a peer domain.
+ */
+public class DomainId extends Identifier<String> {
+
+ /**
+ * Constructor of the peer id.
+ *
+ * @param identifier of the peer
+ */
+ public DomainId(String identifier) {
+ super(identifier);
+ }
+
+ /**
+ * Creates a peer id from the string identifier.
+ *
+ * @param identifier string identifier
+ * @return instance of the class DomainId
+ */
+ public static DomainId domainId(String identifier) {
+ return new DomainId(identifier);
+ }
+}
\ No newline at end of file
diff --git a/icona/domainmgr/src/main/java/org/onosproject/icona/domainmgr/api/DomainListener.java b/icona/domainmgr/src/main/java/org/onosproject/icona/domainmgr/api/DomainListener.java
new file mode 100644
index 0000000..6094ff8
--- /dev/null
+++ b/icona/domainmgr/src/main/java/org/onosproject/icona/domainmgr/api/DomainListener.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.icona.domainmgr.api;
+
+import org.onosproject.event.EventListener;
+
+/**
+ * Listeners for domain events. Currently we handle the addition and remotion of a domain.
+ * Domain topology elements events can be sensed through existing Device, Host, Link listener
+ */
+public interface DomainListener extends EventListener<DomainEvent> {
+}
diff --git a/icona/domainmgr/src/main/java/org/onosproject/icona/domainmgr/api/DomainService.java b/icona/domainmgr/src/main/java/org/onosproject/icona/domainmgr/api/DomainService.java
new file mode 100644
index 0000000..4ccaf6a
--- /dev/null
+++ b/icona/domainmgr/src/main/java/org/onosproject/icona/domainmgr/api/DomainService.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.icona.domainmgr.api;
+
+import org.apache.commons.lang3.tuple.Pair;
+import org.onosproject.net.Device;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Host;
+import org.onosproject.net.HostId;
+import org.onosproject.net.Link;
+
+import java.util.Set;
+
+/**
+ * Service to access domain topology elements.
+ */
+public interface DomainService {
+
+ /**
+ * Adds a new domain id to the store.
+ * @param domainId domain identifier
+ */
+ void registerDomainId(DomainId domainId);
+
+ /**
+ * Removes the specified domain id from the store.
+ * @param domainId domain identifier
+ */
+ void unregisterDomainId(DomainId domainId);
+
+ /**
+ * Returns the set of domains that have an associated topology.
+ *
+ * @return set of domain identifiers
+ */
+ Set<DomainId> getDomainIds();
+
+ /**
+ * Returns the set of the devices of the specified domain.
+ *
+ * @param domainId domain identifier
+ * @return set of device objects
+ */
+ Set<DeviceId> getDeviceIds(DomainId domainId);
+
+ /**
+ * Gets all the devices of the specified domain.
+ * @param domainId domain identifier.
+ * @return set of devices
+ */
+ Set<Device> getDevices(DomainId domainId);
+
+ /**
+ * Returns the set of hosts of the specified domain.
+ * @param domainId domain id
+ * @return set of host objects
+ */
+ Set<HostId> getHostIds(DomainId domainId);
+
+ /**
+ * Gets the hosts of the specified domain.
+ * @param domainId domain id
+ * @return set of host objects
+ */
+ Set<Host> getHosts(DomainId domainId);
+
+ /**
+ * Gets the list of interlinks between the specified domains.
+ * @return set of interlinks
+ */
+ Set<Link> getInterLinks(Pair<DomainId, DomainId> endDomains);
+
+ /**
+ * Gets the list of links within a domain.
+ * @param domainId domain id
+ * @return set of intra-domain link
+ */
+ Set<Link> getIntraLinks(DomainId domainId);
+}
diff --git a/icona/domainmgr/src/main/java/org/onosproject/icona/domainmgr/api/DomainStore.java b/icona/domainmgr/src/main/java/org/onosproject/icona/domainmgr/api/DomainStore.java
new file mode 100644
index 0000000..4501731
--- /dev/null
+++ b/icona/domainmgr/src/main/java/org/onosproject/icona/domainmgr/api/DomainStore.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.icona.domainmgr.api;
+
+import org.apache.commons.lang3.tuple.Pair;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.HostId;
+import org.onosproject.net.Link;
+import org.onosproject.store.Store;
+
+import java.util.Set;
+
+/**
+ * Domain store interface.
+ */
+public interface DomainStore extends Store<DomainEvent, DomainStoreDelegate> {
+
+ /**
+ * Returns the set of domains that have an associated topology.
+ * @return set of domain identifiers
+ */
+ Set<DomainId> getDomainIds();
+
+ /**
+ * Returns the set of the devices of the specified domain.
+ * @param domainId domain identifier
+ * @return set of device objects
+ */
+ Set<DeviceId> getDeviceIds(DomainId domainId);
+
+ //TODO: get the topology of the topologies of all domain
+
+ /**
+ * Adds a new domain ID to the store.
+ * @param domainId domain id
+ */
+ void addDomain(DomainId domainId);
+
+ /**
+ * Removes the specified domain ID from the store.
+ * @param domainId domain identifier
+ */
+ void removeDomain(DomainId domainId);
+
+ /**
+ * Adds a new device to the store.
+ * @param domainId domain ientifier
+ * @param deviceId device identifier
+ */
+ void addDevice(DomainId domainId, DeviceId deviceId);
+
+ /**
+ * Removes a device from the store.
+ * @param domainId domain identifier
+ * @param deviceId device identifier
+ */
+ void removeDevice(DomainId domainId, DeviceId deviceId);
+
+ /**
+ * Gets the set of host identifiers of the specified domain.
+ * @param domainId domain identifier
+ * @return set of host identifiers
+ */
+ Set<HostId> getHostIds(DomainId domainId);
+
+ /**
+ * Adds a host to the domain store.
+ * @param domainId domain identifier
+ * @param hostId host identifier
+ */
+ void addHost(DomainId domainId, HostId hostId);
+
+ /**
+ * Removes a host from a domain.
+ * @param domainId domain identifier
+ * @param hostId host identifier
+ */
+ void removeHost(DomainId domainId, HostId hostId);
+
+ /**
+ * Gets the set of interlinks having source port within the specified domains.
+ * @param endDomains end domains identifier
+ * @return set of links
+ */
+ Set<Link> getInterLinks(Pair<DomainId, DomainId> endDomains);
+
+ /**
+ * Adds an interlink to the store. Link source port is within the specified domain.
+ * @param endDomains end domains identifier
+ * @param link link object
+ */
+ void addOrUpdateInterLink(Pair<DomainId, DomainId> endDomains, Link link);
+
+ /**
+ * Removes an interlink from the store.
+ * @param endDomains end domain identifiers
+ * @param link link object
+ */
+ void removeInterLink(Pair<DomainId, DomainId> endDomains, Link link);
+}
diff --git a/icona/domainmgr/src/main/java/org/onosproject/icona/domainmgr/api/DomainStoreDelegate.java b/icona/domainmgr/src/main/java/org/onosproject/icona/domainmgr/api/DomainStoreDelegate.java
new file mode 100644
index 0000000..edb7d9a
--- /dev/null
+++ b/icona/domainmgr/src/main/java/org/onosproject/icona/domainmgr/api/DomainStoreDelegate.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.icona.domainmgr.api;
+
+
+import org.onosproject.store.StoreDelegate;
+
+/**
+ * Domain store delegate.
+ */
+public interface DomainStoreDelegate extends StoreDelegate<DomainEvent> {
+
+}
diff --git a/icona/domainmgr/src/main/java/org/onosproject/icona/domainmgr/api/package-info.java b/icona/domainmgr/src/main/java/org/onosproject/icona/domainmgr/api/package-info.java
new file mode 100644
index 0000000..32e1199
--- /dev/null
+++ b/icona/domainmgr/src/main/java/org/onosproject/icona/domainmgr/api/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Icona manager APIs.
+ */
+package org.onosproject.icona.domainmgr.api;
\ No newline at end of file
diff --git a/icona/domainmgr/src/main/java/org/onosproject/icona/domainmgr/impl/DistributedDomainStore.java b/icona/domainmgr/src/main/java/org/onosproject/icona/domainmgr/impl/DistributedDomainStore.java
new file mode 100644
index 0000000..4c28802
--- /dev/null
+++ b/icona/domainmgr/src/main/java/org/onosproject/icona/domainmgr/impl/DistributedDomainStore.java
@@ -0,0 +1,280 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.icona.domainmgr.impl;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Sets;
+import org.apache.commons.lang3.tuple.Pair;
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.onlab.util.Identifier;
+import org.onlab.util.KryoNamespace;
+import org.onosproject.icona.domainmgr.api.DomainId;
+import org.onosproject.icona.domainmgr.api.DomainEvent;
+import org.onosproject.icona.domainmgr.api.DomainStore;
+import org.onosproject.icona.domainmgr.api.DomainStoreDelegate;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.HostId;
+import org.onosproject.net.Link;
+import org.onosproject.store.AbstractStore;
+import org.onosproject.store.serializers.KryoNamespaces;
+import org.onosproject.store.service.StorageService;
+import org.onosproject.store.service.DistributedSet;
+import org.onosproject.store.service.ConsistentMap;
+import org.onosproject.store.service.SetEventListener;
+import org.onosproject.store.service.SetEvent;
+import org.onosproject.store.service.Serializer;
+
+import org.slf4j.Logger;
+
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import static org.onosproject.icona.domainmgr.api.DomainEvent.Type;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+
+import static org.onosproject.icona.domainmgr.api.DomainEvent.Type.DOMAIN_ADDED;
+import static org.onosproject.icona.domainmgr.api.DomainEvent.Type.DOMAIN_REMOVED;
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Distributed domain store implementation.
+ */
+public class DistributedDomainStore extends AbstractStore<DomainEvent, DomainStoreDelegate>
+ implements DomainStore {
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected StorageService storageService;
+
+ private final Logger log = getLogger(getClass());
+
+ private DistributedSet<DomainId> domainIds;
+ private final SetEventListener<DomainId> domainIdSetEventListener = new InternalMapListener();
+
+ private ConsistentMap<DomainId, Set<DeviceId>> domainIdDeviceIdsConsistentMap;
+ private Map<DomainId, Set<DeviceId>> domainIdDeviceIdsMap;
+
+ private ConsistentMap<DomainId, Set<HostId>> domainIdHostsIdsConsistentMap;
+ private Map<DomainId, Set<HostId>> domainIdHostIdsMap;
+
+ private ConsistentMap<Pair<DomainId, DomainId>, Set<Link>> domainIdLinkSetConsistentMap;
+ private Map<Pair<DomainId, DomainId>, Set<Link>> domainIdLinkSetMap;
+
+ private static final Serializer SERIALIZER = Serializer
+ .using(new KryoNamespace.Builder().register(KryoNamespaces.API)
+ .register(Identifier.class)
+ .register(DomainId.class)
+ .build());
+
+ @Activate
+ public void activate() {
+
+ domainIds = storageService.<DomainId>setBuilder()
+ .withSerializer(SERIALIZER)
+ .withName("onos-domainId")
+ .withRelaxedReadConsistency()
+ .build()
+ .asDistributedSet();
+ domainIds.addListener(domainIdSetEventListener);
+
+ domainIdDeviceIdsConsistentMap = storageService.<DomainId, Set<DeviceId>>consistentMapBuilder()
+ .withSerializer(SERIALIZER)
+ .withName("onos-domain-device-ids")
+ .withRelaxedReadConsistency()
+ .build();
+ domainIdDeviceIdsMap = domainIdDeviceIdsConsistentMap.asJavaMap();
+
+ domainIdHostsIdsConsistentMap = storageService.<DomainId, Set<HostId>>consistentMapBuilder()
+ .withSerializer(SERIALIZER)
+ .withName("onos-domain-host-ids")
+ .withRelaxedReadConsistency()
+ .build();
+ domainIdHostIdsMap = domainIdHostsIdsConsistentMap.asJavaMap();
+
+ domainIdLinkSetConsistentMap = storageService.<Pair<DomainId, DomainId>, Set<Link>>
+ consistentMapBuilder()
+ .withSerializer(SERIALIZER)
+ .withName("onos-domain-links")
+ .withRelaxedReadConsistency()
+ .build();
+ domainIdLinkSetMap = domainIdLinkSetConsistentMap.asJavaMap();
+
+ log.info("Started");
+
+ }
+
+ @Deactivate
+ public void deactivate() {
+ domainIds.removeListener(domainIdSetEventListener);
+ log.info("Stopped");
+
+ }
+
+ @Override
+ public Set<DomainId> getDomainIds() {
+ return ImmutableSet.copyOf(domainIds);
+ }
+
+ @Override
+ public Set<DeviceId> getDeviceIds(DomainId domainId) {
+ checkState(domainExists(domainId), "Domain id unknown");
+ return ImmutableSet.copyOf(domainIdDeviceIdsMap.get(domainId));
+ }
+
+ @Override
+ public void addDomain(DomainId domainId) {
+ domainIds.add(domainId);
+ }
+
+ @Override
+ public void removeDomain(DomainId domainId) {
+ domainIds.remove(domainId);
+ clear(domainId);
+ }
+
+ @Override
+ public void addDevice(DomainId domainId, DeviceId deviceId) {
+ checkState(domainExists(domainId), "Domain id unknown");
+ domainIdDeviceIdsMap.compute(domainId, (k, set) -> {
+ if (set == null) {
+ set = Sets.newConcurrentHashSet();
+ }
+ set.add(deviceId);
+ return set;
+ });
+ }
+
+ @Override
+ public void removeDevice(DomainId domainId, DeviceId deviceId) {
+ checkState(domainExists(domainId), "Domain id unknown");
+ domainIdDeviceIdsMap.computeIfPresent(domainId, (k, existingSet) -> {
+ if (existingSet.contains(deviceId)) {
+ existingSet.remove(deviceId);
+ return existingSet;
+ } else {
+ return existingSet;
+ }
+ });
+ }
+
+ @Override
+ public Set<HostId> getHostIds(DomainId domainId) {
+ checkState(domainExists(domainId), "Domain id unknown");
+ return ImmutableSet.copyOf(domainIdHostIdsMap.get(domainId));
+ }
+
+ @Override
+ public void addHost(DomainId domainId, HostId hostId) {
+ checkState(domainExists(domainId), "Domain id unknown");
+ domainIdHostIdsMap.compute(domainId, (k, set) -> {
+ if (set == null) {
+ set = Sets.newConcurrentHashSet();
+ }
+ set.add(hostId);
+ return set;
+ });
+ }
+
+ @Override
+ public void removeHost(DomainId domainId, HostId hostId) {
+ checkState(domainExists(domainId), "Domain id unknown");
+ domainIdHostIdsMap.computeIfPresent(domainId, (k, existingSet) -> {
+ if (existingSet.contains(hostId)) {
+ existingSet.remove(hostId);
+ return existingSet;
+ } else {
+ return existingSet;
+ }
+ });
+ }
+
+ @Override
+ public Set<Link> getInterLinks(Pair<DomainId, DomainId> endDomains) {
+ checkState(domainExists(endDomains.getLeft()), "Domain id unknown");
+ checkState(domainExists(endDomains.getRight()), "Domain id unknown");
+ return ImmutableSet.copyOf(domainIdLinkSetMap.get(endDomains));
+ }
+
+ @Override
+ public void addOrUpdateInterLink(Pair<DomainId, DomainId> endDomains, Link link) {
+ checkState(domainExists(endDomains.getLeft()), "Domain id unknown");
+ checkState(domainExists(endDomains.getRight()), "Domain id unknown");
+ domainIdLinkSetMap.compute(endDomains, (k, set) -> {
+ if (set == null) {
+ set = Sets.newConcurrentHashSet();
+ }
+ set.add(link);
+ return set;
+ });
+ }
+
+ @Override
+ public void removeInterLink(Pair<DomainId, DomainId> endDomains, Link link) {
+ checkState(domainExists(endDomains.getLeft()), "Domain id unknown");
+ checkState(domainExists(endDomains.getRight()), "Domain id unknown");
+ domainIdLinkSetMap.computeIfPresent(endDomains, (k, existingSet) -> {
+ if (existingSet.contains(link)) {
+ existingSet.remove(link);
+ return existingSet;
+ } else {
+ return existingSet;
+ }
+ });
+ }
+
+ private void clear(DomainId domainId) {
+ Set<Pair<DomainId, DomainId>> domainPairs = new HashSet<>();
+ // find all domains connected with the one to be removed and remove related links
+ domainIdLinkSetMap.keySet().forEach(endDomains -> {
+ if (endDomains.getLeft().equals(domainId) ||
+ endDomains.getRight().equals(domainId)) {
+ domainPairs.add(endDomains);
+ }
+ });
+ domainPairs.forEach(pair -> domainIdLinkSetMap.remove(pair));
+ domainIdDeviceIdsMap.remove(domainId);
+ domainIdHostIdsMap.remove(domainId);
+ }
+
+ private class InternalMapListener implements SetEventListener<DomainId> {
+ @Override
+ public void event(SetEvent<DomainId> event) {
+ Type type;
+ switch (event.type()) {
+ case ADD:
+ type = DOMAIN_ADDED;
+ break;
+ case REMOVE:
+ type = DOMAIN_REMOVED;
+ break;
+ default:
+ log.error("Unsupported event type: " + event.type());
+ return;
+ }
+ notifyDelegate(new DomainEvent(type, event.entry()));
+ }
+ }
+
+ private boolean domainExists(DomainId domainId) {
+ checkNotNull(domainId, "domain identifier is null");
+ return domainIds.contains(domainId);
+ }
+}
\ No newline at end of file
diff --git a/icona/domainmgr/src/main/java/org/onosproject/icona/domainmgr/impl/DomainManager.java b/icona/domainmgr/src/main/java/org/onosproject/icona/domainmgr/impl/DomainManager.java
new file mode 100644
index 0000000..e554f59
--- /dev/null
+++ b/icona/domainmgr/src/main/java/org/onosproject/icona/domainmgr/impl/DomainManager.java
@@ -0,0 +1,246 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.icona.domainmgr.impl;
+
+import com.google.common.collect.ImmutableSet;
+import org.apache.commons.lang3.tuple.Pair;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Service;
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.apache.felix.scr.annotations.Reference;
+import org.onosproject.event.AbstractListenerManager;
+import org.onosproject.icona.domainmgr.api.DomainEvent;
+import org.onosproject.icona.domainmgr.api.DomainListener;
+import org.onosproject.icona.domainmgr.api.DomainService;
+import org.onosproject.icona.domainmgr.api.DomainStore;
+import org.onosproject.icona.domainmgr.api.DomainStoreDelegate;
+import org.onosproject.icona.domainmgr.api.DomainId;
+import org.onosproject.net.HostId;
+import org.onosproject.net.Host;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Link;
+import org.onosproject.net.Device;
+import org.onosproject.net.device.DeviceEvent;
+import org.onosproject.net.device.DeviceListener;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.host.HostEvent;
+import org.onosproject.net.host.HostListener;
+import org.onosproject.net.host.HostService;
+import org.onosproject.net.link.LinkEvent;
+import org.onosproject.net.link.LinkListener;
+import org.onosproject.net.link.LinkService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Exposes domain topology elements and listen for updates of such elements.
+ */
+@Component(immediate = true)
+@Service
+public class DomainManager extends AbstractListenerManager<DomainEvent, DomainListener>
+ implements DomainService {
+
+ private final Logger log = LoggerFactory.getLogger(getClass());
+ private static final String DOMAIN_ID = "domainId";
+ private static final String SRC_DOMAIN_ID = "srcDomainId";
+ private static final String DST_DOMAIN_ID = "dstDomainId";
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected DomainStore domainStore;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected DeviceService deviceService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected HostService hostService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected LinkService linkService;
+
+ protected DomainStoreDelegate delegate = this::post;
+
+ private final DeviceListener deviceListener = new InternalDeviceListener();
+ private final HostListener hostListener = new InternalHostListener();
+ private final LinkListener linkListener = new InternalLinkListener();
+
+ @Activate
+ public void activate() {
+ deviceService.addListener(deviceListener);
+ hostService.addListener(hostListener);
+ linkService.addListener(linkListener);
+ domainStore.setDelegate(delegate);
+ log.info("Started");
+ }
+
+ @Deactivate
+ public void deactivate() {
+ deviceService.removeListener(deviceListener);
+ hostService.removeListener(hostListener);
+ linkService.removeListener(linkListener);
+ domainStore.unsetDelegate(delegate);
+ log.info("Stopped");
+ }
+
+ @Override
+ public void registerDomainId(DomainId domainId) {
+ checkNotNull(domainId);
+ domainStore.addDomain(domainId);
+ }
+
+ @Override
+ public void unregisterDomainId(DomainId domainId) {
+ checkNotNull(domainId);
+ domainStore.removeDomain(domainId);
+ }
+
+ @Override
+ public Set<DomainId> getDomainIds() {
+ return domainStore.getDomainIds();
+ }
+
+ @Override
+ public Set<DeviceId> getDeviceIds(DomainId domainId) {
+ return domainStore.getDeviceIds(domainId);
+ }
+
+ @Override
+ public Set<Device> getDevices(DomainId domainId) {
+ Set<DeviceId> deviceIds = domainStore.getDeviceIds(domainId);
+ Set<Device> devices = new HashSet<>();
+ deviceService.getDevices().forEach(device -> {
+ if (deviceIds.contains(device.id())) {
+ devices.add(device);
+ }
+ });
+ return ImmutableSet.copyOf(devices);
+ }
+
+ @Override
+ public Set<HostId> getHostIds(DomainId domainId) {
+ return domainStore.getHostIds(domainId);
+ }
+
+ @Override
+ public Set<Host> getHosts(DomainId domainId) {
+ Set<HostId> hostIds = domainStore.getHostIds(domainId);
+ Set<Host> hosts = new HashSet<>();
+ hostService.getHosts().forEach(host -> {
+ if (hostIds.contains(host.id())) {
+ hosts.add(host);
+ }
+ });
+ return ImmutableSet.copyOf(hosts);
+ }
+
+ @Override
+ public Set<Link> getInterLinks(Pair<DomainId, DomainId> endDomains) {
+ return domainStore.getInterLinks(endDomains);
+ }
+
+ @Override
+ public Set<Link> getIntraLinks(DomainId domainId) {
+ Set<Device> domDevices = getDevices(domainId);
+ Set<Link> intralinks = new HashSet<>();
+ domDevices.forEach(device -> {
+ Set<Link> devLinks = linkService.getDeviceLinks(device.id());
+ devLinks.forEach(link -> {
+ if (!link.annotations().keys().contains(SRC_DOMAIN_ID)) {
+ intralinks.add(link);
+ }
+ });
+ });
+ return ImmutableSet.copyOf(intralinks);
+ }
+
+ private class InternalDeviceListener implements DeviceListener {
+ @Override
+ public void event(DeviceEvent event) {
+ Device device = event.subject();
+ if (!device.annotations().keys().contains(DOMAIN_ID)) {
+ return;
+ }
+ DomainId domainId = DomainId.domainId(
+ device.annotations().value(DOMAIN_ID));
+ switch (event.type()) {
+ case DEVICE_ADDED:
+ domainStore.addDevice(domainId, device.id());
+ break;
+ case DEVICE_REMOVED:
+ domainStore.removeDevice(domainId, device.id());
+ break;
+ default:
+ log.error("Unsupported event type: " + event.type());
+ }
+ }
+ }
+
+ private class InternalHostListener implements HostListener {
+ @Override
+ public void event(HostEvent event) {
+ Host host = event.subject();
+ if (!host.annotations().keys().contains(DOMAIN_ID)) {
+ return;
+ }
+ DomainId domainId = DomainId.domainId(
+ host.annotations().value(DOMAIN_ID));
+ switch (event.type()) {
+ case HOST_ADDED:
+ domainStore.addHost(domainId, host.id());
+ break;
+ case HOST_REMOVED:
+ domainStore.removeHost(domainId, host.id());
+ break;
+ default:
+ log.error("Unsupported event type: " + event.type());
+ }
+ }
+ }
+
+ private class InternalLinkListener implements LinkListener {
+ @Override
+ public void event(LinkEvent event) {
+ Link link = event.subject();
+ if (!link.annotations().keys().contains(SRC_DOMAIN_ID) ||
+ !link.annotations().keys().contains(DST_DOMAIN_ID)) {
+ return;
+ }
+ DomainId srcDomainId = DomainId.domainId(
+ link.annotations().value(SRC_DOMAIN_ID));
+ DomainId dstDomainId = DomainId.domainId(
+ link.annotations().value(DST_DOMAIN_ID));
+ Pair<DomainId, DomainId> endDomains = Pair.of(srcDomainId, dstDomainId);
+ switch (event.type()) {
+ case LINK_ADDED:
+ case LINK_UPDATED:
+ domainStore.addOrUpdateInterLink(endDomains, link);
+ break;
+ case LINK_REMOVED:
+ domainStore.removeInterLink(endDomains, link);
+ break;
+ default:
+ log.error("Unsupported event type: " + event.type());
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/icona/domainmgr/src/main/java/org/onosproject/icona/domainmgr/impl/package-info.java b/icona/domainmgr/src/main/java/org/onosproject/icona/domainmgr/impl/package-info.java
new file mode 100644
index 0000000..5f9144e
--- /dev/null
+++ b/icona/domainmgr/src/main/java/org/onosproject/icona/domainmgr/impl/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Icona manager implementation.
+ */
+package org.onosproject.icona.domainmgr.impl;
\ No newline at end of file
diff --git a/icona/domainprovider/pom.xml b/icona/domainprovider/pom.xml
new file mode 100644
index 0000000..2c25234
--- /dev/null
+++ b/icona/domainprovider/pom.xml
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright 2016-present Open Networking Laboratory
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-icona</artifactId>
+ <version>1.7.0-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>onos-app-icona-domain-provider</artifactId>
+ <packaging>bundle</packaging>
+
+
+ <description>Inter Cluster Onos Network App/provider</description>
+
+ <properties>
+ <onos.app.name>org.onosproject.icona.domainprovider</onos.app.name>
+ </properties>
+
+
+ <dependencies>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.compendium</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-api</artifactId>
+ <version>${onos.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-core-serializers</artifactId>
+ <version>${onos.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onlab-osgi</artifactId>
+ <version>${onos.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onlab-misc</artifactId>
+ <version>${onos.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.core</groupId>
+ <artifactId>jersey-client</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-app-icona-domain-manager</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ </dependencies>
+</project>
diff --git a/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/DefaultDomainTopology.java b/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/DefaultDomainTopology.java
new file mode 100644
index 0000000..511928d
--- /dev/null
+++ b/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/DefaultDomainTopology.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.icona.domainprovider.api;
+
+import com.google.common.collect.ImmutableSet;
+import org.onosproject.icona.domainmgr.api.DomainId;
+import org.onosproject.icona.domainprovider.api.device.DomainDevice;
+import org.onosproject.icona.domainprovider.api.host.DomainHostDescription;
+import org.onosproject.icona.domainprovider.api.link.IntraLinkDescription;
+
+import java.util.Set;
+
+/**
+ * Default implementation of {@link DomainTopology}.
+ */
+public class DefaultDomainTopology implements DomainTopology {
+
+ private final DomainId domainId;
+ private final Set<DomainDevice> devices;
+ private final Set<IntraLinkDescription> intraLinkDescriptions;
+ private final Set<DomainHostDescription> domainHostDescriptions;
+
+ /**
+ * Creates a domain topology object with the supplied elements.
+ *
+ * @param domainId domain identifier
+ * @param devices set of devices
+ * @param intraLinkDescriptions set of links inside the domain
+ * @param domainHostDescriptions set of hosts
+ */
+ public DefaultDomainTopology(DomainId domainId, Set<DomainDevice> devices,
+ Set<IntraLinkDescription> intraLinkDescriptions,
+ Set<DomainHostDescription> domainHostDescriptions) {
+ this.domainId = domainId;
+ this.devices = devices;
+ this.intraLinkDescriptions = intraLinkDescriptions;
+ this.domainHostDescriptions = domainHostDescriptions;
+ }
+
+ @Override
+ public DomainId domainId() {
+ return domainId;
+ }
+
+ @Override
+ public Set<DomainDevice> domainDevices() {
+ return ImmutableSet.copyOf(devices);
+ }
+
+ @Override
+ public Set<IntraLinkDescription> domainLinks() {
+ return ImmutableSet.copyOf(intraLinkDescriptions);
+ }
+
+ @Override
+ public Set<DomainHostDescription> domainHosts() {
+ return ImmutableSet.copyOf(domainHostDescriptions);
+ }
+}
diff --git a/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/DomainElement.java b/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/DomainElement.java
new file mode 100644
index 0000000..4ef9c67
--- /dev/null
+++ b/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/DomainElement.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.icona.domainprovider.api;
+
+import org.onosproject.icona.domainmgr.api.DomainId;
+
+/**
+ * Interface implemented by the domain topology elements.
+ */
+public interface DomainElement {
+
+ /**
+ * Returns the domain id the element belongs to.
+ *
+ * @return domain id
+ */
+ DomainId domainId();
+}
diff --git a/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/DomainTopology.java b/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/DomainTopology.java
new file mode 100644
index 0000000..1d9f98b
--- /dev/null
+++ b/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/DomainTopology.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.icona.domainprovider.api;
+
+import org.onosproject.icona.domainprovider.api.device.DomainDevice;
+import org.onosproject.icona.domainprovider.api.host.DomainHostDescription;
+import org.onosproject.icona.domainprovider.api.link.IntraLinkDescription;
+
+import java.util.Set;
+/**
+ * Methods for describing a topology exposed by a domain.
+ */
+public interface DomainTopology extends DomainElement {
+
+ /**
+ * Returns the set of "virtual" devices of the domain.
+ * @return set of devices
+ */
+ Set<DomainDevice> domainDevices();
+
+ /**
+ * @return set of intra-links
+ */
+ Set<IntraLinkDescription> domainLinks();
+
+ /**
+ * Returns set of hosts exposed by the domain.
+ *
+ * @return set of domain hosts
+ */
+ Set<DomainHostDescription> domainHosts();
+}
diff --git a/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/IconaSBListener.java b/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/IconaSBListener.java
new file mode 100644
index 0000000..079642d
--- /dev/null
+++ b/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/IconaSBListener.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.icona.domainprovider.api;
+
+
+import org.onosproject.icona.domainprovider.api.device.IconaSBDeviceListener;
+import org.onosproject.icona.domainprovider.api.host.IconaSBHostListener;
+import org.onosproject.icona.domainprovider.api.link.IconaSBLinkListener;
+
+/**
+ * This interface enables a single component that implements IconaSBListenerService
+ * to orchestrate multiple southbound components implementing all the element-specific listeners.
+ */
+public interface IconaSBListener extends IconaSBDeviceListener,
+ IconaSBHostListener, IconaSBLinkListener, IconaSBTopologyListener {
+}
diff --git a/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/IconaSBListenerService.java b/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/IconaSBListenerService.java
new file mode 100644
index 0000000..fc06fea
--- /dev/null
+++ b/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/IconaSBListenerService.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.icona.domainprovider.api;
+
+/**
+ * Service used by the southbound components to listen for local domain events.
+ */
+public interface IconaSBListenerService {
+
+ /**
+ * Adds southbound listener to the provider.
+ *
+ * @param listener listener
+ */
+ void addListener(IconaSBListener listener);
+
+ /**
+ * Removes a southbound listener from the provider.
+ *
+ * @param listener listener
+ */
+ void removeListener(IconaSBListener listener);
+}
diff --git a/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/IconaSBTopologyListener.java b/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/IconaSBTopologyListener.java
new file mode 100644
index 0000000..58267cf
--- /dev/null
+++ b/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/IconaSBTopologyListener.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.icona.domainprovider.api;
+
+import com.google.common.annotations.Beta;
+import org.onosproject.icona.domainmgr.api.DomainId;
+
+import java.util.Map;
+
+/**
+ * Methods implemented by the southbound components to send the complete local topology to another domain.
+ */
+public interface IconaSBTopologyListener {
+
+ /**
+ * Configures the local topology exposed to a domain, based on configuration policies.
+ *
+ * @param topologyMap a map with the domain id as the key and the topology object as the value
+ */
+ void configTopology(Map<DomainId, DomainTopology> topologyMap);
+
+
+ /**
+ * Remove a complete topology configuration exposed to a domain.
+ *
+ * @param domainId domain identifier
+ */
+ @Beta
+ void removeConfigTopology(DomainId domainId);
+}
diff --git a/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/PeerState.java b/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/PeerState.java
new file mode 100644
index 0000000..75f1bdf
--- /dev/null
+++ b/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/PeerState.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.icona.domainprovider.api;
+
+/**
+ * State of a session with a remote domain.
+ */
+public enum PeerState {
+
+ UP,
+ DOWN,
+ UNKNOWN
+}
diff --git a/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/device/DefaultDomainDevice.java b/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/device/DefaultDomainDevice.java
new file mode 100644
index 0000000..88ff89b
--- /dev/null
+++ b/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/device/DefaultDomainDevice.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.icona.domainprovider.api.device;
+
+import com.google.common.collect.ImmutableList;
+import org.onosproject.icona.domainmgr.api.DomainId;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.device.PortDescription;
+
+import java.util.List;
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+/**
+ * Default implementation of a domain device.
+ */
+public class DefaultDomainDevice implements DomainDevice {
+
+ private final DeviceId deviceId;
+ private final DomainId domainId;
+ private final List<PortDescription> ports;
+
+ public DefaultDomainDevice(DeviceId deviceId, DomainId domainId, List<PortDescription> ports) {
+ this.deviceId = deviceId;
+ this.domainId = domainId;
+ this.ports = ports;
+ }
+
+ @Override
+ public DeviceId deviceId() {
+ return deviceId;
+ }
+
+ @Override
+ public DomainId domainId() {
+ return domainId;
+ }
+
+ @Override
+ public List<PortDescription> ports() {
+ return ImmutableList.copyOf(ports);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(super.hashCode(), deviceId, domainId);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof DefaultDomainDevice) {
+ final DefaultDomainDevice other = (DefaultDomainDevice) obj;
+ return Objects.equals(this.deviceId, other.deviceId()) &&
+ Objects.equals(this.domainId, other.domainId());
+
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this)
+ .add("deviceId", deviceId.toString())
+ .add("domainId", domainId)
+ .add("ports", ports.toString())
+ .toString();
+ }
+}
diff --git a/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/device/DomainDevice.java b/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/device/DomainDevice.java
new file mode 100644
index 0000000..b5dc0df
--- /dev/null
+++ b/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/device/DomainDevice.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.icona.domainprovider.api.device;
+
+import org.onosproject.icona.domainprovider.api.DomainElement;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.device.PortDescription;
+
+import java.util.List;
+
+/**
+ * Peer domain device.
+ */
+public interface DomainDevice extends DomainElement {
+
+ /**
+ * Returns the device ID.
+ *
+ * @return device identifier
+ */
+ DeviceId deviceId();
+
+ /**
+ * Returns a list of port descriptions.
+ * These ports differ in ports where end-points (hosts) are attached to, intra-link ports
+ * and inter-link ports.
+ *
+ * @return list of port descriptions
+ */
+ List<PortDescription> ports();
+}
diff --git a/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/device/IconaSBDeviceListener.java b/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/device/IconaSBDeviceListener.java
new file mode 100644
index 0000000..9b7b4d0
--- /dev/null
+++ b/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/device/IconaSBDeviceListener.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.icona.domainprovider.api.device;
+
+import org.onosproject.icona.domainmgr.api.DomainId;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.device.PortDescription;
+
+/**
+ * Methods implemented by the southbound components for (local topology) device events.
+ */
+public interface IconaSBDeviceListener {
+
+ /**
+ * Connects a new domain device with its list of ports to a remote domain.
+ * The first parameter is the domain ID of the receiving domain, while the domain
+ * ID inside the device parameter is the local domain identifier which is
+ * the "owner" of the device.
+ *
+ * @param domainId domain interested to this device
+ * @param device to be added
+ */
+ void connectDevice(DomainId domainId, DomainDevice device);
+
+ /**
+ * Adds a port to an existing domain device.
+ *
+ * @param domainId domain interested to this addition
+ * @param deviceId device identifier
+ * @param portDescription description of the port
+ */
+ void addPort(DomainId domainId, DeviceId deviceId, PortDescription portDescription);
+
+ /**
+ * Enables or disables a port on a domain device.
+ * No distinction between administrative and operational state currently.
+ *
+ * @param domainId domain interested to this change
+ * @param deviceId device identifier
+ * @param portNumber port identifier
+ * @param enable true if port is to be enabled, false to disable
+ */
+ void updatePortState(DomainId domainId, DeviceId deviceId, PortNumber portNumber, boolean enable);
+
+ /**
+ * Disconnects the device with the specified identifier.
+ *
+ * @param domainId domain interested to this update
+ * @param deviceId device identifier
+ */
+ void disconnectDevice(DomainId domainId, DeviceId deviceId);
+
+ /**
+ * Removes the port with the specified identifier.
+ *
+ * @param domainId domain interested to this update
+ * @param deviceId device identifier
+ * @param portNumber port number
+ */
+ void removePort(DomainId domainId, DeviceId deviceId, PortNumber portNumber);
+}
\ No newline at end of file
diff --git a/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/device/IconaSBDeviceService.java b/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/device/IconaSBDeviceService.java
new file mode 100644
index 0000000..664331a
--- /dev/null
+++ b/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/device/IconaSBDeviceService.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.icona.domainprovider.api.device;
+
+import org.onosproject.icona.domainmgr.api.DomainId;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.device.PortDescription;
+
+/**
+ * Service used by the southbound components to advertise remote device events.
+ */
+public interface IconaSBDeviceService {
+
+ /**
+ * Signals the domain provider to connect a domain device.
+ *
+ * @param domainDevice device object
+ */
+ void connectRemoteDevice(DomainDevice domainDevice);
+
+ /**
+ * Signals the domain provider to add a new port to a domain device.
+ *
+ * @param domainId domain identifier
+ * @param deviceId device identifier
+ * @param portDescription description of the port
+ */
+ void addRemotePort(DomainId domainId, DeviceId deviceId, PortDescription portDescription);
+
+ /**
+ * Signals a remote port update.
+ *
+ * @param domainId domain identifier
+ * @param deviceId device identifier
+ * @param portDescription port description
+ */
+ void updateRemotePortState(DomainId domainId, DeviceId deviceId, PortDescription portDescription);
+
+
+ /**
+ * Signals the disconnection of a remote domain device.
+ *
+ * @param domainId domain identifier
+ * @param deviceId device identifier
+ */
+ void disconnectRemoteDevice(DomainId domainId, DeviceId deviceId);
+
+ /**
+ * Signals the deletion of a remote domain device port.
+ *
+ * @param domainId domain identifier
+ * @param deviceId device identifier
+ * @param portNumber port identifier
+ */
+ void removeRemotePort(DomainId domainId, DeviceId deviceId, PortNumber portNumber);
+
+}
diff --git a/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/device/package-info.java b/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/device/package-info.java
new file mode 100644
index 0000000..b04b14c
--- /dev/null
+++ b/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/device/package-info.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Multi domain device apis.
+ */
+
+package org.onosproject.icona.domainprovider.api.device;
\ No newline at end of file
diff --git a/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/host/DefaultDomainHostDescription.java b/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/host/DefaultDomainHostDescription.java
new file mode 100644
index 0000000..f8f2d22
--- /dev/null
+++ b/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/host/DefaultDomainHostDescription.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.icona.domainprovider.api.host;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Sets;
+import org.onlab.packet.Ip6Prefix;
+import org.onlab.packet.Ip4Prefix;
+import org.onlab.packet.MacAddress;
+import org.onlab.packet.VlanId;
+import org.onlab.packet.IpAddress;
+import org.onosproject.icona.domainmgr.api.DomainId;
+import org.onosproject.net.SparseAnnotations;
+import org.onosproject.net.HostLocation;
+import org.onosproject.net.Host;
+import org.onosproject.net.host.DefaultHostDescription;
+
+import java.util.Objects;
+import java.util.Set;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+/**
+ * Default implementation of {@link DomainHostDescription}.
+ */
+public class DefaultDomainHostDescription extends DefaultHostDescription
+ implements DomainHostDescription {
+
+ private final DomainId domainId;
+ private final Set<Ip4Prefix> ip4Subnets;
+ private final Set<Ip6Prefix> ip6Subnets;
+
+ /**
+ * Creates an end-station host using the supplied information.
+ *
+ * @param domainId domain identifier
+ * @param mac host MAC address
+ * @param vlan host VLAN identifier
+ * @param location host location
+ * @param ips host IP addresses
+ * @param ip4Subnets ipv4 subnets
+ * @param annotations optional key/value annotations
+ */
+ public DefaultDomainHostDescription(DomainId domainId,
+ MacAddress mac,
+ VlanId vlan,
+ HostLocation location,
+ Set<IpAddress> ips,
+ Set<Ip4Prefix> ip4Subnets,
+ SparseAnnotations... annotations) {
+ super(mac, vlan, location, ips, annotations);
+
+ this.domainId = domainId;
+ this.ip4Subnets = ip4Subnets;
+ this.ip6Subnets = Sets.newHashSet();
+ }
+
+ /**
+ * Creates an end-station host using the supplied information.
+ *
+ * @param domainId domain identifier
+ * @param mac host MAC address
+ * @param vlan host VLAN identifier
+ * @param location host location
+ * @param ips host IP addresses
+ * @param ip4Subnets ipv4 subnets
+ * @param ip6Subnets ip6 subnets
+ * @param annotations optional key/value annotations
+ */
+ public DefaultDomainHostDescription(DomainId domainId,
+ MacAddress mac,
+ VlanId vlan,
+ HostLocation location,
+ Set<IpAddress> ips,
+ Set<Ip4Prefix> ip4Subnets,
+ Set<Ip6Prefix> ip6Subnets,
+ SparseAnnotations... annotations) {
+ super(mac, vlan, location, ips, annotations);
+
+ this.domainId = domainId;
+ this.ip4Subnets = ip4Subnets;
+ this.ip6Subnets = ip6Subnets;
+ }
+
+ @Override
+ public DomainId domainId() {
+ return domainId;
+ }
+
+ @Override
+ public Set<Ip4Prefix> ip4Subnets() {
+ return ImmutableSet.copyOf(ip4Subnets);
+ }
+
+ @Override
+ public Set<Ip6Prefix> ip6Subnets() {
+ return ImmutableSet.copyOf(ip6Subnets);
+
+ }
+
+ @Override
+ public boolean isHost(Host host) {
+ return Objects.equals(this.hwAddress(), host.mac());
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(super.hashCode(), domainId, ip4Subnets, ip6Subnets);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof DefaultDomainHostDescription) {
+ final DefaultDomainHostDescription other = (DefaultDomainHostDescription) obj;
+ return Objects.equals(this.hwAddress(), other.hwAddress()) &&
+ Objects.equals(this.ipAddress(), other.ipAddress()) &&
+ Objects.equals(this.location(), other.location()) &&
+ Objects.equals(this.domainId, other.domainId) &&
+ Objects.equals(this.ip4Subnets, other.ip4Subnets()) &&
+ Objects.equals(this.ip6Subnets, other.ip6Subnets());
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this)
+ .add("mac", hwAddress())
+ .add("vlan", vlan())
+ .add("location", location())
+ .add("ipAdresses", ipAddress())
+ .add("ip4Subnets", ip4Subnets)
+ .add("ip6Subnets", ip6Subnets)
+ .add("domain", domainId)
+ .add("annotations", annotations())
+ .toString();
+ }
+}
diff --git a/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/host/DomainHostDescription.java b/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/host/DomainHostDescription.java
new file mode 100644
index 0000000..658d4ee
--- /dev/null
+++ b/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/host/DomainHostDescription.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.icona.domainprovider.api.host;
+
+import org.onlab.packet.Ip4Prefix;
+import org.onlab.packet.Ip6Prefix;
+import org.onosproject.icona.domainprovider.api.DomainElement;
+import org.onosproject.net.Host;
+import org.onosproject.net.host.HostDescription;
+
+import java.util.Set;
+
+/**
+ * Description of a host that belongs to another domain.
+ */
+public interface DomainHostDescription extends HostDescription, DomainElement {
+
+ /**
+ * Verify if the domain host corresponds to the specified host in the local domain.
+ * The domainHost will have a host location pointing to a (virtual) domain device
+ * exposed to the other domains.
+ *
+ * @param host to compare with
+ * @return true if they correspond
+ */
+ boolean isHost(Host host);
+
+ /**
+ * Returns the ipv4 subnets.
+ *
+ * @return set of ipv4 subnets
+ */
+ Set<Ip4Prefix> ip4Subnets();
+
+ /**
+ * Returns the ipv6 subnets.
+ *
+ * @return set of ipv6 subnets
+ */
+ Set<Ip6Prefix> ip6Subnets();
+}
diff --git a/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/host/IconaSBHostListener.java b/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/host/IconaSBHostListener.java
new file mode 100644
index 0000000..a4b4292
--- /dev/null
+++ b/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/host/IconaSBHostListener.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.icona.domainprovider.api.host;
+
+import org.onosproject.icona.domainmgr.api.DomainId;
+import org.onosproject.net.HostId;
+
+import java.util.Set;
+
+/**
+ * Methods implemented by the southbound components to react to the (local topology) host events.
+ */
+public interface IconaSBHostListener {
+
+ /**
+ * Advertises a set of new domain hosts to a domain.
+ *
+ * @param domainId domain interested to this addition
+ * @param hosts set of hosts to add
+ */
+ void addHosts(DomainId domainId, Set<DomainHostDescription> hosts);
+
+ /**
+ * Replaces the information about an existing set of domain hosts.
+ *
+ * @param domainId domain interested to this update
+ * @param hosts set of hosts to update
+ */
+ void replaceHosts(DomainId domainId, Set<DomainHostDescription> hosts);
+
+ /**
+ * Removes a set of domain hosts exposed to a domain.
+ *
+ * @param domainId domain interested to this deletion
+ * @param hostIds set of host identifiers
+ */
+ void removeHosts(DomainId domainId, Set<HostId> hostIds);
+}
diff --git a/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/host/IconaSBHostService.java b/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/host/IconaSBHostService.java
new file mode 100644
index 0000000..fc34af4
--- /dev/null
+++ b/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/host/IconaSBHostService.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.icona.domainprovider.api.host;
+
+import org.onosproject.icona.domainmgr.api.DomainId;
+import org.onosproject.net.HostId;
+
+import java.util.Set;
+
+/**
+ * Service consumed by the southbound components to advertise
+ * remote host events to the provider.
+ */
+public interface IconaSBHostService {
+
+ /**
+ * Signals the domain provider to add a set of remote domain hosts.
+ *
+ * @param domainId remote domain identifier
+ * @param domainHostDescriptions hosts to be added
+ */
+ void addRemoteHosts(DomainId domainId, Set<DomainHostDescription> domainHostDescriptions);
+
+ /**
+ * Signals the domain provider to replace the set of domain hosts.
+ *
+ * @param domainId remote domain identifier
+ * @param domainHostDescriptions hosts to be updated
+ */
+ void replaceRemoteHosts(DomainId domainId, Set<DomainHostDescription> domainHostDescriptions);
+
+ /**
+ * Signals the domain provider to remove the given remote hosts.
+ *
+ * @param domainId domain identifier
+ * @param hostIds host identifiers
+ */
+ void removeRemoteHosts(DomainId domainId, Set<HostId> hostIds);
+}
diff --git a/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/host/package-info.java b/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/host/package-info.java
new file mode 100644
index 0000000..50e88a1
--- /dev/null
+++ b/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/host/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Multi domain host APIs.
+ */
+package org.onosproject.icona.domainprovider.api.host;
\ No newline at end of file
diff --git a/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/link/DefaultInterLinkDescription.java b/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/link/DefaultInterLinkDescription.java
new file mode 100644
index 0000000..8eac6f5
--- /dev/null
+++ b/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/link/DefaultInterLinkDescription.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.icona.domainprovider.api.link;
+
+import org.apache.commons.lang3.tuple.Pair;
+import org.onosproject.icona.domainmgr.api.DomainId;
+import org.onosproject.net.SparseAnnotations;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.link.DefaultLinkDescription;
+
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+import static org.onosproject.net.Link.Type;
+
+/**
+ * Default implementation of {@link InterLinkDescription}.
+ */
+public class DefaultInterLinkDescription extends DefaultLinkDescription
+ implements InterLinkDescription {
+
+ private final Pair<DomainId, DomainId> endDomains;
+ private final LinkId id;
+
+ /**
+ * Creates an interlink using the supplied information.
+ *
+ * @param src source connect point
+ * @param dst destination connect point
+ * @param type link type
+ * @param endDomains pair of domains: source left, destination right
+ * @param id link identifier
+ * @param annotations more information
+ */
+ public DefaultInterLinkDescription(ConnectPoint src, ConnectPoint dst, Type type,
+ Pair<DomainId, DomainId> endDomains, LinkId id,
+ SparseAnnotations... annotations) {
+ super(src, dst, type, true, annotations);
+
+ this.id = id;
+ this.endDomains = endDomains;
+ }
+
+ @Override
+ public Pair<DomainId, DomainId> endDomains() {
+ return endDomains;
+ }
+
+ @Override
+ public LinkId linkId() {
+ return id;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(endDomains, id);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof DefaultInterLinkDescription) {
+ final DefaultInterLinkDescription other = (DefaultInterLinkDescription) obj;
+ return Objects.equals(this.endDomains, other.endDomains()) &&
+ Objects.equals(this.id, other.linkId());
+
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this)
+ .add("endDomains", endDomains.toString())
+ .add("linkId", id)
+ .toString();
+ }
+
+}
diff --git a/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/link/DefaultIntraLinkDescription.java b/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/link/DefaultIntraLinkDescription.java
new file mode 100644
index 0000000..f647427
--- /dev/null
+++ b/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/link/DefaultIntraLinkDescription.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.icona.domainprovider.api.link;
+
+import org.onosproject.icona.domainmgr.api.DomainId;
+import org.onosproject.net.SparseAnnotations;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.link.DefaultLinkDescription;
+
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+import static org.onosproject.net.Link.Type;
+
+/**
+ * Default implementation of {@link IntraLinkDescription}.
+ */
+public class DefaultIntraLinkDescription extends DefaultLinkDescription implements IntraLinkDescription {
+
+ private final DomainId domainId;
+ private final String id;
+
+ /**
+ * Creates an intra-link using the supplied information.
+ *
+ * @param src source connect point
+ * @param dst destination connect point
+ * @param type link type
+ * @param domainId domain identifier
+ * @param id link identifier
+ * @param annotations more information
+ */
+ public DefaultIntraLinkDescription(ConnectPoint src,
+ ConnectPoint dst, Type type,
+ DomainId domainId, String id,
+ SparseAnnotations... annotations) {
+ super(src, dst, type, true, annotations);
+
+ this.domainId = domainId;
+ this.id = id;
+ }
+
+ @Override
+ public DomainId domainId() {
+ return domainId;
+ }
+
+ @Override
+ public String linkId() {
+ return id;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(domainId, id);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof DefaultIntraLinkDescription) {
+ final DefaultIntraLinkDescription other = (DefaultIntraLinkDescription) obj;
+ return Objects.equals(this.domainId, other.domainId()) &&
+ Objects.equals(this.id, other.linkId());
+
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this)
+ .add("domain", domainId)
+ .add("linkId", id)
+ .toString();
+ }
+
+}
diff --git a/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/link/IconaSBLinkListener.java b/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/link/IconaSBLinkListener.java
new file mode 100644
index 0000000..61b56ad
--- /dev/null
+++ b/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/link/IconaSBLinkListener.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.icona.domainprovider.api.link;
+
+import org.onosproject.icona.domainmgr.api.DomainId;
+
+import static org.onosproject.net.Link.State;
+
+/**
+ * Methods implemented by the southbound components for the (local topology) link events.
+ */
+public interface IconaSBLinkListener {
+
+ /**
+ * Advertises the presence of a link between two local domain devices.
+ *
+ * @param domainId domain interested to this addition
+ * @param link link to be added
+ */
+ void addLink(DomainId domainId, IntraLinkDescription link);
+
+ /**
+ * Updates a link state.
+ *
+ * @param domainId domain interested to this update
+ * @param linkId link identifier
+ * @param state updated state
+ */
+ void updateLinkState(DomainId domainId, LinkId linkId, State state);
+
+ /**
+ * Updates a link metric.
+ *
+ * @param domainId domain interested to this update
+ * @param linkId link identifier
+ * @param metric changed metric
+ */
+ void updateLinkMetric(DomainId domainId, LinkId linkId, int metric);
+
+ /**
+ * Removes a link.
+ *
+ * @param domainId domain interested to this update
+ * @param linkId link identifier
+ */
+ void removeLink(DomainId domainId, LinkId linkId);
+}
diff --git a/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/link/IconaSBLinkService.java b/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/link/IconaSBLinkService.java
new file mode 100644
index 0000000..68470c0
--- /dev/null
+++ b/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/link/IconaSBLinkService.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.icona.domainprovider.api.link;
+
+import org.onosproject.icona.domainmgr.api.DomainId;
+
+import static org.onosproject.net.Link.State;
+
+/**
+ * Interface used by the southbound components to advertise remote host events.
+ */
+public interface IconaSBLinkService {
+
+ /**
+ * Signals the domain provider to add a remote link.
+ *
+ * @param link link to be added
+ */
+ void addRemoteLink(IntraLinkDescription link);
+
+ /**
+ * Signals the domain provider to add an interlink between this and a remote domain.
+ *
+ * @param domainId remote domain identifier
+ * @param link link to be added
+ */
+ void addInterLink(DomainId domainId, InterLinkDescription link);
+
+ /**
+ * Signals the domain provider to change a remote link state.
+ *
+ * @param domainId domain identifier
+ * @param id link identifier
+ * @param state updated link state
+ */
+ void updateRemoteLinkState(DomainId domainId, LinkId id, State state);
+
+ /**
+ * Signals the domain provider to change a remote link metric.
+ *
+ * @param domainId domain identifier
+ * @param id link identifier
+ * @param metric updated metric
+ */
+ void updateRemoteLinkMetric(DomainId domainId, LinkId id, int metric);
+
+ /**
+ * Signals the domain provider to delete a remote link.
+ *
+ * @param domainId domain identifier
+ * @param id link identifier
+ */
+ void removeRemoteLink(DomainId domainId, LinkId id);
+}
diff --git a/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/link/InterLinkDescription.java b/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/link/InterLinkDescription.java
new file mode 100644
index 0000000..4d620a5
--- /dev/null
+++ b/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/link/InterLinkDescription.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.icona.domainprovider.api.link;
+
+import org.apache.commons.lang3.tuple.Pair;
+import org.onosproject.icona.domainmgr.api.DomainId;
+import org.onosproject.net.link.LinkDescription;
+
+
+/**
+ * Link between domains.
+ */
+public interface InterLinkDescription extends LinkDescription {
+
+ /**
+ * Returns the source and the destination domain ids of this interlink.
+ *
+ * @return pair of source and destination id
+ */
+ Pair<DomainId, DomainId> endDomains();
+
+ /**
+ * ID of the link.
+ *
+ * @return string ID
+ */
+ LinkId linkId();
+}
diff --git a/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/link/IntraLinkDescription.java b/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/link/IntraLinkDescription.java
new file mode 100644
index 0000000..cc9e3d7
--- /dev/null
+++ b/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/link/IntraLinkDescription.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.icona.domainprovider.api.link;
+
+import org.onosproject.icona.domainprovider.api.DomainElement;
+import org.onosproject.net.link.LinkDescription;
+
+
+/**
+ * Link between two devices of the same domain.
+ */
+public interface IntraLinkDescription extends LinkDescription, DomainElement {
+
+ /**
+ * ID of the link.
+ * @return string id
+ */
+ String linkId();
+}
diff --git a/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/link/LinkId.java b/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/link/LinkId.java
new file mode 100644
index 0000000..575d50d
--- /dev/null
+++ b/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/link/LinkId.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.icona.domainprovider.api.link;
+
+import org.onlab.util.Identifier;
+
+/**
+ * Domain link identifier class.
+ */
+public class LinkId extends Identifier<String> {
+
+ public LinkId(String identifier) {
+ super(identifier);
+ }
+
+ public static LinkId linkId(String id) {
+ return new LinkId(id);
+ }
+}
diff --git a/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/link/package-info.java b/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/link/package-info.java
new file mode 100644
index 0000000..8458e95
--- /dev/null
+++ b/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/link/package-info.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Multi domain link apis.
+ */
+
+package org.onosproject.icona.domainprovider.api.link;
\ No newline at end of file
diff --git a/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/package-info.java b/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/package-info.java
new file mode 100644
index 0000000..8fc209f
--- /dev/null
+++ b/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/api/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * APIs of the ICONA multi domain domainprovider.
+ */
+package org.onosproject.icona.domainprovider.api;
\ No newline at end of file
diff --git a/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/impl/IconaRemoteDeviceProvider.java b/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/impl/IconaRemoteDeviceProvider.java
new file mode 100644
index 0000000..ec11959
--- /dev/null
+++ b/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/impl/IconaRemoteDeviceProvider.java
@@ -0,0 +1,302 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.icona.domainprovider.impl;
+
+import com.google.common.collect.Sets;
+import org.apache.commons.lang3.tuple.Pair;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Service;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.onlab.packet.ChassisId;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreService;
+import org.onosproject.icona.domainmgr.api.DomainId;
+import org.onosproject.icona.domainprovider.api.device.DomainDevice;
+import org.onosproject.icona.domainprovider.api.device.IconaSBDeviceService;
+import org.onosproject.icona.domainprovider.api.link.DefaultInterLinkDescription;
+import org.onosproject.icona.domainprovider.api.link.IconaSBLinkService;
+import org.onosproject.icona.domainprovider.api.link.InterLinkDescription;
+import org.onosproject.icona.domainprovider.api.link.LinkId;
+import org.onosproject.icona.domainprovider.impl.config.IconaConfig;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DefaultAnnotations;
+import org.onosproject.net.SparseAnnotations;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Device;
+import org.onosproject.net.MastershipRole;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.Link;
+import org.onosproject.net.config.ConfigFactory;
+import org.onosproject.net.config.NetworkConfigListener;
+import org.onosproject.net.config.NetworkConfigRegistry;
+import org.onosproject.net.config.NetworkConfigService;
+import org.onosproject.net.config.NetworkConfigEvent;
+import org.onosproject.net.device.DeviceProvider;
+import org.onosproject.net.device.DeviceProviderRegistry;
+import org.onosproject.net.device.DeviceProviderService;
+import org.onosproject.net.device.DefaultDeviceDescription;
+import org.onosproject.net.device.DeviceDescription;
+import org.onosproject.net.device.PortDescription;
+import org.onosproject.net.provider.ProviderId;
+import org.slf4j.Logger;
+
+import java.util.Optional;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.ExecutorService;
+
+import static org.onosproject.icona.domainprovider.impl.IconaTopologyManager.INTER_LINK_ID;
+import static org.onosproject.icona.domainprovider.impl.config.IconaConfig.DomainConfig;
+import static java.util.concurrent.Executors.newFixedThreadPool;
+import static org.onlab.util.Tools.groupedThreads;
+import static org.slf4j.LoggerFactory.getLogger;
+import static org.onosproject.net.config.basics.SubjectFactories.APP_SUBJECT_FACTORY;
+
+/**
+ * Exposes remote domain devices to the core.
+ */
+@Component(immediate = true)
+@Service(IconaSBDeviceService.class)
+public class IconaRemoteDeviceProvider implements DeviceProvider, IconaSBDeviceService {
+
+ private final Logger log = getLogger(getClass());
+ protected static final String PROVIDER_NAME = "org.onosproject.icona.domainprovider";
+ protected static final ProviderId PROVIDER_ID = new ProviderId("domain", PROVIDER_NAME);
+ private static final String UNKNOWN = "unknown";
+
+ private ApplicationId appId;
+ private DomainId localDomainId;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected NetworkConfigRegistry configRegistry;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected NetworkConfigService configService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected CoreService coreService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected DeviceProviderRegistry deviceProviderRegistry;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected IconaSBLinkService iconaSBLinkService;
+
+ protected DeviceProviderService deviceProviderService;
+
+ private Set<DomainConfig> domainConfigs = Sets.newConcurrentHashSet();
+
+ private final NetworkConfigListener configListener = new InternalConfigListener();
+ private final ConfigFactory configFactory =
+ new ConfigFactory(APP_SUBJECT_FACTORY, IconaConfig.class, "icona") {
+ @Override
+ public IconaConfig createConfig() {
+ return new IconaConfig();
+ }
+ };
+ private final ExecutorService eventExecutor =
+ newFixedThreadPool(3, groupedThreads("onos/icona-sb-manager", "event-handler-%d"));
+
+ @Override
+ public ProviderId id() {
+ return PROVIDER_ID;
+ }
+
+ @Activate
+ public void activate() {
+ appId = coreService.registerApplication(PROVIDER_NAME);
+ configRegistry.registerConfigFactory(configFactory);
+ configService.addListener(configListener);
+ deviceProviderService = deviceProviderRegistry.register(this);
+ }
+
+ @Deactivate
+ public void deactivate() {
+ //TODO: disconnect devices
+ configService.removeListener(configListener);
+ configRegistry.unregisterConfigFactory(configFactory);
+ deviceProviderRegistry.unregister(this);
+ }
+
+ /**
+ * Notify the core system that a new domain device is on.
+ *
+ * @param deviceId remote device identifier
+ */
+ private void advertiseDevice(DeviceId deviceId, DomainId domainId) {
+ ChassisId chassisId = new ChassisId();
+
+ // disable lldp for this virtual device
+ SparseAnnotations annotations = DefaultAnnotations.builder()
+ .set("no-lldp", "lldp is disabled for a domain device")
+ .set("domainId", domainId.toString())
+ .build();
+
+ // TODO: give meaningful device info from the remote cluster
+ DeviceDescription deviceDescription = new DefaultDeviceDescription(
+ deviceId.uri(),
+ Device.Type.SWITCH,
+ UNKNOWN, UNKNOWN,
+ UNKNOWN, UNKNOWN,
+ chassisId,
+ annotations);
+ deviceProviderService.deviceConnected(deviceId, deviceDescription);
+ }
+
+ /**
+ * Notifies the core system of all ports of a device.
+ *
+ * @param deviceId device identifier
+ * @param portDescriptions description of ports
+ */
+ private void advertiseDevicePorts(DeviceId deviceId, List<PortDescription> portDescriptions) {
+ // ports are properly annotated in the southbound bundles
+ deviceProviderService.updatePorts(deviceId, portDescriptions);
+ }
+
+ /**
+ * Creates two directed links for each inter-link port found among the list
+ * of all the domain device ports, assuming all interlinks are bidirectional.
+ * One connect-point is taken from configuration, the other from the port description.
+ *
+ * @param domainId domain identifier
+ * @param deviceId port identifier
+ * @param port interlink port description
+ */
+ private void advertiseInterlinks(DomainId domainId, DeviceId deviceId, PortDescription port) {
+ LinkId interLinkId = LinkId.linkId(port.annotations().value(INTER_LINK_ID));
+ Optional<DomainConfig> optional = domainConfigs.stream()
+ .filter(config -> !config.peerId().equals(domainId))
+ .findFirst();
+ if (optional.isPresent()) {
+ Pair<Link.Type, ConnectPoint> interlinkConf =
+ optional.get()
+ .interLinkConnectPointMap()
+ .get(interLinkId);
+ ConnectPoint localCp = interlinkConf.getRight();
+ ConnectPoint remoteCp = new ConnectPoint(deviceId, port.portNumber());
+ Link.Type linkType = interlinkConf.getLeft();
+ // currently we handle interlinks as being bidirectional...
+ SparseAnnotations annotations = annotateInterLink(localDomainId.id(), domainId.id());
+ InterLinkDescription interLinkDescription1 = new DefaultInterLinkDescription(localCp,
+ remoteCp, linkType, Pair.of(localDomainId, domainId), interLinkId, annotations);
+ SparseAnnotations annotations1 = annotateInterLink(domainId.id(), localDomainId.id());
+ InterLinkDescription interLinkDescription2 = new DefaultInterLinkDescription(remoteCp,
+ localCp, linkType, Pair.of(domainId, localDomainId), interLinkId, annotations1);
+ iconaSBLinkService.addInterLink(domainId, interLinkDescription1);
+ iconaSBLinkService.addInterLink(domainId, interLinkDescription2);
+ } else {
+ log.info("No local connect point for interlink: " + interLinkId);
+ }
+ }
+ private SparseAnnotations annotateInterLink(String srcDomain, String dstDomain) {
+ return DefaultAnnotations.builder()
+ .set("srcDomain", srcDomain)
+ .set("dstDomain", dstDomain)
+ .build();
+ }
+
+ // DeviceProvider
+ @Override
+ public void triggerProbe(DeviceId deviceId) {
+ // TODO Auto-generated method stub
+ }
+
+ @Override
+ public void roleChanged(DeviceId deviceId, MastershipRole newRole) {
+
+ }
+
+ @Override
+ public boolean isReachable(DeviceId deviceId) {
+ // TODO
+ return true;
+ }
+
+ @Override
+ public void changePortState(DeviceId deviceId, PortNumber portNumber,
+ boolean enable) {
+ // TODO
+ }
+
+ // IconaSBDeviceService
+ @Override
+ public void connectRemoteDevice(DomainDevice domainDevice) {
+ DomainId domainId = domainDevice.domainId();
+ DeviceId deviceId = domainDevice.deviceId();
+ advertiseDevice(deviceId, domainId);
+ advertiseDevicePorts(deviceId, domainDevice.ports());
+ domainDevice.ports().forEach(port -> {
+ if (port.annotations().keys().contains(INTER_LINK_ID)) {
+ advertiseInterlinks(domainId, deviceId, port);
+ }
+ });
+ }
+
+ @Override
+ public void addRemotePort(DomainId domainId, DeviceId deviceId, PortDescription portDescription) {
+ // TODO
+ }
+
+ @Override
+ public void updateRemotePortState(DomainId domainId, DeviceId deviceId, PortDescription portDescription) {
+ // TODO
+ }
+
+ @Override
+ public void disconnectRemoteDevice(DomainId domainId, DeviceId deviceId) {
+ // TODO
+ }
+
+ @Override
+ public void removeRemotePort(DomainId domainId, DeviceId deviceId, PortNumber portNumber) {
+ // TODO
+ }
+
+ private void readConfig() {
+ IconaConfig iconaConfig =
+ configRegistry.getConfig(appId, IconaConfig.class);
+ localDomainId = iconaConfig.getLocalId();
+ domainConfigs.addAll(
+ iconaConfig.getPeersConfig());
+ }
+
+ private class InternalConfigListener implements NetworkConfigListener {
+
+ @Override
+ public void event(NetworkConfigEvent event) {
+ if (!event.configClass().equals(IconaConfig.class)) {
+ return;
+ }
+ switch (event.type()) {
+ case CONFIG_ADDED:
+ log.info("Network configuration added");
+ eventExecutor.execute(IconaRemoteDeviceProvider.this::readConfig);
+ break;
+ case CONFIG_UPDATED:
+ log.info("Network configuration updated");
+ eventExecutor.execute(IconaRemoteDeviceProvider.this::readConfig);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/impl/IconaRemoteHostProvider.java b/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/impl/IconaRemoteHostProvider.java
new file mode 100644
index 0000000..2e54b8d
--- /dev/null
+++ b/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/impl/IconaRemoteHostProvider.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.icona.domainprovider.impl;
+
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Service;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.onosproject.core.CoreService;
+import org.onosproject.icona.domainmgr.api.DomainId;
+import org.onosproject.icona.domainprovider.api.host.DomainHostDescription;
+import org.onosproject.icona.domainprovider.api.host.IconaSBHostService;
+import org.onosproject.net.Host;
+import org.onosproject.net.HostId;
+import org.onosproject.net.host.HostProvider;
+import org.onosproject.net.host.HostProviderService;
+import org.onosproject.net.host.HostProviderRegistry;
+import org.onosproject.net.provider.ProviderId;
+import org.slf4j.Logger;
+
+import java.util.Set;
+
+import static org.slf4j.LoggerFactory.getLogger;
+import static org.onosproject.icona.domainprovider.impl.IconaRemoteDeviceProvider.PROVIDER_ID;
+import static org.onosproject.icona.domainprovider.impl.IconaRemoteDeviceProvider.PROVIDER_NAME;
+
+/**
+ * Exposes remote domain hosts to the core.
+ */
+@Component(immediate = true)
+@Service(IconaSBHostService.class)
+public class IconaRemoteHostProvider implements HostProvider, IconaSBHostService {
+
+ private final Logger log = getLogger(getClass());
+
+ private static final boolean REPLACE_IPS = true;
+ private static final boolean MERGE_IPS = false;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected CoreService coreService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected HostProviderRegistry hostProviderRegistry;
+
+ protected HostProviderService hostProviderService;
+
+ @Override
+ public ProviderId id() {
+ return PROVIDER_ID;
+ }
+
+ @Activate
+ public void activate() {
+ coreService.registerApplication(PROVIDER_NAME);
+ hostProviderService = hostProviderRegistry.register(this);
+ }
+
+ @Deactivate
+ public void deactivate() {
+ hostProviderRegistry.unregister(this);
+ }
+
+
+ /**
+ * Notify the core system that a new host is reachable through a domain device.
+ *
+ * @param domainHostDescription host description of the remote host
+ */
+ private void advertiseHost(DomainHostDescription domainHostDescription) {
+ HostId hostId = HostId.hostId(domainHostDescription.hwAddress(), domainHostDescription.vlan());
+ hostProviderService.hostDetected(hostId, domainHostDescription, REPLACE_IPS);
+ }
+
+ /**
+ * Remove a remote domain host.
+ *
+ * @param hostId id of the vanished host
+ */
+ private void removeHost(HostId hostId) {
+ hostProviderService.hostVanished(hostId);
+ }
+
+ // IconaSBHostService interface
+ @Override
+ public void addRemoteHosts(DomainId domainId, Set<DomainHostDescription> domainHostDescriptions) {
+ // TODO
+ }
+
+ @Override
+ public void replaceRemoteHosts(DomainId domainId, Set<DomainHostDescription> domainHostDescriptions) {
+ // TODO
+ }
+
+ @Override
+ public void removeRemoteHosts(DomainId domainId, Set<HostId> hostIds) {
+ // TODO
+ }
+
+ // HostProvider interface
+ @Override
+ public void triggerProbe(Host host) {
+ // TODO Auto-generated method stub
+ }
+}
\ No newline at end of file
diff --git a/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/impl/IconaRemoteLinkProvider.java b/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/impl/IconaRemoteLinkProvider.java
new file mode 100644
index 0000000..35485ac
--- /dev/null
+++ b/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/impl/IconaRemoteLinkProvider.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.icona.domainprovider.impl;
+
+import com.google.common.annotations.Beta;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Service;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.onosproject.core.CoreService;
+import org.onosproject.icona.domainmgr.api.DomainId;
+import org.onosproject.icona.domainprovider.api.link.InterLinkDescription;
+import org.onosproject.icona.domainprovider.api.link.IntraLinkDescription;
+import org.onosproject.icona.domainprovider.api.link.IconaSBLinkService;
+import org.onosproject.icona.domainprovider.api.link.LinkId;
+import org.onosproject.net.Link;
+import org.onosproject.net.link.LinkProvider;
+import org.onosproject.net.link.LinkProviderRegistry;
+import org.onosproject.net.link.LinkProviderService;
+import org.onosproject.net.provider.ProviderId;
+import org.slf4j.Logger;
+
+import static org.slf4j.LoggerFactory.getLogger;
+import static org.onosproject.icona.domainprovider.impl.IconaRemoteDeviceProvider.PROVIDER_ID;
+import static org.onosproject.icona.domainprovider.impl.IconaRemoteDeviceProvider.PROVIDER_NAME;
+
+/**
+ * Exposes remote domain links to the core.
+ */
+@Component(immediate = true)
+@Service(IconaSBLinkService.class)
+public class IconaRemoteLinkProvider implements LinkProvider, IconaSBLinkService {
+
+ private final Logger log = getLogger(getClass());
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected CoreService coreService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected LinkProviderRegistry linkProviderRegistry;
+
+ protected LinkProviderService linkProviderService;
+
+ @Override
+ public ProviderId id() {
+ return PROVIDER_ID;
+ }
+
+ @Activate
+ public void activate() {
+ coreService.registerApplication(PROVIDER_NAME);
+ linkProviderService = linkProviderRegistry.register(this);
+ }
+
+ @Deactivate
+ public void deactivate() {
+ linkProviderRegistry.unregister(this);
+ }
+
+ // IconaSBLinkService
+ @Override
+ public void addRemoteLink(IntraLinkDescription link) {
+ // TODO
+ }
+
+ @Override
+ public void addInterLink(DomainId domainId, InterLinkDescription link) {
+ }
+
+ @Override
+ public void updateRemoteLinkState(DomainId domainId, LinkId id, Link.State state) {
+ // TODO
+ }
+
+ @Override
+ @Beta
+ public void updateRemoteLinkMetric(DomainId domainId, LinkId id, int metric) {
+ // TODO
+ // the metric is meaningful only among links within the same domain and only if there is trust between domains
+ }
+
+ @Override
+ public void removeRemoteLink(DomainId domainId, LinkId id) {
+ // TODO
+ }
+}
diff --git a/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/impl/IconaTopologyManager.java b/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/impl/IconaTopologyManager.java
new file mode 100644
index 0000000..4050a2e
--- /dev/null
+++ b/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/impl/IconaTopologyManager.java
@@ -0,0 +1,336 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.icona.domainprovider.impl;
+
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Service;
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.apache.felix.scr.annotations.Reference;
+import org.onlab.packet.Ip4Prefix;
+import org.onlab.packet.MacAddress;
+import org.onlab.packet.VlanId;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreService;
+import org.onosproject.icona.domainmgr.api.DomainId;
+import org.onosproject.icona.domainprovider.api.DomainTopology;
+import org.onosproject.icona.domainprovider.api.DefaultDomainTopology;
+import org.onosproject.icona.domainprovider.api.IconaSBListener;
+import org.onosproject.icona.domainprovider.api.IconaSBListenerService;
+import org.onosproject.icona.domainprovider.api.device.DefaultDomainDevice;
+import org.onosproject.icona.domainprovider.api.device.DomainDevice;
+import org.onosproject.icona.domainprovider.api.host.DefaultDomainHostDescription;
+import org.onosproject.icona.domainprovider.api.host.DomainHostDescription;
+import org.onosproject.icona.domainprovider.api.link.IntraLinkDescription;
+import org.onosproject.icona.domainprovider.impl.config.IconaConfig;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.HostLocation;
+import org.onosproject.net.SparseAnnotations;
+import org.onosproject.net.DefaultAnnotations;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.config.ConfigFactory;
+import org.onosproject.net.config.NetworkConfigRegistry;
+import org.onosproject.net.config.NetworkConfigService;
+import org.onosproject.net.config.NetworkConfigEvent;
+import org.onosproject.net.config.NetworkConfigListener;
+import org.onosproject.net.device.DefaultPortDescription;
+import org.onosproject.net.device.PortDescription;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.device.DeviceListener;
+import org.onosproject.net.device.DeviceEvent;
+import org.onosproject.net.host.HostEvent;
+import org.onosproject.net.host.HostListener;
+import org.onosproject.net.host.HostService;
+import org.onosproject.net.link.LinkEvent;
+import org.onosproject.net.link.LinkListener;
+import org.onosproject.net.link.LinkService;
+import org.slf4j.Logger;
+
+import java.util.Map;
+import java.util.Set;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.concurrent.CopyOnWriteArraySet;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.atomic.AtomicLong;
+
+import static java.util.concurrent.Executors.newFixedThreadPool;
+import static org.onosproject.icona.domainprovider.impl.IconaRemoteDeviceProvider.PROVIDER_NAME;
+import static org.onosproject.icona.domainprovider.impl.config.IconaConfig.DomainConfig;
+import static org.onlab.util.Tools.groupedThreads;
+import static org.onosproject.net.Port.Type.VIRTUAL;
+import static org.slf4j.LoggerFactory.getLogger;
+import static org.onosproject.net.config.basics.SubjectFactories.APP_SUBJECT_FACTORY;
+
+/**
+ * Component in charge of sending the local topology abstraction to the remote clusters
+ * through the southbound listeners. It also listens for relevant local topology events.
+ */
+@Component(immediate = true)
+@Service
+public class IconaTopologyManager implements IconaSBListenerService {
+ private static final String DEVICE_ID = "deviceId";
+ private static final String DOMAIN_ID = "domainId";
+ protected static final String INTER_LINK_ID = "interlinkId";
+
+ private static DomainId localDomainId;
+
+ private final Logger log = getLogger(IconaTopologyManager.class);
+
+ private ApplicationId appId;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected NetworkConfigRegistry configRegistry;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected NetworkConfigService configService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected CoreService coreService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected DeviceService deviceService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected HostService hostService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected LinkService linkService;
+
+ private final ConfigFactory configFactory =
+ new ConfigFactory(APP_SUBJECT_FACTORY, IconaConfig.class, "icona") {
+ @Override
+ public IconaConfig createConfig() {
+ return new IconaConfig();
+ }
+ };
+
+ private final ExecutorService eventExecutor =
+ newFixedThreadPool(3, groupedThreads("onos/icona-sb-manager", "event-handler-%d"));
+
+ private Set<DomainConfig> domainConfigs = Sets.newConcurrentHashSet();
+ private Set<IconaSBListener> sbListeners = new CopyOnWriteArraySet<>();
+
+ private final NetworkConfigListener configListener = new InternalConfigListener();
+ private final LocalDeviceListener deviceListener = new LocalDeviceListener();
+ private final LocalHostListener hostListener = new LocalHostListener();
+ private final LocalLinkListener linkListener = new LocalLinkListener();
+
+ @Activate
+ public void activate() {
+ appId = coreService.registerApplication(PROVIDER_NAME);
+ configRegistry.registerConfigFactory(configFactory);
+ configService.addListener(configListener);
+
+ deviceService.addListener(deviceListener);
+ linkService.addListener(linkListener);
+ hostService.addListener(hostListener);
+ }
+
+ @Deactivate
+ public void deactivate() {
+ eventExecutor.shutdown();
+ deviceService.removeListener(deviceListener);
+ linkService.removeListener(linkListener);
+ hostService.removeListener(hostListener);
+
+ configService.removeListener(configListener);
+ configRegistry.unregisterConfigFactory(configFactory);
+ }
+
+ @Override
+ public void addListener(IconaSBListener sbListener) {
+ sbListeners.add(sbListener);
+ }
+
+ @Override
+ public void removeListener(IconaSBListener sbListener) {
+ sbListeners.remove(sbListener);
+ }
+
+ private class LocalDeviceListener implements DeviceListener {
+
+ @Override
+ public void event(DeviceEvent event) {
+ switch (event.type()) {
+ case DEVICE_ADDED:
+ // TODO: check config policy and the impact on the local topology exposed to the peers
+ break;
+ case DEVICE_REMOVED:
+ // TODO: check config policy and the impact on the local topology exposed to the peers
+ break;
+ case DEVICE_SUSPENDED:
+ // TODO: check config policy and the impact on the local topology exposed to the peers
+ break;
+ case PORT_REMOVED:
+ // TODO: check config policy and the impact on the local topology exposed to the peers
+ break;
+ case PORT_ADDED:
+ // TODO: check config policy and the impact on the local topology exposed to the peers
+ break;
+ default:
+ }
+ }
+ }
+
+ private class LocalHostListener implements HostListener {
+ @Override
+ public void event(HostEvent event) {
+ switch (event.type()) {
+ case HOST_ADDED:
+ // TODO: check config policy and the impact on the local topology exposed to the peers
+ break;
+ case HOST_REMOVED:
+ // TODO: check config policy and the impact on the local topology exposed to the peers
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ private class LocalLinkListener implements LinkListener {
+
+ @Override
+ public void event(LinkEvent event) {
+ switch (event.type()) {
+ case LINK_ADDED:
+ // TODO: check config policy and the impact on the local topology exposed to the peers
+ break;
+ case LINK_REMOVED:
+ // TODO: check config policy and the impact on the local topology exposed to the peers
+ break;
+ case LINK_UPDATED:
+ // TODO: check config policy and the impact on the local topology exposed to the peers
+ default:
+ }
+ }
+ }
+
+ private void buildFullMesh(DomainConfig domainConfig) {
+
+ }
+ // We will add a parameter to this method to process only the subsets of domains
+ // whose TopologyConfig.Type is equal to BIG_SWITCH
+ private void buildBigSwitch(String bigSwitchPrefixId) {
+ Map<DomainId, DomainTopology> topologyMap = Maps.newHashMap();
+ domainConfigs.forEach(domainConfig -> {
+ log.info("Building big switch topology for domain {}", domainConfig.peerId().id());
+ DeviceId bigSwitchId = DeviceId.deviceId(bigSwitchPrefixId + localDomainId);
+ AtomicLong portCounter = new AtomicLong(0);
+
+ List<PortDescription> allPorts = new ArrayList<>();
+
+ domainConfig.interLinkConnectPointMap()
+ .forEach((interLinkId, pair) -> {
+ SparseAnnotations annotations = DefaultAnnotations.builder()
+ .set(DEVICE_ID, bigSwitchId.toString())
+ .set(DOMAIN_ID, localDomainId.id())
+ .set(INTER_LINK_ID, interLinkId.id())
+ .build();
+ allPorts.add(
+ new DefaultPortDescription(
+ PortNumber.portNumber(portCounter.get()),
+ true,
+ VIRTUAL,
+ 100, // port speed is to be configured
+ annotations));
+
+ portCounter.getAndIncrement();
+ });
+
+ Set<DomainHostDescription> domainHostDescriptions = new HashSet<>();
+ hostService.getHosts().forEach(host ->
+ domainConfig.topologyConfig()
+ .endPointIds().forEach(mac -> {
+ if (host.mac().equals(MacAddress.valueOf(mac))) {
+ DefaultDomainHostDescription domainHost = new DefaultDomainHostDescription(
+ localDomainId,
+ MacAddress.valueOf(mac),
+ VlanId.NONE,
+ new HostLocation(bigSwitchId,
+ PortNumber.portNumber(portCounter.get()), 0),
+ host.ipAddresses(),
+ new HashSet<Ip4Prefix>()); // TODO: ip4/6prefixes from config
+ domainHostDescriptions.add(domainHost);
+ log.info("host {} added as domainHost for domain {}", host.id(), domainConfig.peerId());
+ portCounter.getAndIncrement();
+ }
+ })
+ );
+
+ domainHostDescriptions.forEach(domainHost ->
+ allPorts.add(new DefaultPortDescription(domainHost.location().port(),
+ true, VIRTUAL, 100)));
+ DomainDevice bigSwitch =
+ new DefaultDomainDevice(bigSwitchId, localDomainId, allPorts);
+ Set<DomainDevice> domainDevices = Sets.newHashSet();
+ domainDevices.add(bigSwitch);
+ Set<IntraLinkDescription> interLinks = Sets.newHashSet();
+ DomainTopology domainTopology = new DefaultDomainTopology(localDomainId, domainDevices,
+ interLinks, domainHostDescriptions);
+ topologyMap.put(domainConfig.peerId(), domainTopology);
+ });
+
+ log.info("Calling southbound listeners to expose the local topology...");
+ // listeners will executes network tasks,
+ // load balancing is handled via the leadership service
+ sbListeners.forEach(listener ->
+ listener.configTopology(topologyMap));
+ }
+
+ private void readConfig() {
+ log.info("List of domains and inter-link connect points received");
+
+ IconaConfig iconaConfig =
+ configRegistry.getConfig(appId, IconaConfig.class);
+
+ localDomainId = iconaConfig.getLocalId();
+
+ domainConfigs.addAll(
+ iconaConfig.getPeersConfig());
+
+ // TODO: different topology for different TopologyConfig.Type values
+ buildBigSwitch(iconaConfig.getBigSwitchPrefixId());
+ }
+
+ private class InternalConfigListener implements NetworkConfigListener {
+
+ @Override
+ public void event(NetworkConfigEvent event) {
+ if (!event.configClass().equals(IconaConfig.class)) {
+ return;
+ }
+ switch (event.type()) {
+ case CONFIG_ADDED:
+ log.info("Network configuration added");
+ eventExecutor.execute(IconaTopologyManager.this::readConfig);
+ break;
+ case CONFIG_UPDATED:
+ log.info("Network configuration updated");
+ eventExecutor.execute(IconaTopologyManager.this::readConfig);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/impl/config/IconaConfig.java b/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/impl/config/IconaConfig.java
new file mode 100644
index 0000000..e9ee7f6
--- /dev/null
+++ b/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/impl/config/IconaConfig.java
@@ -0,0 +1,191 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.icona.domainprovider.impl.config;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+import org.apache.commons.lang3.tuple.Pair;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.icona.domainmgr.api.DomainId;
+import org.onosproject.icona.domainprovider.api.link.LinkId;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Link;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.config.Config;
+import org.slf4j.Logger;
+
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.Set;
+
+import static org.onosproject.icona.domainprovider.impl.config.TopologyConfig.Type.BIG_SWITCH;
+import static org.onosproject.icona.domainprovider.impl.config.TopologyConfig.Type.FULL_MESH;
+import static org.onosproject.net.Link.Type.*;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Provider configuration class.
+ * Refer to tools/sample_configs/multidomain-config.json, under
+ * "org.onosproject.icona.domainprovider" for a sample configuration
+ */
+public class IconaConfig extends Config<ApplicationId> {
+
+ private final Logger log = getLogger(getClass());
+
+ private static final String LOCAL_DOMAIN_ID = "localDomainId";
+ private static final String BIG_SWITCH_PREFIX_ID = "bigSwitchPrefixId";
+ private static final String PEERS = "peers";
+ private static final String DOMAIN_ID = "domainId";
+
+ private static final String DOMAIN_INTER_LINKS = "interlinks";
+ private static final String INTER_LINK_DEVICE_ID = "deviceId";
+ private static final String INTER_LINK_DEVICE_PORTNUM = "portNumber";
+ private static final String INTER_LINK_ID = "interlinkId";
+ private static final String INTER_LINK_TYPE = "interlinkType";
+
+ private static final String TOPOLOGY = "topology";
+ private static final String END_POINTS = "endPointIds";
+
+ /**
+ * Gets local domain identifier from configuration.
+ *
+ * @return string identifier
+ */
+ public DomainId getLocalId() {
+ return DomainId.domainId(object.get(LOCAL_DOMAIN_ID).asText());
+ }
+
+ /**
+ * Gets the ID of the local big switch abstraction.
+ *
+ * @return big switch identifier
+ */
+ public String getBigSwitchPrefixId() {
+ return object.get(BIG_SWITCH_PREFIX_ID).asText();
+ }
+
+ /**
+ * Parses the list of peers from the configuration json object.
+ *
+ * @return set of domain configuration objects
+ */
+ public Set<DomainConfig> getPeersConfig() {
+
+ Set<DomainConfig> peers = Sets.newHashSet();
+
+ JsonNode peerNodes = object.get(PEERS);
+
+ peerNodes.forEach(peerNode -> {
+
+ String id = peerNode.path(DOMAIN_ID).asText();
+
+ DomainId domainId = new DomainId(id);
+
+ JsonNode cpsNode = peerNode.path(DOMAIN_INTER_LINKS);
+
+ Map<LinkId, Pair<Link.Type, ConnectPoint>> interLinkConnectPointMap = Maps.newHashMap();
+
+ cpsNode.forEach(il -> {
+ // real internal deviceId where the inter-link is attached
+ DeviceId deviceId = DeviceId.deviceId(il.path(INTER_LINK_DEVICE_ID).asText());
+ // TODO: LinkDiscovery must be disabled for this port
+ PortNumber portNumber = PortNumber.portNumber(il.path(INTER_LINK_DEVICE_PORTNUM).asText());
+ String ilid = il.path(INTER_LINK_ID).asText();
+ String type = il.path(INTER_LINK_TYPE).asText();
+ Link.Type ilType;
+ switch (type) {
+ case "indirect":
+ ilType = INDIRECT;
+ break;
+ case "virtual":
+ ilType = VIRTUAL;
+ break;
+ case "optical":
+ ilType = OPTICAL;
+ break;
+ case "tunnel":
+ ilType = TUNNEL;
+ break;
+ case "direct":
+ ilType = DIRECT;
+ break;
+ default:
+ ilType = INDIRECT;
+ }
+ interLinkConnectPointMap.put(LinkId.linkId(ilid),
+ Pair.of(ilType, new ConnectPoint(deviceId, portNumber)));
+
+ });
+
+ JsonNode topologyNode = peerNode.path(TOPOLOGY);
+ TopologyConfig.Type type;
+ switch (topologyNode.path("type")
+ .asText()) {
+ case "bigSwitch":
+ type = BIG_SWITCH;
+ break;
+ case "fullMesh":
+ type = FULL_MESH;
+ break;
+ default:
+ type = TopologyConfig.Type.BIG_SWITCH;
+ }
+ ArrayList<String> endPointIds = new ArrayList<>();
+ topologyNode.path(END_POINTS).forEach(
+ endPointId -> endPointIds.add(endPointId.asText())
+ );
+ TopologyConfig topologyConfig = new TopologyConfig(type, endPointIds);
+
+ peers.add(new DomainConfig(domainId, interLinkConnectPointMap, topologyConfig));
+ });
+
+ return peers;
+ }
+
+ /**
+ * Domain configuration class.
+ */
+ public static class DomainConfig {
+
+ private final DomainId domainId;
+ private final Map<LinkId, Pair<Link.Type, ConnectPoint>> interLinkConnectPointMap;
+ private final TopologyConfig topologyConfig;
+
+ public DomainConfig(DomainId domainId, Map<LinkId, Pair<Link.Type, ConnectPoint>> interLinkConnectPointMap,
+ TopologyConfig topologyConfig) {
+ this.domainId = checkNotNull(domainId);
+ this.interLinkConnectPointMap = interLinkConnectPointMap;
+ this.topologyConfig = topologyConfig;
+ }
+
+ public DomainId peerId() {
+ return domainId;
+ }
+
+ public Map<LinkId, Pair<Link.Type, ConnectPoint>> interLinkConnectPointMap() {
+ return interLinkConnectPointMap;
+ }
+
+ public TopologyConfig topologyConfig() {
+ return topologyConfig;
+ }
+
+ }
+}
diff --git a/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/impl/config/TopologyConfig.java b/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/impl/config/TopologyConfig.java
new file mode 100644
index 0000000..31f4274
--- /dev/null
+++ b/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/impl/config/TopologyConfig.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.icona.domainprovider.impl.config;
+
+
+import java.util.List;
+
+/**
+ * Topology config policy class.
+ * Depending on the topology abstraction type, the end-points will reside on some virtual devices,
+ * currently only BIG_SWITCH (one device) and FULL_MESH (as many devices as those where the end-points, or hosts,
+ * are attached to) are supported.
+ * The concept of end-points is still to be defined, currently it is a mac address of a NIC.
+ */
+public class TopologyConfig {
+
+ /**
+ * Type of topology exposed to/from a domain.
+ */
+ public enum Type {
+ BIG_SWITCH,
+ FULL_MESH
+ }
+
+ private Type type;
+ private List<String> endPointIds;
+
+ /**
+ * Creates a topology configuration object using the supplied information.
+ *
+ * @param type topology type
+ * @param endPointIds list of end-point mac addresses
+ */
+ public TopologyConfig(Type type, List<String> endPointIds) {
+ this.type = type;
+ this.endPointIds = endPointIds;
+ }
+
+ /**
+ * Returns the type of topology abstraction for a specific domain.
+ */
+ public Type type() {
+ return type;
+ }
+
+ /**
+ * Returns the list of end points that are exposed to a specific domain.
+ *
+ * @return list of endpoints
+ */
+ public List<String> endPointIds() {
+ return endPointIds;
+ }
+
+}
diff --git a/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/impl/config/package-info.java b/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/impl/config/package-info.java
new file mode 100644
index 0000000..6d8ec1c
--- /dev/null
+++ b/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/impl/config/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Configuration package.
+ */
+package org.onosproject.icona.domainprovider.impl.config;
\ No newline at end of file
diff --git a/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/impl/package-info.java b/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/impl/package-info.java
new file mode 100644
index 0000000..693c2ec
--- /dev/null
+++ b/icona/domainprovider/src/main/java/org/onosproject/icona/domainprovider/impl/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Icona domainprovider implementation.
+ */
+package org.onosproject.icona.domainprovider.impl;
\ No newline at end of file
diff --git a/icona/pom.xml b/icona/pom.xml
new file mode 100644
index 0000000..f309754
--- /dev/null
+++ b/icona/pom.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ ~ Copyright 2016-present Open Networking Laboratory
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-app-samples</artifactId>
+ <version>1.7.0-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>onos-icona</artifactId>
+ <version>1.7.0-SNAPSHOT</version>
+ <packaging>pom</packaging>
+
+ <modules>
+ <module>app</module>
+ <module>domainmgr</module>
+ <module>domainprovider</module>
+ </modules>
+</project>
\ No newline at end of file
diff --git a/icona/tools/sample_configs/multidomain-config.json b/icona/tools/sample_configs/multidomain-config.json
new file mode 100644
index 0000000..537abb8
--- /dev/null
+++ b/icona/tools/sample_configs/multidomain-config.json
@@ -0,0 +1,31 @@
+{
+ "apps" : {
+ "org.onosproject.icona.domainprovider" : {
+ "icona" : {
+ "localDomainId" : "polito-sdn",
+ "bigSwitchPrefixId" : "domain:dev0000",
+ "peers" : [
+ {
+ "domainId" : "polito-turin",
+ "interlinks" : [
+ {
+ "deviceId" : "of:0000000000000001",
+ "portNumber" : "2",
+ "interlinkId" : "il:00000001",
+ "interlinkType" : "tunnel"
+ }
+ ],
+ "topology" :
+ {
+ "type" : "bigSwitch",
+ "endpointIds" : [
+ "aa:ee:bb:cc:dd:ff",
+ "aa:ee:bb:cc:dd:fe"
+ ]
+ }
+ }
+ ]
+ }
+ }
+ }
+}