Refactored tunnel and interface config behavior

- Added tunnel interface configuratoin to interfaceConfig and
  deprecated tunnelConfig
- OVSDB client service provides interface create/remove APIs instead
  of tunnel interface create/remove, and this APIs can be used to
  create/remove various types of interfaces like tunnel, patch, tap and so on
- Use tunnel description when create tunnel interface so that we can extend
  more config options later
- Some cleaup OVSDB client

Change-Id: I4653595504a27b18384a92ebe4b31ce9d99237cd
diff --git a/apps/openstacknode/src/main/java/org/onosproject/openstacknode/OpenstackNodeManager.java b/apps/openstacknode/src/main/java/org/onosproject/openstacknode/OpenstackNodeManager.java
index c011fc3..a645ec5 100644
--- a/apps/openstacknode/src/main/java/org/onosproject/openstacknode/OpenstackNodeManager.java
+++ b/apps/openstacknode/src/main/java/org/onosproject/openstacknode/OpenstackNodeManager.java
@@ -15,8 +15,6 @@
  */
 package org.onosproject.openstacknode;
 
-import com.google.common.collect.ImmutableMap;
-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;
@@ -30,19 +28,18 @@
 import org.onosproject.cluster.NodeId;
 import org.onosproject.core.ApplicationId;
 import org.onosproject.core.CoreService;
-import org.onosproject.net.DefaultAnnotations;
 import org.onosproject.net.Device;
 import org.onosproject.net.DeviceId;
 import org.onosproject.net.Port;
 import org.onosproject.net.behaviour.BridgeConfig;
 import org.onosproject.net.behaviour.BridgeDescription;
-import org.onosproject.net.behaviour.BridgeName;
 import org.onosproject.net.behaviour.ControllerInfo;
 import org.onosproject.net.behaviour.DefaultBridgeDescription;
 import org.onosproject.net.behaviour.DefaultTunnelDescription;
-import org.onosproject.net.behaviour.TunnelConfig;
+import org.onosproject.net.behaviour.InterfaceConfig;
 import org.onosproject.net.behaviour.TunnelDescription;
-import org.onosproject.net.behaviour.TunnelName;
+import org.onosproject.net.behaviour.TunnelEndPoints;
+import org.onosproject.net.behaviour.TunnelKeys;
 import org.onosproject.net.config.ConfigFactory;
 import org.onosproject.net.config.NetworkConfigEvent;
 import org.onosproject.net.config.NetworkConfigListener;
@@ -72,7 +69,6 @@
 
 import java.util.ArrayList;
 import java.util.List;
-import java.util.Map;
 import java.util.concurrent.ExecutorService;
 import java.util.stream.Collectors;
 
@@ -97,9 +93,6 @@
     private static final String OPENSTACK_NODESTORE = "openstacknode-nodestore";
     private static final String OPENSTACK_NODEMANAGER_ID = "org.onosproject.openstacknode";
 
-    private static final Map<String, String> DEFAULT_TUNNEL_OPTIONS
-            = ImmutableMap.of("key", "flow", "remote_ip", "flow");
-
     private static final int DPID_BEGIN = 3;
     private static final int OFPORT = 6653;
 
@@ -390,26 +383,22 @@
             return;
         }
 
-        List<ControllerInfo> controllers = new ArrayList<>();
-        Sets.newHashSet(clusterService.getNodes()).stream()
-                .forEach(controller -> {
-                    ControllerInfo ctrlInfo = new ControllerInfo(controller.ip(), OFPORT, "tcp");
-                    controllers.add(ctrlInfo);
-                });
+        List<ControllerInfo> controllers = clusterService.getNodes().stream()
+                .map(controller -> new ControllerInfo(controller.ip(), OFPORT, "tcp"))
+                .collect(Collectors.toList());
         String dpid = node.intBrId().toString().substring(DPID_BEGIN);
 
+        BridgeDescription bridgeDesc = DefaultBridgeDescription.builder()
+                .name(DEFAULT_BRIDGE)
+                .failMode(BridgeDescription.FailMode.SECURE)
+                .datapathId(dpid)
+                .disableInBand()
+                .controllers(controllers)
+                .build();
+
         try {
             DriverHandler handler = driverService.createHandler(node.ovsdbId());
             BridgeConfig bridgeConfig =  handler.behaviour(BridgeConfig.class);
-
-            BridgeDescription bridgeDesc = DefaultBridgeDescription.builder()
-                    .name(DEFAULT_BRIDGE)
-                    .failMode(BridgeDescription.FailMode.SECURE)
-                    .datapathId(dpid)
-                    .disableInBand()
-                    .controllers(controllers)
-                    .build();
-
             bridgeConfig.addBridge(bridgeDesc);
         } catch (ItemNotFoundException e) {
             log.warn("Failed to create integration bridge on {}", node.ovsdbId());
@@ -426,17 +415,17 @@
             return;
         }
 
-        DefaultAnnotations.Builder optionBuilder = DefaultAnnotations.builder();
-        for (String key : DEFAULT_TUNNEL_OPTIONS.keySet()) {
-            optionBuilder.set(key, DEFAULT_TUNNEL_OPTIONS.get(key));
-        }
-        TunnelDescription description =
-                new DefaultTunnelDescription(null, null, VXLAN, TunnelName.tunnelName(DEFAULT_TUNNEL),
-                        optionBuilder.build());
+        TunnelDescription description = DefaultTunnelDescription.builder()
+                .deviceId(DEFAULT_BRIDGE)
+                .ifaceName(DEFAULT_TUNNEL)
+                .type(VXLAN)
+                .remote(TunnelEndPoints.flowTunnelEndpoint())
+                .key(TunnelKeys.flowTunnelKey())
+                .build();
         try {
             DriverHandler handler = driverService.createHandler(node.ovsdbId());
-            TunnelConfig tunnelConfig =  handler.behaviour(TunnelConfig.class);
-            tunnelConfig.createTunnelInterface(BridgeName.bridgeName(DEFAULT_BRIDGE), description);
+            InterfaceConfig ifaceConfig =  handler.behaviour(InterfaceConfig.class);
+            ifaceConfig.addTunnelMode(DEFAULT_TUNNEL, description);
         } catch (ItemNotFoundException e) {
             log.warn("Failed to create tunnel interface on {}", node.ovsdbId());
         }
diff --git a/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/manager/impl/VtnManager.java b/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/manager/impl/VtnManager.java
index 2b794dc..f2971bf 100644
--- a/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/manager/impl/VtnManager.java
+++ b/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/manager/impl/VtnManager.java
@@ -487,7 +487,7 @@
     private void programTunnelConfig(DeviceId localDeviceId, IpAddress localIp,
                                      DriverHandler localHandler) {
         if (mastershipService.isLocalMaster(localDeviceId)) {
-            VtnConfig.applyTunnelConfig(localHandler, localIp, IpAddress.valueOf(DEFAULT_IP));
+            VtnConfig.applyTunnelConfig(localHandler, localIp);
             log.info("Add tunnel on {}", localIp);
         }
     }
diff --git a/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/util/VtnConfig.java b/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/util/VtnConfig.java
index e4b0767..9796e14 100644
--- a/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/util/VtnConfig.java
+++ b/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/util/VtnConfig.java
@@ -27,11 +27,10 @@
 import org.onosproject.net.behaviour.BridgeName;
 import org.onosproject.net.behaviour.DefaultBridgeDescription;
 import org.onosproject.net.behaviour.DefaultTunnelDescription;
-import org.onosproject.net.behaviour.IpTunnelEndPoint;
-import org.onosproject.net.behaviour.TunnelConfig;
+import org.onosproject.net.behaviour.InterfaceConfig;
 import org.onosproject.net.behaviour.TunnelDescription;
-import org.onosproject.net.behaviour.TunnelEndPoint;
-import org.onosproject.net.behaviour.TunnelName;
+import org.onosproject.net.behaviour.TunnelEndPoints;
+import org.onosproject.net.behaviour.TunnelKeys;
 import org.onosproject.net.driver.DriverHandler;
 
 /**
@@ -95,43 +94,34 @@
      *
      * @param handler DriverHandler
      * @param srcIp the ipAddress of the local controller device
-     * @param dstIp the ipAddress of the remote controller device
      */
-    public static void applyTunnelConfig(DriverHandler handler, IpAddress srcIp,
-                                  IpAddress dstIp) {
+    public static void applyTunnelConfig(DriverHandler handler, IpAddress srcIp) {
         DefaultAnnotations.Builder optionBuilder = DefaultAnnotations.builder();
         for (String key : DEFAULT_TUNNEL_OPTIONS.keySet()) {
             optionBuilder.set(key, DEFAULT_TUNNEL_OPTIONS.get(key));
         }
-        TunnelConfig tunnelConfig = handler.behaviour(TunnelConfig.class);
-        TunnelEndPoint tunnelAsSrc = IpTunnelEndPoint.ipTunnelPoint(srcIp);
-        TunnelDescription tunnel = new DefaultTunnelDescription(
-                                                                tunnelAsSrc,
-                                                                null,
-                                                                TunnelDescription.Type.VXLAN,
-                                                                TunnelName.tunnelName(DEFAULT_TUNNEL),
-                                                                optionBuilder.build());
-        tunnelConfig.createTunnelInterface(BridgeName.bridgeName(DEFAULT_BRIDGE_NAME), tunnel);
+
+        InterfaceConfig interfaceConfig = handler.behaviour(InterfaceConfig.class);
+        TunnelDescription tunnel = DefaultTunnelDescription.builder()
+                .deviceId(DEFAULT_BRIDGE_NAME)
+                .ifaceName(DEFAULT_TUNNEL)
+                .type(TunnelDescription.Type.VXLAN)
+                .local(TunnelEndPoints.ipTunnelEndpoint(srcIp))
+                .remote(TunnelEndPoints.flowTunnelEndpoint())
+                .key(TunnelKeys.flowTunnelKey())
+                .otherConfigs(optionBuilder.build())
+                .build();
+        interfaceConfig.addTunnelMode(DEFAULT_TUNNEL, tunnel);
     }
 
     /**
      * Creates or update tunnel in the controller device.
      *
      * @param handler DriverHandler
-     * @param srcIp the ipAddress of the local controller device
-     * @param dstIp the ipAddress of the remote controller device
      */
-    public static void removeTunnelConfig(DriverHandler handler, IpAddress srcIp,
-                                   IpAddress dstIp) {
-        TunnelConfig tunnelConfig = handler.behaviour(TunnelConfig.class);
-        TunnelEndPoint tunnelAsSrc = IpTunnelEndPoint.ipTunnelPoint(srcIp);
-        TunnelEndPoint tunnelAsDst = IpTunnelEndPoint.ipTunnelPoint(dstIp);
-        TunnelDescription tunnel = new DefaultTunnelDescription(
-                                                                tunnelAsSrc,
-                                                                tunnelAsDst,
-                                                                TunnelDescription.Type.VXLAN,
-                                                                null);
-        tunnelConfig.removeTunnel(tunnel);
+    public static void removeTunnelConfig(DriverHandler handler) {
+        InterfaceConfig interfaceConfig = handler.behaviour(InterfaceConfig.class);
+        interfaceConfig.removeTunnelMode(DEFAULT_TUNNEL);
     }
 
     /**
diff --git a/core/api/src/main/java/org/onosproject/net/behaviour/DefaultTunnelDescription.java b/core/api/src/main/java/org/onosproject/net/behaviour/DefaultTunnelDescription.java
index 57965aa..9e94cba 100644
--- a/core/api/src/main/java/org/onosproject/net/behaviour/DefaultTunnelDescription.java
+++ b/core/api/src/main/java/org/onosproject/net/behaviour/DefaultTunnelDescription.java
@@ -15,25 +15,29 @@
  */
 package org.onosproject.net.behaviour;
 
+import com.google.common.base.Strings;
 import org.onosproject.net.AbstractDescription;
 import org.onosproject.net.SparseAnnotations;
 
-import com.google.common.annotations.Beta;
 import com.google.common.base.MoreObjects;
 
+import java.util.Optional;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
 /**
- * Default implementation of immutable tunnel description entity.
+ * Default implementation of immutable tunnel interface description entity.
  */
-@Beta
-public class DefaultTunnelDescription extends AbstractDescription
+public final class DefaultTunnelDescription extends AbstractDescription
         implements TunnelDescription {
 
-    private final TunnelEndPoint src;
-    private final TunnelEndPoint dst;
+    private final Optional<String> deviceId;
+    private final String ifaceName;
     private final Type type;
-    // which a tunnel match up
-    // tunnel producer
-    private final TunnelName tunnelName; // name of a tunnel
+    private final Optional<TunnelEndPoint> local;
+    private final Optional<TunnelEndPoint> remote;
+    private final Optional<TunnelKey> key;
 
     /**
      * Creates a tunnel description using the supplied information.
@@ -43,26 +47,67 @@
      * @param type tunnel type
      * @param tunnelName tunnel name
      * @param annotations optional key/value annotations
+     * @deprecated version 1.7.0 - Hummingbird
      */
+    @Deprecated
     public DefaultTunnelDescription(TunnelEndPoint src,
                                     TunnelEndPoint dst, Type type,
                                     TunnelName tunnelName,
                                     SparseAnnotations... annotations) {
         super(annotations);
-        this.src = src;
-        this.dst = dst;
+        this.deviceId = Optional.empty();
+        this.local = Optional.ofNullable(src);
+        this.remote = Optional.ofNullable(dst);
         this.type = type;
-        this.tunnelName = tunnelName;
+        this.ifaceName = tunnelName.value();
+        this.key = Optional.empty();
     }
 
+    /**
+     * Creates a tunnel description using the supplied information.
+     *
+     * @param ifaceName tunnel interface ifaceName
+     * @param local source tunnel endpoint
+     * @param remote destination tunnel endpoint
+     * @param type tunnel type
+     * @param annotations optional key/value annotations
+     */
+    private DefaultTunnelDescription(Optional<String> deviceId,
+                                     String ifaceName,
+                                     Type type,
+                                     Optional<TunnelEndPoint> local,
+                                     Optional<TunnelEndPoint> remote,
+                                     Optional<TunnelKey> key,
+                                     SparseAnnotations... annotations) {
+        super(annotations);
+        this.deviceId = deviceId;
+        this.ifaceName = checkNotNull(ifaceName);
+        this.type = type;
+        this.local = local;
+        this.remote = remote;
+        this.key = key;
+    }
+
+    @Override
+    public Optional<String> deviceId() {
+        return deviceId;
+    }
+
+    @Override
+    public String ifaceName() {
+        return ifaceName;
+    }
+
+    @Deprecated
     @Override
     public TunnelEndPoint src() {
-        return src;
+        return local.isPresent() ? local.get() : null;
     }
 
+    @Deprecated
     @Override
     public TunnelEndPoint dst() {
-        return dst;
+        return remote.isPresent() ? remote.get() : null;
     }
 
     @Override
@@ -71,17 +116,112 @@
     }
 
     @Override
+    public Optional<TunnelEndPoint> local() {
+        return local;
+    }
+
+    @Override
+    public Optional<TunnelEndPoint> remote() {
+        return remote;
+    }
+
+    @Override
+    public Optional<TunnelKey> key() {
+        return key;
+    }
+
+    @Deprecated
+    @Override
     public TunnelName tunnelName() {
-        return tunnelName;
+        return TunnelName.tunnelName(ifaceName);
     }
 
     @Override
     public String toString() {
         return MoreObjects.toStringHelper(this)
-                .add("src", src())
-                .add("dst", dst())
-                .add("type", type())
-                .add("tunnelName", tunnelName())
+                .add("deviceId", deviceId)
+                .add("ifaceName", ifaceName)
+                .add("type", type)
+                .add("local", local)
+                .add("remote", remote)
+                .add("key", key)
                 .toString();
     }
+
+    /**
+     * Creates and returns a new builder instance.
+     *
+     * @return default tunnel description builder
+     */
+    public static Builder builder() {
+        return new Builder();
+    }
+
+    public static final class Builder implements TunnelDescription.Builder {
+        private Optional<String> deviceId = Optional.empty();
+        private String ifaceName;
+        private Type type;
+        private Optional<TunnelEndPoint> local = Optional.empty();
+        private Optional<TunnelEndPoint> remote = Optional.empty();
+        private Optional<TunnelKey> key = Optional.empty();
+        private Optional<SparseAnnotations> otherConfigs = Optional.empty();
+
+        private Builder() {
+        }
+
+        @Override
+        public TunnelDescription build() {
+            if (otherConfigs.isPresent()) {
+                return new DefaultTunnelDescription(deviceId, ifaceName, type,
+                                                    local, remote, key,
+                                                    otherConfigs.get());
+            } else {
+                return new DefaultTunnelDescription(deviceId, ifaceName, type,
+                                                    local, remote, key);
+            }
+        }
+
+        @Override
+        public Builder deviceId(String deviceId) {
+            this.deviceId = Optional.ofNullable(deviceId);
+            return this;
+        }
+
+        @Override
+        public Builder ifaceName(String ifaceName) {
+            checkArgument(!Strings.isNullOrEmpty(ifaceName));
+            this.ifaceName = ifaceName;
+            return this;
+        }
+
+        @Override
+        public Builder type(Type type) {
+            this.type = type;
+            return this;
+        }
+
+        @Override
+        public Builder local(TunnelEndPoint endpoint) {
+            local = Optional.ofNullable(endpoint);
+            return this;
+        }
+
+        @Override
+        public Builder remote(TunnelEndPoint endpoint) {
+            remote = Optional.ofNullable(endpoint);
+            return this;
+        }
+
+        @Override
+        public Builder key(TunnelKey key) {
+            this.key = Optional.ofNullable(key);
+            return this;
+        }
+
+        @Override
+        public Builder otherConfigs(SparseAnnotations configs) {
+            otherConfigs = Optional.ofNullable(configs);
+            return this;
+        }
+    }
 }
diff --git a/core/api/src/main/java/org/onosproject/net/behaviour/InterfaceConfig.java b/core/api/src/main/java/org/onosproject/net/behaviour/InterfaceConfig.java
index fecdf7f..47f6100 100644
--- a/core/api/src/main/java/org/onosproject/net/behaviour/InterfaceConfig.java
+++ b/core/api/src/main/java/org/onosproject/net/behaviour/InterfaceConfig.java
@@ -125,6 +125,23 @@
     boolean removeRateLimit(String intf);
 
     /**
+     * Adds a tunnel mode to supplied interface.
+     *
+     * @param intf the name of the interface
+     * @param tunnelDesc tunnel interface description
+     * @return true if the operation succeeds
+     */
+    boolean addTunnelMode(String intf, TunnelDescription tunnelDesc);
+
+    /**
+     * Removes a tunnel interface.
+     *
+     * @param intf tunnel interface name
+     * @return true if the operation succeeds
+     */
+    boolean removeTunnelMode(String intf);
+
+    /**
      * Provides the interfaces configured on a device.
      *
      * @param deviceId the device ID
@@ -148,5 +165,4 @@
      *  getTrunkVlans(Interface), getAccessVlan(Interface) should be added to
      *  complete the behavior.
      */
-
 }
diff --git a/core/api/src/main/java/org/onosproject/net/behaviour/IpTunnelEndPoint.java b/core/api/src/main/java/org/onosproject/net/behaviour/IpTunnelEndPoint.java
index d3b67e7..9b8e264 100644
--- a/core/api/src/main/java/org/onosproject/net/behaviour/IpTunnelEndPoint.java
+++ b/core/api/src/main/java/org/onosproject/net/behaviour/IpTunnelEndPoint.java
@@ -16,27 +16,25 @@
 
 package org.onosproject.net.behaviour;
 
-import java.util.Objects;
-
 import com.google.common.annotations.Beta;
-import org.onlab.packet.IpAddress;
-
 import com.google.common.base.MoreObjects;
+import org.onlab.packet.IpAddress;
 
 /**
  * Represent for a tunnel point using ip address.
+ *
+ * @deprecated version 1.7.0 - Hummingbird; use {@code TunnelEndPoint<IpAddress>}
  */
+@Deprecated
 @Beta
-public final class IpTunnelEndPoint implements TunnelEndPoint {
-
-    private final IpAddress ip;
+public final class IpTunnelEndPoint extends TunnelEndPoint<IpAddress> {
 
     /**
      * Public construction is prohibited.
      * @param ip ip address
      */
     private IpTunnelEndPoint(IpAddress ip) {
-        this.ip = ip;
+        super(ip);
     }
 
     /**
@@ -53,28 +51,11 @@
      * @return IP address
      */
     public IpAddress ip() {
-        return ip;
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(ip);
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (obj instanceof IpTunnelEndPoint) {
-            final IpTunnelEndPoint other = (IpTunnelEndPoint) obj;
-            return Objects.equals(this.ip, other.ip);
-        }
-        return false;
+        return value;
     }
 
     @Override
     public String toString() {
-        return MoreObjects.toStringHelper(getClass()).add("ip", ip).toString();
+        return MoreObjects.toStringHelper(getClass()).add("ip", value).toString();
     }
 }
diff --git a/core/api/src/main/java/org/onosproject/net/behaviour/TunnelConfig.java b/core/api/src/main/java/org/onosproject/net/behaviour/TunnelConfig.java
index 9d305e8..404bfd8 100644
--- a/core/api/src/main/java/org/onosproject/net/behaviour/TunnelConfig.java
+++ b/core/api/src/main/java/org/onosproject/net/behaviour/TunnelConfig.java
@@ -21,7 +21,10 @@
 
 /**
  * Behaviour for handling various drivers for tunnel configuration.
+ *
+ * @deprecated version 1.7.0 - Hummingbird; use interface config tunnel mode
  */
+@Deprecated
 public interface TunnelConfig extends HandlerBehaviour {
 
     /**
diff --git a/core/api/src/main/java/org/onosproject/net/behaviour/TunnelDescription.java b/core/api/src/main/java/org/onosproject/net/behaviour/TunnelDescription.java
index 4967a41..a06ea23 100644
--- a/core/api/src/main/java/org/onosproject/net/behaviour/TunnelDescription.java
+++ b/core/api/src/main/java/org/onosproject/net/behaviour/TunnelDescription.java
@@ -19,9 +19,12 @@
 import org.onosproject.net.Description;
 
 import com.google.common.annotations.Beta;
+import org.onosproject.net.SparseAnnotations;
+
+import java.util.Optional;
 
 /**
- * Describes a tunnel.
+ * Describes a tunnel interface.
  */
 @Beta
 public interface TunnelDescription extends Description, Annotated {
@@ -57,18 +60,18 @@
     }
 
     /**
-     * Returns the connection point source.
+     * Returns the identifier of the device where the interface is.
      *
-     * @return tunnel source ConnectionPoint
+     * @return device identifier
      */
-    TunnelEndPoint src();
+    Optional<String> deviceId();
 
     /**
-     * Returns the connection point destination.
+     * Return the name of the tunnel interface.
      *
-     * @return tunnel destination
+     * @return tunnel interface name
      */
-    TunnelEndPoint dst();
+    String ifaceName();
 
     /**
      * Returns the tunnel type.
@@ -78,9 +81,120 @@
     Type type();
 
     /**
+     * Returns the local connection point.
+     *
+     * @return tunnel source ConnectionPoint
+     */
+    Optional<TunnelEndPoint> local();
+
+    /**
+     * Returns the remote connection point.
+     *
+     * @return tunnel destination
+     */
+    Optional<TunnelEndPoint> remote();
+
+    /**
+     * Returns the tunnel key.
+     *
+     * @return tunnel key
+     */
+    Optional<TunnelKey> key();
+
+    /**
+     * Returns the connection point source.
+     *
+     * @deprecated version 1.7.0 - Hummingbird; use local instead
+     * @return tunnel source ConnectionPoint
+     */
+    @Deprecated
+    TunnelEndPoint src();
+
+    /**
+     * Returns the connection point destination.
+     *
+     * @deprecated version 1.7.0 - Hummingbird; use remote instead
+     * @return tunnel destination
+     */
+    @Deprecated
+    TunnelEndPoint dst();
+
+    /**
      * Return the name of a tunnel.
      *
+     * @deprecated version 1.7.0 - Hummingbird; use ifaceName instead
      * @return Tunnel Name
      */
+    @Deprecated
     TunnelName tunnelName();
+
+    /**
+     * Builder of tunnel interface description entities.
+     */
+    interface Builder {
+
+        /**
+         * Returns new tunnel interface description.
+         *
+         * @return tunnel description
+         */
+        TunnelDescription build();
+
+        /**
+         * Returns tunnel interface description biulder with supplied device ID.
+         *
+         * @param deviceId device identifier
+         * @return tunnel description builder
+         */
+        Builder deviceId(String deviceId);
+
+        /**
+         * Returns tunnel interface description builder with a given interface name.
+         *
+         * @param name tunnel interface name
+         * @return tunnel description builder
+         */
+        Builder ifaceName(String name);
+
+        /**
+         * Returns tunnel interface description builder with a given tunnel type.
+         *
+         * @param type tunnel type
+         * @return tunnel description builder
+         */
+        Builder type(Type type);
+
+        /**
+         * Returns tunnel interface description builder with a given local
+         * tunnel endpoint.
+         *
+         * @param endpoint tunnel endpoint
+         * @return tunnel description builder
+         */
+        Builder local(TunnelEndPoint endpoint);
+
+        /**
+         * Returns tunnel interface description builder with a given remote
+         * tunnel endpoint.
+         *
+         * @param endpoint tunnel endpoint
+         * @return tunnel description builder
+         */
+        Builder remote(TunnelEndPoint endpoint);
+
+        /**
+         * Returns tunnel interface description builder with a tunnel key.
+         *
+         * @return tunnel description builder
+         */
+        Builder key(TunnelKey tunnelKey);
+
+        /**
+         * Returns tunnel interface descriptions builder with other configurations.
+         *
+         * @param configs configurations
+         * @return tunnel description builder
+         */
+        Builder otherConfigs(SparseAnnotations configs);
+    }
 }
diff --git a/core/api/src/main/java/org/onosproject/net/behaviour/TunnelEndPoint.java b/core/api/src/main/java/org/onosproject/net/behaviour/TunnelEndPoint.java
index d8d6627..c3ab5f3 100644
--- a/core/api/src/main/java/org/onosproject/net/behaviour/TunnelEndPoint.java
+++ b/core/api/src/main/java/org/onosproject/net/behaviour/TunnelEndPoint.java
@@ -16,13 +16,58 @@
 
 package org.onosproject.net.behaviour;
 
-import com.google.common.annotations.Beta;
+import java.util.Objects;
 
 /**
  * Represents for source end point or destination end point of a tunnel. Maybe a tunnel
  * based on ConnectPoint, IpAddress, MacAddress and so on is built.
  */
-@Beta
-public interface TunnelEndPoint {
+public class TunnelEndPoint<T> {
 
+    protected final T value;
+
+    /**
+     * Default constructor.
+     *
+     * @param value value of the tunnel endpoint
+     */
+    public TunnelEndPoint(T value) {
+        this.value = value;
+    }
+
+    /**
+     * Returns the value.
+     *
+     * @return tunnel endpoint value
+     */
+    public T value() {
+        return value;
+    }
+
+    /**
+     * Returns the value as a string.
+     *
+     * @return string value
+     */
+    public String strValue() {
+        return value.toString();
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof TunnelEndPoint) {
+            final TunnelEndPoint that = (TunnelEndPoint) obj;
+            return this.getClass() == that.getClass() &&
+                    Objects.equals(this.value, that.value);
+        }
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        return value.hashCode();
+    }
 }
diff --git a/core/api/src/main/java/org/onosproject/net/behaviour/TunnelEndPoints.java b/core/api/src/main/java/org/onosproject/net/behaviour/TunnelEndPoints.java
new file mode 100644
index 0000000..54fd66d
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/behaviour/TunnelEndPoints.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.net.behaviour;
+
+import org.onlab.packet.IpAddress;
+
+/**
+ * Static utility methods pertaining to {@link TunnelEndPoint} instances.
+ */
+public final class TunnelEndPoints {
+
+    private TunnelEndPoints() {
+    }
+
+    private static TunnelEndPoint<String> flowEndpoint = new TunnelEndPoint<>("flow");
+
+    /**
+     * Returns a tunnel endpoint with supplied IP address.
+     *
+     * @param ipAddress ip address
+     * @return tunnel endpoint instance
+     */
+    public static TunnelEndPoint<IpAddress> ipTunnelEndpoint(IpAddress ipAddress) {
+        return new TunnelEndPoint<>(ipAddress);
+    }
+
+    /**
+     * Returns a tunnel endpoint with FLOW keyword.
+     *
+     * @return tunnel endpoint instance
+     */
+    public static TunnelEndPoint<String> flowTunnelEndpoint() {
+        return flowEndpoint;
+    }
+}
diff --git a/core/api/src/main/java/org/onosproject/net/behaviour/TunnelKey.java b/core/api/src/main/java/org/onosproject/net/behaviour/TunnelKey.java
new file mode 100644
index 0000000..527b44a
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/behaviour/TunnelKey.java
@@ -0,0 +1,75 @@
+/*
+ * 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.net.behaviour;
+
+import java.util.Objects;
+
+/**
+ * Represent for a tunnel key. The tunnel accepts packets with the tunnel key.
+ * A positive 24-bit (for Geneve, VXLAN, and LISP), 32-bit (for GRE) or 64-bit (for
+ * GRE64) number value is used for example. Open vSwitch allows "flow" as the key
+ * to set this value with matching in the flow table.
+ */
+public final class TunnelKey<T> {
+
+    private final T value;
+
+    /**
+     * Default constructor.
+     *
+     * @param value value of the tunnel key
+     */
+    public TunnelKey(T value) {
+        this.value = value;
+    }
+
+    /**
+     * Returns the value.
+     *
+     * @return tunnel key value
+     */
+    public T value() {
+        return value;
+    }
+
+    /**
+     * Returns the value as a string.
+     *
+     * @return string value
+     */
+    public String strValue() {
+        return value.toString();
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof TunnelKey) {
+            final TunnelKey that = (TunnelKey) obj;
+            return this.getClass() == that.getClass() &&
+                    Objects.equals(this.value, that.value);
+        }
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        return value.hashCode();
+    }
+}
diff --git a/core/api/src/main/java/org/onosproject/net/behaviour/TunnelKeys.java b/core/api/src/main/java/org/onosproject/net/behaviour/TunnelKeys.java
new file mode 100644
index 0000000..4b98064
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/behaviour/TunnelKeys.java
@@ -0,0 +1,38 @@
+/*
+ * 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.net.behaviour;
+
+/**
+ * Static utility methods pertaining to {@link TunnelKey} instances.
+ */
+public final class TunnelKeys {
+
+    private TunnelKeys() {
+    }
+
+    private static TunnelKey<String> flowKey = new TunnelKey<>("flow");
+
+    /**
+     * Returns a tunnel key with FLOW keyword.
+     *
+     * @return tunnel key instance
+     */
+    public static TunnelKey<String> flowTunnelKey() {
+        return flowKey;
+    }
+
+    // TODO add more for various types of tunnel
+}
diff --git a/core/api/src/main/java/org/onosproject/net/behaviour/TunnelName.java b/core/api/src/main/java/org/onosproject/net/behaviour/TunnelName.java
index 416acc2..03c7332 100644
--- a/core/api/src/main/java/org/onosproject/net/behaviour/TunnelName.java
+++ b/core/api/src/main/java/org/onosproject/net/behaviour/TunnelName.java
@@ -24,7 +24,10 @@
  * Represents for a unique tunnel name. TunnelId is generated by ONOS while
  * TunnelName is given by producer. The consumer can borrow tunnels with
  * TunnelId or TunnelName.
+ *
+ * @deprecated version 1.7.0 - Hummingbird
  */
+@Deprecated
 @Beta
 public final class TunnelName {
     private final String str;
diff --git a/drivers/cisco/src/main/java/org/onosproject/drivers/cisco/InterfaceConfigCiscoIosImpl.java b/drivers/cisco/src/main/java/org/onosproject/drivers/cisco/InterfaceConfigCiscoIosImpl.java
index f31c8b0..a631e46 100644
--- a/drivers/cisco/src/main/java/org/onosproject/drivers/cisco/InterfaceConfigCiscoIosImpl.java
+++ b/drivers/cisco/src/main/java/org/onosproject/drivers/cisco/InterfaceConfigCiscoIosImpl.java
@@ -22,6 +22,7 @@
 import org.onosproject.drivers.utilities.XmlConfigParser;
 import org.onosproject.net.DeviceId;
 import org.onosproject.net.behaviour.InterfaceConfig;
+import org.onosproject.net.behaviour.TunnelDescription;
 import org.onosproject.net.device.DeviceInterfaceDescription;
 import org.onosproject.net.driver.AbstractHandlerBehaviour;
 import org.onosproject.netconf.NetconfController;
@@ -480,5 +481,14 @@
         return rpc.toString();
     }
 
+    @Override
+    public boolean addTunnelMode(String ifaceName, TunnelDescription tunnelDesc) {
+        throw new UnsupportedOperationException("Add tunnel mode is not supported");
+    }
+
+    @Override
+    public boolean removeTunnelMode(String ifaceName) {
+        throw new UnsupportedOperationException("Remove tunnel mode is not supported");
+    }
 }
 
diff --git a/drivers/ovsdb/src/main/java/org/onosproject/drivers/ovsdb/OvsdbInterfaceConfig.java b/drivers/ovsdb/src/main/java/org/onosproject/drivers/ovsdb/OvsdbInterfaceConfig.java
new file mode 100644
index 0000000..e35599c
--- /dev/null
+++ b/drivers/ovsdb/src/main/java/org/onosproject/drivers/ovsdb/OvsdbInterfaceConfig.java
@@ -0,0 +1,147 @@
+/*
+ * 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.drivers.ovsdb;
+
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.VlanId;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.behaviour.InterfaceConfig;
+import org.onosproject.net.behaviour.TunnelDescription;
+import org.onosproject.net.device.DeviceInterfaceDescription;
+import org.onosproject.net.driver.AbstractHandlerBehaviour;
+import org.onosproject.net.driver.DriverHandler;
+import org.onosproject.ovsdb.controller.OvsdbClientService;
+import org.onosproject.ovsdb.controller.OvsdbController;
+import org.onosproject.ovsdb.controller.OvsdbInterface;
+import org.onosproject.ovsdb.controller.OvsdbNodeId;
+import org.slf4j.Logger;
+
+import java.util.List;
+
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * OVSDB-based implementation of interface config behaviour.
+ */
+public class OvsdbInterfaceConfig extends AbstractHandlerBehaviour implements InterfaceConfig {
+
+    private final Logger log = getLogger(getClass());
+
+    @Override
+    public boolean addTunnelMode(String ifaceName, TunnelDescription tunnelDesc) {
+        OvsdbInterface ovsdbIface = OvsdbInterface.builder(tunnelDesc).build();
+        OvsdbClientService ovsdbClient = getOvsdbClient(handler());
+
+        if (!tunnelDesc.deviceId().isPresent()) {
+            log.warn("Device ID is required {}", tunnelDesc);
+            return false;
+        }
+        return ovsdbClient.createInterface(tunnelDesc.deviceId().get(), ovsdbIface);
+    }
+
+    @Override
+    public boolean removeTunnelMode(String ifaceName) {
+        OvsdbClientService ovsdbClient = getOvsdbClient(handler());
+        return ovsdbClient.dropInterface(ifaceName);
+    }
+
+    @Override
+    public boolean addAccessMode(String ifaceName, VlanId vlanId) {
+        // TODO implement
+        throw new UnsupportedOperationException("Not implemented yet");
+    }
+
+    @Override
+    public boolean removeAccessMode(String ifaceName) {
+        // TODO implement
+        throw new UnsupportedOperationException("Not implemented yet");
+    }
+
+    @Override
+    public boolean addTrunkMode(String ifaceName, List<VlanId> vlanIds) {
+        // TODO implement
+        throw new UnsupportedOperationException("Not implemented yet");
+    }
+
+    @Override
+    public boolean removeTrunkMode(String ifaceName) {
+        // TODO implement
+        throw new UnsupportedOperationException("Not implemented yet");
+    }
+
+    @Override
+    public boolean addRateLimit(String ifaceName, short limit) {
+        // TODO implement
+        throw new UnsupportedOperationException("Not implemented yet");
+    }
+
+    @Override
+    public boolean removeRateLimit(String ifaceName) {
+        // TODO implement
+        throw new UnsupportedOperationException("Not implemented yet");
+    }
+
+    @Override
+    public List<DeviceInterfaceDescription> getInterfaces() {
+        // TODO implement
+        throw new UnsupportedOperationException("Not implemented yet");
+    }
+
+    // deprecated interfaces
+    @Override
+    public boolean addAccessInterface(DeviceId deviceId, String ifaceName, VlanId vlanId) {
+        throw new UnsupportedOperationException("Not implemented yet");
+    }
+
+    @Override
+    public boolean removeAccessInterface(DeviceId deviceId, String ifaceName) {
+        throw new UnsupportedOperationException("Not implemented yet");
+    }
+
+    @Override
+    public boolean addTrunkInterface(DeviceId deviceId, String ifaceName, List<VlanId> vlanIds) {
+        throw new UnsupportedOperationException("Not implemented yet");
+    }
+
+    @Override
+    public List<DeviceInterfaceDescription> getInterfaces(DeviceId deviceId) {
+        return null;
+    }
+
+    @Override
+    public boolean removeTrunkInterface(DeviceId deviceId, String ifaceName) {
+        throw new UnsupportedOperationException("Not implemented yet");
+    }
+
+    // OvsdbNodeId(IP) is used in the adaptor while DeviceId(ovsdb:IP)
+    // is used in the core. So DeviceId need be changed to OvsdbNodeId.
+    private OvsdbNodeId changeDeviceIdToNodeId(DeviceId deviceId) {
+        String[] splits = deviceId.toString().split(":");
+        if (splits.length < 1) {
+            return null;
+        }
+        IpAddress ipAddress = IpAddress.valueOf(splits[1]);
+        return new OvsdbNodeId(ipAddress, 0);
+    }
+
+    private OvsdbClientService getOvsdbClient(DriverHandler handler) {
+        OvsdbController ovsController = handler.get(OvsdbController.class);
+        OvsdbNodeId nodeId = changeDeviceIdToNodeId(handler.data().deviceId());
+
+        return ovsController.getOvsdbClient(nodeId);
+    }
+}
diff --git a/drivers/ovsdb/src/main/java/org/onosproject/drivers/ovsdb/OvsdbTunnelConfig.java b/drivers/ovsdb/src/main/java/org/onosproject/drivers/ovsdb/OvsdbTunnelConfig.java
index 03ce0b5..783f511 100644
--- a/drivers/ovsdb/src/main/java/org/onosproject/drivers/ovsdb/OvsdbTunnelConfig.java
+++ b/drivers/ovsdb/src/main/java/org/onosproject/drivers/ovsdb/OvsdbTunnelConfig.java
@@ -17,68 +17,43 @@
 package org.onosproject.drivers.ovsdb;
 
 import org.onlab.packet.IpAddress;
-import org.onosproject.net.DefaultAnnotations;
 import org.onosproject.net.DeviceId;
 import org.onosproject.net.behaviour.BridgeName;
-import org.onosproject.net.behaviour.DefaultTunnelDescription;
-import org.onosproject.net.behaviour.IpTunnelEndPoint;
 import org.onosproject.net.behaviour.TunnelConfig;
 import org.onosproject.net.behaviour.TunnelDescription;
-import org.onosproject.net.behaviour.TunnelName;
 import org.onosproject.net.driver.AbstractHandlerBehaviour;
 import org.onosproject.net.driver.DriverHandler;
 import org.onosproject.ovsdb.controller.OvsdbClientService;
 import org.onosproject.ovsdb.controller.OvsdbController;
+import org.onosproject.ovsdb.controller.OvsdbInterface;
 import org.onosproject.ovsdb.controller.OvsdbNodeId;
-import org.onosproject.ovsdb.controller.OvsdbTunnel;
 
 import java.util.Collection;
-import java.util.Map;
-import java.util.Set;
-import java.util.stream.Collectors;
+import java.util.Collections;
 
 /**
  * OVSDB-based implementation of tunnel config behaviour.
+ *
+ * @deprecated version 1.7.0 - Hummingbird; use interface config instead
  */
+@Deprecated
 public class OvsdbTunnelConfig extends AbstractHandlerBehaviour
         implements TunnelConfig {
 
-    private static final String DEFAULT_ADDRESS = "0.0.0.0";
-    private static final String OPTION_LOCAL_IP = "local_ip";
-    private static final String OPTION_REMOTE_IP = "remote_ip";
-
     @Override
     public boolean createTunnelInterface(BridgeName bridgeName, TunnelDescription tunnel) {
-        Map<String, String> options = ((DefaultAnnotations) tunnel.annotations()).asMap();
-        if (tunnel.src() != null) {
-            options.put(OPTION_LOCAL_IP, ((IpTunnelEndPoint) tunnel.src()).ip().toString());
-        }
-        if (tunnel.dst() != null) {
-            options.put(OPTION_REMOTE_IP, ((IpTunnelEndPoint) tunnel.dst()).ip().toString());
-        }
-
         DriverHandler handler = handler();
-        OvsdbClientService ovsdbClient = getOvsdbNode(handler);
-        return ovsdbClient.createTunnel(bridgeName.name(), tunnel.tunnelName().toString(),
-                                        tunnel.type().toString().toLowerCase(), options);
+        OvsdbClientService ovsdbNode = getOvsdbNode(handler);
+
+        OvsdbInterface ovsdbIface = OvsdbInterface.builder(tunnel).build();
+        return ovsdbNode.createInterface(bridgeName.name(), ovsdbIface);
     }
 
     @Override
     public void removeTunnel(TunnelDescription tunnel) {
         DriverHandler handler = handler();
         OvsdbClientService ovsdbNode = getOvsdbNode(handler);
-        IpTunnelEndPoint ipSrc = IpTunnelEndPoint.ipTunnelPoint(IpAddress
-                .valueOf(DEFAULT_ADDRESS));
-        IpTunnelEndPoint ipDst = IpTunnelEndPoint.ipTunnelPoint(IpAddress
-                .valueOf(DEFAULT_ADDRESS));
-        if (tunnel.src() instanceof IpTunnelEndPoint) {
-            ipSrc = (IpTunnelEndPoint) tunnel.src();
-        }
-        if (tunnel.dst() instanceof IpTunnelEndPoint) {
-            ipDst = (IpTunnelEndPoint) tunnel.dst();
-        }
-      //Even if source point ip or destination point ip equals 0:0:0:0, it is still work-in-progress.
-        ovsdbNode.dropTunnel(ipSrc.ip(), ipDst.ip());
+        ovsdbNode.dropInterface(tunnel.ifaceName());
     }
 
     @Override
@@ -89,20 +64,7 @@
 
     @Override
     public Collection<TunnelDescription> getTunnels() {
-        DriverHandler handler = handler();
-        OvsdbClientService ovsdbNode = getOvsdbNode(handler);
-        Set<OvsdbTunnel> tunnels = ovsdbNode.getTunnels();
-
-        return tunnels.stream()
-                .map(x ->
-                        new DefaultTunnelDescription(
-                                IpTunnelEndPoint.ipTunnelPoint(x.localIp()),
-                                IpTunnelEndPoint.ipTunnelPoint(x.remoteIp()),
-                                TunnelDescription.Type.VXLAN,
-                                TunnelName.tunnelName(x.tunnelName().toString())
-                        )
-                )
-                .collect(Collectors.toSet());
+        return Collections.emptyList();
     }
 
     // OvsdbNodeId(IP) is used in the adaptor while DeviceId(ovsdb:IP)
diff --git a/drivers/ovsdb/src/main/resources/ovsdb-drivers.xml b/drivers/ovsdb/src/main/resources/ovsdb-drivers.xml
index e70925b..9e88ba9 100644
--- a/drivers/ovsdb/src/main/resources/ovsdb-drivers.xml
+++ b/drivers/ovsdb/src/main/resources/ovsdb-drivers.xml
@@ -21,6 +21,8 @@
                    impl="org.onosproject.drivers.ovsdb.OvsdbTunnelConfig"/>
         <behaviour api="org.onosproject.net.behaviour.BridgeConfig"
                    impl="org.onosproject.drivers.ovsdb.OvsdbBridgeConfig"/>
+        <behaviour api="org.onosproject.net.behaviour.InterfaceConfig"
+                   impl="org.onosproject.drivers.ovsdb.OvsdbInterfaceConfig"/>
     </driver>
     <driver name="ovs" extends="default"
             manufacturer="Nicira, Inc\." hwVersion="Open vSwitch" swVersion="2\..*">
diff --git a/protocols/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbClientService.java b/protocols/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbClientService.java
index bf91497..5a0676b 100644
--- a/protocols/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbClientService.java
+++ b/protocols/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbClientService.java
@@ -16,16 +16,12 @@
 package org.onosproject.ovsdb.controller;
 
 import com.google.common.util.concurrent.ListenableFuture;
-
 import org.onlab.packet.IpAddress;
 import org.onosproject.net.DeviceId;
 import org.onosproject.net.behaviour.ControllerInfo;
 import org.onosproject.ovsdb.rfc.jsonrpc.OvsdbRpc;
-import org.onosproject.ovsdb.rfc.message.OperationResult;
 import org.onosproject.ovsdb.rfc.message.TableUpdates;
 import org.onosproject.ovsdb.rfc.notation.Row;
-import org.onosproject.ovsdb.rfc.notation.Uuid;
-import org.onosproject.ovsdb.rfc.operations.Operation;
 import org.onosproject.ovsdb.rfc.schema.DatabaseSchema;
 
 import java.util.List;
@@ -46,28 +42,43 @@
     /**
      * Creates a tunnel port with given options.
      *
+     * @deprecated version 1.7.0 - Hummingbird
      * @param bridgeName bridge name
      * @param portName port name
      * @param tunnelType tunnel type
      * @param options tunnel options
      * @return true if tunnel creation is successful, false otherwise
      */
-    boolean createTunnel(String bridgeName, String portName, String tunnelType, Map<String, String> options);
+    @Deprecated
+    boolean createTunnel(String bridgeName, String portName, String tunnelType,
+                         Map<String, String> options);
 
     /**
      * Drops the configuration for tunnel.
      *
+     * @deprecated version 1.7.0 - Hummingbird
      * @param srcIp source IP address
      * @param dstIp destination IP address
      */
+    @Deprecated
     void dropTunnel(IpAddress srcIp, IpAddress dstIp);
 
     /**
-     * Gets tunnels of node.
+     * Creates an interface with a given OVSDB interface description.
      *
-     * @return set of tunnels; empty if no tunnel is find
+     * @param bridgeName bridge name
+     * @param ovsdbIface ovsdb interface description
+     * @return true if interface creation is successful, false otherwise
      */
-    Set<OvsdbTunnel> getTunnels();
+    boolean createInterface(String bridgeName, OvsdbInterface ovsdbIface);
+
+    /**
+     * Removes an interface with the supplied interface name.
+     *
+     * @param ifaceName interface name
+     * @return true if interface creation is successful, false otherwise
+     */
+    boolean dropInterface(String ifaceName);
 
     /**
      * Creates a bridge.
@@ -142,17 +153,6 @@
     ControllerInfo localController();
 
     /**
-     * Sets the Controllers for the specified bridge.
-     * <p>
-     * This method will replace the existing controller list with the new controller
-     * list.
-     *
-     * @param bridgeUuid bridge uuid
-     * @param controllers list of controllers
-     */
-    void setControllersWithUuid(Uuid bridgeUuid, List<ControllerInfo> controllers);
-
-    /**
      * Sets the Controllers for the specified device.
      * <p>
      * This method will replace the existing controller list with the new controller
@@ -211,32 +211,6 @@
     String getPortUuid(String portName, String bridgeUuid);
 
     /**
-     * Gets the Interface uuid.
-     *
-     * @param portUuid port uuid
-     * @param portName port name
-     * @return interface uuid, empty if no uuid is find
-     */
-    String getInterfaceUuid(String portUuid, String portName);
-
-    /**
-     * Gets the Controller uuid.
-     *
-     * @param controllerName   controller name
-     * @param controllerTarget controller target
-     * @return controller uuid, empty if no uuid is find
-     */
-    String getControllerUuid(String controllerName, String controllerTarget);
-
-    /**
-     * Gets the OVS uuid.
-     *
-     * @param dbName database name
-     * @return ovs uuid, empty if no uuid is find
-     */
-    String getOvsUuid(String dbName);
-
-    /**
      * Gets the OVSDB database schema.
      *
      * @param dbName database name
@@ -254,16 +228,6 @@
     ListenableFuture<TableUpdates> monitorTables(String dbName, String id);
 
     /**
-     * Gets the OVSDB config operation result.
-     *
-     * @param dbName     database name
-     * @param operations the list of operations
-     * @return operation results
-     */
-    ListenableFuture<List<OperationResult>> transactConfig(String dbName,
-                                                           List<Operation> operations);
-
-    /**
      * Gets the OVSDB database schema from local.
      *
      * @param dbName database name
diff --git a/protocols/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbConstant.java b/protocols/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbConstant.java
index 5bca1f9..bf1e513 100644
--- a/protocols/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbConstant.java
+++ b/protocols/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbConstant.java
@@ -45,6 +45,10 @@
     public static final String DATAPATH_ID = "datapath-id";
     public static final String DISABLE_INBAND = "disable-in-band";
 
+    /** Port table. */
+    public static final String PORT = "Port";
+    public static final String INTERFACES = "interfaces";
+
     /** Interface table. */
     public static final String INTERFACE = "Interface";
     // type
@@ -52,13 +56,14 @@
     // virtual machine identifiers
     public static final String EXTERNAL_ID_INTERFACE_ID = "iface-id";
     public static final String EXTERNAL_ID_VM_MAC = "attached-mac";
+    // tunnel interface options
+    public static final String TUNNEL_LOCAL_IP = "local_ip";
+    public static final String TUNNEL_REMOTE_IP = "remote_ip";
+    public static final String TUNNEL_KEY = "key";
 
     /** Controller table. */
     public static final String CONTROLLER = "Controller";
 
-    /** Port table. */
-    public static final String PORT = "Port";
-
     /** Ovsdb bridge name. */
     // TODO remove this particular bridge name from OVSDB provider
     public static final String INTEGRATION_BRIDGE = "br-int";
diff --git a/protocols/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbInterface.java b/protocols/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbInterface.java
new file mode 100644
index 0000000..e047833
--- /dev/null
+++ b/protocols/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbInterface.java
@@ -0,0 +1,232 @@
+/*
+ * Copyright 2015-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.ovsdb.controller;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+import static org.onosproject.ovsdb.controller.OvsdbConstant.*;
+
+import java.util.Map;
+import java.util.Objects;
+
+import com.google.common.collect.Maps;
+import org.onosproject.net.DefaultAnnotations;
+import org.onosproject.net.behaviour.TunnelDescription;
+
+/**
+ * The class representing an OVSDB interface.
+ * This class is immutable.
+ */
+public final class OvsdbInterface {
+
+    public enum Type {
+        /**
+         * An ordinary network device, e.g. eth0 on Linux.
+         */
+        SYSTEM,
+        /**
+         * A simulated network device that sends and receives traffic.
+         */
+        INTERNAL,
+        /**
+         * A TUN/TAP device managed by Open vSwitch.
+         */
+        TAP,
+        /**
+         * An Ethernet over RFC 2890 Generic Routing Encapsulation over IPv4 IPsec tunnel.
+         */
+        GRE,
+        /**
+         * An Ethernet tunnel over the experimental, UDP-based VXLAN protocol.
+         */
+        VXLAN,
+        /**
+         * A pair of virtual devices that act as a patch cable.
+         */
+        PATCH
+    }
+
+    private final String name;
+    private final Type type;
+
+    /* Adds more configs */
+
+    /* Fields start with "options:" prefix defined in the OVSDB */
+    private final Map<String, String> options;
+
+    private OvsdbInterface(String name, Type type, Map<String, String> options) {
+        this.name = name;
+        this.type = type;
+        this.options = Maps.newHashMap(options);
+    }
+
+    /**
+     * Returns name of the interface.
+     *
+     * @return interface name
+     */
+    public String name() {
+        return name;
+    }
+
+    /**
+     * Returns type of the interface.
+     *
+     * @return interface type
+     */
+    public Type type() {
+        return type;
+    }
+
+    /**
+     * Returns type of the interface with lowercase string.
+     *
+     * @return interface type string
+     */
+    public String typeToString() {
+        return type.name().toLowerCase();
+    }
+
+    /**
+     * Returns optional configs of the interface.
+     *
+     * @return interface options
+     */
+    public Map<String, String> options() {
+        return options;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(name);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof OvsdbInterface) {
+            final OvsdbInterface otherOvsdbInterface = (OvsdbInterface) obj;
+            return Objects.equals(this.name, otherOvsdbInterface.name);
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return toStringHelper(this)
+                .add("name", name)
+                .add("type", type)
+                .add("options", options)
+                .toString();
+    }
+
+    /**
+     * Returns new OVSDB interface builder.
+     *
+     * @return ovsdb interface builder
+     */
+    public static OvsdbInterface.Builder builder() {
+        return new Builder();
+    }
+
+    /**
+     * Returns new OVSDB interface builder with tunnel interface description.
+     *
+     * @param tunnelDesc tunnel interface description
+     * @return ovsdb interface builder
+     */
+    public static OvsdbInterface.Builder builder(TunnelDescription tunnelDesc) {
+        return new Builder(tunnelDesc);
+    }
+
+    /**
+     * Builder of OVSDB interface entities.
+     */
+    public static final class Builder {
+        private String name;
+        private Type type;
+        private Map<String, String> options = Maps.newHashMap();
+
+        private Builder() {
+        }
+
+        /**
+         * Constructs a builder with a given tunnel interface description.
+         *
+         * @param tunnelDesc tunnel interface description
+         */
+        private Builder(TunnelDescription tunnelDesc) {
+            this.name = tunnelDesc.ifaceName();
+            this.type = Type.valueOf(tunnelDesc.type().name());
+
+            if (tunnelDesc.local().isPresent()) {
+                options.put(TUNNEL_LOCAL_IP, tunnelDesc.local().get().strValue());
+            }
+            if (tunnelDesc.remote().isPresent()) {
+                options.put(TUNNEL_REMOTE_IP, tunnelDesc.remote().get().strValue());
+            }
+            if (tunnelDesc.key().isPresent()) {
+                options.put(TUNNEL_KEY, tunnelDesc.key().get().strValue());
+            }
+
+            // set other configurations if there are any
+            options.putAll(((DefaultAnnotations) tunnelDesc.annotations()).asMap());
+        }
+
+        /**
+         * Returns new OVSDB interface.
+         *
+         * @return ovsdb interface
+         */
+        public OvsdbInterface build() {
+            return new OvsdbInterface(name, type, options);
+        }
+
+        /**
+         * Returns OVSDB interface builder with a given name.
+         *
+         * @param name name of the interface
+         * @return ovsdb interface builder
+         */
+        public Builder name(String name) {
+            this.name = name;
+            return this;
+        }
+
+        /**
+         * Returns OVSDB interface builder with a given interface type.
+         *
+         * @param type type of the interface
+         * @return ovsdb interface builder
+         */
+        public Builder type(Type type) {
+            this.type = type;
+            return this;
+        }
+
+        /**
+         * Returns OVSDB interface builder with given options.
+         *
+         * @param options map of options
+         * @return ovsdb interface builder
+         */
+        public Builder options(Map<String, String> options) {
+            this.options = Maps.newHashMap(options);
+            return this;
+        }
+    }
+}
diff --git a/protocols/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbTunnel.java b/protocols/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbTunnel.java
deleted file mode 100644
index fd9987c..0000000
--- a/protocols/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbTunnel.java
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright 2015-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.ovsdb.controller;
-
-import static com.google.common.base.MoreObjects.toStringHelper;
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import java.util.Objects;
-
-import org.onlab.packet.IpAddress;
-
-/**
- * The class representing an ovsdb tunnel.
- * This class is immutable.
- */
-public final class OvsdbTunnel {
-
-    private final IpAddress localIp;
-    private final IpAddress remoteIp;
-
-    public enum Type {
-        VXLAN, GRE
-    }
-
-    private final Type tunnelType;
-    private final OvsdbTunnelName tunnelName;
-
-    /**
-     * Constructor from an IpAddress localIp, IpAddress remoteIp Type tunnelType,
-     * OvsdbTunnelName tunnelName.
-     *
-     * @param localIp the localIp to use
-     * @param remoteIp the remoteIp to use
-     * @param tunnelType the tunnelType to use
-     * @param tunnelName the tunnelName to use
-     */
-    public OvsdbTunnel(IpAddress localIp, IpAddress remoteIp, Type tunnelType,
-                       OvsdbTunnelName tunnelName) {
-        checkNotNull(localIp, "portName is not null");
-        checkNotNull(remoteIp, "portName is not null");
-        checkNotNull(tunnelName, "portName is not null");
-        this.localIp = localIp;
-        this.remoteIp = remoteIp;
-        this.tunnelType = tunnelType;
-        this.tunnelName = tunnelName;
-    }
-
-    /**
-     * Gets the local IP of tunnel.
-     *
-     * @return the local IP of tunnel
-     */
-    public IpAddress localIp() {
-        return localIp;
-    }
-
-    /**
-     * Gets the remote IP of tunnel.
-     *
-     * @return the remote IP of tunnel
-     */
-    public IpAddress remoteIp() {
-        return remoteIp;
-    }
-
-    /**
-     * Gets the tunnel type of tunnel.
-     *
-     * @return the tunnel type of tunnel
-     */
-    public Type tunnelType() {
-        return tunnelType;
-    }
-
-    /**
-     * Gets the tunnel name of tunnel.
-     *
-     * @return the tunnel name of tunnel
-     */
-    public OvsdbTunnelName tunnelName() {
-        return tunnelName;
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(localIp, remoteIp, tunnelType, tunnelName);
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (obj instanceof OvsdbTunnel) {
-            final OvsdbTunnel otherOvsdbTunnel = (OvsdbTunnel) obj;
-            return Objects.equals(this.localIp, otherOvsdbTunnel.localIp)
-                    && Objects.equals(this.remoteIp, otherOvsdbTunnel.remoteIp)
-                    && Objects.equals(this.tunnelType,
-                                      otherOvsdbTunnel.tunnelType)
-                    && Objects.equals(this.tunnelName,
-                                      otherOvsdbTunnel.tunnelName);
-        }
-        return false;
-    }
-
-    @Override
-    public String toString() {
-        return toStringHelper(this).add("localIp", localIp.toString())
-                .add("remoteIp", remoteIp.toString())
-                .add("tunnelType", tunnelType).add("tunnelName", tunnelName)
-                .toString();
-    }
-}
diff --git a/protocols/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbTunnelName.java b/protocols/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbTunnelName.java
deleted file mode 100644
index 2494ddc..0000000
--- a/protocols/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbTunnelName.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright 2015-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.ovsdb.controller;
-
-import static com.google.common.base.MoreObjects.toStringHelper;
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import java.util.Objects;
-
-/**
- * The class representing a tunnel name.
- * This class is immutable.
- */
-public final class OvsdbTunnelName {
-    private final String value;
-
-    /**
-     * Constructor from a String.
-     *
-     * @param value the tunnel name to use
-     */
-    public OvsdbTunnelName(String value) {
-        checkNotNull(value, "value is not null");
-        this.value = value;
-    }
-
-    /**
-     * Gets the value of tunnel name.
-     *
-     * @return the value of tunnel name
-     */
-    public String value() {
-        return value;
-    }
-
-    @Override
-    public int hashCode() {
-        return value.hashCode();
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (obj instanceof OvsdbTunnelName) {
-            final OvsdbTunnelName otherOvsdbTunnelName = (OvsdbTunnelName) obj;
-            return Objects.equals(this.value, otherOvsdbTunnelName.value);
-        }
-        return false;
-    }
-
-    @Override
-    public String toString() {
-        return toStringHelper(this).add("value", value).toString();
-    }
-}
diff --git a/protocols/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/driver/DefaultOvsdbClient.java b/protocols/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/driver/DefaultOvsdbClient.java
index cbb94ac..6469f4d 100644
--- a/protocols/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/driver/DefaultOvsdbClient.java
+++ b/protocols/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/driver/DefaultOvsdbClient.java
@@ -32,6 +32,8 @@
 import org.onosproject.net.behaviour.ControllerInfo;
 import org.onosproject.ovsdb.controller.OvsdbBridge;
 import org.onosproject.ovsdb.controller.OvsdbClientService;
+import org.onosproject.ovsdb.controller.OvsdbInterface;
+import org.onosproject.ovsdb.controller.OvsdbInterface.Type;
 import org.onosproject.ovsdb.controller.OvsdbNodeId;
 import org.onosproject.ovsdb.controller.OvsdbPort;
 import org.onosproject.ovsdb.controller.OvsdbPortName;
@@ -39,7 +41,6 @@
 import org.onosproject.ovsdb.controller.OvsdbRowStore;
 import org.onosproject.ovsdb.controller.OvsdbStore;
 import org.onosproject.ovsdb.controller.OvsdbTableStore;
-import org.onosproject.ovsdb.controller.OvsdbTunnel;
 import org.onosproject.ovsdb.rfc.jsonrpc.Callback;
 import org.onosproject.ovsdb.rfc.message.OperationResult;
 import org.onosproject.ovsdb.rfc.message.TableUpdates;
@@ -72,11 +73,11 @@
 
 import java.net.InetSocketAddress;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 import java.util.Set;
 import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.ExecutionException;
@@ -102,7 +103,6 @@
     private final Map<String, String> requestMethod = Maps.newHashMap();
     private final Map<String, SettableFuture<? extends Object>> requestResult = Maps.newHashMap();
     private final Map<String, DatabaseSchema> schema = Maps.newHashMap();
-    private final Set<OvsdbTunnel> ovsdbTunnels = new HashSet<OvsdbTunnel>();
 
     /**
      * Creates an OvsdbClient.
@@ -263,38 +263,8 @@
     }
 
     @Override
-    public String getInterfaceUuid(String portUuid, String portName) {
-        DatabaseSchema dbSchema = schema.get(DATABASENAME);
-
-        Row portRow = getRow(DATABASENAME, PORT, portUuid);
-        Port port = (Port) TableGenerator.getTable(dbSchema, portRow, OvsdbTable.PORT);
-
-        if (port != null) {
-            OvsdbSet setInterfaces = (OvsdbSet) port.getInterfacesColumn().data();
-            @SuppressWarnings("unchecked")
-            Set<Uuid> interfaces = setInterfaces.set();
-
-            if (interfaces == null || interfaces.size() == 0) {
-                log.warn("The interface uuid is null");
-                return null;
-            }
-
-            for (Uuid uuid : interfaces) {
-                Row intfRow = getRow(DATABASENAME, INTERFACE, uuid.value());
-                Interface intf = (Interface) TableGenerator
-                        .getTable(dbSchema, intfRow, OvsdbTable.INTERFACE);
-                if (intf != null && portName.equalsIgnoreCase(intf.getName())) {
-                    return uuid.value();
-                }
-            }
-        }
-        return null;
-    }
-
-    @Override
     public String getBridgeUuid(String bridgeName) {
         DatabaseSchema dbSchema = schema.get(DATABASENAME);
-
         OvsdbRowStore rowStore = getRowStore(DATABASENAME, BRIDGE);
         if (rowStore == null) {
             log.debug("The bridge uuid is null");
@@ -317,32 +287,7 @@
         return null;
     }
 
-    @Override
-    public String getControllerUuid(String controllerName, String controllerTarget) {
-        DatabaseSchema dbSchema = schema.get(DATABASENAME);
-        OvsdbRowStore rowStore = getRowStore(DATABASENAME, CONTROLLER);
-        if (rowStore == null) {
-            log.debug("The controller uuid is null");
-            return null;
-        }
-
-        ConcurrentMap<String, Row> controllerTableRows = rowStore.getRowStore();
-        if (controllerTableRows != null) {
-            for (String uuid : controllerTableRows.keySet()) {
-                Controller controller = (Controller) TableGenerator
-                        .getTable(dbSchema, controllerTableRows.get(uuid),
-                                  OvsdbTable.CONTROLLER);
-                String target = (String) controller.getTargetColumn().data();
-                if (target.equalsIgnoreCase(controllerTarget)) {
-                    return uuid;
-                }
-            }
-        }
-        return null;
-    }
-
-    @Override
-    public String getOvsUuid(String dbName) {
+    private String getOvsUuid(String dbName) {
         OvsdbRowStore rowStore = getRowStore(DATABASENAME, DATABASENAME);
         if (rowStore == null) {
             log.debug("The bridge uuid is null");
@@ -485,8 +430,7 @@
         return new ControllerInfo(ipAddress, OFPORT, "tcp");
     }
 
-    @Override
-    public void setControllersWithUuid(Uuid bridgeUuid, List<ControllerInfo> controllers) {
+    private void setControllersWithUuid(Uuid bridgeUuid, List<ControllerInfo> controllers) {
         DatabaseSchema dbSchema = schema.get(DATABASENAME);
         if (dbSchema == null) {
             log.debug("There is no schema");
@@ -555,19 +499,37 @@
             log.warn("Could not find bridge in node", nodeId.getIpAddress());
             return;
         }
-        deleteConfig(BRIDGE, UUID, bridgeUuid, DATABASENAME, "bridges");
+        deleteConfig(BRIDGE, UUID, bridgeUuid, DATABASENAME, BRIDGES);
+    }
+
+    @Deprecated
+    @Override
+    public boolean createTunnel(String bridgeName, String ifaceName, String tunnelType,
+                                Map<String, String> options) {
+        OvsdbInterface ovsdbIface = OvsdbInterface.builder()
+                .name(ifaceName)
+                .type(Type.valueOf(tunnelType))
+                .options(options)
+                .build();
+
+        return createInterface(bridgeName, ovsdbIface);
+    }
+
+    @Deprecated
+    @Override
+    public void dropTunnel(IpAddress srcIp, IpAddress dstIp) {
     }
 
     @Override
-    public boolean createTunnel(String bridgeName, String portName, String tunnelType, Map<String, String> options) {
+    public boolean createInterface(String bridgeName, OvsdbInterface ovsdbIface) {
         String bridgeUuid  = getBridgeUuid(bridgeName);
         if (bridgeUuid == null) {
             log.warn("Couldn't find bridge {} in {}", bridgeName, nodeId.getIpAddress());
             return false;
         }
 
-        if (getPortUuid(portName, bridgeUuid) != null) {
-            log.warn("Port {} already exists", portName);
+        if (getPortUuid(ovsdbIface.name(), bridgeUuid) != null) {
+            log.warn("Interface {} already exists", ovsdbIface.name());
             // remove existing one and re-create?
             return false;
         }
@@ -577,45 +539,57 @@
 
         // insert a new port to the port table
         Port port = (Port) TableGenerator.createTable(dbSchema, OvsdbTable.PORT);
-        port.setName(portName);
-        Insert portInsert = new Insert(dbSchema.getTableSchema("Port"), "Port", port.getRow());
-        portInsert.getRow().put("interfaces", Uuid.uuid("Interface"));
+        port.setName(ovsdbIface.name());
+        Insert portInsert = new Insert(dbSchema.getTableSchema(PORT), PORT, port.getRow());
+        portInsert.getRow().put(INTERFACES, Uuid.uuid(INTERFACE));
         operations.add(portInsert);
 
         // update the bridge table
         Condition condition = ConditionUtil.isEqual(UUID, Uuid.uuid(bridgeUuid));
-        Mutation mutation = MutationUtil.insert(PORTS, Uuid.uuid("Port"));
-        List<Condition> conditions = new ArrayList<>(Arrays.asList(condition));
-        List<Mutation> mutations = new ArrayList<>(Arrays.asList(mutation));
-        operations.add(new Mutate(dbSchema.getTableSchema("Bridge"), conditions, mutations));
+        Mutation mutation = MutationUtil.insert(PORTS, Uuid.uuid(PORT));
+        List<Condition> conditions = Lists.newArrayList(condition);
+        List<Mutation> mutations = Lists.newArrayList(mutation);
+        operations.add(new Mutate(dbSchema.getTableSchema(BRIDGE), conditions, mutations));
 
         // insert a tunnel interface
         Interface intf = (Interface) TableGenerator.createTable(dbSchema, OvsdbTable.INTERFACE);
-        intf.setName(portName);
-        intf.setType(tunnelType);
-        intf.setOptions(options);
-        Insert intfInsert = new Insert(dbSchema.getTableSchema("Interface"), "Interface", intf.getRow());
+        intf.setName(ovsdbIface.name());
+        intf.setType(ovsdbIface.typeToString());
+        intf.setOptions(ovsdbIface.options());
+        Insert intfInsert = new Insert(dbSchema.getTableSchema(INTERFACE), INTERFACE, intf.getRow());
         operations.add(intfInsert);
 
         transactConfig(DATABASENAME, operations);
+        log.info("Created interface {}", ovsdbIface.name());
         return true;
     }
 
     @Override
-    public void dropTunnel(IpAddress srcIp, IpAddress dstIp) {
-        String bridgeName = INTEGRATION_BRIDGE;
-        String portName = getTunnelName(TYPEVXLAN, dstIp);
-        String bridgeUuid = getBridgeUuid(INTEGRATION_BRIDGE);
-        if (bridgeUuid == null) {
-            log.warn("Could not find bridge {} in {}", bridgeName,
-                     nodeId.getIpAddress());
-            return;
+    public boolean dropInterface(String ifaceName) {
+        OvsdbRowStore rowStore = getRowStore(DATABASENAME, BRIDGE);
+        if (rowStore == null) {
+            log.warn("Failed to get BRIDGE table");
+            return false;
         }
 
-        String portUuid = getPortUuid(portName, bridgeUuid);
-        if (portUuid != null) {
-            log.info("Delete tunnel");
-            deleteConfig(PORT, UUID, portUuid, BRIDGE, PORTS);
+        ConcurrentMap<String, Row> bridgeTableRows = rowStore.getRowStore();
+        if (bridgeTableRows == null) {
+            log.warn("Failed to get BRIDGE table rows");
+            return false;
+        }
+
+        // interface name is unique
+        Optional<String> bridgeId = bridgeTableRows.keySet().stream()
+                .filter(uuid -> getPortUuid(ifaceName, uuid) != null)
+                .findFirst();
+
+        if (bridgeId.isPresent()) {
+            String portId = getPortUuid(ifaceName, bridgeId.get());
+            deleteConfig(PORT, UUID, portId, BRIDGE, PORTS);
+            return true;
+        } else {
+            log.warn("Unable to find the interface with name {}", ifaceName);
+            return false;
         }
     }
 
@@ -727,7 +701,7 @@
         }
         if (childTableName.equalsIgnoreCase(PORT)) {
             log.debug("Handle port insert");
-            Insert intfInsert = handlePortInsertTable(INTERFACE, row);
+            Insert intfInsert = handlePortInsertTable(row);
 
             if (intfInsert != null) {
                 operations.add(intfInsert);
@@ -754,11 +728,10 @@
     /**
      * Handles port insert.
      *
-     * @param tableName ovsdb table interface
      * @param portRow   row of port
      * @return insert, empty if null
      */
-    private Insert handlePortInsertTable(String tableName, Row portRow) {
+    private Insert handlePortInsertTable(Row portRow) {
         DatabaseSchema dbSchema = schema.get(DATABASENAME);
 
         TableSchema portTableSchema = dbSchema.getTableSchema(PORT);
@@ -772,17 +745,6 @@
         return new Insert(intfTableSchema, INTERFACE, inf.getRow());
     }
 
-    /**
-     * Gets tunnel name.
-     *
-     * @param tunnelType tunnel type
-     * @param dstIp      the remote ip address
-     * @return tunnel name
-     */
-    private String getTunnelName(String tunnelType, IpAddress dstIp) {
-        return tunnelType + "-" + dstIp.toString();
-    }
-
     @Override
     public ListenableFuture<DatabaseSchema> getOvsdbSchema(String dbName) {
         if (dbName == null) {
@@ -834,9 +796,8 @@
         return null;
     }
 
-    @Override
-    public ListenableFuture<List<OperationResult>> transactConfig(String dbName,
-                                                                  List<Operation> operations) {
+    private ListenableFuture<List<OperationResult>> transactConfig(String dbName,
+                                                                   List<Operation> operations) {
         if (dbName == null) {
             return null;
         }
@@ -958,11 +919,6 @@
     }
 
     @Override
-    public Set<OvsdbTunnel> getTunnels() {
-        return ovsdbTunnels;
-    }
-
-    @Override
     public Set<OvsdbBridge> getBridges() {
         Set<OvsdbBridge> ovsdbBridges = new HashSet<>();
         OvsdbTableStore tableStore = getTableStore(DATABASENAME);
diff --git a/protocols/ovsdb/api/src/test/java/org/onosproject/ovsdb/controller/driver/OvsdbClientServiceAdapter.java b/protocols/ovsdb/api/src/test/java/org/onosproject/ovsdb/controller/driver/OvsdbClientServiceAdapter.java
index c0aaf91..8601185 100644
--- a/protocols/ovsdb/api/src/test/java/org/onosproject/ovsdb/controller/driver/OvsdbClientServiceAdapter.java
+++ b/protocols/ovsdb/api/src/test/java/org/onosproject/ovsdb/controller/driver/OvsdbClientServiceAdapter.java
@@ -24,13 +24,11 @@
 import org.onosproject.net.behaviour.ControllerInfo;
 import org.onosproject.ovsdb.controller.OvsdbBridge;
 import org.onosproject.ovsdb.controller.OvsdbClientService;
+import org.onosproject.ovsdb.controller.OvsdbInterface;
 import org.onosproject.ovsdb.controller.OvsdbNodeId;
 import org.onosproject.ovsdb.controller.OvsdbPort;
-import org.onosproject.ovsdb.controller.OvsdbTunnel;
-import org.onosproject.ovsdb.rfc.message.OperationResult;
 import org.onosproject.ovsdb.rfc.message.TableUpdates;
 import org.onosproject.ovsdb.rfc.notation.Row;
-import org.onosproject.ovsdb.rfc.notation.Uuid;
 import org.onosproject.ovsdb.rfc.operations.Operation;
 import org.onosproject.ovsdb.rfc.schema.DatabaseSchema;
 
@@ -55,17 +53,20 @@
 
     @Override
     public void dropTunnel(IpAddress srcIp, IpAddress dstIp) {
-
     }
 
     @Override
-    public Set<OvsdbTunnel> getTunnels() {
-        return null;
+    public boolean createInterface(String bridgeName, OvsdbInterface ovsdbIface) {
+        return true;
+    }
+
+    @Override
+    public boolean dropInterface(String name) {
+        return true;
     }
 
     @Override
     public void createBridge(String bridgeName) {
-
     }
 
     @Override
@@ -80,7 +81,6 @@
 
     @Override
     public void dropBridge(String bridgeName) {
-
     }
 
     @Override
@@ -99,11 +99,6 @@
     }
 
     @Override
-    public void setControllersWithUuid(Uuid bridgeUuid, List<ControllerInfo> controllers) {
-
-    }
-
-    @Override
     public void setControllersWithDeviceId(DeviceId deviceId, List<ControllerInfo> controllers) {
 
     }
@@ -139,21 +134,6 @@
     }
 
     @Override
-    public String getInterfaceUuid(String portUuid, String portName) {
-        return null;
-    }
-
-    @Override
-    public String getControllerUuid(String controllerName, String controllerTarget) {
-        return null;
-    }
-
-    @Override
-    public String getOvsUuid(String dbName) {
-        return null;
-    }
-
-    @Override
     public ListenableFuture<DatabaseSchema> getOvsdbSchema(String dbName) {
         return null;
     }
@@ -164,11 +144,6 @@
     }
 
     @Override
-    public ListenableFuture<List<OperationResult>> transactConfig(String dbName, List<Operation> operations) {
-        return null;
-    }
-
-    @Override
     public DatabaseSchema getDatabaseSchema(String dbName) {
         return null;
     }