[ONOS-6551] Tunnel implementation for L3VPN service.

Change-Id: I3171a83305cb7391d80fda94ddf567629a10675e
diff --git a/apps/l3vpn/BUCK b/apps/l3vpn/BUCK
index 1a59467..1ac39c1 100644
--- a/apps/l3vpn/BUCK
+++ b/apps/l3vpn/BUCK
@@ -7,6 +7,8 @@
     '//lib:onos-yang-model',
     '//lib:onos-yang-runtime',
     '//apps/yang:onos-apps-yang',
+    '//apps/pce/app:onos-apps-pce-app',
+    '//incubator/api:onos-incubator-api'
 ]
 
 TEST_DEPS = [
diff --git a/apps/l3vpn/src/main/java/org/onosproject/l3vpn/netl3vpn/BgpDriverInfo.java b/apps/l3vpn/src/main/java/org/onosproject/l3vpn/netl3vpn/BgpDriverInfo.java
index 13bc818..54ee93a 100644
--- a/apps/l3vpn/src/main/java/org/onosproject/l3vpn/netl3vpn/BgpDriverInfo.java
+++ b/apps/l3vpn/src/main/java/org/onosproject/l3vpn/netl3vpn/BgpDriverInfo.java
@@ -24,7 +24,7 @@
     /**
      * Model id level of the BGP information that needed to be added in store.
      */
-    private BgpModelIdLevel modIdLevel;
+    private ModelIdLevel modIdLevel;
 
     /**
      * Device id required for the creation of driver model object data.
@@ -37,7 +37,7 @@
      * @param m model id level for BGP
      * @param d device id
      */
-    public BgpDriverInfo(BgpModelIdLevel m, String d) {
+    public BgpDriverInfo(ModelIdLevel m, String d) {
         modIdLevel = m;
         devId = d;
     }
@@ -47,7 +47,7 @@
      *
      * @return model id level
      */
-    public BgpModelIdLevel modIdLevel() {
+    public ModelIdLevel modIdLevel() {
         return modIdLevel;
     }
 
diff --git a/apps/l3vpn/src/main/java/org/onosproject/l3vpn/netl3vpn/DeviceInfo.java b/apps/l3vpn/src/main/java/org/onosproject/l3vpn/netl3vpn/DeviceInfo.java
index 20cf1c5..9a2c49a 100644
--- a/apps/l3vpn/src/main/java/org/onosproject/l3vpn/netl3vpn/DeviceInfo.java
+++ b/apps/l3vpn/src/main/java/org/onosproject/l3vpn/netl3vpn/DeviceInfo.java
@@ -17,7 +17,6 @@
 package org.onosproject.l3vpn.netl3vpn;
 
 import org.onosproject.net.DeviceId;
-import org.onosproject.net.behaviour.L3VpnConfig;
 import org.onosproject.net.driver.DriverHandler;
 import org.onosproject.net.driver.DriverService;
 import org.onosproject.yang.model.ModelObjectData;
@@ -37,6 +36,11 @@
     private final DeviceId deviceId;
 
     /**
+     * Type of the VPN.
+     */
+    private final VpnType type;
+
+    /**
      * BGP information of the device.
      */
     private BgpInfo bgpInfo;
@@ -52,12 +56,24 @@
     private List<AccessInfo> accesses;
 
     /**
-     * Constructs device info with a device id.
+     * List of tunnel names belonging to the device.
+     */
+    private List<String> tnlNames;
+
+    /**
+     * Status of tunnel policy being created for this device in this VPN.
+     */
+    private boolean isTnlPolCreated;
+
+    /**
+     * Constructs device info with a device id and VPN type.
      *
      * @param d device id
+     * @param t VPN type
      */
-    public DeviceInfo(DeviceId d) {
+    public DeviceInfo(DeviceId d, VpnType t) {
         deviceId = d;
+        type = t;
     }
 
     /**
@@ -70,6 +86,15 @@
     }
 
     /**
+     * Returns the type of the VPN instance.
+     *
+     * @return VPN type
+     */
+    public VpnType type() {
+        return type;
+    }
+
+    /**
      * Adds a interface name to the list.
      *
      * @param ifName interface name
@@ -99,6 +124,56 @@
         this.ifNames = ifNames;
     }
 
+    /***
+     * Returns the list of tunnel names.
+     *
+     * @return tunnel names
+     */
+    public List<String> tnlNames() {
+        return tnlNames;
+    }
+
+    /**
+     * Sets the list of tunnel names.
+     *
+     * @param tnlNames tunnel names
+     */
+    public void tnlNames(List<String> tnlNames) {
+        this.tnlNames = tnlNames;
+    }
+
+    /**
+     * Adds a tunnel name to the list.
+     *
+     * @param tnlName tunnel name
+     */
+    public void addTnlName(String tnlName) {
+        if (tnlNames == null) {
+            tnlNames = new LinkedList<>();
+        }
+        tnlNames.add(tnlName);
+    }
+
+    /**
+     * Returns true if tunnel policy is created for this device in this VPN;
+     * false otherwise.
+     *
+     * @return true if tunnel policy is created; false otherwise
+     */
+    public boolean isTnlPolCreated() {
+        return isTnlPolCreated;
+    }
+
+    /**
+     * Sets true if tunnel policy is created for this device in this VPN;
+     * false otherwise.
+     *
+     * @param tnlPolCreated status of tunnel policy creation
+     */
+    public void setTnlPolCreated(boolean tnlPolCreated) {
+        isTnlPolCreated = tnlPolCreated;
+    }
+
     /**
      * Returns the BGP information.
      *
@@ -159,7 +234,7 @@
     public ModelObjectData processCreateInstance(DriverService driverSvc,
                                                  ModelObjectData modelData) {
         L3VpnConfig config = getL3VpnConfig(driverSvc);
-        return (ModelObjectData) config.createInstance(modelData);
+        return config.createInstance(modelData);
     }
 
     /**
@@ -174,7 +249,7 @@
     public ModelObjectData processCreateInterface(DriverService driverSvc,
                                                   ModelObjectData modData) {
         L3VpnConfig config = getL3VpnConfig(driverSvc);
-        return (ModelObjectData) config.bindInterface(modData);
+        return config.bindInterface(modData);
     }
 
     /**
@@ -191,7 +266,67 @@
                                                 BgpInfo bgpInfo,
                                                 BgpDriverInfo driverInfo) {
         L3VpnConfig config = getL3VpnConfig(driverSvc);
-        return (ModelObjectData) config.createBgpInfo(bgpInfo, driverInfo);
+        return config.createBgpInfo(bgpInfo, driverInfo);
+    }
+
+    /**
+     * Processes the creation of tunnel tree from the devices and device
+     * level. It returns the tunnel info with devices and device of driver
+     * constructed model object data.
+     *
+     * @param driverSvc driver service
+     * @param tnlInfo   tunnel info
+     * @return driver model object data of tunnel info with devices and device
+     */
+    public ModelObjectData processCreateTnlDev(DriverService driverSvc,
+                                               TunnelInfo tnlInfo) {
+        L3VpnConfig config = getL3VpnConfig(driverSvc);
+        return config.createTnlDev(tnlInfo);
+    }
+
+    /**
+     * Processes the creation of tunnel policy in the tree from the tunnel
+     * manager or tunnel policy level. It returns the tunnel info with
+     * tunnel policy level of driver constructed model object data.
+     *
+     * @param driverSvc driver service
+     * @param tnlInfo   tunnel info
+     * @return driver model object data of tunnel info with tunnel policy
+     */
+    public ModelObjectData processCreateTnlPol(DriverService driverSvc,
+                                               TunnelInfo tnlInfo) {
+        L3VpnConfig config = getL3VpnConfig(driverSvc);
+        return config.createTnlPol(tnlInfo);
+    }
+
+    /**
+     * Processes the creation of tunnel in the tree from the tunnel next hops
+     * or only tunnel next hop. It returns the tunnel info with tunnel level
+     * of driver constructed model object data
+     *
+     * @param driverSvc driver service
+     * @param tnlInfo   tunnel info
+     * @return driver model object data of tunnel info with tunnel
+     */
+    public ModelObjectData processCreateTnl(DriverService driverSvc,
+                                            TunnelInfo tnlInfo) {
+        L3VpnConfig config = getL3VpnConfig(driverSvc);
+        return config.createTnl(tnlInfo);
+    }
+
+    /**
+     * Processes the binding of tunnel policy to the VPN instance. It returns
+     * the VPN instance with tunnel policy of driver constructed model object
+     * data.
+     *
+     * @param driverSvc driver service
+     * @param tnlInfo   tunnel info
+     * @return driver model object data of VPN instance with tunnel
+     */
+    public ModelObjectData processBindTnl(DriverService driverSvc,
+                                          TunnelInfo tnlInfo) {
+        L3VpnConfig config = getL3VpnConfig(driverSvc);
+        return config.bindTnl(tnlInfo);
     }
 
     /**
@@ -206,7 +341,7 @@
     public ModelObjectData processDeleteInstance(DriverService driverSvc,
                                                  ModelObjectData modData) {
         L3VpnConfig config = getL3VpnConfig(driverSvc);
-        return (ModelObjectData) config.deleteInstance(modData);
+        return config.deleteInstance(modData);
     }
 
     /**
@@ -238,7 +373,22 @@
                                                 BgpInfo bgpInfo,
                                                 BgpDriverInfo driverInfo) {
         L3VpnConfig config = getL3VpnConfig(driverSvc);
-        return (ModelObjectData) config.deleteBgpInfo(bgpInfo, driverInfo);
+        return config.deleteBgpInfo(bgpInfo, driverInfo);
+    }
+
+    /**
+     * Processes the deletion of tunnel info according to the levels it has
+     * to be deleted. It returns the tunnel info of driver constructed model
+     * object data.
+     *
+     * @param driverSvc driver service
+     * @param tnlInfo   tunnel info
+     * @return driver tunnel info model object data
+     */
+    public ModelObjectData processDeleteTnl(DriverService driverSvc,
+                                            TunnelInfo tnlInfo) {
+        L3VpnConfig config = getL3VpnConfig(driverSvc);
+        return config.deleteTnl(tnlInfo);
     }
 
     /**
diff --git a/apps/l3vpn/src/main/java/org/onosproject/l3vpn/netl3vpn/L3VpnConfig.java b/apps/l3vpn/src/main/java/org/onosproject/l3vpn/netl3vpn/L3VpnConfig.java
new file mode 100644
index 0000000..bfc8164
--- /dev/null
+++ b/apps/l3vpn/src/main/java/org/onosproject/l3vpn/netl3vpn/L3VpnConfig.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.l3vpn.netl3vpn;
+
+import org.onosproject.net.driver.HandlerBehaviour;
+import org.onosproject.yang.model.ModelObjectData;
+
+/**
+ * Behaviour for handling various drivers for l3vpn configurations.
+ */
+public interface L3VpnConfig extends HandlerBehaviour {
+
+    /**
+     * Create virtual routing forwarding instance on requested device with
+     * given standard device model object data.
+     *
+     * @param objectData standard device model object data
+     * @return device model object data
+     */
+    ModelObjectData createInstance(ModelObjectData objectData);
+
+    /**
+     * Binds requested virtual routing forwarding instance to interface on the
+     * requested device with given standard device model object data.
+     *
+     * @param objectData standard device model object data
+     * @return device model object data
+     */
+    ModelObjectData bindInterface(ModelObjectData objectData);
+
+    /**
+     * Deletes virtual routing forwarding instance on requested device with
+     * given standard device model object data.
+     *
+     * @param objectData standard device model object data
+     * @return device model object data
+     */
+    ModelObjectData deleteInstance(ModelObjectData objectData);
+
+    /**
+     * Unbinds requested virtual routing forwarding instance to interface on the
+     * requested device with given standard device model object data.
+     *
+     * @param objectData standard device model object data
+     * @return device model object data
+     */
+    ModelObjectData unbindInterface(ModelObjectData objectData);
+
+    /**
+     * Deletes tunnel on requested device with the given tunnel info.
+     *
+     * @param tnlInfo tunnel info
+     * @return device model object data
+     */
+    ModelObjectData deleteTnl(TunnelInfo tnlInfo);
+
+    /**
+     * Creates BGP routing protocol info on requested device with given
+     * BGP info object.
+     *
+     * @param bgpInfo   BGP info object
+     * @param bgpConfig BGP driver config
+     * @return device model object data
+     */
+    ModelObjectData createBgpInfo(BgpInfo bgpInfo, BgpDriverInfo bgpConfig);
+
+    /**
+     * Deletes BGP routing protocol info on requested device with given
+     * BGP info object.
+     *
+     * @param bgpInfo   BGP info object
+     * @param bgpConfig BGP driver config
+     * @return device model object data
+     */
+    ModelObjectData deleteBgpInfo(BgpInfo bgpInfo, BgpDriverInfo bgpConfig);
+
+    /**
+     * Creates device and devices level on requested device for tunnel creation.
+     *
+     * @param tnlInfo tunnel info
+     * @return device model object data
+     */
+    ModelObjectData createTnlDev(TunnelInfo tnlInfo);
+
+    /**
+     * Creates tunnel policy on requested device with given tunnel info.
+     *
+     * @param tnlInfo tunnel info
+     * @return device model object data
+     */
+    ModelObjectData createTnlPol(TunnelInfo tnlInfo);
+
+    /**
+     * Creates tunnel on requested device with given tunnel info.
+     *
+     * @param tnlInfo tunnel info
+     * @return device model object data
+     */
+    ModelObjectData createTnl(TunnelInfo tnlInfo);
+
+    /**
+     * Binds requested tunnel policy name to the VPN to the requested device
+     * with given tunnel info.
+     *
+     * @param tnlInfo tunnel info
+     * @return device model object data
+     */
+    ModelObjectData bindTnl(TunnelInfo tnlInfo);
+}
diff --git a/apps/l3vpn/src/main/java/org/onosproject/l3vpn/netl3vpn/BgpModelIdLevel.java b/apps/l3vpn/src/main/java/org/onosproject/l3vpn/netl3vpn/ModelIdLevel.java
similarity index 73%
rename from apps/l3vpn/src/main/java/org/onosproject/l3vpn/netl3vpn/BgpModelIdLevel.java
rename to apps/l3vpn/src/main/java/org/onosproject/l3vpn/netl3vpn/ModelIdLevel.java
index e5c76b1..91bf248 100644
--- a/apps/l3vpn/src/main/java/org/onosproject/l3vpn/netl3vpn/BgpModelIdLevel.java
+++ b/apps/l3vpn/src/main/java/org/onosproject/l3vpn/netl3vpn/ModelIdLevel.java
@@ -17,10 +17,10 @@
 package org.onosproject.l3vpn.netl3vpn;
 
 /**
- * Represents the model id level of BGP information to be added to store.
- * //TODO: Further more levels of BGP addition has to be added.
+ * Represents the model id level to add it in the store.
+ * //TODO: Further levels has to be added.
  */
-public enum BgpModelIdLevel {
+public enum ModelIdLevel {
 
     /**
      * Requested model id level is not present, representing top node.
@@ -40,5 +40,20 @@
     /**
      * Requested model id level is VPN list.
      */
-    VPN
+    VPN,
+
+    /**
+     * Requested model id level is tunnel manager.
+     */
+    TNL_M,
+
+    /**
+     * Requested model id level is tunnel policy.
+     */
+    TNL_POL,
+
+    /**
+     * Requested model id level is tunnel hop.
+     */
+    TP_HOP
 }
diff --git a/apps/l3vpn/src/main/java/org/onosproject/l3vpn/netl3vpn/NetL3VpnStore.java b/apps/l3vpn/src/main/java/org/onosproject/l3vpn/netl3vpn/NetL3VpnStore.java
index 8d63809..db926a2 100644
--- a/apps/l3vpn/src/main/java/org/onosproject/l3vpn/netl3vpn/NetL3VpnStore.java
+++ b/apps/l3vpn/src/main/java/org/onosproject/l3vpn/netl3vpn/NetL3VpnStore.java
@@ -55,6 +55,13 @@
     Map<AccessInfo, InterfaceInfo> getInterfaceInfo();
 
     /**
+     * Returns the tunnel information map available in the store, for a device.
+     *
+     * @return tunnel info map
+     */
+    Map<DeviceId, Integer> getTunnelInfo();
+
+    /**
      * Adds freed id to the freed list in the store.
      *
      * @param id id
@@ -95,6 +102,14 @@
     void addBgpInfo(BgpInfo bgpInfo, DeviceId devId);
 
     /**
+     * Adds the device id and the number of tunnels created for that device.
+     *
+     * @param devId device id
+     * @param count number of tunnels
+     */
+    void addTunnelInfo(DeviceId devId, Integer count);
+
+    /**
      * Removes the interface info with the key access info from the store.
      *
      * @param accessInfo access info
@@ -127,4 +142,13 @@
      * @return true if removed; false otherwise
      */
     boolean removeBgpInfo(BgpInfo bgpInfo);
+
+    /**
+     * Removes the device id from the store with the value count of number of
+     * tunnels.
+     *
+     * @param id device id
+     * @return true if removed; false otherwise
+     */
+    boolean removeTunnelInfo(DeviceId id);
 }
diff --git a/apps/l3vpn/src/main/java/org/onosproject/l3vpn/netl3vpn/TunnelInfo.java b/apps/l3vpn/src/main/java/org/onosproject/l3vpn/netl3vpn/TunnelInfo.java
new file mode 100644
index 0000000..db8c9c6
--- /dev/null
+++ b/apps/l3vpn/src/main/java/org/onosproject/l3vpn/netl3vpn/TunnelInfo.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.l3vpn.netl3vpn;
+
+/**
+ * Represents the tunnel information.
+ */
+public class TunnelInfo {
+
+    /**
+     * Destination ip address.
+     */
+    private final String desIp;
+
+    /**
+     * Tunnel name.
+     */
+    private final String tnlName;
+
+    /**
+     * Tunnel policy name.
+     */
+    private final String polName;
+
+    /**
+     * Device id.
+     */
+    private final String devId;
+
+    /**
+     * Level of the model.
+     */
+    private ModelIdLevel level;
+
+    /**
+     * Creates tunnel info with destination ip address, tunnel name, tunnel
+     * policy name and device id.
+     *
+     * @param dIp   destination ip
+     * @param tName tunnel name
+     * @param pName tunnel policy name
+     * @param dId   device id
+     */
+    public TunnelInfo(String dIp, String tName, String pName, String dId) {
+        this.desIp = dIp;
+        this.tnlName = tName;
+        this.polName = pName;
+        this.devId = dId;
+    }
+
+    /**
+     * Returns the destination ip-address.
+     *
+     * @return destination ip-address
+     */
+    public String desIp() {
+        return desIp;
+    }
+
+    /**
+     * Returns the tunnel name.
+     *
+     * @return tunnel name
+     */
+    public String tnlName() {
+        return tnlName;
+    }
+
+    /**
+     * Returns the tunnel policy name.
+     *
+     * @return tunnel policy name
+     */
+    public String polName() {
+        return polName;
+    }
+
+    /**
+     * Returns the device id.
+     *
+     * @return device id
+     */
+    public String devId() {
+        return devId;
+    }
+
+    /**
+     * Returns the model id level.
+     *
+     * @return model id level
+     */
+    public ModelIdLevel level() {
+        return level;
+    }
+
+    /**
+     * Sets the model id level.
+     *
+     * @param level model id level
+     */
+    public void level(ModelIdLevel level) {
+        this.level = level;
+    }
+}
diff --git a/apps/l3vpn/src/main/java/org/onosproject/l3vpn/netl3vpn/impl/DistributedNetL3VpnStore.java b/apps/l3vpn/src/main/java/org/onosproject/l3vpn/netl3vpn/impl/DistributedNetL3VpnStore.java
index 6fa2cfd..28a90da 100644
--- a/apps/l3vpn/src/main/java/org/onosproject/l3vpn/netl3vpn/impl/DistributedNetL3VpnStore.java
+++ b/apps/l3vpn/src/main/java/org/onosproject/l3vpn/netl3vpn/impl/DistributedNetL3VpnStore.java
@@ -32,6 +32,7 @@
 import org.onosproject.l3vpn.netl3vpn.NetL3VpnStore;
 import org.onosproject.l3vpn.netl3vpn.ProtocolInfo;
 import org.onosproject.l3vpn.netl3vpn.RouteProtocol;
+import org.onosproject.l3vpn.netl3vpn.TunnelInfo;
 import org.onosproject.l3vpn.netl3vpn.VpnConfig;
 import org.onosproject.l3vpn.netl3vpn.VpnInstance;
 import org.onosproject.l3vpn.netl3vpn.VpnType;
@@ -81,6 +82,7 @@
                            .register(BgpInfo.class)
                            .register(RouteProtocol.class)
                            .register(ProtocolInfo.class)
+                           .register(TunnelInfo.class)
                            .build());
 
     private static final String FREE_ID_NULL = "Free ID cannot be null";
@@ -116,6 +118,11 @@
      */
     private ConsistentMap<BgpInfo, DeviceId> bgpInfoMap;
 
+    /**
+     * Map of device id and tunnel count.
+     */
+    private ConsistentMap<DeviceId, Integer> tunnelInfoMap;
+
     @Activate
     protected void activate() {
         vpnInsMap = storageService.<String, VpnInstance>consistentMapBuilder()
@@ -134,6 +141,11 @@
                 .withSerializer(L3VPN_SERIALIZER)
                 .build();
 
+        tunnelInfoMap = storageService.<DeviceId, Integer>consistentMapBuilder()
+                .withName("onos-l3vpn-tnl-info-map")
+                .withSerializer(L3VPN_SERIALIZER)
+                .build();
+
         freedIdList = storageService.<Long>setBuilder()
                 .withName("onos-l3vpn-id-freed-list")
                 .withSerializer(Serializer.using(KryoNamespaces.API))
@@ -175,6 +187,13 @@
     }
 
     @Override
+    public Map<DeviceId, Integer> getTunnelInfo() {
+        return tunnelInfoMap.entrySet().stream()
+                .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue()
+                        .value()));
+    }
+
+    @Override
     public void addIdToFreeList(Long id) {
         checkNotNull(id, FREE_ID_NULL);
         freedIdList.add(id);
@@ -203,12 +222,18 @@
 
     @Override
     public void addBgpInfo(BgpInfo bgpInfo, DeviceId devId) {
-        checkNotNull(devId, BGP_INFO_NULL);
+        checkNotNull(bgpInfo, BGP_INFO_NULL);
         checkNotNull(devId, DEV_ID_NULL);
         bgpInfoMap.put(bgpInfo, devId);
     }
 
     @Override
+    public void addTunnelInfo(DeviceId devId, Integer count) {
+        checkNotNull(devId, DEV_ID_NULL);
+        tunnelInfoMap.put(devId, count);
+    }
+
+    @Override
     public boolean removeInterfaceInfo(AccessInfo accessInfo) {
         checkNotNull(accessInfo, ACCESS_INFO_NULL);
 
@@ -255,4 +280,15 @@
         }
         return true;
     }
+
+    @Override
+    public boolean removeTunnelInfo(DeviceId id) {
+        checkNotNull(id, DEV_ID_NULL);
+
+        if (tunnelInfoMap.remove(id) == null) {
+            log.error("Device id deletion in tunnel info has failed.");
+            return false;
+        }
+        return true;
+    }
 }
diff --git a/apps/l3vpn/src/main/java/org/onosproject/l3vpn/netl3vpn/impl/NetL3VpnManager.java b/apps/l3vpn/src/main/java/org/onosproject/l3vpn/netl3vpn/impl/NetL3VpnManager.java
index cc0d51e..3b45c7d 100644
--- a/apps/l3vpn/src/main/java/org/onosproject/l3vpn/netl3vpn/impl/NetL3VpnManager.java
+++ b/apps/l3vpn/src/main/java/org/onosproject/l3vpn/netl3vpn/impl/NetL3VpnManager.java
@@ -48,11 +48,11 @@
 import org.onosproject.l3vpn.netl3vpn.VpnInstance;
 import org.onosproject.l3vpn.netl3vpn.VpnSiteRole;
 import org.onosproject.l3vpn.netl3vpn.VpnType;
-import org.onosproject.net.Device;
 import org.onosproject.net.DeviceId;
 import org.onosproject.net.Port;
 import org.onosproject.net.device.DeviceService;
 import org.onosproject.net.driver.DriverService;
+import org.onosproject.pce.pceservice.api.PceService;
 import org.onosproject.yang.gen.v1.ietfinterfaces.rev20140508.ietfinterfaces.devices.device.Interfaces;
 import org.onosproject.yang.gen.v1.ietfl3vpnsvc.rev20160730.ietfl3vpnsvc.DefaultL3VpnSvc;
 import org.onosproject.yang.gen.v1.ietfl3vpnsvc.rev20160730.ietfl3vpnsvc.L3VpnSvc;
@@ -67,8 +67,6 @@
 import org.onosproject.yang.gen.v1.ietfl3vpnsvc.rev20160730.ietfl3vpnsvc.l3vpnsvc.sites.site.sitenetworkaccesses.SiteNetworkAccess;
 import org.onosproject.yang.gen.v1.ietfl3vpnsvc.rev20160730.ietfl3vpnsvc.l3vpnsvc.vpnservices.VpnSvc;
 import org.onosproject.yang.gen.v1.ietfl3vpnsvc.rev20160730.ietfl3vpnsvc.siteattachmentbearer.Bearer;
-import org.onosproject.yang.gen.v1.ietfl3vpnsvc.rev20160730.ietfl3vpnsvc.siteattachmentbearer.DefaultBearer;
-import org.onosproject.yang.gen.v1.ietfl3vpnsvc.rev20160730.ietfl3vpnsvc.siteattachmentbearer.bearer.DefaultRequestedType;
 import org.onosproject.yang.gen.v1.ietfl3vpnsvc.rev20160730.ietfl3vpnsvc.siteattachmentbearer.bearer.RequestedType;
 import org.onosproject.yang.gen.v1.ietfl3vpnsvc.rev20160730.ietfl3vpnsvc.siteattachmentipconnection.IpConnection;
 import org.onosproject.yang.gen.v1.ietfl3vpnsvc.rev20160730.ietfl3vpnsvc.siterouting.RoutingProtocols;
@@ -111,7 +109,6 @@
 import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.ID_LIMIT;
 import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.ID_LIMIT_EXCEEDED;
 import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.INT_INFO_NULL;
-import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.IP;
 import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.IP_INT_INFO_NULL;
 import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.MAX_BATCH_MS;
 import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.MAX_EVENTS;
@@ -125,9 +122,9 @@
 import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.VPN_POLICY_NOT_SUPPORTED;
 import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.VPN_TYPE_UNSUPPORTED;
 import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.getBgpCreateConfigObj;
+import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.getId;
 import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.getIntCreateModObj;
 import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.getIntNotAvailable;
-import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.getMgmtIpUnAvailErr;
 import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.getModIdForL3VpnSvc;
 import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.getModIdForSites;
 import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.getResourceData;
@@ -144,6 +141,7 @@
 
     private static final String APP_ID = "org.onosproject.app.l3vpn";
     private static final String L3_VPN_ID_TOPIC = "l3vpn-id";
+    private static final String TNL_ID_TOPIC = "l3vpn-tnl-id";
 
     private final Logger log = LoggerFactory.getLogger(getClass());
 
@@ -180,8 +178,13 @@
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected ClusterService clusterService;
 
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected PceService pceService;
+
     protected IdGenerator l3VpnIdGen;
 
+    protected IdGenerator tnlIdGen;
+
     private NodeId localNodeId;
 
     private ApplicationId appId;
@@ -194,15 +197,21 @@
 
     private boolean isElectedLeader;
 
+    private NetL3VpnTunnelHandler tnlHandler;
+
     @Activate
     protected void activate() {
         appId = coreService.registerApplication(APP_ID);
         l3VpnIdGen = coreService.getIdGenerator(L3_VPN_ID_TOPIC);
+        tnlIdGen = coreService.getIdGenerator(TNL_ID_TOPIC);
         localNodeId = clusterService.getLocalNode().id();
         leadershipService.addListener(leadershipEventListener);
         leadershipService.runForLeadership(appId.name());
         getResourceId();
         configService.addListener(configListener);
+        tnlHandler = new NetL3VpnTunnelHandler(
+                pceService, driverService, configService, l3VpnStore,
+                deviceService, tnlIdGen, modelConverter);
         log.info("Started");
     }
 
@@ -526,8 +535,8 @@
      */
     private DeviceInfo buildDevVpnIns(Bearer bearer, VpnInstance ins,
                                       VpnSiteRole role, IpConnection connect) {
-        DefaultAugmentedL3VpnBearer augBearer = ((DefaultBearer) bearer)
-                .augmentation(DefaultAugmentedL3VpnBearer.class);
+        DefaultAugmentedL3VpnBearer augBearer = bearer.augmentation(
+                DefaultAugmentedL3VpnBearer.class);
         DeviceId id = getDeviceId(augBearer);
         Map<DeviceId, DeviceInfo> devices = ins.devInfo();
         DeviceInfo info = null;
@@ -554,24 +563,7 @@
             throw new NetL3VpnException(DEVICE_INFO_NULL);
         }
         String ip = attach.bearerAttachment().peMgmtIp().string();
-        return getId(ip);
-    }
-
-    /**
-     * Returns the device id whose management ip address matches with the ip
-     * received.
-     *
-     * @param ip ip address
-     * @return device id
-     */
-    public DeviceId getId(String ip) {
-        for (Device device : deviceService.getAvailableDevices()) {
-            String val = device.annotations().value(IP);
-            if (ip.equals(val)) {
-                return device.id();
-            }
-        }
-        throw new NetL3VpnException(getMgmtIpUnAvailErr(ip));
+        return getId(ip, true, deviceService.getAvailableDevices());
     }
 
     /**
@@ -588,21 +580,46 @@
                                          VpnInstance inst, IpConnection ip) {
         Map<AccessInfo, InterfaceInfo> intMap = l3VpnStore.getInterfaceInfo();
         generateRdRt(inst, role);
-        DeviceInfo info = new DeviceInfo(id);
+        DeviceInfo info = new DeviceInfo(id, role.role());
 
         NetworkInstances instances = createInstance(inst, role, ip);
         ModelObjectData devMod = getVpnCreateModObj(intMap, instances,
                                                     id.toString());
+        inst.addDevInfo(id, info);
+        l3VpnStore.addVpnIns(inst.vpnName(), inst);
+
         ModelObjectData driMod = info.processCreateInstance(driverService,
                                                             devMod);
         ResourceData resData = modelConverter.createDataNode(driMod);
         addToStore(resData);
-        l3VpnStore.addVpnIns(inst.vpnName(), inst);
-        inst.addDevInfo(id, info);
+        checkAndUpdateTunnel(inst, id);
         return info;
     }
 
     /**
+     * Checks if the tunnel can be established and creates the tunnel from
+     * source to destination.
+     *
+     * @param inst VPN instance
+     * @param id   device id
+     */
+    private void checkAndUpdateTunnel(VpnInstance inst, DeviceId id) {
+        Map<DeviceId, DeviceInfo> devInfo = inst.devInfo();
+        int devSize = devInfo.size();
+        String vpnName = inst.vpnName();
+        if (devSize != 1) {
+            DeviceInfo info = devInfo.get(id);
+            tnlHandler.createSrcInfo(vpnName, info);
+            for (Map.Entry<DeviceId, DeviceInfo> device : devInfo.entrySet()) {
+                DeviceInfo val = device.getValue();
+                if (val != info) {
+                    tnlHandler.createSrcDesTunnel(val);
+                }
+            }
+        }
+    }
+
+    /**
      * Adds the resource data that is received from the driver, after
      * converting from the model object data.
      *
@@ -737,9 +754,8 @@
      * @return interface name
      */
     private String getInterfaceName(DeviceInfo info, RequestedType reqType) {
-        DefaultAugmentedL3VpnRequestedType req =
-                ((DefaultRequestedType) reqType).augmentation(
-                        DefaultAugmentedL3VpnRequestedType.class);
+        DefaultAugmentedL3VpnRequestedType req = reqType.augmentation(
+                DefaultAugmentedL3VpnRequestedType.class);
         if (req == null || req.requestedTypeProfile() == null ||
                 req.requestedTypeProfile().requestedTypeChoice() == null) {
             throw new NetL3VpnException(INT_INFO_NULL);
@@ -925,6 +941,7 @@
                         driverService, devMod);
                 ResourceData resData = modelConverter.createDataNode(driMod);
                 deleteFromStore(resData);
+                tnlHandler.deleteTunnel(dev, instance.vpnName());
             }
             l3VpnStore.removeVpnInstance(instance.vpnName());
         }
diff --git a/apps/l3vpn/src/main/java/org/onosproject/l3vpn/netl3vpn/impl/NetL3VpnTunnelHandler.java b/apps/l3vpn/src/main/java/org/onosproject/l3vpn/netl3vpn/impl/NetL3VpnTunnelHandler.java
new file mode 100644
index 0000000..edef00a
--- /dev/null
+++ b/apps/l3vpn/src/main/java/org/onosproject/l3vpn/netl3vpn/impl/NetL3VpnTunnelHandler.java
@@ -0,0 +1,329 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.l3vpn.netl3vpn.impl;
+
+import org.onosproject.config.DynamicConfigService;
+import org.onosproject.core.IdGenerator;
+import org.onosproject.incubator.net.tunnel.Tunnel;
+import org.onosproject.l3vpn.netl3vpn.DeviceInfo;
+import org.onosproject.l3vpn.netl3vpn.ModelIdLevel;
+import org.onosproject.l3vpn.netl3vpn.NetL3VpnException;
+import org.onosproject.l3vpn.netl3vpn.NetL3VpnStore;
+import org.onosproject.l3vpn.netl3vpn.TunnelInfo;
+import org.onosproject.l3vpn.netl3vpn.VpnType;
+import org.onosproject.net.Device;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.driver.DriverService;
+import org.onosproject.pce.pceservice.api.PceService;
+import org.onosproject.yang.model.DataNode;
+import org.onosproject.yang.model.ModelConverter;
+import org.onosproject.yang.model.ModelObjectData;
+import org.onosproject.yang.model.ResourceData;
+
+import java.util.List;
+import java.util.Map;
+
+import static org.onosproject.l3vpn.netl3vpn.ModelIdLevel.DEVICE;
+import static org.onosproject.l3vpn.netl3vpn.ModelIdLevel.DEVICES;
+import static org.onosproject.l3vpn.netl3vpn.ModelIdLevel.TNL_M;
+import static org.onosproject.l3vpn.netl3vpn.ModelIdLevel.TNL_POL;
+import static org.onosproject.l3vpn.netl3vpn.ModelIdLevel.TP_HOP;
+import static org.onosproject.l3vpn.netl3vpn.VpnType.SPOKE;
+import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.NEW_NAME;
+import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.getId;
+import static org.onosproject.l3vpn.netl3vpn.impl.NetL3VpnUtil.getIpFromDevId;
+import static org.onosproject.pce.pceservice.LspType.WITH_SIGNALLING;
+
+/**
+ * Represents net l3VPN tunnel handler, which handles tunnel operations like
+ * creation and deletion and updating it to the driver.
+ */
+public class NetL3VpnTunnelHandler {
+
+    private PceService pceSvc;
+    private DriverService driSvc;
+    private DynamicConfigService configSvc;
+    private NetL3VpnStore store;
+    private DeviceService devSvc;
+    private IdGenerator tnlIdGen;
+    private ModelConverter modelCon;
+    private String sIp;
+    private String vpnName;
+    private DeviceInfo sInfo;
+    private VpnType type;
+
+    /**
+     * Constructs net l3VPN tunnel handler with required services.
+     *
+     * @param p   pce service
+     * @param d   driver service
+     * @param c   dynamic config service
+     * @param s   net l3VPN store
+     * @param dev device service
+     * @param id  ID generator
+     * @param m   model converter
+     */
+    public NetL3VpnTunnelHandler(PceService p, DriverService d,
+                                 DynamicConfigService c,
+                                 NetL3VpnStore s, DeviceService dev,
+                                 IdGenerator id, ModelConverter m) {
+        pceSvc = p;
+        driSvc = d;
+        configSvc = c;
+        store = s;
+        devSvc = dev;
+        tnlIdGen = id;
+        modelCon = m;
+    }
+
+    /**
+     * Creates the source information for tunnel creation. It creates from
+     * source device info and VPN name.
+     *
+     * @param vName   VPN name
+     * @param devInfo device info
+     */
+    public void createSrcInfo(String vName, DeviceInfo devInfo) {
+        vpnName = vName;
+        sInfo = devInfo;
+        type = devInfo.type();
+        sIp = getIpFromDevId(sInfo.deviceId());
+    }
+
+    /**
+     * Creates tunnel between source and destination devices.
+     *
+     * @param dInfo destination device
+     */
+    public void createSrcDesTunnel(DeviceInfo dInfo) {
+        VpnType dType = dInfo.type();
+        if (type == SPOKE && dType == SPOKE) {
+            return;
+        }
+        String dIp = getIpFromDevId(dInfo.deviceId());
+        createTunnelInfo(sIp, dIp, sInfo);
+        createTunnelInfo(dIp, sIp, dInfo);
+    }
+
+    /**
+     * Creates tunnel info and tunnel based on source and destination ip
+     * address and configures it in the source device.
+     *
+     * @param sIp   source ip address
+     * @param dIp   destination ip address
+     * @param sInfo source device info
+     */
+    private void createTunnelInfo(String sIp, String dIp, DeviceInfo sInfo) {
+        DeviceId id = sInfo.deviceId();
+        Map<DeviceId, Integer> tnlMap = store.getTunnelInfo();
+        int count = 0;
+        if (tnlMap.containsKey(id)) {
+            count = tnlMap.get(id);
+        }
+        String tnlName = createTunnel(sIp, dIp);
+        sInfo.addTnlName(tnlName);
+        store.addTunnelInfo(id, count + 1);
+        TunnelInfo tnl = new TunnelInfo(dIp, tnlName, vpnName, id.toString());
+        configureDevTnl(sInfo, tnl, tnlMap);
+    }
+
+    /**
+     * Creates tunnel between source ip address and destination ip address
+     * with pce service.
+     *
+     * @param srcIp source ip address
+     * @param desIp destination ip address
+     * @return tunnel name
+     */
+    private String createTunnel(String srcIp, String desIp) {
+        Iterable<Device> devices = devSvc.getAvailableDevices();
+        DeviceId srcDevId = getId(srcIp, false, devices);
+        DeviceId desDevId = getId(desIp, false, devices);
+        String name = getNewName();
+        boolean isCreated = pceSvc.setupPath(srcDevId, desDevId, name,
+                                             null, WITH_SIGNALLING);
+        if (!isCreated) {
+            throw new NetL3VpnException("Tunnel is not created between " +
+                                                srcDevId.toString() + " and " +
+                                                desDevId.toString());
+        }
+        return name;
+    }
+
+    /**
+     * Returns a unique name for tunnel to be created.
+     *
+     * @return unique tunnel name
+     */
+    private String getNewName() {
+        return NEW_NAME + String.valueOf(tnlIdGen.getNewId());
+    }
+
+    /**
+     * Configures the created tunnel to the device by processing it at the
+     * proper level and sending it to the driver.
+     *
+     * @param info    source device info
+     * @param tnlInfo tunnel info
+     * @param tnlMap  store tunnel map
+     */
+    private void configureDevTnl(DeviceInfo info, TunnelInfo tnlInfo,
+                                 Map<DeviceId, Integer> tnlMap) {
+        DeviceId id = info.deviceId();
+        int count = 0;
+        if (tnlMap.containsKey(id)) {
+            count = tnlMap.get(id);
+        }
+        if (tnlMap.size() == 0) {
+            tnlInfo.level(DEVICES);
+        } else if (count == 0) {
+            tnlInfo.level(DEVICE);
+        }
+
+        if (tnlInfo.level() != null) {
+            ModelObjectData mod = info.processCreateTnlDev(driSvc, tnlInfo);
+            addDataNodeToStore(mod);
+            tnlInfo.level(TNL_M);
+            tnlPolToStore(info, tnlInfo);
+        }
+        if (!info.isTnlPolCreated()) {
+            tnlInfo.level(TNL_POL);
+            tnlPolToStore(info, tnlInfo);
+        }
+        if (tnlInfo.level() == null) {
+            tnlInfo.level(TP_HOP);
+        }
+
+        ModelObjectData tnlMod = info.processCreateTnl(driSvc, tnlInfo);
+        addDataNodeToStore(tnlMod);
+        if (tnlInfo.level() != TP_HOP) {
+            ModelObjectData mod = info.processBindTnl(driSvc, tnlInfo);
+            addDataNodeToStore(mod);
+        }
+    }
+
+    /**
+     * Adds data node to the store after converting it to the resource data.
+     *
+     * @param driMod driver model object data
+     */
+    private void addDataNodeToStore(ModelObjectData driMod) {
+        ResourceData resData = modelCon.createDataNode(driMod);
+        addToStore(resData);
+    }
+
+    /**
+     * Adds resource data to the store.
+     *
+     * @param resData resource data
+     */
+    private void addToStore(ResourceData resData) {
+        if (resData != null && resData.dataNodes() != null) {
+            List<DataNode> dataNodes = resData.dataNodes();
+            for (DataNode node : dataNodes) {
+                configSvc.createNode(resData.resourceId(), node);
+            }
+        }
+    }
+
+    /**
+     * Creates tunnel policy from driver and adds it to the store.
+     *
+     * @param info    device info
+     * @param tnlInfo tunnel info
+     */
+    private void tnlPolToStore(DeviceInfo info, TunnelInfo tnlInfo) {
+        ModelObjectData mod = info.processCreateTnlPol(driSvc, tnlInfo);
+        addDataNodeToStore(mod);
+        info.setTnlPolCreated(true);
+    }
+
+    /**
+     * Deletes the tunnel with the source tunnel info and VPN name.
+     * //FIXME: PCE does'nt have api, which can give tunnel by providing the
+     * tunnel name.
+     *
+     * @param info  device info
+     * @param vName VPN name
+     */
+    public void deleteTunnel(DeviceInfo info, String vName) {
+        List<String> tnlNames = info.tnlNames();
+        for (String tnlName : tnlNames) {
+            Iterable<Tunnel> path = pceSvc.queryAllPath();
+            for (Tunnel tnl : path) {
+                if (tnl.tunnelName().toString().equals(tnlName)) {
+                    pceSvc.releasePath(tnl.tunnelId());
+                    break;
+                }
+            }
+        }
+        deleteFromDevice(info, vName);
+    }
+
+    /**
+     * Deletes tunnel configuration from the device by updating various
+     * levels in the store.
+     *
+     * @param info  device info
+     * @param vName VPN name
+     */
+    private void deleteFromDevice(DeviceInfo info, String vName) {
+        Map<DeviceId, Integer> map = store.getTunnelInfo();
+        DeviceId id = info.deviceId();
+        Integer count = map.get(id);
+        int tnlCount = info.tnlNames().size();
+        int upCount = count - tnlCount;
+        ModelIdLevel level;
+        TunnelInfo tnlInfo = new TunnelInfo(null, null, vName, id.toString());
+        if (upCount == 0) {
+            if (map.size() == 1) {
+                level = DEVICES;
+            } else {
+                level = DEVICE;
+            }
+        } else {
+            if (map.size() > 1) {
+                level = TNL_POL;
+            } else {
+                return;
+            }
+        }
+        tnlInfo.level(level);
+        ModelObjectData mod = info.processDeleteTnl(driSvc, tnlInfo);
+        deleteFromStore(mod);
+        info.tnlNames(null);
+        info.setTnlPolCreated(false);
+        if (upCount == 0) {
+            store.removeTunnelInfo(id);
+        } else {
+            store.addTunnelInfo(id, upCount);
+        }
+    }
+
+    /**
+     * Deletes the data node from the store.
+     *
+     * @param mod driver model object data
+     */
+    private void deleteFromStore(ModelObjectData mod) {
+        ResourceData resData = modelCon.createDataNode(mod);
+        if (resData != null) {
+            configSvc.deleteNode(resData.resourceId());
+        }
+    }
+}
diff --git a/apps/l3vpn/src/main/java/org/onosproject/l3vpn/netl3vpn/impl/NetL3VpnUtil.java b/apps/l3vpn/src/main/java/org/onosproject/l3vpn/netl3vpn/impl/NetL3VpnUtil.java
index 1dbb008..1fd03bd 100644
--- a/apps/l3vpn/src/main/java/org/onosproject/l3vpn/netl3vpn/impl/NetL3VpnUtil.java
+++ b/apps/l3vpn/src/main/java/org/onosproject/l3vpn/netl3vpn/impl/NetL3VpnUtil.java
@@ -46,10 +46,10 @@
 import java.util.List;
 import java.util.Map;
 
-import static org.onosproject.l3vpn.netl3vpn.BgpModelIdLevel.DEVICE;
-import static org.onosproject.l3vpn.netl3vpn.BgpModelIdLevel.DEVICES;
-import static org.onosproject.l3vpn.netl3vpn.BgpModelIdLevel.ROOT;
-import static org.onosproject.l3vpn.netl3vpn.BgpModelIdLevel.VPN;
+import static org.onosproject.l3vpn.netl3vpn.ModelIdLevel.DEVICE;
+import static org.onosproject.l3vpn.netl3vpn.ModelIdLevel.DEVICES;
+import static org.onosproject.l3vpn.netl3vpn.ModelIdLevel.ROOT;
+import static org.onosproject.l3vpn.netl3vpn.ModelIdLevel.VPN;
 import static org.onosproject.l3vpn.netl3vpn.VpnType.ANY_TO_ANY;
 import static org.onosproject.l3vpn.netl3vpn.VpnType.HUB;
 import static org.onosproject.l3vpn.netl3vpn.VpnType.SPOKE;
@@ -112,6 +112,11 @@
     static final String IP = "ipaddress";
 
     /**
+     * Static constant value for lsr id.
+     */
+    static final String LSR_ID = "lsrId";
+
+    /**
      * Error message for VPN type being not supported.
      */
     static final String VPN_TYPE_UNSUPPORTED = "The VPN type is not supported";
@@ -169,11 +174,17 @@
      */
     static final String EVENT_NULL = "Event cannot be null";
 
+    /**
+     * Unique tunnel name for net-l3VPN.
+     */
+    static final String NEW_NAME = "onos-netl3vpn";
+
     private static final String SITE_ROLE_INVALID = "The given site role is " +
             "invalid";
     private static final String ANY_TO_ANY_ROLE = "AnyToAnyRole";
     private static final String HUB_ROLE = "HubRole";
     private static final String SPOKE_ROLE = "SpokeRole";
+    private static final String COLON = ":";
 
     // No instantiation.
     private NetL3VpnUtil() {
@@ -515,4 +526,42 @@
         }
         return driInfo;
     }
+
+    /**
+     * Returns the device id whose management ip address or lsr ID matches with
+     * the ip or lsr ID received respectively.
+     *
+     * @param ip      value of ip or lsr id
+     * @param isIp    if ip or lsr id
+     * @param devices available devices
+     * @return device id
+     */
+    static DeviceId getId(String ip, boolean isIp,
+                          Iterable<org.onosproject.net.Device> devices) {
+        for (org.onosproject.net.Device device : devices) {
+            String val;
+            if (isIp) {
+                val = device.annotations().value(IP);
+            } else {
+                val = device.annotations().value(LSR_ID);
+            }
+            if (ip.equals(val)) {
+                return device.id();
+            }
+        }
+        throw new NetL3VpnException(getMgmtIpUnAvailErr(ip));
+    }
+
+    /**
+     * Returns ip address from the device id by parsing.
+     *
+     * @param devId device id
+     * @return ip address
+     */
+    static String getIpFromDevId(DeviceId devId) {
+        String devKey = devId.toString();
+        int firstInd = devKey.indexOf(COLON);
+        int secInd = devKey.indexOf(COLON, firstInd + 1);
+        return devKey.substring(firstInd + 1, secInd);
+    }
 }
diff --git a/core/api/src/main/java/org/onosproject/net/behaviour/L3VpnConfig.java b/core/api/src/main/java/org/onosproject/net/behaviour/L3VpnConfig.java
deleted file mode 100644
index de63d46..0000000
--- a/core/api/src/main/java/org/onosproject/net/behaviour/L3VpnConfig.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright 2017-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.net.behaviour;
-
-import org.onosproject.net.driver.HandlerBehaviour;
-
-/**
- * Behaviour for handling various drivers for l3vpn configurations.
- *
- * @deprecated in 1.11.0 ("Loon") release
- */
-@Deprecated
-public interface L3VpnConfig extends HandlerBehaviour {
-
-    /**
-     * Create virtual routing forwarding instance on requested device with
-     * given standard device model object data.
-     *
-     * @param objectData standard device model object data
-     * @return device model object data
-     */
-    Object createInstance(Object objectData);
-
-    /**
-     * Binds requested virtual routing forwarding instance to interface on the
-     * requested device with given standard device model object data.
-     *
-     * @param objectData standard device model object data
-     * @return device model object data
-     */
-    Object bindInterface(Object objectData);
-
-    /**
-     * Deletes virtual routing forwarding instance on requested device with
-     * given standard device model object data.
-     *
-     * @param objectData standard device model object data
-     * @return device model object data
-     */
-    Object deleteInstance(Object objectData);
-
-    /**
-     * Unbinds requested virtual routing forwarding instance to interface on the
-     * requested device with given standard device model object data.
-     *
-     * @param objectData standard device model object data
-     * @return device model object data
-     */
-    Object unbindInterface(Object objectData);
-
-    /**
-     * Creates BGP routing protocol info on requested device with given
-     * BGP info object.
-     *
-     * @param bgpInfo   BGP info object
-     * @param bgpConfig BGP driver config
-     * @return device model object data
-     */
-    Object createBgpInfo(Object bgpInfo, Object bgpConfig);
-
-    /**
-     * Deletes BGP routing protocol info on requested device with given
-     * BGP info object.
-     *
-     * @param bgpInfo   BGP info object
-     * @param bgpConfig BGP driver config
-     * @return device model object data
-     */
-    Object deleteBgpInfo(Object bgpInfo, Object bgpConfig);
-}
diff --git a/drivers/huawei/src/main/java/org/onosproject/drivers/huawei/BgpConstructionUtil.java b/drivers/huawei/src/main/java/org/onosproject/drivers/huawei/BgpConstructionUtil.java
index 4f82a4a..b385252 100644
--- a/drivers/huawei/src/main/java/org/onosproject/drivers/huawei/BgpConstructionUtil.java
+++ b/drivers/huawei/src/main/java/org/onosproject/drivers/huawei/BgpConstructionUtil.java
@@ -18,7 +18,7 @@
 
 import org.onosproject.l3vpn.netl3vpn.BgpDriverInfo;
 import org.onosproject.l3vpn.netl3vpn.BgpInfo;
-import org.onosproject.l3vpn.netl3vpn.BgpModelIdLevel;
+import org.onosproject.l3vpn.netl3vpn.ModelIdLevel;
 import org.onosproject.l3vpn.netl3vpn.ProtocolInfo;
 import org.onosproject.l3vpn.netl3vpn.RouteProtocol;
 import org.onosproject.yang.gen.v1.nebgpcomm.rev20141225.nebgpcomm.DefaultDevices;
@@ -91,7 +91,7 @@
     static ModelObjectData getCreateBgp(BgpInfo bgpInfo,
                                         BgpDriverInfo config) {
         String devId = config.devId();
-        BgpModelIdLevel modIdLevel = config.modIdLevel();
+        ModelIdLevel modIdLevel = config.modIdLevel();
 
         Bgp bgp = new DefaultBgp();
         Bgpcomm bgpBuilder = new DefaultBgpcomm();
@@ -246,7 +246,7 @@
      * @param route      import route object
      * @return model object data
      */
-    public static ModelObjectData getModObjData(BgpModelIdLevel modIdLevel,
+    public static ModelObjectData getModObjData(ModelIdLevel modIdLevel,
                                                 Bgp bgp, String devId,
                                                 BgpVrf bgpVrf, ImportRoute route) {
         switch (modIdLevel) {
@@ -371,7 +371,7 @@
      */
     static ModelObjectData getDeleteBgp(BgpInfo bgpInfo,
                                         BgpDriverInfo bgpConfig) {
-        BgpModelIdLevel modIdLvl = bgpConfig.modIdLevel();
+        ModelIdLevel modIdLvl = bgpConfig.modIdLevel();
         switch (modIdLvl) {
             case ROOT:
                 return getDelRootModObj();
diff --git a/drivers/huawei/src/main/java/org/onosproject/drivers/huawei/HuaweiL3VpnConfig.java b/drivers/huawei/src/main/java/org/onosproject/drivers/huawei/HuaweiL3VpnConfig.java
index 63519f2..2c08d36 100644
--- a/drivers/huawei/src/main/java/org/onosproject/drivers/huawei/HuaweiL3VpnConfig.java
+++ b/drivers/huawei/src/main/java/org/onosproject/drivers/huawei/HuaweiL3VpnConfig.java
@@ -21,7 +21,8 @@
 import org.onosproject.config.FailedException;
 import org.onosproject.l3vpn.netl3vpn.BgpDriverInfo;
 import org.onosproject.l3vpn.netl3vpn.BgpInfo;
-import org.onosproject.net.behaviour.L3VpnConfig;
+import org.onosproject.l3vpn.netl3vpn.L3VpnConfig;
+import org.onosproject.l3vpn.netl3vpn.TunnelInfo;
 import org.onosproject.net.driver.AbstractHandlerBehaviour;
 import org.onosproject.yang.model.DataNode;
 import org.onosproject.yang.model.ModelObjectData;
@@ -37,6 +38,11 @@
 import static org.onosproject.drivers.huawei.InsConstructionUtil.getCreateVpnIns;
 import static org.onosproject.drivers.huawei.InsConstructionUtil.getDeleteVpnIns;
 import static org.onosproject.drivers.huawei.IntConstructionUtil.getCreateInt;
+import static org.onosproject.drivers.huawei.TnlConstructionUtil.getBindTnl;
+import static org.onosproject.drivers.huawei.TnlConstructionUtil.getCreateTnl;
+import static org.onosproject.drivers.huawei.TnlConstructionUtil.getCreateTnlDev;
+import static org.onosproject.drivers.huawei.TnlConstructionUtil.getCreateTnlPol;
+import static org.onosproject.drivers.huawei.TnlConstructionUtil.getDeleteTnl;
 
 /**
  * Configures l3vpn on Huawei devices.
@@ -74,39 +80,64 @@
     }
 
     @Override
-    public Object createInstance(Object objectData) {
+    public ModelObjectData createInstance(ModelObjectData objectData) {
         if (modelRegistry == null) {
             init();
         }
-        return getCreateVpnIns((ModelObjectData) objectData,
-                               isDevicesPresent());
+        return getCreateVpnIns(objectData, isDevicesPresent());
     }
 
     @Override
-    public Object bindInterface(Object objectData) {
-        return getCreateInt((ModelObjectData) objectData);
+    public ModelObjectData bindInterface(ModelObjectData objectData) {
+        return getCreateInt(objectData);
     }
 
     @Override
-    public Object createBgpInfo(Object bgpInfo, Object bgpConfig) {
-        return getCreateBgp((BgpInfo) bgpInfo, (BgpDriverInfo) bgpConfig);
-    }
-
-
-    @Override
-    public Object deleteInstance(Object objectData) {
-        return getDeleteVpnIns((ModelObjectData) objectData);
+    public ModelObjectData createBgpInfo(BgpInfo bgpInfo,
+                                         BgpDriverInfo bgpConfig) {
+        return getCreateBgp(bgpInfo, bgpConfig);
     }
 
     @Override
-    public Object unbindInterface(Object objectData) {
+    public ModelObjectData createTnlDev(TunnelInfo tnlInfo) {
+        return getCreateTnlDev(tnlInfo);
+    }
+
+    @Override
+    public ModelObjectData createTnlPol(TunnelInfo tnlInfo) {
+        return getCreateTnlPol(tnlInfo);
+    }
+
+    @Override
+    public ModelObjectData createTnl(TunnelInfo tnlInfo) {
+        return getCreateTnl(tnlInfo);
+    }
+
+    @Override
+    public ModelObjectData bindTnl(TunnelInfo tnlInfo) {
+        return getBindTnl(tnlInfo);
+    }
+
+    @Override
+    public ModelObjectData deleteInstance(ModelObjectData objectData) {
+        return getDeleteVpnIns(objectData);
+    }
+
+    @Override
+    public ModelObjectData unbindInterface(ModelObjectData objectData) {
         //TODO:To be committed.
         return null;
     }
 
     @Override
-    public Object deleteBgpInfo(Object bgpInfo, Object bgpConfig) {
-        return getDeleteBgp((BgpInfo) bgpInfo, (BgpDriverInfo) bgpConfig);
+    public ModelObjectData deleteTnl(TunnelInfo tnlInfo) {
+        return getDeleteTnl(tnlInfo);
+    }
+
+    @Override
+    public ModelObjectData deleteBgpInfo(BgpInfo bgpInfo,
+                                         BgpDriverInfo bgpConfig) {
+        return getDeleteBgp(bgpInfo, bgpConfig);
     }
 
     /**
diff --git a/drivers/huawei/src/main/java/org/onosproject/drivers/huawei/HuaweiModelRegistrator.java b/drivers/huawei/src/main/java/org/onosproject/drivers/huawei/HuaweiModelRegistrator.java
index b4b3732..9f175e8 100644
--- a/drivers/huawei/src/main/java/org/onosproject/drivers/huawei/HuaweiModelRegistrator.java
+++ b/drivers/huawei/src/main/java/org/onosproject/drivers/huawei/HuaweiModelRegistrator.java
@@ -24,6 +24,8 @@
 import org.onosproject.yang.gen.v1.nel3vpnapi.rev20141225.NeL3VpnApi;
 import org.onosproject.yang.gen.v1.nel3vpncomm.rev20141225.NeL3Vpncomm;
 import org.onosproject.yang.gen.v1.nel3vpncommtype.rev20141225.NeL3VpncommType;
+import org.onosproject.yang.gen.v1.netnlm.rev20141225.NeTnlm;
+import org.onosproject.yang.gen.v1.netnlmtype.rev20141225.NeTnlmType;
 import org.onosproject.yang.model.DefaultYangModuleId;
 import org.onosproject.yang.model.YangModuleId;
 import org.onosproject.yang.runtime.AppModuleInfo;
@@ -58,6 +60,10 @@
                     new DefaultAppModuleInfo(NeL3Vpncomm.class, null));
         appInfo.put(new DefaultYangModuleId("ne-l3vpncomm-type", "2014-00-25"),
                     new DefaultAppModuleInfo(NeL3VpncommType.class, null));
+        appInfo.put(new DefaultYangModuleId("ne-tnlm", "2014-00-25"),
+                    new DefaultAppModuleInfo(NeTnlm.class, null));
+        appInfo.put(new DefaultYangModuleId("ne-tnlm-type", "2014-00-25"),
+                    new DefaultAppModuleInfo(NeTnlmType.class, null));
         return ImmutableMap.copyOf(appInfo);
     }
 }
diff --git a/drivers/huawei/src/main/java/org/onosproject/drivers/huawei/InsConstructionUtil.java b/drivers/huawei/src/main/java/org/onosproject/drivers/huawei/InsConstructionUtil.java
index 18b573a..eb7fedf 100644
--- a/drivers/huawei/src/main/java/org/onosproject/drivers/huawei/InsConstructionUtil.java
+++ b/drivers/huawei/src/main/java/org/onosproject/drivers/huawei/InsConstructionUtil.java
@@ -390,7 +390,7 @@
      * @param modObj model object data
      * @return driver model object data
      */
-    static Object getDeleteVpnIns(ModelObjectData modObj) {
+    static ModelObjectData getDeleteVpnIns(ModelObjectData modObj) {
         ModelIdLevel modIdLvl = DEVICE;
         String id = getIdFromModId(modObj.identifier(), true);
         Object obj = getObjFromModData(modObj);
@@ -472,7 +472,7 @@
      * @param id device id
      * @return model object id builder
      */
-    private static ModelObjectId.Builder getModObjIdDriDevice(String id) {
+    static ModelObjectId.Builder getModObjIdDriDevice(String id) {
         DeviceKeys key = new DeviceKeys();
         key.deviceid(id);
         return ModelObjectId.builder()
diff --git a/drivers/huawei/src/main/java/org/onosproject/drivers/huawei/TnlConstructionUtil.java b/drivers/huawei/src/main/java/org/onosproject/drivers/huawei/TnlConstructionUtil.java
new file mode 100644
index 0000000..1ba29dd
--- /dev/null
+++ b/drivers/huawei/src/main/java/org/onosproject/drivers/huawei/TnlConstructionUtil.java
@@ -0,0 +1,262 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.drivers.huawei;
+
+import org.onosproject.l3vpn.netl3vpn.TunnelInfo;
+import org.onosproject.yang.gen.v1.nel3vpncommtype.rev20141225.nel3vpncommtype.Ipv4Address;
+import org.onosproject.yang.gen.v1.nel3vpncommtype.rev20141225.nel3vpncommtype.L3VpncommonL3VpnPrefixType;
+import org.onosproject.yang.gen.v1.nel3vpnapi.rev20141225.nel3vpnapi.devices.device.DefaultL3Vpn;
+import org.onosproject.yang.gen.v1.nel3vpnapi.rev20141225.nel3vpnapi.devices.device.l3vpn.DefaultL3Vpncomm;
+import org.onosproject.yang.gen.v1.nel3vpnapi.rev20141225.nel3vpnapi.devices.device.l3vpn.l3vpncomm.DefaultL3VpnInstances;
+import org.onosproject.yang.gen.v1.nel3vpnapi.rev20141225.nel3vpnapi.devices.device.l3vpn.l3vpncomm.l3vpninstances.DefaultL3VpnInstance;
+import org.onosproject.yang.gen.v1.nel3vpnapi.rev20141225.nel3vpnapi.devices.device.l3vpn.l3vpncomm.l3vpninstances.L3VpnInstanceKeys;
+import org.onosproject.yang.gen.v1.nel3vpnapi.rev20141225.nel3vpnapi.devices.device.l3vpn.l3vpncomm.l3vpninstances.l3vpninstance.DefaultVpnInstAfs;
+import org.onosproject.yang.gen.v1.nel3vpnapi.rev20141225.nel3vpnapi.devices.device.l3vpn.l3vpncomm.l3vpninstances.l3vpninstance.vpninstafs.DefaultVpnInstAf;
+import org.onosproject.yang.gen.v1.nel3vpnapi.rev20141225.nel3vpnapi.devices.device.l3vpn.l3vpncomm.l3vpninstances.l3vpninstance.vpninstafs.VpnInstAfKeys;
+import org.onosproject.yang.gen.v1.netnlm.rev20141225.netnlm.DefaultDevices;
+import org.onosproject.yang.gen.v1.netnlm.rev20141225.netnlm.Devices;
+import org.onosproject.yang.gen.v1.netnlm.rev20141225.netnlm.devices.DefaultDevice;
+import org.onosproject.yang.gen.v1.netnlm.rev20141225.netnlm.devices.Device;
+import org.onosproject.yang.gen.v1.netnlm.rev20141225.netnlm.devices.DeviceKeys;
+import org.onosproject.yang.gen.v1.netnlm.rev20141225.netnlm.devices.device.DefaultTnlm;
+import org.onosproject.yang.gen.v1.netnlm.rev20141225.netnlm.devices.device.Tnlm;
+import org.onosproject.yang.gen.v1.netnlm.rev20141225.netnlm.devices.device.tnlm.DefaultTunnelPolicys;
+import org.onosproject.yang.gen.v1.netnlm.rev20141225.netnlm.devices.device.tnlm.TunnelPolicys;
+import org.onosproject.yang.gen.v1.netnlm.rev20141225.netnlm.devices.device.tnlm.tunnelpolicys.DefaultTunnelPolicy;
+import org.onosproject.yang.gen.v1.netnlm.rev20141225.netnlm.devices.device.tnlm.tunnelpolicys.TunnelPolicy;
+import org.onosproject.yang.gen.v1.netnlm.rev20141225.netnlm.devices.device.tnlm.tunnelpolicys.TunnelPolicyKeys;
+import org.onosproject.yang.gen.v1.netnlm.rev20141225.netnlm.devices.device.tnlm.tunnelpolicys.tunnelpolicy.DefaultTpNexthops;
+import org.onosproject.yang.gen.v1.netnlm.rev20141225.netnlm.devices.device.tnlm.tunnelpolicys.tunnelpolicy.TpNexthops;
+import org.onosproject.yang.gen.v1.netnlm.rev20141225.netnlm.devices.device.tnlm.tunnelpolicys.tunnelpolicy.tpnexthops.DefaultTpNexthop;
+import org.onosproject.yang.gen.v1.netnlm.rev20141225.netnlm.devices.device.tnlm.tunnelpolicys.tunnelpolicy.tpnexthops.TpNexthop;
+import org.onosproject.yang.gen.v1.netnlm.rev20141225.netnlm.devices.device.tnlm.tunnelpolicys.tunnelpolicy.tpnexthops.tpnexthop.DefaultTpTunnels;
+import org.onosproject.yang.gen.v1.netnlm.rev20141225.netnlm.devices.device.tnlm.tunnelpolicys.tunnelpolicy.tpnexthops.tpnexthop.TpTunnels;
+import org.onosproject.yang.gen.v1.netnlm.rev20141225.netnlm.devices.device.tnlm.tunnelpolicys.tunnelpolicy.tpnexthops.tpnexthop.tptunnels.DefaultTpTunnel;
+import org.onosproject.yang.gen.v1.netnlm.rev20141225.netnlm.devices.device.tnlm.tunnelpolicys.tunnelpolicy.tpnexthops.tpnexthop.tptunnels.TpTunnel;
+import org.onosproject.yang.gen.v1.netnlmtype.rev20141225.netnlmtype.tnlmbasetnlpolicytype.TnlmbaseTnlPolicyTypeEnum;
+import org.onosproject.yang.model.DefaultModelObjectData;
+import org.onosproject.yang.model.InnerModelObject;
+import org.onosproject.yang.model.LeafModelObject;
+import org.onosproject.yang.model.ModelObjectData;
+import org.onosproject.yang.model.ModelObjectId.Builder;
+
+import static org.onosproject.drivers.huawei.DriverUtil.UNSUPPORTED_MODEL_LVL;
+import static org.onosproject.drivers.huawei.DriverUtil.getData;
+import static org.onosproject.drivers.huawei.InsConstructionUtil.getModObjIdDriDevice;
+import static org.onosproject.l3vpn.netl3vpn.ModelIdLevel.TP_HOP;
+import static org.onosproject.yang.gen.v1.nel3vpncommtype.rev20141225.nel3vpncommtype.l3vpncommonl3vpnprefixtype.L3VpncommonL3VpnPrefixTypeEnum.IPV4UNI;
+import static org.onosproject.yang.gen.v1.nel3vpnapi.rev20141225.nel3vpnapi.devices.device.l3vpn.l3vpncomm.l3vpninstances.l3vpninstance.vpninstafs.VpnInstAf.LeafIdentifier.TNLPOLICYNAME;
+import static org.onosproject.yang.gen.v1.netnlmtype.rev20141225.netnlmtype.TnlmbaseTnlPolicyType.of;
+import static org.onosproject.yang.model.ModelObjectId.builder;
+
+/**
+ * Representation of utility for tunnel creation and deletion.
+ */
+public final class TnlConstructionUtil {
+
+    /**
+     * Error message for unsupported device type.
+     */
+    private static final String UNSUPPORTED_DEV_TYPE = "Levels other than " +
+            "devices and device are not permitted.";
+
+    /**
+     * Error message for unsupported tunnel policy type.
+     */
+    private static final String UNSUPPORTED_TNL_POL_TYPE = "Levels other" +
+            " than tnlm and tnl policy are not permitted.";
+
+    // No instantiation.
+    private TnlConstructionUtil() {
+    }
+
+    /**
+     * Returns the created model object data of devices or device level from
+     * the tunnel info.
+     *
+     * @param tnlInfo tunnel info
+     * @return driver model object data
+     */
+    static ModelObjectData getCreateTnlDev(TunnelInfo tnlInfo) {
+        Device device = new DefaultDevice();
+        device.deviceid(tnlInfo.devId());
+
+        switch (tnlInfo.level()) {
+            case DEVICES:
+                Devices devices = new DefaultDevices();
+                devices.addToDevice(device);
+                return getData(null, (InnerModelObject) devices);
+
+            case DEVICE:
+                Builder id = getDevicesId();
+                return getData(id.build(), (InnerModelObject) device);
+
+            default:
+                throw new IllegalArgumentException(UNSUPPORTED_DEV_TYPE);
+        }
+    }
+
+    /**
+     * Returns the created model object data of tunnel policy from the tunnel
+     * info.
+     *
+     * @param tnlInfo tunnel info
+     * @return driver model object data
+     */
+    static ModelObjectData getCreateTnlPol(TunnelInfo tnlInfo) {
+        Builder id = getDeviceId(tnlInfo.devId());
+        TunnelPolicy tnlPol = new DefaultTunnelPolicy();
+        tnlPol.tnlPolicyName(tnlInfo.polName());
+        tnlPol.tnlPolicyType(of(TnlmbaseTnlPolicyTypeEnum.of(2)));
+
+        switch (tnlInfo.level()) {
+            case TNL_M:
+                Tnlm tnlm = new DefaultTnlm();
+                TunnelPolicys tnlPolicys = new DefaultTunnelPolicys();
+                tnlPolicys.addToTunnelPolicy(tnlPol);
+                tnlm.tunnelPolicys(tnlPolicys);
+                return getData(id.build(), (InnerModelObject) tnlm);
+
+            case TNL_POL:
+                id = getTunnelPolicysId(id);
+                return getData(id.build(), (InnerModelObject) tnlPol);
+
+            default:
+                throw new IllegalArgumentException(UNSUPPORTED_TNL_POL_TYPE);
+        }
+    }
+
+    /**
+     * Returns the created model object data of tunnel from the tunnel info.
+     *
+     * @param tnlInfo tunnel info
+     * @return driver model object data
+     */
+    static ModelObjectData getCreateTnl(TunnelInfo tnlInfo) {
+        TunnelPolicyKeys key = new TunnelPolicyKeys();
+        key.tnlPolicyName(tnlInfo.polName());
+
+        Builder id = getDeviceId(tnlInfo.devId());
+        id = getTunnelPolicysId(id);
+        id = id.addChild(DefaultTunnelPolicy.class, key);
+        TpNexthop tpHop = new DefaultTpNexthop();
+        TpTunnels tunnels = new DefaultTpTunnels();
+        TpTunnel tunnel = new DefaultTpTunnel();
+        tunnel.tunnelName(tnlInfo.tnlName());
+        tunnel.autoTunnel(true);
+        tunnels.addToTpTunnel(tunnel);
+        tpHop.tpTunnels(tunnels);
+        tpHop.nexthopIpaddr(Ipv4Address.of(tnlInfo.desIp()));
+
+        if (tnlInfo.level() == TP_HOP) {
+            id.addChild(DefaultTpNexthops.class);
+            return getData(id.build(), (InnerModelObject) tpHop);
+        } else {
+            TpNexthops tpHops = new DefaultTpNexthops();
+            tpHops.addToTpNexthop(tpHop);
+            return getData(id.build(), (InnerModelObject) tpHops);
+        }
+    }
+
+    /**
+     * Returns the created model object data of binding the tunnel policy to
+     * the VPN from the tunnel policy name and device id.
+     *
+     * @param tnlInfo tunnel info
+     * @return driver model object data
+     */
+    static ModelObjectData getBindTnl(TunnelInfo tnlInfo) {
+        L3VpnInstanceKeys vpnKey = new L3VpnInstanceKeys();
+        vpnKey.vrfName(tnlInfo.polName());
+        VpnInstAfKeys afKeys = new VpnInstAfKeys();
+        afKeys.afType(L3VpncommonL3VpnPrefixType.of(IPV4UNI));
+
+        Builder id = getModObjIdDriDevice(tnlInfo.devId());
+        id.addChild(DefaultL3Vpn.class);
+        id.addChild(DefaultL3Vpncomm.class);
+        id.addChild(DefaultL3VpnInstances.class);
+        id.addChild(DefaultL3VpnInstance.class, vpnKey);
+        id.addChild(DefaultVpnInstAfs.class);
+        id.addChild(DefaultVpnInstAf.class, afKeys);
+
+        LeafModelObject leaf = new LeafModelObject();
+        leaf.leafIdentifier(TNLPOLICYNAME);
+        leaf.addValue(tnlInfo.polName());
+        return DefaultModelObjectData.builder().addModelObject(leaf)
+                .identifier(id.build()).build();
+    }
+
+    /**
+     * Returns the driver model object data for delete, according to the
+     * levels it has to be constructed for tunnel policy.
+     *
+     * @param tnlInfo tunnel info
+     * @return driver model object data
+     */
+    static ModelObjectData getDeleteTnl(TunnelInfo tnlInfo) {
+        Builder id = getDeviceId(tnlInfo.devId());
+        switch (tnlInfo.level()) {
+            case DEVICES:
+                return getData(getDevicesId().build(), new DefaultDevice());
+
+            case DEVICE:
+                return getData(id.build(), new DefaultTnlm());
+
+            case TNL_POL:
+                id = getTunnelPolicysId(id);
+                TunnelPolicyKeys polKey = new TunnelPolicyKeys();
+                polKey.tnlPolicyName(tnlInfo.polName());
+                id = id.addChild(DefaultTunnelPolicy.class, polKey);
+                return getData(id.build(), new DefaultTpNexthops());
+
+            default:
+                throw new IllegalArgumentException(UNSUPPORTED_MODEL_LVL);
+        }
+    }
+
+    /**
+     * Returns the model object id of tunnel with devices and device.
+     *
+     * @param id device id
+     * @return model object id
+     */
+    private static Builder getDeviceId(String id) {
+        DeviceKeys devId = new DeviceKeys();
+        devId.deviceid(id);
+        return getDevicesId().addChild(DefaultDevice.class, devId);
+    }
+
+    /**
+     * Returns the model object id of tunnel with devices.
+     *
+     * @return model object id
+     */
+    private static Builder getDevicesId() {
+        return builder().addChild(DefaultDevices.class);
+    }
+
+    /**
+     * Returns the model object id of tunnel policies.
+     *
+     * @param id model object id
+     * @return model object id with tunnel policies
+     */
+    public static Builder getTunnelPolicysId(Builder id) {
+        return id.addChild(DefaultTnlm.class)
+                .addChild(DefaultTunnelPolicys.class);
+    }
+}
diff --git a/drivers/huawei/src/main/resources/huawei-drivers.xml b/drivers/huawei/src/main/resources/huawei-drivers.xml
index d1170c6..0ec590d 100644
--- a/drivers/huawei/src/main/resources/huawei-drivers.xml
+++ b/drivers/huawei/src/main/resources/huawei-drivers.xml
@@ -17,7 +17,7 @@
 <drivers>
     <driver name="huawei" extends="" manufacturer="Huawei"
             hwVersion="" swVersion="">
-        <behaviour api="org.onosproject.net.behaviour.L3VpnConfig"
+        <behaviour api="org.onosproject.l3vpn.netl3vpn.L3VpnConfig"
                    impl="org.onosproject.drivers.huawei.HuaweiL3VpnConfig"/>
         <behaviour api="org.onosproject.net.device.DeviceDescriptionDiscovery"
                    impl="org.onosproject.drivers.huawei.HuaweiDeviceDescription"/>
diff --git a/models/huawei/src/main/yang/ne-l3vpn-api.yang b/models/huawei/src/main/yang/ne-l3vpn-api.yang
index 5b0181c..5320617 100644
--- a/models/huawei/src/main/yang/ne-l3vpn-api.yang
+++ b/models/huawei/src/main/yang/ne-l3vpn-api.yang
@@ -57,6 +57,9 @@
                                         type "string";
                                         description "route-distinguisher.";
                                     }
+                                    leaf tnlPolicyName {
+                                        type "string";
+                                    }
                                     container vpnTargets {
                                         description "";
                                         list vpnTarget {
diff --git a/models/huawei/src/main/yang/ne-tnlm-type.yang b/models/huawei/src/main/yang/ne-tnlm-type.yang
new file mode 100644
index 0000000..8dac8e8
--- /dev/null
+++ b/models/huawei/src/main/yang/ne-tnlm-type.yang
@@ -0,0 +1,30 @@
+/*
+WARNING:
+This yang model is just for fuction ONOS opensource project demo purpose only,
+And is subject to change in future, Huawei does not commit provide compatibilty
+in commercial product.
+*/
+module ne-tnlm-type {
+    namespace "ne-tnlm-type";
+    prefix tnlm-type;
+    organization "Huawei Technologies Co., Ltd";
+    contact "Huawei Industrial Base
+        Bantian, Longgang
+        Shenzhen 518129
+        People's Republic of China
+        Website: http://www.huawei.com
+        Email: support@huawei.com";
+    description "VRP V800R010 Schema";
+
+    revision "2014-12-25" {
+        reference "Huawei VRPV8 Schema";
+    }
+
+    typedef tnlmbaseTnlPolicyType {
+        type enumeration {
+            enum invalid;
+            enum tnlSelectSeq;
+            enum tnlBinding;
+        }
+    }
+}
\ No newline at end of file
diff --git a/models/huawei/src/main/yang/ne-tnlm.yang b/models/huawei/src/main/yang/ne-tnlm.yang
new file mode 100644
index 0000000..73796f4
--- /dev/null
+++ b/models/huawei/src/main/yang/ne-tnlm.yang
@@ -0,0 +1,71 @@
+/*
+WARNING:
+This yang model is just for fuction ONOS opensource project demo purpose only,
+And is subject to change in future, Huawei does not commit provide compatibilty
+in commercial product.
+*/
+module ne-tnlm {
+    namespace "ne-tnlm";
+    prefix tnlm;
+
+    import ne-l3vpncomm-type {
+        prefix l3vpncomm-type;
+    }
+    import ne-tnlm-type {
+        prefix tnlmtype;
+    }
+    organization "Huawei Technologies Co., Ltd";
+    contact "Huawei Industrial Base
+        Bantian, Longgang
+        Shenzhen 518129
+        People's Republic of China
+        Website: http://www.huawei.com
+        Email: support@huawei.com";
+    description "VRP V800R010 Schema";
+    revision "2014-12-25" {
+        reference "Huawei VRPV8 Schema";
+    }
+    container devices {
+        list device {
+            key deviceid;
+            leaf deviceid {
+                type string;
+            }
+            container tnlm {
+                container tunnelPolicys {
+                    list tunnelPolicy {
+                        key tnlPolicyName;
+                        leaf tnlPolicyName {
+                            type string;
+                        }
+                        leaf tnlPolicyType {
+                            type tnlmtype:tnlmbaseTnlPolicyType;
+                        }
+                        container tpNexthops {
+                            list tpNexthop {
+                                key nexthopIPaddr;
+                                leaf nexthopIPaddr {
+                                    type "l3vpncomm-type:ipv4Address";
+                                }
+                                leaf tnlPolicyName {
+                                    type string;
+                                }
+                                container tpTunnels {
+                                    list tpTunnel {
+                                        key "tunnelName";
+                                        leaf autoTunnel {
+                                            type boolean;
+                                        }
+                                        leaf tunnelName {
+                                            type string;
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
\ No newline at end of file