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/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;