diff --git a/README.md b/README.md
index 575fc56f0c25554e44b61c674b218bbda72a078e..725d962d7534c670b135f4bf8de51cd6508db5af 100644
--- a/README.md
+++ b/README.md
@@ -2,6 +2,9 @@
 
 `uspd` is a [TR-369/USP](https://usp.technology/) backend ubus daemon process to understand [USP syntax](https://usp.technology/specification/architecture/) defined in R-ARC.7 - R-ARC.12 and provide details.
 
+> Note 1: The command outputs shown in this readme are examples only, actual output may differ based on device and configuration.
+> Note 2: Long command outputs are compressed for better readability
+
 ## Project Components
 
 Project consists of following components:
@@ -49,30 +52,40 @@ Each namespace provide the similar result but in different formats. `usp` namesp
 
 ````bash
 root@iopsys:~# ubus -v list usp
-'usp' @ac452d85
-	"get":{"path":"String","proto":"String"}
-	"get_safe":{"paths":"Array","proto":"String"}
-	"set":{"path":"String","value":"String","values":"Table","proto":"String"}
-	"operate":{"path":"String","action":"String","input":"Table","proto":"String"}
-	"add_object":{"path":"String","proto":"String","key":"String"}
-	"del_object":{"path":"String","proto":"String","key":"String"}
-	"object_names":{"path":"String","proto":"String"}
-	"instances":{"path":"String","proto":"String"}
-
+'usp' @deb5f751
+        "dump_schema":{}
+        "list_operate":{}
+        "get":{"path":"String","proto":"String","maxdepth":"Integer","next-level":"Boolean"}
+        "object_names":{"path":"String","proto":"String","maxdepth":"Integer","next-level":"Boolean"}
+        "instances":{"path":"String","proto":"String","maxdepth":"Integer","next-level":"Boolean"}
+        "validate":{"path":"String","proto":"String","maxdepth":"Integer","next-level":"Boolean"}
+        "set":{"path":"String","value":"String","values":"Table","proto":"String","key":"String"}
+        "operate":{"path":"String","action":"String","input":"Table","proto":"String"}
+        "add_object":{"path":"String","proto":"String","key":"String"}
+        "del_object":{"path":"String","proto":"String","key":"String"}
+        "get_safe_values":{"paths":"Array","proto":"String","next-level":"Boolean"}
+        "get_safe_attributes":{"paths":"Array","proto":"String","next-level":"Boolean"}
+        "get_safe_names":{"paths":"Array","proto":"String","next-level":"Boolean"}
+        "set_safe_attributes":{"paths":"Array","proto":"String"}
 root@iopsys:~#
 root@iopsys:~# ubus -v list usp.raw
-'usp.raw' @20cb78d8
-	"get":{"path":"String","proto":"String"}
-	"get_safe":{"paths":"Array","proto":"String"}
-	"set":{"path":"String","value":"String","values":"Table","proto":"String"}
-	"operate":{"path":"String","action":"String","input":"Table","proto":"String"}
-	"add_object":{"path":"String","proto":"String","key":"String"}
-	"del_object":{"path":"String","proto":"String","key":"String"}
-	"object_names":{"path":"String","proto":"String"}
-	"instances":{"path":"String","proto":"String"}
+'usp.raw' @ff9d104b
+        "dump_schema":{}
+        "list_operate":{}
+        "get":{"path":"String","proto":"String","maxdepth":"Integer","next-level":"Boolean"}
+        "object_names":{"path":"String","proto":"String","maxdepth":"Integer","next-level":"Boolean"}
+        "instances":{"path":"String","proto":"String","maxdepth":"Integer","next-level":"Boolean"}
+        "validate":{"path":"String","proto":"String","maxdepth":"Integer","next-level":"Boolean"}
+        "set":{"path":"String","value":"String","values":"Table","proto":"String","key":"String"}
+        "operate":{"path":"String","action":"String","input":"Table","proto":"String"}
+        "add_object":{"path":"String","proto":"String","key":"String"}
+        "del_object":{"path":"String","proto":"String","key":"String"}
+        "get_safe_values":{"paths":"Array","proto":"String","next-level":"Boolean"}
+        "get_safe_attributes":{"paths":"Array","proto":"String","next-level":"Boolean"}
+        "get_safe_names":{"paths":"Array","proto":"String","next-level":"Boolean"}
+        "set_safe_attributes":{"paths":"Array","proto":"String"}
 root@iopsys:~#
 ````
-
 > Note: `proto` in each method specify the datamodel prototype('cwmp', 'usp') to use, if not provided default datamodel will be used.
 
 The objects registered with the above namespaces can be called with appropriate parameters to perform a USP `Get/Set/Operate/Add Object/Delete Object` operation as below.
@@ -82,17 +95,23 @@ The objects registered with the above namespaces can be called with appropriate
 uspd provides below commands in pretty(usp) or raw(usp.raw) formats:
 
  1. Get
- 2. Get safe
- 3. Set
- 4. Operate
- 5. Add object
- 6. Delete object
- 7. Object names
- 8. Instances
+ 2. Get safe values
+ 3. Get safe names
+ 4. Get safe attributes
+ 5. Set
+ 6. Operate
+ 7. Add object
+ 8. Delete object
+ 9. Object names
+ 10. Instances
+ 11. Validate
+ 12. Dump schema
+ 13. List operate
 
 It also provide a granularity layer which can be configured using uci parameter and provide additional ubus objects.
 
 ### Granularity
+
 Granularity feature is basically exposes the same USP functionality by registering additinal ubus namespaces to reduce the `path` length in ubus parameter. It is the number of levels upto which we want to shorten the length.
 
 Ex:
@@ -102,7 +121,7 @@ Ex:
 ````bash
 root@iopsys:~# ubus list|grep usp
 usp
-usp.Device
+usp.Device.
 usp.raw
 ````
 
@@ -111,66 +130,47 @@ usp.raw
 ````bash
 root@iopsys:~# ubus list|grep usp
 usp
-usp.Device
-usp.Device.ATM
-usp.Device.Bridging
-usp.Device.BulkData
-usp.Device.DHCPv4
-usp.Device.DHCPv6
-usp.Device.DNS
-usp.Device.DSL
-usp.Device.DeviceInfo
-usp.Device.Ethernet
-usp.Device.Firewall
-usp.Device.Hosts
-usp.Device.IP
-usp.Device.InterfaceStack
-usp.Device.ManagementServer
-usp.Device.NAT
-usp.Device.PPP
-usp.Device.PTM
-usp.Device.Routing
-usp.Device.Services
-usp.Device.SoftwareModules
-usp.Device.Time
-usp.Device.UPnP
-usp.Device.USB
-usp.Device.UserInterface
-usp.Device.Users
-usp.Device.WiFi
-usp.Device.XMPP
-usp.Device.X_IOPSYS_EU_Buttons
-usp.Device.X_IOPSYS_EU_Dropbear
-usp.Device.X_IOPSYS_EU_ICE
-usp.Device.X_IOPSYS_EU_IGMP
-usp.Device.X_IOPSYS_EU_IpAccCfg
-usp.Device.X_IOPSYS_EU_LoginCfg
-usp.Device.X_IOPSYS_EU_Owsd
-usp.Device.X_IOPSYS_EU_PowerManagement
-usp.Device.X_IOPSYS_EU_SyslogCfg
-usp.Device.X_IOPSYS_EU_WiFiLife
+usp.Device.
+usp.Device.Bridging.
+usp.Device.DHCPv4.
+usp.Device.DHCPv6.
+usp.Device.DNS.
+usp.Device.DeviceInfo.
+usp.Device.DynamicDNS.
+usp.Device.Ethernet.
+usp.Device.Firewall.
+usp.Device.Hosts.
+usp.Device.IP.
 usp.raw
+root@iopsys:~#
 ````
 
 These granular ubus objects provides the same functionality as of `usp` ubus namespace
 
 ````bash
-root@iopsys:~# ubus -v list usp.Device.WiFi
-'usp.Device.WiFi' @69650977
-	"get":{"path":"String","proto":"String"}
-	"get_safe":{"paths":"Array","proto":"String"}
-	"set":{"path":"String","value":"String","values":"Table","proto":"String"}
-	"operate":{"path":"String","action":"String","input":"Table","proto":"String"}
-	"add_object":{"path":"String","proto":"String","key":"String"}
-	"del_object":{"path":"String","proto":"String","key":"String"}
-	"object_names":{"path":"String","proto":"String"}
-	"instances":{"path":"String","proto":"String"}
+root@iopsys:~# ubus -v list usp.Device.WiFi.
+'usp.Device.WiFi.' @6fd43aca
+        "dump_schema":{}
+        "list_operate":{}
+        "get":{"path":"String","proto":"String","maxdepth":"Integer","next-level":"Boolean"}
+        "object_names":{"path":"String","proto":"String","maxdepth":"Integer","next-level":"Boolean"}
+        "instances":{"path":"String","proto":"String","maxdepth":"Integer","next-level":"Boolean"}
+        "validate":{"path":"String","proto":"String","maxdepth":"Integer","next-level":"Boolean"}
+        "set":{"path":"String","value":"String","values":"Table","proto":"String","key":"String"}
+        "operate":{"path":"String","action":"String","input":"Table","proto":"String"}
+        "add_object":{"path":"String","proto":"String","key":"String"}
+        "del_object":{"path":"String","proto":"String","key":"String"}
+        "get_safe_values":{"paths":"Array","proto":"String","next-level":"Boolean"}
+        "get_safe_attributes":{"paths":"Array","proto":"String","next-level":"Boolean"}
+        "get_safe_names":{"paths":"Array","proto":"String","next-level":"Boolean"}
+        "set_safe_attributes":{"paths":"Array","proto":"String"}
+root@iopsys:~#
 ````
 
 Registered method can be called with appropriate parameters, like:
 
 ````bash
-root@iopsys:~# ubus call usp.Device get '{"path":"Users."}'
+root@iopsys:~# ubus call usp.Device. get '{"path":"Users."}'
 {
         "Users": {
                 "User": [
@@ -202,6 +202,13 @@ root@iopsys:~# ubus call usp.Device get '{"path":"Users."}'
                 "UserNumberOfEntries": 3
         }
 }
+root@iopsys:~#
+root@iopsys:~# ubus call usp.Device. get_safe_values '{"paths":["Device.Users.User.1.Username","Device.Users.User.2.Username"]}'
+{
+        "Device.Users.User.1.Username": "user",
+        "Device.Users.User.2.Username": "support"
+}
+root@iopsys:~#
 ````
 
 ### Get
@@ -217,24 +224,10 @@ root@iopsys:~# ubus call usp get '{"path":"Device.IP.Diagnostics.", "proto":"usp
                 "IPv4PingSupported": true,
                 "IPv4ServerSelectionDiagnosticsSupported": true,
                 "IPv4TraceRouteSupported": true,
-                "IPv4UDPEchoDiagnosticsSupported": true,
-                "IPv4UploadDiagnosticsSupported": true,
-                "IPv6DownloadDiagnosticsSupported": true,
-                "IPv6PingSupported": true,
-                "IPv6ServerSelectionDiagnosticsSupported": true,
-                "IPv6TraceRouteSupported": true,
-                "IPv6UDPEchoDiagnosticsSupported": true,
                 "IPv6UploadDiagnosticsSupported": true,
                 "UDPEchoConfig": {
                         "BytesReceived": 0,
                         "BytesResponded": 0,
-                        "EchoPlusEnabled": false,
-                        "EchoPlusSupported": false,
-                        "Enable": false,
-                        "Interface": "",
-                        "PacketsReceived": 0,
-                        "PacketsResponded": 0,
-                        "SourceIPAddress": "",
                         "TimeFirstPacketReceived": "0",
                         "TimeLastPacketReceived": "0",
                         "UDPPort": 0
@@ -250,23 +243,6 @@ root@iopsys:~# ubus call usp get '{"path":"Device.IP.Diagnostics.", "proto":"cwm
                         "DSCP": 0,
                         "DiagnosticsState": "None",
                         "DownloadDiagnosticMaxConnections": 1,
-                        "DownloadTransports": "HTTP,FTP",
-                        "DownloadURL": "",
-                        "EOMTime": "0",
-                        "EnablePerConnectionResults": false,
-                        "EthernetPriority": 0,
-                        "Interface": "",
-                        "NumberOfConnections": 1,
-                        "PerConnectionResultNumberOfEntries": 0,
-                        "PeriodOfFullLoading": 0,
-                        "ProtocolVersion": "Any",
-                        "ROMTime": "0",
-                        "TCPOpenRequestTime": "0",
-                        "TCPOpenResponseTime": "0",
-                        "TestBytesReceived": 0,
-                        "TestBytesReceivedUnderFullLoading": 0,
-                        "TotalBytesReceived": 0,
-                        "TotalBytesReceivedUnderFullLoading": 0,
                         "TotalBytesSent": 0,
                         "TotalBytesSentUnderFullLoading": 0
                 },
@@ -275,15 +251,6 @@ root@iopsys:~# ubus call usp get '{"path":"Device.IP.Diagnostics.", "proto":"cwm
                         "AverageResponseTimeDetailed": 0,
                         "DSCP": 0,
                         "DataBlockSize": 64,
-                        "DiagnosticsState": "None",
-                        "FailureCount": 0,
-                        "Host": "",
-                        "Interface": "",
-                        "MaximumResponseTime": 0,
-                        "MaximumResponseTimeDetailed": 0,
-                        "MinimumResponseTime": 0,
-                        "MinimumResponseTimeDetailed": 0,
-                        "NumberOfRepetitions": 3,
                         "ProtocolVersion": "Any",
                         "SuccessCount": 0,
                         "Timeout": 1000
@@ -291,97 +258,8 @@ root@iopsys:~# ubus call usp get '{"path":"Device.IP.Diagnostics.", "proto":"cwm
                 "IPv4DownloadDiagnosticsSupported": true,
                 "IPv4PingSupported": true,
                 "IPv4ServerSelectionDiagnosticsSupported": true,
-                "IPv4TraceRouteSupported": true,
-                "IPv4UDPEchoDiagnosticsSupported": true,
-                "IPv4UploadDiagnosticsSupported": true,
-                "IPv6DownloadDiagnosticsSupported": true,
-                "IPv6PingSupported": true,
-                "IPv6ServerSelectionDiagnosticsSupported": true,
-                "IPv6TraceRouteSupported": true,
                 "IPv6UDPEchoDiagnosticsSupported": true,
                 "IPv6UploadDiagnosticsSupported": true,
-                "ServerSelectionDiagnostics": {
-                        "AverageResponseTime": 0,
-                        "DiagnosticsState": "None",
-                        "FastestHost": "",
-                        "HostList": "",
-                        "Interface": "",
-                        "MaximumResponseTime": 0,
-                        "MinimumResponseTime": 0,
-                        "NumberOfRepetitions": 3,
-                        "Port": 0,
-                        "Protocol": "ICMP",
-                        "ProtocolVersion": "Any",
-                        "Timeout": 1000
-                },
-                "TraceRoute": {
-                        "DSCP": 0,
-                        "DataBlockSize": 38,
-                        "DiagnosticsState": "None",
-                        "Host": "",
-                        "Interface": "",
-                        "MaxHopCount": 30,
-                        "NumberOfTries": 3,
-                        "ProtocolVersion": "Any",
-                        "ResponseTime": 0,
-                        "RouteHopsNumberOfEntries": 0,
-                        "Timeout": 5000
-                },
-                "UDPEchoConfig": {
-                        "BytesReceived": 0,
-                        "BytesResponded": 0,
-                        "EchoPlusEnabled": false,
-                        "EchoPlusSupported": false,
-                        "Enable": false,
-                        "Interface": "",
-                        "PacketsReceived": 0,
-                        "PacketsResponded": 0,
-                        "SourceIPAddress": "",
-                        "TimeFirstPacketReceived": "0",
-                        "TimeLastPacketReceived": "0",
-                        "UDPPort": 0
-                },
-                "UDPEchoDiagnostics": {
-                        "AverageResponseTime": 0,
-                        "DSCP": 0,
-                        "DataBlockSize": 24,
-                        "DiagnosticsState": "None",
-                        "FailureCount": 0,
-                        "Host": "",
-                        "InterTransmissionTime": 1000,
-                        "Interface": "",
-                        "MaximumResponseTime": 0,
-                        "MinimumResponseTime": 0,
-                        "NumberOfRepetitions": 1,
-                        "Port": 0,
-                        "ProtocolVersion": "Any",
-                        "SuccessCount": 0,
-                        "Timeout": 5000
-                },
-                "UploadDiagnostics": {
-                        "BOMTime": "0",
-                        "DSCP": 0,
-                        "DiagnosticsState": "None",
-                        "EOMTime": "0",
-                        "EnablePerConnectionResults": false,
-                        "EthernetPriority": 0,
-                        "Interface": "",
-                        "NumberOfConnections": 1,
-                        "PerConnectionResultNumberOfEntries": 0,
-                        "PeriodOfFullLoading": 0,
-                        "ProtocolVersion": "Any",
-                        "ROMTime": "0",
-                        "TCPOpenRequestTime": "0",
-                        "TCPOpenResponseTime": "0",
-                        "TestBytesSent": 0,
-                        "TestBytesSentUnderFullLoading": 0,
-                        "TestFileLength": 0,
-                        "TotalBytesReceived": 0,
-                        "TotalBytesReceivedUnderFullLoading": 0,
-                        "TotalBytesSent": 0,
-                        "TotalBytesSentUnderFullLoading": 0,
-                        "UploadTransports": "HTTP,FTP",
-                        "UploadURL": ""
                 }
         }
 }
@@ -419,6 +297,7 @@ root@iopsys:~# ubus call usp get '{"path":"Device.Users."}'
         }
 }
 ````
+
 #### To get the output in raw format use `usp.raw` ubus namespace:
 ````bash
 root@iopsys:~# ubus call usp.raw get '{"path":"Device.Users."}'
@@ -445,86 +324,61 @@ root@iopsys:~# ubus call usp.raw get '{"path":"Device.Users."}'
                         "type": "xsd:string"
                 },
                 {
-                        "parameter": "Device.Users.User.1.RemoteAccessCapable",
-                        "value": "1",
-                        "type": "xsd:boolean"
-                },
-                {
-                        "parameter": "Device.Users.User.1.Username",
-                        "value": "user",
-                        "type": "xsd:string"
-                },
-                {
-                        "parameter": "Device.Users.User.2.Alias",
-                        "value": "cpe-2",
-                        "type": "xsd:string"
-                },
-                {
-                        "parameter": "Device.Users.User.2.Enable",
-                        "value": "1",
-                        "type": "xsd:boolean"
-                },
-                {
-                        "parameter": "Device.Users.User.2.Language",
-                        "value": "",
-                        "type": "xsd:string"
-                },
-                {
-                        "parameter": "Device.Users.User.2.Password",
-                        "value": "",
-                        "type": "xsd:string"
-                },
-                {
-                        "parameter": "Device.Users.User.2.RemoteAccessCapable",
-                        "value": "1",
-                        "type": "xsd:boolean"
-                },
-                {
-                        "parameter": "Device.Users.User.2.Username",
-                        "value": "support",
-                        "type": "xsd:string"
-                },
-                {
-                        "parameter": "Device.Users.User.3.Alias",
-                        "value": "cpe-3",
-                        "type": "xsd:string"
-                },
-                {
-                        "parameter": "Device.Users.User.3.Enable",
-                        "value": "1",
-                        "type": "xsd:boolean"
-                },
-                {
-                        "parameter": "Device.Users.User.3.Language",
-                        "value": "",
-                        "type": "xsd:string"
-                },
-                {
-                        "parameter": "Device.Users.User.3.Password",
-                        "value": "",
-                        "type": "xsd:string"
-                },
-                {
-                        "parameter": "Device.Users.User.3.RemoteAccessCapable",
-                        "value": "1",
-                        "type": "xsd:boolean"
-                },
-                {
-                        "parameter": "Device.Users.User.3.Username",
-                        "value": "admin",
-                        "type": "xsd:string"
-                },
-                {
-                        "parameter": "Device.Users.UserNumberOfEntries",
-                        "value": "3",
-                        "type": "xsd:unsignedInt"
-                }
-        ]
-}
 ````
 - For more info on the `usp` ubus API see [link](./docs/api/usp.md#get)
 - For more info on the `usp.raw` ubus API see [link](./docs/api/usp.raw.md#get)
 
+#### Get safe values
+API to get values to specific object, object name must be provided in `paths` paratermer array.
+
+````bash
+root@iopsys:~# ubus call usp get_safe_values '{"paths":["Device.Users.Us
+er.1.","Device.Users.User.2."]}'
+{
+        "Device.Users.User.1.": {
+                "Alias": "cpe-1",
+                "Enable": "1",
+                "Language": "",
+                "Password": "",
+                "RemoteAccessCapable": "1",
+                "Username": "user"
+        },
+        "Device.Users.User.2.": {
+                "Alias": "cpe-2",
+                "Enable": "1",
+                "Language": "",
+                "Password": "",
+                "RemoteAccessCapable": "1",
+                "Username": "support"
+        }
+}
+````
+
+#### Get safe attributes
+API to get attributes to specific object, object name must be provided in `paths` paratermer array.
+
+````bash
+root@iopsys:~# ubus call usp get_safe_attributes '{"paths":["Device.Users.User.1.","Device.Users.User.2."]}'
+{
+        "Device.Users.User.1.": {
+                "Alias": "0",
+                "Enable": "0",
+                "Language": "0",
+                "Password": "0",
+                "RemoteAccessCapable": "0",
+                "Username": "0"
+        },
+        "Device.Users.User.2.": {
+                "Alias": "0",
+                "Enable": "0",
+                "Language": "0",
+                "Password": "0",
+                "RemoteAccessCapable": "0",
+                "Username": "0"
+        }
+}
+````
+
 #### Set
 API to set value to specific object, object name must be provided in `path` parameter and vlaue in `value` paratermer.
 
@@ -587,20 +441,75 @@ API to run operate/diagnostics commands as defined in TR-369
 ````bash
 root@iopsys:~# ubus call usp operate '{"path":"Device.IP.Diagnostics.", "action":"IPPing","input":{"Host":"iopsys.eu"}}'
 {
-        "AverageResponseTime": "0",
-        "AverageResponseTimeDetailed": "0",
-        "FailureCount": "3",
-        "MaximumResponseTime": "0",
-        "MaximumResponseTimeDetailed": "0",
-        "MinimumResponseTime": "9999",
-        "MinimumResponseTimeDetailed": "999999999",
-        "SuccessCount": "0"
+        "Results": [
+                {
+                        "path": "Device.IP.Diagnostics.IPPing",
+                        "result": [
+                                {
+                                        "AverageResponseTime": 0,
+                                        "AverageResponseTimeDetailed": 0,
+                                        "FailureCount": 3,
+                                        "MaximumResponseTime": 0,
+                                        "MaximumResponseTimeDetailed": 0,
+                                        "MinimumResponseTime": 9999,
+                                        "MinimumResponseTimeDetailed": 999999999,
+                                        "SuccessCount": 0
+                                }
+                        ]
+                }
+        ]
 }
 
+root@iopsys:~# ubus call usp.raw operate '{"path":"Device.IP.Diagnostics.", "action":"IPPing","input":{"Host":"iopsys.eu"}}'
+{
+        "Results": [
+                {
+                        "path": "Device.IP.Diagnostics.IPPing",
+                        "parameters": [
+                                {
+                                        "parameter": "AverageResponseTime",
+                                        "value": "0",
+                                        "type": "xsd:unsignedInt"
+                                },
+                                {
+                                        "parameter": "AverageResponseTimeDetailed",
+                                        "value": "0",
+                                        "type": "xsd:unsignedInt"
+                                },
+                                {
+                                        "parameter": "FailureCount",
+                                        "value": "3",
+                                        "type": "xsd:unsignedInt"
+                                },
+                                {
+                }
+        ]
+}
 
-root@iopsys:~# ubus call usp operate '{"path":"Device.IP.Interface.[Name==\"wan\"]", "action":"Reset"}'
+root@iopsys:~# ubus call usp operate '{"path":"Device.IP.Interface.[Name==\"wan\"].", "action":"Reset"}'
 {
-        "status": true
+        "Results": [
+                {
+                        "path": "Device.IP.Interface.2.Reset",
+                        "result": [
+                                {
+
+                                }
+                        ]
+                }
+        ]
+}
+
+root@iopsys:~# ubus call usp.raw operate '{"path":"Device.IP.Interface.[Name==\"wan\"].", "action":"Reset"}'
+{
+        "Results": [
+                {
+                        "path": "Device.IP.Interface.2.Reset",
+                        "parameters": [
+
+                        ]
+                }
+        ]
 }
 ````
 - For more info on the `usp` ubus API see [link](./docs/api/usp.md#operate)
@@ -637,12 +546,213 @@ root@iopsys:~# ubus call usp instances '{"path":"Device.IP.Interface.", "proto":
         ]
 }
 ````
+
+#### List Operate
+API to list all operate command objects
+
+
+````bash
+root@iopsys:~# ubus call usp list_operate
+{
+        "parameters": [
+                {
+                        "parameter": "Device.DHCPv4.Client.{i}.Renew()",
+                        "type": "sync"
+                },
+                {
+                        "parameter": "Device.DNS.Diagnostics.NSLookupDiagnostics()",
+                        "type": "async"
+                },
+                {
+                {
+                        "parameter": "Device.IP.Diagnostics.IPPing()",
+                        "type": "async"
+                },
+                {
+                        "parameter": "Device.IP.Diagnostics.TraceRoute()",
+                        "type": "async"
+                },
+                {
+                        "parameter": "Device.IP.Diagnostics.UDPEchoDiagnostics()",
+                        "type": "async"
+                },
+                {
+                        "parameter": "Device.IP.Interface.{i}.Reset()",
+                        "type": "sync"
+                },
+                {
+                        "parameter": "Device.Reboot()",
+                        "type": "sync"
+                },
+                {
+````
+
+#### Dump schema
+API to dump all registered schema paths,
+
+````bash
+{
+        "parameters": [
+                {
+                        "parameter": "Device.ATM.Link.{i}.",
+                        "writable": "1",
+                        "type": "xsd:object"
+                },
+                {
+                        "parameter": "Device.ATM.Link.{i}.Alias",
+                        "writable": "1",
+                        "type": "xsd:string"
+                },
+                {
+                        "parameter": "Device.ATM.Link.{i}.DestinationAddress",
+                        "writable": "1",
+                        "type": "xsd:string"
+                },
+                {
+                        "parameter": "Device.ATM.Link.{i}.Enable",
+                        "writable": "1",
+                        "type": "xsd:boolean"
+                },
+                {
+````
+
 - For more info on the `usp` ubus API see [link](./docs/api/usp.md#instances)
 - For more info on the `usp.raw` ubus API see [link](./docs/api/usp.raw.md#instances)
 
+#### Path syntax and possible error cases
+Please note some error scenerios with the uspd.
+
+1. The path parameter value must start with 'Device.'. The command below doesn't have Device before path "Users.User."
+
+````bash
+root@iopsys:~# ubus call usp.raw get '{"path":"Users.User."}'
+{
+        "fault": 7026
+}
+````
+
+2. The path parameter must end with a '.' if the path element is not a leaf element e.g.,
+   Note that first two commands doesn't end with a '.' while the command with Alias is correct, due to Alias
+   being the leaf element. To find correct schema path user can check with dump_schema option.
+
+````bash
+root@iopsys:~#
+root@iopsys:~# ubus call usp get '{"path":"Device.Users.User.4"}'
+{
+        "fault": 7026
+}
+root@iopsys:~#
+root@iopsys:~# ubus call usp get '{"path":"Device.Users.User"}'
+{
+        "fault": 9005
+}
+root@iopsys:~#
+root@iopsys:~# ubus call usp get '{"path":"Device.Users.User.*"}'
+{
+        "fault": 7026
+}
+root@iopsys:~#
+root@iopsys:~# ubus call usp get '{"path":"Device.Users.User.4.Alias"}'
+{
+        "Alias": "cpe-4"
+}
+````
+
+3. In path parameter value below, note that, the first search expression 'Type==Normal' is string which should be used as : Type==\"Normal\"
+
+````bash
+root@iopsys:~# ubus call usp get '{"path":"Device.IP.Interface.[Type==Normal].IPv4Address.[AddressingType==\"Static\"].IPAddress"}'
+{
+        "fault": 7008
+}
+root@iopsys:~#
+root@iopsys:~# ubus call usp get '{"path":"Device.IP.Interface.[Type==\"Normal\"].IPv4Address.[AddressingType==\"Static\"].IPAddress"}'
+{
+        "Interface": [
+                {
+                        "IPv4Address": [
+                                {
+                                        "IPAddress": "2.0.0.3"
+                                }
+                        ]
+                }
+        ]
+}
+````
+
+4. The path parameter value must not have an empty search expression
+
+````bash
+root@iopsys:~# ubus call usp get '{"path":"Device.Users.User.[]."}'
+{
+        "fault": 9005
+}
+````
+
+5. The path parameter value must use proper '.' seperated path search expression. Note that a '.' is missing between User and *
+
+````bash
+root@iopsys:~# ubus call usp get '{"path":"Device.Users.User*."}'
+{
+        "fault": 7026
+}
+````
+
+6. The path parameter value must be a valid path schema, in example below SSID is used which is invalid schema element for Device.Users.User.{i}.
+
+````bash
+root@iopsys:~# ubus call usp get '{"path":"Device.Users.User.1.SSID"}'
+{
+        "fault": 7026
+}
+````
+
+7. Please note that in search expression, string comparison only work with "==" or "!=". Whereas in command below its =
+
+````bash
+root@iopsys:~# ubus call usp get '{"path":"Device.Users.User.[Username=\"user\"].Alias"}'
+{
+        "fault": 7008
+}
+````
+
+#### Errors Codes
+
+| Error Code | Meaning                                                      |
+|------------|--------------------------------------------------------------|
+| 7003       | Message failed due to an internal error.                     |
+| 7004       | Message failed due to invalid values in the request elements and/or failure to update one or more parameters during Add or Set requests. |
+| 7005       | Message failed due to memory or processing limitations.      |
+| 7008       | Requested path was invalid or a reference was invalid.       |
+| 7010       | Requested Path Name associated with this ParamError did not match any instantiated parameters. |
+| 7011       | Unable to convert string value to correct data type.         |
+| 7012       | Out of range or invalid enumeration.                         |
+| 7022       | Command failed to operate.                                   |
+| 7026       | Path is not present in the data model schema.                |
+
+
+#### Parallel calls
+Uspd can also handle parallel object calls, e.g.,
+
+````bash
+root@iopsys:~# time ubus call usp.raw get '{"path":"Device."}' >/dev/null &
+root@iopsys:~# time ubus call usp.raw get '{"path":"Device.Users."}' >/dev/null
+real    0m 0.07s
+user    0m 0.00s
+sys     0m 0.00s
+root@iopsys:~#
+real     0m 1.86s
+user    0m 0.05s
+sys     0m 0.00s
+
+[1]+  Done                       time ubus call usp.raw get "{\"path\":\"Device.\"}" >/dev/null
+root@iopsys:~#
+````
+
 ### More example ###
 
 ````bash
+
 root@iopsys:~# ubus call usp get '{"path":"Device.WiFi.SSID.*.SSID"}'
 {
         "SSID": [
diff --git a/src/Makefile b/src/Makefile
index 515c64deafce0472b947cd7dabdc574ac7a502f2..e12d9e17ff442c2c9fe5962ec958d250473b461d 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -1,5 +1,5 @@
 PROG = uspd
-OBJS =common.o get.o set.o operate.o add_delete.o usp.o
+OBJS =common.o get.o get_helper.o set.o operate.o add_delete.o pretty_print.o usp.o
 CP=cp -f
 
 PROG_CFLAGS = $(CFLAGS) \
@@ -9,7 +9,7 @@ PROG_CFLAGS = $(CFLAGS) \
 	      -Wformat-signedness
 
 PROG_LDFLAGS = $(LDFLAGS)
-PROG_LDFLAGS += -luci -lubus -lubox -ljson-c -lblobmsg_json -lbbfdm
+PROG_LDFLAGS += -luci -lubus -lubox -ljson-c -lblobmsg_json -lbbfdm -lpthread
 GCOV = gcov
 CODECOVERAGE_SRC = usp.c
 
diff --git a/src/add_delete.c b/src/add_delete.c
index 2f039a2c5659efbe3c2e122b551ae7cc1b9aca81..89dfbd9733888645486d329de88c68e1e764f2df 100644
--- a/src/add_delete.c
+++ b/src/add_delete.c
@@ -22,80 +22,49 @@
 
 #include "common.h"
 #include "add_delete.h"
+#include "get_helper.h"
 
-extern pathnode *head;
-
-void add_object(struct blob_buf *bb, char *path, const char *pkey)
+void create_del_response(struct blob_buf *bb, char *path, const char *pkey, int proto)
 {
-	struct dmctx dm_ctx = {0};
-	struct dmctx *ctx = &dm_ctx;
-	uint32_t fault = 0;
-
-	INFO("Req to add object |%s|", path);
-	bbf_init(&dm_ctx, path);
-
-	if (pkey == NULL || pkey[0] == 0)
-		pkey = "true";
-
-	fault = (uint32_t)dm_entry_param_method(&dm_ctx, CMD_ADD_OBJECT, path, (char *)pkey, NULL);
+	struct pathNode *p;
+	void *array, *table;
 
-	if (fault) {
-		blobmsg_add_u32(bb, "fault", fault);
-	} else {
+	LIST_HEAD(resolved_paths);
+	LIST_HEAD(pv_list);
 
-		if (ctx->addobj_instance) {
-			blobmsg_add_u8(bb, "status", 1);
-			blobmsg_add_string(bb, "instance", ctx->addobj_instance);
-		} else {
-			blobmsg_add_u8(bb, "status", 0);
-			blobmsg_add_u32(bb, "fault", FAULT_9002);
-		}
+	get_resolved_paths(path, proto, &pv_list, &resolved_paths);
 
-		bbf_apply_end_session();
-		dm_entry_restart_services();
+	array = blobmsg_open_array(bb, "parameters");
+	list_for_each_entry(p, &resolved_paths, list) {
+		table = blobmsg_open_table(bb, NULL);
+		usp_del_object(bb, p->path, pkey, proto);
+		blobmsg_close_table(bb, table);
 	}
-	bbf_cleanup(&dm_ctx);
+	blobmsg_close_array(bb, array);
+
+	free_pv_list(&pv_list);
+	free_path_list(&resolved_paths);
 }
 
-void create_del_response(struct blob_buf *bb, char *path, const char *pkey)
+void create_add_response(struct blob_buf *bb, char *path, const char *pkey, int proto)
 {
+	struct pathNode *p;
 	void *array, *table;
-	pathnode *p;
 
-	filter_results(path, 0, strlen(path));
+	LIST_HEAD(resolved_paths);
+	LIST_HEAD(pv_list);
+
+	get_resolved_paths(path, proto, &pv_list, &resolved_paths);
 
-	p = head;
 	array = blobmsg_open_array(bb, "parameters");
-	while(p) {
+	list_for_each_entry(p, &resolved_paths, list) {
 		table = blobmsg_open_table(bb, NULL);
-		del_object(bb, p->ref_path, pkey);
+		usp_add_object(bb, p->path, pkey, proto);
 		blobmsg_close_table(bb, table);
-		p = p->next;
 	}
-	deleteList();
 	blobmsg_close_array(bb, array);
-}
-
-void del_object(struct blob_buf *bb, char *path, const char *pkey)
-{
-	struct dmctx dm_ctx = {0};
-	uint32_t fault = 0;
-
-	bbf_init(&dm_ctx, path);
 
-	if (pkey == NULL || pkey[0] == 0)
-		pkey = "true";
-
-	fault = (uint32_t)dm_entry_param_method(&dm_ctx, CMD_DEL_OBJECT, path, (char *)pkey, NULL);
-
-	blobmsg_add_string(bb, "parameter", path);
-	if (fault) {
-		blobmsg_add_u8(bb, "status", 0);
-		blobmsg_add_u32(bb, "fault", fault);
-	} else {
-		blobmsg_add_u8(bb, "status", 1);
-		bbf_apply_end_session();
-		dm_entry_restart_services();
-	}
-	bbf_cleanup(&dm_ctx);
+	free_pv_list(&pv_list);
+	free_path_list(&resolved_paths);
 }
+
diff --git a/src/add_delete.h b/src/add_delete.h
index 07bbb7647be39e273d673b389e7bd19b5951793d..7399f620437a693007ac480006a988ab59184217 100644
--- a/src/add_delete.h
+++ b/src/add_delete.h
@@ -1,6 +1,5 @@
 #ifndef ADD_DEL_H
 #define ADD_DEL_H
-void add_object(struct blob_buf *bb, char *path, const char *pkey);
-void del_object(struct blob_buf *bb, char *path, const char *pkey);
-void create_del_response(struct blob_buf *bb, char *path, const char *pkey);
+void create_del_response(struct blob_buf *bb, char *path, const char *pkey, int proto);
+void create_add_response(struct blob_buf *bb, char *path, const char *pkey, int proto);
 #endif /* ADD_DEL_H */
diff --git a/src/common.c b/src/common.c
index e6c57178843657f88583ef5e03b818f9cc1d6f9d..b3f71b927f12a70bc0f816b724f7e27105e7b193 100644
--- a/src/common.c
+++ b/src/common.c
@@ -4,7 +4,6 @@
  * Copyright (C) 2019 iopsys Software Solutions AB. All rights reserved.
  *
  * Author: Vivek Dutta <vivek.dutta@iopsys.eu>
- * Author: Yashvardhan <y.yashvardhan@iopsys.eu>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -23,47 +22,12 @@
 
 #include "common.h"
 #include "strncpyt.h"
+#include <libbbfdm/dmbbfcommon.h>
 
-#define GLOB_CHAR "[[+*]+"
-#define GLOB_EXPR "[=><]+"
-#define RESULT_STACK 15
 
-static unsigned char gLogLevel;
+#define DEFAULT_LOG_LEVEL (2)
 
-const char *DMT_TYPE[] = {
-[DMT_STRING] = "xsd:string",
-[DMT_UNINT] = "xsd:unsignedInt",
-[DMT_INT] = "xsd:int",
-[DMT_UNLONG] = "xsd:unsignedLong",
-[DMT_LONG] = "xsd:long",
-[DMT_BOOL] = "xsd:boolean",
-[DMT_TIME] = "xsd:dateTime",
-[DMT_HEXBIN] = "xsd:hexBinary",
-};
-
-static bool is_node_instance(char *path);
-bool match(const char *string, const char *pattern);
-struct uci_context *uci_ctx = NULL;
-
-// Global variables
-typedef struct resultnode {
-	char *name;
-	char *value;
-	char *type;
-	struct resultnode *next;
-} resultnode;
-
-typedef struct resultstack {
-	void *cookie;
-	char *key;
-} resultstack;
-
-static int rtop=-1;
-
-static resultstack g_result[RESULT_STACK];
-static resultnode *rnode = NULL;
-pathnode *head = NULL;
-static pathnode *temphead = NULL;
+static unsigned char gLogLevel = DEFAULT_LOG_LEVEL;
 
 // Logging utilities
 void set_debug_level(unsigned char level)
@@ -75,688 +39,152 @@ void print_error(const char *format, ...)
 {
 	va_list arglist;
 
-	if (gLogLevel < 1) {
+	if (gLogLevel < 1)
 		return;
-	}
 
-	va_start( arglist, format );
+	va_start(arglist, format);
 	vsyslog(LOG_ERR, format, arglist);
-	va_end( arglist );
-
-	return;
+	va_end(arglist);
 }
 
 void print_warning(const char *format, ...)
 {
 	va_list arglist;
-	if (gLogLevel < 2) {
+
+	if (gLogLevel < 2)
 		return;
-	}
 
-	va_start( arglist, format );
+	va_start(arglist, format);
 	vsyslog(LOG_WARNING, format, arglist);
-	va_end( arglist );
+	va_end(arglist);
 }
 
 void print_info(const char *format, ...)
 {
 	va_list arglist;
 
-	if (gLogLevel < 3) {
+	if (gLogLevel < 3)
 		return;
-	}
 
-	va_start( arglist, format );
+	va_start(arglist, format);
 	vsyslog(LOG_INFO, format, arglist);
-	va_end( arglist );
+	va_end(arglist);
 }
 
 void print_debug(const char *format, ...)
 {
 	va_list arglist;
 
-	if (gLogLevel < 4) {
+	if (gLogLevel < 4)
 		return;
-	}
 
-	va_start( arglist, format );
+	va_start(arglist, format);
 	vsyslog(LOG_DEBUG, format, arglist);
-	va_end( arglist );
-}
-
-// Stack utils
-bool is_stack_empty() {
-	return (rtop == -1);
-}
-
-bool push() {
-	DEBUG("entry");
-	if(rtop >= RESULT_STACK) {
-		ERR("Stack full, change stack logic");
-		return false;
-	}
-	rtop ++;
-	return true;
-}
-
-bool pop() {
-	DEBUG("entry");
-	if(is_stack_empty()) {
-		WARNING("Stack empty, can't pop");
-		return false;
-	}
-	free(g_result[rtop].key);
-	memset(&g_result[rtop], '\0', sizeof(resultstack));
-	rtop--;
-	return true;
+	va_end(arglist);
 }
 
-bool top() {
-	if(is_stack_empty()) {
-		DEBUG("Stack empty, no top");
-		return false;
-	}
-	return true;
-}
 
-// Common utilities
-bool is_str_eq(const char *s1, const char *s2) {
-	if(0==strcmp(s1, s2))
+bool is_str_eq(const char *s1, const char *s2)
+{
+	if (strcmp(s1, s2) == 0)
 		return true;
 
 	return false;
 }
 
-static bool get_boolean_string(char *value)
+bool get_boolean_string(char *value)
 {
 	if (!value)
 		return false;
 
-	if (0 == strncasecmp(value, "true", 4) ||
-	    '1' == value[0] ||
-	    0 == strncasecmp(value, "on", 2) ||
-	    0 == strncasecmp(value, "yes", 3) ||
-	    0 == strncasecmp(value, "enabled", 7))
+	if (strncasecmp(value, "true", 4) == 0 ||
+	    value[0] == '1' ||
+	    strncasecmp(value, "on", 2) == 0 ||
+	    strncasecmp(value, "yes", 3) == 0 ||
+	    strncasecmp(value, "enabled", 7) == 0)
 		return true;
 
 	return false;
 }
 
-static bool is_node_instance(char *path) {
+bool is_node_instance(char *path)
+{
+	char temp_char[MAX_DM_KEY_LEN] = {'\0'};
 	bool ret = false;
+	char *rb = NULL;
+	size_t shift;
+
 	DEBUG("entry |%s|", path);
-	if(path[0]=='[') {
-		char *rb = NULL;
+	if (!path)
+		return false;
+
+	if (path[0] == '[') {
 		rb = strchr(path, ']');
-		char temp_char[NAME_MAX] = {'\0'};
-		size_t shift = (size_t) labs(rb-path);
-		strncpy(temp_char, path, shift);
-		if(!match(temp_char, GLOB_EXPR))
+		shift = (size_t) labs(rb - path);
+		strncpyt(temp_char, path, shift + 1);
+		if (!match(temp_char, GLOB_EXPR))
 			ret = true;
 	} else {
-		if(atoi(path))
+		if (atoi(path))
 			ret = true;
 	}
-	return(ret);
+	return ret;
 }
 
-int usp_uci_init(void)
+bool get_uci_option_string(char *package, char *section,
+			   char *option, char **value)
 {
-	uci_ctx = uci_alloc_context();
-	if (!uci_ctx) {
-		return -1;
-	}
-	return 0;
-}
-
-int usp_uci_teardown(void)
-{
-	if (uci_ctx) {
-		uci_free_context(uci_ctx);
-	}
-	uci_ctx = NULL;
-	return 0;
-}
-
-bool get_uci_option_string(char *package, char *section, char *option, char **value) {
+	struct uci_context *uci_ctx;
 	struct uci_ptr ptr = {0};
 	bool ret = true;
-	usp_uci_init();
+
+	*value = NULL;
+	uci_ctx = uci_alloc_context();
+
+	if (!uci_ctx)
+		return false;
 
 	if (bbfdmuci_lookup_ptr(uci_ctx, &ptr, package, section, option, NULL)) {
-		*value = "";
+		*value = NULL;
 		ret = false;
-	}
-	else if (ptr.o && ptr.o->v.string) {
+	} else if (ptr.o && ptr.o->v.string) {
 		*value = strdup(ptr.o->v.string);
 	} else {
 		*value = NULL;
 		ret = false;
 	}
-	usp_uci_teardown();
-
-	return(ret);
-}
-
-// RE utilities
-bool match(const char *string, const char *pattern) {
-	regex_t re;
-	if (regcomp(&re, pattern, REG_EXTENDED) != 0) return 0;
-	int status = regexec(&re, string, 0, NULL, 0);
-	regfree(&re);
-	if (status != 0) return false;
-	return true;
-}
-
-void bbf_init(struct dmctx *dm_ctx, char *path) {
-	unsigned int amd = AMD_2, instance = INSTANCE_MODE_ALIAS;
-
-	if(match(path, "[[]+")) {
-		if(!match(path, GLOB_EXPR)) {
-			amd = AMD_5;
-		}
-	} else {
-		char *uci_amd = NULL, *uci_instance = NULL;
-		if(get_uci_option_string("cwmp", "cpe", "amd_version", &uci_amd)) {
-			amd = (unsigned int) atoi(uci_amd);
-			free(uci_amd);
-		}
-		if(get_uci_option_string("cwmp", "cpe", "instance_mode", &uci_instance)) {
-			if(!is_str_eq(uci_instance, "InstanceAlias"))
-				instance = INSTANCE_MODE_NUMBER;
-			free(uci_instance);
-		}
-	}
-	DEBUG("amd |%u| instance|%u|", amd, instance);
-	dm_ctx_init(dm_ctx, DM_CWMP, amd, instance);
-}
-
-void bbf_cleanup(struct dmctx *dm_ctx) {
-	dm_ctx_clean(dm_ctx);
-}
-
-//if matched start will have first match index, end will have end index
-static bool is_res_required(char *str, size_t *start, size_t *len) {
-
-	DEBUG("Entry |%s|", str);
-	if (match(str, GLOB_CHAR)) {
-		size_t s_len=strlen(str);
-		size_t b_len=s_len, p_len=s_len;
-
-		char *star = strchr(str, '*');
-		char *b_start = strchr(str, '[');
-		char *b_end = strchr(str, ']');
-		char *plus = strchr(str, '+');
-
-		if(star)
-			s_len = (size_t)labs(star - str);
-
-		if(b_start)
-			b_len = (size_t)labs(b_start - str);
-
-		if(plus)
-			p_len = (size_t)labs(plus - str);
-
-		*start = MIN(MIN(s_len, p_len), b_len);
-		if (*start == s_len) {
-			*len = 1;
-		} else if (*start == p_len) {
-			size_t i=0, index=0;
-			while((str+i)!=plus){
-				if(str[i] == DELIM)
-					index = i;
-				++i;
-			}
-			*start = index+1;
-			*len = p_len - index;
-		} else {
-			*len = (size_t)labs(b_end - b_start );
-		}
-
-		// Check if naming with aliases used
-		char temp_char[NAME_MAX] = {'\0'};
-		strncpy(temp_char, str+*start, *len);
-		if(match(temp_char, GLOB_EXPR))
-			return true;
-
-		if(match(temp_char, "[*+]+"))
-			return true;
-	}
-	*start = strlen(str);
-	return false;
-}
-
-static void add_data_blob(struct blob_buf *bb, char *param, char *value, char *type) {
-	if(param==NULL || value==NULL || type==NULL)
-		return;
-
-	if (is_str_eq(type, DMT_TYPE[DMT_UNINT])) {
-		blobmsg_add_u32(bb, param, (uint32_t)atoi(value));
-	} else if (is_str_eq(type, DMT_TYPE[DMT_INT])) {
-		blobmsg_add_u32(bb, param, (uint32_t)atoi(value));
-	} else if (is_str_eq(type, DMT_TYPE[DMT_LONG])) {
-		blobmsg_add_u64(bb, param, (uint64_t)atoll(value));
-	} else if (is_str_eq(type, DMT_TYPE[DMT_UNLONG])) {
-		blobmsg_add_u64(bb, param, (uint64_t)atoll(value));
-	} else if (is_str_eq(type, DMT_TYPE[DMT_BOOL])) {
-		if (get_boolean_string(value))
-			blobmsg_add_u8(bb, param, true);
-		else
-			blobmsg_add_u8(bb, param, false);
-	} else { //"xsd:hexbin" "xsd:dateTime" "xsd:string"
-		blobmsg_add_string(bb, param, value);
-	}
-}
-
-//display the list
-void printList(bool active) {
-	pathnode *ptr;
-
-	if(active)
-		ptr = head;
-	else
-		ptr = temphead;
-
-	//start from the beginning
-	while(ptr != NULL) {
-		DEBUG("%s",ptr->ref_path);
-		ptr = ptr->next;
-	}
-}
-
-static void swap_heads() {
-	DEBUG("Entry");
-	pathnode *temp = head;
-	head = temphead;
-	temphead = temp;
-}
-
-
-// Insert link at the first location
-void insert_result(char *name, char *value, char *type) {
-	DEBUG("Entry result|%s| value|%s|", name, value);
-	//create a link
-	resultnode *link = (resultnode*) calloc(1, sizeof(resultnode));
-	if(!link) {
-		ERR("Malloc failed!");
-		return;
-	}
-
-	link->name = strdup(name);
-	link->value = strdup(value);
-	link->type = strdup(type);
-
-	link->next = rnode;
-	rnode = link;
-}
-
-void delete_result() {
-	resultnode *ptr = rnode, *temp;
-	DEBUG("Entry");
-	if ( ptr == NULL) {
-		DEBUG("Result List is empty");
-	}
-	//start from the beginning
-	while(ptr != NULL) {
-		temp = ptr;
-		free(ptr->name);
-		free(ptr->value);
-		free(ptr->type);
-
-		if(ptr->next != NULL) {
-			ptr = ptr->next;
-		} else {
-			ptr = NULL;
-		}
-		free(temp);
-	}
-	rnode = NULL;
-}
-
-static void rev_result() {
-	resultnode *tmp = rnode;
-	rnode = NULL;
-	while(tmp != NULL) {
-		resultnode *t = tmp;
-		insert_result(tmp->name, tmp->value, tmp->type);
-		free(tmp->name);
-		free(tmp->value);
-		free(tmp->type);
-		tmp = tmp->next;
-		free(t);
-	}
-}
-
-// Insert link at the first location
-void insert(char *data, bool active) {
-	DEBUG("Entry |%s| active|%d|", data, active);
-	//create a link
-	pathnode *link = (pathnode*) calloc(1, sizeof(pathnode));
-	if(!link) {
-		ERR("Malloc failed!");
-		return;
-	}
-
-	link->ref_path = data;
-
-	if(active) {
-		link->next = head;
-		head = link;
-	} else {
-		link->next = temphead;
-		temphead = link;
-	}
-}
-
-// delete active list and swap with passive
-void deleteList() {
-	pathnode *ptr = head, *temp;
-	DEBUG("Entry");
-	if ( ptr == NULL) {
-		DEBUG("List is empty");
-	}
-	//start from the beginning
-	while(ptr != NULL) {
-		temp = ptr;
-		free(ptr->ref_path);
-		if(ptr->next != NULL) {
-			ptr = ptr->next;
-		} else {
-			ptr = NULL;
-		}
-		free(temp);
-	}
-	head = NULL;
-	swap_heads();
-}
-
-static int bbf_exec(int operation, char *path, struct dmctx *dm_ctx, char *arg1, char *arg2)
-{
-	int fault;
-
-	DEBUG("Entry |%s| operation|%d|", path, operation);
-	fault = dm_entry_param_method(dm_ctx, operation, path, arg1, arg2);
-
-	if (dm_ctx->list_fault_param.next != &dm_ctx->list_fault_param) {
-		struct param_fault *p;
-		list_for_each_entry(p, &dm_ctx->list_fault_param, list) {
-			return p->fault;
-		}
-	}
-	return fault;
-}
-
-static int bbf_get(int operation, char *path, struct dmctx *dm_ctx, char *next)
-{
-	return bbf_exec(operation, path, dm_ctx, next, NULL);
-}
 
-int bbf_list_operate(struct dmctx *dm_ctx)
-{
-	int fault = 0;
+	uci_free_context(uci_ctx);
 
-	fault = dm_entry_param_method(dm_ctx, CMD_USP_LIST_OPERATE, NULL,
-					      NULL, NULL);
-	return fault;
+	return ret;
 }
 
-int bbf_operate(struct dmctx *dm_ctx, char *path, char *input_params)
+// RE utilities
+bool match(const char *string, const char *pattern)
 {
-	int fault = 0;
-
-	if (input_params)
-		fault = dm_entry_param_method(dm_ctx, CMD_USP_OPERATE, path,
-					      input_params, NULL);
-	else
-		fault = dm_entry_param_method(dm_ctx, CMD_USP_OPERATE, path,
-					      NULL, NULL);
-	return fault;
-}
-
-bool get_granular_obj_list(char *path) {
-	struct dmctx dm_ctx = {0};
-	struct dm_parameter *n;
-	bool ret = false;
-
-	bbf_init(&dm_ctx, path);
-	if(!bbf_get(CMD_GET_NAME, path, &dm_ctx, "true")) {
-		list_for_each_entry(n, &dm_ctx.list_parameter, list) {
-			size_t len = strlen(n->name);
-			// Get only datamodel objects and skip leafs
-			if (n->name[len-1] == DELIM) {
-				insert(strdup(n->name), true);
-			}
-		}
-		ret = true;
-	}
-	bbf_cleanup(&dm_ctx);
-	return(ret);
-}
-
-// return true ==> success
-// false ==> failure
-bool bbf_get_name(char *path) {
-	struct dmctx dm_ctx = {0};
-	struct dm_parameter *n;
-	bool ret = false;
-
-	bbf_init(&dm_ctx, path);
-	if(!bbf_get(CMD_GET_NAME, path, &dm_ctx, "true")) {
-		list_for_each_entry(n, &dm_ctx.list_parameter, list) {
-			insert(strdup(n->name), false);
-		}
-		ret = true;
-	}
-	bbf_cleanup(&dm_ctx);
-	return(ret);
-}
-
-char *bbf_get_value_by_id(char *id) {
-	struct dmctx dm_ctx = {0};
-	struct dm_parameter *n;
-	char *value = NULL;
-
-	DEBUG("Entry id |%s|", id);
-	bbf_init(&dm_ctx, id);
-	if(!bbf_get(CMD_GET_VALUE, id, &dm_ctx, NULL)) {
-			list_for_each_entry(n, &dm_ctx.list_parameter, list) {
-				DEBUG("value |%s|", n->name);
-				value = strdup(n->data); // mem will be freed on caller
-				break;
-			}
-	}
-	bbf_cleanup(&dm_ctx);
-	return (value);
-}
-
-// path = 1.Stats.BytesReceived
-static bool leaf_same_group(char *path) {
-	DEBUG("entry");
-	char *key;
-
-	if(top()) {
-		key = g_result[rtop].key;
-		unsigned int klen = strlen(key);
-
-		if(0 == strncmp(path, key, klen)) {
-			DEBUG("same group|%s| path|%s|", g_result[rtop].key, path);
-			return true;
-		}
-	}
-	return false;
-}
-
-static bool is_leaf(char *path, char *node, size_t maxlen) {
-	DEBUG("entry path|%s|", path);
-	char *ret = NULL;
-
-	ret = strchr(path, DELIM);
-	if (ret != NULL) {
-		size_t retlen = (size_t)(ret - path) + 1;
-
-		if (retlen > maxlen)
-			retlen = maxlen;
-
-		memcpy(node, path, retlen);
-		node[retlen] = 0;
-	}
-
-	return (ret==NULL);
-}
-
-void process_result(struct blob_buf *bb, unsigned int len) {
-	char pn[NAME_MAX]={'\0'};
-
-	if(rnode == NULL) {
-		return;
-	}
-
-	DEBUG("Entry node |%s|, len|%u|", rnode->name, len);
-
-	if(leaf_same_group(rnode->name)) {
-		if(is_leaf(rnode->name+len, pn, sizeof(pn) - 1)) {
-			//INFO("add leaf |%s|", rnode->name+len);
-			add_data_blob(bb, rnode->name+len, rnode->value, rnode->type);
-		} else {
-			//check after stack top it's a leaf
-			if(top()) {
-				if(is_str_eq(g_result[rtop].key, pn)) {
-					len = strlen(g_result[rtop].key);
-				} else {
-					push();
-					char temp[NAME_MAX] = {'\0'};
-					memcpy(temp, rnode->name, len);
-					strncat(temp, pn, sizeof(temp) - 1);
-					//INFO("Push1 |%s|, node|%s|", temp, pn);
-					len = strlen(temp);
-
-					char table_name[NAME_MAX]={'\0'};
-					// Remove last dot in pn
-					strncpy(table_name, pn, strlen(pn) - 1);
-
-					if(is_node_instance(rnode->name + len)) {
-						//INFO("Open table |%s|", table_name);
-						g_result[rtop].cookie = blobmsg_open_array(bb, table_name);
-						g_result[rtop].key = strdup(temp);
-					} else {
-						if(is_node_instance(pn)) {
-							g_result[rtop].cookie = blobmsg_open_table(bb, NULL);
-						} else {
-							g_result[rtop].cookie = blobmsg_open_table(bb, table_name);
-						}
-						g_result[rtop].key = strdup(temp);
-					}
-				}
-			}
-			process_result(bb, len);
-		}
-	} else {
-		// check if it still belong to the group on stack
-		if(top()) { // if element present in stack but not matching
-			//INFO("Closing table for |%s|", g_result[rtop].key);
-			blobmsg_close_table(bb,g_result[rtop].cookie);
-		}
-		if(is_leaf(rnode->name, pn, sizeof(pn) - 1)) {
-			//INFO("add in blob|%s|, value|%s|, type|%s|", rnode->name, rnode->value, rnode->type);
-			add_data_blob(bb, rnode->name, rnode->value, rnode->type);
-		} else {
-			if(top()) { // if element present in stack but not matching
-				pop();
-				if(top())
-					len = strlen(g_result[rtop].key);
-			} else {
-				if(push() == false)
-					return;
-				//INFO("Pushing |%s|", pn);
-				len = strlen(pn);
-
-				char table_name[NAME_MAX]={'\0'};
-
-				memcpy(table_name, pn, len - 1);
-
-				if(is_node_instance(rnode->name + len)) {
-					//INFO("Open table |%s|", table_name);
-					g_result[rtop].cookie = blobmsg_open_array(bb, table_name);
-					g_result[rtop].key = strdup(pn);
-				} else {
-					if(is_node_instance(pn)) {
-						g_result[rtop].cookie = blobmsg_open_table(bb, NULL);
-					} else {
-						g_result[rtop].cookie = blobmsg_open_table(bb, table_name);
-					}
-					g_result[rtop].key = strdup(pn);
-				}
-			}
-			process_result(bb, len);
-		}
-	}
-	if(rnode != NULL)
-		rnode = rnode->next;
-
-	process_result(bb, len);
-}
-
-
-static size_t get_glob_len(char *path) {
-	size_t m_index = 0, m_len=0, ret=0;
-	size_t plen = strlen(path);
-	DEBUG("Entry");
-	if(is_res_required(path, &m_index, &m_len)) {
-		char temp_name[NAME_MAX] = {'\0'};
-		strncpy(temp_name, path, m_index - 1 );
-		char *end = strrchr(temp_name, DELIM);
-		ret = m_index - strlen(end);
-	} else {
-		char name[NAME_MAX] = {'\0'};
-		if(path[plen - 1] == DELIM) {
-			strncpy(name, path, plen -1 );
-		} else {
-			ret = 1;
-			strncpy(name, path, plen );
-		}
-		char *end = strrchr(name, DELIM);
-		if(end == NULL)
-			return ret;
-
-		ret = ret + strlen(path) - strlen(end);
-		if(is_node_instance(end+1)) {
-			char temp_name[NAME_MAX] = {'\0'};
-			strncpy(temp_name, path, plen - strlen(end) - 1 );
-			end = strrchr(temp_name, DELIM);
-			ret = ret - strlen(end);
-		}
-	}
-	return(ret);
-}
-
-bool is_search_by_reference(char *path) {
-	size_t m_index = 0, m_len=0;
-	char *last_plus = strrchr(path, '+');
-	char *last_bracket = strrchr(path, ']');
-	DEBUG("Entry |%s|", path);
+	int status;
+	regex_t re;
 
-	if(!is_res_required(path, &m_index, &m_len))
-		return false;
+	if (regcomp(&re, pattern, REG_EXTENDED) != 0)
+		return 0;
 
-	if(!last_plus)
+	status = regexec(&re, string, 0, NULL, 0);
+	regfree(&re);
+	if (status != 0)
 		return false;
 
-	if(!last_bracket)
-		return true;
-
-	return ((last_plus-last_bracket)>0?true:false);
+	return true;
 }
 
-static int count_delim(char *path)
+int count_delim(char *path)
 {
 	int count = 0;
-	const char s[2] = ".";
 	char *token, *save;
 	char *pp = strdup(path);
 
-	token = strtok_r(pp, s, &save);
-	while (token != NULL) {
-		token = strtok_r(NULL, s, &save);
+	token = strtok_r(pp, ".", &save);
+	while (token) {
+		token = strtok_r(NULL, ".", &save);
 		count++;
 	}
 	free(pp);
@@ -765,599 +193,3 @@ static int count_delim(char *path)
 	return (count - 1);
 }
 
-int bbf_get_value(char *path, bool fill, char *query_path, struct blob_buf *bb, uint8_t maxdepth)
-{
-	struct dmctx dm_ctx = {0};
-	struct dm_parameter *n;
-	DEBUG("Entry path |%s|, fill|%d|, query_path|%s|", path, fill, query_path);
-	size_t plen = get_glob_len(query_path);
-	size_t path_len = strlen(path);
-
-	DEBUG("plen |%zu|", plen);
-	bbf_init(&dm_ctx, path);
-	int fault = bbf_get(CMD_GET_VALUE, path, &dm_ctx, NULL);
-
-	if(!fault && fill) {
-		list_for_each_entry(n, &dm_ctx.list_parameter, list) {
-			if(is_search_by_reference(query_path)) {
-				char *end_delim = strrchr(n->name, DELIM);
-				plen = (size_t)labs(end_delim - n->name);
-			}
-			if (maxdepth > 4 || maxdepth == 0) {
-				insert_result(n->name+plen, n->data, n->type);
-			} else {
-				uint8_t count = count_delim(n->name + path_len);
-				if (count < maxdepth) {
-					insert_result(n->name+plen, n->data, n->type);
-				}
-			}
-		}
-	} else {
-		if (fault) {
-			blobmsg_add_string(bb, "path", path);
-			blobmsg_add_u32(bb, "fault", (uint32_t)fault);
-		}
-	}
-
-	bbf_cleanup(&dm_ctx);
-	return fault;
-}
-
-int bbf_get_blob(int cmd, char *path, struct blob_buf *bb, char *nxt_lvl)
-{
-	struct dmctx dm_ctx = {0};
-	struct dm_parameter *n;
-	size_t plen = strlen(path);
-	int fault;
-
-	DEBUG("Entry path |%s|", path);
-
-	bbf_init(&dm_ctx, path);
-	fault = bbf_get(cmd, path, &dm_ctx, nxt_lvl);
-	if(!fault) {
-		void *t = NULL;
-		size_t poff = 0;
-
-		if (path[plen - 1] == '.') {
-			t = blobmsg_open_table(bb, path);
-			poff = plen;
-		}
-
-		list_for_each_entry(n, &dm_ctx.list_parameter, list)
-			blobmsg_add_string(bb, n->name + poff,  n->data);
-
-		if (t)
-			blobmsg_close_table(bb, t);
-	} else {
-		blobmsg_add_string(bb, "path", path);
-		blobmsg_add_u32(bb, "fault", (uint32_t)fault);
-	}
-	bbf_cleanup(&dm_ctx);
-	return fault;
-}
-
-int bbf_get_raw(int cmd, char *path, struct blob_buf *bb, char *nxt_lvl)
-{
-	struct dmctx dm_ctx = {0};
-	struct dm_parameter *n;
-	void *table;
-	int fault;
-
-	DEBUG("Entry path |%s|", path);
-
-	bbf_init(&dm_ctx, path);
-	fault = bbf_get(cmd, path, &dm_ctx, nxt_lvl);
-	if(!fault) {
-		list_for_each_entry(n, &dm_ctx.list_parameter, list) {
-			table = blobmsg_open_table(bb, NULL);
-
-			blobmsg_add_string(bb, "parameter", n->name);
-
-			if (n->data)
-				blobmsg_add_string(bb, "value", n->data);
-
-			if (n->type)
-				blobmsg_add_string(bb, "type", n->type);
-
-			blobmsg_close_table(bb, table);
-			DEBUG("param|%s|, value|%s|", n->name, n->data);
-		}
-	} else {
-		table = blobmsg_open_table(bb, NULL);
-		blobmsg_add_string(bb, "path", path);
-		blobmsg_add_u32(bb, "fault", (uint32_t)fault);
-		blobmsg_close_table(bb, table);
-	}
-	bbf_cleanup(&dm_ctx);
-	return fault;
-}
-
-int bbf_get_inst_name_raw(char *path, struct blob_buf *bb) {
-	struct dmctx dm_ctx = {0};
-	struct dm_parameter *n;
-	DEBUG("Entry path |%s|", path);
-
-	bbf_init(&dm_ctx, path);
-	int fault = bbf_get(CMD_GET_NAME, path, &dm_ctx, "false");
-	if(!fault) {
-		list_for_each_entry(n, &dm_ctx.list_parameter, list) {
-			size_t nlen = strlen(n->name);
-			size_t cnt = 1;
-			bool is_inst = true;
-			if(n->name[nlen-1]=='.') {
-				while(n->name[nlen-1-cnt] != '.') {
-					if(!(isdigit(n->name[nlen-1-cnt]))) {
-						is_inst = false;
-						break;
-					}
-					cnt += 1;
-				}
-				if(is_inst) {
-					// Remove the last . from path
-					char temp[NAME_MAX] = { };
-					size_t nlen = strlen(n->name);
-					strncpyt(temp, n->name, nlen);
-					if (temp[nlen - 1] == '.')
-						temp[nlen - 1] = '\0';
-					void *table = blobmsg_open_table(bb, NULL);
-					blobmsg_add_string(bb, "parameter", temp);
-					blobmsg_close_table(bb, table);
-				}
-			}
-		}
-	} else {
-		void *table = blobmsg_open_table(bb, NULL);
-		blobmsg_add_string(bb, "path", path);
-		blobmsg_add_u32(bb, "fault", (uint32_t)fault);
-		blobmsg_close_table(bb, table);
-	}
-	bbf_cleanup(&dm_ctx);
-	return fault;
-}
-
-int bbf_get_name_raw(char *path, struct blob_buf *bb, bool nxt_lvl) {
-	struct dmctx dm_ctx = {0};
-	struct dm_parameter *n;
-	char *nxt_lvl_str = nxt_lvl ? "1" : "0";
-
-	DEBUG("Entry path |%s|", path);
-
-	bbf_init(&dm_ctx, path);
-	int fault = bbf_get(CMD_GET_NAME, path, &dm_ctx, nxt_lvl_str);
-	if(!fault) {
-		list_for_each_entry(n, &dm_ctx.list_parameter, list) {
-			void *table = blobmsg_open_table(bb, NULL);
-
-			blobmsg_add_string(bb, "parameter", n->name);
-			if (n->data)
-				blobmsg_add_string(bb, "writable", n->data);
-			if (n->type)
-				blobmsg_add_string(bb, "type", n->type);
-			blobmsg_close_table(bb, table);
-		}
-	} else {
-		void *table = blobmsg_open_table(bb, NULL);
-		blobmsg_add_string(bb, "path", path);
-		blobmsg_add_u32(bb, "fault", (uint32_t)fault);
-		blobmsg_close_table(bb, table);
-	}
-	bbf_cleanup(&dm_ctx);
-	return fault;
-}
-
-int bbf_validate_path(char *path)
-{
-	int fault;
-	struct dmctx dm_ctx = {0};
-
-	bbf_init(&dm_ctx, path);
-	fault = bbf_get(CMD_GET_NAME, path, &dm_ctx, "true");
-	bbf_cleanup(&dm_ctx);
-
-	return fault;
-}
-
-void update_valid_paths()
-{
-	pathnode *p=head;
-	int fault = 0;
-
-	while(p != NULL) {
-		fault = bbf_validate_path(p->ref_path);
-		if (fault == 0 ||
-		    fault == 9003 ||
-		    fault == 7004) {
-			insert(strdup(p->ref_path), false);
-		}
-		p = p->next;
-	}
-	deleteList();
-}
-
-void prepare_result(struct blob_buf *bb) {
-	rev_result();
-	resultnode *rhead = rnode;
-	process_result(bb, 0);
-	while(top()){
-		DEBUG("Close all open tables");
-		blobmsg_close_table(bb,g_result[rtop].cookie);
-		pop();
-	}
-	rnode = rhead;
-	delete_result();
-}
-
-static bool bbf_get_name_exp(char *path, char *operator, char *operand) {
-	struct dmctx dm_ctx = {0};
-	struct dm_parameter *n;
-	bool ret = false;
-
-	bbf_init(&dm_ctx, path);
-	if(bbf_get(CMD_GET_VALUE, path, &dm_ctx, NULL)) {
-		ERR("bbf_get failed path(%s)", path);
-		bbf_cleanup(&dm_ctx);
-		return(ret);
-	}
-	list_for_each_entry(n, &dm_ctx.list_parameter, list) {
-		DEBUG("Get |%s| value|%s| operator|%s|", path, n->data, operator);
-		unsigned long n1=0, n2=0;
-		// TODO: fix this for all datatypes
-		n1 = (unsigned long) atol(operand);
-		n2 = (unsigned long) atol(n->data);
-		if (is_str_eq("==", operator)) {
-			if (is_str_eq(n->type, DMT_TYPE[DMT_BOOL])) {
-				if (get_boolean_string(n->data) ==
-				    get_boolean_string(operand)) {
-					ret = true;
-					break;
-				}
-			} else {
-				if (strcasecmp(n->data, operand) == 0) {
-					ret = true;
-					break;
-				}
-			}
-
-		} else if (is_str_eq("!=",operator)) {
-			if (is_str_eq(n->type, DMT_TYPE[DMT_BOOL])) {
-				if (get_boolean_string(n->data) !=
-				    get_boolean_string(operand)) {
-					ret = true;
-					break;
-				}
-			} else {
-				if (strcasecmp(n->data, operand) != 0) {
-					ret = true;
-					break;
-				}
-			}
-		} else if (is_str_eq("<", operator)) {
-			if ( n2 < n1 ) {
-				ret = true;
-				break;
-			}
-		} else if (is_str_eq(">", operator)) {
-			if ( n2 > n1 ) {
-				ret = true;
-				break;
-			}
-		} else if (is_str_eq("<=", operator)) {
-			if ( n2 <= n1 ) {
-				ret = true;
-				break;
-			}
-		} else if (is_str_eq(">=", operator)) {
-			if ( n2 >= n1 ) {
-				ret = true;
-				break;
-			}
-		} else {
-			ERR("Fail (%s %s %s)", operand, operator, n->data);
-		}
-	}
-	bbf_cleanup(&dm_ctx);
-	return(ret);
-}
-
-int bbf_set_notification(struct blob_buf *bb, char *path, char *notif, char *change)
-{
-	struct dmctx dm_ctx = {};
-	void *t;
-	int fault;
-
-	bbf_init(&dm_ctx, path);
-	fault = bbf_exec(CMD_SET_NOTIFICATION, path, &dm_ctx, notif, change);
-
-	t = blobmsg_open_table(bb, NULL);
-	blobmsg_add_string(bb, "path", path);
-	if (fault)
-		blobmsg_add_u32(bb, "fault", fault);
-	blobmsg_close_table(bb, t);
-
-	return fault;
-}
-
-int bbf_set_value(struct blob_buf *bb, char *path, char *value, char *key) {
-	int fault = 0;
-	struct dmctx dm_ctx = {0};
-	struct dmctx *p_dmctx = &dm_ctx;
-	void *bb_array = blobmsg_open_table(bb, NULL);
-
-	bbf_init(&dm_ctx, path);
-	DEBUG("Entry path|%s|, value|%s|", path, value);
-	fault = dm_entry_param_method(&dm_ctx, CMD_SET_VALUE, path, value, NULL);
-
-	if(!fault) {
-		fault = dm_entry_apply(&dm_ctx, CMD_SET_VALUE, key, NULL);
-	}
-
-	if (p_dmctx->list_fault_param.next != &p_dmctx->list_fault_param) {
-		struct param_fault *p;
-		list_for_each_entry(p, &p_dmctx->list_fault_param, list) {
-			DEBUG("path|%s|, fault|%d|", p->name, p->fault);
-			fault = p->fault;
-		}
-	}
-
-	if (fault) {
-		blobmsg_add_u8(bb, "status", false);
-		blobmsg_add_string(bb, "path", path);
-		blobmsg_add_u32(bb, "fault", (uint32_t)fault);
-	} else {
-		blobmsg_add_u8(bb, "status", true);
-		blobmsg_add_string(bb, "path", path);
-	}
-
-	blobmsg_close_table(bb, bb_array);
-	bbf_cleanup(&dm_ctx);
-	return fault;
-}
-
-static void dereference_path(char *ref, char *l_op, char *r_op, char *op) {
-	pathnode *p=head;
-
-	while(p!=NULL) {
-		char path[NAME_MAX]={'\0'};
-		char ref_path[NAME_MAX]={'\0'};
-		char *node = NULL;
-		strncpyt(path, p->ref_path, sizeof(path));
-		strncat(path, ref, sizeof(path) - 1);
-		node = bbf_get_value_by_id(path);
-		strncpyt(ref_path, node, sizeof(ref_path));
-		strncat(ref_path, l_op, sizeof(ref_path) - 1);
-		DEBUG("de ref|%s|, path|%s|, node|%s|", ref_path, path, node);
-		free(node);
-
-		if(bbf_get_name_exp(ref_path, op, r_op)) {
-			insert(strdup(p->ref_path), false);
-		}
-		p=p->next;
-	}
-}
-
-static void tokenize(char *exp, char *l_op, char *r_op, char *op) {
-	bool operator_found = false;
-	int index = 0, o_len=0;
-	size_t len = strlen(exp);
-	DEBUG("Entry exp|%s|", exp);
-	for(size_t i=0; i<len; ++i) {
-		switch(exp[i]) {
-			case '"':
-				{
-					++i;
-					while(exp[i]!='"') r_op[index++] = exp[i++];
-					break;
-				}
-			case 'a' ... 'z':
-			case 'A' ... 'Z':
-			case '0' ... '9':
-			case '.':
-				if(operator_found) {
-					r_op[index++]=exp[i];
-				} else {
-					l_op[index++]=exp[i];
-				}
-				break;
-			case '=':
-			case '!':
-			case '>':
-			case '<':
-				operator_found = true;
-				index=0;
-				op[o_len++] = exp[i];
-				break;
-			default:
-				ERR("Unknown symbol to parse [%c]", exp[i]);
-				return;
-		}
-	}
-}
-
-static void solve(char *exp) {
-	DEBUG("Entry |%s|", exp);
-
-	char operator[3]={'\0'};
-	char token[NAME_MAX] = {'\0'};
-	char operand[NAME_MAX] = {'\0'};
-	char *plus = strchr(exp, '+');
-
-	if(plus != NULL ) {
-		char s[NAME_MAX] = {'\0'};
-		strncpy(s, exp, (size_t)labs(plus-exp));
-		tokenize(plus+2, token, operand, operator);
-		dereference_path(s, token, operand, operator);
-	} else {
-		tokenize(exp, token, operand, operator);
-		pathnode *p=head;
-		while(p!=NULL) {
-			char name[NAME_MAX]={'\0'};
-			strncpyt(name, p->ref_path, sizeof(name));
-			strncat(name, token, sizeof(name) - 1);
-			if(bbf_get_name_exp(name, operator, operand)){
-				insert(strdup(p->ref_path), false);
-			}
-			p=p->next;
-		}
-	}
-	deleteList();
-}
-
-static void fill_node_path() {
-	pathnode *p=head;
-	while(p!=NULL) {
-		bbf_get_name(p->ref_path);
-		p=p->next;
-	}
-	deleteList();
-
-	// Check if the newly added nodes are instances or not
-	p = head;
-	if (p != NULL) {
-		char *ins = NULL;
-		size_t len;
-		char temp[NAME_MAX] = { };
-
-		len = strlen(p->ref_path);
-		strncpyt(temp, p->ref_path, len);
-		if (temp[len - 1] == '.')
-			temp[len - 1] = '\0';
-
-		ins = strrchr(temp, DELIM);
-
-		if (ins) {
-			size_t diff = labs(ins - temp);
-			if (is_node_instance(temp + diff + 1) == false) {
-				ERR("Invalid expression used to expand path");
-				deleteList();
-			}
-		}
-	}
-}
-
-static size_t expand_expression(char *path, char *exp) {
-	DEBUG("Entry path|%s|, exp|%s|", path, exp);
-	size_t shiftpos = 0;
-
-	switch(exp[0]) {
-		case '*':
-			fill_node_path();
-			shiftpos = 2;
-			break;
-		case '[':
-			fill_node_path();
-			// Get multiple tokens and then evaluate
-			shiftpos = strlen(exp) + 2;
-			char *token;
-			char *rest = exp+1;
-			/* walk through other tokens */
-			while ((token = strtok_r(rest, "&&", &rest))) {
-				DEBUG("solve %s", token );
-				solve(token);
-			}
-			break;
-		case 'A' ... 'Z': // search by reference
-		case 'a' ... 'z':
-			shiftpos = strlen(exp)+1;
-			char *sharp = strchr(exp, '#');
-			int ref_number=1;
-			char *node = NULL;
-			char name[NAME_MAX] = {'\0'};
-			char _path[NAME_MAX] = {'\0'};
-			if(sharp) {
-				ref_number = atoi(sharp +1);
-				DEBUG("sharp |%s|, ins |%d|", sharp, ref_number);
-			}
-			char *plus = strchr(exp, '+');
-
-			if(!plus) {
-				ERR("solver not available[%s]", exp);
-				break;
-			}
-
-			if(sharp)
-				strncpy(name, exp, (size_t)labs(sharp - exp));
-			else
-				strncpy(name, exp, (size_t)labs(plus - exp));
-
-			pathnode *p=head;
-			while(p!=NULL) {
-				char *token = NULL;
-				snprintf(_path, NAME_MAX, "%s%s", p->ref_path, name);
-				node = bbf_get_value_by_id(_path);
-				int node_count = 1;
-				while ((token = strtok_r(node, ",", &node))) {
-					if(node_count == ref_number)
-						break;
-					node_count++;
-				}
-				if(token) // Error handling if non-existent ref_num is given
-					insert(strdup(token), false);
-
-				p=p->next;
-				free(node);
-			}
-			deleteList();
-			break;
-		default:
-			ERR("Unsupported case[%c]", path[0]);
-			break;
-	}
-	return(shiftpos);
-}
-
-void filter_results(char *path, size_t start, size_t end) {
-	size_t startpos = start, m_index=0, m_len=0;
-	char *pp = path + startpos;
-	char exp[NAME_MAX]={'\0'};
-	DEBUG("Entry path|%s| start|%zu| end|%zu| pp|%s|", path, start, end, pp);
-
-	if(start >= end) {
-		return;
-	}
-
-	if(!is_res_required(pp, &m_index, &m_len)) {
-		//append rest of the path to the final list
-		if(pp == path ) {
-			insert(strdup(pp), true);
-			return;
-		}
-
-		pathnode *p=head;
-		while(p!=NULL) {
-			char name[NAME_MAX]={'\0'};
-			strncpy(name, p->ref_path, sizeof(name));
-			strncat(name, pp, sizeof(name) - 1);
-			DEBUG("Final path[%s], ref |%s|", name, p->ref_path);
-			insert(strdup(name), false);
-			p = p->next;
-		}
-		deleteList();
-		return;
-	}
-
-	// Get the string before the match
-	char name[NAME_MAX]={'\0'};
-	strncpy(name, pp, m_index);
-	pathnode *p = head;
-
-	if(p == NULL) {
-		insert(strdup(name), false);
-	}
-
-	while(p!=NULL) {
-		char ref_name[NAME_MAX]={'\0'};
-		snprintf(ref_name, NAME_MAX, "%s%s", p->ref_path, name);
-		insert(strdup(ref_name), false);
-		p = p->next;
-	}
-	deleteList();
-	startpos += m_index;
-
-	strncpy(exp, pp+m_index, m_len);
-	pp = path + startpos;
-	size_t pos = 0;
-	pos = expand_expression(pp, exp);
-	startpos += pos;
-	filter_results(path, startpos, end);
-}
-
diff --git a/src/common.h b/src/common.h
index deb2fecb7533a87f7e653d0c54eecad8b1ca252d..f824c72edab44c65b959104a383e1c0a66fa5d53 100644
--- a/src/common.h
+++ b/src/common.h
@@ -6,83 +6,68 @@
 #include <syslog.h>
 #include <regex.h>
 #include <sys/param.h>
-#include <ctype.h>
 
 #include <libubox/blobmsg.h>
 #include <libubox/blobmsg_json.h>
 #include <libubox/utils.h>
-#include <libubus.h>
 
-#include <libbbfdm/dmentry.h>
-#include <libbbfdm/dmbbfcommon.h>
-#include <libbbf_api/dmbbf.h>
+#define ROOT_NODE "Device."
+#define USP "usp"
+#define USPRAW "usp.raw"
+#define USPEXT "usp.Device."
 
+#define MAX_DM_KEY_LEN 256
+#define MAX_DM_PATH 1024
+#define MAX_DM_VALUE 4096
+#define DM_VALUE_SEP ","
 #define DELIM '.'
 
-typedef struct pathnode {
-	char *ref_path;
-	struct pathnode *next;
-} pathnode;
+#define GLOB_CHAR "[[+*]+"
+#define GLOB_EXPR "[=><]+"
+#define GLOB_USP_PATH "[+#=><]+"
+
+#define USP_ERR_OK                        0
+#define USP_ERR_INTERNAL_ERROR            7003       // Message failed due to an internal error
+// Message failed due to invalid values in the request elements and/or failure
+// to update one or more parameters during Add or Set requests
+#define USP_ERR_INVALID_ARGUMENTS         7004
+#define USP_ERR_RESOURCES_EXCEEDED        7005       // Message failed due to memory or processing limitations
+#define USP_ERR_INVALID_PATH_SYNTAX       7008       // Requested path was invalid or a reference was invalid
+// Requested Path Name associated with this ParamError did not match any
+// instantiated parameters
+#define USP_ERR_UNSUPPORTED_PARAM         7010
+#define USP_ERR_INVALID_TYPE              7011       // Unable to convert string value to correct data type
+#define USP_ERR_INVALID_VALUE             7012       // Out of range or invalid enumeration
+#define USP_ERR_COMMAND_FAILURE           7022       // Command failed to operate
+#define USP_ERR_INVALID_PATH              7026       // Path is not present in the data model schema
 
-
-void bbf_init(struct dmctx *dm_ctx, char *path);
-void bbf_cleanup(struct dmctx *dm_ctx);
-char *bbf_get_value_by_id(char *id);
-int bbf_set_value(struct blob_buf *bb, char *path, char *value, char *key);
-int bbf_set_notification(struct blob_buf *bb, char *path, char *notif, char *change);
-int bbf_get_value(char *path, bool fill, char *query_path,
-		  struct blob_buf *bb, uint8_t maxdepth);
-bool bbf_get_name(char *path);
-int bbf_get_raw(int cmd, char *path, struct blob_buf *bb, char *nxt_lvl);
-int bbf_get_blob(int cmd, char *path, struct blob_buf *bb, char *nxt_lvl);
-int bbf_get_inst_name_raw(char *path, struct blob_buf *bb);
-int bbf_get_name_raw(char *path, struct blob_buf *bb, bool nxt_lvl);
-bool get_granular_obj_list(char *path);
-int bbf_operate(struct dmctx *dm_ctx, char *path, char *input_params);
-
-void insert(char *data, bool active);
-void filter_results(char *path, size_t start, size_t end);
-
-void deleteList();
-void printList(bool active);
-
-bool is_str_eq(const char *s1, const char *s2);
 bool match(const char *string, const char *pattern);
-void insert_result(char *name, char *value, char *type);
-void delete_result();
-void process_result(struct blob_buf *bb, unsigned int len);
-void prepare_result(struct blob_buf *bb);
-
-bool get_uci_option_string(char *package, char *section, char *option, char **value);
-int bbf_validate_path(char *path);
-void update_valid_paths();
-int bbf_list_operate(struct dmctx *dm_ctx);
+bool is_str_eq(const char *s1, const char *s2);
+bool is_node_instance(char *path);
+int count_delim(char *path);
+bool get_uci_option_string(char *package, char *section,
+			   char *option, char **value);
 
 void set_debug_level(unsigned char level);
 void print_error(const char *format, ...);
 void print_warning(const char *format, ...);
 void print_info(const char *format, ...);
 void print_debug(const char *format, ...);
+bool get_boolean_string(char *value);
+
+int get_dm_type(char *dm_str);
 
 #define DEBUG(fmt, args...) \
-do { \
-	print_debug("[%s:%d]"fmt, __func__, __LINE__, ##args); \
-} while (0)
+	print_debug("[%s:%d]"fmt, __func__, __LINE__, ##args)
 
 #define INFO(fmt, args...) \
-do { \
-	print_info(fmt, ##args); \
-} while (0)
+	print_info(fmt, ##args)
 
 #define ERR(fmt, args...) \
-do { \
-	print_error("[%s:%d] " fmt, __func__, __LINE__, ##args); \
-} while (0)
+	print_error("[%s:%d] " fmt, __func__, __LINE__, ##args)
 
 #define WARNING(fmt, args...) \
-do { \
-	print_warning("[%s:%d] " fmt, __func__, __LINE__, ##args); \
-} while (0)
+	print_warning("[%s:%d] " fmt, __func__, __LINE__, ##args)
 
 #define __unused __attribute__((unused))
 
diff --git a/src/get.c b/src/get.c
index b5ff5d54e89c81ae35cc0801726655d134c70e7c..facb026aa526e16211596d9aae7e535eb97c8dcc 100644
--- a/src/get.c
+++ b/src/get.c
@@ -20,114 +20,273 @@
  * 02110-1301 USA
  */
 
-#include "common.h"
 #include "get.h"
 #include "strncpyt.h"
+#include "get_helper.h"
+#include "pretty_print.h"
+#include <libubus.h>
 
-extern pathnode *head;
+void *usp_get_thread(void *arg)
+{
+	struct ubus_context *ctx;
+	struct ubus_request_data *req;
+	struct thread_data *tdata;
+	struct blob_buf bb;
+	int fault = USP_ERR_OK, proto;
+	char *qpath;
+	bool raw;
+	uint8_t depth;
+
+	tdata = (struct thread_data *) arg;
+
+	if (tdata == NULL)
+		return NULL;
+
+	ctx = tdata->ctx;
+	req = tdata->req;
+	qpath = tdata->qpath;
+	proto = tdata->proto;
+	raw = tdata->raw;
+	depth = tdata->depth;
+
+	LIST_HEAD(pv_list);
+	LIST_HEAD(resolved_list);
+
+	// Fill the blob_buf for sharing the result
+	memset(&bb, 0, sizeof(struct blob_buf));
+	blob_buf_init(&bb, 0);
+
+	fault = get_resolved_paths(qpath, proto, &pv_list, &resolved_list);
 
-void create_response(struct blob_buf *bb, char *qpath, uint8_t maxdepth) {
-	pathnode *p=head;
-	p = head;
-	while(p!=NULL) {
-		if (bbf_get_value(p->ref_path, true, qpath, bb, maxdepth))
-			break;
-		p = p->next;
+	INFO("Preparing result for(%s)", qpath);
+	if (fault) {
+		fill_err_code(&bb, fault);
+	} else {
+		if (raw)
+			prepare_result_raw(&bb, &pv_list, &resolved_list);
+		else
+			prepare_pretty_result(depth, qpath, &bb, &pv_list, &resolved_list);
 	}
-	deleteList();
-	prepare_result(bb);
+
+
+	ubus_send_reply(ctx, req, bb.head);
+	ubus_complete_deferred_request(ctx, req, 0);
+
+	// free
+	blob_buf_free(&bb);
+	free_path_list(&resolved_list);
+	free_pv_list(&pv_list);
+	free(req);
+	free(qpath);
+	free(tdata);
+
+	return NULL;
 }
 
-void create_raw_response(struct blob_buf *bb) {
-	pathnode *p=head;
-	void *array = blobmsg_open_array(bb, "parameters");
-	while(p!=NULL) {
-		if (bbf_get_raw(CMD_GET_VALUE, p->ref_path, bb, NULL))
-			break;
-		p = p->next;
+void usp_validate_path(struct thread_data *tdata)
+{
+	struct ubus_context *ctx;
+	struct ubus_request_data *req;
+	struct blob_buf bb;
+	int fault = USP_ERR_OK;
+	char *qpath;
+	size_t len;
+
+	if (tdata == NULL)
+		return;
+
+	LIST_HEAD(pv_list);
+
+	ctx = tdata->ctx;
+	req = tdata->req;
+	qpath = tdata->qpath;
+
+	memset(&bb, 0, sizeof(struct blob_buf));
+	blob_buf_init(&bb, 0);
+
+	fault = bbf_dm_get_names(qpath, &pv_list, tdata->proto, tdata->next_level);
+	if (!list_empty(&pv_list)) {
+		len = strlen(qpath);
+		if (qpath[len - 1] == '.')
+			qpath[len - 1] = '\0';
+
+		blobmsg_add_string(&bb, "parameter", qpath);
 	}
-	blobmsg_close_array(bb, array);
-	deleteList();
-	prepare_result(bb);
+
+	if (fault)
+		fill_err_code(&bb, fault);
+
+	ubus_send_reply(ctx, req, bb.head);
+	ubus_complete_deferred_request(ctx, req, 0);
+
+	// free
+	blob_buf_free(&bb);
+	free_pv_list(&pv_list);
+	free(req);
+	free(qpath);
+	free(tdata);
 }
 
-void get_resolved_path(struct blob_buf *bb)
+void *usp_get_instance_thread(void *arg)
 {
-	pathnode *p=head;
+	struct ubus_context *ctx;
+	struct ubus_request_data *req;
+	struct thread_data *tdata;
+	struct blob_buf bb;
+	int fault = USP_ERR_OK;
+	char *qpath, *tok;
+	struct pvNode *pv;
 	void *array, *table;
+	size_t qlen, plen;
 
-	array = blobmsg_open_array(bb, "parameters");
-	while(p != NULL) {
-		char temp[NAME_MAX] = { };
-		size_t nlen = strlen(p->ref_path);
-		strncpyt(temp, p->ref_path, nlen);
-		if (temp[nlen - 1] == '.')
-			temp[nlen - 1] = '\0';
+	tdata = (struct thread_data *) arg;
+	if (tdata == NULL)
+		return NULL;
 
-		table = blobmsg_open_table(bb, NULL);
+	LIST_HEAD(pv_list);
 
-		blobmsg_add_string(bb, "parameter", temp);
-		blobmsg_close_table(bb, table);
-		p = p->next;
-	}
-	blobmsg_close_array(bb, array);
-	deleteList();
-}
+	ctx = tdata->ctx;
+	req = tdata->req;
+	qpath = tdata->qpath;
+	qlen = strlen(qpath);
 
-void create_inst_name_response(struct blob_buf *bb) {
-	pathnode *p=head;
-	void *array = blobmsg_open_array(bb, "parameters");
-	while(p!=NULL) {
-		if (bbf_get_inst_name_raw(p->ref_path, bb))
-			break;
-		p = p->next;
-	}
-	blobmsg_close_array(bb, array);
-	deleteList();
-}
+	memset(&bb, 0, sizeof(struct blob_buf));
+	blob_buf_init(&bb, 0);
+
+	if (qpath[qlen - 1] != '.') {
+		fault = USP_ERR_INVALID_PATH_SYNTAX;
+	} else {
+		fault = bbf_dm_get_names(qpath, &pv_list, tdata->proto, tdata->next_level);
+		array = blobmsg_open_array(&bb, "parameters");
+		list_for_each_entry(pv, &pv_list, list) {
+			if (strcmp(pv->type, "xsd:object"))
+				continue;
+
+			plen = strlen(pv->param);
+			if (pv->param[plen - 1] == '.')
+				pv->param[plen - 1] = '\0';
+
+			tok = strrchr(pv->param, DELIM);
+			if (tok == NULL)
+				continue;
 
-void create_name_response(struct blob_buf *bb, bool nxt_lvl) {
-	pathnode *p=head;
-	void *array = blobmsg_open_array(bb, "parameters");
-	while(p!=NULL) {
-		if (bbf_get_name_raw(p->ref_path, bb, nxt_lvl))
-			break;
-		p = p->next;
+			if (is_node_instance(&tok[1])) {
+				table = blobmsg_open_table(&bb, NULL);
+				blobmsg_add_string(&bb, "parameter", pv->param);
+				blobmsg_close_table(&bb, table);
+			}
+		}
+		blobmsg_close_array(&bb, array);
 	}
-	blobmsg_close_array(bb, array);
-	deleteList();
+
+	if (fault)
+		fill_err_code(&bb, fault);
+
+	ubus_send_reply(ctx, req, bb.head);
+	ubus_complete_deferred_request(ctx, req, 0);
+
+	// free
+	blob_buf_free(&bb);
+	free_pv_list(&pv_list);
+	free(req);
+	free(qpath);
+	free(tdata);
+
+	return NULL;
 }
 
-static int bbf_list_schema(struct dmctx *dm_ctx)
+void *usp_get_name_thread(void *arg)
 {
-	int fault = 0;
+	struct ubus_context *ctx;
+	struct ubus_request_data *req;
+	struct thread_data *tdata;
+	struct blob_buf bb;
+	int fault;
+	char *qpath;
+	struct pvNode *pv;
+	void *array, *table;
+
+	LIST_HEAD(pv_list);
+
+	tdata = (struct thread_data *) arg;
+	if (tdata == NULL)
+		return NULL;
+
+	ctx = tdata->ctx;
+	req = tdata->req;
+	qpath = tdata->qpath;
+
+	memset(&bb, 0, sizeof(struct blob_buf));
+	blob_buf_init(&bb, 0);
 
-	fault = dm_entry_param_method(dm_ctx, CMD_GET_SCHEMA, NULL, NULL, NULL);
-	return fault;
+	fault = bbf_dm_get_names(qpath, &pv_list, tdata->proto, tdata->next_level);
+	if (fault) {
+		fill_err_code(&bb, fault);
+	} else {
+		array = blobmsg_open_array(&bb, "parameters");
+		list_for_each_entry(pv, &pv_list, list) {
+			table = blobmsg_open_table(&bb, NULL);
+			blobmsg_add_string(&bb, "parameter", pv->param);
+			blobmsg_add_string(&bb, "writable", pv->val);
+			blobmsg_add_string(&bb, "type", pv->type);
+			blobmsg_close_table(&bb, table);
+		}
+		blobmsg_close_array(&bb, array);
+	}
+
+	ubus_send_reply(ctx, req, bb.head);
+	ubus_complete_deferred_request(ctx, req, 0);
+
+	// free
+	blob_buf_free(&bb);
+	free_pv_list(&pv_list);
+	free(req);
+	free(qpath);
+	free(tdata);
+
+	return NULL;
 }
 
-void list_schema(struct blob_buf *bb)
+void *get_safe_thread(void *arg)
 {
-	struct dmctx dm_ctx = {0};
-	struct dm_parameter *n;
-	void *array, *table;
+	struct safe_thread_data *tdata;
+	struct pathNode *pn;
+	struct blob_buf bb;
+	void *array;
 
-	bbf_init(&dm_ctx, "Device.");
-	bbf_list_schema(&dm_ctx);
-	array = blobmsg_open_array(bb, "parameters");
+	tdata = (struct safe_thread_data *) arg;
 
-	list_for_each_entry(n, &dm_ctx.list_parameter, list) {
-		table = blobmsg_open_table(bb, NULL);
-		blobmsg_add_string(bb, "parameter", n->name);
-		if (strlen(n->data))
-			blobmsg_add_string(bb, "writable", n->data);
-		else
-			blobmsg_add_string(bb, "writable", "0");
+	if (tdata == NULL)
+		return NULL;
 
-		blobmsg_add_string(bb, "type", n->type);
-		blobmsg_close_table(bb, table);
+	memset(&bb, 0, sizeof(struct blob_buf));
+	blob_buf_init(&bb, 0);
+
+	if (tdata->raw)
+		array = blobmsg_open_array(&bb, "parameters");
+
+	dump_resolved_list(tdata->plist);
+	list_for_each_entry(pn, tdata->plist, list) {
+		if (tdata->raw)
+			bbf_get_raw(tdata->cmd, pn->path, &bb,
+				    tdata->next_level, tdata->proto);
+		else
+			bbf_get_blob(tdata->cmd, pn->path, &bb,
+				     tdata->next_level, tdata->proto);
 	}
+	if (tdata->raw)
+		blobmsg_close_array(&bb, array);
 
-	bbf_cleanup(&dm_ctx);
-	blobmsg_close_array(bb, array);
+	ubus_send_reply(tdata->ctx, tdata->req, bb.head);
+	ubus_complete_deferred_request(tdata->ctx, tdata->req, 0);
+
+	free(tdata->req);
+	free(tdata->next_level);
+	free_path_list(tdata->plist);
+	free(tdata->plist);
+	free(tdata);
+	blob_buf_free(&bb);
+
+	return NULL;
 }
+
diff --git a/src/get.h b/src/get.h
index 2758f47e662ba353f217d5f2e5c2689889de9d69..bff8cea416388f229630cdf0e92aa85450f87da1 100644
--- a/src/get.h
+++ b/src/get.h
@@ -1,11 +1,31 @@
 #ifndef GET_H
 #define GET_H
+#include "common.h"
 
-void create_response(struct blob_buf *bb, char *qpath, uint8_t maxdepth);
-void create_raw_response(struct blob_buf *bb);
-void create_name_response(struct blob_buf *bb, bool nxt_lvl);
-void create_inst_name_response(struct blob_buf *bb);
-void get_resolved_path(struct blob_buf *bb);
-void list_schema(struct blob_buf *bb);
+struct safe_thread_data {
+	struct ubus_context *ctx;
+	struct ubus_request_data *req;
+	int proto;
+	bool raw;
+	char *next_level;
+	struct list_head *plist;
+	int cmd;
+};
+
+struct thread_data {
+	struct ubus_context *ctx;
+	struct ubus_request_data *req;
+	char *qpath;
+	int proto;
+	bool raw;
+	uint8_t depth;
+	char next_level[6];
+};
+
+void usp_validate_path(struct thread_data *tdata);
+void *usp_get_thread(void *arg);
+void *usp_get_instance_thread(void *arg);
+void *usp_get_name_thread(void *arg);
+void *get_safe_thread(void *arg);
 
 #endif /* GET_H */
diff --git a/src/get_helper.c b/src/get_helper.c
new file mode 100644
index 0000000000000000000000000000000000000000..36174589ebdf9a7b43d1aea3be308bbb8b380fac
--- /dev/null
+++ b/src/get_helper.c
@@ -0,0 +1,1694 @@
+/*
+ * get_helper.c: Get Fast handler for uspd
+ *
+ * Copyright (C) 2019 iopsys Software Solutions AB. All rights reserved.
+ *
+ * Author: Shubham Sharma <shubham.sharma@iopsys.eu>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#define _XOPEN_SOURCE
+#define _DEFAULT_SOURCE
+
+#include <time.h>
+#include <pthread.h>
+
+#include <libbbfdm/dmentry.h>
+#include <libbbfdm/dmbbfcommon.h>
+#include <libbbf_api/dmbbf.h>
+
+#include "get_helper.h"
+#include "common.h"
+#include "pretty_print.h"
+
+
+static pthread_mutex_t gs_mutex_lock;
+
+static const char * const operations[] = {
+	[OPER_EQUAL_EQUAL] = "==",
+	[OPER_NOT_EQUAL] = "!=",
+	[OPER_LESS_THAN_EQUAL] = "<=",
+	[OPER_GREATER_THAN_EQUAL] = ">=",
+	[OPER_LESS_THAN] = "<",
+	[OPER_GREATER_THAN] = ">"
+};
+
+const char *DMT_TYPE[] = {
+[DMT_STRING] = "xsd:string",
+[DMT_UNINT] = "xsd:unsignedInt",
+[DMT_INT] = "xsd:int",
+[DMT_UNLONG] = "xsd:unsignedLong",
+[DMT_LONG] = "xsd:long",
+[DMT_BOOL] = "xsd:boolean",
+[DMT_TIME] = "xsd:dateTime",
+[DMT_HEXBIN] = "xsd:hexBinary",
+};
+
+// Common utilities
+int get_dm_type(char *dm_str)
+{
+	if (dm_str == NULL)
+		return DMT_STRING;
+
+	if (strcmp(dm_str, DMT_TYPE[DMT_STRING]) == 0)
+		return DMT_STRING;
+	else if (strcmp(dm_str, DMT_TYPE[DMT_UNINT]) == 0)
+		return DMT_UNINT;
+	else if (strcmp(dm_str, DMT_TYPE[DMT_INT]) == 0)
+		return DMT_INT;
+	else if (strcmp(dm_str, DMT_TYPE[DMT_UNLONG]) == 0)
+		return DMT_UNLONG;
+	else if (strcmp(dm_str, DMT_TYPE[DMT_LONG]) == 0)
+		return DMT_LONG;
+	else if (strcmp(dm_str, DMT_TYPE[DMT_BOOL]) == 0)
+		return DMT_BOOL;
+	else if (strcmp(dm_str, DMT_TYPE[DMT_TIME]) == 0)
+		return DMT_TIME;
+	else if (strcmp(dm_str, DMT_TYPE[DMT_HEXBIN]) == 0)
+		return DMT_HEXBIN;
+	else
+		return DMT_STRING;
+
+	return DMT_STRING;
+}
+
+static void bbf_init(struct dmctx *dm_ctx, char *path)
+{
+	unsigned int amd = AMD_5, instance = INSTANCE_MODE_NUMBER;
+
+	if (match(path, "[[]+")) {
+		if (!match(path, GLOB_EXPR))
+			instance = INSTANCE_MODE_ALIAS;
+	}
+	DEBUG("amd |%u| instance|%u|", amd, instance);
+	dm_ctx_init(dm_ctx, DM_CWMP, amd, instance);
+}
+
+static void bbf_cleanup(struct dmctx *dm_ctx)
+{
+	dm_ctx_clean(dm_ctx);
+}
+
+static void __unused bbf_sub_init(struct dmctx *dm_ctx, char *path);
+static void __unused bbf_sub_cleanup(struct dmctx *dm_ctx);
+
+static void bbf_sub_init(struct dmctx *dm_ctx, char *path)
+{
+	unsigned int amd = AMD_5, instance = INSTANCE_MODE_NUMBER;
+
+	if (match(path, "[[]+")) {
+		if (!match(path, GLOB_EXPR))
+			instance = INSTANCE_MODE_ALIAS;
+	}
+	DEBUG("amd |%u| instance|%u|", amd, instance);
+	dm_ctx_init_sub(dm_ctx, DM_CWMP, amd, instance);
+}
+
+static void bbf_sub_cleanup(struct dmctx *dm_ctx)
+{
+	dm_ctx_clean_sub(dm_ctx);
+}
+
+int get_resolved_paths(char *qpath, int proto, struct list_head *pv_list, struct list_head *resolved_paths)
+{
+	int fault = USP_ERR_OK;
+	char bpath[MAX_DM_PATH] = {0};
+	size_t pos = 0;
+
+	if (proto == BBFDM_CWMP) {
+		if (match(qpath, GLOB_USP_PATH)) {
+			fault = 9005;
+		} else {
+			add_path_node(qpath, resolved_paths);
+			fault = bbf_dm_get_values(qpath, pv_list, proto);
+		}
+	} else {
+		if (get_base_path(qpath, bpath)) {
+			pos = strlen(bpath);
+			INFO("Base Path :: |%s| Pos :: |%d|", bpath, pos);
+
+			fault = bbf_dm_get_values(bpath, pv_list, proto);
+			if (fault == USP_ERR_OK) {
+				add_path_node(bpath, resolved_paths);
+				fault = resolve_path(qpath, pos, pv_list, resolved_paths);
+			}
+		} else {
+			fault = USP_ERR_INVALID_PATH_SYNTAX;
+		}
+	}
+
+	return fault;
+}
+
+bool helper_thread_init(void)
+{
+	if (pthread_mutex_init(&gs_mutex_lock, NULL) != 0) {
+		ERR("mutex init failed");
+		return false;
+	}
+	return true;
+}
+
+bool helper_thread_stop(void)
+{
+	pthread_mutex_destroy(&gs_mutex_lock);
+	return true;
+}
+
+bool get_instance(char *path, size_t start, char *instance)
+{
+	char *ptr;
+	size_t plen;
+
+	if (instance == NULL)
+		return false;
+
+	plen = strlen(path);
+	if (plen <= start)
+		return false;
+
+	ptr = strchr(path + start, '.');
+
+	if (ptr == NULL)
+		return false;
+
+	plen = abs(ptr - path) - start;
+	if (plen > strlen(path))
+		return false;
+
+	strncpyt(instance, path + start, plen + 1);
+	if (atoi(instance) == 0) {
+		if (instance[0] != '[')
+			return false;
+	}
+
+	return true;
+}
+
+// Check for entry in resolved ist, if present or not
+bool present_in_path_list(struct list_head *plist, char *entry)
+{
+	struct pathNode *pos;
+
+	list_for_each_entry(pos, plist, list) {
+		if (!strcmp(pos->path, entry))
+			return true;
+	}
+
+	return false;
+}
+
+bool path_present_in_pvlist(struct list_head *pvlist, char *entry)
+{
+	struct pvNode *pv;
+	size_t len;
+
+	len = strlen(entry);
+	list_for_each_entry(pv, pvlist, list) {
+		if (!strncmp(pv->param, entry, len))
+			return true;
+	}
+
+	return false;
+}
+
+int seperator(char *token, char *para, enum operation *oper, char *value)
+{
+	char *ptr;
+	size_t plen;
+	bool found;
+	uint8_t i, op_count;
+
+	// handle ==, !=, <=, >=
+	if (token == NULL || para == NULL ||
+	    oper == NULL || value == NULL)
+		return USP_ERR_INTERNAL_ERROR;
+
+	found = false;
+	op_count = ARRAY_SIZE(operations);
+	for (i = 0; i < op_count; i++) {
+		ptr = strstr(token, operations[i]);
+		if (ptr) {
+			*oper = i;
+			plen = abs(ptr - token);
+			ptr += strlen(operations[i]);
+			found = true;
+			break;
+		}
+	}
+
+	if (found) {
+		strncpyt(para, token, plen + 1);
+		strcpy(value, ptr);
+		return 0;
+	}
+
+	return USP_ERR_INVALID_PATH_SYNTAX;
+}
+
+void add_path_node(char *para, struct list_head *plist)
+{
+	struct pathNode *node = NULL;
+
+	node = (struct pathNode *) malloc(sizeof(*node));
+
+	if (!node) {
+		ERR("Out of memory!");
+		return;
+	}
+
+	strcpy(node->path, para);
+
+	INIT_LIST_HEAD(&node->list);
+	list_add_tail(&node->list, plist);
+}
+
+void add_pv_node(char *para, char *val, char *type, struct list_head *pv_list)
+{
+	struct pvNode *node = NULL;
+
+	node = (struct pvNode *) malloc(sizeof(*node));
+
+	if (!node) {
+		ERR("Out of memory!");
+		return;
+	}
+
+	node->param = (para) ? strdup(para) : strdup("");
+	node->val = (val) ? strdup(val) : strdup("");
+	node->type = (type) ? strdup(type) : strdup("");
+
+	INIT_LIST_HEAD(&node->list);
+	list_add_tail(&node->list, pv_list);
+}
+
+
+void free_path_list(struct list_head *head)
+{
+	struct pathNode *iter, *node;
+
+	list_for_each_entry_safe(iter, node, head, list) {
+		list_del(&iter->list);
+		free(iter);
+	}
+}
+
+void free_pv_list(struct list_head *head)
+{
+	struct pvNode *iter, *node;
+
+	list_for_each_entry_safe(iter, node, head, list) {
+		free(iter->param);
+		free(iter->val);
+		free(iter->type);
+
+		list_del(&iter->list);
+		free(iter);
+	}
+}
+
+void free_pv_node(struct pvNode *pv)
+{
+	if (pv) {
+		if (strlen(pv->param))
+			free(pv->param);
+		if (strlen(pv->val))
+			free(pv->val);
+		if (strlen(pv->type))
+			free(pv->type);
+
+		list_del(&pv->list);
+		free(pv);
+	}
+}
+
+void refresh_path_list(struct list_head *path_list, struct list_head *plist_local)
+{
+
+	struct pathNode *iter;
+
+	free_path_list(path_list);
+
+	list_for_each_entry(iter, plist_local, list) {
+		add_path_node(iter->path, path_list);
+	}
+}
+
+static bool handle_uint(char *v1, char *v2, enum operation op, int *fault)
+{
+	uint32_t ui1, ui2;
+
+	if (!fault)
+		return false;
+
+	if (v1 == NULL || v2 == NULL)
+		return false;
+
+	ui1 = (uint32_t) atoi(v1);
+	ui2 = (uint32_t) atoi(v2);
+
+	if ((ui1 == 0 && v1[0] != '0') ||
+	    (ui2 == 0 && v2[0] != '0')) {
+		*fault = USP_ERR_INVALID_TYPE;
+		return false;
+	}
+
+	switch (op) {
+	case OPER_EQUAL_EQUAL:
+		return (ui1 == ui2);
+	case OPER_NOT_EQUAL:
+		return (ui1 != ui2);
+	case OPER_LESS_THAN:
+		return (ui1 < ui2);
+	case OPER_GREATER_THAN:
+		return (ui1 > ui2);
+	case OPER_LESS_THAN_EQUAL:
+		return (ui1 <= ui2);
+	case OPER_GREATER_THAN_EQUAL:
+		return (ui1 >= ui2);
+	}
+
+	return false;
+}
+
+static bool handle_int(char *v1, char *v2, enum operation op, int *fault)
+{
+	int32_t i1, i2;
+
+	if (!fault)
+		return false;
+
+	if (v1 == NULL || v2 == NULL)
+		return false;
+
+	i1 = (int32_t) atoi(v1);
+	i2 = (int32_t) atoi(v2);
+
+	if ((i1 == 0 && v1[0] != '0') ||
+	    (i2 == 0 && v2[0] != '0')) {
+		*fault = USP_ERR_INVALID_TYPE;
+		return false;
+	}
+
+	switch (op) {
+	case OPER_EQUAL_EQUAL:
+		return (i1 == i2);
+	case OPER_NOT_EQUAL:
+		return (i1 != i2);
+	case OPER_LESS_THAN:
+		return (i1 < i2);
+	case OPER_GREATER_THAN:
+		return (i1 > i2);
+	case OPER_LESS_THAN_EQUAL:
+		return (i1 <= i2);
+	case OPER_GREATER_THAN_EQUAL:
+		return (i1 >= i2);
+	}
+
+	return false;
+}
+
+static bool handle_unlong(char *v1, char *v2, enum operation op, int *fault)
+{
+	uint64_t ul1, ul2;
+
+	if (!fault)
+		return false;
+
+	if (v1 == NULL || v2 == NULL)
+		return false;
+
+	ul1 = (uint64_t) atoll(v1);
+	ul2 = (uint64_t) atoll(v2);
+
+	if ((ul1 == 0 && v1[0] != '0') ||
+	    (ul2 == 0 && v2[0] != '0')) {
+		*fault = USP_ERR_INVALID_TYPE;
+		return false;
+	}
+
+	switch (op) {
+	case OPER_EQUAL_EQUAL:
+		return (ul1 == ul2);
+	case OPER_NOT_EQUAL:
+		return (ul1 != ul2);
+	case OPER_LESS_THAN:
+		return (ul1 < ul2);
+	case OPER_GREATER_THAN:
+		return (ul1 > ul2);
+	case OPER_LESS_THAN_EQUAL:
+		return (ul1 <= ul2);
+	case OPER_GREATER_THAN_EQUAL:
+		return (ul1 >= ul2);
+	}
+
+	return false;
+}
+
+static bool handle_long(char *v1, char *v2, enum operation op, int *fault)
+{
+	int64_t l1, l2;
+
+	if (!fault)
+		return false;
+
+	if (v1 == NULL || v2 == NULL)
+		return false;
+
+	l1 = (int64_t) atoll(v1);
+	l2 = (int64_t) atoll(v2);
+
+	if ((l1 == 0 && v1[0] != '0') ||
+	    (l2 == 0 && v2[0] != '0')) {
+		*fault = USP_ERR_INVALID_TYPE;
+		return false;
+	}
+
+	switch (op) {
+	case OPER_EQUAL_EQUAL:
+		return (l1 == l2);
+	case OPER_NOT_EQUAL:
+		return (l1 != l2);
+	case OPER_LESS_THAN:
+		return (l1 < l2);
+	case OPER_GREATER_THAN:
+		return (l1 > l2);
+	case OPER_LESS_THAN_EQUAL:
+		return (l1 <= l2);
+	case OPER_GREATER_THAN_EQUAL:
+		return (l1 >= l2);
+	}
+
+	return false;
+}
+
+static bool handle_bool(char *v1, char *v2, enum operation op, int *fault)
+{
+	bool vb1, vb2;
+
+	if (!fault)
+		return false;
+
+	if (v1 == NULL || v2 == NULL)
+		return false;
+
+	vb1 = get_boolean_string(v1);
+	vb2 = get_boolean_string(v2);
+
+	switch (op) {
+	case OPER_EQUAL_EQUAL:
+		return (vb1 == vb2);
+	case OPER_NOT_EQUAL:
+		return (vb1 != vb2);
+	case OPER_LESS_THAN:
+	case OPER_GREATER_THAN:
+	case OPER_LESS_THAN_EQUAL:
+	case OPER_GREATER_THAN_EQUAL:
+		*fault = USP_ERR_INVALID_PATH_SYNTAX;
+		return false;
+	}
+
+	return false;
+}
+
+static bool handle_time(char *v1, char *v2, enum operation op, int *fault)
+{
+	struct tm tm1, tm2;
+	char *tmp;
+	time_t t1, t2;
+	double sec;
+
+	if (!fault)
+		return false;
+
+	if (v1 == NULL || v2 == NULL)
+		return false;
+
+	memset(&tm1, 0, sizeof(t1));
+	memset(&tm2, 0, sizeof(t2));
+
+	tmp = strptime(v1, "%Y-%m-%dT%H:%M:%S", &tm1);
+	if (tmp == NULL)
+		return USP_ERR_INVALID_TYPE;
+
+	tmp = strptime(v2, "%Y-%m-%dT%H:%M:%S", &tm2);
+	if (tmp == NULL)
+		return USP_ERR_INVALID_TYPE;
+
+	t1 = timegm(&tm1);
+	t2 = timegm(&tm2);
+
+	sec = difftime(t1, t2);
+	switch (op) {
+	case OPER_EQUAL_EQUAL:
+		return (sec == 0);
+	case OPER_NOT_EQUAL:
+		return (sec != 0);
+	case OPER_LESS_THAN:
+		return (sec < 0);
+	case OPER_GREATER_THAN:
+		return (sec > 0);
+	case OPER_LESS_THAN_EQUAL:
+		return (sec <= 0);
+	case OPER_GREATER_THAN_EQUAL:
+		return (sec >= 0);
+	}
+
+	return false;
+}
+
+static bool handle_hexbin(char *v1, char *v2,
+			  enum operation op __attribute__((unused)),
+			  int *fault)
+{
+	if (v1 == NULL || v2 == NULL)
+		return false;
+
+	*fault = USP_ERR_INVALID_PATH_SYNTAX;
+	return false;
+}
+
+static bool handle_string(char *v1, char *v2, enum operation op, int *fault)
+{
+	char temp[MAX_DM_VALUE];
+
+	if (!fault)
+		return false;
+
+	if (v2[0] != '"' || v2[strlen(v2) - 1] != '"') {
+		*fault = USP_ERR_INVALID_PATH_SYNTAX;
+		return false;
+	}
+
+	sprintf(temp, "\"%s\"", v1);
+	switch (op) {
+	case OPER_EQUAL_EQUAL:
+		return !strcmp(temp, v2);
+	case OPER_NOT_EQUAL:
+		return !!strcmp(temp, v2);
+	case OPER_LESS_THAN:
+	case OPER_GREATER_THAN:
+	case OPER_LESS_THAN_EQUAL:
+	case OPER_GREATER_THAN_EQUAL:
+		*fault = USP_ERR_INVALID_PATH_SYNTAX;
+		return false;
+	}
+
+	return false;
+}
+
+static bool check_values(char *val_type, char *val1, char *val2, enum operation oper, int *fault)
+{
+	bool result = false;
+
+	DEBUG("type(%s), val1(%s), Val2(%s), Oper(%d)", val_type, val1, val2, oper);
+	switch (get_dm_type(val_type)) {
+	case DMT_STRING:
+		result = handle_string(val1, val2, oper, fault);
+		break;
+	case DMT_UNINT:
+		result = handle_uint(val1, val2, oper, fault);
+		break;
+	case DMT_INT:
+		result = handle_int(val1, val2, oper, fault);
+		break;
+	case DMT_UNLONG:
+		result = handle_unlong(val1, val2, oper, fault);
+		break;
+	case DMT_LONG:
+		result = handle_long(val1, val2, oper, fault);
+		break;
+	case DMT_BOOL:
+		result = handle_bool(val1, val2, oper, fault);
+		break;
+	case DMT_TIME:
+		result = handle_time(val1, val2, oper, fault);
+		break;
+	case DMT_HEXBIN:
+		result = handle_hexbin(val1, val2, oper, fault);
+		break;
+	}
+
+	return result;
+}
+
+bool match_bbf_value(char *path, char *value, enum operation op, int *fault)
+{
+	bool ret;
+	struct pvNode *pv;
+
+	LIST_HEAD(pv_list);
+
+	if (path == NULL || value == NULL || fault == NULL)
+		return false;
+
+	DEBUG("path(%s)", path);
+
+	*fault = bbf_dm_get_values(path, &pv_list, BBFDM_USP);
+	if (*fault) {
+		free_pv_list(&pv_list);
+		ERR("Fault form bbf_get_value : |0x%x| ", fault);
+		return false;
+	}
+
+	ret = false;
+	list_for_each_entry(pv, &pv_list, list) {
+		ret = check_values(pv->type, pv->val, value, op, fault);
+		if (ret) {
+			break;
+		} else {
+			if (*fault != USP_ERR_OK)
+				break;
+		}
+	}
+
+	free_pv_list(&pv_list);
+	return ret;
+}
+
+bool split_reference_info(char *para, char *refer, char *ref_num_str, char *ref_param)
+{
+	char *ptr;
+	uint8_t index;
+	bool found;
+	size_t len, i;
+
+	if (para == NULL || refer == NULL || ref_num_str == NULL || ref_param == NULL)
+		return false;
+
+	len = strlen(para);
+	found = false;
+	ptr = refer;
+	index = 0;
+	ref_num_str[0] = '\0';
+	ref_param[0] = '\0';
+	refer[0] = '\0';
+	for (i = 0; i < len; i++) {
+		if (index >= len)
+			return false;
+
+		if (para[i] == '#') {
+			found = true;
+			ptr[index] = '\0';
+			index = 0;
+			ptr = ref_num_str;
+		} else if (para[i] == '+') {
+			ptr[index] = '\0';
+			index = 0;
+			ptr = ref_param;
+		} else {
+			ptr[index++] = para[i];
+		}
+	}
+	ptr[index] = '\0';
+	if (found) {
+		if (ref_num_str[0] != '*' && atoi(ref_num_str) == 0)
+			return false;
+
+		if (strlen(ref_num_str) > 3)
+			return false;
+	}
+
+	if (ref_param[0] != '.')
+		return false;
+
+	return true;
+}
+
+static int _get_ref_from_path(char *path, char *num, char *ref)
+{
+	int ref_num, count;
+	char *token, *save;
+
+	ref[0] = '\0';
+	ref_num = atoi(num);
+	if (ref_num == 0)
+		return USP_ERR_INVALID_PATH_SYNTAX;
+
+	token = strtok_r(path, DM_VALUE_SEP, &save);
+	count = 0;
+	while (token) {
+		count++;
+		if (ref_num == count)
+			break;
+		token = strtok_r(NULL, DM_VALUE_SEP, &save);
+	}
+	if (ref_num > count)
+		return USP_ERR_INVALID_PATH_SYNTAX;
+
+	strcpy(ref, token);
+
+	return USP_ERR_OK;
+}
+
+int handle_reference(char *bPath, struct list_head *pv_list, char *para,
+		      enum operation oper, char *val, struct list_head *resolved_plist)
+{
+	char temp[MAX_DM_PATH], inst[MAX_DM_KEY_LEN];
+	int fault = 0;
+	size_t len;
+	char refer[MAX_DM_KEY_LEN], ref_num_str[MAX_DM_KEY_LEN] = {0}, ref_param[MAX_DM_KEY_LEN];
+	bool found;
+	struct pvNode *pv;
+	char *token, *save;
+	struct pathNode *iter, *node;
+
+	// parameter will be in order para (SSIDReference#n+.SSID) value("MyHome")
+	found = split_reference_info(para, refer, ref_num_str, ref_param);
+	if (found == false)
+		return USP_ERR_INVALID_PATH_SYNTAX;
+
+	len = strlen(bPath);
+	if (list_empty(resolved_plist)) {
+		list_for_each_entry(pv, pv_list, list) {
+			if (strncmp(pv->param, bPath, len) != 0)
+				continue;
+
+			if (get_instance(pv->param, len, inst) == false)
+				continue;
+
+			sprintf(temp, "%s%s.%s", bPath, inst, refer);
+			if (strcmp(pv->param, temp) != 0)
+				continue;
+
+			if (ref_num_str[0] == '*') {
+				found = true;
+				token = strtok_r(pv->val, DM_VALUE_SEP, &save);
+				while (token) {
+					sprintf(temp, "%s%s", token, &ref_param[1]);
+					if (match_bbf_value(temp, val, oper, &fault) == false) {
+						if (fault != 0)
+							return fault;
+
+						found = false;
+						break;
+					} else {
+						sprintf(temp, "%s%s.", bPath, inst);
+					}
+					token = strtok_r(NULL, DM_VALUE_SEP, &save);
+				}
+
+				if (found)
+					add_path_node(temp, resolved_plist); // Resolved List
+
+				continue;
+			}
+
+			if (strlen(ref_num_str)) {
+				fault = _get_ref_from_path(pv->val, ref_num_str, temp);
+				if (fault)
+					return fault;
+
+				strcat(temp, &ref_param[1]);
+			} else {
+				sprintf(temp, "%s%s", pv->val, &ref_param[1]);
+			}
+
+			if (match_bbf_value(temp, val, oper, &fault)) {
+				sprintf(temp, "%s%s.", bPath, inst);
+				add_path_node(temp, resolved_plist); // Resolved List
+			} else {
+				if (fault != 0)
+					return fault;
+			}
+		}
+	} else {
+
+		list_for_each_entry_safe(iter, node, resolved_plist, list) {
+			sprintf(temp, "%s%s", iter->path, refer);
+
+			found = false;
+			list_for_each_entry(pv, pv_list, list) {
+				if (strcmp(pv->param, temp) == 0) {
+					found = true;
+					break;
+				}
+			}
+
+			if (found == false)
+				return USP_ERR_INVALID_PATH_SYNTAX;
+
+			if (ref_num_str[0] == '*') {
+				token = strtok_r(pv->val, DM_VALUE_SEP, &save);
+				while (token) {
+					sprintf(temp, "%s%s", token, &ref_param[1]);
+					if (match_bbf_value(temp, val, oper, &fault) == false) {
+						list_del(&iter->list);
+						free(iter);
+						if (fault != 0)
+							return fault;
+					}
+					token = strtok_r(NULL, DM_VALUE_SEP, &save);
+				}
+				continue;
+			}
+
+			if (strlen(ref_num_str)) {
+				fault = _get_ref_from_path(pv->val, ref_num_str, temp);
+				if (fault)
+					return fault;
+
+				strcat(temp, &ref_param[1]);
+			} else {
+				sprintf(temp, "%s%s", pv->val, &ref_param[1]);
+			}
+
+			if (match_bbf_value(temp, val, oper, &fault) == false) {
+				list_del(&iter->list);
+				free(iter);
+				if (fault != 0)
+					return fault;
+			}
+		}
+	}
+
+	return 0;
+}
+
+int search_n_apply(char *bPath, char *para, enum operation oper, char *value,
+		   struct list_head *fltrd, struct list_head *resolved_plist)
+{
+	char inst[MAX_DM_KEY_LEN], temp[MAX_DM_PATH] = {0};
+	struct pvNode *pv;
+	size_t blen;
+	int fault = USP_ERR_OK;
+
+	blen = strlen(bPath);
+	if (match(para, "[+]+")) {
+		return handle_reference(bPath, fltrd, para, oper, value, resolved_plist);
+	} else {
+		if (!list_empty(resolved_plist)) {
+			struct pathNode *iter, *node;
+
+			list_for_each_entry_safe(iter, node, resolved_plist, list) {
+				sprintf(temp, "%s%s", iter->path, para);
+
+				list_for_each_entry(pv, fltrd, list) {
+					if (strcmp(pv->param, temp) == 0)
+						break;
+				}
+
+				if (check_values(pv->type, pv->val, value, oper, &fault) == false) {
+					list_del(&iter->list);
+					free(iter);
+					if (fault != USP_ERR_OK)
+						return fault;
+				}
+			}
+		} else {
+			list_for_each_entry(pv, fltrd, list) {
+				if (strncmp(pv->param, bPath, blen) != 0)
+					continue;
+
+				if (get_instance(pv->param, blen, inst) == false)
+					continue;
+
+				sprintf(temp, "%s%s.%s", bPath, inst, para);
+
+				if (strcmp(pv->param, temp) != 0)
+					continue;
+
+				if (check_values(pv->type, pv->val, value, oper, &fault)) {
+					sprintf(temp, "%s%s.", bPath, inst);
+					add_path_node(temp, resolved_plist); // Resolved List
+				} else {
+					if (fault)
+						return fault;
+				}
+			}
+		}
+	}
+
+	return fault;
+}
+
+static int solve_all_filters(char *bPath, char *param, struct list_head *pv_list, struct list_head *resolved_plist)
+{
+	int ret = 0;
+	char *token, *save;
+	struct pvNode *pv;
+	struct pathNode *iter;
+	size_t blen;
+
+	LIST_HEAD(pv_local);
+	LIST_HEAD(plist_local);
+
+	INFO("## Basepath(%s), param(%s)", bPath, param);
+	// Use shorter list for rest of the operation
+	blen = strlen(bPath);
+	list_for_each_entry(pv, pv_list, list) {
+		if (strncmp(pv->param, bPath, blen) == 0)
+			add_pv_node(pv->param, pv->val, pv->type, &pv_local);
+	}
+
+	token = strtok_r(param, "&&", &save);
+	while (token) {
+		enum operation oper;
+		char para[MAX_DM_KEY_LEN] = {0};
+		char value[MAX_DM_VALUE] = {0};
+
+		ret = seperator(token, para, &oper, value);
+		if (ret != 0)
+			break;
+
+		INFO("Filter Para(%s), oper(%d), Val(%s)", para, oper, value);
+		ret = search_n_apply(bPath, para, oper, value, &pv_local, &plist_local);
+
+		if (ret != 0)
+			break;
+
+		if (list_empty(&plist_local))
+			break;
+
+		token = strtok_r(NULL, "&&", &save);
+	}
+
+	//dump_resolved_list(&plist_local);
+	list_for_each_entry(iter, &plist_local, list) {
+		add_path_node(iter->path, resolved_plist);
+	}
+
+	free_path_list(&plist_local);
+	free_pv_list(&pv_local);
+	return ret;
+}
+
+// Will fill param with only the Dot seperated_token
+bool get_next_param(char *qPath, size_t *pos, char *param)
+{
+	size_t qlen, i;
+	bool found;
+
+	if (qPath == NULL || pos == NULL || param == NULL)
+		return false;
+
+	qlen = strlen(qPath);
+	if (*pos >= qlen || *pos >= MAX_DM_PATH || qlen >= MAX_DM_PATH)
+		return false;
+
+	param[0] = '\0';
+	found = false;
+	for (i = *pos; i < qlen; i++) {
+		switch (qPath[i]) {
+		case '[':
+			while (i < qlen) {
+				if (qPath[++i] == ']')
+					break;
+			}
+			if (qPath[++i] != '.') {
+				ERR("No dot after search parameters");
+				return false;
+			}
+			// skip the dot
+			i++;
+			found = true;
+			break;
+		case '.':
+			i++;
+			found = true;
+			break;
+		case '+':
+		case '#':
+			i = qlen;
+			found = true;
+			break;
+		}
+		if (found)
+			break;
+	}
+	if (i == qlen)
+		strncpyt(param, qPath + *pos, i - *pos + 1);
+	else
+		strncpyt(param, qPath + *pos, i - *pos);
+
+	*pos = i;
+
+	// removing last . from param
+	qlen = strlen(param);
+	if (param[qlen - 1] == '.')
+		param[qlen - 1] = '\0';
+
+	if (param[0] == '*') {
+		if (strlen(param) > 1) {
+			ERR("* followed by other characters(%s)", param);
+			return false;
+		}
+
+		// * is not followed by .
+		if (qPath[*pos - 1] != '.') {
+			ERR("* not followed by dot(%c)", qPath[*pos - 1]);
+			return false;
+		}
+	}
+
+	return true;
+}
+
+bool get_base_path(char *query_path, char *base_path)
+{
+	bool found;
+	size_t i, qlen, lastdot, j;
+	char ch;
+
+	if (base_path == NULL)
+		return false;
+
+	base_path[0] = '\0';
+
+	lastdot = 6;
+	qlen = strlen(query_path);
+	found = false;
+	for (i = 0; i < qlen; i++) {
+		switch (query_path[i]) {
+		case '.':
+			lastdot = i + 1;
+			break;
+		case '[':
+			if (query_path[i - 1] != '.')
+				return false;
+
+			for (j = i + 1; j < qlen; j++) {
+				ch = query_path[j];
+				if ((ch == '>') ||
+				    (ch == '<') ||
+				    (ch == '=')) {
+					found = true;
+					break;
+				}
+				if (query_path[j] == ']') {
+					i = j;
+					break;
+				}
+			}
+			break;
+		case '*':
+			if (query_path[i - 1] != '.' &&
+			    query_path[i + 1] != '.')
+				return false;
+			found = true;
+			break;
+		case '+':
+		case '#':
+			if (query_path[i - 1] == '.')
+				return false;
+
+			i = lastdot;
+			found = true;
+			break;
+		}
+		if (found)
+			break;
+	}
+
+	strncpyt(base_path, query_path, i + 1);
+	return true;
+}
+
+static int append_all_instances(char *bPath, struct list_head *pv_list, struct list_head *plist_local)
+{
+	size_t blen;
+	char temp[MAX_DM_PATH], inst[MAX_DM_KEY_LEN], last_added[MAX_DM_KEY_LEN];
+	struct pvNode *pv;
+
+	blen = strlen(bPath);
+	INFO("Base(%s), blen(%d)", bPath, blen);
+
+	last_added[0] = '\0';
+	list_for_each_entry(pv, pv_list, list) {
+		if (strncmp(pv->param, bPath, blen) != 0)
+			continue;
+
+		if (get_instance(pv->param, blen, inst) == false)
+			continue;
+
+		if (strcmp(inst, last_added) == 0)
+			continue;
+
+		// Update Base Path with instance.
+		sprintf(temp, "%s%s.", bPath, inst);
+
+		// safety check, if instances repeates or not in serial order
+		if (!present_in_path_list(plist_local, temp)) {
+			strcpy(last_added, inst);
+			add_path_node(temp, plist_local);
+		}
+	}
+
+	return USP_ERR_OK;
+}
+
+static int follow_ref(char *bPath, char *param, struct list_head *pv_list,
+		struct list_head *plist_local)
+{
+	char temp[MAX_DM_PATH];
+	char refer[MAX_DM_KEY_LEN], ref_num_str[MAX_DM_KEY_LEN], ref_param[MAX_DM_KEY_LEN];
+	bool found;
+	int fault;
+	struct pvNode *pv;
+	uint8_t ref_num, count;
+	char *token, *save;
+
+	DEBUG("bpath(%s), param(%s)", bPath, param);
+
+	found = split_reference_info(param, refer, ref_num_str, ref_param);
+	if (found == false)
+		return USP_ERR_INVALID_PATH_SYNTAX;
+
+	DEBUG("re(%s), num(%s), ref_param(%s)", refer, ref_num_str, ref_param);
+	sprintf(temp, "%s%s", bPath, refer);
+
+	found = false;
+	list_for_each_entry(pv, pv_list, list) {
+		if (strcmp(pv->param, temp) == 0) {
+			found = true;
+			break;
+		}
+	}
+
+	if (found == false)
+		return USP_ERR_INVALID_PATH_SYNTAX;
+
+	if (get_dm_type(pv->type) != DMT_STRING)
+		return USP_ERR_INVALID_VALUE;
+
+	// all references
+	if (ref_num_str[0] == '*') {
+		token = strtok_r(pv->val, DM_VALUE_SEP, &save);
+		while (token) {
+			sprintf(temp, "%s%s", token, &ref_param[1]);
+			DEBUG("## Getting dm * (%s)", temp);
+			fault = bbf_dm_get_values(temp, pv_list, BBFDM_USP);
+			if (fault) {
+				ERR("Fault form bbf_get_value : |0x%x| ", fault);
+				return fault;
+			}
+			add_path_node(temp, plist_local);
+			token = strtok_r(NULL, DM_VALUE_SEP, &save);
+		}
+		return USP_ERR_OK;
+	}
+
+	ref_num = (uint8_t) atoi(ref_num_str);
+	count = 0;
+	found = true;
+	if (ref_num) {
+		token = strtok_r(pv->val, DM_VALUE_SEP, &save);
+		while (token) {
+			count++;
+			if (count == ref_num) {
+				found = true;
+				break;
+			}
+			token = strtok_r(NULL, DM_VALUE_SEP, &save);
+		}
+		if (ref_num > count)
+			return USP_ERR_UNSUPPORTED_PARAM;
+
+		sprintf(temp, "%s%s", token, &ref_param[1]);
+	} else {
+		if (strlen(ref_num_str) != 0)
+			return USP_ERR_INVALID_PATH_SYNTAX;
+
+		sprintf(temp, "%s%s", pv->val, &ref_param[1]);
+	}
+
+	INFO("## Getting dm pv for (%s)", temp);
+	fault = bbf_dm_get_values(temp, pv_list, BBFDM_USP);
+	if (fault) {
+		ERR("Fault form bbf_get_value : |0x%x| ", fault);
+		return fault;
+	}
+	add_path_node(temp, plist_local);
+
+	return 0;
+}
+
+int resolve_path(char *qPath, size_t pos, struct list_head *pv_list, struct list_head *resolved_plist)
+{
+	char temp[MAX_DM_PATH] = {0};
+	char param[MAX_DM_PATH] = {0};
+	size_t plen;
+	struct pathNode *ptr;
+	int fault;
+	size_t start;
+
+	LIST_HEAD(plist_local);
+
+	start = pos;
+	if (start >= strlen(qPath))
+		return 0;
+
+	if (list_empty(resolved_plist))
+		return 0;
+
+	INFO("Entry Len :: %d & qPath :: %s", start, qPath);
+	//dump_pv_list(resolved_plist);
+
+	if (get_next_param(qPath, &start, param) == false)
+		return USP_ERR_INVALID_PATH_SYNTAX;
+
+	plen = strlen(param);
+	DEBUG("PARAM ::(%s) pos ::(%d)", param, start);
+
+	fault = 0;
+	list_for_each_entry(ptr, resolved_plist, list) {
+		strcpy(temp, ptr->path);
+		if (temp[strlen(temp) - 1] != '.')
+			strcat(temp, ".");
+
+		if (param[0] == '[') {
+			param[plen-1] = 0;
+			fault = solve_all_filters(temp, param+1, pv_list, &plist_local);
+		} else if (param[0] == '*') {
+			fault = append_all_instances(temp, pv_list, &plist_local);
+		} else if (match(param, "[+]+")) {
+			fault = follow_ref(temp, param, pv_list, &plist_local);
+		} else {
+			strcat(temp, param);
+			add_path_node(temp, &plist_local);
+			DEBUG("Adding (%s) in reslv local", temp);
+		}
+		if (fault)
+			return fault;
+	}
+
+	refresh_path_list(resolved_plist, &plist_local);
+	free_path_list(&plist_local);
+
+	return resolve_path(qPath, start, pv_list, resolved_plist);
+}
+
+int usp_dm_set(struct blob_buf *bb, char *path, char proto, char *value, char *key)
+{
+	int fault = 0;
+	struct dmctx dm_ctx = {0};
+	void *table;
+
+	// Guard by mutex
+	pthread_mutex_lock(&gs_mutex_lock);
+
+	set_bbfdatamodel_type(proto);
+	bbf_init(&dm_ctx, path);
+
+	fault = dm_entry_param_method(&dm_ctx, CMD_SET_VALUE, path, value, NULL);
+	if (!fault)
+		fault = dm_entry_apply(&dm_ctx, CMD_SET_VALUE, key, NULL);
+
+	if (!list_empty(&dm_ctx.list_fault_param)) {
+		struct param_fault *p;
+
+		list_for_each_entry(p, &dm_ctx.list_fault_param, list) {
+			fault = p->fault;
+			break;
+		}
+	}
+
+	table = blobmsg_open_table(bb, NULL);
+	if (fault) {
+		blobmsg_add_u8(bb, "status", false);
+		blobmsg_add_string(bb, "path", path);
+		blobmsg_add_u32(bb, "fault", (uint32_t)fault);
+	} else {
+		blobmsg_add_u8(bb, "status", true);
+		blobmsg_add_string(bb, "path", path);
+	}
+	blobmsg_close_table(bb, table);
+	bbf_cleanup(&dm_ctx);
+
+	// mutex ends here
+	pthread_mutex_unlock(&gs_mutex_lock);
+
+	return fault;
+}
+
+static int usp_dm_get(int cmd, char *path, struct list_head *pv_list, int proto, char *arg1, char *arg2)
+{
+	int fault = 0;
+	struct param_fault *p;
+	struct dmctx dm_ctx = {0};
+	struct dm_parameter *n;
+
+	if (path == NULL || pv_list == NULL)
+		return USP_ERR_INTERNAL_ERROR;
+
+	// Guard by mutex
+	pthread_mutex_lock(&gs_mutex_lock);
+	set_bbfdatamodel_type(proto);
+	bbf_init(&dm_ctx, path);
+
+	fault = dm_entry_param_method(&dm_ctx, cmd, path, arg1, arg2);
+	if (dm_ctx.list_fault_param.next != &dm_ctx.list_fault_param) {
+		list_for_each_entry(p, &dm_ctx.list_fault_param, list) {
+			fault = p->fault;
+			break;
+		}
+	}
+
+	if (fault == 0) {
+		list_for_each_entry(n, &dm_ctx.list_parameter, list) {
+			add_pv_node(n->name, n->data, n->type, pv_list);
+		}
+	}
+
+	bbf_cleanup(&dm_ctx);
+	// mutex ends here
+	pthread_mutex_unlock(&gs_mutex_lock);
+
+	return fault;
+}
+
+static int usp_dm_set_notif(char *path, int proto, char *arg1, char *arg2)
+{
+	int fault = 0;
+	struct param_fault *p;
+	struct dmctx dm_ctx = {0};
+
+	if (path == NULL)
+		return USP_ERR_INTERNAL_ERROR;
+
+	// Guard by mutex
+	pthread_mutex_lock(&gs_mutex_lock);
+	set_bbfdatamodel_type(proto);
+	bbf_init(&dm_ctx, path);
+
+	fault = dm_entry_param_method(&dm_ctx, CMD_SET_NOTIFICATION, path, arg1, arg2);
+	if (dm_ctx.list_fault_param.next != &dm_ctx.list_fault_param) {
+		list_for_each_entry(p, &dm_ctx.list_fault_param, list) {
+			fault = p->fault;
+			break;
+		}
+	}
+
+	bbf_cleanup(&dm_ctx);
+	// mutex ends here
+	pthread_mutex_unlock(&gs_mutex_lock);
+
+	return fault;
+}
+
+int usp_dm_operate(struct blob_buf *bb, char *path, char *input_params, bool raw)
+{
+	int fault = 0, ret = 0;
+	struct dmctx dm_ctx = {0};
+	struct dm_parameter *n;
+	void *table, *array;
+	struct pvNode *pv;
+
+	LIST_HEAD(pv_list);
+
+	// Guard by mutex
+	pthread_mutex_lock(&gs_mutex_lock);
+	set_bbfdatamodel_type(BBFDM_USP);
+	bbf_init(&dm_ctx, path);
+
+	ret = dm_entry_param_method(&dm_ctx, CMD_USP_OPERATE, path, input_params, NULL);
+	switch (ret) {
+	case CMD_NOT_FOUND:
+		fault = USP_ERR_INVALID_PATH;
+		break;
+	case UBUS_INVALID_ARGUMENTS:
+		fault = USP_ERR_INVALID_ARGUMENTS;
+		break;
+	case FAIL:
+		fault = USP_ERR_COMMAND_FAILURE;
+		break;
+	case SUCCESS:
+		fault = USP_ERR_OK;
+		DEBUG("command executed successfully");
+		break;
+	default:
+		WARNING("Case(%d) not defined", fault);
+		fault = USP_ERR_INVALID_PATH;
+		break;
+	}
+
+	if (ret == SUCCESS) {
+		list_for_each_entry(n, &dm_ctx.list_parameter, list) {
+			add_pv_node(n->name, n->data, n->type, &pv_list);
+		}
+	} else {
+		INFO("libbbf return err(%d), path(%s)", fault, path);
+		fill_err_code(bb, fault);
+	}
+
+	bbf_cleanup(&dm_ctx);
+	// mutex ends here
+	pthread_mutex_unlock(&gs_mutex_lock);
+
+	if (fault != USP_ERR_OK) {
+		WARNING("Fault(%d) in operate(%s)", fault, path);
+		free_pv_list(&pv_list);
+		return fault;
+	}
+
+	if (raw) {
+		array = blobmsg_open_array(bb, "parameters");
+		list_for_each_entry(pv, &pv_list, list) {
+			table = blobmsg_open_table(bb, NULL);
+			blobmsg_add_string(bb, "parameter", pv->param);
+			blobmsg_add_string(bb, "value", pv->val);
+			blobmsg_add_string(bb, "type", pv->type);
+			blobmsg_close_table(bb, table);
+		}
+		blobmsg_close_array(bb, array);
+	} else {
+		array = blobmsg_open_array(bb, "result");
+		table = blobmsg_open_table(bb, NULL);
+		prepare_result_blob(bb, &pv_list);
+		blobmsg_close_table(bb, table);
+		blobmsg_close_array(bb, array);
+	}
+
+	free_pv_list(&pv_list);
+
+	return USP_ERR_OK;
+}
+
+void usp_add_object(struct blob_buf *bb, char *path, const char *pkey, int proto)
+{
+	struct dmctx dm_ctx = {0};
+	struct dmctx *ctx = &dm_ctx;
+	uint32_t fault = 0;
+
+	INFO("Req to add object |%s|", path);
+
+	// Guard by mutex
+	pthread_mutex_lock(&gs_mutex_lock);
+
+	set_bbfdatamodel_type(proto);
+	bbf_init(&dm_ctx, path);
+
+	if (pkey == NULL || pkey[0] == 0)
+		pkey = "true";
+
+	fault = (uint32_t)dm_entry_param_method(&dm_ctx, CMD_ADD_OBJECT, path, (char *)pkey, NULL);
+
+	blobmsg_add_string(bb, "parameter", path);
+	if (fault) {
+		blobmsg_add_u32(bb, "fault", fault);
+	} else {
+		if (ctx->addobj_instance) {
+			blobmsg_add_u8(bb, "status", 1);
+			blobmsg_add_string(bb, "instance", ctx->addobj_instance);
+		} else {
+			blobmsg_add_u8(bb, "status", 0);
+		}
+
+		bbf_apply_end_session();
+		dm_entry_restart_services();
+	}
+	bbf_cleanup(&dm_ctx);
+	// mutex ends here
+	pthread_mutex_unlock(&gs_mutex_lock);
+}
+
+void usp_del_object(struct blob_buf *bb, char *path, const char *pkey, int proto)
+{
+	struct dmctx dm_ctx = {0};
+	uint32_t fault = 0;
+
+	// Guard by mutex
+	pthread_mutex_lock(&gs_mutex_lock);
+
+	set_bbfdatamodel_type(proto);
+	bbf_init(&dm_ctx, path);
+
+	if (pkey == NULL || pkey[0] == 0)
+		pkey = "true";
+
+	fault = (uint32_t)dm_entry_param_method(&dm_ctx, CMD_DEL_OBJECT, path, (char *)pkey, NULL);
+
+	blobmsg_add_string(bb, "parameter", path);
+	if (fault) {
+		blobmsg_add_u8(bb, "status", 0);
+		blobmsg_add_u32(bb, "fault", fault);
+	} else {
+		blobmsg_add_u8(bb, "status", 1);
+		bbf_apply_end_session();
+		dm_entry_restart_services();
+	}
+
+	bbf_cleanup(&dm_ctx);
+	// mutex ends here
+	pthread_mutex_unlock(&gs_mutex_lock);
+}
+
+int bbf_get_blob(int cmd, char *path, struct blob_buf *bb, char *nxt_lvl, int proto)
+{
+	struct pvNode *pv;
+	size_t plen = strlen(path);
+	int fault;
+
+	LIST_HEAD(pv_list);
+
+	DEBUG("Entry path |%s|", path);
+
+	fault = usp_dm_get(cmd, path, &pv_list, proto, nxt_lvl, NULL);
+	if (!fault) {
+		void *t = NULL;
+		size_t poff = 0;
+
+		if (path[plen - 1] == '.') {
+			t = blobmsg_open_table(bb, path);
+			poff = plen;
+		}
+
+		list_for_each_entry(pv, &pv_list, list)
+			blobmsg_add_string(bb, pv->param + poff,  pv->val);
+
+		if (t)
+			blobmsg_close_table(bb, t);
+	} else {
+		blobmsg_add_string(bb, "path", path);
+		blobmsg_add_u32(bb, "fault", (uint32_t)fault);
+	}
+
+	free_pv_list(&pv_list);
+	return fault;
+}
+
+int bbf_get_raw(int cmd, char *path, struct blob_buf *bb, char *nxt_lvl, int proto)
+{
+	struct pvNode *pv;
+	void *table;
+	int fault = USP_ERR_OK;
+
+	LIST_HEAD(pv_list);
+
+	INFO("Entry path |%s|", path);
+	fault = usp_dm_get(cmd, path, &pv_list, proto, nxt_lvl, NULL);
+	if (!fault) {
+		list_for_each_entry(pv, &pv_list, list) {
+			table = blobmsg_open_table(bb, NULL);
+			blobmsg_add_string(bb, "parameter", pv->param);
+			blobmsg_add_string(bb, "value", pv->val);
+			blobmsg_add_string(bb, "type", pv->type);
+			blobmsg_close_table(bb, table);
+		}
+	} else {
+		table = blobmsg_open_table(bb, NULL);
+		blobmsg_add_string(bb, "path", path);
+		blobmsg_add_u32(bb, "fault", (uint32_t)fault);
+		blobmsg_close_table(bb, table);
+	}
+
+	free_pv_list(&pv_list);
+	return fault;
+}
+
+int bbf_set_notification(struct blob_buf *bb, char *path, char *notif, char *change, int proto)
+{
+	void *t;
+	int fault = USP_ERR_OK;
+
+	fault = usp_dm_set_notif(path, proto, notif, change);
+
+	t = blobmsg_open_table(bb, NULL);
+	blobmsg_add_string(bb, "path", path);
+	if (fault)
+		blobmsg_add_u32(bb, "fault", fault);
+	blobmsg_close_table(bb, t);
+
+	return fault;
+}
+
+int bbf_dm_get_schema(struct list_head *pv_list)
+{
+	int fault = 0;
+
+	fault = usp_dm_get(CMD_GET_SCHEMA, "Device.", pv_list, BBFDM_BOTH, NULL, NULL);
+
+	return fault;
+}
+
+int bbf_dm_get_values(char *path, struct list_head *pv_list, int proto)
+{
+	int fault = 0;
+
+	fault = usp_dm_get(CMD_GET_VALUE, path, pv_list, proto, NULL, NULL);
+
+	return fault;
+}
+
+int bbf_dm_get_names(char *path, struct list_head *pv_list, int proto, char *next)
+{
+	int fault = 0;
+
+	fault = usp_dm_get(CMD_GET_NAME, path, pv_list, proto, next, NULL);
+
+	return fault;
+}
+
+int bbf_dm_list_operate(struct list_head *pv_list)
+{
+	int fault = 0;
+
+	fault = usp_dm_get(CMD_USP_LIST_OPERATE, ROOT_NODE, pv_list, BBFDM_USP, NULL, NULL);
+
+	return fault;
+}
+
+bool get_granural_object_paths(struct list_head *path_list, uint8_t maxdepth)
+{
+	struct pvNode *pv;
+	uint8_t count;
+	int fault;
+
+	LIST_HEAD(pv_list);
+
+	fault = bbf_dm_get_names("Device.", &pv_list, BBFDM_BOTH, "0");
+
+	list_for_each_entry(pv, &pv_list, list) {
+		if (strcmp(pv->type, "xsd:object") == 0) {
+			count = count_delim(pv->param);
+			if (count < maxdepth)
+				add_path_node(pv->param, path_list);
+		}
+	}
+	free_pv_list(&pv_list);
+
+	if (fault)
+		return false;
+
+	return true;
+}
+
+void fill_err_code(struct blob_buf *bb, int fault)
+{
+	if (bb && fault)
+		blobmsg_add_u32(bb, "fault", fault);
+}
+
diff --git a/src/get_helper.h b/src/get_helper.h
new file mode 100644
index 0000000000000000000000000000000000000000..a104197bd9f531d3c6f7692f04adf18f657a3707
--- /dev/null
+++ b/src/get_helper.h
@@ -0,0 +1,80 @@
+#ifndef GET_HELPER_H
+#define GET_HELPER_H
+
+#include "common.h"
+#include "strncpyt.h"
+
+#include <libubox/list.h>
+
+enum operation {
+	OPER_EQUAL_EQUAL,
+	OPER_NOT_EQUAL,
+	OPER_LESS_THAN_EQUAL,
+	OPER_GREATER_THAN_EQUAL,
+	OPER_LESS_THAN,
+	OPER_GREATER_THAN,
+};
+
+struct pvNode {
+	char *param;
+	char *val;
+	char *type;
+	struct list_head list;
+};
+
+struct pathNode {
+	char path[MAX_DM_PATH];
+	struct list_head list;
+};
+
+int resolve_path(char *qPath, size_t pos,
+		 struct list_head *pv_list,
+		 struct list_head *resolved_plist);
+
+int bbf_get_values(char *path, struct list_head *pv_list,
+		   int proto);
+
+void add_path_node(char *para, struct list_head *plist);
+void fill_err_code(struct blob_buf *bb, int fault);
+void add_pv_node(char *para, char *val, char *type,
+		 struct list_head *pv_list);
+
+bool path_present_in_pvlist(struct list_head *pvlist, char *entry);
+void free_pv_list(struct list_head *head);
+void free_pv_node(struct pvNode *pv);
+void free_path_list(struct list_head *head);
+
+bool helper_thread_init(void);
+bool helper_thread_stop(void);
+bool get_granural_object_paths(struct list_head *path_list,
+			       uint8_t maxdepth);
+
+int bbf_dm_get_values(char *path, struct list_head *pv_list, int proto);
+int bbf_dm_get_schema(struct list_head *pv_list);
+int bbf_dm_get_names(char *path, struct list_head *pv_list,
+		     int proto, char *next);
+
+int bbf_dm_list_operate(struct list_head *pv_list);
+int usp_dm_set(struct blob_buf *bb, char *path, char proto,
+	       char *value, char *key);
+
+int get_resolved_paths(char *qpath, int proto,
+		       struct list_head *pv_list,
+		       struct list_head *resolved_paths);
+
+int usp_dm_operate(struct blob_buf *bb, char *path, char *input_params, bool raw);
+void usp_del_object(struct blob_buf *bb, char *path,
+		    const char *pkey, int proto);
+
+void usp_add_object(struct blob_buf *bb, char *path,
+		    const char *pkey, int proto);
+
+int bbf_get_blob(int cmd, char *path, struct blob_buf *bb,
+		 char *nxt_lvl, int proto);
+int bbf_get_raw(int cmd, char *path, struct blob_buf *bb,
+		char *nxt_lvl, int proto);
+int bbf_set_notification(struct blob_buf *bb, char *path,
+			 char *notif, char *change, int proto);
+bool get_base_path(char *query_path, char *base_path);
+bool get_next_param(char *qPath, size_t *pos, char *param);
+#endif /* GET_HELPER_H */
diff --git a/src/operate.c b/src/operate.c
index c3c7f74ef8650bc1a0ba5079e6c54b932a21756d..594d5359a9a859fb91a191bcd8f5d59af0be7352 100644
--- a/src/operate.c
+++ b/src/operate.c
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 2019 iopsys Software Solutions AB. All rights reserved.
  *
- * Author: Yashvardhan <y.yashvardhan@iopsys.eu>
+ * Author: Vivek Dutta <vivek.dutta@iopsys.eu>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -22,133 +22,116 @@
 
 #include "common.h"
 #include "operate.h"
+#include "get_helper.h"
+#include "pretty_print.h"
+#include <libbbfdm/dmbbfcommon.h>
+#include <libubus.h>
 
-extern pathnode *head;
-
-static int get_schema_path(char *path, char *schema, int slen)
+static int get_operate_schema_path(char *path, char *schema)
 {
 	char *temp;
 	char *tok, *save;
 
+	schema[0] = '\0';
 	temp = strdup(path);
 	tok = strtok_r(temp, ".", &save);
 	while (tok != NULL) {
-		if (tok[0] == '*') {
-			strncat(schema, "{i}", slen);
-		} else {
-			strncat(schema, tok, slen);
-		}
+		if (tok[0] == '*')
+			strcat(schema, "{i}");
+		else
+			strcat(schema, tok);
+
 		tok = strtok_r(NULL, ".", &save);
 
 		if (tok)
-			strncat(schema, ".", slen);
+			strcat(schema, ".");
 	}
 	free(temp);
-	strncat(schema, "()", slen);
+
+	strcat(schema, "()");
 	return 0;
 }
 
 void list_operate_schema(struct blob_buf *bb)
 {
-	struct dmctx dm_ctx = {0};
-	struct dm_parameter *n;
-	char tmp[NAME_MAX] = {'\0'};
+	struct pvNode *pv;
+	char tmp[MAX_DM_PATH] = {'\0'};
 	void *array, *table;
 
+	LIST_HEAD(pv_list);
+
+	bbf_dm_list_operate(&pv_list);
 
-	bbf_init(&dm_ctx, "Device.");
-	bbf_list_operate(&dm_ctx);
 	array = blobmsg_open_array(bb, "parameters");
+	list_for_each_entry(pv, &pv_list, list) {
+		get_operate_schema_path(pv->param, tmp);
+		DEBUG("Operate node|%s|, schema|%s| type(%s)",
+		      pv->param, tmp, pv->type);
 
-	list_for_each_entry(n, &dm_ctx.list_parameter, list) {
 		table = blobmsg_open_table(bb, NULL);
-		memset(tmp, 0, NAME_MAX);
-		get_schema_path(n->name, tmp, NAME_MAX - 1);
-		INFO("Operate node|%s|, schema|%s| ", n->name, tmp);
 		blobmsg_add_string(bb, "parameter", tmp);
-
-		if (n->type) {
-			INFO("operate type(%s)", n->type);
-			blobmsg_add_string(bb, "type", n->type);
-		}
+		blobmsg_add_string(bb, "type", pv->type);
 		blobmsg_close_table(bb, table);
 	}
 
-	bbf_cleanup(&dm_ctx);
 	blobmsg_close_array(bb, array);
+	free_pv_list(&pv_list);
 }
-opr_ret_t create_operate_response(struct blob_buf *bb, char *cmd, struct blob_attr *bv)
+
+void *usp_operate_thread(void *arg)
 {
-	char *input_params;
-	int fault = 0;
+	struct operate_thread_data *tdata;
+	struct blob_buf bb;
+	struct ubus_context *ctx;
+	struct ubus_request_data *req;
+	struct pathNode *rv;
 	void *array, *table;
+	char path[MAX_DM_PATH];
+	int fault = USP_ERR_OK;
 
-	pathnode *p=head;
+	tdata = (struct operate_thread_data *) arg;
 
-	DEBUG("entry");
+	if (tdata == NULL)
+		return NULL;
 
-	array = blobmsg_open_array(bb, "parameters");
-	while(p!=NULL) {
-		struct dmctx dm_ctx = {0};
-		struct dm_parameter *n;
-		char tmp[NAME_MAX] = {'\0'};
-		snprintf(tmp, NAME_MAX, "%s%s", p->ref_path, cmd);
-		bbf_init(&dm_ctx, tmp);
-
-		if(bv) {
-			input_params = blobmsg_format_json(bv, true);
-			fault = bbf_operate(&dm_ctx, tmp, input_params);
-			free(input_params);
-		} else {
-			fault = bbf_operate(&dm_ctx, tmp, NULL);
-		}
-
-		switch(fault) {
-			case CMD_NOT_FOUND:
-				{
-					table = blobmsg_open_table(bb, NULL);
-					blobmsg_add_u32(bb, "fault", 7026); //USP_ERR_INVALID_PATH
-					blobmsg_close_table(bb, table);
-				}
-				break;
-			case UBUS_INVALID_ARGUMENTS:
-				{
-					table = blobmsg_open_table(bb, NULL);
-					blobmsg_add_u32(bb, "fault", 7004); //USP_ERR_INVALID_ARGUMENTS
-					blobmsg_close_table(bb, table);
-				}
-				break;
-			case SUCCESS:
-				{
-					list_for_each_entry(n, &dm_ctx.list_parameter, list) {
-						table = blobmsg_open_table(bb, NULL);
-						DEBUG("insert node|%s|, value|%s| ", n->name, n->data);
-						blobmsg_add_string(bb, "parameter", n->name);
-						blobmsg_add_string(bb, "value", n->data);
-						blobmsg_add_string(bb, "type", n->type);
-						blobmsg_close_table(bb, table);
-					}
-				}
-				break;
-			case FAIL:
-				{
-					table = blobmsg_open_table(bb, NULL);
-					blobmsg_add_u32(bb, "fault", 7022); //USP_ERR_COMMAND_FAILURE
-					blobmsg_close_table(bb, table);
-				}
-				break;
-			default:
-				{
-					table = blobmsg_open_table(bb, NULL);
-					blobmsg_add_u32(bb, "fault", 7026); //USP_ERR_INVALID_PATH
-					blobmsg_close_table(bb, table);
-					ERR("Case not defined");
-				}
-		}
-		bbf_cleanup(&dm_ctx);
-		p=p->next;
+	ctx = tdata->ctx;
+	req = tdata->req;
+
+	LIST_HEAD(resolved_paths);
+	LIST_HEAD(pv_list);
+
+	memset(&bb, 0, sizeof(struct blob_buf));
+	blob_buf_init(&bb, 0);
+
+	get_resolved_paths(tdata->qpath, BBFDM_USP, &pv_list, &resolved_paths);
+
+	array = blobmsg_open_array(&bb, "Results");
+	list_for_each_entry(rv, &resolved_paths, list) {
+		strcpy(path, rv->path);
+		strcat(path, tdata->cmd);
+
+		table = blobmsg_open_table(&bb, NULL);
+		blobmsg_add_string(&bb, "path", path);
+		fault = usp_dm_operate(&bb, path, tdata->input, tdata->raw);
+		if (fault != USP_ERR_OK)
+			blobmsg_add_u32(&bb, "fault", fault);
+
+		blobmsg_close_table(&bb, table);
 	}
-	blobmsg_close_array(bb, array);
-	deleteList();
-	return SUCCESS;
+	blobmsg_close_array(&bb, array);
+
+	ubus_send_reply(ctx, req, bb.head);
+	ubus_complete_deferred_request(ctx, req, 0);
+
+	// free
+	blob_buf_free(&bb);
+	free_path_list(&resolved_paths);
+	free_pv_list(&pv_list);
+	free(req);
+	free(tdata->qpath);
+	free(tdata->input);
+	free(tdata->cmd);
+	free(tdata);
+
+	return NULL;
 }
diff --git a/src/operate.h b/src/operate.h
index d41ae2b95c6638e00125f708d02d0a18832f027f..180d7a556985dc37011aea4490b272920ecfdbaf 100644
--- a/src/operate.h
+++ b/src/operate.h
@@ -11,6 +11,16 @@ enum {
 	__DM_OPERATE_MAX,
 };
 
-opr_ret_t create_operate_response(struct blob_buf *bb, char *cmd, struct blob_attr *bv);
+struct operate_thread_data {
+	struct ubus_context *ctx;
+	struct ubus_request_data *req;
+	char *qpath;
+	char *cmd;
+	char *input;
+	int proto;
+	bool raw;
+};
+
 void list_operate_schema(struct blob_buf *bb);
+void *usp_operate_thread(void *arg);
 #endif /* OPERATE_H */
diff --git a/src/pretty_print.c b/src/pretty_print.c
new file mode 100644
index 0000000000000000000000000000000000000000..fc1b7ec8ed69e256043350dafe934fce017edae9
--- /dev/null
+++ b/src/pretty_print.c
@@ -0,0 +1,444 @@
+/*
+ * pretty_print.c: utils for pretty printing of results
+ *
+ * Copyright (C) 2020 iopsys Software Solutions AB. All rights reserved.
+ *
+ * Author: Vivek Dutta <vivek.dutta@iopsys.eu>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include "common.h"
+#include "get_helper.h"
+#include "pretty_print.h"
+#include <libbbf_api/dmbbf.h>
+
+
+// private function and structures
+struct resultstack {
+	void *cookie;
+	char *key;
+	struct list_head list;
+};
+
+static bool is_search_by_reference(char *path)
+{
+	size_t pindex = 0, bindex = 0;
+	char *last_plus, *last_bracket;
+
+	DEBUG("Entry |%s|", path);
+
+	if (match(path, "[+]+")) {
+		last_bracket = strrchr(path, ']');
+		if (!last_bracket)
+			return true;
+
+		last_plus = strrchr(path, '+');
+
+		pindex = abs(last_plus - path);
+		bindex = abs(last_bracket - path);
+
+		if (pindex > bindex)
+			return true;
+	}
+
+	return false;
+}
+
+//if matched start will have first match index, end will have end index
+static bool is_res_required(char *str, size_t *start, size_t *len)
+{
+	size_t i = 0, index = 0;
+	char temp_char[MAX_DM_KEY_LEN] = {'\0'};
+	size_t s_len, b_len, p_len;
+	char *star, *b_start, *b_end, *plus;
+
+	DEBUG("Entry |%s|", str);
+	if (match(str, GLOB_CHAR)) {
+		s_len = strlen(str);
+		b_len = s_len;
+		p_len = s_len;
+
+		star = strchr(str, '*');
+		b_start = strchr(str, '[');
+		b_end = strchr(str, ']');
+		plus = strchr(str, '+');
+
+		if (star)
+			s_len = (size_t)labs(star - str);
+
+		if (b_start)
+			b_len = (size_t)labs(b_start - str);
+
+		if (plus)
+			p_len = (size_t)labs(plus - str);
+
+		*start = MIN(MIN(s_len, p_len), b_len);
+		if (*start == s_len) {
+			*len = 1;
+		} else if (*start == p_len) {
+			i = 0, index = 0;
+
+			while ((str+i) != plus) {
+				if (str[i] == DELIM)
+					index = i;
+				++i;
+			}
+			*start = index+1;
+			*len = p_len - index;
+		} else {
+			*len = (size_t)labs(b_end - b_start);
+		}
+
+		// Check if naming with aliases used
+		strncpy(temp_char, str + *start, *len);
+		if (match(temp_char, GLOB_EXPR))
+			return true;
+
+		if (match(temp_char, "[*+]+"))
+			return true;
+	}
+	*start = strlen(str);
+	return false;
+}
+
+static size_t get_glob_len(char *path)
+{
+	size_t m_index = 0, m_len = 0, ret = 0;
+	size_t plen = strlen(path);
+	char temp_name[MAX_DM_KEY_LEN] = {'\0'};
+	char *end = NULL;
+	char name[MAX_DM_KEY_LEN] = {'\0'};
+
+	DEBUG("Entry");
+	if (is_res_required(path, &m_index, &m_len)) {
+		strncpy(temp_name, path, m_index - 1);
+		end = strrchr(temp_name, DELIM);
+		ret = m_index - strlen(end);
+	} else {
+		if (path[plen - 1] == DELIM) {
+			strncpy(name, path, plen - 1);
+		} else {
+			ret = 1;
+			strncpy(name, path, plen);
+		}
+		end = strrchr(name, DELIM);
+		if (end == NULL)
+			return ret;
+
+		ret = ret + strlen(path) - strlen(end);
+		if (is_node_instance(end+1)) {
+			strncpy(temp_name, path, plen - strlen(end) - 1);
+			end = strrchr(temp_name, DELIM);
+			ret = ret - strlen(end);
+		}
+	}
+	return(ret);
+}
+
+static void resulting(uint8_t maxdepth, char *path, char *qPath, struct list_head *pv_list, struct list_head *pv_local)
+{
+	struct pvNode *pv;
+	uint8_t count;
+
+	size_t plen = get_glob_len(qPath);
+	//size_t plen = 0;
+	size_t path_len = strlen(path);
+
+	list_for_each_entry(pv, pv_list, list) {
+		if (!strncmp(pv->param, path, strlen(path))) {
+			if (is_search_by_reference(qPath))
+				plen = 0;
+
+			if (maxdepth > 4 || maxdepth == 0) {
+				add_pv_node(pv->param + plen, pv->val, pv->type, pv_local);
+			} else {
+				count = count_delim(pv->param + path_len);
+				if (count < maxdepth)
+					add_pv_node(pv->param + plen, pv->val, pv->type, pv_local);
+			}
+		}
+	}
+}
+
+static void add_data_blob(struct blob_buf *bb, char *param, char *value, char *type)
+{
+	if (param == NULL || value == NULL || type == NULL)
+		return;
+
+	DEBUG("# Adding BLOB (%s)::(%s)", param, value);
+	switch (get_dm_type(type)) {
+	case DMT_UNINT:
+		blobmsg_add_u32(bb, param, (uint32_t)atoi(value));
+		break;
+	case DMT_INT:
+		blobmsg_add_u32(bb, param, (uint32_t)atoi(value));
+		break;
+	case DMT_LONG:
+		blobmsg_add_u64(bb, param, (uint64_t)atoll(value));
+		break;
+	case DMT_UNLONG:
+		blobmsg_add_u64(bb, param, (uint64_t)atoll(value));
+		break;
+	case DMT_BOOL:
+		if (get_boolean_string(value))
+			blobmsg_add_u8(bb, param, true);
+		else
+			blobmsg_add_u8(bb, param, false);
+		break;
+	default: //"xsd:hexbin" "xsd:dateTime" "xsd:string"
+		blobmsg_add_string(bb, param, value);
+		break;
+	}
+}
+
+static void free_result_list(struct list_head *head)
+{
+	struct resultstack *iter, *node;
+
+	list_for_each_entry_safe(iter, node, head, list) {
+		free(iter->key);
+		list_del(&iter->list);
+		free(iter);
+	}
+}
+
+static void free_result_node(struct resultstack *rnode)
+{
+	if (rnode) {
+		DEBUG("## ResStack DEL(%s)", rnode->key);
+		free(rnode->key);
+		list_del(&rnode->list);
+		free(rnode);
+	}
+}
+
+static void add_result_node(struct list_head *rlist, char *key, char *cookie)
+{
+	struct resultstack *rnode = NULL;
+
+	rnode = (struct resultstack *) malloc(sizeof(*rnode));
+	if (!rnode) {
+		ERR("Out of memory!");
+		return;
+	}
+
+	rnode->key = (key) ? strdup(key) : strdup("");
+	rnode->cookie = cookie;
+	DEBUG("## ResSTACK ADD (%s) ##", rnode->key);
+
+	INIT_LIST_HEAD(&rnode->list);
+	list_add(&rnode->list, rlist);
+}
+
+static bool is_leaf_element(char *path)
+{
+	char *ptr = NULL;
+
+	if (!path)
+		return true;
+
+	ptr = strchr(path, DELIM);
+
+	return (ptr == NULL);
+}
+
+static bool get_next_element(char *path, char *param)
+{
+	char *ptr;
+
+	if (!path)
+		return false;
+
+	ptr = strchr(path, DELIM);
+	if (ptr)
+		strncpyt(param, path, abs(ptr - path) + 1);
+	else
+		strcpy(param, path);
+
+	return true;
+}
+
+static bool is_same_group(char *path, char *group)
+{
+	return (strncmp(path, group, strlen(group)) == 0);
+}
+
+static bool add_paths_to_stack(struct blob_buf *bb, char *path, size_t begin,
+			       struct pvNode *pv, struct list_head *result_stack)
+{
+	char key[MAX_DM_KEY_LEN], param[MAX_DM_PATH], *ptr;
+	size_t parsed_len = 0;
+	void *c;
+	char *k;
+
+
+	ptr = path + begin;
+	if (is_leaf_element(ptr)) {
+		add_data_blob(bb, ptr, pv->val, pv->type);
+		return true;
+	}
+
+	while (get_next_element(ptr, key)) {
+		parsed_len += strlen(key) + 1;
+		ptr += strlen(key) + 1;
+		if (is_leaf_element(ptr)) {
+			strncpyt(param, path, begin + parsed_len + 1);
+			if (is_node_instance(key))
+				c = blobmsg_open_table(bb, NULL);
+			else
+				c = blobmsg_open_table(bb, key);
+
+			k = param;
+			add_result_node(result_stack, k, c);
+			add_data_blob(bb, ptr, pv->val, pv->type);
+			break;
+		} else {
+			strncpyt(param, pv->param, begin + parsed_len + 1);
+			if (is_node_instance(ptr))
+				c = blobmsg_open_array(bb, key);
+			else
+				c = blobmsg_open_table(bb, key);
+
+			k = param;
+			add_result_node(result_stack, k, c);
+		}
+	}
+
+	return true;
+}
+
+// public functions
+void prepare_result_blob(struct blob_buf *bb, struct list_head *pv_list)
+{
+	char *ptr;
+	size_t len = 0;
+	struct pvNode *pv;
+	struct resultstack *rnode;
+
+	LIST_HEAD(result_stack);
+
+	if (!bb || !pv_list)
+		return;
+
+	if (list_empty(pv_list))
+		return;
+
+	list_for_each_entry(pv, pv_list, list) {
+		ptr = pv->param;
+		if (list_empty(&result_stack)) {
+			DEBUG("stack empty Processing (%s)", ptr);
+			add_paths_to_stack(bb, pv->param, 0, pv, &result_stack);
+		} else {
+			bool is_done = false;
+
+			while (is_done == false) {
+				rnode = list_entry(result_stack.next, struct resultstack, list);
+				if (is_same_group(ptr, rnode->key)) {
+					len = strlen(rnode->key);
+					ptr = ptr + len;
+
+					DEBUG("GROUP (%s), ptr(%s), len(%d)", pv->param, ptr, len);
+					add_paths_to_stack(bb, pv->param, len, pv, &result_stack);
+					is_done = true;
+				} else {
+					// Get the latest entry before deleting it
+					DEBUG("DIFF GROUP pv(%s), param(%s)", pv->param, ptr);
+					blobmsg_close_table(bb, rnode->cookie);
+					free_result_node(rnode);
+					if (list_empty(&result_stack)) {
+						add_paths_to_stack(bb, pv->param, 0, pv, &result_stack);
+						is_done = true;
+					}
+				}
+			}
+		}
+	}
+
+	// Close the stack entry if left
+	list_for_each_entry(rnode, &result_stack, list) {
+		blobmsg_close_table(bb, rnode->cookie);
+	}
+	free_result_list(&result_stack);
+}
+
+void prepare_pretty_result(uint8_t maxdepth, char *qPath, struct blob_buf *bb,
+			   struct list_head *pv_list, struct list_head *rslvd)
+{
+	struct pathNode *iter = NULL;
+
+	LIST_HEAD(pv_local);
+
+	list_for_each_entry(iter, rslvd, list) {
+		resulting(maxdepth, iter->path, qPath, pv_list, &pv_local);
+	}
+
+	struct pvNode *pv;
+
+	DEBUG("################### DATA to PROCESS ##################");
+	list_for_each_entry(pv, &pv_local, list) {
+		DEBUG("## %s ##", pv->param);
+	}
+	DEBUG("######################################################");
+
+	prepare_result_blob(bb, &pv_local);
+
+	free_pv_list(&pv_local);
+}
+
+void dump_pv_list(struct list_head *pv_list)
+{
+	struct pvNode *pv;
+
+	INFO("############### PV list Dump #########");
+	list_for_each_entry(pv, pv_list, list) {
+		INFO("## (%s)::(%s)::(%s) ##", pv->param, pv->val, pv->type);
+	}
+	INFO("############# dump done ###############");
+}
+
+void dump_resolved_list(struct list_head *resolved_list)
+{
+	struct pathNode *iter;
+
+	INFO("********************Resolved List Dump***********************");
+	list_for_each_entry(iter, resolved_list, list) {
+		INFO("## %s ##", iter->path);
+	}
+	INFO("**************************DONE*******************************");
+}
+
+void prepare_result_raw(struct blob_buf *bb, struct list_head *pv_list, struct list_head *rslvd)
+{
+	struct pathNode *iter = NULL;
+	struct pvNode *pv;
+	void *array, *table;
+	size_t ilen;
+
+	array = blobmsg_open_array(bb, "parameters");
+	list_for_each_entry(iter, rslvd, list) {
+		ilen = strlen(iter->path);
+		list_for_each_entry(pv, pv_list, list) {
+			if (!strncmp(pv->param, iter->path, ilen)) {
+				table = blobmsg_open_table(bb, NULL);
+				blobmsg_add_string(bb, "parameter", pv->param);
+				blobmsg_add_string(bb, "value", pv->val);
+				blobmsg_add_string(bb, "type", pv->type);
+				blobmsg_close_table(bb, table);
+			}
+		}
+	}
+	blobmsg_close_array(bb, array);
+}
diff --git a/src/pretty_print.h b/src/pretty_print.h
new file mode 100644
index 0000000000000000000000000000000000000000..d301e3197c65ce83121be62b96d39589e86998e9
--- /dev/null
+++ b/src/pretty_print.h
@@ -0,0 +1,33 @@
+/*
+ * pretty_print.h: utils for pretty printing of results
+ *
+ * Copyright (C) 2020 iopsys Software Solutions AB. All rights reserved.
+ *
+ * Author: Vivek Dutta <vivek.dutta@iopsys.eu>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#ifndef PRETTY_PRINT_H
+#define PRETTY_PRINT_H
+
+void prepare_result_blob(struct blob_buf *bb, struct list_head *pv_list);
+void prepare_pretty_result(uint8_t maxdepth, char *qPath, struct blob_buf *bb,
+			 struct list_head *pv_list, struct list_head *rslvd);
+void prepare_result_raw(struct blob_buf *bb, struct list_head *pv_list, struct list_head *rslvd);
+void dump_pv_list(struct list_head *pv_list);
+void dump_resolved_list(struct list_head *resolved_list);
+
+#endif
diff --git a/src/set.c b/src/set.c
index bf0bac6f5df58980959a6c61b45227fab9e38e53..79700e61cabc8697911b76bb906cd9a6f5fc3109 100644
--- a/src/set.c
+++ b/src/set.c
@@ -22,58 +22,109 @@
 
 #include "common.h"
 #include "set.h"
+#include "get_helper.h"
+#include <libubus.h>
 
-extern pathnode *head;
+#include <libbbfdm/dmentry.h>
 
-void create_set_response(struct blob_buf *bb, char *value, char *key) {
-	pathnode *p=head;
-	while(p!=NULL) {
-		if (bbf_set_value(bb, p->ref_path, value, key))
-			break;
-		p=p->next;
+
+void *usp_set_thread(void *arg)
+{
+	struct set_thread_data *tdata;
+	struct blob_buf bb;
+	struct ubus_context *ctx;
+	struct ubus_request_data *req;
+	char *qpath;
+	struct list_head *val_pv_list;
+	char *key;
+	int proto;
+	char temp[MAX_DM_PATH] = {0};
+	void *array;
+	struct pathNode *rv;
+	struct pvNode *pv;
+
+	tdata = (struct set_thread_data *) arg;
+
+	if (tdata == NULL)
+		return NULL;
+
+	ctx = tdata->ctx;
+	req = tdata->req;
+	qpath = tdata->qpath;
+	proto = tdata->proto;
+	val_pv_list = tdata->pv_list;
+	key = tdata->key;
+
+	LIST_HEAD(resolved_paths);
+	LIST_HEAD(pv_list);
+
+	memset(&bb, 0, sizeof(struct blob_buf));
+	blob_buf_init(&bb, 0);
+
+	get_resolved_paths(qpath, proto, &pv_list, &resolved_paths);
+
+	array = blobmsg_open_array(&bb, "parameters");
+	list_for_each_entry(rv, &resolved_paths, list) {
+		list_for_each_entry(pv, val_pv_list, list) {
+			snprintf(temp, MAX_DM_PATH, "%s%s", rv->path, pv->param);
+			INFO("## set (%s)::(%s)::(%s) ##", temp, pv->val, key);
+			usp_dm_set(&bb, temp, proto, pv->val, key);
+		}
 	}
-	deleteList();
-}
+	blobmsg_close_array(&bb, array);
 
-void set_multiple_values(struct blob_buf *bb, struct blob_attr *blob_value, char *key) {
+	ubus_send_reply(ctx, req, bb.head);
+	ubus_complete_deferred_request(ctx, req, 0);
 
-	size_t tlen = (size_t)blobmsg_data_len(blob_value);
+	// free
+	blob_buf_free(&bb);
+	free_path_list(&resolved_paths);
+	free_pv_list(&pv_list);
+	free_pv_list(val_pv_list);
+	free(val_pv_list);
+	free(req);
+	free(qpath);
+	free(tdata);
+	free(key);
+
+	// Restart all the affected services
+	dm_entry_restart_services();
+	return NULL;
+}
+
+bool get_values_in_pvlist(struct blob_attr *blob_value, struct list_head *pv_list)
+{
 	struct blob_attr *attr;
+	char value[MAX_DM_VALUE];
+	struct blobmsg_hdr *hdr;
+	size_t tlen = (size_t)blobmsg_data_len(blob_value);
 
 	__blob_for_each_attr(attr, blobmsg_data(blob_value), tlen) {
-		struct blobmsg_hdr *hdr = blob_data(attr);
-
-		pathnode *p=head;
-		while(p!=NULL) {
-			char path[PATH_MAX] = {'\0'}, value[NAME_MAX] = {'\0'};
-			snprintf(path, PATH_MAX, "%s%s", p->ref_path, hdr->name);
-
-			switch(blob_id(attr)) {
-				case BLOBMSG_TYPE_STRING:
-					snprintf(value, NAME_MAX, "%s", (char *)blobmsg_data(attr));
-					break;
-				case BLOBMSG_TYPE_INT8:
-					sprintf(value, "%d", *(uint8_t *)blobmsg_data(attr));
-					break;
-				case BLOBMSG_TYPE_INT16:
-					sprintf(value, "%d", *(uint16_t *)blobmsg_data(attr));
-					break;
-				case BLOBMSG_TYPE_INT32:
-					sprintf(value, "%u", *(uint32_t *)blobmsg_data(attr));
-					break;
-				case BLOBMSG_TYPE_INT64:
-				case BLOBMSG_TYPE_DOUBLE:
-					snprintf(value, NAME_MAX, "%"PRIu64"", *(uint64_t *)blobmsg_data(attr));
-					break;
-				default:
-					INFO("Unhandled set request type|%x|", blob_id(attr));
-					break;
-			}
-
-			if (bbf_set_value(bb, path, value, key))
-				break;
-			p=p->next;
+		hdr = blob_data(attr);
+
+		switch (blob_id(attr)) {
+		case BLOBMSG_TYPE_STRING:
+			snprintf(value, MAX_DM_VALUE, "%s", (char *)blobmsg_data(attr));
+			break;
+		case BLOBMSG_TYPE_INT8:
+			sprintf(value, "%d", *(uint8_t *)blobmsg_data(attr));
+			break;
+		case BLOBMSG_TYPE_INT16:
+			sprintf(value, "%d", *(uint16_t *)blobmsg_data(attr));
+			break;
+		case BLOBMSG_TYPE_INT32:
+			sprintf(value, "%u", *(uint32_t *)blobmsg_data(attr));
+			break;
+		case BLOBMSG_TYPE_INT64:
+		case BLOBMSG_TYPE_DOUBLE:
+			snprintf(value, MAX_DM_VALUE, "%"PRIu64"", *(uint64_t *)blobmsg_data(attr));
+			break;
+		default:
+			INFO("Unhandled set request type|%x|", blob_id(attr));
+			return false;
 		}
+		add_pv_node((char *)hdr->name, value, NULL, pv_list);
 	}
-	deleteList();
+
+	return true;
 }
diff --git a/src/set.h b/src/set.h
index d0b7da39021c1f4578f21d107eeb6439f2f52947..1755945b0b25be777d71ad18e4a228a4b41f67ee 100644
--- a/src/set.h
+++ b/src/set.h
@@ -1,7 +1,22 @@
 #ifndef SET_H
 #define SET_H
 
+struct set_thread_data {
+	struct ubus_context *ctx;
+	struct ubus_request_data *req;
+	char *qpath;
+	struct list_head *pv_list;
+	char *key;
+	int proto;
+};
+
 void create_set_response(struct blob_buf *bb, char *value, char *key);
-void set_multiple_values(struct blob_buf *bb, struct blob_attr *blob_value, char *key);
+void set_multiple_values(struct blob_buf *bb, struct blob_attr *blob_value,
+			 char *key);
+bool get_values_in_pvlist(struct blob_attr *blob_value,
+			  struct list_head *pv_list);
+
+void *usp_set_thread(void *arg);
+
 #endif /* SET_H */
 
diff --git a/src/strncpyt.h b/src/strncpyt.h
index 77eca01d2049b9e200c8aa4e4c772500f2e3460f..5f286111d1444c9d626ae084d7806d7d3b9c66de 100644
--- a/src/strncpyt.h
+++ b/src/strncpyt.h
@@ -3,20 +3,14 @@
 
 #include <string.h>
 
-/* glibc doesn't guarantee a 0 termianted string on strncpy
- */
-#ifdef __GLIBC__
-
-/* strncpy with always 0 terminated string
- */
+// glibc doesn't guarantee a 0 termianted string on strncpy
+// strncpy with always 0 terminated string
 static inline void strncpyt(char *dst, const char *src, size_t n)
 {
-	strncpy(dst, src, n - 1);
-	dst[n - 1] = 0;
+	if (n > 1) {
+		strncpy(dst, src, n - 1);
+		dst[n - 1] = 0;
+	}
 }
 
-#else
-#define strncpyt strncpy
-#endif
-
 #endif
diff --git a/src/usp.c b/src/usp.c
index c7534d9f05a544f8e67a78311ecda619bc5e7819..a5042336227ad4a59abacfff2da275fcf181739a 100644
--- a/src/usp.c
+++ b/src/usp.c
@@ -4,7 +4,6 @@
  * Copyright (C) 2019 iopsys Software Solutions AB. All rights reserved.
  *
  * Author: Vivek Dutta <vivek.dutta@iopsys.eu>
- * Author: Yashvardhan <y.yashvardhan@iopsys.eu>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -29,6 +28,11 @@
 #include <libubox/blobmsg.h>
 #include <libubox/uloop.h>
 #include <libubus.h>
+#include <pthread.h>
+
+#include <libbbfdm/dmentry.h>
+#include <libbbfdm/dmbbfcommon.h>
+#include <libbbf_api/dmbbf.h>
 
 /* Not all libc implementations have MAXNAMLEN defined
  */
@@ -38,21 +42,16 @@
 
 #include "set.h"
 #include "get.h"
+#include "get_helper.h"
 #include "operate.h"
 #include "common.h"
 #include "add_delete.h"
 #include "strncpyt.h"
 
-#define USP "usp"
-#define USP_GRA "usp."
-#define RAWUSP "usp.raw"
-#define DEFAULT_LOG_LEVEL (2)
-
-#define MIN_LEN (7)  // len of 'Device.'
-#define ROOT_NODE "Device."
+#define USP_EXT_LEN (4) // length of usp.
+#define MAX_GRANURALITY_DEPTH (3)
 
-
-extern pathnode *head;
+LIST_HEAD(g_schema_pv_list);
 
 enum {
 	DM_GET_PATH,
@@ -62,13 +61,6 @@ enum {
 	__DM_GET_MAX
 };
 
-enum {
-	DM_GET_SAFE_PATHS,
-	DM_GET_SAFE_PROTO,
-	DM_GET_SAFE_NXT_LVL,
-	__DM_GET_SAFE_MAX
-};
-
 enum {
 	DM_SETS_PATHS,
 	DM_SETS_PROTO,
@@ -98,37 +90,44 @@ enum {
 	__DM_SET_MAX,
 };
 
-static const struct blobmsg_policy dm_get_policy[__DM_GET_MAX] = {
-	[DM_GET_PATH] = { .name = "path", .type = BLOBMSG_TYPE_STRING },
-	[DM_GET_PROTO] = { .name = "proto", .type = BLOBMSG_TYPE_STRING },
-	[DM_GET_MAXDEPTH] = { .name = "maxdepth", .type = BLOBMSG_TYPE_INT32 },
-	[DM_GET_NXT_LVL] = { .name = "next-level", .type = BLOBMSG_TYPE_INT8 },
+enum {
+	DM_GET_SAFE_PATHS,
+	DM_GET_SAFE_PROTO,
+	DM_GET_SAFE_NXT_LVL,
+	__DM_GET_SAFE_MAX
 };
 
-static const struct blobmsg_policy dm_get_safe_policy[__DM_GET_SAFE_MAX] = {
+static const struct blobmsg_policy dm_get_safe_policy[] = {
 	[DM_GET_SAFE_PATHS] = { .name = "paths", .type = BLOBMSG_TYPE_ARRAY },
 	[DM_GET_SAFE_PROTO] = { .name = "proto", .type = BLOBMSG_TYPE_STRING },
 	[DM_GET_SAFE_NXT_LVL] = { .name = "next-level", .type = BLOBMSG_TYPE_INT8 },
 };
 
-static const struct blobmsg_policy dm_sets_policy[__DM_SETS_MAX] = {
+static const struct blobmsg_policy dm_get_policy[] = {
+	[DM_GET_PATH] = { .name = "path", .type = BLOBMSG_TYPE_STRING },
+	[DM_GET_PROTO] = { .name = "proto", .type = BLOBMSG_TYPE_STRING },
+	[DM_GET_MAXDEPTH] = { .name = "maxdepth", .type = BLOBMSG_TYPE_INT32 },
+	[DM_GET_NXT_LVL] = { .name = "next-level", .type = BLOBMSG_TYPE_INT8 },
+};
+
+static const struct blobmsg_policy dm_sets_policy[] = {
 	[DM_SETS_PATHS] = { .name = "paths", .type = BLOBMSG_TYPE_ARRAY },
 	[DM_SETS_PROTO] = { .name = "proto", .type = BLOBMSG_TYPE_STRING },
 };
 
-static const struct blobmsg_policy dm_sets_attrib_policy[__DM_SETS_A_NOTIF_MAX] = {
+static const struct blobmsg_policy dm_sets_attrib_policy[] = {
 	[DM_SETS_A_NOTIF_PATH] = { .name = "path", .type = BLOBMSG_TYPE_STRING },
 	[DM_SETS_A_NOTIF_VALUE] = { .name = "notify-type", .type = BLOBMSG_TYPE_STRING },
 	[DM_SETS_A_NOTIF_CHANGE] = { .name = "notify", .type = BLOBMSG_TYPE_STRING },
 };
 
-static const struct blobmsg_policy dm_add_policy[__DM_ADD_MAX] = {
+static const struct blobmsg_policy dm_add_policy[] = {
 	[DM_ADD_PATH] = { .name = "path", .type = BLOBMSG_TYPE_STRING },
 	[DM_ADD_PROTO] = { .name = "proto", .type = BLOBMSG_TYPE_STRING },
 	[DM_ADD_PARAMETER_KEY] = { .name = "key", .type = BLOBMSG_TYPE_STRING }
 };
 
-static const struct blobmsg_policy dm_set_policy[__DM_SET_MAX] = {
+static const struct blobmsg_policy dm_set_policy[] = {
 	[DM_SET_PATH] = { .name = "path", .type = BLOBMSG_TYPE_STRING },
 	[DM_SET_VALUE] = { .name = "value", .type = BLOBMSG_TYPE_STRING },
 	[DM_SET_VALUE_TABLE] = { .name = "values", .type = BLOBMSG_TYPE_TABLE },
@@ -136,32 +135,7 @@ static const struct blobmsg_policy dm_set_policy[__DM_SET_MAX] = {
 	[DM_SET_PARAMETER_KEY] = { .name = "key", .type = BLOBMSG_TYPE_STRING }
 };
 
-static bool is_sanitized(char *param)
-{
-	size_t len;
-
-	if (param==NULL)
-		return false;
-
-	len = strlen(param);
-	if (param[0] == '\0' || param[0] == ' ')
-		return false;
-
-	// Check the minimum len in path
-	if (len < MIN_LEN)
-		return false;
-
-	// Fail if path does not start from Device.
-	if (strncmp(param, ROOT_NODE, MIN_LEN))
-		return false;
-
-	if (param[len-1]==' ')
-		return false;
-
-	return true;
-}
-
-static void set_bbf_data_type(struct blob_attr *proto)
+static int get_bbf_proto_type(struct blob_attr *proto)
 {
 	int type;
 
@@ -178,26 +152,123 @@ static void set_bbf_data_type(struct blob_attr *proto)
 		type = BBFDM_BOTH;
 	}
 
-	set_bbfdatamodel_type(type);
+	return type;
 }
 
-static int get_safe(struct ubus_context *ctx,
-			struct ubus_object *obj,
-			struct ubus_request_data *req,
-			struct blob_attr *msg,
-			int bbf_cmd)
+static bool get_schema_path(char *qpath, char *spath)
+{
+	size_t qlen, i, j;
+	bool found;
+
+	if (qpath == NULL || spath == NULL)
+		return false;
+
+	j = 0;
+	spath[0] = '\0';
+	qlen = strlen(qpath);
+	for (i = 0; i < qlen; i++) {
+		switch (qpath[i]) {
+		case '+':
+		case '#':
+			i = qlen;
+			break;
+		case '*':
+			if (i == (qlen - 1))
+				return false;
+
+			if (qpath[i - 1] != '.' && qpath[i + 1] != '.')
+				return false;
+
+			spath[j++] = '{';
+			spath[j++] = 'i';
+			spath[j++] = '}';
+			break;
+		case '[':
+			found = false;
+			while (i < qlen) {
+				if (qpath[i] == ']') {
+					spath[j++] = '{';
+					spath[j++] = 'i';
+					spath[j++] = '}';
+					found = true;
+					break;
+				}
+				i++;
+			}
+			if (found == false)
+				return false;
+
+			break;
+		case '0' ... '9':
+			if (qpath[i - 1] == '.') {
+				while (i < qlen) {
+					if (qpath[i + 1] < '0' || qpath[i + 1] > '9')
+						break;
+					i++;
+				}
+				if (qpath[i + 1] != '.')
+					return false;
+
+				spath[j++] = '{';
+				spath[j++] = 'i';
+				spath[j++] = '}';
+			} else {
+				spath[j++] = qpath[i];
+			}
+			break;
+		default:
+			spath[j++] = qpath[i];
+		}
+	}
+	spath[j] = '\0';
+
+	return true;
+}
+
+static bool path_present_in_schema(char *param)
+{
+	char spath[MAX_DM_PATH] = {'\0'};
+	bool found = false;
+
+	if (param == NULL)
+		return false;
+
+	// Check if path starts from Device.
+	if (strncmp(param, ROOT_NODE, 7) != 0)
+		return false;
+
+	DEBUG("qpath(%s)", param);
+	if (get_schema_path(param, spath) == false) {
+		WARNING("path(%s) syntax is wrong", param);
+		return false;
+	}
+
+	found = path_present_in_pvlist(&g_schema_pv_list, spath);
+
+	if (found == false)
+		INFO("path doesn't exists in schema(%s)", spath);
+
+	return found;
+}
+
+int get_safe(struct ubus_context *ctx,
+		    struct ubus_object *obj,
+		    struct ubus_request_data *req,
+		    struct blob_attr *msg,
+		    int bbf_cmd)
 {
-	struct blob_buf bb = {};
 	struct blob_attr *tb[__DM_GET_SAFE_MAX];
 	struct blob_attr *paths;
 	struct blob_attr *path;
-	void *a;
-	char *nxt_lvl;
+	char *nxt_lvl = NULL;
 	size_t rem;
-	const int raw = is_str_eq(obj->name, RAWUSP);
+	struct ubus_request_data *req_new = NULL;
+	struct safe_thread_data *tdata = NULL;
+	pthread_t tid;
+	struct list_head *paths_list;
 
 	blobmsg_parse(dm_get_safe_policy, __DM_GET_SAFE_MAX,
-			tb, blob_data(msg), blob_len(msg));
+		      tb, blob_data(msg), blob_len(msg));
 
 	paths = tb[DM_GET_SAFE_PATHS];
 	if (paths == NULL)
@@ -208,36 +279,46 @@ static int get_safe(struct ubus_context *ctx,
 			nxt_lvl = "1";
 		else
 			nxt_lvl = "0";
-	} else {
-		nxt_lvl = NULL;
 	}
 
-	set_bbf_data_type(tb[DM_GET_SAFE_PROTO]);
 
-	memset(&bb, 0, sizeof(struct blob_buf));
-	blob_buf_init(&bb, 0);
-
-	if (raw)
-		a = blobmsg_open_array(&bb, "parameters");
+	paths_list = malloc(sizeof(*paths_list));
+	INIT_LIST_HEAD(paths_list);
 
 	blobmsg_for_each_attr(path, paths, rem) {
 		char *path_str = blobmsg_get_string(path);
 
-		if (raw)
-			bbf_get_raw(bbf_cmd, path_str, &bb, nxt_lvl);
-		else
-			bbf_get_blob(bbf_cmd, path_str, &bb, nxt_lvl);
+		add_path_node(path_str, paths_list);
 	}
 
-	if (raw)
-		blobmsg_close_array(&bb, a);
 
-	ubus_send_reply(ctx, req, bb.head);
-	blob_buf_free(&bb);
+	tdata = malloc(sizeof(*tdata));
+	req_new = malloc(sizeof(*req_new));
+	if (tdata && req_new) {
+		ubus_defer_request(ctx, req, req_new);
+
+		tdata->ctx = ctx;
+		tdata->req = req_new;
+		tdata->proto = get_bbf_proto_type(tb[DM_GET_SAFE_PROTO]);
+		tdata->raw = is_str_eq(obj->name, USPRAW);
+		tdata->next_level = (nxt_lvl) ? strdup(nxt_lvl) : NULL;
+		tdata->plist = paths_list;
+		tdata->cmd = bbf_cmd;
+
+		pthread_create(&tid, NULL, get_safe_thread, (void *)tdata);
+		pthread_detach(tid);
+	} else {
+		free(tdata);
+		free(req_new);
+		free_path_list(paths_list);
+		free(paths_list);
+		return UBUS_STATUS_UNKNOWN_ERROR;
+	}
+
 	return 0;
 }
 
-static int usp_get_attributes(struct ubus_context *ctx,
+int usp_get_attributes(struct ubus_context *ctx,
 			struct ubus_object *obj,
 			struct ubus_request_data *req,
 			__unused const char *method,
@@ -246,7 +327,7 @@ static int usp_get_attributes(struct ubus_context *ctx,
 	return get_safe(ctx, obj, req, msg, CMD_GET_NOTIFICATION);
 }
 
-static int usp_get_safe_values(struct ubus_context *ctx,
+int usp_get_safe_values(struct ubus_context *ctx,
 			struct ubus_object *obj,
 			struct ubus_request_data *req,
 			__unused const char *method,
@@ -255,7 +336,7 @@ static int usp_get_safe_values(struct ubus_context *ctx,
 	return get_safe(ctx, obj, req, msg, CMD_GET_VALUE);
 }
 
-static int usp_get_safe_names(struct ubus_context *ctx,
+int usp_get_safe_names(struct ubus_context *ctx,
 			struct ubus_object *obj,
 			struct ubus_request_data *req,
 			__unused const char *method,
@@ -264,7 +345,7 @@ static int usp_get_safe_names(struct ubus_context *ctx,
 	return get_safe(ctx, obj, req, msg, CMD_GET_NAME);
 }
 
-static int usp_set_safe_attributes(struct ubus_context *ctx,
+int usp_set_safe_attributes(struct ubus_context *ctx,
 			__unused struct ubus_object *obj,
 			struct ubus_request_data *req,
 			__unused const char *method,
@@ -276,15 +357,16 @@ static int usp_set_safe_attributes(struct ubus_context *ctx,
 	struct blob_attr *cur;
 	void *a;
 	size_t rem;
+	int proto;
 
 	blobmsg_parse(dm_sets_policy, __DM_SETS_MAX,
-			tb, blob_data(msg), blob_len(msg));
+		      tb, blob_data(msg), blob_len(msg));
 
 	paths = tb[DM_SETS_PATHS];
 	if (paths == NULL)
 		return UBUS_STATUS_INVALID_ARGUMENT;
 
-	set_bbf_data_type(tb[DM_SETS_PROTO]);
+	proto = get_bbf_proto_type(tb[DM_SETS_PROTO]);
 
 	blob_buf_init(&bb, 0);
 	a = blobmsg_open_array(&bb, "parameters");
@@ -294,7 +376,7 @@ static int usp_set_safe_attributes(struct ubus_context *ctx,
 		char *path, *value, *notif_change;
 
 		blobmsg_parse(dm_sets_attrib_policy, __DM_SETS_A_NOTIF_MAX,
-				tb_n, blobmsg_data(cur), blobmsg_len(cur));
+			      tb_n, blobmsg_data(cur), blobmsg_len(cur));
 
 		path = NULL;
 		value = NULL;
@@ -312,7 +394,7 @@ static int usp_set_safe_attributes(struct ubus_context *ctx,
 		if (path == NULL || value == NULL)
 			continue;
 
-		bbf_set_notification(&bb, path, value, notif_change);
+		bbf_set_notification(&bb, path, value, notif_change, proto);
 	}
 
 	blobmsg_close_array(&bb, a);
@@ -323,8 +405,8 @@ static int usp_set_safe_attributes(struct ubus_context *ctx,
 
 
 int usp_add_del_handler(struct ubus_context *ctx, struct ubus_object *obj,
-		struct ubus_request_data *req, const char *method,
-		struct blob_attr *msg)
+			struct ubus_request_data *req, const char *method,
+			struct blob_attr *msg)
 {
 	struct blob_attr *tb[__DM_ADD_MAX];
 	char path[PATH_MAX];
@@ -332,9 +414,10 @@ int usp_add_del_handler(struct ubus_context *ctx, struct ubus_object *obj,
 	struct blob_buf bb = {};
 	size_t path_len;
 	char *blob_msg = NULL;
+	int proto;
 
 
-	if(blobmsg_parse(dm_add_policy, __DM_ADD_MAX, tb, blob_data(msg), blob_len(msg))) {
+	if (blobmsg_parse(dm_add_policy, __DM_ADD_MAX, tb, blob_data(msg), blob_len(msg))) {
 		ERR("Failed to parse blob");
 		return UBUS_STATUS_UNKNOWN_ERROR;
 	}
@@ -342,12 +425,12 @@ int usp_add_del_handler(struct ubus_context *ctx, struct ubus_object *obj,
 	if (!(tb[DM_ADD_PATH]))
 		return UBUS_STATUS_INVALID_ARGUMENT;
 
-	set_bbf_data_type(tb[DM_ADD_PROTO]);
+	proto = get_bbf_proto_type(tb[DM_ADD_PROTO]);
 
 	// In case of granular objects, Concatenate relative path to ubus object
-	if ((0 != strcmp(obj->name, USP)) && (0 != strcmp(obj->name, RAWUSP))) {
-		snprintf(path, NAME_MAX, "%s.%s", obj->name+strlen(USP_GRA), \
-			(char *)blobmsg_data(tb[DM_ADD_PATH]));
+	if (strncmp(obj->name, USPEXT, strlen(USPEXT)) == 0) {
+		snprintf(path, PATH_MAX, "%s%s", obj->name + USP_EXT_LEN,
+			 (char *)blobmsg_data(tb[DM_ADD_PATH]));
 	} else {
 		blob_msg = blobmsg_data(tb[DM_ADD_PATH]);
 		strncpyt(path, blob_msg, sizeof(path));
@@ -356,11 +439,11 @@ int usp_add_del_handler(struct ubus_context *ctx, struct ubus_object *obj,
 	path_len = strlen(path);
 	// Path is invalid if the path have leave elements
 	// Need to add . as obuspa trims last . from path
-	if(path[path_len-1] != DELIM) {
+	if (path[path_len-1] != DELIM)
 		strcat(path, ".");
-	}
 
-	if (!is_sanitized(path)) {
+	INFO("ubus method|%s|, name|%s|, path(%s)", method, obj->name, path);
+	if (!path_present_in_schema(path)) {
 		ERR("Invalid path |%s|", path);
 		return UBUS_STATUS_INVALID_ARGUMENT;
 	}
@@ -371,15 +454,12 @@ int usp_add_del_handler(struct ubus_context *ctx, struct ubus_object *obj,
 	memset(&bb, 0, sizeof(struct blob_buf));
 	blob_buf_init(&bb, 0);
 
-	INFO("ubus method|%s| name|%s|, path(%s)", method, obj->name, path);
-
-	if (is_str_eq(method, "add_object")) {
-		add_object(&bb, path, pkey);
-	} else if (is_str_eq(method, "del_object")) {
-		create_del_response(&bb, path, pkey);
-	} else {
+	if (is_str_eq(method, "add_object"))
+		create_add_response(&bb, path, pkey, proto);
+	else if (is_str_eq(method, "del_object"))
+		create_del_response(&bb, path, pkey, proto);
+	else
 		ERR("method(%s) not defined", method);
-	}
 
 	ubus_send_reply(ctx, req, bb.head);
 	blob_buf_free(&bb);
@@ -388,17 +468,21 @@ int usp_add_del_handler(struct ubus_context *ctx, struct ubus_object *obj,
 }
 
 int usp_get_handler(struct ubus_context *ctx, struct ubus_object *obj,
-		struct ubus_request_data *req, const char *method,
-		struct blob_attr *msg)
+		    struct ubus_request_data *req, const char *method __unused,
+		    struct blob_attr *msg)
 {
 	struct blob_attr *tb[__DM_GET_MAX];
+	struct thread_data *tdata = NULL;
+	struct ubus_request_data *req_new = NULL;
+	const bool raw = is_str_eq(obj->name, USPRAW);
 	char path[PATH_MAX];
 	struct blob_buf bb = {};
-	char *blob_msg = NULL;
+	int fault = USP_ERR_OK;
 	uint8_t maxdepth = 0;
+	pthread_t tid;
+	char *nxt_lvl_str;
 
-
-	if(blobmsg_parse(dm_get_policy, __DM_GET_MAX, tb, blob_data(msg), blob_len(msg))) {
+	if (blobmsg_parse(dm_get_policy, __DM_GET_MAX, tb, blob_data(msg), blob_len(msg))) {
 		ERR("Failed to parse blob");
 		return UBUS_STATUS_UNKNOWN_ERROR;
 	}
@@ -406,74 +490,98 @@ int usp_get_handler(struct ubus_context *ctx, struct ubus_object *obj,
 	if (!(tb[DM_GET_PATH]))
 		return UBUS_STATUS_INVALID_ARGUMENT;
 
-	set_bbf_data_type(tb[DM_GET_PROTO]);
+	if (tb[DM_GET_MAXDEPTH])
+		maxdepth = blobmsg_get_u32(tb[DM_GET_MAXDEPTH]);
+
+	if (tb[DM_GET_NXT_LVL])
+		nxt_lvl_str = blobmsg_get_u8(tb[DM_GET_NXT_LVL]) ? "1" :  "0";
+	else
+		nxt_lvl_str = "0";
 
 	// In case of granular objects, Concatenate relative path to ubus object
-	if ((0 != strcmp(obj->name, USP)) && (0 != strcmp(obj->name, RAWUSP))) {
-		snprintf(path, NAME_MAX, "%s.%s", obj->name+strlen(USP_GRA), \
-			(char *)blobmsg_data(tb[DM_GET_PATH]));
+	if (strncmp(obj->name, USPEXT, strlen(USPEXT)) == 0) {
+		snprintf(path, PATH_MAX, "%s%s", obj->name + USP_EXT_LEN,
+			 (char *)blobmsg_data(tb[DM_ADD_PATH]));
 	} else {
-		blob_msg = blobmsg_data(tb[DM_GET_PATH]);
-		strncpyt(path, blob_msg, sizeof(path));
+		strncpyt(path, blobmsg_data(tb[DM_GET_PATH]), sizeof(path));
 	}
 
-	if (!is_sanitized(path)) {
-		ERR("Invalid path |%s|", path);
-		return UBUS_STATUS_INVALID_ARGUMENT;
-	}
-
-	INFO("ubus method|%s|, name|%s|, path(%s)", method, obj->name, path);
-
-	filter_results(path, 0, strlen(path));
-	update_valid_paths();
-
-	if (tb[DM_GET_MAXDEPTH])
-		maxdepth = blobmsg_get_u32(tb[DM_GET_MAXDEPTH]);
-
 	memset(&bb, 0, sizeof(struct blob_buf));
 	blob_buf_init(&bb, 0);
 
-	if (is_str_eq(method, "get")) {
-		if(is_str_eq(obj->name, RAWUSP)) {
-			create_raw_response(&bb);
+	INFO("ubus method|%s|, name|%s|, path(%s)", method, obj->name, path);
+	if (!path_present_in_schema(path)) {
+		ERR("Invalid path |%s|", path);
+		fill_err_code(&bb, USP_ERR_INVALID_PATH);
+		ubus_send_reply(ctx, req, bb.head);
+		blob_buf_free(&bb);
+		return 0;
+	}
+
+	tdata = malloc(sizeof(*tdata));
+	req_new = malloc(sizeof(*req_new));
+	if (tdata && req_new) {
+		ubus_defer_request(ctx, req, req_new);
+
+		tdata->ctx = ctx;
+		tdata->req = req_new;
+		tdata->qpath = strdup(path);
+		tdata->proto = get_bbf_proto_type(tb[DM_GET_PROTO]);
+		tdata->raw = raw;
+		tdata->depth = maxdepth;
+		strcpy(tdata->next_level, nxt_lvl_str);
+
+		if (is_str_eq(method, "get")) {
+			fault = pthread_create(&tid, NULL, usp_get_thread, (void *)tdata);
+			pthread_detach(tid);
+		} else if (is_str_eq(method, "object_names")) {
+			fault = pthread_create(&tid, NULL, usp_get_name_thread, (void *)tdata);
+			pthread_detach(tid);
+		} else if (is_str_eq(method, "instances")) {
+			fault = pthread_create(&tid, NULL, usp_get_instance_thread, (void *)tdata);
+			pthread_detach(tid);
+		} else if (is_str_eq(method, "validate")) {
+			usp_validate_path(tdata);
 		} else {
-			create_response(&bb, path, maxdepth);
+			fault = USP_ERR_INTERNAL_ERROR;
+			ERR("method(%s) not defined", method);
+		}
+		if (fault) {
+			fill_err_code(&bb, USP_ERR_INTERNAL_ERROR);
+			ubus_send_reply(ctx, req, bb.head);
+			ubus_complete_deferred_request(ctx, req_new, 0);
+			free(tdata->qpath);
+			free(req_new);
+			free(tdata);
 		}
-	} else if (is_str_eq(method, "object_names")) {
-		bool nxt_lvl;
-
-		if (tb[DM_GET_NXT_LVL])
-			nxt_lvl = blobmsg_get_u8(tb[DM_GET_NXT_LVL]);
-		else
-			nxt_lvl = false;
 
-		create_name_response(&bb, nxt_lvl);
-	} else if (is_str_eq(method, "instances")) {
-		create_inst_name_response(&bb);
-	} else if (is_str_eq(method, "resolve")) {
-		get_resolved_path(&bb);
 	} else {
-		ERR("method(%s) not defined", method);
+		ERR("Out of memory!!");
+		fill_err_code(&bb, USP_ERR_RESOURCES_EXCEEDED);
+		ubus_send_reply(ctx, req, bb.head);
 	}
-
-	ubus_send_reply(ctx, req, bb.head);
 	blob_buf_free(&bb);
 
 	return 0;
 }
 
 int usp_set(struct ubus_context *ctx, struct ubus_object *obj,
-		struct ubus_request_data *req, const char *method,
-		struct blob_attr *msg)
+	    struct ubus_request_data *req, const char *method,
+	    struct blob_attr *msg)
 {
 	struct blob_buf bb = {};
 	struct blob_attr *tb[__DM_SET_MAX] = {NULL};
-	char path[PATH_MAX]={'\0'}, value[NAME_MAX]={'\0'};
+	char path[PATH_MAX] = {'\0'}, value[MAX_DM_VALUE] = {'\0'};
 	char *blob_msg = NULL;
-	void *array = NULL;
 	char *key = "";
-
-	if(blobmsg_parse(dm_set_policy, __DM_SET_MAX, tb, blob_data(msg), blob_len(msg))) {
+	size_t plen;
+	struct set_thread_data *tdata = NULL;
+	struct ubus_request_data *req_new = NULL;
+	pthread_t tid;
+	int fault = USP_ERR_OK;
+	struct list_head *pv_list;
+
+	if (blobmsg_parse(dm_set_policy, __DM_SET_MAX, tb, blob_data(msg), blob_len(msg))) {
 		ERR("Failed to parse blob");
 		return UBUS_STATUS_UNKNOWN_ERROR;
 	}
@@ -487,46 +595,97 @@ int usp_set(struct ubus_context *ctx, struct ubus_object *obj,
 	if (tb[DM_SET_PARAMETER_KEY])
 		key = blobmsg_get_string(tb[DM_SET_PARAMETER_KEY]);
 
-	set_bbf_data_type(tb[DM_SET_PROTO]);
-
 	memset(&bb, 0, sizeof(struct blob_buf));
 	blob_buf_init(&bb, 0);
 
 	// In case of granular objects, Concatenate relative path to ubus object
-	if ((0 != strcmp(obj->name, USP)) && (0 != strcmp(obj->name, RAWUSP))) {
-		snprintf(path, NAME_MAX, "%s.%s", obj->name+strlen(USP_GRA), \
-			 (char *)blobmsg_data(tb[DM_SET_PATH]));
+	if (strncmp(obj->name, USPEXT, strlen(USPEXT)) == 0) {
+		snprintf(path, PATH_MAX, "%s%s", obj->name + USP_EXT_LEN,
+			 (char *)blobmsg_data(tb[DM_ADD_PATH]));
 	} else {
 		blob_msg = blobmsg_data(tb[DM_SET_PATH]);
 		strncpyt(path, blob_msg, sizeof(path));
 	}
 
-	if (!is_sanitized(path)) {
+	if (!path_present_in_schema(path)) {
 		ERR("Invalid path |%s|", path);
-		return UBUS_STATUS_INVALID_ARGUMENT;
+		fault = USP_ERR_INVALID_PATH;
 	}
 
 	INFO("ubus method|%s|, name|%s|, path(%s)", method, obj->name, path);
-	filter_results(path, 0, strlen(path));
-	update_valid_paths();
 
-	array = blobmsg_open_array(&bb, "parameters");
+	pv_list = malloc(sizeof(*pv_list));
+	INIT_LIST_HEAD(pv_list);
 
 	if (tb[DM_SET_VALUE]) {
-		blob_msg = blobmsg_data(tb[DM_SET_VALUE]);
-		strncpyt(value, blob_msg, sizeof(value));
-		create_set_response(&bb, value, key);
+		char *tmp, tpath[MAX_DM_PATH] = {0};
+
+		plen = strlen(path);
+		if (path[plen - 1] == '.') {
+			fault = USP_ERR_INVALID_PATH;
+		} else {
+			tmp = strrchr(path, '.');
+			snprintf(tpath, plen - strlen(tmp) + 2, "%s", path);
+		}
+
+		if (fault == USP_ERR_OK) {
+			blob_msg = blobmsg_data(tb[DM_SET_VALUE]);
+			strncpyt(value, blob_msg, sizeof(value));
+			add_pv_node(&tmp[1], value, NULL, pv_list);
+			strcpy(path, tpath);
+		}
 	}
-	if(tb[DM_SET_VALUE_TABLE]) {
-		set_multiple_values(&bb, tb[DM_SET_VALUE_TABLE], key);
+
+	if (tb[DM_SET_VALUE_TABLE]) {
+		if (get_values_in_pvlist(tb[DM_SET_VALUE_TABLE], pv_list) == false)
+			fault = USP_ERR_INVALID_PATH;
+	}
+
+	if (fault) {
+		fill_err_code(&bb, fault);
+		ubus_send_reply(ctx, req, bb.head);
+		blob_buf_free(&bb);
+		free_pv_list(pv_list);
+		free(pv_list);
+		return 0;
+	}
+
+	tdata = malloc(sizeof(*tdata));
+	req_new = malloc(sizeof(*req_new));
+	if (tdata && req_new) {
+		ubus_defer_request(ctx, req, req_new);
+
+		tdata->ctx = ctx;
+		tdata->req = req_new;
+		tdata->qpath = strdup(path);
+		tdata->pv_list = pv_list;
+		tdata->key = strdup(key);
+		tdata->proto = get_bbf_proto_type(tb[DM_GET_PROTO]);
+
+		fault = pthread_create(&tid, NULL, usp_set_thread, (void *)tdata);
+		pthread_detach(tid);
+
+		if (fault) {
+			fill_err_code(&bb, USP_ERR_INTERNAL_ERROR);
+			ubus_send_reply(ctx, req, bb.head);
+			ubus_complete_deferred_request(ctx, req_new, 0);
+			free(tdata->qpath);
+			free_pv_list(pv_list);
+			free(req_new);
+			free(tdata->key);
+			free(tdata);
+			free(pv_list);
+		}
+	} else {
+		ERR("Out of memory!!");
+		free(tdata);
+		free(req_new);
+		fill_err_code(&bb, USP_ERR_RESOURCES_EXCEEDED);
+		ubus_send_reply(ctx, req, bb.head);
 	}
 
-	blobmsg_close_array(&bb, array);
-	ubus_send_reply(ctx, req, bb.head);
 	blob_buf_free(&bb);
 
-	// Restart all the affected services
-	dm_entry_restart_services();
 	return 0;
 }
 
@@ -543,11 +702,15 @@ int usp_operate(struct ubus_context *ctx, struct ubus_object *obj,
 {
 	struct blob_attr *tb[__DM_OPERATE_MAX] = {NULL};
 	struct blob_buf bb;
-	char path[PATH_MAX]={'\0'};
-	char cmd[NAME_MAX]={'\0'};
+	char path[MAX_DM_PATH] = {0};
+	char cmd[MAX_DM_KEY_LEN] = {0};
 	char *blob_msg = NULL;
+	struct operate_thread_data *tdata = NULL;
+	struct ubus_request_data *req_new = NULL;
+	int fault = USP_ERR_OK;
+	pthread_t tid;
 
-	if(blobmsg_parse(dm_operate_policy, __DM_OPERATE_MAX, tb, blob_data(msg), blob_len(msg))) {
+	if (blobmsg_parse(dm_operate_policy, __DM_OPERATE_MAX, tb, blob_data(msg), blob_len(msg))) {
 		ERR("Failed to parse blob");
 		return UBUS_STATUS_UNKNOWN_ERROR;
 	}
@@ -558,15 +721,13 @@ int usp_operate(struct ubus_context *ctx, struct ubus_object *obj,
 	if (!(tb[DM_OPERATE_ACTION]))
 		return UBUS_STATUS_INVALID_ARGUMENT;
 
-	set_bbf_data_type(tb[DM_OPERATE_PROTO]);
-
 	memset(&bb, 0, sizeof(struct blob_buf));
 	blob_buf_init(&bb, 0);
 
 	// In case of granular objects, Concatenate relative path to ubus object
-	if ((0 != strcmp(obj->name, USP)) && (0 != strcmp(obj->name, RAWUSP))) {
-		snprintf(path, NAME_MAX, "%s.%s", obj->name+strlen(USP_GRA), \
-			 (char *)blobmsg_data(tb[DM_OPERATE_PATH]));
+	if (strncmp(obj->name, USPEXT, strlen(USPEXT)) == 0) {
+		snprintf(path, MAX_DM_PATH, "%s%s", obj->name + USP_EXT_LEN,
+			 (char *)blobmsg_data(tb[DM_ADD_PATH]));
 	} else {
 		blob_msg = blobmsg_data(tb[DM_OPERATE_PATH]);
 		strncpyt(path, blob_msg, sizeof(path));
@@ -575,49 +736,96 @@ int usp_operate(struct ubus_context *ctx, struct ubus_object *obj,
 	strncpyt(cmd, blob_msg, sizeof(cmd));
 	INFO("ubus method|%s|, name|%s|, path(%s)", method, obj->name, path);
 
-	filter_results(path, 0, strlen(path));
-	update_valid_paths();
-
-	if(UBUS_INVALID_ARGUMENTS == create_operate_response(&bb, cmd, tb[DM_OPERATE_INPUT])) {
+	if (get_bbf_proto_type(tb[DM_GET_PROTO]) == BBFDM_CWMP) {
 		blob_buf_free(&bb);
-		return UBUS_STATUS_INVALID_ARGUMENT;
+		ERR("Operate commands not available for CWMP proto");
+		return UBUS_STATUS_UNKNOWN_ERROR;
+	}
+
+	tdata = malloc(sizeof(*tdata));
+	req_new = malloc(sizeof(*req_new));
+	if (tdata && req_new) {
+		ubus_defer_request(ctx, req, req_new);
+
+		tdata->ctx = ctx;
+		tdata->req = req_new;
+		tdata->qpath = strdup(path);
+		tdata->cmd = strdup(cmd);
+		tdata->proto = get_bbf_proto_type(tb[DM_GET_PROTO]);
+		tdata->raw = is_str_eq(obj->name, USPRAW);
+
+		if (tb[DM_OPERATE_INPUT])
+			tdata->input = blobmsg_format_json(tb[DM_OPERATE_INPUT], true);
+		else
+			tdata->input = NULL;
+
+		fault = pthread_create(&tid, NULL, usp_operate_thread, (void *)tdata);
+		pthread_detach(tid);
+
+		if (fault) {
+			fill_err_code(&bb, USP_ERR_INTERNAL_ERROR);
+			ubus_send_reply(ctx, req, bb.head);
+			ubus_complete_deferred_request(ctx, req_new, 0);
+			free(tdata->qpath);
+			free(req_new);
+			free(tdata->input);
+			free(tdata->cmd);
+			free(tdata);
+		}
+	} else {
+		ERR("Out of memory!!");
+		fill_err_code(&bb, USP_ERR_RESOURCES_EXCEEDED);
+		ubus_send_reply(ctx, req, bb.head);
 	}
 
-	ubus_send_reply(ctx, req, bb.head);
 	blob_buf_free(&bb);
 
 	return 0;
 }
 
-static int usp_list_schema(struct ubus_context *actx, struct ubus_object *obj,
+int usp_list_schema(struct ubus_context *actx, struct ubus_object *obj,
 			    struct ubus_request_data *req, const char *method,
 			    struct blob_attr *msg __attribute__ ((unused)))
 {
-	struct blob_buf b;
+	struct blob_buf bb;
+	void *array, *table;
+	struct pvNode *pv;
 
-	memset(&b, 0, sizeof(struct blob_buf));
-	blob_buf_init(&b, 0);
+	memset(&bb, 0, sizeof(struct blob_buf));
+	blob_buf_init(&bb, 0);
 
 	INFO("ubus method|%s|, name|%s|", method, obj->name);
 
-	set_bbfdatamodel_type(BBFDM_USP);
-	list_schema(&b);
+	array = blobmsg_open_array(&bb, "parameters");
+	list_for_each_entry(pv, &g_schema_pv_list, list) {
+		table = blobmsg_open_table(&bb, NULL);
+
+		blobmsg_add_string(&bb, "parameter", pv->param);
+		if (pv->val)
+			blobmsg_add_string(&bb, "writable", pv->val);
+		else
+			blobmsg_add_string(&bb, "writable", "0");
+
+		blobmsg_add_string(&bb, "type", pv->type);
 
-	ubus_send_reply(actx, req, b.head);
-	blob_buf_free(&b);
+		blobmsg_close_table(&bb, table);
+	}
+	blobmsg_close_array(&bb, array);
+
+	ubus_send_reply(actx, req, bb.head);
+	blob_buf_free(&bb);
 	return 0;
 }
 
-static int usp_list_operate(struct ubus_context *actx, struct ubus_object *obj,
+int usp_list_operate(struct ubus_context *actx, struct ubus_object *obj,
 			    struct ubus_request_data *req, const char *method,
-			    struct blob_attr *msg __attribute__ ((unused)))
+			    struct blob_attr *msg __unused)
 {
 	struct blob_buf bb;
 
 	memset(&bb, 0, sizeof(struct blob_buf));
 	blob_buf_init(&bb, 0);
 
-	set_bbfdatamodel_type(BBFDM_USP);
 	INFO("ubus method|%s|, name|%s|", method, obj->name);
 
 	list_operate_schema(&bb);
@@ -630,140 +838,138 @@ static int usp_list_operate(struct ubus_context *actx, struct ubus_object *obj,
 static struct ubus_method usp_methods[] = {
 	UBUS_METHOD_NOARG("dump_schema", usp_list_schema),
 	UBUS_METHOD_NOARG("list_operate", usp_list_operate),
-	UBUS_METHOD("get_safe_attributes", usp_get_attributes, dm_get_safe_policy),
-	UBUS_METHOD("get_safe_values", usp_get_safe_values, dm_get_safe_policy),
-	UBUS_METHOD("get_safe_names", usp_get_safe_names, dm_get_safe_policy),
-	UBUS_METHOD("set_safe_attributes", usp_set_safe_attributes, dm_sets_policy),
 	UBUS_METHOD("get", usp_get_handler, dm_get_policy),
+	UBUS_METHOD("object_names", usp_get_handler, dm_get_policy),
+	UBUS_METHOD("instances", usp_get_handler, dm_get_policy),
+	UBUS_METHOD("validate", usp_get_handler, dm_get_policy),
 	UBUS_METHOD("set", usp_set, dm_set_policy),
 	UBUS_METHOD("operate", usp_operate, dm_operate_policy),
 	UBUS_METHOD("add_object", usp_add_del_handler, dm_add_policy),
 	UBUS_METHOD("del_object", usp_add_del_handler, dm_add_policy),
-	UBUS_METHOD("object_names", usp_get_handler, dm_get_policy),
-	UBUS_METHOD("instances", usp_get_handler, dm_get_policy),
-	UBUS_METHOD("resolve", usp_get_handler, dm_get_policy),
+	UBUS_METHOD("get_safe_values", usp_get_safe_values, dm_get_safe_policy),
+	UBUS_METHOD("get_safe_attributes", usp_get_attributes, dm_get_safe_policy),
+	UBUS_METHOD("get_safe_names", usp_get_safe_names, dm_get_safe_policy),
+	UBUS_METHOD("set_safe_attributes", usp_set_safe_attributes, dm_sets_policy),
 };
 
 static struct ubus_object_type usp_type = UBUS_OBJECT_TYPE("usp", usp_methods);
 
-static struct ubus_object usp_object = {
-	.name = USP,
-	.type = &usp_type,
-	.methods = usp_methods,
-	.n_methods = ARRAY_SIZE(usp_methods),
-};
-
-static struct ubus_object usp_raw_object = {
-	.name = RAWUSP,
-	.type = &usp_type,
-	.methods = usp_methods,
-	.n_methods = ARRAY_SIZE(usp_methods),
-};
-
-static void ubus_add_granular_objects(struct ubus_context *ctx, char *obj)
+static int usp_add_ubus_object(struct ubus_context *ctx, char *obj_name)
 {
 	int retval;
-	char *obj_name = strdup(obj);
-	struct ubus_object *usp_granular_object = (struct ubus_object*)
-			malloc(sizeof(struct ubus_object));
+	struct ubus_object *obj;
+
+	retval = UBUS_STATUS_OK;
 
-	struct ubus_object granular_object = {
-		.name = obj_name,
-		.type = &usp_type,
-		.methods = usp_methods,
-		.n_methods = ARRAY_SIZE(usp_methods)};
+	obj = (struct ubus_object *) calloc(1, sizeof(*obj));
+	if (!obj) {
+		ERR("Out of memory!!");
+		return UBUS_STATUS_UNKNOWN_ERROR;
+	}
 
-	*usp_granular_object = granular_object;
+	obj->name = strdup(obj_name);
+	obj->type = &usp_type;
+	obj->methods = usp_methods;
+	obj->n_methods = ARRAY_SIZE(usp_methods);
 
-	retval = ubus_add_object(ctx, usp_granular_object);
-	if (retval)
+	retval = ubus_add_object(ctx, obj);
+	if (retval) {
+		free(obj);
 		ERR("Failed to add 'usp' ubus object: %s\n", ubus_strerror(retval));
+	}
 
+	return retval;
 }
 
-static void add_granular_objects(struct ubus_context *ctx, int gn_level)
+static int add_granular_objects(struct ubus_context *ctx, uint8_t gn_level)
 {
-	pathnode *p=head;
+	int fault;
+	char obj_path[PATH_MAX];
+	struct pathNode *pnode;
 
-	if (gn_level == 0) {
-		INFO("Granularity level is set to zero. No more 'usp' ubus objects to add");
-		return;
-	}
+	LIST_HEAD(path_list);
 
-	set_bbfdatamodel_type(BBFDM_BOTH);
+	get_granural_object_paths(&path_list, gn_level);
 
-	insert(strdup("Device."), true);
-	for (int i = 2; i <= gn_level; i++) {
-		p = head;
-		while(p!=NULL) {
-			get_granular_obj_list(p->ref_path);
-			p=p->next;
-		}
+	fault = UBUS_STATUS_OK;
+	list_for_each_entry(pnode, &path_list, list) {
+		sprintf(obj_path, "%s.%s", USP, pnode->path);
+		fault = usp_add_ubus_object(ctx, obj_path);
+
+		if (fault != UBUS_STATUS_OK)
+			break;
 	}
-	p = head;
-	while(p!=NULL) {
-		char obj_path[MAXNAMLEN]=USP_GRA;
-		strncat(obj_path,p->ref_path,sizeof(obj_path) - 1);
 
-		size_t len = strlen(obj_path);
-		if (obj_path[len-1] == DELIM)
-			obj_path[len-1]='\0';
+	free_path_list(&path_list);
 
-		DEBUG("ubus objects to register |%s|", obj_path);
-		ubus_add_granular_objects(ctx, obj_path);
-		p=p->next;
-	}
-	deleteList();
+	return fault;
 }
 
-static void usp_init(struct ubus_context *ctx)
+static int usp_init(struct ubus_context *ctx)
 {
 	int ret;
+	uint8_t log_level, gran_level;
+	char *temp = NULL;
 
-	char *log_level = NULL;
-	if (!(get_uci_option_string("uspd", "usp", "loglevel", &log_level))) {
-		INFO("loglevel get failed, defaults to|0x%x|", DEFAULT_LOG_LEVEL);
-		set_debug_level(DEFAULT_LOG_LEVEL);
-	} else {
-		set_debug_level(atoi(log_level));
-		free(log_level);
-	}
+	INFO("Registering ubus objects....");
 
-	ret = ubus_add_object(ctx, &usp_object);
-	if (ret) {
-		ERR("Failed to add 'usp' ubus object: %s\n", ubus_strerror(ret));
-		exit(ret);
+	get_uci_option_string("uspd", "usp", "loglevel", &temp);
+	if (temp) {
+		log_level = (uint8_t) atoi(temp);
+		set_debug_level(log_level);
+		free(temp);
 	}
 
-	ret = ubus_add_object(ctx, &usp_raw_object);
-	if (ret) {
-		ERR("Failed to add 'usp' ubus object: %s\n", ubus_strerror(ret));
-		exit(ret);
+	gran_level = 0;
+	get_uci_option_string("uspd", "usp", "granularitylevel", &temp);
+	if (temp) {
+		gran_level = (uint8_t) atoi(temp);
+		free(temp);
 	}
+	if (gran_level > MAX_GRANURALITY_DEPTH)
+		gran_level = MAX_GRANURALITY_DEPTH;
+
+	ret = usp_add_ubus_object(ctx, USP);
+	if (ret)
+		return ret;
+
+	ret = usp_add_ubus_object(ctx, USPRAW);
+	if (ret)
+		return ret;
 
 	// Get Granularity level of 'uspd' ubus objects
-	char *gran_level = NULL;
+	if (gran_level)
+		ret = add_granular_objects(ctx, gran_level);
 
-	if (!(get_uci_option_string("uspd", "usp", "granularitylevel",
-				   &gran_level))) {
-		INFO("Failed to fetch uci option 'granularitylevel'");
-	} else {
+	return ret;
+}
 
-		int gn_level = atoi(gran_level);
-		DEBUG("Granularity level is %d", gn_level);
-		if (gn_level < 0)
-			WARNING("Granularity Level should either be zero or a positive number");
-		else
-			add_granular_objects(ctx, gn_level);
+bool usp_pre_init(void)
+{
+	int ret;
 
-		free(gran_level);
-	}
+	if (helper_thread_init() == false)
+		return false;
+
+	ret = bbf_dm_get_schema(&g_schema_pv_list);
+	if (ret != 0)
+		return false;
+
+	return true;
 }
 
-int main()
+bool usp_cleanup(void)
+{
+	helper_thread_stop();
+	free_pv_list(&g_schema_pv_list);
+	return true;
+}
+
+int main(void)
 {
 	const char *ubus_socket = NULL;
 	struct ubus_context *ctx = NULL;
+	int ret = 0;
 
 	openlog("uspd", LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1);
 
@@ -773,13 +979,23 @@ int main()
 		fprintf(stderr, "Failed to connect to ubus\n");
 		return -1;
 	}
+
+	if (usp_pre_init() == false)
+		goto exit;
+
 	ubus_add_uloop(ctx);
-	usp_init(ctx);
+	ret = usp_init(ctx);
+	if (ret != UBUS_STATUS_OK) {
+		ret = UBUS_STATUS_UNKNOWN_ERROR;
+		goto exit;
+	}
 
 	uloop_run();
+exit:
 	ubus_free(ctx);
 	uloop_done();
+	usp_cleanup();
 	closelog();
 
-	return 0;
+	return ret;
 }