ONOS-6886 Move interface classes from incubator to core
Change-Id: Iaae4d98279e4b77fc3f0b5a63d547921f93aeb46
diff --git a/core/api/src/main/java/org/onosproject/net/intf/Interface.java b/core/api/src/main/java/org/onosproject/net/intf/Interface.java
new file mode 100644
index 0000000..9c059e4
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/intf/Interface.java
@@ -0,0 +1,206 @@
+/*
+ * Copyright 2015-present Open Networking Foundation
+ *
+ * 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.net.intf;
+
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+
+import org.onlab.packet.MacAddress;
+import org.onlab.packet.VlanId;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.host.InterfaceIpAddress;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Lists;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * An Interface maps network configuration information (such as addresses and
+ * vlans) to a port in the network.
+ */
+
+public class Interface {
+ public static final String NO_INTERFACE_NAME = "";
+
+ private final String name;
+ private final ConnectPoint connectPoint;
+ private final List<InterfaceIpAddress> ipAddresses;
+ private final MacAddress macAddress;
+ // TODO: Deprecate this due to ambiguity
+ private final VlanId vlan;
+ private final VlanId vlanUntagged;
+ private final Set<VlanId> vlanTagged;
+ private final VlanId vlanNative;
+
+ /**
+ * Creates new Interface with the provided configuration.
+ *
+ * @param name name of the interface
+ * @param connectPoint the connect point this interface maps to
+ * @param ipAddresses list of IP addresses
+ * @param macAddress MAC address
+ * @param vlan VLAN ID
+ */
+ public Interface(String name, ConnectPoint connectPoint,
+ List<InterfaceIpAddress> ipAddresses,
+ MacAddress macAddress, VlanId vlan) {
+ this(name, connectPoint, ipAddresses, macAddress, vlan, null, null, null);
+ }
+
+ /**
+ * Creates new Interface with the provided configuration.
+ *
+ * @param name name of the interface
+ * @param connectPoint the connect point this interface maps to
+ * @param ipAddresses list of IP addresses
+ * @param macAddress MAC address
+ * @param vlan VLAN ID
+ * @param vlanUntagged untagged VLAN.
+ * Cannot be used with vlanTagged or vlanNative.
+ * @param vlanTagged tagged VLANs.
+ * Cannot be used with vlanUntagged.
+ * @param vlanNative native vLAN. Optional.
+ * Can only be used when vlanTagged is specified. Cannot be used with vlanUntagged.
+ */
+ public Interface(String name, ConnectPoint connectPoint,
+ List<InterfaceIpAddress> ipAddresses,
+ MacAddress macAddress, VlanId vlan,
+ VlanId vlanUntagged, Set<VlanId> vlanTagged, VlanId vlanNative) {
+ this.name = name == null ? NO_INTERFACE_NAME : name;
+ this.connectPoint = checkNotNull(connectPoint);
+ this.ipAddresses = ipAddresses == null ? Lists.newArrayList() : ipAddresses;
+ this.macAddress = macAddress == null ? MacAddress.NONE : macAddress;
+ this.vlan = vlan == null ? VlanId.NONE : vlan;
+ this.vlanUntagged = vlanUntagged == null ? VlanId.NONE : vlanUntagged;
+ this.vlanTagged = vlanTagged == null ? ImmutableSet.of() : ImmutableSet.copyOf(vlanTagged);
+ this.vlanNative = vlanNative == null ? VlanId.NONE : vlanNative;
+ }
+
+ /**
+ * Retrieves the name of the interface.
+ *
+ * @return name
+ */
+ public String name() {
+ return name;
+ }
+
+ /**
+ * Retrieves the connection point that this interface maps to.
+ *
+ * @return the connection point
+ */
+ public ConnectPoint connectPoint() {
+ return connectPoint;
+ }
+
+ /**
+ * Retrieves a list of IP addresses that are assigned to the interface in
+ * the order that they were configured.
+ *
+ * @return list of IP addresses
+ */
+ public List<InterfaceIpAddress> ipAddressesList() {
+ return ipAddresses;
+ }
+
+ /**
+ * Retrieves the MAC address that is assigned to the interface.
+ *
+ * @return the MAC address
+ */
+ public MacAddress mac() {
+ return macAddress;
+ }
+
+ /**
+ * Retrieves the VLAN ID that is assigned to the interface.
+ *
+ * @return the VLAN ID
+ */
+ public VlanId vlan() {
+ return vlan;
+ }
+
+ /**
+ * Retrieves the VLAN ID that is assigned to untagged packets.
+ *
+ * @return the VLAN ID
+ */
+ public VlanId vlanUntagged() {
+ return vlanUntagged;
+ }
+
+ /**
+ * Retrieves the set of VLAN IDs that are allowed on this interface.
+ *
+ * @return the VLAN ID
+ */
+ public Set<VlanId> vlanTagged() {
+ return vlanTagged;
+ }
+
+ /**
+ * Retrieves the VLAN ID that is assigned to untagged packets on this
+ * tagged interface.
+ *
+ * @return the VLAN ID
+ */
+ public VlanId vlanNative() {
+ return vlanNative;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (!(other instanceof Interface)) {
+ return false;
+ }
+
+ Interface otherInterface = (Interface) other;
+
+ return Objects.equals(name, otherInterface.name) &&
+ Objects.equals(connectPoint, otherInterface.connectPoint) &&
+ Objects.equals(ipAddresses, otherInterface.ipAddresses) &&
+ Objects.equals(macAddress, otherInterface.macAddress) &&
+ Objects.equals(vlan, otherInterface.vlan) &&
+ Objects.equals(vlanUntagged, otherInterface.vlanUntagged) &&
+ Objects.equals(vlanTagged, otherInterface.vlanTagged) &&
+ Objects.equals(vlanNative, otherInterface.vlanNative);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(connectPoint, name, ipAddresses, macAddress, vlan,
+ vlanUntagged, vlanTagged, vlanNative);
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass())
+ .add("name", name)
+ .add("connectPoint", connectPoint)
+ .add("ipAddresses", ipAddresses)
+ .add("macAddress", macAddress)
+ .add("vlan", vlan)
+ .add("vlanUntagged", vlanUntagged)
+ .add("vlanTagged", vlanTagged)
+ .add("vlanNative", vlanNative)
+ .toString();
+ }
+}
diff --git a/core/api/src/main/java/org/onosproject/net/intf/InterfaceAdminService.java b/core/api/src/main/java/org/onosproject/net/intf/InterfaceAdminService.java
new file mode 100644
index 0000000..c276c96
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/intf/InterfaceAdminService.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2015-present Open Networking Foundation
+ *
+ * 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.net.intf;
+
+import org.onosproject.net.ConnectPoint;
+
+/**
+ * Provides a means to modify the interfaces configuration.
+ */
+public interface InterfaceAdminService {
+
+ /**
+ * Adds a new interface configuration to the system.
+ *
+ * @param intf interface to add
+ */
+ void add(Interface intf);
+
+ /**
+ * Removes an interface configuration from the system.
+ *
+ * @param connectPoint connect point of the interface
+ * @param name name of the interface
+ * @return the result of removal
+ */
+ boolean remove(ConnectPoint connectPoint, String name);
+}
diff --git a/core/api/src/main/java/org/onosproject/net/intf/InterfaceEvent.java b/core/api/src/main/java/org/onosproject/net/intf/InterfaceEvent.java
new file mode 100644
index 0000000..1e7d9ba
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/intf/InterfaceEvent.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2015-present Open Networking Foundation
+ *
+ * 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.net.intf;
+
+import org.joda.time.LocalDateTime;
+import org.onosproject.event.AbstractEvent;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+/**
+ * Describes an interface event.
+ */
+public class InterfaceEvent extends AbstractEvent<InterfaceEvent.Type, Interface> {
+
+ private final Interface prevSubject;
+
+ public enum Type {
+ /**
+ * Indicates a new interface has been added.
+ */
+ INTERFACE_ADDED,
+
+ /**
+ * Indicates an interface has been updated.
+ */
+ INTERFACE_UPDATED,
+
+ /**
+ * Indicates an interface has been removed.
+ */
+ INTERFACE_REMOVED
+ }
+
+ /**
+ * Creates an interface event with type and subject.
+ *
+ * @param type event type
+ * @param subject subject interface
+ */
+ public InterfaceEvent(Type type, Interface subject) {
+ this(type, subject, null);
+ }
+
+ /**
+ * Creates an interface event with type, subject and time of event.
+ *
+ * @param type event type
+ * @param subject subject interface
+ * @param time time of event
+ */
+ public InterfaceEvent(Type type, Interface subject, long time) {
+ this(type, subject, null, time);
+ }
+
+ /**
+ * Creates an interface event with type, subject and previous subject.
+ *
+ * @param type event type
+ * @param subject subject interface
+ * @param prevSubject previous interface subject
+ */
+ public InterfaceEvent(Type type, Interface subject, Interface prevSubject) {
+ super(type, subject);
+ this.prevSubject = prevSubject;
+ }
+
+ /**
+ * Creates an interface event with type, subject, previous subject and time.
+ *
+ * @param type event type
+ * @param subject subject interface
+ * @param prevSubject previous interface subject
+ * @param time time of event
+ */
+ public InterfaceEvent(Type type, Interface subject, Interface prevSubject, long time) {
+ super(type, subject, time);
+ this.prevSubject = prevSubject;
+ }
+
+ /**
+ * Returns the previous interface subject.
+ *
+ * @return previous subject of interface or null if the event is not interface specific.
+ */
+ public Interface prevSubject() {
+ return prevSubject;
+ }
+
+ @Override
+ public String toString() {
+ if (prevSubject == null) {
+ return super.toString();
+ }
+ return toStringHelper(this)
+ .add("time", new LocalDateTime(time()))
+ .add("type", type())
+ .add("subject", subject())
+ .add("prevSubject", prevSubject)
+ .toString();
+ }
+}
diff --git a/core/api/src/main/java/org/onosproject/net/intf/InterfaceListener.java b/core/api/src/main/java/org/onosproject/net/intf/InterfaceListener.java
new file mode 100644
index 0000000..878b52d
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/intf/InterfaceListener.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2015-present Open Networking Foundation
+ *
+ * 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.net.intf;
+
+import org.onosproject.event.EventListener;
+
+/**
+ * Listener for interface events.
+ */
+public interface InterfaceListener extends EventListener<InterfaceEvent> {
+}
diff --git a/core/api/src/main/java/org/onosproject/net/intf/InterfaceService.java b/core/api/src/main/java/org/onosproject/net/intf/InterfaceService.java
new file mode 100644
index 0000000..3e2f742
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/intf/InterfaceService.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2015-present Open Networking Foundation
+ *
+ * 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.net.intf;
+
+import java.util.Set;
+
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.VlanId;
+import org.onosproject.event.ListenerService;
+import org.onosproject.net.ConnectPoint;
+
+/**
+ * Service for interacting with interfaces.
+ */
+
+public interface InterfaceService
+ extends ListenerService<InterfaceEvent, InterfaceListener> {
+
+ /**
+ * Returns the set of all interfaces in the system.
+ *
+ * @return set of interfaces
+ */
+ Set<Interface> getInterfaces();
+
+ /**
+ * Returns the interface with the given name.
+ *
+ * @param connectPoint connect point of the interface
+ * @param name name of the interface
+ * @return interface if it exists, otherwise null
+ */
+ Interface getInterfaceByName(ConnectPoint connectPoint, String name);
+
+ /**
+ * Returns the set of interfaces configured on the given port.
+ *
+ * @param port connect point
+ * @return set of interfaces
+ */
+ Set<Interface> getInterfacesByPort(ConnectPoint port);
+
+ /**
+ * Returns the set of interfaces with the given IP address.
+ *
+ * @param ip IP address
+ * @return set of interfaces
+ */
+ Set<Interface> getInterfacesByIp(IpAddress ip);
+
+ /**
+ * Returns the set of interfaces in the given VLAN.
+ *
+ * @param vlan VLAN ID of the interfaces
+ * @return set of interfaces
+ */
+ Set<Interface> getInterfacesByVlan(VlanId vlan);
+
+ /**
+ * Returns an interface that has an address that is in the same subnet as
+ * the given IP address.
+ *
+ * @param ip IP address to find matching subnet interface for
+ * @return interface
+ */
+ Interface getMatchingInterface(IpAddress ip);
+
+ /**
+ * Returns all interfaces that have an address that is in the same
+ * subnet as the given IP address.
+ *
+ * @param ip IP address to find matching subnet interface for
+ * @return a set of interfaces
+ */
+ Set<Interface> getMatchingInterfaces(IpAddress ip);
+}
diff --git a/core/api/src/main/java/org/onosproject/net/intf/package-info.java b/core/api/src/main/java/org/onosproject/net/intf/package-info.java
new file mode 100644
index 0000000..6119e10
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/intf/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2015-present Open Networking Foundation
+ *
+ * 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.
+ */
+
+/**
+ * Interface Service.
+ */
+package org.onosproject.net.intf;
diff --git a/core/api/src/test/java/org/onosproject/net/intf/InterfaceServiceAdapter.java b/core/api/src/test/java/org/onosproject/net/intf/InterfaceServiceAdapter.java
new file mode 100644
index 0000000..8eb2214
--- /dev/null
+++ b/core/api/src/test/java/org/onosproject/net/intf/InterfaceServiceAdapter.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.net.intf;
+
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.VlanId;
+import org.onosproject.net.ConnectPoint;
+
+import java.util.Set;
+
+/**
+ * Interface service adapter class for tests.
+ */
+public class InterfaceServiceAdapter implements InterfaceService {
+ @Override
+ public Set<Interface> getInterfaces() {
+ return null;
+ }
+
+ @Override
+ public Interface getInterfaceByName(ConnectPoint connectPoint, String name) {
+ return null;
+ }
+
+ @Override
+ public Set<Interface> getInterfacesByPort(ConnectPoint port) {
+ return null;
+ }
+
+ @Override
+ public Set<Interface> getInterfacesByIp(IpAddress ip) {
+ return null;
+ }
+
+ @Override
+ public Set<Interface> getInterfacesByVlan(VlanId vlan) {
+ return null;
+ }
+
+ @Override
+ public Interface getMatchingInterface(IpAddress ip) {
+ return null;
+ }
+
+ @Override
+ public Set<Interface> getMatchingInterfaces(IpAddress ip) {
+ return null;
+ }
+
+ @Override
+ public void addListener(InterfaceListener listener) {
+
+ }
+
+ @Override
+ public void removeListener(InterfaceListener listener) {
+
+ }
+}
diff --git a/core/common/src/main/java/org/onosproject/utils/Comparators.java b/core/common/src/main/java/org/onosproject/utils/Comparators.java
index db91440..b5d843e 100644
--- a/core/common/src/main/java/org/onosproject/utils/Comparators.java
+++ b/core/common/src/main/java/org/onosproject/utils/Comparators.java
@@ -18,7 +18,7 @@
import org.onosproject.cluster.ControllerNode;
import org.onosproject.core.Application;
import org.onosproject.core.ApplicationId;
-import org.onosproject.incubator.net.intf.Interface;
+import org.onosproject.net.intf.Interface;
import org.onosproject.incubator.net.virtual.TenantId;
import org.onosproject.incubator.net.virtual.VirtualDevice;
import org.onosproject.incubator.net.virtual.VirtualNetwork;
diff --git a/core/common/src/test/java/org/onosproject/utils/ComparatorsTest.java b/core/common/src/test/java/org/onosproject/utils/ComparatorsTest.java
index f1b5cf2..f4b4dc2 100644
--- a/core/common/src/test/java/org/onosproject/utils/ComparatorsTest.java
+++ b/core/common/src/test/java/org/onosproject/utils/ComparatorsTest.java
@@ -69,7 +69,7 @@
import org.onosproject.core.DefaultApplication;
import org.onosproject.core.DefaultApplicationId;
import org.onosproject.core.GroupId;
-import org.onosproject.incubator.net.intf.Interface;
+import org.onosproject.net.intf.Interface;
import org.onosproject.incubator.net.virtual.DefaultVirtualDevice;
import org.onosproject.incubator.net.virtual.DefaultVirtualNetwork;
import org.onosproject.incubator.net.virtual.DefaultVirtualPort;
diff --git a/core/net/src/main/java/org/onosproject/net/host/impl/HostManager.java b/core/net/src/main/java/org/onosproject/net/host/impl/HostManager.java
index 183a0ba..cda9e04 100644
--- a/core/net/src/main/java/org/onosproject/net/host/impl/HostManager.java
+++ b/core/net/src/main/java/org/onosproject/net/host/impl/HostManager.java
@@ -29,7 +29,7 @@
import org.onlab.packet.VlanId;
import org.onlab.util.Tools;
import org.onosproject.cfg.ComponentConfigService;
-import org.onosproject.incubator.net.intf.InterfaceService;
+import org.onosproject.net.intf.InterfaceService;
import org.onosproject.net.HostLocation;
import org.onosproject.net.edge.EdgePortService;
import org.onosproject.net.provider.AbstractListenerProviderRegistry;
diff --git a/core/net/src/main/java/org/onosproject/net/host/impl/HostMonitor.java b/core/net/src/main/java/org/onosproject/net/host/impl/HostMonitor.java
index 52829ba..950bedd 100644
--- a/core/net/src/main/java/org/onosproject/net/host/impl/HostMonitor.java
+++ b/core/net/src/main/java/org/onosproject/net/host/impl/HostMonitor.java
@@ -23,7 +23,7 @@
import org.onlab.packet.VlanId;
import org.onlab.packet.ndp.NeighborSolicitation;
import org.onlab.util.SharedScheduledExecutors;
-import org.onosproject.incubator.net.intf.InterfaceService;
+import org.onosproject.net.intf.InterfaceService;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.Host;
import org.onosproject.net.edge.EdgePortService;
diff --git a/core/net/src/main/java/org/onosproject/net/intf/impl/InterfaceManager.java b/core/net/src/main/java/org/onosproject/net/intf/impl/InterfaceManager.java
new file mode 100644
index 0000000..5693db5
--- /dev/null
+++ b/core/net/src/main/java/org/onosproject/net/intf/impl/InterfaceManager.java
@@ -0,0 +1,267 @@
+/*
+ * Copyright 2015-present Open Networking Foundation
+ *
+ * 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.net.intf.impl;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.apache.felix.scr.annotations.Service;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.VlanId;
+import org.onosproject.event.ListenerRegistry;
+import org.onosproject.incubator.net.config.basics.ConfigException;
+import org.onosproject.incubator.net.config.basics.InterfaceConfig;
+import org.onosproject.net.intf.Interface;
+import org.onosproject.net.intf.InterfaceAdminService;
+import org.onosproject.net.intf.InterfaceEvent;
+import org.onosproject.net.intf.InterfaceListener;
+import org.onosproject.net.intf.InterfaceService;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.config.NetworkConfigEvent;
+import org.onosproject.net.config.NetworkConfigListener;
+import org.onosproject.net.config.NetworkConfigService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.stream.Stream;
+
+import static java.util.stream.Collectors.collectingAndThen;
+import static java.util.stream.Collectors.toSet;
+
+/**
+ * Manages the inventory of interfaces in the system.
+ */
+@Service
+@Component(immediate = true)
+public class InterfaceManager extends ListenerRegistry<InterfaceEvent, InterfaceListener>
+ implements InterfaceService, InterfaceAdminService {
+
+ private final Logger log = LoggerFactory.getLogger(getClass());
+
+ private static final Class<ConnectPoint> SUBJECT_CLASS = ConnectPoint.class;
+ private static final Class<InterfaceConfig> CONFIG_CLASS = InterfaceConfig.class;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected NetworkConfigService configService;
+
+ private final InternalConfigListener listener = new InternalConfigListener();
+
+ private final Map<ConnectPoint, Set<Interface>> interfaces = Maps.newConcurrentMap();
+
+ @Activate
+ public void activate() {
+ configService.addListener(listener);
+
+ // TODO address concurrency issues here
+ for (ConnectPoint subject : configService.getSubjects(SUBJECT_CLASS, CONFIG_CLASS)) {
+ InterfaceConfig config = configService.getConfig(subject, CONFIG_CLASS);
+
+ if (config != null) {
+ updateInterfaces(config);
+ }
+ }
+
+ log.info("Started");
+ }
+
+ @Deactivate
+ public void deactivate() {
+ configService.removeListener(listener);
+
+ log.info("Stopped");
+ }
+
+ @Override
+ public Set<Interface> getInterfaces() {
+ return interfaces.values()
+ .stream()
+ .flatMap(set -> set.stream())
+ .collect(collectingAndThen(toSet(), ImmutableSet::copyOf));
+ }
+
+ @Override
+ public Interface getInterfaceByName(ConnectPoint connectPoint, String name) {
+ Optional<Interface> intf =
+ interfaces.getOrDefault(connectPoint, Collections.emptySet())
+ .stream()
+ .filter(i -> i.name().equals(name))
+ .findAny();
+
+ return intf.orElse(null);
+ }
+
+ @Override
+ public Set<Interface> getInterfacesByPort(ConnectPoint port) {
+ Set<Interface> intfs = interfaces.get(port);
+ if (intfs == null) {
+ return Collections.emptySet();
+ }
+ return ImmutableSet.copyOf(intfs);
+ }
+
+ @Override
+ public Set<Interface> getInterfacesByIp(IpAddress ip) {
+ return interfaces.values()
+ .stream()
+ .flatMap(Collection::stream)
+ .filter(intf -> intf.ipAddressesList()
+ .stream()
+ .anyMatch(ia -> ia.ipAddress().equals(ip)))
+ .collect(collectingAndThen(toSet(), ImmutableSet::copyOf));
+ }
+
+ @Override
+ public Interface getMatchingInterface(IpAddress ip) {
+ return getMatchingInterfacesStream(ip).findFirst().orElse(null);
+ }
+
+ @Override
+ public Set<Interface> getMatchingInterfaces(IpAddress ip) {
+ return getMatchingInterfacesStream(ip).collect(toSet());
+ }
+
+ private Stream<Interface> getMatchingInterfacesStream(IpAddress ip) {
+ return interfaces.values()
+ .stream()
+ .flatMap(Collection::stream)
+ .filter(intf -> intf.ipAddressesList()
+ .stream()
+ .anyMatch(intfIp -> intfIp.subnetAddress().contains(ip)));
+ }
+
+ @Override
+ public Set<Interface> getInterfacesByVlan(VlanId vlan) {
+ return interfaces.values()
+ .stream()
+ .flatMap(Collection::stream)
+ .filter(intf -> intf.vlan().equals(vlan))
+ .collect(collectingAndThen(toSet(), ImmutableSet::copyOf));
+ }
+
+ private void updateInterfaces(InterfaceConfig intfConfig) {
+ try {
+ Set<Interface> old = interfaces.put(intfConfig.subject(),
+ Sets.newHashSet(intfConfig.getInterfaces()));
+
+ if (old == null) {
+ old = Collections.emptySet();
+ }
+
+ for (Interface intf : intfConfig.getInterfaces()) {
+ if (intf.name().equals(Interface.NO_INTERFACE_NAME)) {
+ process(new InterfaceEvent(InterfaceEvent.Type.INTERFACE_ADDED, intf));
+ } else {
+ Optional<Interface> oldIntf = findInterface(intf, old);
+ if (oldIntf.isPresent()) {
+ old.remove(oldIntf.get());
+ if (!oldIntf.get().equals(intf)) {
+ process(new InterfaceEvent(InterfaceEvent.Type.INTERFACE_UPDATED, intf, oldIntf.get()));
+ }
+ } else {
+ process(new InterfaceEvent(InterfaceEvent.Type.INTERFACE_ADDED, intf));
+ }
+ }
+ }
+
+ for (Interface intf : old) {
+ if (!intf.name().equals(Interface.NO_INTERFACE_NAME)) {
+ process(new InterfaceEvent(InterfaceEvent.Type.INTERFACE_REMOVED, intf));
+ }
+ }
+ } catch (ConfigException e) {
+ log.error("Error in interface config", e);
+ }
+ }
+
+ private Optional<Interface> findInterface(Interface intf, Set<Interface> set) {
+ return set.stream().filter(i -> i.name().equals(intf.name())).findAny();
+ }
+
+ private void removeInterfaces(ConnectPoint port) {
+ Set<Interface> old = interfaces.remove(port);
+
+ old.stream()
+ .filter(i -> !i.name().equals(Interface.NO_INTERFACE_NAME))
+ .forEach(i -> process(new InterfaceEvent(InterfaceEvent.Type.INTERFACE_REMOVED, i)));
+ }
+
+ @Override
+ public void add(Interface intf) {
+ InterfaceConfig config =
+ configService.addConfig(intf.connectPoint(), CONFIG_CLASS);
+
+ config.addInterface(intf);
+
+ configService.applyConfig(intf.connectPoint(), CONFIG_CLASS, config.node());
+ }
+
+ @Override
+ public boolean remove(ConnectPoint connectPoint, String name) {
+ InterfaceConfig config = configService.addConfig(connectPoint, CONFIG_CLASS);
+ config.removeInterface(name);
+
+ try {
+ if (config.getInterfaces().isEmpty()) {
+ configService.removeConfig(connectPoint, CONFIG_CLASS);
+ } else {
+ configService.applyConfig(connectPoint, CONFIG_CLASS, config.node());
+ }
+ } catch (ConfigException e) {
+ log.error("Error reading interfaces JSON", e);
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Listener for network config events.
+ */
+ private class InternalConfigListener implements NetworkConfigListener {
+
+ @Override
+ public void event(NetworkConfigEvent event) {
+ if (event.configClass() == CONFIG_CLASS) {
+ switch (event.type()) {
+ case CONFIG_ADDED:
+ case CONFIG_UPDATED:
+ InterfaceConfig config =
+ configService.getConfig((ConnectPoint) event.subject(), InterfaceConfig.class);
+ updateInterfaces(config);
+ break;
+ case CONFIG_REMOVED:
+ removeInterfaces((ConnectPoint) event.subject());
+ break;
+ case CONFIG_REGISTERED:
+ case CONFIG_UNREGISTERED:
+ default:
+ break;
+ }
+ }
+ }
+ }
+}
diff --git a/core/net/src/main/java/org/onosproject/net/intf/impl/package-info.java b/core/net/src/main/java/org/onosproject/net/intf/impl/package-info.java
new file mode 100644
index 0000000..e5884c5
--- /dev/null
+++ b/core/net/src/main/java/org/onosproject/net/intf/impl/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2015-present Open Networking Foundation
+ *
+ * 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.
+ */
+
+/**
+ * Implementation of service for interacting with interfaces.
+ */
+package org.onosproject.net.impl;
diff --git a/core/net/src/test/java/org/onosproject/net/host/impl/HostMonitorTest.java b/core/net/src/test/java/org/onosproject/net/host/impl/HostMonitorTest.java
index 473c720..37ae0d3 100644
--- a/core/net/src/test/java/org/onosproject/net/host/impl/HostMonitorTest.java
+++ b/core/net/src/test/java/org/onosproject/net/host/impl/HostMonitorTest.java
@@ -29,8 +29,8 @@
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import org.onlab.packet.ndp.NeighborSolicitation;
-import org.onosproject.incubator.net.intf.Interface;
-import org.onosproject.incubator.net.intf.InterfaceService;
+import org.onosproject.net.intf.Interface;
+import org.onosproject.net.intf.InterfaceService;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
diff --git a/core/net/src/test/java/org/onosproject/net/intf/impl/InterfaceManagerTest.java b/core/net/src/test/java/org/onosproject/net/intf/impl/InterfaceManagerTest.java
new file mode 100644
index 0000000..89ca4ee
--- /dev/null
+++ b/core/net/src/test/java/org/onosproject/net/intf/impl/InterfaceManagerTest.java
@@ -0,0 +1,289 @@
+/*
+ * Copyright 2015-present Open Networking Foundation
+ *
+ * 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.net.intf.impl;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+import org.junit.Before;
+import org.junit.Test;
+import org.onlab.packet.Ip4Address;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.MacAddress;
+import org.onlab.packet.VlanId;
+import org.onosproject.incubator.net.config.basics.ConfigException;
+import org.onosproject.incubator.net.config.basics.InterfaceConfig;
+import org.onosproject.net.intf.Interface;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.config.Config;
+import org.onosproject.net.config.NetworkConfigEvent;
+import org.onosproject.net.config.NetworkConfigListener;
+import org.onosproject.net.config.NetworkConfigServiceAdapter;
+import org.onosproject.net.host.InterfaceIpAddress;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import static junit.framework.TestCase.assertEquals;
+import static org.junit.Assert.assertNull;
+
+/**
+ * Unit tests for InterfaceManager.
+ */
+public class InterfaceManagerTest {
+ private static final Class<InterfaceConfig> CONFIG_CLASS = InterfaceConfig.class;
+
+ private static final int NUM_INTERFACES = 4;
+
+ private Set<ConnectPoint> subjects = Sets.newHashSet();
+ private Map<ConnectPoint, InterfaceConfig> configs = Maps.newHashMap();
+
+ private Set<Interface> interfaces = Sets.newHashSet();
+
+ private NetworkConfigListener listener;
+
+ private InterfaceManager interfaceManager;
+
+ @Before
+ public void setUp() throws Exception {
+ for (int i = 0; i < NUM_INTERFACES; i++) {
+ ConnectPoint cp = createConnectPoint(i);
+ subjects.add(cp);
+
+ Interface intf = createInterface(i);
+
+ interfaces.add(intf);
+
+ InterfaceConfig ic = new TestInterfaceConfig(cp, Sets.newHashSet(intf));
+
+ configs.put(cp, ic);
+ }
+
+ TestNetworkConfigService configService =
+ new TestNetworkConfigService(subjects, configs);
+
+ interfaceManager = new InterfaceManager();
+ interfaceManager.configService = configService;
+ interfaceManager.activate();
+ }
+
+ private Interface createInterface(int i) {
+ ConnectPoint cp = createConnectPoint(i);
+
+ InterfaceIpAddress ia = InterfaceIpAddress.valueOf("192.168." + i + ".1/24");
+
+ Interface intf = new Interface(Interface.NO_INTERFACE_NAME, cp,
+ Collections.singletonList(ia),
+ MacAddress.valueOf(i),
+ VlanId.vlanId((short) i));
+
+ return intf;
+ }
+
+ private ConnectPoint createConnectPoint(int i) {
+ return ConnectPoint.deviceConnectPoint("of:000000000000000" + i + "/1");
+ }
+
+ @Test
+ public void testGetInterfaces() throws Exception {
+ assertEquals(interfaces, interfaceManager.getInterfaces());
+ }
+
+ @Test
+ public void testGetInterfacesByPort() throws Exception {
+ ConnectPoint cp = ConnectPoint.deviceConnectPoint("of:0000000000000001/1");
+
+ Set<Interface> byPort = Collections.singleton(createInterface(1));
+
+ assertEquals(byPort, interfaceManager.getInterfacesByPort(cp));
+ }
+
+ @Test
+ public void testGetInterfacesByIp() throws Exception {
+ IpAddress ip = Ip4Address.valueOf("192.168.2.1");
+
+ Set<Interface> byIp = Collections.singleton(createInterface(2));
+
+ assertEquals(byIp, interfaceManager.getInterfacesByIp(ip));
+ }
+
+ @Test
+ public void testGetMatchingInterface() throws Exception {
+ IpAddress ip = Ip4Address.valueOf("192.168.1.100");
+
+ Interface matchingIntf = createInterface(1);
+
+ assertEquals(matchingIntf, interfaceManager.getMatchingInterface(ip));
+
+ // Searching for an IP with no match should return null
+ ip = Ip4Address.valueOf("1.1.1.1");
+
+ assertNull(interfaceManager.getMatchingInterface(ip));
+ }
+
+ @Test
+ public void testGetInterfacesByVlan() throws Exception {
+ VlanId vlanId = VlanId.vlanId((short) 1);
+
+ Set<Interface> byVlan = Collections.singleton(createInterface(1));
+
+ assertEquals(byVlan, interfaceManager.getInterfacesByVlan(vlanId));
+ }
+
+ @Test
+ public void testAddInterface() throws Exception {
+ // Create a new InterfaceConfig which will get added
+ VlanId vlanId = VlanId.vlanId((short) 1);
+ ConnectPoint cp = ConnectPoint.deviceConnectPoint("of:0000000000000001/2");
+ Interface newIntf = new Interface(Interface.NO_INTERFACE_NAME, cp,
+ Collections.emptyList(),
+ MacAddress.valueOf(100),
+ vlanId);
+
+ InterfaceConfig ic = new TestInterfaceConfig(cp, Collections.singleton(newIntf));
+
+ subjects.add(cp);
+ configs.put(cp, ic);
+ interfaces.add(newIntf);
+
+ NetworkConfigEvent event = new NetworkConfigEvent(
+ NetworkConfigEvent.Type.CONFIG_ADDED, cp, CONFIG_CLASS);
+
+ assertEquals(NUM_INTERFACES, interfaceManager.getInterfaces().size());
+
+ // Send in a config event containing a new interface config
+ listener.event(event);
+
+ // Check the new interface exists in the InterfaceManager's inventory
+ assertEquals(interfaces, interfaceManager.getInterfaces());
+ assertEquals(NUM_INTERFACES + 1, interfaceManager.getInterfaces().size());
+
+ // There are now two interfaces with vlan ID 1
+ Set<Interface> byVlan = Sets.newHashSet(createInterface(1), newIntf);
+ assertEquals(byVlan, interfaceManager.getInterfacesByVlan(vlanId));
+ }
+
+ @Test
+ public void testUpdateInterface() throws Exception {
+ ConnectPoint cp = createConnectPoint(1);
+
+ // Create an interface that is the same as the existing one, but adds a
+ // new IP address
+ Interface intf = createInterface(1);
+ List<InterfaceIpAddress> addresses = Lists.newArrayList(intf.ipAddressesList());
+ addresses.add(InterfaceIpAddress.valueOf("192.168.100.1/24"));
+ intf = new Interface(Interface.NO_INTERFACE_NAME, intf.connectPoint(), addresses, intf.mac(), intf.vlan());
+
+ // Create a new interface on the same connect point as the existing one
+ InterfaceIpAddress newAddr = InterfaceIpAddress.valueOf("192.168.101.1/24");
+ Interface newIntf = new Interface(Interface.NO_INTERFACE_NAME, cp,
+ Collections.singletonList(newAddr),
+ MacAddress.valueOf(101),
+ VlanId.vlanId((short) 101));
+
+ Set<Interface> interfaces = Sets.newHashSet(intf, newIntf);
+
+ // New interface config updates the existing interface and adds a new
+ // interface to the same connect point
+ InterfaceConfig ic = new TestInterfaceConfig(cp, interfaces);
+
+ configs.put(cp, ic);
+
+ NetworkConfigEvent event = new NetworkConfigEvent(
+ NetworkConfigEvent.Type.CONFIG_UPDATED, cp, CONFIG_CLASS);
+
+ // Send in the event signalling the interfaces for this connect point
+ // have been updated
+ listener.event(event);
+
+ assertEquals(NUM_INTERFACES + 1, interfaceManager.getInterfaces().size());
+ assertEquals(interfaces, interfaceManager.getInterfacesByPort(cp));
+ }
+
+ @Test
+ public void testRemoveInterface() throws Exception {
+ ConnectPoint cp = createConnectPoint(1);
+
+ NetworkConfigEvent event = new NetworkConfigEvent(
+ NetworkConfigEvent.Type.CONFIG_REMOVED, cp, CONFIG_CLASS);
+
+ assertEquals(NUM_INTERFACES, interfaceManager.getInterfaces().size());
+
+ // Send in a config event removing an interface config
+ listener.event(event);
+
+ assertEquals(NUM_INTERFACES - 1, interfaceManager.getInterfaces().size());
+ }
+
+ /**
+ * Test version of NetworkConfigService which allows us to pass in subjects
+ * and InterfaceConfigs directly.
+ */
+ private class TestNetworkConfigService extends NetworkConfigServiceAdapter {
+ private final Set<ConnectPoint> subjects;
+ private final Map<ConnectPoint, InterfaceConfig> configs;
+
+ public TestNetworkConfigService(Set<ConnectPoint> subjects,
+ Map<ConnectPoint, InterfaceConfig> configs) {
+ this.subjects = subjects;
+ this.configs = configs;
+ }
+
+ @Override
+ public <S, C extends Config<S>> Set<S> getSubjects(Class<S> subjectClass,
+ Class<C> configClass) {
+ return (Set<S>) subjects;
+ }
+
+ @Override
+ public <S, C extends Config<S>> C getConfig(S subject, Class<C> configClass) {
+ return (C) configs.get(subject);
+ }
+
+ @Override
+ public void addListener(NetworkConfigListener listener) {
+ InterfaceManagerTest.this.listener = listener;
+ }
+ }
+
+ /**
+ * Test version of InterfaceConfig where we can inject interfaces directly,
+ * rather than parsing them from JSON.
+ */
+ private class TestInterfaceConfig extends InterfaceConfig {
+ private final ConnectPoint subject;
+ private final Set<Interface> interfaces;
+
+ @Override
+ public ConnectPoint subject() {
+ return subject;
+ }
+
+ public TestInterfaceConfig(ConnectPoint subject, Set<Interface> interfaces) {
+ this.subject = subject;
+ this.interfaces = interfaces;
+ }
+
+ @Override
+ public Set<Interface> getInterfaces() throws ConfigException {
+ return interfaces;
+ }
+ }
+
+}