VOL-3121 - Separated ports from devices.

Similar to flows/groups/meters/logical ports.
Also added ListDevicePorts and GetDevicePort to the adapter API.
Also removed unused `// +build integration` tests.

Change-Id: I586adb9f46a249c9430d4205ef5db2d105dbbe06
diff --git a/db/model/proxy_test.go b/db/model/proxy_test.go
index a73a071..498eb45 100644
--- a/db/model/proxy_test.go
+++ b/db/model/proxy_test.go
@@ -28,7 +28,6 @@
 	"github.com/opencord/voltha-lib-go/v3/pkg/db"
 	"github.com/opencord/voltha-lib-go/v3/pkg/db/kvstore"
 	"github.com/opencord/voltha-lib-go/v3/pkg/log"
-	"github.com/opencord/voltha-protos/v3/go/common"
 	"github.com/opencord/voltha-protos/v3/go/openflow_13"
 	"github.com/opencord/voltha-protos/v3/go/voltha"
 	"github.com/stretchr/testify/assert"
@@ -44,10 +43,7 @@
 	TestProxyLogicalDeviceID       string
 	TestProxyTargetDeviceID        string
 	TestProxyTargetLogicalDeviceID string
-	TestProxyLogicalPorts          []*voltha.LogicalPort
-	TestProxyPorts                 []*voltha.Port
 	TestProxyStats                 *openflow_13.OfpFlowStats
-	TestProxyFlows                 *openflow_13.Flows
 	TestProxyDevice                *voltha.Device
 	TestProxyLogicalDevice         *voltha.LogicalDevice
 	TestProxyAdapter               *voltha.Adapter
@@ -72,46 +68,19 @@
 	TestProxyRootDevice = proxy.Proxy("device")
 	TestProxyRootAdapter = proxy.Proxy("adapters")
 
-	TestProxyLogicalPorts = []*voltha.LogicalPort{
-		{
-			Id:           "123",
-			DeviceId:     "logicalport-0-device-id",
-			DevicePortNo: 123,
-			RootPort:     false,
-		},
-	}
-	TestProxyPorts = []*voltha.Port{
-		{
-			PortNo:     123,
-			Label:      "test-port-0",
-			Type:       voltha.Port_PON_OLT,
-			AdminState: common.AdminState_ENABLED,
-			OperStatus: common.OperStatus_ACTIVE,
-			DeviceId:   "etcd_port-0-device-id",
-			Peers:      []*voltha.Port_PeerPort{},
-		},
-	}
-
 	TestProxyStats = &openflow_13.OfpFlowStats{
 		Id: 1111,
 	}
-	TestProxyFlows = &openflow_13.Flows{
-		Items: []*openflow_13.OfpFlowStats{TestProxyStats},
-	}
 	TestProxyDevice = &voltha.Device{
 		Id:         TestProxyDeviceID,
 		Type:       "simulated_olt",
 		Address:    &voltha.Device_HostAndPort{HostAndPort: "1.2.3.4:5555"},
 		AdminState: voltha.AdminState_PREPROVISIONED,
-		Flows:      TestProxyFlows,
-		Ports:      TestProxyPorts,
 	}
 
 	TestProxyLogicalDevice = &voltha.LogicalDevice{
 		Id:         TestProxyDeviceID,
 		DatapathId: 0,
-		Ports:      TestProxyLogicalPorts,
-		Flows:      TestProxyFlows,
 	}
 
 	TestProxyAdapter = &voltha.Adapter{
diff --git a/go.mod b/go.mod
index 5ceffaa..ee14fab 100644
--- a/go.mod
+++ b/go.mod
@@ -6,8 +6,8 @@
 	github.com/gogo/protobuf v1.3.0
 	github.com/golang/protobuf v1.3.2
 	github.com/google/uuid v1.1.1
-	github.com/opencord/voltha-lib-go/v3 v3.2.0
-	github.com/opencord/voltha-protos/v3 v3.3.9
+	github.com/opencord/voltha-lib-go/v3 v3.2.1
+	github.com/opencord/voltha-protos/v3 v3.4.1
 	github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2
 	github.com/stretchr/testify v1.4.0
 	google.golang.org/grpc v1.24.0
diff --git a/go.sum b/go.sum
index 4f22a44..9c0256a 100644
--- a/go.sum
+++ b/go.sum
@@ -198,10 +198,10 @@
 github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
 github.com/onsi/gomega v1.4.2 h1:3mYCb7aPxS/RU7TI1y4rkEn1oKmPRjNJLNEXgw7MH2I=
 github.com/onsi/gomega v1.4.2/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
-github.com/opencord/voltha-lib-go/v3 v3.2.0 h1:r7X7jZE5oJklv7GgqkuZWJMqjDZNT35X7VOMY1oyfus=
-github.com/opencord/voltha-lib-go/v3 v3.2.0/go.mod h1:sa508HZ5vlOauh0i+WC0XFX1JZnfHtJqNIms5XBT/Z0=
-github.com/opencord/voltha-protos/v3 v3.3.9 h1:BnfDN9oaRBgyAiH9ZN7LpBpEJYxjX/ZS7R4OT2hDrtY=
-github.com/opencord/voltha-protos/v3 v3.3.9/go.mod h1:nl1ETp5Iw3avxOaKD8BJlYY5wYI4KeV95aT1pL63nto=
+github.com/opencord/voltha-lib-go/v3 v3.2.1 h1:s6thA7jLGkrx6S3fzyCBYkXS4c0lIlPgmI0nYCme6NA=
+github.com/opencord/voltha-lib-go/v3 v3.2.1/go.mod h1:RPWJ4EY9Q758uwYAAb2WqZYDSI2M0FCQqjIHJxxDiHY=
+github.com/opencord/voltha-protos/v3 v3.4.1 h1:Nrr0jKy7WiMiFlXYiK8z73RvI4K4L5b/top7d3htQQI=
+github.com/opencord/voltha-protos/v3 v3.4.1/go.mod h1:nl1ETp5Iw3avxOaKD8BJlYY5wYI4KeV95aT1pL63nto=
 github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU=
 github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
 github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
diff --git a/rw_core/core/api/adapter_request_handler.go b/rw_core/core/api/adapter_request_handler.go
index d1e655e..79093a7 100644
--- a/rw_core/core/api/adapter_request_handler.go
+++ b/rw_core/core/api/adapter_request_handler.go
@@ -19,6 +19,7 @@
 import (
 	"context"
 	"errors"
+
 	"github.com/golang/protobuf/ptypes"
 	"github.com/golang/protobuf/ptypes/empty"
 	"github.com/opencord/voltha-go/rw_core/core/adapter"
@@ -455,6 +456,7 @@
 		return nil, err
 	}
 	deviceID := &voltha.ID{}
+	portTypeFilter := &ic.IntType{}
 	operStatus := &ic.IntType{}
 	transactionID := &ic.StrType{}
 	for _, arg := range args {
@@ -464,6 +466,11 @@
 				logger.Warnw(ctx, "cannot-unmarshal-device-id", log.Fields{"error": err})
 				return nil, err
 			}
+		case "port_type_filter":
+			if err := ptypes.UnmarshalAny(arg.Value, portTypeFilter); err != nil {
+				logger.Warnw(ctx, "cannot-unmarshal-device-id", log.Fields{"error": err})
+				return nil, err
+			}
 		case "oper_status":
 			if err := ptypes.UnmarshalAny(arg.Value, operStatus); err != nil {
 				logger.Warnw(ctx, "cannot-unmarshal-operStatus", log.Fields{"error": err})
@@ -478,7 +485,7 @@
 	}
 	logger.Debugw(ctx, "PortsStateUpdate", log.Fields{"deviceID": deviceID.Id, "operStatus": operStatus, "transactionID": transactionID.Val})
 
-	if err := rhp.deviceMgr.UpdatePortsState(context.TODO(), deviceID.Id, voltha.OperStatus_Types(operStatus.Val)); err != nil {
+	if err := rhp.deviceMgr.UpdatePortsState(context.TODO(), deviceID.Id, uint32(portTypeFilter.Val), voltha.OperStatus_Types(operStatus.Val)); err != nil {
 		logger.Debugw(ctx, "unable-to-update-ports-state", log.Fields{"error": err})
 		return nil, err
 	}
@@ -572,6 +579,68 @@
 	return &empty.Empty{}, nil
 }
 
+// GetDevicePort returns a single port
+func (rhp *AdapterRequestHandlerProxy) GetDevicePort(ctx context.Context, args []*ic.Argument) (*voltha.Port, error) {
+	if len(args) < 3 {
+		logger.Warn(ctx, "invalid-number-of-args", log.Fields{"args": args})
+		err := errors.New("invalid-number-of-args")
+		return nil, err
+	}
+	deviceID := &voltha.ID{}
+	portNo := &ic.IntType{}
+	transactionID := &ic.StrType{}
+	for _, arg := range args {
+		switch arg.Key {
+		case "device_id":
+			if err := ptypes.UnmarshalAny(arg.Value, deviceID); err != nil {
+				logger.Warnw(ctx, "cannot-unmarshal-device-id", log.Fields{"error": err})
+				return nil, err
+			}
+		case "port_no":
+			if err := ptypes.UnmarshalAny(arg.Value, portNo); err != nil {
+				logger.Warnw(ctx, "cannot-unmarshal-port-no", log.Fields{"error": err})
+				return nil, err
+			}
+		case kafka.TransactionKey:
+			if err := ptypes.UnmarshalAny(arg.Value, transactionID); err != nil {
+				logger.Warnw(ctx, "cannot-unmarshal-transaction-ID", log.Fields{"error": err})
+				return nil, err
+			}
+		}
+	}
+	logger.Debugw(ctx, "GetDevicePort", log.Fields{"deviceID": deviceID.Id, "portNo": portNo.Val, "transactionID": transactionID.Val})
+
+	return rhp.deviceMgr.GetDevicePort(context.TODO(), deviceID.Id, uint32(portNo.Val))
+}
+
+// ListDevicePorts returns all ports belonging to the device
+func (rhp *AdapterRequestHandlerProxy) ListDevicePorts(ctx context.Context, args []*ic.Argument) (*voltha.Ports, error) {
+	if len(args) < 2 {
+		logger.Warn(ctx, "invalid-number-of-args", log.Fields{"args": args})
+		err := errors.New("invalid-number-of-args")
+		return nil, err
+	}
+	deviceID := &voltha.ID{}
+	transactionID := &ic.StrType{}
+	for _, arg := range args {
+		switch arg.Key {
+		case "device_id":
+			if err := ptypes.UnmarshalAny(arg.Value, deviceID); err != nil {
+				logger.Warnw(ctx, "cannot-unmarshal-device-id", log.Fields{"error": err})
+				return nil, err
+			}
+		case kafka.TransactionKey:
+			if err := ptypes.UnmarshalAny(arg.Value, transactionID); err != nil {
+				logger.Warnw(ctx, "cannot-unmarshal-transaction-ID", log.Fields{"error": err})
+				return nil, err
+			}
+		}
+	}
+	logger.Debugw(ctx, "ListDevicePorts", log.Fields{"deviceID": deviceID.Id, "transactionID": transactionID.Val})
+
+	return rhp.deviceMgr.ListDevicePorts(context.TODO(), deviceID)
+}
+
 // ChildDevicesLost indicates that a parent device is in a state (Disabled) where it cannot manage the child devices.
 // This will trigger the Core to disable all the child devices.
 func (rhp *AdapterRequestHandlerProxy) ChildDevicesLost(ctx context.Context, args []*ic.Argument) (*empty.Empty, error) {
diff --git a/rw_core/core/api/common_test.go b/rw_core/core/api/common_test.go
index 6fcd511..92ba701 100644
--- a/rw_core/core/api/common_test.go
+++ b/rw_core/core/api/common_test.go
@@ -38,6 +38,7 @@
 type isLogicalDeviceConditionSatisfied func(ld *voltha.LogicalDevice) bool
 type isLogicalDevicePortsConditionSatisfied func(ports []*voltha.LogicalPort) bool
 type isDeviceConditionSatisfied func(ld *voltha.Device) bool
+type isDevicePortsConditionSatisfied func(ports *voltha.Ports) bool
 type isDevicesConditionSatisfied func(ds *voltha.Devices) bool
 type isLogicalDevicesConditionSatisfied func(lds *voltha.LogicalDevices) bool
 type isConditionSatisfied func() bool
@@ -88,6 +89,36 @@
 	}
 }
 
+func waitUntilDevicePortsReadiness(deviceID string,
+	timeout time.Duration,
+	verificationFunction isDevicePortsConditionSatisfied,
+	nbi *NBIHandler) error {
+	ch := make(chan int, 1)
+	done := false
+	go func() {
+		for {
+			ports, _ := nbi.ListDevicePorts(getContext(), &voltha.ID{Id: deviceID})
+			if verificationFunction(ports) {
+				ch <- 1
+				break
+			}
+			if done {
+				break
+			}
+			time.Sleep(retryInterval)
+		}
+	}()
+	timer := time.NewTimer(timeout)
+	defer timer.Stop()
+	select {
+	case <-ch:
+		return nil
+	case <-timer.C:
+		done = true
+		return fmt.Errorf("expected-states-not-reached-for-device%s", deviceID)
+	}
+}
+
 func waitUntilLogicalDeviceReadiness(oltDeviceID string,
 	timeout time.Duration,
 	nbi *NBIHandler,
diff --git a/rw_core/core/api/grpc_nbi_handler_test.go b/rw_core/core/api/grpc_nbi_handler_test.go
index 434df90..6b37a14 100755
--- a/rw_core/core/api/grpc_nbi_handler_test.go
+++ b/rw_core/core/api/grpc_nbi_handler_test.go
@@ -205,6 +205,8 @@
 			// Now, verify the details of the device.  First get the latest update
 			d, err := nbi.GetDevice(getContext(), &voltha.ID{Id: device.Id})
 			assert.Nil(t, err)
+			dPorts, err := nbi.ListDevicePorts(getContext(), &voltha.ID{Id: device.Id})
+			assert.Nil(t, err)
 			assert.Equal(t, voltha.AdminState_ENABLED, d.AdminState)
 			assert.Equal(t, voltha.ConnectStatus_REACHABLE, d.ConnectStatus)
 			assert.Equal(t, voltha.OperStatus_ACTIVE, d.OperStatus)
@@ -227,8 +229,8 @@
 			} else {
 				assert.Error(t, errors.New("invalid-device-type"))
 			}
-			assert.Equal(t, 2, len(d.Ports))
-			for _, p := range d.Ports {
+			assert.Equal(t, 2, len(dPorts.Items))
+			for _, p := range dPorts.Items {
 				assert.Equal(t, voltha.AdminState_ENABLED, p.AdminState)
 				assert.Equal(t, voltha.OperStatus_ACTIVE, p.OperStatus)
 				if p.Type == voltha.Port_ETHERNET_NNI || p.Type == voltha.Port_ETHERNET_UNI {
@@ -635,8 +637,10 @@
 	oltDevice, err := nb.getADevice(true, nbi)
 	assert.Nil(t, err)
 	assert.NotNil(t, oltDevice)
+	oltPorts, err := nbi.ListDevicePorts(getContext(), &voltha.ID{Id: oltDevice.Id})
+	assert.Nil(t, err)
 
-	for _, cp = range oltDevice.Ports {
+	for _, cp = range oltPorts.Items {
 		if cp.Type == voltha.Port_PON_OLT {
 			break
 		}
@@ -649,15 +653,15 @@
 	_, err = nbi.DisablePort(getContext(), cp)
 	assert.Nil(t, err)
 	// Wait for the olt device Port  to be disabled
-	var vdFunction isDeviceConditionSatisfied = func(device *voltha.Device) bool {
-		for _, port := range device.Ports {
+	var vdFunction isDevicePortsConditionSatisfied = func(ports *voltha.Ports) bool {
+		for _, port := range ports.Items {
 			if port.PortNo == cp.PortNo {
 				return port.AdminState == voltha.AdminState_DISABLED
 			}
 		}
 		return false
 	}
-	err = waitUntilDeviceReadiness(oltDevice.Id, nb.maxTimeout, vdFunction, nbi)
+	err = waitUntilDevicePortsReadiness(oltDevice.Id, nb.maxTimeout, vdFunction, nbi)
 	assert.Nil(t, err)
 	// Wait for the logical device to satisfy the expected condition
 	var vlFunction = func(ports []*voltha.LogicalPort) bool {
@@ -677,15 +681,15 @@
 	assert.Nil(t, err)
 
 	// Wait for the olt device Port to be enabled
-	vdFunction = func(device *voltha.Device) bool {
-		for _, port := range device.Ports {
+	vdFunction = func(ports *voltha.Ports) bool {
+		for _, port := range ports.Items {
 			if port.PortNo == cp.PortNo {
 				return port.AdminState == voltha.AdminState_ENABLED
 			}
 		}
 		return false
 	}
-	err = waitUntilDeviceReadiness(oltDevice.Id, nb.maxTimeout, vdFunction, nbi)
+	err = waitUntilDevicePortsReadiness(oltDevice.Id, nb.maxTimeout, vdFunction, nbi)
 	assert.Nil(t, err)
 	// Wait for the logical device to satisfy the expected condition
 	vlFunction = func(ports []*voltha.LogicalPort) bool {
@@ -701,7 +705,7 @@
 	assert.Nil(t, err)
 
 	// Disable a non-PON port
-	for _, cp = range oltDevice.Ports {
+	for _, cp = range oltPorts.Items {
 		if cp.Type != voltha.Port_PON_OLT {
 			break
 		}
diff --git a/rw_core/core/device/agent.go b/rw_core/core/device/agent.go
index 2b18296..9fbeb9d 100755
--- a/rw_core/core/device/agent.go
+++ b/rw_core/core/device/agent.go
@@ -29,6 +29,7 @@
 	"github.com/opencord/voltha-go/rw_core/core/adapter"
 	"github.com/opencord/voltha-go/rw_core/core/device/flow"
 	"github.com/opencord/voltha-go/rw_core/core/device/group"
+	"github.com/opencord/voltha-go/rw_core/core/device/port"
 	"github.com/opencord/voltha-go/rw_core/core/device/remote"
 	"github.com/opencord/voltha-lib-go/v3/pkg/kafka"
 
@@ -48,7 +49,7 @@
 	deviceID       string
 	parentID       string
 	deviceType     string
-	isRootdevice   bool
+	isRootDevice   bool
 	adapterProxy   *remote.AdapterProxy
 	adapterMgr     *adapter.Manager
 	deviceMgr      *Manager
@@ -63,32 +64,33 @@
 
 	flowLoader  *flow.Loader
 	groupLoader *group.Loader
+	portLoader  *port.Loader
 }
 
 //newAgent creates a new device agent. The device will be initialized when start() is called.
-func newAgent(ap *remote.AdapterProxy, device *voltha.Device, deviceMgr *Manager, dbProxy *model.Path, deviceProxy *model.Proxy, timeout time.Duration) *Agent {
-	var agent Agent
-	agent.adapterProxy = ap
-	if device.Id == "" {
-		agent.deviceID = coreutils.CreateDeviceID()
-	} else {
-		agent.deviceID = device.Id
+func newAgent(ap *remote.AdapterProxy, device *voltha.Device, deviceMgr *Manager, dbPath *model.Path, deviceProxy *model.Proxy, timeout time.Duration) *Agent {
+	deviceID := device.Id
+	if deviceID == "" {
+		deviceID = coreutils.CreateDeviceID()
 	}
 
-	agent.isRootdevice = device.Root
-	agent.parentID = device.ParentId
-	agent.deviceType = device.Type
-	agent.deviceMgr = deviceMgr
-	agent.adapterMgr = deviceMgr.adapterMgr
-	agent.exitChannel = make(chan int, 1)
-	agent.dbProxy = deviceProxy
-	agent.defaultTimeout = timeout
-	agent.device = proto.Clone(device).(*voltha.Device)
-	agent.requestQueue = coreutils.NewRequestQueue()
-	agent.flowLoader = flow.NewLoader(dbProxy.SubPath("flows").Proxy(device.Id))
-	agent.groupLoader = group.NewLoader(dbProxy.SubPath("groups").Proxy(device.Id))
-
-	return &agent
+	return &Agent{
+		deviceID:       deviceID,
+		adapterProxy:   ap,
+		isRootDevice:   device.Root,
+		parentID:       device.ParentId,
+		deviceType:     device.Type,
+		deviceMgr:      deviceMgr,
+		adapterMgr:     deviceMgr.adapterMgr,
+		exitChannel:    make(chan int, 1),
+		dbProxy:        deviceProxy,
+		defaultTimeout: timeout,
+		device:         proto.Clone(device).(*voltha.Device),
+		requestQueue:   coreutils.NewRequestQueue(),
+		flowLoader:     flow.NewLoader(dbPath.SubPath("flows").Proxy(deviceID)),
+		groupLoader:    group.NewLoader(dbPath.SubPath("groups").Proxy(deviceID)),
+		portLoader:     port.NewLoader(dbPath.SubPath("ports").Proxy(deviceID)),
+	}
 }
 
 // start() saves the device to the data model and registers for callbacks on that device if deviceToCreate!=nil.
@@ -124,6 +126,7 @@
 		// load the flows and groups from KV to cache
 		agent.flowLoader.Load(ctx)
 		agent.groupLoader.Load(ctx)
+		agent.portLoader.Load(ctx)
 
 		logger.Infow(ctx, "device-loaded-from-dB", log.Fields{"device-id": agent.deviceID})
 	} else {
@@ -134,8 +137,6 @@
 		device = (proto.Clone(deviceToCreate)).(*voltha.Device)
 		device.Id = agent.deviceID
 		device.AdminState = voltha.AdminState_PREPROVISIONED
-		device.FlowGroups = &ofp.FlowGroups{Items: nil}
-		device.Flows = &ofp.Flows{Items: nil}
 		if !deviceToCreate.GetRoot() && deviceToCreate.ProxyAddress != nil {
 			// Set the default vlan ID to the one specified by the parent adapter.  It can be
 			// overwritten by the child adapter during a device update request
@@ -202,6 +203,7 @@
 	agent.device = device
 	agent.flowLoader.Load(ctx)
 	agent.groupLoader.Load(ctx)
+	agent.portLoader.Load(ctx)
 	logger.Debugw(ctx, "reconciled-device-agent-devicetype", log.Fields{"device-id": agent.deviceID, "type": agent.deviceType})
 }
 
@@ -714,27 +716,26 @@
 }
 
 func (agent *Agent) ChildDeviceLost(ctx context.Context, device *voltha.Device) error {
-	if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
-		return err
-	}
-	defer agent.requestQueue.RequestComplete()
-
 	logger.Debugw(ctx, "childDeviceLost", log.Fields{"child-device-id": device.Id, "parent-device-ud": agent.deviceID})
 
-	//Remove the associated peer ports on the parent device
-	parentDevice := agent.getDeviceWithoutLock()
-	var updatedPeers []*voltha.Port_PeerPort
-	for _, port := range parentDevice.Ports {
-		updatedPeers = make([]*voltha.Port_PeerPort, 0)
-		for _, peerPort := range port.Peers {
-			if peerPort.DeviceId != device.Id {
-				updatedPeers = append(updatedPeers, peerPort)
+	// Remove the associated peer ports on the parent device
+	for portID := range agent.portLoader.ListIDs() {
+		if portHandle, have := agent.portLoader.Lock(portID); have {
+			oldPort := portHandle.GetReadOnly()
+			updatedPeers := make([]*voltha.Port_PeerPort, 0)
+			for _, peerPort := range oldPort.Peers {
+				if peerPort.DeviceId != device.Id {
+					updatedPeers = append(updatedPeers, peerPort)
+				}
 			}
+			newPort := *oldPort
+			newPort.Peers = updatedPeers
+			if err := portHandle.Update(ctx, &newPort); err != nil {
+				portHandle.Unlock()
+				return nil
+			}
+			portHandle.Unlock()
 		}
-		port.Peers = updatedPeers
-	}
-	if err := agent.updateDeviceInStoreWithoutLock(ctx, parentDevice, false, ""); err != nil {
-		return err
 	}
 
 	//send request to adapter
diff --git a/rw_core/core/device/agent_port.go b/rw_core/core/device/agent_port.go
index b3de89d..5ac7aca 100644
--- a/rw_core/core/device/agent_port.go
+++ b/rw_core/core/device/agent_port.go
@@ -21,198 +21,229 @@
 	"fmt"
 
 	"github.com/gogo/protobuf/proto"
+	"github.com/opencord/voltha-go/rw_core/core/device/port"
 	"github.com/opencord/voltha-lib-go/v3/pkg/log"
 	"github.com/opencord/voltha-protos/v3/go/voltha"
 	"google.golang.org/grpc/codes"
 	"google.golang.org/grpc/status"
 )
 
-// getPorts retrieves the ports information of the device based on the port type.
-func (agent *Agent) getPorts(ctx context.Context, portType voltha.Port_PortType) *voltha.Ports {
-	logger.Debugw(ctx, "getPorts", log.Fields{"device-id": agent.deviceID, "port-type": portType})
-	ports := &voltha.Ports{}
-	if device, _ := agent.deviceMgr.getDevice(ctx, agent.deviceID); device != nil {
-		for _, port := range device.Ports {
-			if port.Type == portType {
-				ports.Items = append(ports.Items, port)
-			}
+// listDevicePorts returns device ports
+func (agent *Agent) listDevicePorts() map[uint32]*voltha.Port {
+	portIDs := agent.portLoader.ListIDs()
+	ports := make(map[uint32]*voltha.Port, len(portIDs))
+	for portID := range portIDs {
+		if portHandle, have := agent.portLoader.Lock(portID); have {
+			ports[portID] = portHandle.GetReadOnly()
+			portHandle.Unlock()
 		}
 	}
 	return ports
 }
 
-func (agent *Agent) updatePortsOperState(ctx context.Context, operStatus voltha.OperStatus_Types) error {
+// getPorts retrieves the ports information of the device based on the port type.
+func (agent *Agent) getPorts(ctx context.Context, portType voltha.Port_PortType) *voltha.Ports {
+	logger.Debugw(ctx, "getPorts", log.Fields{"device-id": agent.deviceID, "port-type": portType})
+	ports := &voltha.Ports{}
+	for _, port := range agent.listDevicePorts() {
+		if port.Type == portType {
+			ports.Items = append(ports.Items, port)
+		}
+	}
+	return ports
+}
+
+func (agent *Agent) getDevicePort(portID uint32) (*voltha.Port, error) {
+	portHandle, have := agent.portLoader.Lock(portID)
+	if !have {
+		return nil, status.Errorf(codes.NotFound, "port-%d", portID)
+	}
+	defer portHandle.Unlock()
+	return portHandle.GetReadOnly(), nil
+}
+
+func (agent *Agent) updatePortsOperState(ctx context.Context, portTypeFilter uint32, operStatus voltha.OperStatus_Types) error {
 	logger.Debugw(ctx, "updatePortsOperState", log.Fields{"device-id": agent.deviceID})
-	if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
-		return err
+
+	for portID := range agent.portLoader.ListIDs() {
+		if portHandle, have := agent.portLoader.Lock(portID); have {
+			if oldPort := portHandle.GetReadOnly(); (1<<oldPort.Type)&portTypeFilter == 0 { // only update port types not included in the mask
+				// clone top-level port struct
+				newPort := *oldPort
+				newPort.OperStatus = operStatus
+				if err := portHandle.Update(ctx, &newPort); err != nil {
+					portHandle.Unlock()
+					return err
+				}
+
+				// Notify the logical device manager to change the port state
+				// Do this for NNI and UNIs only. PON ports are not known by logical device
+				if newPort.Type == voltha.Port_ETHERNET_NNI || newPort.Type == voltha.Port_ETHERNET_UNI {
+					go func(portID uint32, ctx context.Context) {
+						if err := agent.deviceMgr.logicalDeviceMgr.updatePortState(ctx, agent.deviceID, portID, operStatus); err != nil {
+							// TODO: VOL-2707
+							logger.Warnw(ctx, "unable-to-update-logical-port-state", log.Fields{"error": err})
+						}
+					}(portID, context.Background())
+				}
+			}
+			portHandle.Unlock()
+		}
 	}
-	defer agent.requestQueue.RequestComplete()
-	cloned := agent.getDeviceWithoutLock()
-	for _, port := range cloned.Ports {
-		port.OperStatus = operStatus
-	}
-	// Store the device
-	return agent.updateDeviceInStoreWithoutLock(ctx, cloned, false, "")
+	return nil
 }
 
 func (agent *Agent) updatePortState(ctx context.Context, portType voltha.Port_PortType, portNo uint32, operStatus voltha.OperStatus_Types) error {
-	if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
-		return err
-	}
-	defer agent.requestQueue.RequestComplete()
-	// Work only on latest data
-	// TODO: Get list of ports from device directly instead of the entire device
-	cloned := agent.getDeviceWithoutLock()
-
 	// Ensure the enums passed in are valid - they will be invalid if they are not set when this function is invoked
 	if _, ok := voltha.Port_PortType_value[portType.String()]; !ok {
 		return status.Errorf(codes.InvalidArgument, "%s", portType)
 	}
-	for _, port := range cloned.Ports {
-		if port.Type == portType && port.PortNo == portNo {
-			port.OperStatus = operStatus
-		}
+
+	portHandle, have := agent.portLoader.Lock(portNo)
+	if !have {
+		return nil
 	}
-	logger.Debugw(ctx, "portStatusUpdate", log.Fields{"deviceId": cloned.Id})
-	// Store the device
-	return agent.updateDeviceInStoreWithoutLock(ctx, cloned, false, "")
+	defer portHandle.Unlock()
+
+	port := portHandle.GetReadOnly()
+	if port.Type != portType {
+		return nil
+	}
+
+	newPort := *port // clone top-level port struct
+	newPort.OperStatus = operStatus
+	return portHandle.Update(ctx, &newPort)
 }
 
 func (agent *Agent) deleteAllPorts(ctx context.Context) error {
 	logger.Debugw(ctx, "deleteAllPorts", log.Fields{"deviceId": agent.deviceID})
-	if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
+
+	device, err := agent.getDevice(ctx)
+	if err != nil {
 		return err
 	}
-	defer agent.requestQueue.RequestComplete()
 
-	cloned := agent.getDeviceWithoutLock()
-
-	if cloned.AdminState != voltha.AdminState_DISABLED && cloned.AdminState != voltha.AdminState_DELETED {
-		err := status.Error(codes.FailedPrecondition, fmt.Sprintf("invalid-state-%v", cloned.AdminState))
-		logger.Warnw(ctx, "invalid-state-removing-ports", log.Fields{"state": cloned.AdminState, "error": err})
+	if device.AdminState != voltha.AdminState_DISABLED && device.AdminState != voltha.AdminState_DELETED {
+		err := status.Error(codes.FailedPrecondition, fmt.Sprintf("invalid-state-%v", device.AdminState))
+		logger.Warnw(ctx, "invalid-state-removing-ports", log.Fields{"state": device.AdminState, "error": err})
 		return err
 	}
-	if len(cloned.Ports) == 0 {
-		logger.Debugw(ctx, "no-ports-present", log.Fields{"deviceId": agent.deviceID})
-		return nil
-	}
 
-	cloned.Ports = []*voltha.Port{}
-	logger.Debugw(ctx, "portStatusUpdate", log.Fields{"deviceId": cloned.Id})
-	// Store the device
-	return agent.updateDeviceInStoreWithoutLock(ctx, cloned, false, "")
+	for portID := range agent.portLoader.ListIDs() {
+		if portHandle, have := agent.portLoader.Lock(portID); have {
+			if err := portHandle.Delete(ctx); err != nil {
+				portHandle.Unlock()
+				return err
+			}
+			portHandle.Unlock()
+		}
+	}
+	return nil
 }
 
 func (agent *Agent) addPort(ctx context.Context, port *voltha.Port) error {
-	if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
-		return err
-	}
-	defer agent.requestQueue.RequestComplete()
 	logger.Debugw(ctx, "addPort", log.Fields{"deviceId": agent.deviceID})
 
-	cloned := agent.getDeviceWithoutLock()
-	updatePort := false
-	if cloned.Ports == nil {
-		//	First port
-		logger.Debugw(ctx, "addPort-first-port-to-add", log.Fields{"deviceId": agent.deviceID})
-		cloned.Ports = make([]*voltha.Port, 0)
-	} else {
-		for _, p := range cloned.Ports {
-			if p.Type == port.Type && p.PortNo == port.PortNo {
-				if p.Label == "" && p.Type == voltha.Port_PON_OLT {
-					//Creation of OLT PON port is being processed after a default PON port was created.  Just update it.
-					logger.Infow(ctx, "update-pon-port-created-by-default", log.Fields{"default-port": p, "port-to-add": port})
-					p.Label = port.Label
-					p.OperStatus = port.OperStatus
-					updatePort = true
-					break
-				}
-				logger.Debugw(ctx, "port already exists", log.Fields{"port": port})
-				return nil
-			}
-		}
+	port.AdminState = voltha.AdminState_ENABLED
+
+	portHandle, created, err := agent.portLoader.LockOrCreate(ctx, port)
+	if err != nil {
+		return err
 	}
-	if !updatePort {
-		cp := proto.Clone(port).(*voltha.Port)
-		// Set the admin state of the port to ENABLE
-		cp.AdminState = voltha.AdminState_ENABLED
-		cloned.Ports = append(cloned.Ports, cp)
+	defer portHandle.Unlock()
+
+	if created {
+		return nil
 	}
-	// Store the device
-	return agent.updateDeviceInStoreWithoutLock(ctx, cloned, false, "")
+
+	oldPort := portHandle.GetReadOnly()
+	if oldPort.Label != "" || oldPort.Type != voltha.Port_PON_OLT {
+		logger.Debugw(ctx, "port already exists", log.Fields{"port": port})
+		return nil
+	}
+
+	// Creation of OLT PON port is being processed after a default PON port was created.  Just update it.
+	logger.Infow(ctx, "update-pon-port-created-by-default", log.Fields{"default-port": oldPort, "port-to-add": port})
+	newPort := *oldPort // clone top-level port struct
+	newPort.Label = port.Label
+	newPort.OperStatus = port.OperStatus
+
+	return portHandle.Update(ctx, &newPort)
 }
 
 func (agent *Agent) addPeerPort(ctx context.Context, peerPort *voltha.Port_PeerPort) error {
-	if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
-		return err
-	}
-	defer agent.requestQueue.RequestComplete()
 	logger.Debugw(ctx, "adding-peer-peerPort", log.Fields{"device-id": agent.deviceID, "peer-peerPort": peerPort})
 
-	cloned := agent.getDeviceWithoutLock()
-
-	// Get the peer port on the device based on the peerPort no
-	found := false
-	for _, port := range cloned.Ports {
-		if port.PortNo == peerPort.PortNo { // found peerPort
-			cp := proto.Clone(peerPort).(*voltha.Port_PeerPort)
-			port.Peers = append(port.Peers, cp)
-			logger.Debugw(ctx, "found-peer", log.Fields{"device-id": agent.deviceID, "portNo": peerPort.PortNo, "deviceId": agent.deviceID})
-			found = true
-			break
-		}
-	}
-	if !found && agent.isRootdevice {
-		// An ONU PON port has been created before the corresponding creation of the OLT PON port.  Create the OLT PON port
-		// with default values which will be updated once the OLT PON port creation is processed.
+	var portHandle *port.Handle
+	if agent.isRootDevice {
+		// If an ONU PON port needs to be referenced before the corresponding creation of the OLT PON port, then create the OLT PON port
+		// with default values, and update it later when the OLT PON port creation is processed.
 		ponPort := &voltha.Port{
 			PortNo:     peerPort.PortNo,
 			Type:       voltha.Port_PON_OLT,
 			AdminState: voltha.AdminState_ENABLED,
 			DeviceId:   agent.deviceID,
-			Peers:      []*voltha.Port_PeerPort{proto.Clone(peerPort).(*voltha.Port_PeerPort)},
+			Peers:      []*voltha.Port_PeerPort{peerPort},
 		}
-		cloned.Ports = append(cloned.Ports, ponPort)
-		logger.Infow(ctx, "adding-default-pon-port", log.Fields{"device-id": agent.deviceID, "peer": peerPort, "pon-port": ponPort})
+
+		h, created, err := agent.portLoader.LockOrCreate(ctx, ponPort)
+		if err != nil {
+			return err
+		}
+		defer h.Unlock()
+
+		if created {
+			logger.Infow(ctx, "added-default-pon-port", log.Fields{"device-id": agent.deviceID, "peer": peerPort, "pon-port": ponPort})
+			return nil
+		}
+
+		portHandle = h
+	} else {
+		h, have := agent.portLoader.Lock(peerPort.PortNo)
+		if !have {
+			return nil
+		}
+		defer h.Unlock()
+
+		portHandle = h
 	}
 
-	// Store the device
-	return agent.updateDeviceInStoreWithoutLock(ctx, cloned, false, "")
+	logger.Debugw(ctx, "found-peer", log.Fields{"device-id": agent.deviceID, "portNo": peerPort.PortNo, "deviceId": agent.deviceID})
+
+	newPort := proto.Clone(portHandle.GetReadOnly()).(*voltha.Port)
+	newPort.Peers = append(newPort.Peers, peerPort)
+
+	return portHandle.Update(ctx, newPort)
 }
 
-func (agent *Agent) disablePort(ctx context.Context, Port *voltha.Port) error {
-	if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
-		return err
-	}
-	defer agent.requestQueue.RequestComplete()
-	logger.Debugw(ctx, "disablePort", log.Fields{"device-id": agent.deviceID, "port-no": Port.PortNo})
-	var cp *voltha.Port
-	// Get the most up to date the device info
-	device := agent.getDeviceWithoutLock()
-	for _, port := range device.Ports {
-		if port.PortNo == Port.PortNo {
-			port.AdminState = voltha.AdminState_DISABLED
-			cp = proto.Clone(port).(*voltha.Port)
-			break
+func (agent *Agent) disablePort(ctx context.Context, portID uint32) error {
+	logger.Debugw(ctx, "disablePort", log.Fields{"device-id": agent.deviceID, "port-no": portID})
 
-		}
+	portHandle, have := agent.portLoader.Lock(portID)
+	if !have {
+		return status.Errorf(codes.InvalidArgument, "%v", portID)
 	}
-	if cp == nil {
-		return status.Errorf(codes.InvalidArgument, "%v", Port.PortNo)
+	defer portHandle.Unlock()
+
+	oldPort := portHandle.GetReadOnly()
+
+	if oldPort.Type != voltha.Port_PON_OLT {
+		return status.Errorf(codes.InvalidArgument, "Disabling of Port Type %v unimplemented", oldPort.Type)
 	}
 
-	if cp.Type != voltha.Port_PON_OLT {
-		return status.Errorf(codes.InvalidArgument, "Disabling of Port Type %v unimplemented", cp.Type)
-	}
-	// Store the device
-	if err := agent.updateDeviceInStoreWithoutLock(ctx, device, false, ""); err != nil {
-		logger.Debugw(ctx, "updateDeviceInStoreWithoutLock error ", log.Fields{"device-id": agent.deviceID, "port-no": Port.PortNo, "error": err})
+	newPort := *oldPort
+	newPort.AdminState = voltha.AdminState_DISABLED
+	if err := portHandle.Update(ctx, &newPort); err != nil {
 		return err
 	}
 
 	//send request to adapter
+	device, err := agent.getDevice(ctx)
+	if err != nil {
+		return err
+	}
 	subCtx, cancel := context.WithTimeout(context.Background(), agent.defaultTimeout)
-	ch, err := agent.adapterProxy.DisablePort(ctx, device, cp)
+	ch, err := agent.adapterProxy.DisablePort(ctx, device, &newPort)
 	if err != nil {
 		cancel()
 		return err
@@ -221,39 +252,34 @@
 	return nil
 }
 
-func (agent *Agent) enablePort(ctx context.Context, Port *voltha.Port) error {
-	if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
+func (agent *Agent) enablePort(ctx context.Context, portID uint32) error {
+	logger.Debugw(ctx, "enablePort", log.Fields{"device-id": agent.deviceID, "port-no": portID})
+
+	portHandle, have := agent.portLoader.Lock(portID)
+	if !have {
+		return status.Errorf(codes.InvalidArgument, "%v", portID)
+	}
+	defer portHandle.Unlock()
+
+	oldPort := portHandle.GetReadOnly()
+
+	if oldPort.Type != voltha.Port_PON_OLT {
+		return status.Errorf(codes.InvalidArgument, "Enabling of Port Type %v unimplemented", oldPort.Type)
+	}
+
+	newPort := *oldPort
+	newPort.AdminState = voltha.AdminState_ENABLED
+	if err := portHandle.Update(ctx, &newPort); err != nil {
 		return err
 	}
-	defer agent.requestQueue.RequestComplete()
-	logger.Debugw(ctx, "enablePort", log.Fields{"device-id": agent.deviceID, "port-no": Port.PortNo})
 
-	var cp *voltha.Port
-	// Get the most up to date the device info
-	device := agent.getDeviceWithoutLock()
-	for _, port := range device.Ports {
-		if port.PortNo == Port.PortNo {
-			port.AdminState = voltha.AdminState_ENABLED
-			cp = proto.Clone(port).(*voltha.Port)
-			break
-		}
-	}
-
-	if cp == nil {
-		return status.Errorf(codes.InvalidArgument, "%v", Port.PortNo)
-	}
-
-	if cp.Type != voltha.Port_PON_OLT {
-		return status.Errorf(codes.InvalidArgument, "Enabling of Port Type %v unimplemented", cp.Type)
-	}
-	// Store the device
-	if err := agent.updateDeviceInStoreWithoutLock(ctx, device, false, ""); err != nil {
-		logger.Debugw(ctx, "updateDeviceInStoreWithoutLock error ", log.Fields{"device-id": agent.deviceID, "port-no": Port.PortNo, "error": err})
-		return err
-	}
 	//send request to adapter
+	device, err := agent.getDevice(ctx)
+	if err != nil {
+		return err
+	}
 	subCtx, cancel := context.WithTimeout(context.Background(), agent.defaultTimeout)
-	ch, err := agent.adapterProxy.EnablePort(ctx, device, cp)
+	ch, err := agent.adapterProxy.EnablePort(ctx, device, &newPort)
 	if err != nil {
 		cancel()
 		return err
diff --git a/rw_core/core/device/agent_test.go b/rw_core/core/device/agent_test.go
index e9bd663..92977ac 100755
--- a/rw_core/core/device/agent_test.go
+++ b/rw_core/core/device/agent_test.go
@@ -60,6 +60,7 @@
 	defaultTimeout   time.Duration
 	maxTimeout       time.Duration
 	device           *voltha.Device
+	devicePorts      map[uint32]*voltha.Port
 	done             chan int
 }
 
@@ -101,12 +102,12 @@
 		Reason:        "All good",
 		ConnectStatus: voltha.ConnectStatus_UNKNOWN,
 		Custom:        nil,
-		Ports: []*voltha.Port{
-			{PortNo: 1, Label: "pon-1", Type: voltha.Port_PON_ONU, AdminState: voltha.AdminState_ENABLED,
-				OperStatus: voltha.OperStatus_ACTIVE, Peers: []*voltha.Port_PeerPort{{DeviceId: parentID, PortNo: 1}}},
-			{PortNo: 100, Label: "uni-100", Type: voltha.Port_ETHERNET_UNI, AdminState: voltha.AdminState_ENABLED,
-				OperStatus: voltha.OperStatus_ACTIVE},
-		},
+	}
+	test.devicePorts = map[uint32]*voltha.Port{
+		1: {PortNo: 1, Label: "pon-1", Type: voltha.Port_PON_ONU, AdminState: voltha.AdminState_ENABLED,
+			OperStatus: voltha.OperStatus_ACTIVE, Peers: []*voltha.Port_PeerPort{{DeviceId: parentID, PortNo: 1}}},
+		100: {PortNo: 100, Label: "uni-100", Type: voltha.Port_ETHERNET_UNI, AdminState: voltha.AdminState_ENABLED,
+			OperStatus: voltha.OperStatus_ACTIVE},
 	}
 	return test
 }
@@ -168,12 +169,17 @@
 	d, err := deviceAgent.start(context.TODO(), clonedDevice)
 	assert.Nil(t, err)
 	assert.NotNil(t, d)
+	for _, port := range dat.devicePorts {
+		err := deviceAgent.addPort(context.TODO(), port)
+		assert.Nil(t, err)
+	}
 	deviceMgr.addDeviceAgentToMap(deviceAgent)
 	return deviceAgent
 }
 
 func (dat *DATest) updateDeviceConcurrently(t *testing.T, da *Agent, globalWG *sync.WaitGroup) {
 	originalDevice, err := da.getDevice(context.Background())
+	originalDevicePorts := da.listDevicePorts()
 	assert.Nil(t, err)
 	assert.NotNil(t, originalDevice)
 	var localWG sync.WaitGroup
@@ -227,7 +233,6 @@
 	expectedChange := proto.Clone(originalDevice).(*voltha.Device)
 	expectedChange.OperStatus = voltha.OperStatus_ACTIVE
 	expectedChange.ConnectStatus = voltha.ConnectStatus_REACHABLE
-	expectedChange.Ports = append(expectedChange.Ports, portToAdd)
 	expectedChange.Root = root
 	expectedChange.Vendor = vendor
 	expectedChange.Model = model
@@ -237,8 +242,11 @@
 	expectedChange.Reason = reason
 
 	updatedDevice, _ := da.getDevice(context.Background())
+	updatedDevicePorts := da.listDevicePorts()
 	assert.NotNil(t, updatedDevice)
 	assert.True(t, proto.Equal(expectedChange, updatedDevice))
+	assert.Equal(t, len(originalDevicePorts)+1, len(updatedDevicePorts))
+	assert.True(t, proto.Equal(updatedDevicePorts[portToAdd.PortNo], portToAdd))
 
 	globalWG.Done()
 }
diff --git a/rw_core/core/device/flow/loader_test.go b/rw_core/core/device/flow/loader_test.go
index 8973f12..958124d 100644
--- a/rw_core/core/device/flow/loader_test.go
+++ b/rw_core/core/device/flow/loader_test.go
@@ -27,14 +27,14 @@
 
 // TestLoadersIdentical ensures that the group, flow, and meter loaders always have an identical implementation.
 func TestLoadersIdentical(t *testing.T) {
-	types := []string{"flow", "group", "meter", "logical_port"}
+	types := []string{"flow", "group", "meter", "port", "logical_port"}
 
 	identical := [][]string{
-		{`ofp\.OfpFlowStats`, `ofp\.OfpGroupEntry`, `ofp\.OfpMeterEntry`, `voltha\.LogicalPort`},
-		{`\.Id`, `\.Desc\.GroupId`, `\.Config\.MeterId`, `\.OfpPort\.PortNo`},
-		{`uint64`, `uint32`, `uint32`, `uint32`},
-		{`Flow`, `Group`, `Meter`, `Port`},
-		{`flow`, `group`, `meter`, `port|logical_port`},
+		{`ofp\.OfpFlowStats`, `ofp\.OfpGroupEntry`, `ofp\.OfpMeterEntry`, `voltha\.Port`, `voltha\.LogicalPort`},
+		{`\.Id`, `\.Desc\.GroupId`, `\.Config\.MeterId`, `\.PortNo`, `\.OfpPort\.PortNo`},
+		{`uint64`, `uint32`, `uint32`, `uint32`, `uint32`},
+		{`Flow`, `Group`, `Meter`, `Port`, `Port`},
+		{`flow`, `group`, `meter`, `port`, `port|logical_port`},
 	}
 
 	regexes := make([][]*regexp.Regexp, len(identical[0]))
diff --git a/rw_core/core/device/logical_agent.go b/rw_core/core/device/logical_agent.go
index 6a14e5a..07f85e8 100644
--- a/rw_core/core/device/logical_agent.go
+++ b/rw_core/core/device/logical_agent.go
@@ -66,13 +66,14 @@
 
 func newLogicalAgent(ctx context.Context, id string, sn string, deviceID string, ldeviceMgr *LogicalManager,
 	deviceMgr *Manager, dbProxy *model.Path, ldProxy *model.Proxy, defaultTimeout time.Duration) *LogicalAgent {
-	agent := &LogicalAgent{
+	return &LogicalAgent{
 		logicalDeviceID: id,
 		serialNumber:    sn,
 		rootDeviceID:    deviceID,
 		deviceMgr:       deviceMgr,
 		ldProxy:         ldProxy,
 		ldeviceMgr:      ldeviceMgr,
+		deviceRoutes:    route.NewDeviceRoutes(id, deviceID, deviceMgr.listDevicePorts),
 		flowDecomposer:  fd.NewFlowDecomposer(deviceMgr),
 		defaultTimeout:  defaultTimeout,
 		requestQueue:    coreutils.NewRequestQueue(),
@@ -82,8 +83,6 @@
 		meterLoader: meter.NewLoader(dbProxy.SubPath("logical_meters").Proxy(id)),
 		portLoader:  port.NewLoader(dbProxy.SubPath("logical_ports").Proxy(id)),
 	}
-	agent.deviceRoutes = route.NewDeviceRoutes(ctx, agent.logicalDeviceID, agent.deviceMgr.getDevice)
-	return agent
 }
 
 // start creates the logical device and add it to the data model
@@ -123,9 +122,6 @@
 		ld.Desc = (proto.Clone(switchCap.Desc)).(*ofp.OfpDesc)
 		logger.Debugw(ctx, "Switch-capability", log.Fields{"Desc": ld.Desc, "fromAd": switchCap.Desc})
 		ld.SwitchFeatures = (proto.Clone(switchCap.SwitchFeatures)).(*ofp.OfpSwitchFeatures)
-		ld.Flows = &ofp.Flows{Items: nil}
-		ld.FlowGroups = &ofp.FlowGroups{Items: nil}
-		ld.Ports = []*voltha.LogicalPort{}
 
 		// Save the logical device
 		if err := agent.ldProxy.Set(ctx, ld.Id, ld); err != nil {
@@ -160,6 +156,9 @@
 		// Update the last data
 		agent.logicalDevice = ld
 
+		// now that the root device is known, create DeviceRoutes with it
+		agent.deviceRoutes = route.NewDeviceRoutes(agent.logicalDeviceID, agent.rootDeviceID, agent.deviceMgr.listDevicePorts)
+
 		// load the flows, meters and groups from KV to cache
 		agent.flowLoader.Load(ctx)
 		agent.meterLoader.Load(ctx)
diff --git a/rw_core/core/device/logical_agent_port.go b/rw_core/core/device/logical_agent_port.go
index 0229c18..40f058e 100644
--- a/rw_core/core/device/logical_agent_port.go
+++ b/rw_core/core/device/logical_agent_port.go
@@ -44,15 +44,15 @@
 	return ret
 }
 
-func (agent *LogicalAgent) updateLogicalPort(ctx context.Context, device *voltha.Device, port *voltha.Port) error {
+func (agent *LogicalAgent) updateLogicalPort(ctx context.Context, device *voltha.Device, devicePorts map[uint32]*voltha.Port, port *voltha.Port) error {
 	logger.Debugw(ctx, "updateLogicalPort", log.Fields{"deviceId": device.Id, "port": port})
 	switch port.Type {
 	case voltha.Port_ETHERNET_NNI:
-		if err := agent.addNNILogicalPort(ctx, device, port); err != nil {
+		if err := agent.addNNILogicalPort(ctx, device.Id, devicePorts, port); err != nil {
 			return err
 		}
 	case voltha.Port_ETHERNET_UNI:
-		if err := agent.addUNILogicalPort(ctx, device, port); err != nil {
+		if err := agent.addUNILogicalPort(ctx, device.Id, device.AdminState, device.OperStatus, devicePorts, port); err != nil {
 			return err
 		}
 	case voltha.Port_PON_OLT:
@@ -60,16 +60,16 @@
 		go func() {
 			if err := agent.buildRoutes(context.Background()); err != nil {
 				// Not an error - temporary state
-				logger.Infow(ctx, "failed-to-update-routes-after-adding-parent-pon-port", log.Fields{"device-id": device.Id, "port": port, "ports-count": len(device.Ports), "error": err})
+				logger.Infow(ctx, "failed-to-update-routes-after-adding-parent-pon-port", log.Fields{"device-id": device.Id, "port": port, "ports-count": len(devicePorts), "error": err})
 			}
 		}()
 		//fallthrough
 	case voltha.Port_PON_ONU:
 		// Add the routes corresponding to that child device
 		go func() {
-			if err := agent.updateAllRoutes(context.Background(), device); err != nil {
+			if err := agent.updateAllRoutes(context.Background(), device.Id, devicePorts); err != nil {
 				// Not an error - temporary state
-				logger.Infow(ctx, "failed-to-update-routes-after-adding-child-pon-port", log.Fields{"device-id": device.Id, "port": port, "ports-count": len(device.Ports), "error": err})
+				logger.Infow(ctx, "failed-to-update-routes-after-adding-child-pon-port", log.Fields{"device-id": device.Id, "port": port, "ports-count": len(devicePorts), "error": err})
 			}
 		}()
 	default:
@@ -99,13 +99,21 @@
 	for _, child := range children.Items {
 		response := coreutils.NewResponse()
 		responses = append(responses, response)
-		go func(child *voltha.Device) {
-			if err = agent.setupUNILogicalPorts(context.Background(), child); err != nil {
+		go func(ctx context.Context, child *voltha.Device) {
+			defer response.Done()
+
+			childPorts, err := agent.deviceMgr.listDevicePorts(ctx, child.Id)
+			if err != nil {
+				logger.Error(ctx, "setting-up-UNI-ports-failed", log.Fields{"deviceID": child.Id})
+				response.Error(status.Errorf(codes.Internal, "UNI-ports-setup-failed: %s", child.Id))
+				return
+			}
+
+			if err = agent.setupUNILogicalPorts(ctx, child, childPorts); err != nil {
 				logger.Error(ctx, "setting-up-UNI-ports-failed", log.Fields{"deviceID": child.Id})
 				response.Error(status.Errorf(codes.Internal, "UNI-ports-setup-failed: %s", child.Id))
 			}
-			response.Done()
-		}(child)
+		}(context.Background(), child)
 	}
 	// Wait for completion
 	if res := coreutils.WaitForNilOrErrorResponses(agent.defaultTimeout, responses...); res != nil {
@@ -118,19 +126,18 @@
 func (agent *LogicalAgent) setupNNILogicalPorts(ctx context.Context, deviceID string) error {
 	logger.Infow(ctx, "setupNNILogicalPorts-start", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
 	// Build the logical device based on information retrieved from the device adapter
-	var err error
 
-	var device *voltha.Device
-	if device, err = agent.deviceMgr.getDevice(ctx, deviceID); err != nil {
-		logger.Errorw(ctx, "error-retrieving-device", log.Fields{"error": err, "deviceId": deviceID})
+	devicePorts, err := agent.deviceMgr.listDevicePorts(ctx, deviceID)
+	if err != nil {
+		logger.Errorw(ctx, "error-retrieving-device-ports", log.Fields{"error": err, "deviceId": deviceID})
 		return err
 	}
 
 	//Get UNI port number
-	for _, port := range device.Ports {
+	for _, port := range devicePorts {
 		if port.Type == voltha.Port_ETHERNET_NNI {
-			if err = agent.addNNILogicalPort(ctx, device, port); err != nil {
-				logger.Errorw(ctx, "error-adding-UNI-port", log.Fields{"error": err})
+			if err = agent.addNNILogicalPort(ctx, deviceID, devicePorts, port); err != nil {
+				logger.Errorw(ctx, "error-adding-NNI-port", log.Fields{"error": err})
 			}
 		}
 	}
@@ -155,25 +162,6 @@
 	return nil
 }
 
-// updatePortsState updates the ports state related to the device
-func (agent *LogicalAgent) updatePortsState(ctx context.Context, deviceID string, state voltha.OperStatus_Types) error {
-	logger.Infow(ctx, "updatePortsState-start", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
-
-	for portNo := range agent.portLoader.ListIDsForDevice(deviceID) {
-		if portHandle, have := agent.portLoader.Lock(portNo); have {
-			newPort := clonePortSetState(portHandle.GetReadOnly(), state)
-			if err := portHandle.Update(ctx, newPort); err != nil {
-				portHandle.Unlock()
-				return err
-			}
-			agent.orderedEvents.send(ctx, agent, agent.logicalDeviceID, ofp.OfpPortReason_OFPPR_MODIFY, newPort.OfpPort)
-
-			portHandle.Unlock()
-		}
-	}
-	return nil
-}
-
 func clonePortSetState(oldPort *voltha.LogicalPort, state voltha.OperStatus_Types) *voltha.LogicalPort {
 	newPort := *oldPort // only clone the struct(s) that will be changed
 	newOfpPort := *oldPort.OfpPort
@@ -190,14 +178,14 @@
 }
 
 // setupUNILogicalPorts creates a UNI port on the logical device that represents a child UNI interface
-func (agent *LogicalAgent) setupUNILogicalPorts(ctx context.Context, childDevice *voltha.Device) error {
+func (agent *LogicalAgent) setupUNILogicalPorts(ctx context.Context, childDevice *voltha.Device, childDevicePorts map[uint32]*voltha.Port) error {
 	logger.Infow(ctx, "setupUNILogicalPort", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
 	// Build the logical device based on information retrieved from the device adapter
 	var err error
 	//Get UNI port number
-	for _, port := range childDevice.Ports {
+	for _, port := range childDevicePorts {
 		if port.Type == voltha.Port_ETHERNET_UNI {
-			if err = agent.addUNILogicalPort(ctx, childDevice, port); err != nil {
+			if err = agent.addUNILogicalPort(ctx, childDevice.Id, childDevice.AdminState, childDevice.OperStatus, childDevicePorts, port); err != nil {
 				logger.Errorw(ctx, "error-adding-UNI-port", log.Fields{"error": err})
 			}
 		}
@@ -312,7 +300,7 @@
 // added and an error in case a valid error is encountered. If the port was successfully added it will return
 // (true, nil).   If the device is not in the correct state it will return (false, nil) as this is a valid
 // scenario. This also applies to the case where the port was already added.
-func (agent *LogicalAgent) addNNILogicalPort(ctx context.Context, device *voltha.Device, port *voltha.Port) error {
+func (agent *LogicalAgent) addNNILogicalPort(ctx context.Context, deviceID string, devicePorts map[uint32]*voltha.Port, port *voltha.Port) error {
 	logger.Debugw(ctx, "addNNILogicalPort", log.Fields{"logical-device-id": agent.logicalDeviceID, "nni-port": port})
 
 	label := fmt.Sprintf("nni-%d", port.PortNo)
@@ -322,7 +310,7 @@
 	ofpPort.Name = label
 	nniPort := &voltha.LogicalPort{
 		RootPort:     true,
-		DeviceId:     device.Id,
+		DeviceId:     deviceID,
 		Id:           label,
 		DevicePortNo: port.PortNo,
 		OfpPort:      &ofpPort,
@@ -346,7 +334,7 @@
 	// Setup the routes for this device and then send the port update event to the OF Controller
 	go func() {
 		// First setup the routes
-		if err := agent.updateRoutes(context.Background(), device, nniPort, agent.listLogicalDevicePorts(ctx)); err != nil {
+		if err := agent.updateRoutes(context.Background(), deviceID, devicePorts, nniPort, agent.listLogicalDevicePorts(ctx)); err != nil {
 			// This is not an error as we may not have enough logical ports to set up routes or some PON ports have not been
 			// created yet.
 			logger.Infow(ctx, "routes-not-ready", log.Fields{"logical-device-id": agent.logicalDeviceID, "logical-port": nniPort.OfpPort.PortNo, "error": err})
@@ -362,10 +350,10 @@
 // added and an error in case a valid error is encountered. If the port was successfully added it will return
 // (true, nil).   If the device is not in the correct state it will return (false, nil) as this is a valid
 // scenario. This also applies to the case where the port was already added.
-func (agent *LogicalAgent) addUNILogicalPort(ctx context.Context, childDevice *voltha.Device, port *voltha.Port) error {
+func (agent *LogicalAgent) addUNILogicalPort(ctx context.Context, deviceID string, deviceAdminState voltha.AdminState_Types, deviceOperStatus voltha.OperStatus_Types, devicePorts map[uint32]*voltha.Port, port *voltha.Port) error {
 	logger.Debugw(ctx, "addUNILogicalPort", log.Fields{"port": port})
-	if childDevice.AdminState != voltha.AdminState_ENABLED || childDevice.OperStatus != voltha.OperStatus_ACTIVE {
-		logger.Infow(ctx, "device-not-ready", log.Fields{"deviceId": childDevice.Id, "admin": childDevice.AdminState, "oper": childDevice.OperStatus})
+	if deviceAdminState != voltha.AdminState_ENABLED || deviceOperStatus != voltha.OperStatus_ACTIVE {
+		logger.Infow(ctx, "device-not-ready", log.Fields{"deviceId": deviceID, "admin": deviceAdminState, "oper": deviceOperStatus})
 		return nil
 	}
 	ofpPort := *port.OfpPort
@@ -373,7 +361,7 @@
 	ofpPort.PortNo = port.PortNo
 	uniPort := &voltha.LogicalPort{
 		RootPort:     false,
-		DeviceId:     childDevice.Id,
+		DeviceId:     deviceID,
 		Id:           port.Label,
 		DevicePortNo: port.PortNo,
 		OfpPort:      &ofpPort,
@@ -397,7 +385,7 @@
 	// Setup the routes for this device and then send the port update event to the OF Controller
 	go func() {
 		// First setup the routes
-		if err := agent.updateRoutes(context.Background(), childDevice, uniPort, agent.listLogicalDevicePorts(ctx)); err != nil {
+		if err := agent.updateRoutes(context.Background(), deviceID, devicePorts, uniPort, agent.listLogicalDevicePorts(ctx)); err != nil {
 			// This is not an error as we may not have enough logical ports to set up routes or some PON ports have not been
 			// created yet.
 			logger.Infow(ctx, "routes-not-ready", log.Fields{"logical-device-id": agent.logicalDeviceID, "logical-port": uniPort.OfpPort.PortNo, "error": err})
diff --git a/rw_core/core/device/logical_agent_route.go b/rw_core/core/device/logical_agent_route.go
index 8043e54..62e8a5f 100644
--- a/rw_core/core/device/logical_agent_route.go
+++ b/rw_core/core/device/logical_agent_route.go
@@ -108,10 +108,10 @@
 }
 
 //updateRoutes updates the device routes
-func (agent *LogicalAgent) updateRoutes(ctx context.Context, device *voltha.Device, lp *voltha.LogicalPort, lps map[uint32]*voltha.LogicalPort) error {
-	logger.Debugw(ctx, "updateRoutes", log.Fields{"logical-device-id": agent.logicalDeviceID, "device-id": device.Id, "port:": lp})
+func (agent *LogicalAgent) updateRoutes(ctx context.Context, deviceID string, devicePorts map[uint32]*voltha.Port, lp *voltha.LogicalPort, lps map[uint32]*voltha.LogicalPort) error {
+	logger.Debugw(ctx, "updateRoutes", log.Fields{"logical-device-id": agent.logicalDeviceID, "device-id": deviceID, "port:": lp})
 
-	if err := agent.deviceRoutes.AddPort(ctx, lp, device, lps); err != nil {
+	if err := agent.deviceRoutes.AddPort(ctx, lp, deviceID, devicePorts, lps); err != nil {
 		return err
 	}
 	if err := agent.deviceRoutes.Print(ctx); err != nil {
@@ -121,10 +121,10 @@
 }
 
 //updateAllRoutes updates the device routes using all the logical ports on that device
-func (agent *LogicalAgent) updateAllRoutes(ctx context.Context, device *voltha.Device) error {
-	logger.Debugw(ctx, "updateAllRoutes", log.Fields{"logical-device-id": agent.logicalDeviceID, "device-id": device.Id, "ports-count": len(device.Ports)})
+func (agent *LogicalAgent) updateAllRoutes(ctx context.Context, deviceID string, devicePorts map[uint32]*voltha.Port) error {
+	logger.Debugw(ctx, "updateAllRoutes", log.Fields{"logical-device-id": agent.logicalDeviceID, "device-id": deviceID, "ports-count": len(devicePorts)})
 
-	if err := agent.deviceRoutes.AddAllPorts(ctx, device, agent.listLogicalDevicePorts(ctx)); err != nil {
+	if err := agent.deviceRoutes.AddAllPorts(ctx, deviceID, devicePorts, agent.listLogicalDevicePorts(ctx)); err != nil {
 		return err
 	}
 	if err := agent.deviceRoutes.Print(ctx); err != nil {
diff --git a/rw_core/core/device/logical_agent_test.go b/rw_core/core/device/logical_agent_test.go
index 5cd72b4..89b3cbe 100644
--- a/rw_core/core/device/logical_agent_test.go
+++ b/rw_core/core/device/logical_agent_test.go
@@ -53,6 +53,7 @@
 	defaultTimeout   time.Duration
 	maxTimeout       time.Duration
 	logicalDevice    *voltha.LogicalDevice
+	logicalPorts     map[uint32]*voltha.LogicalPort
 	deviceIds        []string
 	done             chan int
 }
@@ -89,42 +90,42 @@
 				ofp.OfpCapabilities_OFPC_GROUP_STATS),
 		},
 		RootDeviceId: test.deviceIds[0],
-		Ports: []*voltha.LogicalPort{
-			{
-				Id:           "1001",
-				DeviceId:     test.deviceIds[0],
-				DevicePortNo: 1,
-				RootPort:     true,
-				OfpPort: &ofp.OfpPort{
-					PortNo: 1,
-					Name:   "port1",
-					Config: 4,
-					State:  4,
-				},
+	}
+	test.logicalPorts = map[uint32]*voltha.LogicalPort{
+		1: {
+			Id:           "1001",
+			DeviceId:     test.deviceIds[0],
+			DevicePortNo: 1,
+			RootPort:     true,
+			OfpPort: &ofp.OfpPort{
+				PortNo: 1,
+				Name:   "port1",
+				Config: 4,
+				State:  4,
 			},
-			{
-				Id:           "1002",
-				DeviceId:     test.deviceIds[1],
-				DevicePortNo: 2,
-				RootPort:     false,
-				OfpPort: &ofp.OfpPort{
-					PortNo: 2,
-					Name:   "port2",
-					Config: 4,
-					State:  4,
-				},
+		},
+		2: {
+			Id:           "1002",
+			DeviceId:     test.deviceIds[1],
+			DevicePortNo: 2,
+			RootPort:     false,
+			OfpPort: &ofp.OfpPort{
+				PortNo: 2,
+				Name:   "port2",
+				Config: 4,
+				State:  4,
 			},
-			{
-				Id:           "1003",
-				DeviceId:     test.deviceIds[2],
-				DevicePortNo: 3,
-				RootPort:     false,
-				OfpPort: &ofp.OfpPort{
-					PortNo: 3,
-					Name:   "port3",
-					Config: 4,
-					State:  4,
-				},
+		},
+		3: {
+			Id:           "1003",
+			DeviceId:     test.deviceIds[2],
+			DevicePortNo: 3,
+			RootPort:     false,
+			OfpPort: &ofp.OfpPort{
+				PortNo: 3,
+				Name:   "port3",
+				Config: 4,
+				State:  4,
 			},
 		},
 	}
@@ -184,14 +185,15 @@
 	clonedLD.DatapathId = rand.Uint64()
 	lDeviceAgent := newLogicalAgent(context.Background(), clonedLD.Id, clonedLD.Id, clonedLD.RootDeviceId, lDeviceMgr, deviceMgr, lDeviceMgr.dbPath, lDeviceMgr.ldProxy, lDeviceMgr.defaultTimeout)
 	lDeviceAgent.logicalDevice = clonedLD
-	for _, port := range clonedLD.Ports {
-		handle, created, err := lDeviceAgent.portLoader.LockOrCreate(context.Background(), port)
+	for _, port := range lda.logicalPorts {
+		clonedPort := proto.Clone(port).(*voltha.LogicalPort)
+		handle, created, err := lDeviceAgent.portLoader.LockOrCreate(context.Background(), clonedPort)
 		if err != nil {
 			panic(err)
 		}
 		handle.Unlock()
 		if !created {
-			t.Errorf("port %d already exists", port.OfpPort.PortNo)
+			t.Errorf("port %d already exists", clonedPort.OfpPort.PortNo)
 		}
 	}
 	err := lDeviceAgent.ldProxy.Set(context.Background(), clonedLD.Id, clonedLD)
@@ -201,14 +203,14 @@
 }
 
 func (lda *LDATest) updateLogicalDeviceConcurrently(t *testing.T, ldAgent *LogicalAgent, globalWG *sync.WaitGroup) {
-	originalLogicalDevice, _ := ldAgent.GetLogicalDevice(context.Background())
-	assert.NotNil(t, originalLogicalDevice)
+	originalLogicalPorts := ldAgent.listLogicalDevicePorts(context.Background())
+	assert.NotNil(t, originalLogicalPorts)
 	var localWG sync.WaitGroup
 
 	// Change the state of the first port to FAILED
 	localWG.Add(1)
 	go func() {
-		err := ldAgent.updatePortState(context.Background(), lda.logicalDevice.Ports[0].DevicePortNo, voltha.OperStatus_FAILED)
+		err := ldAgent.updatePortState(context.Background(), 1, voltha.OperStatus_FAILED)
 		assert.Nil(t, err)
 		localWG.Done()
 	}()
@@ -216,7 +218,7 @@
 	// Change the state of the second port to TESTING
 	localWG.Add(1)
 	go func() {
-		err := ldAgent.updatePortState(context.Background(), lda.logicalDevice.Ports[1].DevicePortNo, voltha.OperStatus_TESTING)
+		err := ldAgent.updatePortState(context.Background(), 2, voltha.OperStatus_TESTING)
 		assert.Nil(t, err)
 		localWG.Done()
 	}()
@@ -224,9 +226,9 @@
 	// Change the state of the third port to UNKNOWN and then back to ACTIVE
 	localWG.Add(1)
 	go func() {
-		err := ldAgent.updatePortState(context.Background(), lda.logicalDevice.Ports[2].DevicePortNo, voltha.OperStatus_UNKNOWN)
+		err := ldAgent.updatePortState(context.Background(), 3, voltha.OperStatus_UNKNOWN)
 		assert.Nil(t, err)
-		err = ldAgent.updatePortState(context.Background(), lda.logicalDevice.Ports[2].DevicePortNo, voltha.OperStatus_ACTIVE)
+		err = ldAgent.updatePortState(context.Background(), 3, voltha.OperStatus_ACTIVE)
 		assert.Nil(t, err)
 		localWG.Done()
 	}()
@@ -262,17 +264,27 @@
 		meterHandle.Unlock()
 	}
 
-	expectedChange := proto.Clone(originalLogicalDevice).(*voltha.LogicalDevice)
-	expectedChange.Ports[0].OfpPort.Config = originalLogicalDevice.Ports[0].OfpPort.Config | uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)
-	expectedChange.Ports[0].OfpPort.State = uint32(ofp.OfpPortState_OFPPS_LINK_DOWN)
-	expectedChange.Ports[1].OfpPort.Config = originalLogicalDevice.Ports[0].OfpPort.Config | uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)
-	expectedChange.Ports[1].OfpPort.State = uint32(ofp.OfpPortState_OFPPS_LINK_DOWN)
-	expectedChange.Ports[2].OfpPort.Config = originalLogicalDevice.Ports[0].OfpPort.Config & ^uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)
-	expectedChange.Ports[2].OfpPort.State = uint32(ofp.OfpPortState_OFPPS_LIVE)
+	expectedLogicalPorts := make(map[uint32]*voltha.LogicalPort)
+	for _, port := range originalLogicalPorts {
+		clonedPort := proto.Clone(port).(*voltha.LogicalPort)
+		switch clonedPort.OfpPort.PortNo {
+		case 1:
+			clonedPort.OfpPort.Config = originalLogicalPorts[1].OfpPort.Config | uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)
+			clonedPort.OfpPort.State = uint32(ofp.OfpPortState_OFPPS_LINK_DOWN)
+		case 2:
+			clonedPort.OfpPort.Config = originalLogicalPorts[1].OfpPort.Config | uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)
+			clonedPort.OfpPort.State = uint32(ofp.OfpPortState_OFPPS_LINK_DOWN)
+		case 3:
+			clonedPort.OfpPort.Config = originalLogicalPorts[1].OfpPort.Config & ^uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)
+			clonedPort.OfpPort.State = uint32(ofp.OfpPortState_OFPPS_LIVE)
+		}
+		expectedLogicalPorts[clonedPort.OfpPort.PortNo] = clonedPort
+	}
 
-	updatedLogicalDevicePorts := ldAgent.listLogicalDevicePorts(context.Background())
-	for _, p := range expectedChange.Ports {
-		assert.True(t, proto.Equal(p, updatedLogicalDevicePorts[p.DevicePortNo]))
+	updatedLogicalDevicePorts := ldAgent.listLogicalDevicePorts(ctx)
+	assert.Equal(t, len(expectedLogicalPorts), len(updatedLogicalDevicePorts))
+	for _, p := range updatedLogicalDevicePorts {
+		assert.True(t, proto.Equal(p, expectedLogicalPorts[p.OfpPort.PortNo]))
 	}
 	globalWG.Done()
 }
diff --git a/rw_core/core/device/logical_manager.go b/rw_core/core/device/logical_manager.go
index 4eb5ea7..cf2beed 100644
--- a/rw_core/core/device/logical_manager.go
+++ b/rw_core/core/device/logical_manager.go
@@ -348,7 +348,7 @@
 
 // updateLogicalPort sets up a logical port on the logical device based on the device port
 // information, if needed
-func (ldMgr *LogicalManager) updateLogicalPort(ctx context.Context, device *voltha.Device, port *voltha.Port) error {
+func (ldMgr *LogicalManager) updateLogicalPort(ctx context.Context, device *voltha.Device, devicePorts map[uint32]*voltha.Port, port *voltha.Port) error {
 	ldID, err := ldMgr.getLogicalDeviceID(ctx, device)
 	if err != nil || *ldID == "" {
 		// This is not an error as the logical device may not have been created at this time.  In such a case,
@@ -356,7 +356,7 @@
 		return nil
 	}
 	if agent := ldMgr.getLogicalDeviceAgent(ctx, *ldID); agent != nil {
-		if err := agent.updateLogicalPort(ctx, device, port); err != nil {
+		if err := agent.updateLogicalPort(ctx, device, devicePorts, port); err != nil {
 			return err
 		}
 	}
@@ -381,7 +381,7 @@
 	return nil
 }
 
-func (ldMgr *LogicalManager) setupUNILogicalPorts(ctx context.Context, childDevice *voltha.Device) error {
+func (ldMgr *LogicalManager) setupUNILogicalPorts(ctx context.Context, childDevice *voltha.Device, childDevicePorts map[uint32]*voltha.Port) error {
 	logger.Debugw(ctx, "setupUNILogicalPorts", log.Fields{"childDeviceId": childDevice.Id, "parentDeviceId": childDevice.ParentId, "current-data": childDevice})
 	// Sanity check
 	if childDevice.Root {
@@ -399,7 +399,7 @@
 	}
 
 	if agent := ldMgr.getLogicalDeviceAgent(ctx, logDeviceID); agent != nil {
-		if err := agent.setupUNILogicalPorts(ctx, childDevice); err != nil {
+		if err := agent.setupUNILogicalPorts(ctx, childDevice, childDevicePorts); err != nil {
 			return err
 		}
 	}
@@ -442,24 +442,6 @@
 	return nil
 }
 
-func (ldMgr *LogicalManager) updatePortsState(ctx context.Context, device *voltha.Device, state voltha.OperStatus_Types) error {
-	logger.Debugw(ctx, "updatePortsState", log.Fields{"deviceId": device.Id, "state": state, "current-data": device})
-
-	var ldID *string
-	var err error
-	//Get the logical device Id for this device
-	if ldID, err = ldMgr.getLogicalDeviceID(ctx, device); err != nil {
-		logger.Warnw(ctx, "no-logical-device-found", log.Fields{"deviceId": device.Id, "error": err})
-		return err
-	}
-	if agent := ldMgr.getLogicalDeviceAgent(ctx, *ldID); agent != nil {
-		if err := agent.updatePortsState(ctx, device.Id, state); err != nil {
-			return err
-		}
-	}
-	return nil
-}
-
 // UpdateLogicalDeviceFlowTable updates logical device flow table
 func (ldMgr *LogicalManager) UpdateLogicalDeviceFlowTable(ctx context.Context, flow *openflow_13.FlowTableUpdate) (*empty.Empty, error) {
 	logger.Debugw(ctx, "UpdateLogicalDeviceFlowTable", log.Fields{"logicalDeviceId": flow.Id})
diff --git a/rw_core/core/device/manager.go b/rw_core/core/device/manager.go
index 015c8a3..77da2f0 100755
--- a/rw_core/core/device/manager.go
+++ b/rw_core/core/device/manager.go
@@ -96,7 +96,7 @@
 	}
 	dMgr.lockRootDeviceMap.Lock()
 	defer dMgr.lockRootDeviceMap.Unlock()
-	dMgr.rootDevices[agent.deviceID] = agent.isRootdevice
+	dMgr.rootDevices[agent.deviceID] = agent.isRootDevice
 
 }
 
@@ -211,14 +211,31 @@
 	return &empty.Empty{}, agent.deleteDevice(ctx)
 }
 
+// GetDevicePort returns the port details for a specific device port entry
+func (dMgr *Manager) GetDevicePort(ctx context.Context, deviceID string, portID uint32) (*voltha.Port, error) {
+	logger.Debugw(ctx, "ListDevicePorts", log.Fields{"device-id": deviceID})
+	agent := dMgr.getDeviceAgent(ctx, deviceID)
+	if agent == nil {
+		return nil, status.Errorf(codes.NotFound, "device-%s", deviceID)
+	}
+	return agent.getDevicePort(portID)
+}
+
 // ListDevicePorts returns the ports details for a specific device entry
 func (dMgr *Manager) ListDevicePorts(ctx context.Context, id *voltha.ID) (*voltha.Ports, error) {
 	logger.Debugw(ctx, "ListDevicePorts", log.Fields{"device-id": id.Id})
-	device, err := dMgr.getDevice(ctx, id.Id)
-	if err != nil {
-		return &voltha.Ports{}, err
+	agent := dMgr.getDeviceAgent(ctx, id.Id)
+	if agent == nil {
+		return nil, status.Errorf(codes.NotFound, "device-%s", id.Id)
 	}
-	return &voltha.Ports{Items: device.Ports}, nil
+
+	ports := agent.listDevicePorts()
+	ctr, ret := 0, make([]*voltha.Port, len(ports))
+	for _, port := range ports {
+		ret[ctr] = port
+		ctr++
+	}
+	return &voltha.Ports{Items: ret}, nil
 }
 
 // ListDeviceFlows returns the flow details for a specific device entry
@@ -226,7 +243,7 @@
 	logger.Debugw(ctx, "ListDeviceFlows", log.Fields{"device-id": id.Id})
 	agent := dMgr.getDeviceAgent(ctx, id.Id)
 	if agent == nil {
-		return &ofp.Flows{}, status.Errorf(codes.NotFound, "device-%s", id.Id)
+		return nil, status.Errorf(codes.NotFound, "device-%s", id.Id)
 	}
 
 	flows := agent.listDeviceFlows()
@@ -293,41 +310,46 @@
 	return nil, status.Errorf(codes.NotFound, "%s", id)
 }
 
+func (dMgr *Manager) listDevicePorts(ctx context.Context, id string) (map[uint32]*voltha.Port, error) {
+	logger.Debugw(ctx, "listDevicePorts", log.Fields{"deviceid": id})
+	agent := dMgr.getDeviceAgent(ctx, id)
+	if agent == nil {
+		return nil, status.Errorf(codes.NotFound, "%s", id)
+	}
+	return agent.listDevicePorts(), nil
+}
+
 // GetChildDevice will return a device, either from memory or from the dB, if present
 func (dMgr *Manager) GetChildDevice(ctx context.Context, parentDeviceID string, serialNumber string, onuID int64, parentPortNo int64) (*voltha.Device, error) {
 	logger.Debugw(ctx, "GetChildDevice", log.Fields{"parentDeviceid": parentDeviceID, "serialNumber": serialNumber,
 		"parentPortNo": parentPortNo, "onuId": onuID})
 
-	var parentDevice *voltha.Device
-	var err error
-	if parentDevice, err = dMgr.getDevice(ctx, parentDeviceID); err != nil {
+	parentDevicePorts, err := dMgr.listDevicePorts(ctx, parentDeviceID)
+	if err != nil {
 		return nil, status.Errorf(codes.Aborted, "%s", err.Error())
 	}
-	var childDeviceIds []string
-	if childDeviceIds, err = dMgr.getAllChildDeviceIds(ctx, parentDevice); err != nil {
-		return nil, status.Errorf(codes.Aborted, "%s", err.Error())
-	}
+	childDeviceIds := dMgr.getAllChildDeviceIds(ctx, parentDevicePorts)
 	if len(childDeviceIds) == 0 {
-		logger.Debugw(ctx, "no-child-devices", log.Fields{"parentDeviceId": parentDevice.Id, "serialNumber": serialNumber, "onuId": onuID})
+		logger.Debugw(ctx, "no-child-devices", log.Fields{"parentDeviceId": parentDeviceID, "serialNumber": serialNumber, "onuId": onuID})
 		return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
 	}
 
 	var foundChildDevice *voltha.Device
-	for _, childDeviceID := range childDeviceIds {
+	for childDeviceID := range childDeviceIds {
 		var found bool
 		if searchDevice, err := dMgr.getDevice(ctx, childDeviceID); err == nil {
 
 			foundOnuID := false
 			if searchDevice.ProxyAddress.OnuId == uint32(onuID) {
 				if searchDevice.ParentPortNo == uint32(parentPortNo) {
-					logger.Debugw(ctx, "found-child-by-onuid", log.Fields{"parentDeviceId": parentDevice.Id, "onuId": onuID})
+					logger.Debugw(ctx, "found-child-by-onuid", log.Fields{"parentDeviceId": parentDeviceID, "onuId": onuID})
 					foundOnuID = true
 				}
 			}
 
 			foundSerialNumber := false
 			if searchDevice.SerialNumber == serialNumber {
-				logger.Debugw(ctx, "found-child-by-serialnumber", log.Fields{"parentDeviceId": parentDevice.Id, "serialNumber": serialNumber})
+				logger.Debugw(ctx, "found-child-by-serialnumber", log.Fields{"parentDeviceId": parentDeviceID, "serialNumber": serialNumber})
 				foundSerialNumber = true
 			}
 
@@ -347,11 +369,11 @@
 	}
 
 	if foundChildDevice != nil {
-		logger.Debugw(ctx, "child-device-found", log.Fields{"parentDeviceId": parentDevice.Id, "foundChildDevice": foundChildDevice})
+		logger.Debugw(ctx, "child-device-found", log.Fields{"parentDeviceId": parentDeviceID, "foundChildDevice": foundChildDevice})
 		return foundChildDevice, nil
 	}
 
-	logger.Debugw(ctx, "child-device-not-found", log.Fields{"parentDeviceId": parentDevice.Id,
+	logger.Debugw(ctx, "child-device-not-found", log.Fields{"parentDeviceId": parentDeviceID,
 		"serialNumber": serialNumber, "onuId": onuID, "parentPortNo": parentPortNo})
 	return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
 }
@@ -360,22 +382,18 @@
 func (dMgr *Manager) GetChildDeviceWithProxyAddress(ctx context.Context, proxyAddress *voltha.Device_ProxyAddress) (*voltha.Device, error) {
 	logger.Debugw(ctx, "GetChildDeviceWithProxyAddress", log.Fields{"proxyAddress": proxyAddress})
 
-	var parentDevice *voltha.Device
-	var err error
-	if parentDevice, err = dMgr.getDevice(ctx, proxyAddress.DeviceId); err != nil {
+	parentDevicePorts, err := dMgr.listDevicePorts(ctx, proxyAddress.DeviceId)
+	if err != nil {
 		return nil, status.Errorf(codes.Aborted, "%s", err.Error())
 	}
-	var childDeviceIds []string
-	if childDeviceIds, err = dMgr.getAllChildDeviceIds(ctx, parentDevice); err != nil {
-		return nil, status.Errorf(codes.Aborted, "%s", err.Error())
-	}
+	childDeviceIds := dMgr.getAllChildDeviceIds(ctx, parentDevicePorts)
 	if len(childDeviceIds) == 0 {
-		logger.Debugw(ctx, "no-child-devices", log.Fields{"parentDeviceId": parentDevice.Id})
+		logger.Debugw(ctx, "no-child-devices", log.Fields{"parentDeviceId": proxyAddress.DeviceId})
 		return nil, status.Errorf(codes.NotFound, "%s", proxyAddress)
 	}
 
 	var foundChildDevice *voltha.Device
-	for _, childDeviceID := range childDeviceIds {
+	for childDeviceID := range childDeviceIds {
 		if searchDevice, err := dMgr.getDevice(ctx, childDeviceID); err == nil {
 			if searchDevice.ProxyAddress == proxyAddress {
 				foundChildDevice = searchDevice
@@ -522,30 +540,27 @@
 }
 
 // loadRootDeviceParentAndChildren loads the children and parents of a root device in memory
-func (dMgr *Manager) loadRootDeviceParentAndChildren(ctx context.Context, device *voltha.Device) error {
+func (dMgr *Manager) loadRootDeviceParentAndChildren(ctx context.Context, device *voltha.Device, devicePorts map[uint32]*voltha.Port) error {
 	logger.Debugw(ctx, "loading-parent-and-children", log.Fields{"deviceId": device.Id})
 	if device.Root {
 		// Scenario A
 		if device.ParentId != "" {
-			//	 Load logical device if needed.
+			// Load logical device if needed.
 			if err := dMgr.logicalDeviceMgr.load(ctx, device.ParentId); err != nil {
 				logger.Warnw(ctx, "failure-loading-logical-device", log.Fields{"lDeviceId": device.ParentId})
 			}
 		} else {
 			logger.Debugw(ctx, "no-parent-to-load", log.Fields{"deviceId": device.Id})
 		}
-		//	Load all child devices, if needed
-		if childDeviceIds, err := dMgr.getAllChildDeviceIds(ctx, device); err == nil {
-			for _, childDeviceID := range childDeviceIds {
-				if _, err := dMgr.loadDevice(ctx, childDeviceID); err != nil {
-					logger.Warnw(ctx, "failure-loading-device", log.Fields{"deviceId": childDeviceID, "error": err})
-					return err
-				}
+		// Load all child devices, if needed
+		childDeviceIds := dMgr.getAllChildDeviceIds(ctx, devicePorts)
+		for childDeviceID := range childDeviceIds {
+			if _, err := dMgr.loadDevice(ctx, childDeviceID); err != nil {
+				logger.Warnw(ctx, "failure-loading-device", log.Fields{"deviceId": childDeviceID, "error": err})
+				return err
 			}
-			logger.Debugw(ctx, "loaded-children", log.Fields{"deviceId": device.Id, "numChildren": len(childDeviceIds)})
-		} else {
-			logger.Debugw(ctx, "no-child-to-load", log.Fields{"deviceId": device.Id})
 		}
+		logger.Debugw(ctx, "loaded-children", log.Fields{"deviceId": device.Id, "numChildren": len(childDeviceIds)})
 	}
 	return nil
 }
@@ -575,8 +590,10 @@
 
 	// Now we face two scenarios
 	if device.Root {
+		devicePorts := dAgent.listDevicePorts()
+
 		// Load all children as well as the parent of this device (logical_device)
-		if err := dMgr.loadRootDeviceParentAndChildren(ctx, device); err != nil {
+		if err := dMgr.loadRootDeviceParentAndChildren(ctx, device, devicePorts); err != nil {
 			logger.Warnw(ctx, "failure-loading-device-parent-and-children", log.Fields{"deviceId": deviceID})
 			return err
 		}
@@ -656,8 +673,9 @@
 					logger.Debugw(ctx, "not-reconciling-root-device", log.Fields{"rootId": rootDevice.Id, "state": rootDevice.AdminState})
 				}
 			} else { // Should we be reconciling the root's children instead?
+				rootDevicePorts, _ := dMgr.listDevicePorts(ctx, rootDeviceID)
 			childManagedByAdapter:
-				for _, port := range rootDevice.Ports {
+				for _, port := range rootDevicePorts {
 					for _, peer := range port.Peers {
 						if childDevice, _ := dMgr.getDeviceFromModel(ctx, peer.DeviceId); childDevice != nil {
 							isDeviceOwnedByService, err := dMgr.adapterProxy.IsDeviceOwnedByService(ctx, childDevice.Id, adapter.Type, adapter.CurrentReplica)
@@ -717,11 +735,11 @@
 }
 
 func (dMgr *Manager) ReconcileChildDevices(ctx context.Context, parentDeviceID string) error {
-	if parentDevice, _ := dMgr.getDeviceFromModel(ctx, parentDeviceID); parentDevice != nil {
+	if parentDevicePorts, err := dMgr.listDevicePorts(ctx, parentDeviceID); err == nil {
 		responses := make([]utils.Response, 0)
-		for _, port := range parentDevice.Ports {
+		for _, port := range parentDevicePorts {
 			for _, peer := range port.Peers {
-				if childDevice, _ := dMgr.getDeviceFromModel(ctx, peer.DeviceId); childDevice != nil {
+				if childDevice, err := dMgr.getDeviceFromModel(ctx, peer.DeviceId); err == nil {
 					responses = append(responses, dMgr.sendReconcileDeviceRequest(ctx, childDevice))
 				}
 			}
@@ -758,7 +776,11 @@
 	if err != nil {
 		return err
 	}
-	if err = dMgr.logicalDeviceMgr.updateLogicalPort(context.Background(), device, port); err != nil {
+	ports, err := dMgr.listDevicePorts(ctx, deviceID)
+	if err != nil {
+		return err
+	}
+	if err = dMgr.logicalDeviceMgr.updateLogicalPort(context.Background(), device, ports, port); err != nil {
 		return err
 	}
 	return nil
@@ -793,7 +815,7 @@
 func (dMgr *Manager) deleteParentFlows(ctx context.Context, deviceID string, uniPort uint32, metadata *voltha.FlowMetadata) error {
 	logger.Debugw(ctx, "deleteParentFlows", log.Fields{"device-id": deviceID, "uni-port": uniPort, "metadata": metadata})
 	if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
-		if !agent.isRootdevice {
+		if !agent.isRootDevice {
 			return status.Errorf(codes.FailedPrecondition, "not-a-parent-device-%s", deviceID)
 		}
 		return agent.filterOutFlows(ctx, uniPort, metadata)
@@ -860,10 +882,11 @@
 
 func (dMgr *Manager) GetPorts(ctx context.Context, deviceID string, portType voltha.Port_PortType) (*voltha.Ports, error) {
 	logger.Debugw(ctx, "GetPorts", log.Fields{"deviceid": deviceID, "portType": portType})
-	if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
-		return agent.getPorts(ctx, portType), nil
+	agent := dMgr.getDeviceAgent(ctx, deviceID)
+	if agent == nil {
+		return nil, status.Errorf(codes.NotFound, "%s", deviceID)
 	}
-	return nil, status.Errorf(codes.NotFound, "%s", deviceID)
+	return agent.getPorts(ctx, portType), nil
 }
 
 func (dMgr *Manager) UpdateDeviceStatus(ctx context.Context, deviceID string, operStatus voltha.OperStatus_Types, connStatus voltha.ConnectStatus_Types) error {
@@ -876,19 +899,11 @@
 
 func (dMgr *Manager) UpdateChildrenStatus(ctx context.Context, deviceID string, operStatus voltha.OperStatus_Types, connStatus voltha.ConnectStatus_Types) error {
 	logger.Debugw(ctx, "UpdateChildrenStatus", log.Fields{"parentDeviceid": deviceID, "operStatus": operStatus, "connStatus": connStatus})
-	var parentDevice *voltha.Device
-	var err error
-	if parentDevice, err = dMgr.getDevice(ctx, deviceID); err != nil {
+	parentDevicePorts, err := dMgr.listDevicePorts(ctx, deviceID)
+	if err != nil {
 		return status.Errorf(codes.Aborted, "%s", err.Error())
 	}
-	var childDeviceIds []string
-	if childDeviceIds, err = dMgr.getAllChildDeviceIds(ctx, parentDevice); err != nil {
-		return status.Errorf(codes.Aborted, "%s", err.Error())
-	}
-	if len(childDeviceIds) == 0 {
-		logger.Debugw(ctx, "no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
-	}
-	for _, childDeviceID := range childDeviceIds {
+	for childDeviceID := range dMgr.getAllChildDeviceIds(ctx, parentDevicePorts) {
 		if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
 			if err = agent.updateDeviceStatus(ctx, operStatus, connStatus); err != nil {
 				return status.Errorf(codes.Aborted, "childDevice:%s, error:%s", childDeviceID, err.Error())
@@ -952,37 +967,20 @@
 }
 
 //UpdatePortsState updates all ports on the device
-func (dMgr *Manager) UpdatePortsState(ctx context.Context, deviceID string, state voltha.OperStatus_Types) error {
+func (dMgr *Manager) UpdatePortsState(ctx context.Context, deviceID string, portTypeFilter uint32, state voltha.OperStatus_Types) error {
 	logger.Debugw(ctx, "UpdatePortsState", log.Fields{"deviceid": deviceID})
-
-	if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
-		switch state {
-		case voltha.OperStatus_ACTIVE:
-			if err := agent.updatePortsOperState(ctx, state); err != nil {
-				logger.Warnw(ctx, "updatePortsOperState-failed", log.Fields{"deviceId": deviceID, "error": err})
-				return err
-			}
-		case voltha.OperStatus_UNKNOWN:
-			if err := agent.updatePortsOperState(ctx, state); err != nil {
-				logger.Warnw(ctx, "updatePortsOperState-failed", log.Fields{"deviceId": deviceID, "error": err})
-				return err
-			}
-		default:
-			return status.Error(codes.Unimplemented, "state-change-not-implemented")
-		}
-		// Notify the logical device about the state change
-		device, err := dMgr.getDevice(ctx, deviceID)
-		if err != nil {
-			logger.Warnw(ctx, "non-existent-device", log.Fields{"deviceId": deviceID, "error": err})
-			return err
-		}
-		if err := dMgr.logicalDeviceMgr.updatePortsState(ctx, device, state); err != nil {
-			logger.Warnw(ctx, "failed-updating-ports-state", log.Fields{"deviceId": deviceID, "error": err})
-			return err
-		}
-		return nil
+	agent := dMgr.getDeviceAgent(ctx, deviceID)
+	if agent == nil {
+		return status.Errorf(codes.NotFound, "%s", deviceID)
 	}
-	return status.Errorf(codes.NotFound, "%s", deviceID)
+	if state != voltha.OperStatus_ACTIVE && state != voltha.OperStatus_UNKNOWN {
+		return status.Error(codes.Unimplemented, "state-change-not-implemented")
+	}
+	if err := agent.updatePortsOperState(ctx, portTypeFilter, state); err != nil {
+		logger.Warnw(ctx, "updatePortsOperState-failed", log.Fields{"deviceId": deviceID, "error": err})
+		return err
+	}
+	return nil
 }
 
 func (dMgr *Manager) ChildDeviceDetected(ctx context.Context, parentDeviceID string, parentPortNo int64, deviceType string,
@@ -1176,9 +1174,8 @@
 //cannot manage the child devices.  This will trigger the Core to disable all the child devices.
 func (dMgr *Manager) ChildDevicesLost(ctx context.Context, parentDeviceID string) error {
 	logger.Debug(ctx, "ChildDevicesLost")
-	var err error
-	var parentDevice *voltha.Device
-	if parentDevice, err = dMgr.getDevice(ctx, parentDeviceID); err != nil {
+	parentDevice, err := dMgr.getDevice(ctx, parentDeviceID)
+	if err != nil {
 		logger.Warnw(ctx, "failed-getting-device", log.Fields{"deviceId": parentDeviceID, "error": err})
 		return err
 	}
@@ -1189,34 +1186,28 @@
 // disable/enable sequence.  This will trigger the Core to Enable all the child devices of that parent.
 func (dMgr *Manager) ChildDevicesDetected(ctx context.Context, parentDeviceID string) error {
 	logger.Debug(ctx, "ChildDevicesDetected")
-	var err error
-	var parentDevice *voltha.Device
-	var childDeviceIds []string
-
-	if parentDevice, err = dMgr.getDevice(ctx, parentDeviceID); err != nil {
+	parentDevicePorts, err := dMgr.listDevicePorts(ctx, parentDeviceID)
+	if err != nil {
 		logger.Warnw(ctx, "failed-getting-device", log.Fields{"deviceId": parentDeviceID, "error": err})
 		return err
 	}
-
-	if childDeviceIds, err = dMgr.getAllChildDeviceIds(ctx, parentDevice); err != nil {
-		return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
-	}
+	childDeviceIds := dMgr.getAllChildDeviceIds(ctx, parentDevicePorts)
 	if len(childDeviceIds) == 0 {
-		logger.Debugw(ctx, "no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
+		logger.Debugw(ctx, "no-child-device", log.Fields{"parentDeviceId": parentDeviceID})
 	}
 	allChildEnableRequestSent := true
-	for _, childDeviceID := range childDeviceIds {
+	for childDeviceID := range childDeviceIds {
 		if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
 			// Run the children re-registration in its own routine
-			go func() {
-				err = agent.enableDevice(context.Background())
+			go func(ctx context.Context) {
+				err = agent.enableDevice(ctx)
 				if err != nil {
 					logger.Errorw(ctx, "unable-to-enable-device", log.Fields{"error": err})
 				}
-			}()
+			}(context.Background())
 		} else {
 			err = status.Errorf(codes.Unavailable, "no agent for child device %s", childDeviceID)
-			logger.Errorw(ctx, "no-child-device-agent", log.Fields{"parentDeviceId": parentDevice.Id, "childId": childDeviceID})
+			logger.Errorw(ctx, "no-child-device-agent", log.Fields{"parentDeviceId": parentDeviceID, "childId": childDeviceID})
 			allChildEnableRequestSent = false
 		}
 	}
@@ -1234,17 +1225,10 @@
 //DisableAllChildDevices is invoked as a callback when the parent device is disabled
 func (dMgr *Manager) DisableAllChildDevices(ctx context.Context, parentCurrDevice *voltha.Device) error {
 	logger.Debug(ctx, "DisableAllChildDevices")
-	var childDeviceIds []string
-	var err error
-	if childDeviceIds, err = dMgr.getAllChildDeviceIds(ctx, parentCurrDevice); err != nil {
-		return status.Errorf(codes.NotFound, "%s", parentCurrDevice.Id)
-	}
-	if len(childDeviceIds) == 0 {
-		logger.Debugw(ctx, "no-child-device", log.Fields{"parentDeviceId": parentCurrDevice.Id})
-	}
-	for _, childDeviceID := range childDeviceIds {
+	ports, _ := dMgr.listDevicePorts(ctx, parentCurrDevice.Id)
+	for childDeviceID := range dMgr.getAllChildDeviceIds(ctx, ports) {
 		if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
-			if err = agent.disableDevice(ctx); err != nil {
+			if err := agent.disableDevice(ctx); err != nil {
 				// Just log the error - this error happens only if the child device was already in deleted state.
 				logger.Errorw(ctx, "failure-disable-device", log.Fields{"deviceId": childDeviceID, "error": err.Error()})
 			}
@@ -1256,17 +1240,10 @@
 //DeleteAllChildDevices is invoked as a callback when the parent device is deleted
 func (dMgr *Manager) DeleteAllChildDevices(ctx context.Context, parentCurrDevice *voltha.Device) error {
 	logger.Debug(ctx, "DeleteAllChildDevices")
-	var childDeviceIds []string
-	var err error
-	if childDeviceIds, err = dMgr.getAllChildDeviceIds(ctx, parentCurrDevice); err != nil {
-		return status.Errorf(codes.NotFound, "%s", parentCurrDevice.Id)
-	}
-	if len(childDeviceIds) == 0 {
-		logger.Debugw(ctx, "no-child-device", log.Fields{"parentDeviceId": parentCurrDevice.Id})
-	}
-	for _, childDeviceID := range childDeviceIds {
+	ports, _ := dMgr.listDevicePorts(ctx, parentCurrDevice.Id)
+	for childDeviceID := range dMgr.getAllChildDeviceIds(ctx, ports) {
 		if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
-			if err = agent.deleteDevice(ctx); err != nil {
+			if err := agent.deleteDevice(ctx); err != nil {
 				logger.Warnw(ctx, "failure-delete-device", log.Fields{"deviceId": childDeviceID, "error": err.Error()})
 			}
 			// No further action is required here.  The deleteDevice will change the device state where the resulting
@@ -1300,30 +1277,26 @@
 }
 
 //getAllChildDeviceIds is a helper method to get all the child device IDs from the device passed as parameter
-func (dMgr *Manager) getAllChildDeviceIds(ctx context.Context, parentDevice *voltha.Device) ([]string, error) {
-	logger.Debugw(ctx, "getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id})
-	childDeviceIds := make([]string, 0)
-	if parentDevice != nil {
-		for _, port := range parentDevice.Ports {
-			for _, peer := range port.Peers {
-				childDeviceIds = append(childDeviceIds, peer.DeviceId)
-			}
+func (dMgr *Manager) getAllChildDeviceIds(ctx context.Context, parentDevicePorts map[uint32]*voltha.Port) map[string]struct{} {
+	logger.Debug(ctx, "getAllChildDeviceIds")
+	childDeviceIds := make(map[string]struct{}, len(parentDevicePorts))
+	for _, port := range parentDevicePorts {
+		for _, peer := range port.Peers {
+			childDeviceIds[peer.DeviceId] = struct{}{}
 		}
-		logger.Debugw(ctx, "returning-getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id, "childDeviceIds": childDeviceIds})
 	}
-	return childDeviceIds, nil
+	logger.Debugw(ctx, "returning-getAllChildDeviceIds", log.Fields{"childDeviceIds": childDeviceIds})
+	return childDeviceIds
 }
 
 //GetAllChildDevices is a helper method to get all the child device IDs from the device passed as parameter
 func (dMgr *Manager) GetAllChildDevices(ctx context.Context, parentDeviceID string) (*voltha.Devices, error) {
 	logger.Debugw(ctx, "GetAllChildDevices", log.Fields{"parentDeviceId": parentDeviceID})
-	if parentDevice, err := dMgr.getDevice(ctx, parentDeviceID); err == nil {
+	if parentDevicePorts, err := dMgr.listDevicePorts(ctx, parentDeviceID); err == nil {
 		childDevices := make([]*voltha.Device, 0)
-		if childDeviceIds, er := dMgr.getAllChildDeviceIds(ctx, parentDevice); er == nil {
-			for _, deviceID := range childDeviceIds {
-				if d, e := dMgr.getDevice(ctx, deviceID); e == nil && d != nil {
-					childDevices = append(childDevices, d)
-				}
+		for deviceID := range dMgr.getAllChildDeviceIds(ctx, parentDevicePorts) {
+			if d, e := dMgr.getDevice(ctx, deviceID); e == nil && d != nil {
+				childDevices = append(childDevices, d)
 			}
 		}
 		return &voltha.Devices{Items: childDevices}, nil
@@ -1334,7 +1307,11 @@
 // SetupUNILogicalPorts creates UNI ports on the logical device that represents a child UNI interface
 func (dMgr *Manager) SetupUNILogicalPorts(ctx context.Context, cDevice *voltha.Device) error {
 	logger.Info(ctx, "addUNILogicalPort")
-	if err := dMgr.logicalDeviceMgr.setupUNILogicalPorts(ctx, cDevice); err != nil {
+	cDevicePorts, err := dMgr.listDevicePorts(ctx, cDevice.Id)
+	if err != nil {
+		return err
+	}
+	if err := dMgr.logicalDeviceMgr.setupUNILogicalPorts(ctx, cDevice, cDevicePorts); err != nil {
 		logger.Warnw(ctx, "addUNILogicalPort-error", log.Fields{"device": cDevice, "err": err})
 		return err
 	}
@@ -1529,7 +1506,7 @@
 	if agent == nil {
 		return nil, status.Errorf(codes.NotFound, "%s", port.DeviceId)
 	}
-	return &empty.Empty{}, agent.enablePort(ctx, port)
+	return &empty.Empty{}, agent.enablePort(ctx, port.PortNo)
 }
 
 func (dMgr *Manager) DisablePort(ctx context.Context, port *voltha.Port) (*empty.Empty, error) {
@@ -1538,7 +1515,7 @@
 	if agent == nil {
 		return nil, status.Errorf(codes.NotFound, "%s", port.DeviceId)
 	}
-	return &empty.Empty{}, agent.disablePort(ctx, port)
+	return &empty.Empty{}, agent.disablePort(ctx, port.PortNo)
 }
 
 // ChildDeviceLost  calls parent adapter to delete child device and all its references
diff --git a/tests/core/api/common.go b/rw_core/core/device/port/common.go
similarity index 91%
rename from tests/core/api/common.go
rename to rw_core/core/device/port/common.go
index e694b19..df435c1 100644
--- a/tests/core/api/common.go
+++ b/rw_core/core/device/port/common.go
@@ -1,5 +1,3 @@
-// +build integration
-
 /*
  * Copyright 2020-present Open Networking Foundation
  *
@@ -15,7 +13,9 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package api
+
+// Package core Common Logger initialization
+package port
 
 import (
 	"github.com/opencord/voltha-lib-go/v3/pkg/log"
@@ -26,7 +26,7 @@
 func init() {
 	// Setup this package so that it's log level can be modified at run time
 	var err error
-	logger, err = log.RegisterPackage(log.JSON, log.ErrorLevel, log.Fields{"pkg": "api"})
+	logger, err = log.RegisterPackage(log.JSON, log.ErrorLevel, log.Fields{"pkg": "port"})
 	if err != nil {
 		panic(err)
 	}
diff --git a/rw_core/core/device/port/loader.go b/rw_core/core/device/port/loader.go
new file mode 100644
index 0000000..479695a
--- /dev/null
+++ b/rw_core/core/device/port/loader.go
@@ -0,0 +1,187 @@
+/*
+ * Copyright 2018-present Open Networking Foundation
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+
+ * http://www.apache.org/licenses/LICENSE-2.0
+
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package port
+
+import (
+	"context"
+	"fmt"
+	"sync"
+
+	"github.com/opencord/voltha-go/db/model"
+	"github.com/opencord/voltha-lib-go/v3/pkg/log"
+	"github.com/opencord/voltha-protos/v3/go/voltha"
+	"google.golang.org/grpc/codes"
+	"google.golang.org/grpc/status"
+)
+
+// Loader hides all low-level locking & synchronization related to port state updates
+type Loader struct {
+	dbProxy *model.Proxy
+	// this lock protects the ports map, it does not protect individual ports
+	lock  sync.RWMutex
+	ports map[uint32]*chunk
+}
+
+// chunk keeps a port and the lock for this port
+type chunk struct {
+	// this lock is used to synchronize all access to the port, and also to the "deleted" variable
+	lock    sync.Mutex
+	deleted bool
+
+	port *voltha.Port
+}
+
+func NewLoader(dbProxy *model.Proxy) *Loader {
+	return &Loader{
+		dbProxy: dbProxy,
+		ports:   make(map[uint32]*chunk),
+	}
+}
+
+// Load queries existing ports from the kv,
+// and should only be called once when first created.
+func (loader *Loader) Load(ctx context.Context) {
+	loader.lock.Lock()
+	defer loader.lock.Unlock()
+
+	var ports []*voltha.Port
+	if err := loader.dbProxy.List(ctx, &ports); err != nil {
+		logger.Errorw(ctx, "failed-to-list-ports-from-cluster-data-proxy", log.Fields{"error": err})
+		return
+	}
+	for _, port := range ports {
+		loader.ports[port.PortNo] = &chunk{port: port}
+	}
+}
+
+// LockOrCreate locks this port if it exists, or creates a new port if it does not.
+// In the case of port creation, the provided "port" must not be modified afterwards.
+func (loader *Loader) LockOrCreate(ctx context.Context, port *voltha.Port) (*Handle, bool, error) {
+	// try to use read lock instead of full lock if possible
+	if handle, have := loader.Lock(port.PortNo); have {
+		return handle, false, nil
+	}
+
+	loader.lock.Lock()
+	entry, have := loader.ports[port.PortNo]
+	if !have {
+		entry := &chunk{port: port}
+		loader.ports[port.PortNo] = entry
+		entry.lock.Lock()
+		loader.lock.Unlock()
+
+		if err := loader.dbProxy.Set(ctx, fmt.Sprint(port.PortNo), port); err != nil {
+			// revert the map
+			loader.lock.Lock()
+			delete(loader.ports, port.PortNo)
+			loader.lock.Unlock()
+
+			entry.deleted = true
+			entry.lock.Unlock()
+			return nil, false, err
+		}
+		return &Handle{loader: loader, chunk: entry}, true, nil
+	}
+	loader.lock.Unlock()
+
+	entry.lock.Lock()
+	if entry.deleted {
+		entry.lock.Unlock()
+		return loader.LockOrCreate(ctx, port)
+	}
+	return &Handle{loader: loader, chunk: entry}, false, nil
+}
+
+// Lock acquires the lock for this port, and returns a handle which can be used to access the port until it's unlocked.
+// This handle ensures that the port cannot be accessed if the lock is not held.
+// Returns false if the port is not present.
+// TODO: consider accepting a ctx and aborting the lock attempt on cancellation
+func (loader *Loader) Lock(id uint32) (*Handle, bool) {
+	loader.lock.RLock()
+	entry, have := loader.ports[id]
+	loader.lock.RUnlock()
+
+	if !have {
+		return nil, false
+	}
+
+	entry.lock.Lock()
+	if entry.deleted {
+		entry.lock.Unlock()
+		return loader.Lock(id)
+	}
+	return &Handle{loader: loader, chunk: entry}, true
+}
+
+// Handle is allocated for each Lock() call, all modifications are made using it, and it is invalidated by Unlock()
+// This enforces correct Lock()-Usage()-Unlock() ordering.
+type Handle struct {
+	loader *Loader
+	chunk  *chunk
+}
+
+// GetReadOnly returns an *voltha.Port which MUST NOT be modified externally, but which is safe to keep indefinitely
+func (h *Handle) GetReadOnly() *voltha.Port {
+	return h.chunk.port
+}
+
+// Update updates an existing port in the kv.
+// The provided "port" must not be modified afterwards.
+func (h *Handle) Update(ctx context.Context, port *voltha.Port) error {
+	if err := h.loader.dbProxy.Set(ctx, fmt.Sprint(port.PortNo), port); err != nil {
+		return status.Errorf(codes.Internal, "failed-update-port-%v: %s", port.PortNo, err)
+	}
+	h.chunk.port = port
+	return nil
+}
+
+// Delete removes the device from the kv
+func (h *Handle) Delete(ctx context.Context) error {
+	if err := h.loader.dbProxy.Remove(ctx, fmt.Sprint(h.chunk.port.PortNo)); err != nil {
+		return fmt.Errorf("couldnt-delete-port-from-store-%v", h.chunk.port.PortNo)
+	}
+	h.chunk.deleted = true
+
+	h.loader.lock.Lock()
+	delete(h.loader.ports, h.chunk.port.PortNo)
+	h.loader.lock.Unlock()
+
+	h.Unlock()
+	return nil
+}
+
+// Unlock releases the lock on the port
+func (h *Handle) Unlock() {
+	if h.chunk != nil {
+		h.chunk.lock.Unlock()
+		h.chunk = nil // attempting to access the port through this handle in future will panic
+	}
+}
+
+// ListIDs returns a snapshot of all the managed port IDs
+// TODO: iterating through ports safely is expensive now, since all ports are stored & locked separately
+//       should avoid this where possible
+func (loader *Loader) ListIDs() map[uint32]struct{} {
+	loader.lock.RLock()
+	defer loader.lock.RUnlock()
+	// copy the IDs so caller can safely iterate
+	ret := make(map[uint32]struct{}, len(loader.ports))
+	for id := range loader.ports {
+		ret[id] = struct{}{}
+	}
+	return ret
+}
diff --git a/rw_core/core/device/remote/adapter_proxy_test.go b/rw_core/core/device/remote/adapter_proxy_test.go
index 5ab0127..46de80f 100755
--- a/rw_core/core/device/remote/adapter_proxy_test.go
+++ b/rw_core/core/device/remote/adapter_proxy_test.go
@@ -18,6 +18,10 @@
 import (
 	"context"
 	"crypto/rand"
+	"strings"
+	"testing"
+	"time"
+
 	"github.com/golang/protobuf/ptypes"
 	any2 "github.com/golang/protobuf/ptypes/any"
 	cm "github.com/opencord/voltha-go/rw_core/mocks"
@@ -31,9 +35,6 @@
 	"github.com/stretchr/testify/assert"
 	"google.golang.org/grpc/codes"
 	"google.golang.org/grpc/status"
-	"strings"
-	"testing"
-	"time"
 )
 
 const (
diff --git a/rw_core/flowdecomposition/flow_decomposer_test.go b/rw_core/flowdecomposition/flow_decomposer_test.go
index 80ff313..ea560e2 100644
--- a/rw_core/flowdecomposition/flow_decomposer_test.go
+++ b/rw_core/flowdecomposition/flow_decomposer_test.go
@@ -32,56 +32,58 @@
 
 type testDeviceManager struct {
 	mocks.DeviceManager
-	devices map[string]*voltha.Device
+	devices     map[string]*voltha.Device
+	devicePorts map[string]map[uint32]*voltha.Port
 }
 
 func newTestDeviceManager() *testDeviceManager {
 	var tdm testDeviceManager
 	tdm.devices = make(map[string]*voltha.Device)
+	tdm.devicePorts = make(map[string]map[uint32]*voltha.Port)
 	tdm.devices["olt"] = &voltha.Device{
 		Id:       "olt",
 		Root:     true,
 		ParentId: "logical_device",
-		Ports: []*voltha.Port{
-			{PortNo: 1, Label: "pon"},
-			{PortNo: 2, Label: "nni"},
-		},
+	}
+	tdm.devicePorts["olt"] = map[uint32]*voltha.Port{
+		1: {PortNo: 1, Label: "pon"},
+		2: {PortNo: 2, Label: "nni"},
 	}
 	tdm.devices["onu1"] = &voltha.Device{
 		Id:       "onu1",
 		Root:     false,
 		ParentId: "olt",
-		Ports: []*voltha.Port{
-			{PortNo: 1, Label: "pon"},
-			{PortNo: 2, Label: "uni"},
-		},
+	}
+	tdm.devicePorts["onu1"] = map[uint32]*voltha.Port{
+		1: {PortNo: 1, Label: "pon"},
+		2: {PortNo: 2, Label: "uni"},
 	}
 	tdm.devices["onu2"] = &voltha.Device{
 		Id:       "onu2",
 		Root:     false,
 		ParentId: "olt",
-		Ports: []*voltha.Port{
-			{PortNo: 1, Label: "pon"},
-			{PortNo: 2, Label: "uni"},
-		},
+	}
+	tdm.devicePorts["onu2"] = map[uint32]*voltha.Port{
+		1: {PortNo: 1, Label: "pon"},
+		2: {PortNo: 2, Label: "uni"},
 	}
 	tdm.devices["onu3"] = &voltha.Device{
 		Id:       "onu3",
 		Root:     false,
 		ParentId: "olt",
-		Ports: []*voltha.Port{
-			{PortNo: 1, Label: "pon"},
-			{PortNo: 2, Label: "uni"},
-		},
+	}
+	tdm.devicePorts["onu3"] = map[uint32]*voltha.Port{
+		1: {PortNo: 1, Label: "pon"},
+		2: {PortNo: 2, Label: "uni"},
 	}
 	tdm.devices["onu4"] = &voltha.Device{
 		Id:       "onu4",
 		Root:     false,
 		ParentId: "olt",
-		Ports: []*voltha.Port{
-			{PortNo: 1, Label: "pon"},
-			{PortNo: 2, Label: "uni"},
-		},
+	}
+	tdm.devicePorts["onu4"] = map[uint32]*voltha.Port{
+		1: {PortNo: 1, Label: "pon"},
+		2: {PortNo: 2, Label: "uni"},
 	}
 	return &tdm
 }
@@ -92,6 +94,13 @@
 	}
 	return nil, errors.New("ABSENT")
 }
+func (tdm *testDeviceManager) listDevicePorts(ctx context.Context, deviceID string) (map[uint32]*voltha.Port, error) {
+	ports, have := tdm.devicePorts[deviceID]
+	if !have {
+		return nil, errors.New("ABSENT")
+	}
+	return ports, nil
+}
 func (tdm *testDeviceManager) IsRootDevice(deviceID string) (bool, error) {
 	if d, ok := tdm.devices[deviceID]; ok {
 		return d.Root, nil
@@ -134,62 +143,62 @@
 	tfd.routes[route.OFPortLink{Ingress: 10, Egress: 1}] = []route.Hop{
 		{
 			DeviceID: "olt",
-			Ingress:  tfd.dMgr.devices["olt"].Ports[1].PortNo,
-			Egress:   tfd.dMgr.devices["olt"].Ports[0].PortNo,
+			Ingress:  2,
+			Egress:   1,
 		},
 		{
 			DeviceID: "onu1",
-			Ingress:  tfd.dMgr.devices["onu1"].Ports[0].PortNo,
-			Egress:   tfd.dMgr.devices["onu1"].Ports[1].PortNo,
+			Ingress:  1,
+			Egress:   2,
 		},
 	}
 
 	tfd.routes[route.OFPortLink{Ingress: 10, Egress: 2}] = []route.Hop{
 		{
 			DeviceID: "olt",
-			Ingress:  tfd.dMgr.devices["olt"].Ports[1].PortNo,
-			Egress:   tfd.dMgr.devices["olt"].Ports[0].PortNo,
+			Ingress:  2,
+			Egress:   1,
 		},
 		{
 			DeviceID: "onu2",
-			Ingress:  tfd.dMgr.devices["onu2"].Ports[0].PortNo,
-			Egress:   tfd.dMgr.devices["onu2"].Ports[1].PortNo,
+			Ingress:  1,
+			Egress:   2,
 		},
 	}
 	tfd.routes[route.OFPortLink{Ingress: 10, Egress: 3}] = []route.Hop{
 		{
 			DeviceID: "olt",
-			Ingress:  tfd.dMgr.devices["olt"].Ports[1].PortNo,
-			Egress:   tfd.dMgr.devices["olt"].Ports[0].PortNo,
+			Ingress:  2,
+			Egress:   1,
 		},
 		{
 			DeviceID: "onu3",
-			Ingress:  tfd.dMgr.devices["onu3"].Ports[0].PortNo,
-			Egress:   tfd.dMgr.devices["onu3"].Ports[1].PortNo,
+			Ingress:  1,
+			Egress:   2,
 		},
 	}
 	tfd.routes[route.OFPortLink{Ingress: 10, Egress: 4}] = []route.Hop{
 		{
 			DeviceID: "olt",
-			Ingress:  tfd.dMgr.devices["olt"].Ports[1].PortNo,
-			Egress:   tfd.dMgr.devices["olt"].Ports[0].PortNo,
+			Ingress:  2,
+			Egress:   1,
 		},
 		{
 			DeviceID: "onu4",
-			Ingress:  tfd.dMgr.devices["onu4"].Ports[0].PortNo,
-			Egress:   tfd.dMgr.devices["onu4"].Ports[1].PortNo,
+			Ingress:  1,
+			Egress:   2,
 		},
 	}
 	tfd.routes[route.OFPortLink{Ingress: 10, Egress: 10}] = []route.Hop{
 		{
 			DeviceID: "olt",
-			Ingress:  tfd.dMgr.devices["olt"].Ports[1].PortNo,
-			Egress:   tfd.dMgr.devices["olt"].Ports[1].PortNo,
+			Ingress:  2,
+			Egress:   2,
 		},
 		{
 			DeviceID: "olt",
-			Ingress:  tfd.dMgr.devices["olt"].Ports[1].PortNo,
-			Egress:   tfd.dMgr.devices["olt"].Ports[1].PortNo,
+			Ingress:  2,
+			Egress:   2,
 		},
 	}
 
@@ -198,49 +207,49 @@
 	tfd.routes[route.OFPortLink{Ingress: 1, Egress: 10}] = []route.Hop{
 		{
 			DeviceID: "onu1",
-			Ingress:  tfd.dMgr.devices["onu1"].Ports[1].PortNo,
-			Egress:   tfd.dMgr.devices["onu1"].Ports[0].PortNo,
+			Ingress:  2,
+			Egress:   1,
 		},
 		{
 			DeviceID: "olt",
-			Ingress:  tfd.dMgr.devices["olt"].Ports[0].PortNo,
-			Egress:   tfd.dMgr.devices["olt"].Ports[1].PortNo,
+			Ingress:  1,
+			Egress:   2,
 		},
 	}
 	tfd.routes[route.OFPortLink{Ingress: 2, Egress: 10}] = []route.Hop{
 		{
 			DeviceID: "onu2",
-			Ingress:  tfd.dMgr.devices["onu2"].Ports[1].PortNo,
-			Egress:   tfd.dMgr.devices["onu2"].Ports[0].PortNo,
+			Ingress:  2,
+			Egress:   1,
 		},
 		{
 			DeviceID: "olt",
-			Ingress:  tfd.dMgr.devices["olt"].Ports[0].PortNo,
-			Egress:   tfd.dMgr.devices["olt"].Ports[1].PortNo,
+			Ingress:  1,
+			Egress:   2,
 		},
 	}
 	tfd.routes[route.OFPortLink{Ingress: 3, Egress: 10}] = []route.Hop{
 		{
 			DeviceID: "onu3",
-			Ingress:  tfd.dMgr.devices["onu3"].Ports[1].PortNo,
-			Egress:   tfd.dMgr.devices["onu3"].Ports[0].PortNo,
+			Ingress:  2,
+			Egress:   1,
 		},
 		{
 			DeviceID: "olt",
-			Ingress:  tfd.dMgr.devices["olt"].Ports[0].PortNo,
-			Egress:   tfd.dMgr.devices["olt"].Ports[1].PortNo,
+			Ingress:  1,
+			Egress:   2,
 		},
 	}
 	tfd.routes[route.OFPortLink{Ingress: 4, Egress: 10}] = []route.Hop{
 		{
 			DeviceID: "onu4",
-			Ingress:  tfd.dMgr.devices["onu4"].Ports[1].PortNo,
-			Egress:   tfd.dMgr.devices["onu4"].Ports[0].PortNo,
+			Ingress:  2,
+			Egress:   1,
 		},
 		{
 			DeviceID: "olt",
-			Ingress:  tfd.dMgr.devices["olt"].Ports[0].PortNo,
-			Egress:   tfd.dMgr.devices["olt"].Ports[1].PortNo,
+			Ingress:  1,
+			Egress:   2,
 		},
 	}
 
@@ -250,49 +259,49 @@
 	tfd.routes[route.OFPortLink{Ingress: 1, Egress: 0}] = []route.Hop{
 		{
 			DeviceID: "onu1",
-			Ingress:  tfd.dMgr.devices["onu1"].Ports[1].PortNo,
-			Egress:   tfd.dMgr.devices["onu1"].Ports[0].PortNo,
+			Ingress:  2,
+			Egress:   1,
 		},
 		{
 			DeviceID: "olt",
-			Ingress:  tfd.dMgr.devices["olt"].Ports[0].PortNo,
-			Egress:   tfd.dMgr.devices["olt"].Ports[1].PortNo,
+			Ingress:  1,
+			Egress:   2,
 		},
 	}
 	tfd.routes[route.OFPortLink{Ingress: 2, Egress: 0}] = []route.Hop{
 		{
 			DeviceID: "onu2",
-			Ingress:  tfd.dMgr.devices["onu2"].Ports[1].PortNo,
-			Egress:   tfd.dMgr.devices["onu2"].Ports[0].PortNo,
+			Ingress:  2,
+			Egress:   1,
 		},
 		{
 			DeviceID: "olt",
-			Ingress:  tfd.dMgr.devices["olt"].Ports[0].PortNo,
-			Egress:   tfd.dMgr.devices["olt"].Ports[1].PortNo,
+			Ingress:  1,
+			Egress:   2,
 		},
 	}
 	tfd.routes[route.OFPortLink{Ingress: 3, Egress: 0}] = []route.Hop{
 		{
 			DeviceID: "onu3",
-			Ingress:  tfd.dMgr.devices["onu3"].Ports[1].PortNo,
-			Egress:   tfd.dMgr.devices["onu3"].Ports[0].PortNo,
+			Ingress:  2,
+			Egress:   1,
 		},
 		{
 			DeviceID: "olt",
-			Ingress:  tfd.dMgr.devices["olt"].Ports[0].PortNo,
-			Egress:   tfd.dMgr.devices["olt"].Ports[1].PortNo,
+			Ingress:  1,
+			Egress:   2,
 		},
 	}
 	tfd.routes[route.OFPortLink{Ingress: 4, Egress: 0}] = []route.Hop{
 		{
 			DeviceID: "onu4",
-			Ingress:  tfd.dMgr.devices["onu4"].Ports[1].PortNo,
-			Egress:   tfd.dMgr.devices["onu4"].Ports[0].PortNo,
+			Ingress:  2,
+			Egress:   1,
 		},
 		{
 			DeviceID: "olt",
-			Ingress:  tfd.dMgr.devices["olt"].Ports[0].PortNo,
-			Egress:   tfd.dMgr.devices["olt"].Ports[1].PortNo,
+			Ingress:  1,
+			Egress:   2,
 		},
 	}
 
@@ -301,8 +310,8 @@
 	tfd.routes[route.OFPortLink{Ingress: 10, Egress: 0}] = []route.Hop{
 		{
 			DeviceID: "olt",
-			Ingress:  tfd.dMgr.devices["olt"].Ports[1].PortNo,
-			Egress:   tfd.dMgr.devices["olt"].Ports[0].PortNo,
+			Ingress:  2,
+			Egress:   1,
 		},
 		{}, // 2nd hop is not known yet
 	}
@@ -311,8 +320,8 @@
 		{}, // 1st hop is wildcard
 		{
 			DeviceID: "olt",
-			Ingress:  tfd.dMgr.devices["olt"].Ports[0].PortNo,
-			Egress:   tfd.dMgr.devices["olt"].Ports[1].PortNo,
+			Ingress:  1,
+			Egress:   2,
 		},
 	}
 
@@ -384,7 +393,7 @@
 	tfd.defaultRules.AddFlowsAndGroup("onu4", fg)
 
 	//Set up the device graph - flow decomposer uses it only to verify whether a port is a root port.
-	tfd.deviceRoutes = route.NewDeviceRoutes(context.Background(), "ldid", tfd.getDeviceHelper)
+	tfd.deviceRoutes = route.NewDeviceRoutes("ldid", "olt", tfd.dMgr.listDevicePorts)
 	tfd.deviceRoutes.RootPorts = make(map[uint32]uint32)
 	tfd.deviceRoutes.RootPorts[10] = 10
 
@@ -393,10 +402,6 @@
 	return &tfd
 }
 
-func (tfd *testFlowDecomposer) getDeviceHelper(ctx context.Context, deviceID string) (*voltha.Device, error) {
-	return tfd.dMgr.GetDevice(ctx, &voltha.ID{Id: deviceID})
-}
-
 func (tfd *testFlowDecomposer) GetDeviceLogicalID() string {
 	return ""
 }
diff --git a/rw_core/mocks/adapter_olt.go b/rw_core/mocks/adapter_olt.go
index d040f64..313ecc6 100644
--- a/rw_core/mocks/adapter_olt.go
+++ b/rw_core/mocks/adapter_olt.go
@@ -20,14 +20,16 @@
 	"context"
 	"errors"
 	"fmt"
+	"strings"
+
 	"github.com/gogo/protobuf/proto"
+	"github.com/opencord/voltha-lib-go/v3/pkg/adapters"
 	"github.com/opencord/voltha-lib-go/v3/pkg/adapters/adapterif"
 	com "github.com/opencord/voltha-lib-go/v3/pkg/adapters/common"
 	"github.com/opencord/voltha-lib-go/v3/pkg/log"
 	ic "github.com/opencord/voltha-protos/v3/go/inter_container"
 	of "github.com/opencord/voltha-protos/v3/go/openflow_13"
 	"github.com/opencord/voltha-protos/v3/go/voltha"
-	"strings"
 )
 
 const (
@@ -35,6 +37,9 @@
 	startingUNIPortNo = 100
 )
 
+// static implementation check
+var _ adapters.IAdapter = &OLTAdapter{}
+
 // OLTAdapter represent OLT adapter
 type OLTAdapter struct {
 	*Adapter
@@ -168,7 +173,7 @@
 
 		cloned := proto.Clone(device).(*voltha.Device)
 		// Update the all ports state on that device to disable
-		if err := oltA.coreProxy.PortsStateUpdate(context.TODO(), cloned.Id, voltha.OperStatus_UNKNOWN); err != nil {
+		if err := oltA.coreProxy.PortsStateUpdate(context.TODO(), cloned.Id, 0, voltha.OperStatus_UNKNOWN); err != nil {
 			logger.Warnw(ctx, "updating-ports-failed", log.Fields{"deviceId": device.Id, "error": err})
 		}
 
@@ -202,7 +207,7 @@
 
 		cloned := proto.Clone(device).(*voltha.Device)
 		// Update the all ports state on that device to enable
-		if err := oltA.coreProxy.PortsStateUpdate(context.TODO(), cloned.Id, voltha.OperStatus_ACTIVE); err != nil {
+		if err := oltA.coreProxy.PortsStateUpdate(context.TODO(), cloned.Id, 0, voltha.OperStatus_ACTIVE); err != nil {
 			logger.Fatalf(ctx, "updating-ports-failed", log.Fields{"deviceId": device.Id, "error": err})
 		}
 
@@ -262,7 +267,7 @@
 		if err := oltA.coreProxy.DeviceStateUpdate(context.TODO(), device.Id, voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_UNKNOWN); err != nil {
 			logger.Fatalf(ctx, "device-state-update-failed", log.Fields{"device-id": device.Id, "error": err})
 		}
-		if err := oltA.coreProxy.PortsStateUpdate(context.TODO(), device.Id, voltha.OperStatus_UNKNOWN); err != nil {
+		if err := oltA.coreProxy.PortsStateUpdate(context.TODO(), device.Id, 0, voltha.OperStatus_UNKNOWN); err != nil {
 			// Not an error as the previous command will start the process of clearing the OLT
 			logger.Infow(ctx, "port-update-failed", log.Fields{"device-id": device.Id, "error": err})
 		}
diff --git a/rw_core/mocks/adapter_olt_test.go b/rw_core/mocks/adapter_olt_test.go
deleted file mode 100644
index 082c12e..0000000
--- a/rw_core/mocks/adapter_olt_test.go
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright 2019-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package mocks
-
-import (
-	"context"
-	"testing"
-
-	"github.com/opencord/voltha-lib-go/v3/pkg/adapters"
-)
-
-func TestOLTAdapterImplementsIAdapter(t *testing.T) {
-	adapter := NewOLTAdapter(context.Background(), nil)
-
-	if _, ok := interface{}(adapter).(adapters.IAdapter); !ok {
-		t.Error("OLT adapter does not implement voltha-lib-go/v2/pkg/adapters/IAdapter interface")
-	}
-}
diff --git a/rw_core/mocks/adapter_onu.go b/rw_core/mocks/adapter_onu.go
index 8e7b867..f578df0 100644
--- a/rw_core/mocks/adapter_onu.go
+++ b/rw_core/mocks/adapter_onu.go
@@ -20,6 +20,8 @@
 	"context"
 	"errors"
 	"fmt"
+	"strings"
+
 	"github.com/gogo/protobuf/proto"
 	"github.com/opencord/voltha-lib-go/v3/pkg/adapters/adapterif"
 	com "github.com/opencord/voltha-lib-go/v3/pkg/adapters/common"
@@ -27,7 +29,6 @@
 	ic "github.com/opencord/voltha-protos/v3/go/inter_container"
 	of "github.com/opencord/voltha-protos/v3/go/openflow_13"
 	"github.com/opencord/voltha-protos/v3/go/voltha"
-	"strings"
 )
 
 // ONUAdapter represent ONU adapter attributes
@@ -134,7 +135,7 @@
 		}
 		cloned := proto.Clone(device).(*voltha.Device)
 		// Update the all ports state on that device to disable
-		if err := onuA.coreProxy.PortsStateUpdate(context.TODO(), cloned.Id, voltha.OperStatus_UNKNOWN); err != nil {
+		if err := onuA.coreProxy.PortsStateUpdate(context.TODO(), cloned.Id, 0, voltha.OperStatus_UNKNOWN); err != nil {
 			// Device may also have been deleted in the Core
 			logger.Warnw(ctx, "updating-ports-failed", log.Fields{"deviceId": device.Id, "error": err})
 			return
@@ -161,7 +162,7 @@
 
 		cloned := proto.Clone(device).(*voltha.Device)
 		// Update the all ports state on that device to enable
-		if err := onuA.coreProxy.PortsStateUpdate(context.TODO(), cloned.Id, voltha.OperStatus_ACTIVE); err != nil {
+		if err := onuA.coreProxy.PortsStateUpdate(context.TODO(), cloned.Id, 0, voltha.OperStatus_ACTIVE); err != nil {
 			logger.Fatalf(ctx, "updating-ports-failed", log.Fields{"deviceId": device.Id, "error": err})
 		}
 
diff --git a/rw_core/route/device_route.go b/rw_core/route/device_route.go
index a1f2ae9..48339ec 100644
--- a/rw_core/route/device_route.go
+++ b/rw_core/route/device_route.go
@@ -48,13 +48,14 @@
 	Egress  uint32
 }
 
-// GetDeviceFunc returns device function
-type GetDeviceFunc func(ctx context.Context, id string) (*voltha.Device, error)
+// listDevicePortsFunc returns device ports
+type listDevicePortsFunc func(ctx context.Context, id string) (map[uint32]*voltha.Port, error)
 
 // DeviceRoutes represent the set of routes between logical ports of a logical device
 type DeviceRoutes struct {
 	logicalDeviceID     string
-	getDeviceFromModel  GetDeviceFunc
+	rootDeviceID        string
+	listDevicePorts     listDevicePortsFunc
 	logicalPorts        map[uint32]*voltha.LogicalPort
 	RootPorts           map[uint32]uint32
 	rootPortsLock       sync.RWMutex
@@ -65,17 +66,17 @@
 }
 
 // NewDeviceRoutes creates device graph instance
-func NewDeviceRoutes(ctx context.Context, logicalDeviceID string, getDevice GetDeviceFunc) *DeviceRoutes {
-	var dr DeviceRoutes
-	dr.logicalDeviceID = logicalDeviceID
-	dr.getDeviceFromModel = getDevice
-	dr.RootPorts = make(map[uint32]uint32)
-	dr.Routes = make(map[PathID][]Hop)
-	dr.devicesPonPorts = make(map[string][]*voltha.Port)
-	dr.childConnectionPort = make(map[string]uint32)
-	dr.logicalPorts = make(map[uint32]*voltha.LogicalPort)
-	logger.Debug(ctx, "new device routes created ...")
-	return &dr
+func NewDeviceRoutes(logicalDeviceID, rootDeviceID string, deviceMgr listDevicePortsFunc) *DeviceRoutes {
+	return &DeviceRoutes{
+		logicalDeviceID:     logicalDeviceID,
+		rootDeviceID:        rootDeviceID,
+		listDevicePorts:     deviceMgr,
+		RootPorts:           make(map[uint32]uint32),
+		Routes:              make(map[PathID][]Hop),
+		devicesPonPorts:     make(map[string][]*voltha.Port),
+		childConnectionPort: make(map[string]uint32),
+		logicalPorts:        make(map[uint32]*voltha.LogicalPort),
+	}
 }
 
 //IsRootPort returns true if the port is a root port on a logical device
@@ -103,7 +104,7 @@
 	if err != nil {
 		return nil, err
 	}
-	rootDevicePonPort, err := dr.getParentPonPort(ctx, nniPort.DeviceId, uniPort.DeviceId)
+	rootDevicePonPort, err := dr.getParentPonPort(ctx, uniPort.DeviceId)
 	if err != nil {
 		return nil, err
 	}
@@ -154,8 +155,6 @@
 	if len(nniPorts) == 0 {
 		return fmt.Errorf("no nni port :%w", ErrNoRoute)
 	}
-	var rootDevice *voltha.Device
-	var childDevice *voltha.Device
 	var copyFromNNIPort *voltha.LogicalPort
 	for idx, nniPort := range nniPorts {
 		if idx == 0 {
@@ -165,36 +164,38 @@
 			return nil
 		}
 		// Get root device
-		rootDevice, err = dr.getDeviceWithCacheUpdate(ctx, nniPort.DeviceId)
+		rootDeviceID := nniPort.DeviceId
+		rootDevicePorts, err := dr.getDeviceWithCacheUpdate(ctx, nniPort.DeviceId)
 		if err != nil {
 			return err
 		}
-		if len(rootDevice.Ports) == 0 {
-			err = status.Errorf(codes.FailedPrecondition, "no-port-%s", rootDevice.Id)
+		if len(rootDevicePorts) == 0 {
+			err = status.Errorf(codes.FailedPrecondition, "no-port-%s", rootDeviceID)
 			return err
 		}
-		for _, rootDevicePort := range rootDevice.Ports {
+		for _, rootDevicePort := range rootDevicePorts {
 			if rootDevicePort.Type == voltha.Port_PON_OLT {
-				logger.Debugw(ctx, "peers", log.Fields{"root-device-id": rootDevice.Id, "port-no": rootDevicePort.PortNo, "len-peers": len(rootDevicePort.Peers)})
+				logger.Debugw(ctx, "peers", log.Fields{"root-device-id": rootDeviceID, "port-no": rootDevicePort.PortNo, "len-peers": len(rootDevicePort.Peers)})
 				for _, rootDevicePeer := range rootDevicePort.Peers {
-					childDevice, err = dr.getDeviceWithCacheUpdate(ctx, rootDevicePeer.DeviceId)
+					childDeviceID := rootDevicePeer.DeviceId
+					childDevicePorts, err := dr.getDeviceWithCacheUpdate(ctx, rootDevicePeer.DeviceId)
 					if err != nil {
 						return err
 					}
-					childPonPort, err := dr.getChildPonPort(ctx, childDevice.Id)
+					childPonPort, err := dr.getChildPonPort(ctx, childDeviceID)
 					if err != nil {
 						return err
 					}
-					for _, childDevicePort := range childDevice.Ports {
+					for _, childDevicePort := range childDevicePorts {
 						if childDevicePort.Type == voltha.Port_ETHERNET_UNI {
-							childLogicalPort, exist := physPortToLogicalPortMap[concatDeviceIDPortID(childDevice.Id, childDevicePort.PortNo)]
+							childLogicalPort, exist := physPortToLogicalPortMap[concatDeviceIDPortID(childDeviceID, childDevicePort.PortNo)]
 							if !exist {
 								// This can happen if this logical port has not been created yet for that device
 								continue
 							}
 							dr.Routes[PathID{Ingress: nniPort.OfpPort.PortNo, Egress: childLogicalPort}] = []Hop{
-								{DeviceID: rootDevice.Id, Ingress: nniPort.DevicePortNo, Egress: rootDevicePort.PortNo},
-								{DeviceID: childDevice.Id, Ingress: childPonPort, Egress: childDevicePort.PortNo},
+								{DeviceID: rootDeviceID, Ingress: nniPort.DevicePortNo, Egress: rootDevicePort.PortNo},
+								{DeviceID: childDeviceID, Ingress: childPonPort, Egress: childDevicePort.PortNo},
 							}
 							dr.Routes[PathID{Ingress: childLogicalPort, Egress: nniPort.OfpPort.PortNo}] = getReverseRoute(
 								dr.Routes[PathID{Ingress: nniPort.OfpPort.PortNo, Egress: childLogicalPort}])
@@ -209,20 +210,20 @@
 
 // AddPort augments the current set of routes with new routes corresponding to the logical port "lp".  If the routes have
 // not been built yet then use logical port "lps" to compute all current routes (lps includes lp)
-func (dr *DeviceRoutes) AddPort(ctx context.Context, lp *voltha.LogicalPort, device *voltha.Device, lps map[uint32]*voltha.LogicalPort) error {
+func (dr *DeviceRoutes) AddPort(ctx context.Context, lp *voltha.LogicalPort, deviceID string, devicePorts map[uint32]*voltha.Port, lps map[uint32]*voltha.LogicalPort) error {
 	logger.Debugw(ctx, "add-port-to-routes", log.Fields{"port": lp, "count-logical-ports": len(lps)})
 
 	// Adding NNI port
 	if lp.RootPort {
-		return dr.AddNNIPort(ctx, lp, device, lps)
+		return dr.AddNNIPort(ctx, lp, deviceID, devicePorts, lps)
 	}
 
 	// Adding UNI port
-	return dr.AddUNIPort(ctx, lp, device, lps)
+	return dr.AddUNIPort(ctx, lp, deviceID, devicePorts, lps)
 }
 
 // AddUNIPort setup routes between the logical UNI port lp and all registered NNI ports
-func (dr *DeviceRoutes) AddUNIPort(ctx context.Context, lp *voltha.LogicalPort, device *voltha.Device, lps map[uint32]*voltha.LogicalPort) error {
+func (dr *DeviceRoutes) AddUNIPort(ctx context.Context, lp *voltha.LogicalPort, deviceID string, devicePorts map[uint32]*voltha.Port, lps map[uint32]*voltha.LogicalPort) error {
 	logger.Debugw(ctx, "add-uni-port-to-routes", log.Fields{"port": lp, "count-logical-ports": len(lps)})
 
 	dr.routeBuildLock.Lock()
@@ -232,14 +233,14 @@
 	dr.logicalPorts[lp.OfpPort.PortNo] = lp
 
 	// Update internal structures with device data
-	dr.updateCache(device)
+	dr.updateCache(deviceID, devicePorts)
 
 	// Adding a UNI port
 	childPonPort, err := dr.getChildPonPort(ctx, lp.DeviceId)
 	if err != nil {
 		return err
 	}
-	rootDevicePonPort, err := dr.getParentPonPort(ctx, device.ParentId, device.Id)
+	rootDevicePonPort, err := dr.getParentPonPort(ctx, deviceID)
 	if err != nil {
 		return err
 	}
@@ -259,14 +260,14 @@
 }
 
 // AddNNIPort setup routes between the logical NNI port lp and all registered UNI ports
-func (dr *DeviceRoutes) AddNNIPort(ctx context.Context, lp *voltha.LogicalPort, device *voltha.Device, lps map[uint32]*voltha.LogicalPort) error {
-	logger.Debugw(ctx, "add-port-to-routes", log.Fields{"port": lp, "logical-ports-count": len(lps), "device-id": device.Id})
+func (dr *DeviceRoutes) AddNNIPort(ctx context.Context, lp *voltha.LogicalPort, deviceID string, devicePorts map[uint32]*voltha.Port, lps map[uint32]*voltha.LogicalPort) error {
+	logger.Debugw(ctx, "add-port-to-routes", log.Fields{"port": lp, "logical-ports-count": len(lps), "device-id": deviceID})
 
 	dr.routeBuildLock.Lock()
 	defer dr.routeBuildLock.Unlock()
 
 	// Update internal structures with device data
-	dr.updateCache(device)
+	dr.updateCache(deviceID, devicePorts)
 
 	// Setup the physical ports to logical ports map, the nni ports as well as the root ports map
 	physPortToLogicalPortMap := make(map[string]uint32)
@@ -280,22 +281,23 @@
 		dr.logicalPorts[lp.OfpPort.PortNo] = lp
 	}
 
-	for _, rootDevicePort := range device.Ports {
+	for _, rootDevicePort := range devicePorts {
 		if rootDevicePort.Type == voltha.Port_PON_OLT {
-			logger.Debugw(ctx, "peers", log.Fields{"root-device-id": device.Id, "port-no": rootDevicePort.PortNo, "len-peers": len(rootDevicePort.Peers)})
+			logger.Debugw(ctx, "peers", log.Fields{"root-device-id": deviceID, "port-no": rootDevicePort.PortNo, "len-peers": len(rootDevicePort.Peers)})
 			for _, rootDevicePeer := range rootDevicePort.Peers {
-				childDevice, err := dr.getDeviceWithCacheUpdate(ctx, rootDevicePeer.DeviceId)
+				childDeviceID := rootDevicePeer.DeviceId
+				childDevicePorts, err := dr.getDeviceWithCacheUpdate(ctx, rootDevicePeer.DeviceId)
 				if err != nil {
 					continue
 				}
 
-				childPonPort, err := dr.getChildPonPort(ctx, childDevice.Id)
+				childPonPort, err := dr.getChildPonPort(ctx, childDeviceID)
 				if err != nil {
 					continue
 				}
 
-				for _, childDevicePort := range childDevice.Ports {
-					childLogicalPort, exist := physPortToLogicalPortMap[concatDeviceIDPortID(childDevice.Id, childDevicePort.PortNo)]
+				for _, childDevicePort := range childDevicePorts {
+					childLogicalPort, exist := physPortToLogicalPortMap[concatDeviceIDPortID(childDeviceID, childDevicePort.PortNo)]
 					if !exist {
 						// This can happen if this logical port has not been created yet for that device
 						continue
@@ -303,8 +305,8 @@
 
 					if childDevicePort.Type == voltha.Port_ETHERNET_UNI {
 						dr.Routes[PathID{Ingress: lp.OfpPort.PortNo, Egress: childLogicalPort}] = []Hop{
-							{DeviceID: device.Id, Ingress: lp.DevicePortNo, Egress: rootDevicePort.PortNo},
-							{DeviceID: childDevice.Id, Ingress: childPonPort, Egress: childDevicePort.PortNo},
+							{DeviceID: deviceID, Ingress: lp.DevicePortNo, Egress: rootDevicePort.PortNo},
+							{DeviceID: childDeviceID, Ingress: childPonPort, Egress: childDevicePort.PortNo},
 						}
 						dr.Routes[PathID{Ingress: childLogicalPort, Egress: lp.OfpPort.PortNo}] = getReverseRoute(
 							dr.Routes[PathID{Ingress: lp.OfpPort.PortNo, Egress: childLogicalPort}])
@@ -317,11 +319,11 @@
 }
 
 // AddAllPorts setups up new routes using all ports on the device. lps includes the device's logical port
-func (dr *DeviceRoutes) AddAllPorts(ctx context.Context, device *voltha.Device, lps map[uint32]*voltha.LogicalPort) error {
-	logger.Debugw(ctx, "add-all-port-to-routes", log.Fields{"logical-ports-count": len(lps), "device-id": device.Id})
+func (dr *DeviceRoutes) AddAllPorts(ctx context.Context, deviceID string, devicePorts map[uint32]*voltha.Port, lps map[uint32]*voltha.LogicalPort) error {
+	logger.Debugw(ctx, "add-all-port-to-routes", log.Fields{"logical-ports-count": len(lps), "device-id": deviceID})
 	for _, lp := range lps {
-		if lp.DeviceId == device.Id {
-			if err := dr.AddPort(ctx, lp, device, lps); err != nil {
+		if lp.DeviceId == deviceID {
+			if err := dr.AddPort(ctx, lp, deviceID, devicePorts, lps); err != nil {
 				return err
 			}
 		}
@@ -411,14 +413,14 @@
 }
 
 //getDeviceWithCacheUpdate returns the from the model and updates the PON ports map of that device.
-func (dr *DeviceRoutes) getDeviceWithCacheUpdate(ctx context.Context, deviceID string) (*voltha.Device, error) {
-	device, err := dr.getDeviceFromModel(ctx, deviceID)
+func (dr *DeviceRoutes) getDeviceWithCacheUpdate(ctx context.Context, deviceID string) (map[uint32]*voltha.Port, error) {
+	devicePorts, err := dr.listDevicePorts(ctx, deviceID)
 	if err != nil {
 		logger.Errorw(ctx, "device-not-found", log.Fields{"deviceId": deviceID, "error": err})
 		return nil, err
 	}
-	dr.updateCache(device)
-	return device, nil
+	dr.updateCache(deviceID, devicePorts)
+	return devicePorts, nil
 }
 
 //copyFromExistingNNIRoutes copies routes from an existing set of NNI routes
@@ -491,14 +493,14 @@
 }
 
 // getParentPonPort returns the parent PON port of the child device
-func (dr *DeviceRoutes) getParentPonPort(ctx context.Context, deviceID string, childDeviceID string) (uint32, error) {
+func (dr *DeviceRoutes) getParentPonPort(ctx context.Context, childDeviceID string) (uint32, error) {
 	if pNo, exist := dr.childConnectionPort[childDeviceID]; exist {
 		return pNo, nil
 	}
 
 	// Get parent device from the model
-	if _, err := dr.getDeviceWithCacheUpdate(ctx, deviceID); err != nil {
-		logger.Errorw(ctx, "device-not-found", log.Fields{"deviceId": deviceID, "error": err})
+	if _, err := dr.getDeviceWithCacheUpdate(ctx, dr.rootDeviceID); err != nil {
+		logger.Errorw(ctx, "device-not-found", log.Fields{"deviceId": dr.rootDeviceID, "error": err})
 		return 0, err
 	}
 	// Try again
@@ -508,10 +510,10 @@
 	return 0, fmt.Errorf("pon port associated with child device %s not found", childDeviceID)
 }
 
-func (dr *DeviceRoutes) updateCache(device *voltha.Device) {
-	for _, port := range device.Ports {
+func (dr *DeviceRoutes) updateCache(deviceID string, devicePorts map[uint32]*voltha.Port) {
+	for _, port := range devicePorts {
 		if port.Type == voltha.Port_PON_ONU || port.Type == voltha.Port_PON_OLT {
-			dr.devicesPonPorts[device.Id] = append(dr.devicesPonPorts[device.Id], port)
+			dr.devicesPonPorts[deviceID] = append(dr.devicesPonPorts[deviceID], port)
 			for _, peer := range port.Peers {
 				if port.Type == voltha.Port_PON_ONU {
 					dr.childConnectionPort[port.DeviceId] = peer.PortNo
diff --git a/rw_core/route/device_route_test.go b/rw_core/route/device_route_test.go
index 0fd0836..3857837 100644
--- a/rw_core/route/device_route_test.go
+++ b/rw_core/route/device_route_test.go
@@ -48,13 +48,15 @@
 
 //onuRegistration is a message sent from an ONU device to an OLT device to register an ONU
 type onuRegistration struct {
-	onu      *voltha.Device
+	onuID    string
+	onuPorts map[uint32]*voltha.Port
 	oltPonNo uint32
 	onuPonNo uint32
 }
 
 type logicalDeviceManager struct {
 	logicalDeviceID string
+	rootDeviceID    string
 	ports           map[uint32]*voltha.LogicalPort
 	deviceRoutes    *DeviceRoutes
 	ldChnl          chan portRegistration
@@ -62,23 +64,19 @@
 	done            chan struct{}
 }
 
-func newLogicalDeviceManager(ld *voltha.LogicalDevice, ch chan portRegistration, totalLogicalPorts int, done chan struct{}) *logicalDeviceManager {
-	ports := make(map[uint32]*voltha.LogicalPort)
-	for _, p := range ld.Ports {
-		ports[p.DevicePortNo] = p
-	}
-
+func newLogicalDeviceManager(ld *voltha.LogicalDevice, rootDeviceID string, ch chan portRegistration, totalLogicalPorts int, done chan struct{}) *logicalDeviceManager {
 	return &logicalDeviceManager{
 		logicalDeviceID: ld.Id,
-		ports:           ports,
+		rootDeviceID:    rootDeviceID,
+		ports:           make(map[uint32]*voltha.LogicalPort),
 		ldChnl:          ch,
 		numLogicalPorts: totalLogicalPorts,
 		done:            done,
 	}
 }
 
-func (ldM *logicalDeviceManager) start(ctx context.Context, getDevice GetDeviceFunc, buildRoutes bool) {
-	ldM.deviceRoutes = NewDeviceRoutes(ctx, ldM.logicalDeviceID, getDevice)
+func (ldM *logicalDeviceManager) start(ctx context.Context, listDevicePorts listDevicePortsFunc, buildRoutes bool) {
+	ldM.deviceRoutes = NewDeviceRoutes(ldM.logicalDeviceID, ldM.rootDeviceID, listDevicePorts)
 	ofpPortNo := uint32(1)
 	for portReg := range ldM.ldChnl {
 		if portReg.port == nil {
@@ -94,11 +92,11 @@
 		}
 		ldM.ports[lp.DevicePortNo] = lp
 		if buildRoutes {
-			device, err := getDevice(context.WithValue(context.Background(), testSetupPhase, true), lp.DeviceId)
+			devicePorts, err := listDevicePorts(context.WithValue(context.Background(), testSetupPhase, true), lp.DeviceId)
 			if err != nil {
 				fmt.Println("Error when getting device:", lp.DeviceId, err)
 			}
-			if err := ldM.deviceRoutes.AddPort(context.Background(), lp, device, ldM.ports); err != nil && !strings.Contains(err.Error(), "code = FailedPrecondition") {
+			if err := ldM.deviceRoutes.AddPort(context.Background(), lp, lp.DeviceId, devicePorts, ldM.ports); err != nil && !strings.Contains(err.Error(), "code = FailedPrecondition") {
 				fmt.Println("(Error when adding port:", lp, len(ldM.ports), err)
 			}
 		}
@@ -109,7 +107,8 @@
 }
 
 type oltManager struct {
-	olt              *voltha.Device
+	oltID            string
+	oltPorts         map[uint32]*voltha.Port
 	logicalDeviceMgr *logicalDeviceManager
 	numNNIPort       int
 	numPonPortOnOlt  int
@@ -118,7 +117,8 @@
 
 func newOltManager(oltDeviceID string, ldMgr *logicalDeviceManager, numNNIPort int, numPonPortOnOlt int, ch chan onuRegistration) *oltManager {
 	return &oltManager{
-		olt:              &voltha.Device{Id: oltDeviceID, ParentId: ldMgr.logicalDeviceID, Root: true},
+		oltID:            oltDeviceID, // ParentId: ldMgr.logicalDeviceID, Root: true},
+		oltPorts:         make(map[uint32]*voltha.Port),
 		logicalDeviceMgr: ldMgr,
 		numNNIPort:       numNNIPort,
 		numPonPortOnOlt:  numPonPortOnOlt,
@@ -127,41 +127,40 @@
 }
 
 func (oltM *oltManager) start() {
-	oltM.olt.Ports = make([]*voltha.Port, 0)
 	// Setup the OLT nni ports and trigger the nni ports creation
 	for nniPort := 1; nniPort < oltM.numNNIPort+1; nniPort++ {
-		p := &voltha.Port{Label: fmt.Sprintf("nni-%d", nniPort), PortNo: uint32(nniPort), DeviceId: oltM.olt.Id, Type: voltha.Port_ETHERNET_NNI}
-		oltM.olt.Ports = append(oltM.olt.Ports, p)
+		p := &voltha.Port{Label: fmt.Sprintf("nni-%d", nniPort), PortNo: uint32(nniPort), DeviceId: oltM.oltID, Type: voltha.Port_ETHERNET_NNI}
+		oltM.oltPorts[p.PortNo] = p
 		oltM.logicalDeviceMgr.ldChnl <- portRegistration{port: p, rootPort: true}
 	}
 
 	// Create OLT pon ports
 	for ponPort := oltM.numNNIPort + 1; ponPort < oltM.numPonPortOnOlt+oltM.numNNIPort+1; ponPort++ {
-		p := voltha.Port{PortNo: uint32(ponPort), DeviceId: oltM.olt.Id, Type: voltha.Port_PON_OLT}
-		oltM.olt.Ports = append(oltM.olt.Ports, &p)
+		p := &voltha.Port{PortNo: uint32(ponPort), DeviceId: oltM.oltID, Type: voltha.Port_PON_OLT}
+		oltM.oltPorts[p.PortNo] = p
 	}
 
 	// Wait for onu registration
 	for onuReg := range oltM.oltChnl {
-		if onuReg.onu == nil {
+		if onuReg.onuPorts == nil {
 			// All onu has registered - exit the loop
 			break
 		}
-		oltM.registerOnu(onuReg.onu, onuReg.oltPonNo, onuReg.onuPonNo)
+		oltM.registerOnu(onuReg.onuID, onuReg.onuPorts, onuReg.oltPonNo, onuReg.onuPonNo)
 	}
 	// Inform the logical device manager we are done
 	oltM.logicalDeviceMgr.ldChnl <- portRegistration{port: nil}
 }
 
-func (oltM *oltManager) registerOnu(onu *voltha.Device, oltPonNo uint32, onuPonNo uint32) {
+func (oltM *oltManager) registerOnu(onuID string, onuPorts map[uint32]*voltha.Port, oltPonNo uint32, onuPonNo uint32) {
 	// Update the olt pon peers
-	for _, port := range oltM.olt.Ports {
+	for _, port := range oltM.oltPorts {
 		if port.Type == voltha.Port_PON_OLT && port.PortNo == oltPonNo {
-			port.Peers = append(port.Peers, &voltha.Port_PeerPort{DeviceId: onu.Id, PortNo: onuPonNo})
+			port.Peers = append(port.Peers, &voltha.Port_PeerPort{DeviceId: onuID, PortNo: onuPonNo})
 		}
 	}
 	// For each uni port on the ONU trigger the creation of a logical port
-	for _, port := range onu.Ports {
+	for _, port := range onuPorts {
 		if port.Type == voltha.Port_ETHERNET_UNI {
 			oltM.logicalDeviceMgr.ldChnl <- portRegistration{port: port, rootPort: false}
 		}
@@ -177,6 +176,7 @@
 	numGetDeviceInvokedLock sync.RWMutex
 	deviceLock              sync.RWMutex
 	onus                    []*voltha.Device
+	onuPorts                map[string]map[uint32]*voltha.Port
 }
 
 func newOnuManager(oltMgr *oltManager, numOnus int, numUnisPerOnu int, startingUniPortNo int) *onuManager {
@@ -186,6 +186,7 @@
 		numUnisPerOnu:     numUnisPerOnu,
 		startingUniPortNo: startingUniPortNo,
 		onus:              make([]*voltha.Device, 0),
+		onuPorts:          make(map[string]map[uint32]*voltha.Port),
 	}
 }
 
@@ -198,22 +199,24 @@
 				var onu *voltha.Device
 				defer wg.Done()
 				id := fmt.Sprintf("%d-onu-%d", oltPonNum, onuID)
-				onu = &voltha.Device{Id: id, ParentId: onuM.oltMgr.olt.Id, ParentPortNo: uint32(oltPonNum)}
+				onu = &voltha.Device{Id: id, ParentId: onuM.oltMgr.oltID, ParentPortNo: uint32(oltPonNum)}
 				ponPort := &voltha.Port{Label: fmt.Sprintf("%s:pon-%d", onu.Id, onuID), PortNo: 1, DeviceId: onu.Id, Type: voltha.Port_PON_ONU}
 				ponPort.Peers = make([]*voltha.Port_PeerPort, 0)
-				peerPort := voltha.Port_PeerPort{DeviceId: onuM.oltMgr.olt.Id, PortNo: uint32(oltPonNum)}
+				peerPort := voltha.Port_PeerPort{DeviceId: onuM.oltMgr.oltID, PortNo: uint32(oltPonNum)}
 				ponPort.Peers = append(ponPort.Peers, &peerPort)
-				onu.Ports = make([]*voltha.Port, 0)
-				onu.Ports = append(onu.Ports, ponPort)
+				onuPorts := make(map[uint32]*voltha.Port)
+				onuPorts[ponPort.PortNo] = ponPort
 				for j := onuM.startingUniPortNo; j < onuM.numUnisPerOnu+onuM.startingUniPortNo; j++ {
 					uniPort := &voltha.Port{Label: fmt.Sprintf("%s:uni-%d", onu.Id, j), PortNo: uint32(oltPonNum)<<12 + uint32(onuID+1)<<4 + uint32(j), DeviceId: onu.Id, Type: voltha.Port_ETHERNET_UNI}
-					onu.Ports = append(onu.Ports, uniPort)
+					onuPorts[uniPort.PortNo] = uniPort
 				}
 				onuM.deviceLock.Lock()
 				onuM.onus = append(onuM.onus, onu)
+				onuM.onuPorts[id] = onuPorts
 				onuM.deviceLock.Unlock()
 				onuM.oltMgr.oltChnl <- onuRegistration{
-					onu:      onu,
+					onuID:    onu.Id,
+					onuPorts: onuPorts,
 					oltPonNo: uint32(oltPonNum),
 					onuPonNo: 1,
 				}
@@ -223,34 +226,30 @@
 	wg.Wait()
 	//send an empty device to indicate the end of onu registration
 	onuM.oltMgr.oltChnl <- onuRegistration{
-		onu:      nil,
+		onuPorts: nil,
 		oltPonNo: 0,
 		onuPonNo: 1,
 	}
 }
 
-func (onuM *onuManager) getOnu(deviceID string) *voltha.Device {
+func (onuM *onuManager) getOnuPorts(deviceID string) (map[uint32]*voltha.Port, bool) {
 	onuM.deviceLock.Lock()
 	defer onuM.deviceLock.Unlock()
-	for _, onu := range onuM.onus {
-		if onu.Id == deviceID {
-			return onu
-		}
-	}
-	return nil
+	ports, have := onuM.onuPorts[deviceID]
+	return ports, have
 }
 
-func (onuM *onuManager) GetDeviceHelper(ctx context.Context, id string) (*voltha.Device, error) {
+func (onuM *onuManager) ListDevicePortsHelper(ctx context.Context, id string) (map[uint32]*voltha.Port, error) {
 	if ctx.Value(testSetupPhase) != true {
 		onuM.numGetDeviceInvokedLock.Lock()
 		onuM.numGetDeviceInvoked++
 		onuM.numGetDeviceInvokedLock.Unlock()
 	}
 	if id == oltDeviceID {
-		return onuM.oltMgr.olt, nil
+		return onuM.oltMgr.oltPorts, nil
 	}
-	if onu := onuM.getOnu(id); onu != nil {
-		return onu, nil
+	if onuPorts, have := onuM.getOnuPorts(id); have {
+		return onuPorts, nil
 	}
 	return nil, errors.New("not-found")
 }
@@ -268,14 +267,13 @@
 	// Create all the devices and logical device before computing the routes in one go
 	ld := &voltha.LogicalDevice{Id: logicalDeviceID}
 	ldMgrChnl := make(chan portRegistration, numNNIPort*numPonPortOnOlt*numOnuPerOltPonPort*numUniPerOnu)
-	ldMgr := newLogicalDeviceManager(ld, ldMgrChnl, numNNIPort+numPonPortOnOlt*numOnuPerOltPonPort*numUniPerOnu, done)
+	ldMgr := newLogicalDeviceManager(ld, oltDeviceID, ldMgrChnl, numNNIPort+numPonPortOnOlt*numOnuPerOltPonPort*numUniPerOnu, done)
 	oltMgrChnl := make(chan onuRegistration, numPonPortOnOlt*numOnuPerOltPonPort)
 	oltMgr := newOltManager(oltDeviceID, ldMgr, numNNIPort, numPonPortOnOlt, oltMgrChnl)
 	onuMgr := newOnuManager(oltMgr, numOnuPerOltPonPort, numUniPerOnu, 2)
-	getDevice := onuMgr.GetDeviceHelper
 	// Start the managers.  Only the devices are created.  No routes will be built.
 	ctx := context.Background()
-	go ldMgr.start(ctx, getDevice, false)
+	go ldMgr.start(ctx, onuMgr.ListDevicePortsHelper, false)
 	go oltMgr.start()
 	go onuMgr.start(numNNIPort+1, numPonPortOnOlt)
 
@@ -316,14 +314,13 @@
 	// Create all the devices and logical device before computing the routes in one go
 	ld := &voltha.LogicalDevice{Id: logicalDeviceID}
 	ldMgrChnl := make(chan portRegistration, numNNIPort*numPonPortOnOlt*numOnuPerOltPonPort*numUniPerOnu)
-	ldMgr := newLogicalDeviceManager(ld, ldMgrChnl, numNNIPort+numPonPortOnOlt*numOnuPerOltPonPort*numUniPerOnu, done)
+	ldMgr := newLogicalDeviceManager(ld, oltDeviceID, ldMgrChnl, numNNIPort+numPonPortOnOlt*numOnuPerOltPonPort*numUniPerOnu, done)
 	oltMgrChnl := make(chan onuRegistration, numPonPortOnOlt*numOnuPerOltPonPort)
 	oltMgr := newOltManager(oltDeviceID, ldMgr, numNNIPort, numPonPortOnOlt, oltMgrChnl)
 	onuMgr := newOnuManager(oltMgr, numOnuPerOltPonPort, numUniPerOnu, 2)
-	getDevice := onuMgr.GetDeviceHelper
-
-	ctx := context.Background()
+	getDevice := onuMgr.ListDevicePortsHelper
 	// Start the managers and trigger the routes to be built as the logical ports become available
+	ctx := context.Background()
 	go ldMgr.start(ctx, getDevice, true)
 	go oltMgr.start()
 	go onuMgr.start(numNNIPort+1, numPonPortOnOlt)
@@ -362,11 +359,11 @@
 	// Create all the devices and logical device before computing the routes in one go
 	ld1 := &voltha.LogicalDevice{Id: logicalDeviceID}
 	ldMgrChnl1 := make(chan portRegistration, numNNIPort*numPonPortOnOlt*numOnuPerOltPonPort*numUniPerOnu)
-	ldMgr1 := newLogicalDeviceManager(ld1, ldMgrChnl1, numNNIPort+numPonPortOnOlt*numOnuPerOltPonPort*numUniPerOnu, done)
+	ldMgr1 := newLogicalDeviceManager(ld1, oltDeviceID, ldMgrChnl1, numNNIPort+numPonPortOnOlt*numOnuPerOltPonPort*numUniPerOnu, done)
 	oltMgrChnl1 := make(chan onuRegistration, numPonPortOnOlt*numOnuPerOltPonPort)
 	oltMgr1 := newOltManager(oltDeviceID, ldMgr1, numNNIPort, numPonPortOnOlt, oltMgrChnl1)
 	onuMgr1 := newOnuManager(oltMgr1, numOnuPerOltPonPort, numUniPerOnu, 2)
-	getDevice := onuMgr1.GetDeviceHelper
+	getDevice := onuMgr1.ListDevicePortsHelper
 	ctx := context.Background()
 	// Start the managers.  Only the devices are created.  No routes will be built.
 	go ldMgr1.start(ctx, getDevice, false)
@@ -387,7 +384,7 @@
 	// Create all the devices and logical device before computing the routes in one go
 	ld2 := &voltha.LogicalDevice{Id: logicalDeviceID}
 	ldMgrChnl2 := make(chan portRegistration, numNNIPort*numPonPortOnOlt*numOnuPerOltPonPort*numUniPerOnu)
-	ldMgr2 := newLogicalDeviceManager(ld2, ldMgrChnl2, numNNIPort+numPonPortOnOlt*numOnuPerOltPonPort*numUniPerOnu, done)
+	ldMgr2 := newLogicalDeviceManager(ld2, oltDeviceID, ldMgrChnl2, numNNIPort+numPonPortOnOlt*numOnuPerOltPonPort*numUniPerOnu, done)
 	oltMgrChnl2 := make(chan onuRegistration, numPonPortOnOlt*numOnuPerOltPonPort)
 	oltMgr2 := newOltManager(oltDeviceID, ldMgr2, numNNIPort, numPonPortOnOlt, oltMgrChnl2)
 	onuMgr2 := newOnuManager(oltMgr2, numOnuPerOltPonPort, numUniPerOnu, 2)
diff --git a/tests/core/api/grpc_nbi_api_handler_client_test.go b/tests/core/api/grpc_nbi_api_handler_client_test.go
deleted file mode 100644
index b70531a..0000000
--- a/tests/core/api/grpc_nbi_api_handler_client_test.go
+++ /dev/null
@@ -1,677 +0,0 @@
-// +build integration
-
-/*
- * Copyright 2018-present Open Networking Foundation
-
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
-
- * http://www.apache.org/licenses/LICENSE-2.0
-
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package api
-
-import (
-	"context"
-	"fmt"
-	"os"
-	"os/exec"
-	"strings"
-	"testing"
-	"time"
-
-	"github.com/golang/protobuf/ptypes/empty"
-	com "github.com/opencord/voltha-lib-go/v3/pkg/adapters/common"
-	"github.com/opencord/voltha-lib-go/v3/pkg/log"
-	"github.com/opencord/voltha-protos/v3/go/common"
-	"github.com/opencord/voltha-protos/v3/go/openflow_13"
-	"github.com/opencord/voltha-protos/v3/go/voltha"
-	"github.com/stretchr/testify/assert"
-	"google.golang.org/grpc"
-	"google.golang.org/grpc/codes"
-	"google.golang.org/grpc/metadata"
-	"google.golang.org/grpc/status"
-)
-
-var conn *grpc.ClientConn
-var stub voltha.VolthaServiceClient
-var testMode string
-
-/*
-Prerequite:  These tests require the rw_core to run prior to executing these test cases.
-*/
-
-var devices map[string]*voltha.Device
-
-func setup() {
-	//Start kafka and Etcd
-	startKafka()
-	startEtcd()
-	time.Sleep(10 * time.Second) //TODO: Find a better way to ascertain they are up
-
-	stub = setupGrpcConnection()
-	testMode = common.TestModeKeys_api_test.String()
-	devices = make(map[string]*voltha.Device)
-}
-
-func setupGrpcConnection() voltha.VolthaServiceClient {
-	grpcHostIP := os.Getenv("DOCKER_HOST_IP")
-	grpcPort := 50057
-	grpcHost := fmt.Sprintf("%s:%d", grpcHostIP, grpcPort)
-	var err error
-	conn, err = grpc.Dial(grpcHost, grpc.WithInsecure())
-	if err != nil {
-		logger.Fatalf(ctx, "did not connect: %s", err)
-	}
-	return voltha.NewVolthaServiceClient(conn)
-}
-
-func clearAllDevices(clearMap bool) {
-	for key, _ := range devices {
-		ctx := context.Background()
-		response, err := stub.DeleteDevice(ctx, &voltha.ID{Id: key})
-		logger.Infow(ctx, "response", log.Fields{"res": response, "error": err})
-		if clearMap {
-			delete(devices, key)
-		}
-	}
-}
-
-// Verify if all ids are present in the global list of devices
-func hasAllIds(ids *voltha.IDs) bool {
-	if ids == nil && len(devices) == 0 {
-		return true
-	}
-	if ids == nil {
-		return false
-	}
-	for _, id := range ids.Items {
-		if _, exist := devices[id.Id]; !exist {
-			return false
-		}
-	}
-	return true
-}
-
-func startKafka() {
-	fmt.Println("Starting Kafka and Etcd ...")
-	command := "docker-compose"
-	cmd := exec.Command(command, "-f", "../../../compose/docker-compose-zk-kafka-test.yml", "up", "-d")
-	if err := cmd.Run(); err != nil {
-		logger.Fatal(ctx, err)
-	}
-}
-
-func startEtcd() {
-	fmt.Println("Starting Etcd ...")
-	command := "docker-compose"
-	cmd := exec.Command(command, "-f", "../../../compose/docker-compose-etcd.yml", "up", "-d")
-	if err := cmd.Run(); err != nil {
-		logger.Fatal(ctx, err)
-	}
-}
-
-func stopKafka() {
-	fmt.Println("Stopping Kafka and Etcd ...")
-	command := "docker-compose"
-	cmd := exec.Command(command, "-f", "../../../compose/docker-compose-zk-kafka-test.yml", "down")
-	if err := cmd.Run(); err != nil {
-		// ignore error - as this is mostly due network being left behind as its being used by other
-		// containers
-		logger.Warn(ctx, err)
-	}
-}
-
-func stopEtcd() {
-	fmt.Println("Stopping Etcd ...")
-	command := "docker-compose"
-	cmd := exec.Command(command, "-f", "../../../compose/docker-compose-etcd.yml", "down")
-	if err := cmd.Run(); err != nil {
-		// ignore error - as this is mostly due network being left behind as its being used by other
-		// containers
-		logger.Warn(ctx, err)
-	}
-}
-
-func startCore() {
-	fmt.Println("Starting voltha core ...")
-	command := "docker-compose"
-	cmd := exec.Command(command, "-f", "../../../compose/rw_core.yml", "up", "-d")
-	if err := cmd.Run(); err != nil {
-		logger.Fatal(ctx, err)
-	}
-}
-
-func stopCore() {
-	fmt.Println("Stopping voltha core ...")
-	command := "docker-compose"
-	cmd := exec.Command(command, "-f", "../../../compose/rw_core.yml", "down")
-	if err := cmd.Run(); err != nil {
-		// ignore error - as this is mostly due network being left behind as its being used by other
-		// containers
-		logger.Warn(ctx, err)
-	}
-}
-
-func startSimulatedOLTAndONUAdapters() {
-	fmt.Println("Starting simulated OLT and ONU adapters ...")
-	command := "docker-compose"
-	cmd := exec.Command(command, "-f", "../../../compose/adapters-simulated.yml", "up", "-d")
-	if err := cmd.Run(); err != nil {
-		logger.Fatal(ctx, err)
-	}
-}
-
-func stopSimulatedOLTAndONUAdapters() {
-	fmt.Println("Stopping simulated OLT and ONU adapters ...")
-	command := "docker-compose"
-	cmd := exec.Command(command, "-f", "../../../compose/adapters-simulated.yml", "down")
-	if err := cmd.Run(); err != nil {
-		// ignore error - as this is mostly due network being left behind as its being used by other
-		// containers
-		logger.Warn(ctx, err)
-	}
-}
-
-func TestListDeviceIds(t *testing.T) {
-	fmt.Println("Testing list Devices Ids ...")
-	//0. Start kafka and Ectd
-	startKafka()
-	startEtcd()
-
-	//1. Start the core
-	startCore()
-
-	// Wait until it's up - TODO: find a better way to check
-	time.Sleep(10 * time.Second)
-
-	//2. Create a set of devices into the Core
-	for i := 0; i < 10; i++ {
-		ctx := context.Background()
-		device := &voltha.Device{Type: "simulated_olt"}
-		response, err := stub.CreateDevice(ctx, device)
-		logger.Infow(ctx, "response", log.Fields{"res": response, "error": err})
-		assert.NotNil(t, response)
-		assert.Nil(t, err)
-		devices[response.Id] = response
-	}
-
-	//3. Verify devices have been added correctly
-	ctx := context.Background()
-	response, err := stub.ListDeviceIds(ctx, &empty.Empty{})
-	logger.Infow(ctx, "response", log.Fields{"res": response, "error": err})
-	assert.Nil(t, err)
-	assert.True(t, hasAllIds(response))
-
-	//4. Stop the core
-	stopCore()
-
-	//5. Stop Kafka and Etcd
-	stopKafka()
-	stopEtcd()
-}
-
-func TestReconcileDevices(t *testing.T) {
-	fmt.Println("Testing Reconcile Devices ...")
-
-	//0. Start kafka and Ectd
-	startKafka()
-	startEtcd()
-
-	//1. Start the core
-	startCore()
-
-	// Wait until it's up - TODO: find a better way to check
-	time.Sleep(10 * time.Second)
-
-	//2. Create a set of devices into the Core
-	for i := 0; i < 10; i++ {
-		ctx := context.Background()
-		device := &voltha.Device{Type: "simulated_olt"}
-		response, err := stub.CreateDevice(ctx, device)
-		logger.Infow(ctx, "response", log.Fields{"res": response, "error": err})
-		assert.Nil(t, err)
-		devices[response.Id] = response
-	}
-	//3. Verify devices have been added correctly
-	ctx := context.Background()
-	response, err := stub.ListDeviceIds(ctx, &empty.Empty{})
-	logger.Infow(ctx, "response", log.Fields{"res": response, "error": err})
-	assert.Nil(t, err)
-	assert.True(t, hasAllIds(response))
-
-	//4. Stop the core and restart it. This will start the core with no data in memory but
-	// etcd will still have the data.
-	stopCore()
-	time.Sleep(5 * time.Second)
-	startCore()
-	time.Sleep(10 * time.Second)
-
-	//5. Setup the connection again
-	stub = setupGrpcConnection()
-
-	//6. Verify there are no devices left
-	ctx = context.Background()
-	response, err = stub.ListDeviceIds(ctx, &empty.Empty{})
-	logger.Infow(ctx, "response", log.Fields{"res": response, "error": err})
-	assert.Nil(t, err)
-	assert.Equal(t, len(response.Items), 0)
-
-	//7. Invoke reconcile with all stored list
-	toRestore := &voltha.IDs{Items: make([]*voltha.ID, 0)}
-	for key, _ := range devices {
-		toRestore.Items = append(toRestore.Items, &voltha.ID{Id: key})
-	}
-	ctx = context.Background()
-	_, err = stub.ReconcileDevices(ctx, toRestore)
-	assert.Nil(t, err)
-
-	//8. Verify all devices have been restored
-	ctx = context.Background()
-	response, err = stub.ListDeviceIds(ctx, &empty.Empty{})
-	logger.Infow(ctx, "response", log.Fields{"res": response, "error": err})
-	assert.Nil(t, err)
-	assert.True(t, hasAllIds(response))
-
-	for _, id := range response.Items {
-		fmt.Println("id", id.Id)
-	}
-
-	//9. Store the core
-	stopCore()
-
-	//10. Stop Kafka and Etcd
-	stopKafka()
-	stopEtcd()
-}
-
-func TestDeviceManagement(t *testing.T) {
-	fmt.Println("Testing Device Management ...")
-
-	numberOfOLTDevices := 1
-
-	//0. Start kafka and Ectd
-	startKafka()
-	startEtcd()
-
-	//1. Start the core
-	startCore()
-
-	//2. Start the simulated adapters
-	startSimulatedOLTAndONUAdapters()
-
-	// Wait until the core and adapters sync up
-	time.Sleep(10 * time.Second)
-
-	//3. Create a set of devices into the Core
-	devices = make(map[string]*voltha.Device)
-	logicalDevices := make(map[string]*voltha.LogicalDevice)
-	for i := 0; i < numberOfOLTDevices; i++ {
-		ctx := context.Background()
-		randomMacAddress := strings.ToUpper(com.GetRandomMacAddress())
-		device := &voltha.Device{Type: "simulated_olt", MacAddress: randomMacAddress}
-		response, err := stub.CreateDevice(ctx, device)
-		logger.Infow(ctx, "response", log.Fields{"res": response, "error": err})
-		assert.Nil(t, err)
-		devices[response.Id] = response
-	}
-
-	//4. Enable all the devices
-	for id, _ := range devices {
-		ctx := context.Background()
-		response, err := stub.EnableDevice(ctx, &common.ID{Id: id})
-		logger.Infow(ctx, "response", log.Fields{"res": response, "error": err})
-		assert.Nil(t, err)
-	}
-
-	// Wait until all devices have been enabled
-	if numberOfOLTDevices < 5 {
-		time.Sleep(3 * time.Second)
-	} else if numberOfOLTDevices < 20 {
-		time.Sleep(20 * time.Second)
-	} else {
-		time.Sleep(30 * time.Second)
-	}
-	//time.Sleep(1 * time.Second * time.Duration(numberOfDevices))
-
-	//5. Verify that all devices are in enabled state
-	ctx := context.Background()
-	response, err := stub.ListDevices(ctx, &empty.Empty{})
-	logger.Infow(ctx, "response", log.Fields{"res": response, "error": err})
-	assert.Nil(t, err)
-	assert.Equal(t, len(devices)*2, len(response.Items))
-	for _, d := range response.Items {
-		devices[d.Id] = d
-		assert.Equal(t, d.AdminState, voltha.AdminState_ENABLED)
-	}
-
-	//6. Get the logical devices
-	ctx = context.Background()
-	lresponse, lerr := stub.ListLogicalDevices(ctx, &empty.Empty{})
-	logger.Infow(ctx, "response", log.Fields{"res": response, "error": lerr})
-	assert.Nil(t, lerr)
-	assert.Equal(t, numberOfOLTDevices, len(lresponse.Items))
-	for _, ld := range lresponse.Items {
-		logicalDevices[ld.Id] = ld
-		// Ensure each logical device have two ports
-		ports, err := stub.ListLogicalDevicePorts(ctx, &voltha.ID{Id: ld.Id})
-		assert.Nil(t, err)
-		assert.Equal(t, 2, len(ports.Items))
-	}
-
-	//7. Disable all ONUs & check status & check logical device
-	for id, d := range devices {
-		ctx := context.Background()
-		if d.Type == "simulated_onu" {
-			response, err := stub.DisableDevice(ctx, &common.ID{Id: id})
-			logger.Infow(ctx, "response", log.Fields{"res": response, "error": err})
-			assert.Nil(t, err)
-		}
-	}
-
-	// Wait for all the changes to be populated
-	time.Sleep(3 * time.Second)
-
-	ctx = context.Background()
-	response, err = stub.ListDevices(ctx, &empty.Empty{})
-	logger.Infow(ctx, "response", log.Fields{"res": response, "error": err})
-	assert.Nil(t, err)
-	assert.Equal(t, len(devices), len(response.Items))
-	for _, d := range response.Items {
-		if d.Type == "simulated_onu" {
-			assert.Equal(t, d.AdminState, voltha.AdminState_DISABLED)
-			devices[d.Id] = d
-		} else {
-			assert.Equal(t, d.AdminState, voltha.AdminState_ENABLED)
-		}
-	}
-
-	ctx = context.Background()
-	lresponse, lerr = stub.ListLogicalDevices(ctx, &empty.Empty{})
-	logger.Infow(ctx, "response", log.Fields{"res": response, "error": lerr})
-	assert.Nil(t, lerr)
-	assert.Equal(t, numberOfOLTDevices, len(lresponse.Items))
-	for _, ld := range lresponse.Items {
-		logicalDevices[ld.Id] = ld
-		// Ensure each logical device have one port - only olt port
-		ports, err := stub.ListLogicalDevicePorts(ctx, &common.ID{Id: ld.Id})
-		assert.Nil(t, err)
-		assert.Equal(t, 1, len(ports.Items))
-	}
-
-	//8. Enable all ONUs & check status & check logical device
-	for id, d := range devices {
-		ctx := context.Background()
-		if d.Type == "simulated_onu" {
-			response, err := stub.EnableDevice(ctx, &common.ID{Id: id})
-			logger.Infow(ctx, "response", log.Fields{"res": response, "error": err})
-			assert.Nil(t, err)
-		}
-	}
-
-	// Wait for all the changes to be populated
-	time.Sleep(3 * time.Second)
-
-	ctx = context.Background()
-	response, err = stub.ListDevices(ctx, &empty.Empty{})
-	logger.Infow(ctx, "response", log.Fields{"res": response, "error": err})
-	assert.Nil(t, err)
-	assert.Equal(t, len(devices), len(response.Items))
-	for _, d := range response.Items {
-		assert.Equal(t, d.AdminState, voltha.AdminState_ENABLED)
-		devices[d.Id] = d
-	}
-
-	//ctx = context.Background()
-	//lresponse, lerr = stub.ListLogicalDevices(ctx, &empty.Empty{})
-	//logger.Infow(ctx, "response", log.Fields{"res": response, "error": lerr})
-	//assert.Nil(t, lerr)
-	//assert.Equal(t, numberOfOLTDevices, len(lresponse.Items))
-	//for _, ld := range (lresponse.Items) {
-	//	logicalDevices[ld.Id] = ld
-	//	// Ensure each logical device have two ports
-	//	assert.Equal(t, 2, len(ld.Ports))
-	//}
-
-	//9. Disable all OLTs & check status & check logical device
-
-	//10. Enable all OLTs & Enable all ONUs & check status & check logical device
-
-	//11. Disable all OLTs & check status & check logical device
-
-	//12. Delete all Devices & check status & check logical device
-
-	////13. Store simulated adapters
-	//stopSimulatedOLTAndONUAdapters()
-	//
-	////14. Store the core
-	//stopCore()
-	//
-	////15. Stop Kafka and Etcd
-	//stopKafka()
-	//stopEtcd()
-}
-
-func TestGetDevice(t *testing.T) {
-	var id common.ID
-	id.Id = "anyid"
-	ctx := metadata.NewOutgoingContext(context.Background(), metadata.Pairs(testMode, "true"))
-	response, err := stub.GetDevice(ctx, &id)
-	assert.Nil(t, response)
-	st, _ := status.FromError(err)
-	assert.Equal(t, id.Id, st.Message())
-	assert.Equal(t, codes.NotFound, st.Code())
-}
-
-func TestUpdateLogLevelError(t *testing.T) {
-	ctx := metadata.NewOutgoingContext(context.Background(), metadata.Pairs(testMode, "true"))
-	level := voltha.Logging{PackageName: "github.com/opencord/voltha-go/rw_core/core", Level: common.LogLevel_ERROR}
-	response, err := stub.UpdateLogLevel(ctx, &level)
-	logger.Infow(ctx, "response", log.Fields{"res": response, "error": err})
-	assert.Equal(t, &empty.Empty{}, response)
-	assert.Nil(t, err)
-}
-
-func TestGetVoltha(t *testing.T) {
-	ctx := metadata.NewOutgoingContext(context.Background(), metadata.Pairs(testMode, "true"))
-	response, err := stub.GetVoltha(ctx, &empty.Empty{})
-	assert.Nil(t, response)
-	st, _ := status.FromError(err)
-	assert.Equal(t, "UnImplemented", st.Message())
-}
-
-func TestUpdateLogLevelDebug(t *testing.T) {
-	ctx := metadata.NewOutgoingContext(context.Background(), metadata.Pairs(testMode, "true"))
-	level := voltha.Logging{PackageName: "github.com/opencord/voltha-go/rw_core/core", Level: common.LogLevel_DEBUG}
-	response, err := stub.UpdateLogLevel(ctx, &level)
-	logger.Infow(ctx, "response", log.Fields{"res": response, "error": err})
-	assert.Equal(t, &empty.Empty{}, response)
-	assert.Nil(t, err)
-}
-
-func TestGetCoreInstance(t *testing.T) {
-	id := &voltha.ID{Id: "getCoreInstance"}
-	ctx := metadata.NewOutgoingContext(context.Background(), metadata.Pairs(testMode, "true"))
-	response, err := stub.GetCoreInstance(ctx, id)
-	assert.Nil(t, response)
-	st, _ := status.FromError(err)
-	assert.Equal(t, "UnImplemented", st.Message())
-}
-
-func TestGetLogicalDevice(t *testing.T) {
-	id := &voltha.ID{Id: "getLogicalDevice"}
-	ctx := metadata.NewOutgoingContext(context.Background(), metadata.Pairs(testMode, "true"))
-	response, err := stub.GetLogicalDevice(ctx, id)
-	assert.Nil(t, response)
-	st, _ := status.FromError(err)
-	assert.Equal(t, id.Id, st.Message())
-	assert.Equal(t, codes.NotFound, st.Code())
-}
-
-func TestGetLogicalDevicePort(t *testing.T) {
-	id := &voltha.LogicalPortId{Id: "GetLogicalDevicePort"}
-	ctx := metadata.NewOutgoingContext(context.Background(), metadata.Pairs(testMode, "true"))
-	response, err := stub.GetLogicalDevicePort(ctx, id)
-	assert.Nil(t, response)
-	st, _ := status.FromError(err)
-	assert.Equal(t, "UnImplemented", st.Message())
-}
-
-func TestListLogicalDevicePorts(t *testing.T) {
-	id := &voltha.ID{Id: "listLogicalDevicePorts"}
-	ctx := metadata.NewOutgoingContext(context.Background(), metadata.Pairs(testMode, "true"))
-	response, err := stub.ListLogicalDevicePorts(ctx, id)
-	assert.Nil(t, response)
-	st, _ := status.FromError(err)
-	assert.Equal(t, "UnImplemented", st.Message())
-}
-
-func TestListLogicalDeviceFlows(t *testing.T) {
-	id := &voltha.ID{Id: "ListLogicalDeviceFlows"}
-	ctx := metadata.NewOutgoingContext(context.Background(), metadata.Pairs(testMode, "true"))
-	response, err := stub.ListLogicalDeviceFlows(ctx, id)
-	assert.Nil(t, response)
-	st, _ := status.FromError(err)
-	assert.Equal(t, "UnImplemented", st.Message())
-}
-
-func TestListLogicalDeviceFlowGroups(t *testing.T) {
-	id := &voltha.ID{Id: "ListLogicalDeviceFlowGroups"}
-	ctx := metadata.NewOutgoingContext(context.Background(), metadata.Pairs(testMode, "true"))
-	response, err := stub.ListLogicalDeviceFlowGroups(ctx, id)
-	assert.Nil(t, response)
-	st, _ := status.FromError(err)
-	assert.Equal(t, "UnImplemented", st.Message())
-}
-
-func TestListDevices(t *testing.T) {
-	ctx := metadata.NewOutgoingContext(context.Background(), metadata.Pairs(testMode, "true"))
-	response, _ := stub.ListDevices(ctx, &empty.Empty{})
-	assert.Equal(t, len(response.Items), 0)
-}
-
-func TestListAdapters(t *testing.T) {
-	ctx := metadata.NewOutgoingContext(context.Background(), metadata.Pairs(testMode, "true"))
-	response, err := stub.ListAdapters(ctx, &empty.Empty{})
-	assert.Nil(t, response)
-	st, _ := status.FromError(err)
-	assert.Equal(t, "UnImplemented", st.Message())
-}
-
-func TestListLogicalDevices(t *testing.T) {
-	ctx := metadata.NewOutgoingContext(context.Background(), metadata.Pairs(testMode, "true"))
-	response, _ := stub.ListLogicalDevices(ctx, &empty.Empty{})
-	assert.Equal(t, len(response.Items), 0)
-}
-
-func TestListCoreInstances(t *testing.T) {
-	ctx := metadata.NewOutgoingContext(context.Background(), metadata.Pairs(testMode, "true"))
-	response, err := stub.ListCoreInstances(ctx, &empty.Empty{})
-	assert.Nil(t, response)
-	st, _ := status.FromError(err)
-	assert.Equal(t, "UnImplemented", st.Message())
-}
-
-func TestCreateDevice(t *testing.T) {
-	ctx := metadata.NewOutgoingContext(context.Background(), metadata.Pairs(testMode, "true"))
-	device := &voltha.Device{Id: "newdevice"}
-	response, err := stub.CreateDevice(ctx, device)
-	logger.Infow(ctx, "response", log.Fields{"res": response, "error": err})
-	assert.Equal(t, &voltha.Device{Id: "newdevice"}, response)
-	assert.Nil(t, err)
-}
-
-func TestEnableDevice(t *testing.T) {
-	ctx := metadata.NewOutgoingContext(context.Background(), metadata.Pairs(testMode, "true"))
-	id := &voltha.ID{Id: "enabledevice"}
-	response, err := stub.EnableDevice(ctx, id)
-	logger.Infow(ctx, "response", log.Fields{"res": response, "error": err})
-	assert.Equal(t, &empty.Empty{}, response)
-	assert.Nil(t, err)
-}
-
-func TestDisableDevice(t *testing.T) {
-	ctx := metadata.NewOutgoingContext(context.Background(), metadata.Pairs(testMode, "true"))
-	id := &voltha.ID{Id: "DisableDevice"}
-	response, err := stub.DisableDevice(ctx, id)
-	logger.Infow(ctx, "response", log.Fields{"res": response, "error": err})
-	assert.Equal(t, &empty.Empty{}, response)
-	assert.Nil(t, err)
-}
-
-func TestRebootDevice(t *testing.T) {
-	ctx := metadata.NewOutgoingContext(context.Background(), metadata.Pairs(testMode, "true"))
-	id := &voltha.ID{Id: "RebootDevice"}
-	response, err := stub.RebootDevice(ctx, id)
-	logger.Infow(ctx, "response", log.Fields{"res": response, "error": err})
-	assert.Equal(t, &empty.Empty{}, response)
-	assert.Nil(t, err)
-}
-
-func TestDeleteDevice(t *testing.T) {
-	ctx := metadata.NewOutgoingContext(context.Background(), metadata.Pairs(testMode, "true"))
-	id := &voltha.ID{Id: "DeleteDevice"}
-	response, err := stub.DeleteDevice(ctx, id)
-	logger.Infow(ctx, "response", log.Fields{"res": response, "error": err})
-	assert.Equal(t, &empty.Empty{}, response)
-	assert.Nil(t, err)
-}
-
-func TestEnableLogicalDevicePort(t *testing.T) {
-	ctx := metadata.NewOutgoingContext(context.Background(), metadata.Pairs(testMode, "true"))
-	id := &voltha.LogicalPortId{Id: "EnableLogicalDevicePort"}
-	response, err := stub.EnableLogicalDevicePort(ctx, id)
-	if e, ok := status.FromError(err); ok {
-		logger.Infow(ctx, "response", log.Fields{"error": err, "errorcode": e.Code(), "msg": e.Message()})
-	}
-	logger.Infow(ctx, "response", log.Fields{"res": response, "error": err})
-	assert.Equal(t, &empty.Empty{}, response)
-	assert.Nil(t, err)
-}
-
-func TestDisableLogicalDevicePort(t *testing.T) {
-	ctx := metadata.NewOutgoingContext(context.Background(), metadata.Pairs(testMode, "true"))
-	id := &voltha.LogicalPortId{Id: "DisableLogicalDevicePort"}
-	response, err := stub.DisableLogicalDevicePort(ctx, id)
-	logger.Infow(ctx, "response", log.Fields{"res": response, "error": err})
-	assert.Equal(t, &empty.Empty{}, response)
-	assert.Nil(t, err)
-}
-
-func TestUpdateLogicalDeviceFlowGroupTable(t *testing.T) {
-	ctx := metadata.NewOutgoingContext(context.Background(), metadata.Pairs(testMode, "true"))
-	flow := &openflow_13.FlowGroupTableUpdate{Id: "UpdateLogicalDeviceFlowGroupTable"}
-	response, err := stub.UpdateLogicalDeviceFlowGroupTable(ctx, flow)
-	logger.Infow(ctx, "response", log.Fields{"res": response, "error": err})
-	assert.Equal(t, &empty.Empty{}, response)
-	assert.Nil(t, err)
-}
-
-func TestGetImageDownloadStatus(t *testing.T) {
-	ctx := metadata.NewOutgoingContext(context.Background(), metadata.Pairs(testMode, "true"))
-	img := &voltha.ImageDownload{Id: "GetImageDownloadStatus"}
-	response, err := stub.GetImageDownloadStatus(ctx, img)
-	assert.Nil(t, response)
-	st, _ := status.FromError(err)
-	assert.Equal(t, "UnImplemented", st.Message())
-}
-
-// TODO: complete the remaining tests
-
-func shutdown() {
-	conn.Close()
-}
-
-func TestMain(m *testing.M) {
-	setup()
-	code := m.Run()
-	shutdown()
-	os.Exit(code)
-}
diff --git a/tests/core/common.go b/tests/core/common.go
deleted file mode 100644
index b96b648..0000000
--- a/tests/core/common.go
+++ /dev/null
@@ -1,33 +0,0 @@
-// +build integration
-
-/*
- * Copyright 2020-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package core
-
-import (
-	"github.com/opencord/voltha-lib-go/v3/pkg/log"
-)
-
-var logger log.CLogger
-
-func init() {
-	// Setup this package so that it's log level can be modified at run time
-	var err error
-	logger, err = log.RegisterPackage(log.JSON, log.ErrorLevel, log.Fields{"pkg": "core"})
-	if err != nil {
-		panic(err)
-	}
-}
diff --git a/tests/core/concurrency/common_test.go b/tests/core/concurrency/common_test.go
deleted file mode 100644
index ccf2126..0000000
--- a/tests/core/concurrency/common_test.go
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2020-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package concurrency
-
-import (
-	"github.com/opencord/voltha-lib-go/v3/pkg/log"
-)
-
-var logger log.Logger
-
-func init() {
-	// Setup this package so that it's log level can be modified at run time
-	var err error
-	logger, err = log.AddPackage(log.JSON, log.ErrorLevel, log.Fields{"pkg": "concurrency"})
-	if err != nil {
-		panic(err)
-	}
-}
diff --git a/tests/core/concurrency/core_concurrency_test.go b/tests/core/concurrency/core_concurrency_test.go
deleted file mode 100644
index 87d4e82..0000000
--- a/tests/core/concurrency/core_concurrency_test.go
+++ /dev/null
@@ -1,375 +0,0 @@
-// +build integration
-
-/*
- * Copyright 2018-present Open Networking Foundation
-
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
-
- * http://www.apache.org/licenses/LICENSE-2.0
-
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package concurrency
-
-import (
-	"context"
-	"errors"
-	"fmt"
-	"os"
-	"os/exec"
-	"strings"
-	"testing"
-
-	"github.com/golang/protobuf/ptypes/empty"
-	"github.com/google/uuid"
-	com "github.com/opencord/voltha-lib-go/v3/pkg/adapters/common"
-	"github.com/opencord/voltha-lib-go/v3/pkg/log"
-	"github.com/opencord/voltha-protos/v3/go/common"
-	"github.com/opencord/voltha-protos/v3/go/voltha"
-	"github.com/stretchr/testify/assert"
-	"google.golang.org/grpc"
-	"google.golang.org/grpc/metadata"
-)
-
-var conns []*grpc.ClientConn
-var stubs []voltha.VolthaServiceClient
-var volthaSerialNumberKey string
-var grpcPorts []int
-
-/*
- This series of tests are executed with two RW_Cores
-*/
-
-var devices map[string]*voltha.Device
-
-func setup() {
-	grpcPorts = []int{50057, 50058}
-	stubs = make([]voltha.VolthaServiceClient, 0)
-	conns = make([]*grpc.ClientConn, 0)
-
-	volthaSerialNumberKey = "voltha_serial_number"
-	devices = make(map[string]*voltha.Device)
-}
-
-func connectToCore(port int) (voltha.VolthaServiceClient, error) {
-	grpcHostIP := os.Getenv("DOCKER_HOST_IP")
-	grpcHost := fmt.Sprintf("%s:%d", grpcHostIP, port)
-	conn, err := grpc.Dial(grpcHost, grpc.WithInsecure())
-	if err != nil {
-		logger.Fatalf(ctx, "did not connect: %s", err)
-		return nil, errors.New("failure-to-connect")
-	}
-	conns = append(conns, conn)
-	return voltha.NewVolthaServiceClient(conn), nil
-}
-
-func setupGrpcConnection() []voltha.VolthaServiceClient {
-	// We have 2 concurrent cores.  Connect to them
-	for _, port := range grpcPorts {
-		if client, err := connectToCore(port); err == nil {
-			stubs = append(stubs, client)
-			logger.Infow(ctx, "connected", log.Fields{"port": port})
-		}
-	}
-	return stubs
-}
-
-func clearAllDevices(clearMap bool) {
-	for key, _ := range devices {
-		ctx := context.Background()
-		response, err := stubs[1].DeleteDevice(ctx, &voltha.ID{Id: key})
-		logger.Infow(ctx, "response", log.Fields{"res": response, "error": err})
-		if clearMap {
-			delete(devices, key)
-		}
-	}
-}
-
-// Verify if all ids are present in the global list of devices
-func hasAllIds(ids *voltha.IDs) bool {
-	if ids == nil && len(devices) == 0 {
-		return true
-	}
-	if ids == nil {
-		return false
-	}
-	for _, id := range ids.Items {
-		if _, exist := devices[id.Id]; !exist {
-			return false
-		}
-	}
-	return true
-}
-
-func startKafka() {
-	fmt.Println("Starting Kafka and Etcd ...")
-	command := "docker-compose"
-	cmd := exec.Command(command, "-f", "../../../compose/docker-compose-zk-kafka-test.yml", "up", "-d")
-	if err := cmd.Run(); err != nil {
-		logger.Fatal(ctx, err)
-	}
-}
-
-func startEtcd() {
-	fmt.Println("Starting Etcd ...")
-	command := "docker-compose"
-	cmd := exec.Command(command, "-f", "../../../compose/docker-compose-etcd.yml", "up", "-d")
-	if err := cmd.Run(); err != nil {
-		logger.Fatal(ctx, err)
-	}
-}
-
-func stopKafka() {
-	fmt.Println("Stopping Kafka and Etcd ...")
-	command := "docker-compose"
-	cmd := exec.Command(command, "-f", "../../../compose/docker-compose-zk-kafka-test.yml", "down")
-	if err := cmd.Run(); err != nil {
-		// ignore error - as this is mostly due network being left behind as its being used by other
-		// containers
-		logger.Warn(ctx, err)
-	}
-}
-
-func stopEtcd() {
-	fmt.Println("Stopping Etcd ...")
-	command := "docker-compose"
-	cmd := exec.Command(command, "-f", "../../../compose/docker-compose-etcd.yml", "down")
-	if err := cmd.Run(); err != nil {
-		// ignore error - as this is mostly due network being left behind as its being used by other
-		// containers
-		logger.Warn(ctx, err)
-	}
-}
-
-func startCores() {
-	fmt.Println("Starting voltha cores ...")
-	command := "docker-compose"
-	cmd := exec.Command(command, "-f", "../../../compose/rw_core_concurrency_test.yml", "up", "-d")
-	if err := cmd.Run(); err != nil {
-		logger.Fatal(ctx, err)
-	}
-}
-
-func stopCores() {
-	fmt.Println("Stopping voltha cores ...")
-	command := "docker-compose"
-	cmd := exec.Command(command, "-f", "../../../compose/rw_core_concurrency_test.yml", "down")
-	if err := cmd.Run(); err != nil {
-		// ignore error - as this is mostly due network being left behind as its being used by other
-		// containers
-		logger.Warn(ctx, err)
-	}
-}
-
-func startSimulatedOLTAndONUAdapters() {
-	fmt.Println("Starting simulated OLT and ONU adapters ...")
-	command := "docker-compose"
-	cmd := exec.Command(command, "-f", "../../../compose/adapters-simulated.yml", "up", "-d")
-	if err := cmd.Run(); err != nil {
-		logger.Fatal(ctx, err)
-	}
-}
-
-func stopSimulatedOLTAndONUAdapters() {
-	fmt.Println("Stopping simulated OLT and ONU adapters ...")
-	command := "docker-compose"
-	cmd := exec.Command(command, "-f", "../../../compose/adapters-simulated.yml", "down")
-	if err := cmd.Run(); err != nil {
-		// ignore error - as this is mostly due network being left behind as its being used by other
-		// containers
-		logger.Warn(ctx, err)
-	}
-}
-
-func sendCreateDeviceRequest(ctx context.Context, stub voltha.VolthaServiceClient, device *voltha.Device, ch chan interface{}) {
-	fmt.Println("Sending  create device ...")
-	if response, err := stub.CreateDevice(ctx, device); err != nil {
-		ch <- err
-	} else {
-		ch <- response
-	}
-}
-
-func sendEnableDeviceRequest(ctx context.Context, stub voltha.VolthaServiceClient, deviceId string, ch chan interface{}) {
-	fmt.Println("Sending enable device ...")
-	if response, err := stub.EnableDevice(ctx, &common.ID{Id: deviceId}); err != nil {
-		ch <- err
-	} else {
-		ch <- response
-	}
-}
-
-//// createPonsimDevice sends two requests to each core and waits for both responses
-//func createPonsimDevice(stubs []voltha.VolthaServiceClient) (*voltha.Device, error) {
-//	ui := uuid.New()
-//	ctx := metadata.NewOutgoingContext(context.Background(), metadata.Pairs(volthaSerialNumberKey, ui.String()))
-//	//preprovision_olt -t ponsim_olt -H 172.20.0.11:50060
-//	device := &voltha.Device{Type: "ponsim_olt"}
-//	device.Address = &voltha.Device_HostAndPort{HostAndPort:"172.20.0.11:50060"}
-//	ch := make(chan interface{})
-//	defer close(ch)
-//	requestNum := 0
-//	for _, stub := range stubs {
-//		go sendCreateDeviceRequest(ctx, stub, device, ch)
-//		requestNum += 1
-//	}
-//	fmt.Println("Waiting for create device response ...")
-//	receivedResponse := 0
-//	var err error
-//	var returnedDevice *voltha.Device
-//	select {
-//	case res, ok := <-ch:
-//		receivedResponse += 1
-//		if !ok {
-//		} else if er, ok := res.(error); ok {
-//			err = er
-//		} else if d, ok := res.(*voltha.Device); ok {
-//			returnedDevice = d
-//		}
-//		if receivedResponse == requestNum {
-//			break
-//		}
-//	}
-//	if returnedDevice != nil {
-//		return returnedDevice, nil
-//	}
-//	return nil, err
-//}
-
-// createDevice sends two requests to each core and waits for both responses
-func createDevice(stubs []voltha.VolthaServiceClient) (*voltha.Device, error) {
-	ui := uuid.New()
-	ctx := metadata.NewOutgoingContext(context.Background(), metadata.Pairs(volthaSerialNumberKey, ui.String()))
-	randomMacAddress := strings.ToUpper(com.GetRandomMacAddress())
-	device := &voltha.Device{Type: "simulated_olt", MacAddress: randomMacAddress}
-	ch := make(chan interface{})
-	defer close(ch)
-	requestNum := 0
-	for _, stub := range stubs {
-		go sendCreateDeviceRequest(ctx, stub, device, ch)
-		requestNum += 1
-	}
-	fmt.Println("Waiting for create device response ...")
-	receivedResponse := 0
-	var err error
-	var returnedDevice *voltha.Device
-	select {
-	case res, ok := <-ch:
-		receivedResponse += 1
-		if !ok {
-		} else if er, ok := res.(error); ok {
-			err = er
-		} else if d, ok := res.(*voltha.Device); ok {
-			returnedDevice = d
-		}
-		if receivedResponse == requestNum {
-			break
-		}
-	}
-	if returnedDevice != nil {
-		return returnedDevice, nil
-	}
-	return nil, err
-}
-
-// enableDevices sends two requests to each core for each device and waits for both responses before sending another
-// enable request for a different device.
-func enableAllDevices(stubs []voltha.VolthaServiceClient) error {
-	for deviceId, val := range devices {
-		if val.AdminState == voltha.AdminState_PREPROVISIONED {
-			ui := uuid.New()
-			ctx := metadata.NewOutgoingContext(context.Background(), metadata.Pairs(volthaSerialNumberKey, ui.String()))
-			ch := make(chan interface{})
-			defer close(ch)
-			requestNum := 0
-			for _, stub := range stubs {
-				go sendEnableDeviceRequest(ctx, stub, deviceId, ch)
-				requestNum += 1
-			}
-			receivedResponse := 0
-			var err error
-			fmt.Println("Waiting for enable device response ...")
-			validResponseReceived := false
-			select {
-			case res, ok := <-ch:
-				receivedResponse += 1
-				if !ok {
-				} else if er, ok := res.(error); ok {
-					err = er
-				} else if _, ok := res.(*empty.Empty); ok {
-					validResponseReceived = true
-				}
-				if receivedResponse == requestNum {
-					break
-				}
-			}
-			if validResponseReceived {
-				return nil
-			}
-			return err
-		}
-	}
-	return nil
-}
-
-func TestConcurrentRequests(t *testing.T) {
-	fmt.Println("Testing Concurrent requests ...")
-
-	////0. Start kafka and Ectd
-	startKafka()
-	defer stopKafka()
-	startEtcd()
-	defer stopKafka()
-	//
-	////1. Start the core
-	startCores()
-	defer stopCores()
-	//
-	////2. Start the simulated adapters
-	startSimulatedOLTAndONUAdapters()
-	defer stopSimulatedOLTAndONUAdapters()
-	//
-	//// Wait until the core and adapters sync up
-	//time.Sleep(10 * time.Second)
-
-	stubs = setupGrpcConnection()
-
-	//3.  Create the devices
-	response, err := createDevice(stubs)
-	logger.Infow(ctx, "response", log.Fields{"res": response, "error": err})
-	assert.Nil(t, err)
-	devices[response.Id] = response
-
-	//4. Enable all the devices
-	err = enableAllDevices(stubs)
-	assert.Nil(t, err)
-
-	////5. Store simulated adapters
-	//stopSimulatedOLTAndONUAdapters()
-	//
-	////6. Store the core
-	//stopCores()
-	//
-	////7. Stop Kafka and Etcd
-	//stopKafka()
-	//stopEtcd()
-}
-
-func shutdown() {
-	for _, conn := range conns {
-		conn.Close()
-	}
-}
-
-func TestMain(m *testing.M) {
-	setup()
-	code := m.Run()
-	shutdown()
-	os.Exit(code)
-}
diff --git a/tests/core/flow_management_test.go b/tests/core/flow_management_test.go
deleted file mode 100644
index 7a1079d..0000000
--- a/tests/core/flow_management_test.go
+++ /dev/null
@@ -1,901 +0,0 @@
-// +build integration
-
-/*
- * Copyright 2018-present Open Networking Foundation
-
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
-
- * http://www.apache.org/licenses/LICENSE-2.0
-
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package core
-
-import (
-	"context"
-	"fmt"
-	"github.com/google/uuid"
-	fu "github.com/opencord/voltha-go/rw_core/utils"
-	tu "github.com/opencord/voltha-go/tests/utils"
-	"github.com/opencord/voltha-lib-go/v3/pkg/log"
-	"github.com/opencord/voltha-protos/v3/go/common"
-	ofp "github.com/opencord/voltha-protos/v3/go/openflow_13"
-	"github.com/opencord/voltha-protos/v3/go/voltha"
-	"github.com/stretchr/testify/assert"
-	"google.golang.org/grpc/metadata"
-	"math"
-	"os"
-	"reflect"
-	"sync"
-	"testing"
-	"time"
-)
-
-var stub voltha.VolthaServiceClient
-var volthaSerialNumberKey string
-var mutex sync.Mutex
-
-/*
- This local "integration" test uses one RW-Core, one simulated_olt and one simulated_onu adapter to test flows
-(add/delete), in a development environment. It uses docker-compose to set up the local environment. However, it can
-easily be extended to run in k8s environment.
-
-The compose files used are located under %GOPATH/src/github.com/opencord/voltha-go/compose. If the GOPATH is not set
-then you can specify the location of the compose files by using COMPOSE_PATH to set the compose files location.
-
-To run this test: DOCKER_HOST_IP=<local IP> go test -v
-
-NOTE:  Since this is an integration test that involves several containers and features (device creation, device
-activation, validation of parent and discovered devices, validation of logical device as well as add/delete flows)
-then a failure can occur anywhere not just when testing flows.
-
-*/
-
-var allDevices map[string]*voltha.Device
-var allLogicalDevices map[string]*voltha.LogicalDevice
-
-var composePath string
-
-const (
-	GrpcPort        = 50057
-	NumOfOLTs       = 1
-	NumOfONUsPerOLT = 4 // This should coincide with the number of onus per olt in adapters-simulated.yml file
-	MeterIDStart    = 1
-	MeterIDStop     = 1000
-)
-
-func setup() {
-	volthaSerialNumberKey = "voltha_serial_number"
-	allDevices = make(map[string]*voltha.Device)
-	allLogicalDevices = make(map[string]*voltha.LogicalDevice)
-
-	grpcHostIP := os.Getenv("DOCKER_HOST_IP")
-	goPath := os.Getenv("GOPATH")
-	if goPath != "" {
-		composePath = fmt.Sprintf("%s/src/github.com/opencord/voltha-go/compose", goPath)
-	} else {
-		composePath = os.Getenv("COMPOSE_PATH")
-	}
-
-	fmt.Println("Using compose path:", composePath)
-
-	//Start the simulated environment
-	if err = tu.StartSimulatedEnv(composePath); err != nil {
-		fmt.Println("Failure starting simulated environment:", err)
-		os.Exit(10)
-	}
-
-	stub, err = tu.SetupGrpcConnectionToCore(grpcHostIP, GrpcPort)
-	if err != nil {
-		fmt.Println("Failure connecting to Voltha Core:", err)
-		os.Exit(11)
-	}
-
-	// Wait for the simulated devices to be registered in the Voltha Core
-	adapters := []string{"simulated_olt", "simulated_onu"}
-	if _, err = tu.WaitForAdapterRegistration(stub, adapters, 20); err != nil {
-		fmt.Println("Failure retrieving adapters:", err)
-		os.Exit(12)
-	}
-}
-
-func shutdown() {
-	err := tu.StopSimulatedEnv(composePath)
-	if err != nil {
-		fmt.Println("Failure stop simulated environment:", err)
-	}
-}
-
-func refreshLocalDeviceCache(stub voltha.VolthaServiceClient) error {
-	retrievedDevices, err := tu.ListDevices(stub)
-	if err != nil {
-		return err
-	}
-	mutex.Lock()
-	for _, d := range retrievedDevices.Items {
-		allDevices[d.Id] = d
-	}
-	retrievedLogicalDevices, err := tu.ListLogicalDevices(stub)
-	if err != nil {
-		return err
-	}
-
-	for _, ld := range retrievedLogicalDevices.Items {
-		allLogicalDevices[ld.Id] = ld
-	}
-	mutex.Unlock()
-	return nil
-}
-
-func makeSimpleFlowMod(fa *fu.FlowArgs) *ofp.OfpFlowMod {
-	matchFields := make([]*ofp.OfpOxmField, 0)
-	for _, val := range fa.MatchFields {
-		matchFields = append(matchFields, &ofp.OfpOxmField{Field: &ofp.OfpOxmField_OfbField{OfbField: val}})
-	}
-	return fu.MkSimpleFlowMod(matchFields, fa.Actions, fa.Command, fa.KV)
-}
-
-func addEAPOLFlow(stub voltha.VolthaServiceClient, ld *voltha.LogicalDevice, port *voltha.LogicalPort, meterID uint64,
-	ch chan interface{}) {
-	var fa *fu.FlowArgs
-	fa = &fu.FlowArgs{
-		KV: fu.OfpFlowModArgs{"priority": 2000, "meter_id": meterID},
-		MatchFields: []*ofp.OfpOxmOfbField{
-			fu.InPort(port.OfpPort.PortNo),
-			fu.EthType(0x888e),
-		},
-		Actions: []*ofp.OfpAction{
-			fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
-		},
-	}
-	// Don't add meterID 0
-	if meterID == 0 {
-		delete(fa.KV, "meter_id")
-	}
-
-	matchFields := make([]*ofp.OfpOxmField, 0)
-	for _, val := range fa.MatchFields {
-		matchFields = append(matchFields, &ofp.OfpOxmField{Field: &ofp.OfpOxmField_OfbField{OfbField: val}})
-	}
-	f := ofp.FlowTableUpdate{FlowMod: makeSimpleFlowMod(fa), Id: ld.Id}
-
-	ui := uuid.New()
-	ctx := metadata.NewOutgoingContext(context.Background(), metadata.Pairs(volthaSerialNumberKey, ui.String()))
-	if response, err := stub.UpdateLogicalDeviceFlowTable(ctx, &f); err != nil {
-		ch <- err
-	} else {
-		ch <- response
-	}
-}
-
-func getNumUniPort(ld *voltha.LogicalDevice, lPortNos ...uint32) int {
-	num := 0
-	if len(lPortNos) > 0 {
-		for _, pNo := range lPortNos {
-			for _, lPort := range ld.Ports {
-				if !lPort.RootPort && lPort.OfpPort.PortNo == pNo {
-					num += 1
-				}
-			}
-		}
-	} else {
-		for _, port := range ld.Ports {
-			if !port.RootPort {
-				num += 1
-			}
-		}
-	}
-	return num
-}
-
-func filterOutPort(lPort *voltha.LogicalPort, lPortNos ...uint32) bool {
-	if len(lPortNos) == 0 {
-		return false
-	}
-	for _, pNo := range lPortNos {
-		if lPort.OfpPort.PortNo == pNo {
-			return false
-		}
-	}
-	return true
-}
-
-func verifyEAPOLFlows(t *testing.T, ld *voltha.LogicalDevice, meterID uint64, lPortNos ...uint32) {
-	// First get the flows from the logical device
-	fmt.Println("Info: verifying EAPOL flows")
-	lFlows := ld.Flows
-	assert.Equal(t, getNumUniPort(ld, lPortNos...), len(lFlows.Items))
-
-	onuDeviceId := ""
-
-	// Verify that the flows in the logical device is what was pushed
-	for _, lPort := range ld.Ports {
-		if lPort.RootPort {
-			continue
-		}
-		if filterOutPort(lPort, lPortNos...) {
-			continue
-		}
-		onuDeviceId = lPort.DeviceId
-		var fa *fu.FlowArgs
-		fa = &fu.FlowArgs{
-			KV: fu.OfpFlowModArgs{"priority": 2000, "meter_id": meterID},
-			MatchFields: []*ofp.OfpOxmOfbField{
-				fu.InPort(lPort.OfpPort.PortNo),
-				fu.EthType(0x888e),
-			},
-			Actions: []*ofp.OfpAction{
-				fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
-			},
-		}
-		if meterID == 0 {
-			delete(fa.KV, "meter_id")
-		}
-		expectedLdFlow := fu.MkFlowStat(fa)
-		assert.Equal(t, true, tu.IsFlowPresent(expectedLdFlow, lFlows.Items))
-	}
-
-	//	Verify the OLT flows
-	retrievedOltFlows := allDevices[ld.RootDeviceId].Flows.Items
-	assert.Equal(t, NumOfOLTs*getNumUniPort(ld, lPortNos...)*1, len(retrievedOltFlows))
-	for _, lPort := range ld.Ports {
-		if lPort.RootPort {
-			continue
-		}
-		if filterOutPort(lPort, lPortNos...) {
-			continue
-		}
-
-		fa := &fu.FlowArgs{
-			KV: fu.OfpFlowModArgs{"priority": 2000, "meter_id": meterID},
-			MatchFields: []*ofp.OfpOxmOfbField{
-				fu.InPort(1),
-				fu.TunnelId(uint64(lPort.OfpPort.PortNo)),
-				fu.EthType(0x888e),
-			},
-			Actions: []*ofp.OfpAction{
-				fu.PushVlan(0x8100),
-				fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000)),
-				fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
-			},
-		}
-		expectedOltFlow := fu.MkFlowStat(fa)
-		assert.Equal(t, true, tu.IsFlowPresent(expectedOltFlow, retrievedOltFlows))
-	}
-	//	Verify the ONU flows
-	retrievedOnuFlows := allDevices[onuDeviceId].Flows.Items
-	assert.Equal(t, 0, len(retrievedOnuFlows))
-}
-
-func verifyNOFlows(t *testing.T, ld *voltha.LogicalDevice, lPortNos ...uint32) {
-	if len(lPortNos) == 0 {
-		assert.Equal(t, 0, len(ld.Flows.Items))
-		for _, d := range allDevices {
-			if d.ParentId == ld.Id {
-				assert.Equal(t, 0, len(d.Flows.Items))
-			}
-		}
-		return
-	}
-	for _, p := range lPortNos {
-		// Check absence of flows in logical device for that port
-		for _, f := range ld.Flows.Items {
-			assert.NotEqual(t, p, fu.GetInPort(f))
-		}
-		// Check absence of flows in the parent device for that port
-		for _, d := range allDevices {
-			if d.ParentId == ld.Id {
-				for _, f := range d.Flows.Items {
-					assert.NotEqual(t, p, fu.GetTunnelId(f))
-				}
-			}
-		}
-		//	TODO: check flows in child device.  Not required for the use cases being tested
-	}
-
-}
-
-func installEapolFlows(stub voltha.VolthaServiceClient, lDevice *voltha.LogicalDevice, meterID uint64, lPortNos ...uint32) error {
-	requestNum := 0
-	combineCh := make(chan interface{})
-	if len(lPortNos) > 0 {
-		fmt.Println("Installing EAPOL flows on ports:", lPortNos)
-		for _, p := range lPortNos {
-			for _, lport := range lDevice.Ports {
-				if !lport.RootPort && lport.OfpPort.PortNo == p {
-					go addEAPOLFlow(stub, lDevice, lport, meterID, combineCh)
-					requestNum += 1
-				}
-			}
-		}
-	} else {
-		fmt.Println("Installing EAPOL flows on logical device", lDevice.Id)
-		for _, lport := range lDevice.Ports {
-			if !lport.RootPort {
-				go addEAPOLFlow(stub, lDevice, lport, meterID, combineCh)
-				requestNum += 1
-			}
-		}
-	}
-	receivedResponse := 0
-	var err error
-	for {
-		select {
-		case res, ok := <-combineCh:
-			receivedResponse += 1
-			if !ok {
-			} else if er, ok := res.(error); ok {
-				err = er
-			}
-		}
-		if receivedResponse == requestNum {
-			break
-		}
-	}
-	return err
-}
-
-func deleteAllFlows(stub voltha.VolthaServiceClient, lDevice *voltha.LogicalDevice) error {
-	fmt.Println("Deleting all flows for logical device:", lDevice.Id)
-	ui := uuid.New()
-	ctx := metadata.NewOutgoingContext(context.Background(), metadata.Pairs(volthaSerialNumberKey, ui.String()))
-	ch := make(chan interface{})
-	defer close(ch)
-	fa := &fu.FlowArgs{
-		KV: fu.OfpFlowModArgs{"table_id": uint64(ofp.OfpTable_OFPTT_ALL),
-			"cookie_mask": 0,
-			"out_port":    uint64(ofp.OfpPortNo_OFPP_ANY),
-			"out_group":   uint64(ofp.OfpGroup_OFPG_ANY),
-		},
-	}
-	cmd := ofp.OfpFlowModCommand_OFPFC_DELETE
-	fa.Command = &cmd
-	flowMod := fu.MkSimpleFlowMod(fu.ToOfpOxmField(fa.MatchFields), fa.Actions, fa.Command, fa.KV)
-	f := ofp.FlowTableUpdate{FlowMod: flowMod, Id: lDevice.Id}
-	_, err := stub.UpdateLogicalDeviceFlowTable(ctx, &f)
-	return err
-}
-
-func deleteEapolFlow(stub voltha.VolthaServiceClient, lDevice *voltha.LogicalDevice, meterID uint64, lPortNo uint32) error {
-	fmt.Println("Deleting flows from port ", lPortNo, " of logical device ", lDevice.Id)
-	ui := uuid.New()
-	var fa *fu.FlowArgs
-	ctx := metadata.NewOutgoingContext(context.Background(), metadata.Pairs(volthaSerialNumberKey, ui.String()))
-	fa = &fu.FlowArgs{
-		KV: fu.OfpFlowModArgs{"priority": 2000, "meter_id": meterID},
-		MatchFields: []*ofp.OfpOxmOfbField{
-			fu.InPort(lPortNo),
-			fu.EthType(0x888e),
-		},
-		Actions: []*ofp.OfpAction{
-			fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
-		},
-	}
-	matchFields := make([]*ofp.OfpOxmField, 0)
-	for _, val := range fa.MatchFields {
-		matchFields = append(matchFields, &ofp.OfpOxmField{Field: &ofp.OfpOxmField_OfbField{OfbField: val}})
-	}
-	cmd := ofp.OfpFlowModCommand_OFPFC_DELETE
-	fa.Command = &cmd
-	f := ofp.FlowTableUpdate{FlowMod: makeSimpleFlowMod(fa), Id: lDevice.Id}
-	_, err := stub.UpdateLogicalDeviceFlowTable(ctx, &f)
-	return err
-}
-
-func runInstallEapolFlows(t *testing.T, stub voltha.VolthaServiceClient, meterID uint64, lPortNos ...uint32) {
-	err := refreshLocalDeviceCache(stub)
-	assert.Nil(t, err)
-
-	for _, ld := range allLogicalDevices {
-		err = installEapolFlows(stub, ld, meterID, lPortNos...)
-		assert.Nil(t, err)
-	}
-
-	err = refreshLocalDeviceCache(stub)
-	assert.Nil(t, err)
-	for _, ld := range allLogicalDevices {
-		verifyEAPOLFlows(t, ld, meterID, lPortNos...)
-	}
-}
-
-func runDeleteAllFlows(t *testing.T, stub voltha.VolthaServiceClient) {
-	fmt.Println("Removing ALL flows ...")
-	err := refreshLocalDeviceCache(stub)
-	assert.Nil(t, err)
-
-	for _, ld := range allLogicalDevices {
-		err = deleteAllFlows(stub, ld)
-		assert.Nil(t, err)
-	}
-
-	err = refreshLocalDeviceCache(stub)
-	assert.Nil(t, err)
-
-	for _, ld := range allLogicalDevices {
-		verifyNOFlows(t, ld)
-	}
-}
-
-func runDeleteEapolFlows(t *testing.T, stub voltha.VolthaServiceClient, ld *voltha.LogicalDevice, meterID uint64, lPortNos ...uint32) {
-	err := refreshLocalDeviceCache(stub)
-	assert.Nil(t, err)
-
-	if len(lPortNos) == 0 {
-		err = deleteAllFlows(stub, ld)
-		assert.Nil(t, err)
-	} else {
-		for _, lPortNo := range lPortNos {
-			err = deleteEapolFlow(stub, ld, meterID, lPortNo)
-			assert.Nil(t, err)
-		}
-	}
-
-	err = refreshLocalDeviceCache(stub)
-	assert.Nil(t, err)
-
-	for _, lde := range allLogicalDevices {
-		if lde.Id == ld.Id {
-			verifyNOFlows(t, lde, lPortNos...)
-			break
-		}
-	}
-}
-
-func formulateMeterModUpdateRequest(command ofp.OfpMeterModCommand, meterType ofp.OfpMeterBandType, ldID string, rate,
-	burstSize uint32, meterID uint32) *ofp.MeterModUpdate {
-	meterModUpdateRequest := &ofp.MeterModUpdate{
-		Id: ldID,
-		MeterMod: &ofp.OfpMeterMod{
-			Command: command,
-			Flags:   0,
-			MeterId: meterID,
-			Bands: []*ofp.OfpMeterBandHeader{{
-				Type:      meterType,
-				Rate:      rate,
-				BurstSize: burstSize,
-				Data:      nil,
-			}},
-		},
-	}
-	return meterModUpdateRequest
-}
-
-func formulateMeters(rate, burstsize, meterID uint32, flowCount uint32) *ofp.Meters {
-	// Formulate and return the applied meter band
-	ofpMeterBandHeaderSlice := []*ofp.OfpMeterBandHeader{{
-		Type:      ofp.OfpMeterBandType_OFPMBT_EXPERIMENTER,
-		Rate:      rate,
-		BurstSize: burstsize,
-	}}
-	BandStats := []*ofp.OfpMeterBandStats{{}}
-	appliedMeters_Meters := []*ofp.OfpMeterEntry{{
-		Config: &ofp.OfpMeterConfig{
-			Flags:   0,
-			MeterId: meterID,
-			Bands:   ofpMeterBandHeaderSlice,
-		},
-		Stats: &ofp.OfpMeterStats{
-			MeterId:   meterID,
-			BandStats: BandStats,
-			FlowCount: flowCount,
-		},
-	}}
-	appliedMeters := &ofp.Meters{
-		Items: appliedMeters_Meters,
-	}
-	return appliedMeters
-}
-
-func meterAdd(t *testing.T, meterID, rate, burstSize uint32) {
-	var err error
-	for _, logicalDevice := range allLogicalDevices {
-		meterModupdateRequest := formulateMeterModUpdateRequest(ofp.OfpMeterModCommand_OFPMC_ADD,
-			ofp.OfpMeterBandType_OFPMBT_EXPERIMENTER, logicalDevice.Id, rate, burstSize, meterID)
-		_, err = stub.UpdateLogicalDeviceMeterTable(context.Background(), meterModupdateRequest)
-		assert.Nil(t, err)
-	}
-}
-
-func meterMod(t *testing.T, meterID, rate, burstSize uint32) {
-	for _, logicalDevice := range allLogicalDevices {
-		meterModUpdateRequest := formulateMeterModUpdateRequest(ofp.OfpMeterModCommand_OFPMC_MODIFY,
-			ofp.OfpMeterBandType_OFPMBT_EXPERIMENTER, logicalDevice.Id, rate, burstSize, meterID)
-		_, err := stub.UpdateLogicalDeviceMeterTable(context.Background(), meterModUpdateRequest)
-		assert.Nil(t, err)
-	}
-}
-
-//MeterDel deletes a meter with given meter-ID
-func meterDel(t *testing.T, meterID uint32) {
-	for _, logicalDevice := range allLogicalDevices {
-		meterModUpdateRequest := formulateMeterModUpdateRequest(ofp.OfpMeterModCommand_OFPMC_DELETE,
-			ofp.OfpMeterBandType_OFPMBT_EXPERIMENTER, logicalDevice.Id, uint32(1600), uint32(1600), meterID)
-		_, err := stub.UpdateLogicalDeviceMeterTable(context.Background(), meterModUpdateRequest)
-		assert.Nil(t, err)
-	}
-}
-
-// WaitGroup passed to this function must not be nil
-func addMultipleMeterSequentially(t *testing.T, startMeterId, endMeterId, rate, burstSize uint32, wg *sync.WaitGroup) {
-	defer wg.Done()
-	for meterID := startMeterId; meterID <= endMeterId; meterID++ {
-		meterAdd(t, meterID, rate, burstSize)
-	}
-}
-
-func modMultipleMeterSequentially(t *testing.T, startMeterId, endMeterId, rate, burstSize uint32, wg *sync.WaitGroup) {
-	defer wg.Done()
-	for meterID := startMeterId; meterID <= endMeterId; meterID++ {
-		meterMod(t, meterID, rate, burstSize)
-	}
-}
-
-func delMultipleMeterSequential(t *testing.T, startMeterId, endMeterId uint32, wg *sync.WaitGroup) {
-	defer wg.Done()
-	for meterID := startMeterId; meterID <= endMeterId; meterID++ {
-		meterDel(t, meterID)
-	}
-}
-
-func verifyMeter(t *testing.T, meterID, rate, burstSize, flowCount uint32) {
-	expectedMeter := formulateOfpMeterEntry(meterID, flowCount, rate, burstSize)
-	isMeterPresent := false
-	for _, lD := range allLogicalDevices {
-		for _, meter := range lD.Meters.Items {
-			isMeterPresent = reflect.DeepEqual(meter, expectedMeter)
-			if isMeterPresent == true {
-				break
-			}
-		}
-		if isMeterPresent {
-			break
-		}
-	}
-	if !isMeterPresent {
-		fmt.Printf("Error : Expected %+v\n", expectedMeter)
-	}
-	assert.Equal(t, true, isMeterPresent)
-}
-
-func verifyNoMeters(t *testing.T) {
-	err := refreshLocalDeviceCache(stub)
-	assert.Nil(t, err)
-	expectedMeters := &ofp.Meters{}
-	for _, logicalDevice := range allLogicalDevices {
-		result := reflect.DeepEqual(logicalDevice.Meters, expectedMeters)
-		fmt.Println("Meter Present After Delete :--- ", logicalDevice.Meters)
-		assert.Equal(t, true, result)
-	}
-}
-
-func formulateOfpMeterEntry(meterID, flowCount, rate, burstSize uint32) *ofp.OfpMeterEntry {
-	value := &ofp.OfpMeterEntry{
-		Config: &ofp.OfpMeterConfig{
-			MeterId: meterID,
-			Bands: []*ofp.OfpMeterBandHeader{{
-				Type:      ofp.OfpMeterBandType_OFPMBT_EXPERIMENTER,
-				Rate:      rate,
-				BurstSize: burstSize,
-			}},
-		},
-		Stats: &ofp.OfpMeterStats{
-			MeterId:   meterID,
-			FlowCount: flowCount,
-			BandStats: []*ofp.OfpMeterBandStats{{}},
-		},
-	}
-
-	return value
-}
-
-func deleteAllMeters(t *testing.T) {
-	err := refreshLocalDeviceCache(stub)
-	assert.Nil(t, err)
-	for _, lD := range allLogicalDevices {
-		for _, meter := range lD.Meters.Items {
-			meterDel(t, meter.Config.MeterId)
-		}
-	}
-}
-
-func installMultipleFlowsWithMeter(t *testing.T, startMeterId, stopMeterId uint64, wg *sync.WaitGroup) {
-	defer wg.Done()
-	err := refreshLocalDeviceCache(stub)
-	assert.Nil(t, err)
-
-	for meterID := startMeterId; meterID <= stopMeterId; meterID++ {
-		runInstallEapolFlows(t, stub, uint64(meterID), 100, 101)
-	}
-}
-
-func createAndEnableDevices(t *testing.T) {
-	err := tu.SetAllLogLevel(stub, voltha.Logging{Level: common.LogLevel_WARNING})
-	assert.Nil(t, err)
-
-	err = tu.SetLogLevel(stub, voltha.Logging{Level: common.LogLevel_DEBUG, PackageName: "github.com/opencord/voltha-go/rw_core/core"})
-	assert.Nil(t, err)
-
-	startTime := time.Now()
-
-	//Pre-provision the parent device
-	oltDevice, err := tu.PreProvisionDevice(stub)
-	assert.Nil(t, err)
-
-	fmt.Println("Creation of ", NumOfOLTs, " OLT devices took:", time.Since(startTime))
-
-	startTime = time.Now()
-
-	//Enable all parent device - this will enable the child devices as well as validate the child devices
-	err = tu.EnableDevice(stub, oltDevice, NumOfONUsPerOLT)
-	assert.Nil(t, err)
-
-	fmt.Println("Enabling of  OLT device took:", time.Since(startTime))
-
-	// Wait until the core and adapters sync up after an enabled
-	time.Sleep(time.Duration(math.Max(10, float64(NumOfOLTs*NumOfONUsPerOLT)/2)) * time.Second)
-
-	err = tu.VerifyDevices(stub, NumOfONUsPerOLT)
-	assert.Nil(t, err)
-
-	lds, err := tu.VerifyLogicalDevices(stub, oltDevice, NumOfONUsPerOLT)
-	assert.Nil(t, err)
-	assert.Equal(t, 1, len(lds.Items))
-}
-
-func TestFlowManagement(t *testing.T) {
-	//1. Test creation and activation of the devices.  This will validate the devices as well as the logical device created
-	createAndEnableDevices(t)
-
-	//2. Test installation of EAPOL flows
-	runInstallEapolFlows(t, stub, 0)
-
-	//3. Test deletion of all EAPOL flows
-	runDeleteAllFlows(t, stub)
-
-	//4. Test installation of EAPOL flows on specific ports
-	runInstallEapolFlows(t, stub, 0, 101, 102)
-
-	lds, err := tu.ListLogicalDevices(stub)
-	assert.Nil(t, err)
-
-	//5. Test deletion of EAPOL on a specific port for a given logical device
-	runDeleteEapolFlows(t, stub, lds.Items[0], 0, 101)
-}
-
-// Meter Add Test
-func TestMeters(t *testing.T) {
-	//1. Start test for meter add
-	meterAdd(t, 1, 1600, 1600)
-	err := refreshLocalDeviceCache(stub)
-	assert.Nil(t, err)
-	verifyMeter(t, 1, 1600, 1600, 0)
-
-	//2. Start test for meter mod
-	meterMod(t, 1, 6400, 6400)
-	err = refreshLocalDeviceCache(stub)
-	assert.Nil(t, err)
-	verifyMeter(t, 1, 6400, 6400, 0)
-
-	//3. Start test for meter del
-	meterDel(t, 1)
-	err = refreshLocalDeviceCache(stub)
-	assert.Nil(t, err)
-	verifyNoMeters(t)
-}
-
-func TestFlowManagementWithMeters(t *testing.T) {
-	//1. Delete existing flows
-	for _, logicaldevice := range allLogicalDevices {
-		err := deleteAllFlows(stub, logicaldevice)
-		assert.Nil(t, err)
-	}
-	deleteAllMeters(t)
-	//2. Refresh the local cache so that the changes are reflected here
-	err := refreshLocalDeviceCache(stub)
-	assert.Nil(t, err)
-
-	//3. Add meter with ID
-	meterAdd(t, 1, 1600, 1600)
-
-	err = refreshLocalDeviceCache(stub)
-	assert.Nil(t, err)
-
-	//4. Verify that the meter is installed
-	verifyMeter(t, 1, 1600, 1600, 0)
-
-	//3. Test installation of EAPOL flows with meter (Add and verify the flow)
-	runInstallEapolFlows(t, stub, MeterIDStart)
-
-	//4. Test deletion of all EAPOL flows
-	runDeleteAllFlows(t, stub)
-
-	//5. Test installation of EAPOL flows on specific ports with meter (Add and verify the flows)
-	runInstallEapolFlows(t, stub, MeterIDStart, 101, 102)
-
-	lds, err := tu.ListLogicalDevices(stub)
-	assert.Nil(t, err)
-
-	//6. Test deletion of EAPOL on a specific port for a given logical device
-	runDeleteEapolFlows(t, stub, lds.Items[0], MeterIDStart, 101)
-}
-
-func TestMultipleMeterAddSequential(t *testing.T) {
-	//1. Delete existing flows
-	for _, logicaldevice := range allLogicalDevices {
-		err := deleteAllFlows(stub, logicaldevice)
-		assert.Nil(t, err)
-	}
-
-	// Delete All The Previously Installed Meters
-	deleteAllMeters(t)
-	// Verify that no meters are present
-	err := refreshLocalDeviceCache(stub)
-	assert.Nil(t, err)
-	verifyNoMeters(t)
-	//2. Add Meter Sequentially
-	// Here wait-group is not required, creating and passing wait-group only because the function addMultipleMeterSequentially
-	// expects wait group.
-	var wg sync.WaitGroup
-	wg.Add(1)
-	addMultipleMeterSequentially(t, MeterIDStart, MeterIDStop, 1600, 1600, &wg)
-
-	err = refreshLocalDeviceCache(stub)
-	assert.Nil(t, err)
-
-	//3. Verify that the meters are installed
-	for meterID := MeterIDStart; meterID <= MeterIDStop; meterID++ {
-		verifyMeter(t, uint32(meterID), 1600, 1600, 0)
-	}
-}
-
-func TestMeterDeleteParallel(t *testing.T) {
-	var wg sync.WaitGroup
-	wg.Add(4)
-	go delMultipleMeterSequential(t, MeterIDStart, MeterIDStop/4, &wg)
-	go delMultipleMeterSequential(t, MeterIDStop/4+1, (MeterIDStop / 2), &wg)
-	go delMultipleMeterSequential(t, (MeterIDStop/2)+1, MeterIDStop/4*3, &wg)
-	go delMultipleMeterSequential(t, (MeterIDStop/4*3)+1, MeterIDStop, &wg)
-	wg.Wait()
-
-	verifyNoMeters(t)
-}
-
-func TestMultipleMeterAddParallel(t *testing.T) {
-	err := refreshLocalDeviceCache(stub)
-	assert.Nil(t, err)
-
-	for _, logicaldevice := range allLogicalDevices {
-		err := deleteAllFlows(stub, logicaldevice)
-		assert.Nil(t, err)
-	}
-
-	var wg sync.WaitGroup
-	wg.Add(4)
-	go addMultipleMeterSequentially(t, MeterIDStart, (MeterIDStop / 4), 3200, 3200, &wg)
-	go addMultipleMeterSequentially(t, (MeterIDStop/4 + 1), MeterIDStop/2, 3200, 3200, &wg)
-	go addMultipleMeterSequentially(t, MeterIDStop/2+1, (MeterIDStop / 4 * 3), 3200, 3200, &wg)
-	go addMultipleMeterSequentially(t, (MeterIDStop/4*3)+1, MeterIDStop, 3200, 3200, &wg)
-
-	wg.Wait()
-
-	// Verify the devices
-	err = tu.VerifyDevices(stub, NumOfONUsPerOLT)
-	assert.Nil(t, err)
-
-	err = refreshLocalDeviceCache(stub)
-	assert.Nil(t, err)
-	for meterID := MeterIDStart; meterID <= MeterIDStop; meterID++ {
-		fmt.Println("Verifying meter ID :", meterID)
-		verifyMeter(t, uint32(meterID), 3200, 3200, 0)
-	}
-}
-
-func TestMultipleMeterModSequential(t *testing.T) {
-	var wg sync.WaitGroup
-	wg.Add(1)
-	//1. Modify all the existing meters
-	modMultipleMeterSequentially(t, MeterIDStart, MeterIDStop, 6400, 6400, &wg)
-	//2. Verify that the device state is proper after updating so many meters
-	err := tu.VerifyDevices(stub, NumOfONUsPerOLT)
-	assert.Nil(t, err)
-
-	//3. Refresh logical device cache
-	err = refreshLocalDeviceCache(stub)
-	assert.Nil(t, err)
-
-	//4. Verify that all the meters got modified
-	for meterID := MeterIDStart; meterID <= MeterIDStop; meterID++ {
-		fmt.Println("Verifying meter ID :", meterID)
-		verifyMeter(t, uint32(meterID), 6400, 6400, 0)
-	}
-}
-
-func TestMultipleMeterModParallel(t *testing.T) {
-	var wg sync.WaitGroup
-	wg.Add(4)
-	//1. Modify all the existing meters
-	go modMultipleMeterSequentially(t, MeterIDStart, MeterIDStop/4, 1600, 1600, &wg)
-	go modMultipleMeterSequentially(t, (MeterIDStop/4 + 1), MeterIDStop/2, 1600, 1600, &wg)
-	go modMultipleMeterSequentially(t, (MeterIDStop/2 + 1), (MeterIDStop / 4 * 3), 1600, 1600, &wg)
-	go modMultipleMeterSequentially(t, (MeterIDStop/4*3)+1, MeterIDStop, 1600, 1600, &wg)
-	//2. Verify that the device state is proper after updating so many meters
-	err := tu.VerifyDevices(stub, NumOfONUsPerOLT)
-	assert.Nil(t, err)
-	wg.Wait()
-
-	//3. Refresh logical device cache
-	err = refreshLocalDeviceCache(stub)
-	assert.Nil(t, err)
-
-	//4. Verify that all the meters got modified
-	for meterID := MeterIDStart; meterID <= MeterIDStop; meterID++ {
-		fmt.Println("Verifying meter ID :", meterID)
-		verifyMeter(t, uint32(meterID), 1600, 1600, 0)
-	}
-}
-
-func TestMultipleMeterDelSequential(t *testing.T) {
-	var wg sync.WaitGroup
-	wg.Add(1)
-	//1. Delete all the given meters sequentially
-	delMultipleMeterSequential(t, MeterIDStart, MeterIDStop, &wg)
-	//2. Verify that all the given meters are deleted
-	verifyNoMeters(t)
-}
-
-func TestMultipleFlowsWithMeters(t *testing.T) {
-	err := refreshLocalDeviceCache(stub)
-	assert.Nil(t, err)
-
-	//1. Delete all the previous flows
-	for _, lD := range allLogicalDevices {
-		deleteAllFlows(stub, lD)
-	}
-
-	//2. Add multiple meters for the flows to refer to
-	var wg sync.WaitGroup
-	wg.Add(2)
-	addMultipleMeterSequentially(t, MeterIDStart, 10, 1600, 1600, &wg)
-	// Adding meter verification here again will increase the time taken by the test. So leaving meter verification
-	installMultipleFlowsWithMeter(t, 1, 10, &wg)
-}
-
-func TestFlowDeletionWithMeterDelete(t *testing.T) {
-	err := refreshLocalDeviceCache(stub)
-	assert.Nil(t, err)
-
-	//1. Delete all meters
-	deleteAllMeters(t)
-	//2. Verify that all the meters are deleted
-	verifyNoMeters(t)
-	//3. As no meters are present, so all flows referring to these meters should also be deleted
-	// Flow referring to meterID 1 - 10 were installed in the above test "TestMultipleFlowsWithMeters"
-	err = refreshLocalDeviceCache(stub)
-	assert.Nil(t, err)
-	for _, lD := range allLogicalDevices {
-		verifyNOFlows(t, lD, 100, 101)
-	}
-}
-
-func TestAddFlowWithInvalidMeter(t *testing.T) {
-	var err error
-	for _, ld := range allLogicalDevices {
-		// Adding flows with meter-ID which is not present should throw error stating -
-		// "Meter-referred-by-flow-is-not-found-in-logicaldevice"
-		err = installEapolFlows(stub, ld, 1, 100, 101)
-		assert.NotNil(t, err)
-	}
-}
-
-func TestMain(m *testing.M) {
-	setup()
-	code := m.Run()
-	shutdown()
-	os.Exit(code)
-}
diff --git a/tests/core/performance_metrics_test.go b/tests/core/performance_metrics_test.go
deleted file mode 100644
index 60b0bba..0000000
--- a/tests/core/performance_metrics_test.go
+++ /dev/null
@@ -1,305 +0,0 @@
-// +build integration
-
-/*
- * Copyright 2018-present Open Networking Foundation
-
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
-
- * http://www.apache.org/licenses/LICENSE-2.0
-
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package core
-
-import (
-	"context"
-	"fmt"
-	"github.com/google/uuid"
-	tu "github.com/opencord/voltha-go/tests/utils"
-	"github.com/opencord/voltha-lib-go/v3/pkg/log"
-	"github.com/opencord/voltha-protos/v3/go/common"
-	"github.com/opencord/voltha-protos/v3/go/voltha"
-	"github.com/stretchr/testify/assert"
-	"google.golang.org/grpc/metadata"
-	"math"
-	"os"
-	"testing"
-	"time"
-)
-
-var stub voltha.VolthaServiceClient
-var volthaSerialNumberKey string
-
-/*
- This local "integration" test uses one RW-Core, one simulated_olt and one simulated_onu adapter to test performance
-metrics, in a development environment. It uses docker-compose to set up the local environment. However, it can
-easily be extended to run in k8s environment.
-
-The compose files used are located under %GOPATH/src/github.com/opencord/voltha-go/compose. If the GOPATH is not set
-then you can specify the location of the compose files by using COMPOSE_PATH to set the compose files location.
-
-To run this test: DOCKER_HOST_IP=<local IP> go test -v
-
-*/
-
-var allDevices map[string]*voltha.Device
-var allLogicalDevices map[string]*voltha.LogicalDevice
-
-var composePath string
-
-const (
-	GRPC_PORT        = 50057
-	NUM_OLTS         = 1
-	NUM_ONUS_PER_OLT = 4 // This should coincide with the number of onus per olt in adapters-simulated.yml file
-)
-
-var parentPmNames = []string{
-	"tx_64_pkts",
-	"tx_65_127_pkts",
-	"tx_128_255_pkts",
-	"tx_256_511_pkts",
-	"tx_512_1023_pkts",
-	"tx_1024_1518_pkts",
-	"tx_1519_9k_pkts",
-	"rx_64_pkts",
-	"rx_65_127_pkts",
-	"rx_128_255_pkts",
-	"rx_256_511_pkts",
-	"rx_512_1023_pkts",
-	"rx_1024_1518_pkts",
-	"rx_1519_9k_pkts",
-}
-
-var childPmNames = []string{
-	"tx_64_pkts",
-	"tx_65_127_pkts",
-	"tx_128_255_pkts",
-	"tx_1024_1518_pkts",
-	"tx_1519_9k_pkts",
-	"rx_64_pkts",
-	"rx_64_pkts",
-	"rx_65_127_pkts",
-	"rx_128_255_pkts",
-	"rx_1024_1518_pkts",
-	"rx_1519_9k_pkts",
-}
-
-func setup() {
-	volthaSerialNumberKey = "voltha_serial_number"
-	allDevices = make(map[string]*voltha.Device)
-	allLogicalDevices = make(map[string]*voltha.LogicalDevice)
-
-	grpcHostIP := os.Getenv("DOCKER_HOST_IP")
-	goPath := os.Getenv("GOPATH")
-	if goPath != "" {
-		composePath = fmt.Sprintf("%s/src/github.com/opencord/voltha-go/compose", goPath)
-	} else {
-		composePath = os.Getenv("COMPOSE_PATH")
-	}
-
-	fmt.Println("Using compose path:", composePath)
-
-	//Start the simulated environment
-	if err = tu.StartSimulatedEnv(composePath); err != nil {
-		fmt.Println("Failure starting simulated environment:", err)
-		os.Exit(10)
-	}
-
-	stub, err = tu.SetupGrpcConnectionToCore(grpcHostIP, GRPC_PORT)
-	if err != nil {
-		fmt.Println("Failure connecting to Voltha Core:", err)
-		os.Exit(11)
-	}
-
-	// Wait for the simulated devices to be registered in the Voltha Core
-	adapters := []string{"simulated_olt", "simulated_onu"}
-	if _, err = tu.WaitForAdapterRegistration(stub, adapters, 40); err != nil {
-		fmt.Println("Failure retrieving adapters:", err)
-		os.Exit(12)
-	}
-}
-
-func shutdown() {
-	err := tu.StopSimulatedEnv(composePath)
-	if err != nil {
-		fmt.Println("Failure stop simulated environment:", err)
-	}
-}
-
-func refreshLocalDeviceCache(stub voltha.VolthaServiceClient) error {
-	retrievedDevices, err := tu.ListDevices(stub)
-	if err != nil {
-		return err
-	}
-	for _, d := range retrievedDevices.Items {
-		allDevices[d.Id] = d
-	}
-
-	retrievedLogicalDevices, err := tu.ListLogicalDevices(stub)
-	if err != nil {
-		return err
-	}
-
-	for _, ld := range retrievedLogicalDevices.Items {
-		allLogicalDevices[ld.Id] = ld
-	}
-	return nil
-}
-
-func isPresent(pmName string, pmNames []string) bool {
-	for _, name := range pmNames {
-		if name == pmName {
-			return true
-		}
-	}
-	return false
-}
-
-func verifyDevicePMs(t *testing.T, stub voltha.VolthaServiceClient, device *voltha.Device, allPmNames []string, disabledPmNames []string, frequency uint32) {
-	ui := uuid.New()
-	ctx := metadata.NewOutgoingContext(context.Background(), metadata.Pairs(volthaSerialNumberKey, ui.String()))
-	pmConfigs, err := stub.ListDevicePmConfigs(ctx, &common.ID{Id: device.Id})
-	assert.Nil(t, err)
-	assert.Equal(t, device.Id, pmConfigs.Id)
-	assert.Equal(t, uint32(frequency), pmConfigs.DefaultFreq)
-	assert.Equal(t, false, pmConfigs.FreqOverride)
-	assert.Equal(t, false, pmConfigs.Grouped)
-	assert.Nil(t, pmConfigs.Groups)
-	assert.True(t, len(pmConfigs.Metrics) > 0)
-	metrics := pmConfigs.Metrics
-	for _, m := range metrics {
-		if m.Enabled {
-			assert.True(t, isPresent(m.Name, allPmNames))
-		} else {
-			assert.True(t, isPresent(m.Name, disabledPmNames))
-		}
-		assert.Equal(t, voltha.PmConfig_COUNTER, m.Type)
-	}
-}
-
-func verifyInitialPmConfigs(t *testing.T, stub voltha.VolthaServiceClient) {
-	fmt.Println("Verifying initial PM configs")
-	err := refreshLocalDeviceCache(stub)
-	assert.Nil(t, err)
-	for _, d := range allDevices {
-		if d.Root {
-			verifyDevicePMs(t, stub, d, parentPmNames, []string{}, 150)
-		} else {
-			verifyDevicePMs(t, stub, d, childPmNames, []string{}, 150)
-		}
-	}
-}
-
-func verifyPmFrequencyUpdate(t *testing.T, stub voltha.VolthaServiceClient, device *voltha.Device) {
-	ui := uuid.New()
-	ctx := metadata.NewOutgoingContext(context.Background(), metadata.Pairs(volthaSerialNumberKey, ui.String()))
-	pmConfigs, err := stub.ListDevicePmConfigs(ctx, &common.ID{Id: device.Id})
-	assert.Nil(t, err)
-	pmConfigs.DefaultFreq = 10
-	_, err = stub.UpdateDevicePmConfigs(ctx, pmConfigs)
-	assert.Nil(t, err)
-	if device.Root {
-		verifyDevicePMs(t, stub, device, parentPmNames, []string{}, 10)
-	} else {
-		verifyDevicePMs(t, stub, device, childPmNames, []string{}, 10)
-	}
-}
-
-func updatePmFrequencies(t *testing.T, stub voltha.VolthaServiceClient) {
-	fmt.Println("Verifying update to PMs frequencies")
-	err := refreshLocalDeviceCache(stub)
-	assert.Nil(t, err)
-	for _, d := range allDevices {
-		verifyPmFrequencyUpdate(t, stub, d)
-	}
-}
-
-func verifyDisablingSomePmMetrics(t *testing.T, stub voltha.VolthaServiceClient, device *voltha.Device) {
-	ui := uuid.New()
-	ctx := metadata.NewOutgoingContext(context.Background(), metadata.Pairs(volthaSerialNumberKey, ui.String()))
-	pmConfigs, err := stub.ListDevicePmConfigs(ctx, &common.ID{Id: device.Id})
-	assert.Nil(t, err)
-	metricsToDisable := []string{"tx_64_pkts", "rx_64_pkts", "tx_65_127_pkts", "rx_65_127_pkts"}
-	for _, m := range pmConfigs.Metrics {
-		if isPresent(m.Name, metricsToDisable) {
-			m.Enabled = false
-		}
-	}
-	_, err = stub.UpdateDevicePmConfigs(ctx, pmConfigs)
-	assert.Nil(t, err)
-	if device.Root {
-		verifyDevicePMs(t, stub, device, parentPmNames, metricsToDisable, 10)
-	} else {
-		verifyDevicePMs(t, stub, device, childPmNames, metricsToDisable, 10)
-	}
-}
-
-func disableSomePmMetrics(t *testing.T, stub voltha.VolthaServiceClient) {
-	fmt.Println("Verifying disabling of some PMs")
-	err := refreshLocalDeviceCache(stub)
-	assert.Nil(t, err)
-	for _, d := range allDevices {
-		verifyDisablingSomePmMetrics(t, stub, d)
-	}
-}
-
-func createAndEnableDevices(t *testing.T) {
-	err := tu.SetAllLogLevel(stub, voltha.Logging{Level: common.LogLevel_WARNING})
-	assert.Nil(t, err)
-
-	err = tu.SetLogLevel(stub, voltha.Logging{Level: common.LogLevel_DEBUG, PackageName: "github.com/opencord/voltha-go/rw_core/core"})
-	assert.Nil(t, err)
-
-	startTime := time.Now()
-
-	//Pre-provision the parent device
-	oltDevice, err := tu.PreProvisionDevice(stub)
-	assert.Nil(t, err)
-
-	fmt.Println("Creation of ", NUM_OLTS, " OLT devices took:", time.Since(startTime))
-
-	startTime = time.Now()
-
-	//Enable all parent device - this will enable the child devices as well as validate the child devices
-	err = tu.EnableDevice(stub, oltDevice, NUM_ONUS_PER_OLT)
-	assert.Nil(t, err)
-
-	fmt.Println("Enabling of  OLT device took:", time.Since(startTime))
-
-	// Wait until the core and adapters sync up after an enabled
-	time.Sleep(time.Duration(math.Max(10, float64(NUM_OLTS*NUM_ONUS_PER_OLT)/2)) * time.Second)
-
-	err = tu.VerifyDevices(stub, NUM_ONUS_PER_OLT)
-	assert.Nil(t, err)
-
-	lds, err := tu.VerifyLogicalDevices(stub, oltDevice, NUM_ONUS_PER_OLT)
-	assert.Nil(t, err)
-	assert.Equal(t, 1, len(lds.Items))
-}
-
-func TestPerformanceMetrics(t *testing.T) {
-	//1. Test creation and activation of the devices.  This will validate the devices as well as the logical device created/
-	createAndEnableDevices(t)
-
-	//	2. Test initial PMs on each device
-	verifyInitialPmConfigs(t, stub)
-
-	//	3. Test frequency update of the pmConfigs
-	updatePmFrequencies(t, stub)
-
-	//	4. Test disable some PM metrics
-	disableSomePmMetrics(t, stub)
-}
-
-func TestMain(m *testing.M) {
-	setup()
-	code := m.Run()
-	shutdown()
-	os.Exit(code)
-}
diff --git a/tests/kafka/common.go b/tests/kafka/common.go
deleted file mode 100644
index a26ece9..0000000
--- a/tests/kafka/common.go
+++ /dev/null
@@ -1,33 +0,0 @@
-// +build integration
-
-/*
- * Copyright 2020-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package kafka
-
-import (
-	"github.com/opencord/voltha-lib-go/v3/pkg/log"
-)
-
-var logger log.CLogger
-
-func init() {
-	// Setup this package so that it's log level can be modified at run time
-	var err error
-	logger, err = log.RegisterPackage(log.JSON, log.ErrorLevel, log.Fields{"pkg": "kafka"})
-	if err != nil {
-		panic(err)
-	}
-}
diff --git a/tests/kafka/kafka_client_test.go b/tests/kafka/kafka_client_test.go
deleted file mode 100644
index cce5d7e..0000000
--- a/tests/kafka/kafka_client_test.go
+++ /dev/null
@@ -1,189 +0,0 @@
-// +build integration
-
-/*
- * Copyright 2018-present Open Networking Foundation
-
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
-
- * http://www.apache.org/licenses/LICENSE-2.0
-
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package kafka
-
-import (
-	"fmt"
-	"os"
-	"testing"
-	"time"
-
-	"github.com/golang/protobuf/ptypes"
-	"github.com/golang/protobuf/ptypes/any"
-	"github.com/google/uuid"
-	kk "github.com/opencord/voltha-lib-go/v3/pkg/kafka"
-	"github.com/opencord/voltha-lib-go/v3/pkg/log"
-	ic "github.com/opencord/voltha-protos/v3/go/inter_container"
-	"github.com/stretchr/testify/assert"
-)
-
-/*
-Prerequite:  Start the kafka/zookeeper containers.
-*/
-
-var partionClient kk.Client
-var groupClient kk.Client
-var totalTime int64
-var numMessageToSend int
-var totalMessageReceived int
-
-type sendToKafka func(interface{}, *kk.Topic, ...string) error
-
-func init() {
-	hostIP := os.Getenv("DOCKER_HOST_IP")
-	partionClient = kk.NewSaramaClient(
-		kk.ConsumerType(kk.PartitionConsumer),
-		kk.Host(hostIP),
-		kk.Port(9092),
-		kk.AutoCreateTopic(true),
-		kk.ProducerFlushFrequency(5))
-	partionClient.Start()
-	groupClient = kk.NewSaramaClient(
-		kk.ConsumerType(kk.GroupCustomer),
-		kk.Host(hostIP),
-		kk.Port(9092),
-		kk.AutoCreateTopic(false),
-		kk.ProducerFlushFrequency(5))
-	groupClient.Start()
-	numMessageToSend = 1
-}
-
-func waitForMessage(ch <-chan *ic.InterContainerMessage, doneCh chan string, maxMessages int) {
-	totalTime = 0
-	totalMessageReceived = 0
-	mytime := time.Now()
-startloop:
-	for {
-		select {
-		case msg := <-ch:
-			if totalMessageReceived == 0 {
-				mytime = time.Now()
-			}
-			totalTime = totalTime + (time.Now().UnixNano()-msg.Header.Timestamp)/int64(time.Millisecond)
-			//logger.Debugw(ctx, "msg-received", log.Fields{"msg":msg})
-			totalMessageReceived = totalMessageReceived + 1
-			if totalMessageReceived == maxMessages {
-				doneCh <- "All received"
-				break startloop
-			}
-			if totalMessageReceived%10000 == 0 {
-				fmt.Println("received-so-far", totalMessageReceived, totalTime, totalTime/int64(totalMessageReceived))
-			}
-		}
-	}
-	logger.Infow(ctx, "Received all messages", log.Fields{"total": time.Since(mytime)})
-}
-
-func sendMessages(topic *kk.Topic, numMessages int, fn sendToKafka) error {
-	// Loop for numMessages
-	for i := 0; i < numMessages; i++ {
-		msg := &ic.InterContainerMessage{}
-		msg.Header = &ic.Header{
-			Id:        uuid.New().String(),
-			Type:      ic.MessageType_REQUEST,
-			FromTopic: topic.Name,
-			ToTopic:   topic.Name,
-			Timestamp: time.Now().UnixNano(),
-		}
-		var marshalledArg *any.Any
-		var err error
-		body := &ic.InterContainerRequestBody{Rpc: "testRPC", Args: []*ic.Argument{}}
-		if marshalledArg, err = ptypes.MarshalAny(body); err != nil {
-			logger.Warnw(ctx, "cannot-marshal-request", log.Fields{"error": err})
-			return err
-		}
-		msg.Body = marshalledArg
-		msg.Header.Timestamp = time.Now().UnixNano()
-		go fn(msg, topic)
-		//go partionClient.Send(msg, topic)
-	}
-	return nil
-}
-
-func runWithPartionConsumer(topic *kk.Topic, numMessages int, doneCh chan string) error {
-	var ch <-chan *ic.InterContainerMessage
-	var err error
-	if ch, err = partionClient.Subscribe(topic); err != nil {
-		return nil
-	}
-	go waitForMessage(ch, doneCh, numMessages)
-
-	//Now create a routine to send messages
-	go sendMessages(topic, numMessages, partionClient.Send)
-
-	return nil
-}
-
-func runWithGroupConsumer(topic *kk.Topic, numMessages int, doneCh chan string) error {
-	var ch <-chan *ic.InterContainerMessage
-	var err error
-	if ch, err = groupClient.Subscribe(topic); err != nil {
-		return nil
-	}
-	go waitForMessage(ch, doneCh, numMessages)
-
-	//Now create a routine to send messages
-	go sendMessages(topic, numMessages, groupClient.Send)
-
-	return nil
-}
-
-func TestPartitionConsumer(t *testing.T) {
-	done := make(chan string)
-	topic := &kk.Topic{Name: "CoreTest1"}
-	runWithPartionConsumer(topic, numMessageToSend, done)
-	start := time.Now()
-	// Wait for done
-	val := <-done
-	err := partionClient.DeleteTopic(topic)
-	assert.Nil(t, err)
-	partionClient.Stop()
-	assert.Equal(t, numMessageToSend, totalMessageReceived)
-	logger.Infow(ctx, "Partition consumer completed", log.Fields{"TotalMesages": totalMessageReceived, "TotalTime": totalTime, "val": val, "AverageTime": totalTime / int64(totalMessageReceived), "execTime": time.Since(start)})
-}
-
-func TestGroupConsumer(t *testing.T) {
-	done := make(chan string)
-	topic := &kk.Topic{Name: "CoreTest2"}
-	runWithGroupConsumer(topic, numMessageToSend, done)
-	start := time.Now()
-	// Wait for done
-	val := <-done
-	err := groupClient.DeleteTopic(topic)
-	assert.Nil(t, err)
-	groupClient.Stop()
-	assert.Equal(t, numMessageToSend, totalMessageReceived)
-	logger.Infow(ctx, "Group consumer completed", log.Fields{"TotalMesages": totalMessageReceived, "TotalTime": totalTime, "val": val, "AverageTime": totalTime / int64(totalMessageReceived), "execTime": time.Since(start)})
-
-}
-
-func TestCreateDeleteTopic(t *testing.T) {
-	hostIP := os.Getenv("DOCKER_HOST_IP")
-	client := kk.NewSaramaClient(
-		kk.ConsumerType(kk.PartitionConsumer),
-		kk.Host(hostIP),
-		kk.Port(9092),
-		kk.AutoCreateTopic(true),
-		kk.ProducerFlushFrequency(5))
-	client.Start()
-	topic := &kk.Topic{Name: "CoreTest20"}
-	err := client.CreateTopic(topic, 3, 1)
-	assert.Nil(t, err)
-	err = client.DeleteTopic(topic)
-	assert.Nil(t, err)
-}
diff --git a/tests/kafka/kafka_inter_container_messaging_test.go b/tests/kafka/kafka_inter_container_messaging_test.go
deleted file mode 100644
index d0bd26e..0000000
--- a/tests/kafka/kafka_inter_container_messaging_test.go
+++ /dev/null
@@ -1,554 +0,0 @@
-// +build integration
-
-/*
- * Copyright 2018-present Open Networking Foundation
-
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
-
- * http://www.apache.org/licenses/LICENSE-2.0
-
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package kafka
-
-import (
-	"context"
-	"os"
-	"testing"
-	"time"
-
-	"github.com/golang/protobuf/ptypes"
-	"github.com/google/uuid"
-	"github.com/opencord/voltha-go/rw_core/core/api"
-	kk "github.com/opencord/voltha-lib-go/v3/pkg/kafka"
-	"github.com/opencord/voltha-lib-go/v3/pkg/log"
-	ic "github.com/opencord/voltha-protos/v3/go/inter_container"
-	"github.com/opencord/voltha-protos/v3/go/voltha"
-	"github.com/stretchr/testify/assert"
-)
-
-/*
-Prerequite:  Start the kafka/zookeeper containers.
-*/
-
-const (
-	TEST_RPC_KEY = ""
-)
-
-var coreKafkaProxy *kk.InterContainerProxy
-var adapterKafkaProxy *kk.InterContainerProxy
-var kafkaPartitionClient kk.Client
-var deviceDiscoveryTopic string
-var hostIP string
-var kafkaClient kk.Client
-
-func init() {
-	deviceDiscoveryTopic = "deviceDiscovery"
-	hostIP = os.Getenv("DOCKER_HOST_IP")
-	kafkaClient = kk.NewSaramaClient(
-		kk.Host(hostIP),
-		kk.Port(9092))
-
-	coreKafkaProxy = kk.NewInterContainerProxy(
-		kk.InterContainerHost(hostIP),
-		kk.InterContainerPort(9092),
-		kk.DefaultTopic(&kk.Topic{Name: "Core"}),
-		kk.MsgClient(kafkaClient),
-		kk.DeviceDiscoveryTopic(&kk.Topic{Name: deviceDiscoveryTopic}))
-
-	adapterKafkaProxy = kk.NewInterContainerProxy(
-		kk.InterContainerHost(hostIP),
-		kk.InterContainerPort(9092),
-		kk.DefaultTopic(&kk.Topic{Name: "Adapter"}),
-		kk.MsgClient(kafkaClient))
-
-	kafkaPartitionClient = kk.NewSaramaClient(
-		kk.ConsumerType(kk.PartitionConsumer),
-		kk.Host(hostIP),
-		kk.Port(9092),
-		kk.AutoCreateTopic(true),
-		kk.ProducerFlushFrequency(5))
-	kafkaPartitionClient.Start()
-
-	coreKafkaProxy.Start()
-	adapterKafkaProxy.Start()
-	subscribeTarget(context.Background(), coreKafkaProxy)
-}
-
-func subscribeTarget(ctx context.Context, kmp *kk.InterContainerProxy) {
-	topic := kk.Topic{Name: "Core"}
-	requestProxy := &api.AdapterRequestHandlerProxy{TestMode: true}
-	kmp.SubscribeWithRequestHandlerInterface(ctx, topic, requestProxy)
-}
-
-func waitForRPCMessage(ctx context.Context, topic kk.Topic, ch <-chan *ic.InterContainerMessage, doneCh chan string) {
-	for msg := range ch {
-		logger.Debugw(ctx, "Got-RPC-message", log.Fields{"msg": msg})
-		//	Unpack message
-		requestBody := &ic.InterContainerRequestBody{}
-		if err := ptypes.UnmarshalAny(msg.Body, requestBody); err != nil {
-			doneCh <- "Error"
-		} else {
-			doneCh <- requestBody.Rpc
-		}
-		break
-	}
-}
-
-//func TestSubscribeUnsubscribe(t *testing.T) {
-//	// First subscribe to the specific topic
-//	topic := kk.Topic{Name: "Core"}
-//	ch, err := coreKafkaProxy.Subs(topic)
-//	assert.NotNil(t, ch)
-//	assert.Nil(t, err)
-//	// Create a channel to receive a response
-//	waitCh := make(chan string)
-//	// Wait for a message
-//	go waitForRPCMessage(topic, ch, waitCh)
-//	// Send the message - don't care of the response
-//	rpc := "AnyRPCRequestForTest"
-//	adapterKafkaProxy.InvokeRPC(nil, rpc, &topic, true)
-//	// Wait for the result on ouw own channel
-//	result := <-waitCh
-//	assert.Equal(t, result, rpc)
-//	close(waitCh)
-//	err = coreKafkaProxy.UnSubscribe(topic, ch)
-//	assert.Nil(t, err)
-//}
-//
-//func TestMultipleSubscribeUnsubscribe(t *testing.T) {
-//	// First subscribe to the specific topic
-//	//log.SetPackageLogLevel("github.com/opencord/voltha-lib-go/v3/pkg/kafka", log.DebugLevel)
-//	var err error
-//	var ch1 <-chan *ic.InterContainerMessage
-//	var ch2 <-chan *ic.InterContainerMessage
-//	topic := kk.Topic{Name: "Core"}
-//	ch1, err = coreKafkaProxy.Subscribe(topic)
-//	assert.NotNil(t, ch1)
-//	assert.Nil(t, err)
-//	// Create a channel to receive responses
-//	waitCh := make(chan string)
-//	ch2, err = coreKafkaProxy.Subscribe(topic)
-//	assert.NotNil(t, ch2)
-//	assert.Nil(t, err)
-//	// Wait for a message
-//	go waitForRPCMessage(topic, ch2, waitCh)
-//	go waitForRPCMessage(topic, ch1, waitCh)
-//
-//	// Send the message - don't care of the response
-//	rpc := "AnyRPCRequestForTest"
-//	adapterKafkaProxy.InvokeRPC(nil, rpc, &topic, true)
-//	// Wait for the result on ouw own channel
-//
-//	responses := 0
-//	for msg := range waitCh {
-//		assert.Equal(t, msg, rpc)
-//		responses = responses + 1
-//		if responses > 1 {
-//			break
-//		}
-//	}
-//	assert.Equal(t, responses, 2)
-//	close(waitCh)
-//	err = coreKafkaProxy.UnSubscribe(topic, ch1)
-//	assert.Nil(t, err)
-//	err = coreKafkaProxy.UnSubscribe(topic, ch2)
-//	assert.Nil(t, err)
-//}
-
-func TestIncorrectAPI(t *testing.T) {
-	log.SetPackageLogLevel("github.com/opencord/voltha-lib-go/v3/pkg/kafka", log.ErrorLevel)
-	trnsId := uuid.New().String()
-	protoMsg := &voltha.Device{Id: trnsId}
-	args := make([]*kk.KVArg, 1)
-	args[0] = &kk.KVArg{
-		Key:   "device",
-		Value: protoMsg,
-	}
-	rpc := "IncorrectAPI"
-	topic := kk.Topic{Name: "Core"}
-	start := time.Now()
-	status, result := adapterKafkaProxy.InvokeRPC(nil, rpc, &topic, &topic, true, TEST_RPC_KEY, args...)
-	elapsed := time.Since(start)
-	logger.Infow(ctx, "Result", log.Fields{"status": status, "result": result, "time": elapsed})
-	assert.Equal(t, status, false)
-	//Unpack the result into the actual proto object
-	unpackResult := &ic.Error{}
-	if err := ptypes.UnmarshalAny(result, unpackResult); err != nil {
-		logger.Warnw(ctx, "cannot-unmarshal-response", log.Fields{"error": err})
-	}
-	assert.NotNil(t, unpackResult)
-}
-
-func TestIncorrectAPIParams(t *testing.T) {
-	trnsId := uuid.New().String()
-	protoMsg := &voltha.Device{Id: trnsId}
-	args := make([]*kk.KVArg, 1)
-	args[0] = &kk.KVArg{
-		Key:   "device",
-		Value: protoMsg,
-	}
-	rpc := "GetDevice"
-	topic := kk.Topic{Name: "Core"}
-	start := time.Now()
-	status, result := adapterKafkaProxy.InvokeRPC(nil, rpc, &topic, &topic, true, TEST_RPC_KEY, args...)
-	elapsed := time.Since(start)
-	logger.Infow(ctx, "Result", log.Fields{"status": status, "result": result, "time": elapsed})
-	assert.Equal(t, status, false)
-	//Unpack the result into the actual proto object
-	unpackResult := &ic.Error{}
-	if err := ptypes.UnmarshalAny(result, unpackResult); err != nil {
-		logger.Warnw(ctx, "cannot-unmarshal-response", log.Fields{"error": err})
-	}
-	assert.NotNil(t, unpackResult)
-}
-
-func TestGetDevice(t *testing.T) {
-	trnsId := uuid.New().String()
-	protoMsg := &voltha.ID{Id: trnsId}
-	args := make([]*kk.KVArg, 1)
-	args[0] = &kk.KVArg{
-		Key:   "deviceID",
-		Value: protoMsg,
-	}
-	rpc := "GetDevice"
-	topic := kk.Topic{Name: "Core"}
-	expectedResponse := &voltha.Device{Id: trnsId}
-	timeout := time.Duration(50) * time.Millisecond
-	ctx, cancel := context.WithTimeout(context.Background(), timeout)
-	defer cancel()
-	start := time.Now()
-	status, result := adapterKafkaProxy.InvokeRPC(ctx, rpc, &topic, &topic, true, TEST_RPC_KEY, args...)
-	elapsed := time.Since(start)
-	logger.Infow(ctx, "Result", log.Fields{"status": status, "result": result, "time": elapsed})
-	assert.Equal(t, status, true)
-	unpackResult := &voltha.Device{}
-	if err := ptypes.UnmarshalAny(result, unpackResult); err != nil {
-		logger.Warnw(ctx, "cannot-unmarshal-response", log.Fields{"error": err})
-	}
-	assert.Equal(t, unpackResult, expectedResponse)
-}
-
-func TestGetDeviceTimeout(t *testing.T) {
-	trnsId := uuid.New().String()
-	protoMsg := &voltha.ID{Id: trnsId}
-	args := make([]*kk.KVArg, 1)
-	args[0] = &kk.KVArg{
-		Key:   "deviceID",
-		Value: protoMsg,
-	}
-	rpc := "GetDevice"
-	topic := kk.Topic{Name: "Core"}
-	timeout := time.Duration(2) * time.Millisecond
-	ctx, cancel := context.WithTimeout(context.Background(), timeout)
-	defer cancel()
-	start := time.Now()
-	status, result := adapterKafkaProxy.InvokeRPC(ctx, rpc, &topic, &topic, true, TEST_RPC_KEY, args...)
-	elapsed := time.Since(start)
-	logger.Infow(ctx, "Result", log.Fields{"status": status, "result": result, "time": elapsed})
-	assert.Equal(t, status, false)
-	unpackResult := &ic.Error{}
-	if err := ptypes.UnmarshalAny(result, unpackResult); err != nil {
-		logger.Warnw(ctx, "cannot-unmarshal-response", log.Fields{"error": err})
-	}
-	assert.NotNil(t, unpackResult)
-}
-
-func TestGetChildDevice(t *testing.T) {
-	trnsId := uuid.New().String()
-	protoMsg := &voltha.ID{Id: trnsId}
-	args := make([]*kk.KVArg, 1)
-	args[0] = &kk.KVArg{
-		Key:   "deviceID",
-		Value: protoMsg,
-	}
-	rpc := "GetChildDevice"
-	topic := kk.Topic{Name: "Core"}
-	expectedResponse := &voltha.Device{Id: trnsId}
-	start := time.Now()
-	status, result := adapterKafkaProxy.InvokeRPC(nil, rpc, &topic, &topic, true, TEST_RPC_KEY, args...)
-	elapsed := time.Since(start)
-	logger.Infow(ctx, "Result", log.Fields{"status": status, "result": result, "time": elapsed})
-	assert.Equal(t, status, true)
-	unpackResult := &voltha.Device{}
-	if err := ptypes.UnmarshalAny(result, unpackResult); err != nil {
-		logger.Warnw(ctx, "cannot-unmarshal-response", log.Fields{"error": err})
-	}
-	assert.Equal(t, unpackResult, expectedResponse)
-}
-
-func TestGetChildDevices(t *testing.T) {
-	trnsId := uuid.New().String()
-	protoMsg := &voltha.ID{Id: trnsId}
-	args := make([]*kk.KVArg, 1)
-	args[0] = &kk.KVArg{
-		Key:   "deviceID",
-		Value: protoMsg,
-	}
-	rpc := "GetChildDevices"
-	topic := kk.Topic{Name: "Core"}
-	expectedResponse := &voltha.Device{Id: trnsId}
-	start := time.Now()
-	status, result := adapterKafkaProxy.InvokeRPC(nil, rpc, &topic, &topic, true, TEST_RPC_KEY, args...)
-	elapsed := time.Since(start)
-	logger.Infow(ctx, "Result", log.Fields{"status": status, "result": result, "time": elapsed})
-	assert.Equal(t, status, true)
-	unpackResult := &voltha.Device{}
-	if err := ptypes.UnmarshalAny(result, unpackResult); err != nil {
-		logger.Warnw(ctx, "cannot-unmarshal-response", log.Fields{"error": err})
-	}
-	assert.Equal(t, unpackResult, expectedResponse)
-}
-
-func TestGetPorts(t *testing.T) {
-	trnsId := uuid.New().String()
-	protoArg1 := &voltha.ID{Id: trnsId}
-	args := make([]*kk.KVArg, 2)
-	args[0] = &kk.KVArg{
-		Key:   "deviceID",
-		Value: protoArg1,
-	}
-	protoArg2 := &ic.IntType{Val: 1}
-	args[1] = &kk.KVArg{
-		Key:   "portType",
-		Value: protoArg2,
-	}
-	rpc := "GetPorts"
-	topic := kk.Topic{Name: "Core"}
-	start := time.Now()
-	status, result := adapterKafkaProxy.InvokeRPC(nil, rpc, &topic, &topic, true, TEST_RPC_KEY, args...)
-	elapsed := time.Since(start)
-	logger.Infow(ctx, "Result", log.Fields{"status": status, "result": result, "time": elapsed})
-	assert.Equal(t, status, true)
-	unpackResult := &voltha.Ports{}
-	if err := ptypes.UnmarshalAny(result, unpackResult); err != nil {
-		logger.Warnw(ctx, "cannot-unmarshal-response", log.Fields{"error": err})
-	}
-	expectedLen := len(unpackResult.Items) >= 1
-	assert.Equal(t, true, expectedLen)
-}
-
-func TestGetPortsMissingArgs(t *testing.T) {
-	trnsId := uuid.New().String()
-	protoArg1 := &voltha.ID{Id: trnsId}
-	args := make([]*kk.KVArg, 1)
-	args[0] = &kk.KVArg{
-		Key:   "deviceID",
-		Value: protoArg1,
-	}
-	rpc := "GetPorts"
-	topic := kk.Topic{Name: "Core"}
-	start := time.Now()
-	status, result := adapterKafkaProxy.InvokeRPC(nil, rpc, &topic, &topic, true, TEST_RPC_KEY, args...)
-	elapsed := time.Since(start)
-	logger.Infow(ctx, "Result", log.Fields{"status": status, "result": result, "time": elapsed})
-	assert.Equal(t, status, false)
-	//Unpack the result into the actual proto object
-	unpackResult := &ic.Error{}
-	if err := ptypes.UnmarshalAny(result, unpackResult); err != nil {
-		logger.Warnw(ctx, "cannot-unmarshal-response", log.Fields{"error": err})
-	}
-	assert.NotNil(t, unpackResult)
-}
-
-func TestChildDeviceDetected(t *testing.T) {
-	trnsId := uuid.New().String()
-	protoArg1 := &ic.StrType{Val: trnsId}
-	args := make([]*kk.KVArg, 5)
-	args[0] = &kk.KVArg{
-		Key:   "deviceID",
-		Value: protoArg1,
-	}
-	protoArg2 := &ic.IntType{Val: 1}
-	args[1] = &kk.KVArg{
-		Key:   "parentPortNo",
-		Value: protoArg2,
-	}
-	protoArg3 := &ic.StrType{Val: "great_onu"}
-	args[2] = &kk.KVArg{
-		Key:   "childDeviceType",
-		Value: protoArg3,
-	}
-	protoArg4 := &voltha.Device_ProxyAddress{DeviceId: trnsId, ChannelId: 100}
-	args[3] = &kk.KVArg{
-		Key:   "proxyAddress",
-		Value: protoArg4,
-	}
-	protoArg5 := &ic.IntType{Val: 1}
-	args[4] = &kk.KVArg{
-		Key:   "portType",
-		Value: protoArg5,
-	}
-
-	rpc := "ChildDeviceDetected"
-	topic := kk.Topic{Name: "Core"}
-	start := time.Now()
-	status, result := adapterKafkaProxy.InvokeRPC(nil, rpc, &topic, &topic, true, TEST_RPC_KEY, args...)
-	elapsed := time.Since(start)
-	logger.Infow(ctx, "Result", log.Fields{"status": status, "result": result, "time": elapsed})
-	assert.Equal(t, status, true)
-	assert.Nil(t, result)
-}
-
-func TestChildDeviceDetectedNoWait(t *testing.T) {
-	trnsId := uuid.New().String()
-	protoArg1 := &ic.StrType{Val: trnsId}
-	args := make([]*kk.KVArg, 5)
-	args[0] = &kk.KVArg{
-		Key:   "deviceID",
-		Value: protoArg1,
-	}
-	protoArg2 := &ic.IntType{Val: 1}
-	args[1] = &kk.KVArg{
-		Key:   "parentPortNo",
-		Value: protoArg2,
-	}
-	protoArg3 := &ic.StrType{Val: "great_onu"}
-	args[2] = &kk.KVArg{
-		Key:   "childDeviceType",
-		Value: protoArg3,
-	}
-	protoArg4 := &voltha.Device_ProxyAddress{DeviceId: trnsId, ChannelId: 100}
-	args[3] = &kk.KVArg{
-		Key:   "proxyAddress",
-		Value: protoArg4,
-	}
-	protoArg5 := &ic.IntType{Val: 1}
-	args[4] = &kk.KVArg{
-		Key:   "portType",
-		Value: protoArg5,
-	}
-
-	rpc := "ChildDeviceDetected"
-	topic := kk.Topic{Name: "Core"}
-	start := time.Now()
-	status, result := adapterKafkaProxy.InvokeRPC(nil, rpc, &topic, &topic, false, TEST_RPC_KEY, args...)
-	elapsed := time.Since(start)
-	logger.Infow(ctx, "Result", log.Fields{"status": status, "result": result, "time": elapsed})
-	assert.Equal(t, status, true)
-	assert.Nil(t, result)
-}
-
-func TestChildDeviceDetectedMissingArgs(t *testing.T) {
-	trnsId := uuid.New().String()
-	protoArg1 := &ic.StrType{Val: trnsId}
-	args := make([]*kk.KVArg, 4)
-	args[0] = &kk.KVArg{
-		Key:   "deviceID",
-		Value: protoArg1,
-	}
-	protoArg2 := &ic.IntType{Val: 1}
-	args[1] = &kk.KVArg{
-		Key:   "parentPortNo",
-		Value: protoArg2,
-	}
-	protoArg3 := &ic.StrType{Val: "great_onu"}
-	args[2] = &kk.KVArg{
-		Key:   "childDeviceType",
-		Value: protoArg3,
-	}
-
-	rpc := "ChildDeviceDetected"
-	topic := kk.Topic{Name: "Core"}
-	start := time.Now()
-	status, result := adapterKafkaProxy.InvokeRPC(nil, rpc, &topic, &topic, true, TEST_RPC_KEY, args...)
-	elapsed := time.Since(start)
-	logger.Infow(ctx, "Result", log.Fields{"status": status, "result": result, "time": elapsed})
-	assert.Equal(t, status, false)
-	unpackResult := &ic.Error{}
-	if err := ptypes.UnmarshalAny(result, unpackResult); err != nil {
-		logger.Warnw(ctx, "cannot-unmarshal-response", log.Fields{"error": err})
-	}
-	assert.NotNil(t, unpackResult)
-}
-
-func TestDeviceStateChange(t *testing.T) {
-	log.SetAllLogLevel(log.DebugLevel)
-	trnsId := uuid.New().String()
-	protoArg1 := &voltha.ID{Id: trnsId}
-	args := make([]*kk.KVArg, 4)
-	args[0] = &kk.KVArg{
-		Key:   "device_id",
-		Value: protoArg1,
-	}
-	protoArg2 := &ic.IntType{Val: 1}
-	args[1] = &kk.KVArg{
-		Key:   "oper_status",
-		Value: protoArg2,
-	}
-	protoArg3 := &ic.IntType{Val: 1}
-	args[2] = &kk.KVArg{
-		Key:   "connect_status",
-		Value: protoArg3,
-	}
-
-	rpc := "DeviceStateUpdate"
-	topic := kk.Topic{Name: "Core"}
-	start := time.Now()
-	status, result := adapterKafkaProxy.InvokeRPC(nil, rpc, &topic, &topic, true, TEST_RPC_KEY, args...)
-	elapsed := time.Since(start)
-	logger.Infow(ctx, "Result", log.Fields{"status": status, "result": result, "time": elapsed})
-	assert.Equal(t, status, true)
-	assert.Nil(t, result)
-}
-
-func subscribeToTopic(topic *kk.Topic, waitingChannel chan *ic.InterContainerMessage) error {
-	var ch <-chan *ic.InterContainerMessage
-	var err error
-	if ch, err = kafkaPartitionClient.Subscribe(topic); err != nil {
-		return nil
-	}
-	msg := <-ch
-
-	logger.Debugw(ctx, "msg-received", log.Fields{"msg": msg})
-	waitingChannel <- msg
-	return nil
-}
-
-func TestDeviceDiscovery(t *testing.T) {
-	// Create an intercontainer proxy - similar to the Core
-	testProxy := kk.NewInterContainerProxy(
-		kk.InterContainerHost(hostIP),
-		kk.InterContainerPort(9092),
-		kk.DefaultTopic(&kk.Topic{Name: "Test"}),
-		kk.MsgClient(kafkaClient),
-		kk.DeviceDiscoveryTopic(&kk.Topic{Name: deviceDiscoveryTopic}))
-
-	//	First start to wait for the message
-	waitingChannel := make(chan *ic.InterContainerMessage)
-	go subscribeToTopic(&kk.Topic{Name: deviceDiscoveryTopic}, waitingChannel)
-
-	// Sleep to make sure the consumer is ready
-	time.Sleep(time.Millisecond * 100)
-
-	// Send the message
-	go testProxy.DeviceDiscovered("TestDeviceId", "TestDevicetype", "TestParentId", "myPODName")
-
-	msg := <-waitingChannel
-	totalTime := (time.Now().UnixNano() - msg.Header.Timestamp) / int64(time.Millisecond)
-	assert.Equal(t, msg.Header.Type, ic.MessageType_DEVICE_DISCOVERED)
-	//	Unpack message
-	dd := &ic.DeviceDiscovered{}
-	err := ptypes.UnmarshalAny(msg.Body, dd)
-	assert.Nil(t, err)
-	assert.Equal(t, dd.Id, "TestDeviceId")
-	assert.Equal(t, dd.DeviceType, "TestDevicetype")
-	assert.Equal(t, dd.ParentId, "TestParentId")
-	assert.Equal(t, dd.Publisher, "myPODName")
-	logger.Debugw(ctx, "TotalTime", log.Fields{"time": totalTime})
-}
-
-func TestStopKafkaProxy(t *testing.T) {
-	adapterKafkaProxy.Stop()
-	coreKafkaProxy.Stop()
-}
-
-//func TestMain(m *testing.T) {
-//	logger.Info(ctx, "Main")
-//}
diff --git a/tests/utils/common.go b/tests/utils/common.go
deleted file mode 100644
index f81e3b8..0000000
--- a/tests/utils/common.go
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2020-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// Package utils Common Logger initialization
-package utils
-
-import (
-	"github.com/opencord/voltha-lib-go/v3/pkg/log"
-)
-
-var logger log.CLogger
-
-func init() {
-	// Setup this package so that it's log level can be modified at run time
-	var err error
-	logger, err = log.RegisterPackage(log.JSON, log.ErrorLevel, log.Fields{"pkg": "utils"})
-	if err != nil {
-		panic(err)
-	}
-}
diff --git a/tests/utils/test_utils.go b/tests/utils/test_utils.go
deleted file mode 100644
index 9f8fbc8..0000000
--- a/tests/utils/test_utils.go
+++ /dev/null
@@ -1,473 +0,0 @@
-// "build integration
-
-/*
- * Copyright 2018-present Open Networking Foundation
-
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
-
- * http://www.apache.org/licenses/LICENSE-2.0
-
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package utils
-
-import (
-	"context"
-	"fmt"
-	"os/exec"
-	"strings"
-	"time"
-
-	"github.com/golang/protobuf/ptypes/empty"
-	"github.com/google/uuid"
-	com "github.com/opencord/voltha-lib-go/v3/pkg/adapters/common"
-	"github.com/opencord/voltha-lib-go/v3/pkg/log"
-	"github.com/opencord/voltha-protos/v3/go/common"
-	ofp "github.com/opencord/voltha-protos/v3/go/openflow_13"
-	"github.com/opencord/voltha-protos/v3/go/voltha"
-
-	"google.golang.org/grpc"
-	"google.golang.org/grpc/codes"
-	"google.golang.org/grpc/metadata"
-	"google.golang.org/grpc/status"
-)
-
-// constant represents voltha serial number
-const (
-	VolthaSerialNumberKey = "voltha_serial_number"
-)
-
-func startKafka(composePath string) error {
-	fmt.Println("Starting Kafka and Etcd ...")
-	command := "docker-compose"
-	fileName := fmt.Sprintf("%s/docker-compose-zk-kafka-test.yml", composePath)
-	cmd := exec.Command(command, "-f", fileName, "up", "-d")
-	if err := cmd.Run(); err != nil {
-		return err
-	}
-	return nil
-}
-
-func startEtcd(composePath string) error {
-	fmt.Println("Starting Etcd ...")
-	command := "docker-compose"
-	fileName := fmt.Sprintf("%s/docker-compose-etcd.yml", composePath)
-	cmd := exec.Command(command, "-f", fileName, "up", "-d")
-	if err := cmd.Run(); err != nil {
-		return err
-	}
-	return nil
-}
-
-func stopKafka(composePath string) error {
-	fmt.Println("Stopping Kafka and Etcd ...")
-	command := "docker-compose"
-	fileName := fmt.Sprintf("%s/docker-compose-zk-kafka-test.yml", composePath)
-	cmd := exec.Command(command, "-f", fileName, "down")
-	if err := cmd.Run(); err != nil {
-		return err
-	}
-	return nil
-}
-
-func stopEtcd(composePath string) error {
-	fmt.Println("Stopping Etcd ...")
-	command := "docker-compose"
-	fileName := fmt.Sprintf("%s/docker-compose-etcd.yml", composePath)
-	cmd := exec.Command(command, "-f", fileName, "down")
-	if err := cmd.Run(); err != nil {
-		return err
-	}
-	return nil
-}
-
-func startCore(composePath string) error {
-	fmt.Println("Starting voltha core ...")
-	command := "docker-compose"
-	fileName := fmt.Sprintf("%s/rw_core.yml", composePath)
-	cmd := exec.Command(command, "-f", fileName, "up", "-d")
-	if err := cmd.Run(); err != nil {
-		return err
-	}
-	return nil
-}
-
-func stopCore(composePath string) error {
-	fmt.Println("Stopping voltha core ...")
-	command := "docker-compose"
-	fileName := fmt.Sprintf("%s/rw_core.yml", composePath)
-	cmd := exec.Command(command, "-f", fileName, "down")
-	if err := cmd.Run(); err != nil {
-		return err
-	}
-	return nil
-}
-
-func startSimulatedOLTAndONUAdapters(composePath string) error {
-	fmt.Println("Starting simulated OLT and ONU adapters ...")
-	command := "docker-compose"
-	fileName := fmt.Sprintf("%s/adapters-simulated.yml", composePath)
-	cmd := exec.Command(command, "-f", fileName, "up", "-d")
-	if err := cmd.Run(); err != nil {
-		return err
-	}
-	return nil
-}
-
-func stopSimulatedOLTAndONUAdapters(composePath string) error {
-	fmt.Println("Stopping simulated OLT and ONU adapters ...")
-	command := "docker-compose"
-	fileName := fmt.Sprintf("%s/adapters-simulated.yml", composePath)
-	cmd := exec.Command(command, "-f", fileName, "down")
-	if err := cmd.Run(); err != nil {
-		return err
-	}
-	return nil
-}
-
-// ListLogicalDevices lists all logical devices managed by the Voltha cluster
-func ListLogicalDevices(stub voltha.VolthaServiceClient) (*voltha.LogicalDevices, error) {
-	ui := uuid.New()
-	ctx := metadata.NewOutgoingContext(context.Background(), metadata.Pairs(VolthaSerialNumberKey, ui.String()))
-	return stub.ListLogicalDevices(ctx, &empty.Empty{})
-}
-
-func sendCreateDeviceRequest(ctx context.Context, stub voltha.VolthaServiceClient, device *voltha.Device, ch chan interface{}) {
-	if response, err := stub.CreateDevice(ctx, device); err != nil {
-		ch <- err
-	} else {
-		ch <- response
-	}
-}
-
-func sendListAdapters(ctx context.Context, stub voltha.VolthaServiceClient, ch chan interface{}) {
-	if response, err := stub.ListAdapters(ctx, &empty.Empty{}); err != nil {
-		ch <- err
-	} else {
-		ch <- response
-	}
-}
-
-func sendEnableDeviceRequest(ctx context.Context, stub voltha.VolthaServiceClient, deviceID string, ch chan interface{}) {
-	if response, err := stub.EnableDevice(ctx, &common.ID{Id: deviceID}); err != nil {
-		ch <- err
-	} else {
-		ch <- response
-	}
-}
-
-func getDevices(ctx context.Context, stub voltha.VolthaServiceClient) (*voltha.Devices, error) {
-	return stub.ListDevices(ctx, &empty.Empty{})
-}
-
-func getLogicalDevices(ctx context.Context, stub voltha.VolthaServiceClient) (*voltha.LogicalDevices, error) {
-	return stub.ListLogicalDevices(ctx, &empty.Empty{})
-}
-
-// IsFlowPresent returns true if flow is present
-func IsFlowPresent(lookingFor *voltha.OfpFlowStats, flows []*voltha.OfpFlowStats) bool {
-	for _, f := range flows {
-		if f.String() == lookingFor.String() {
-			return true
-		}
-	}
-	return false
-}
-
-// ListDevices lists all physical devices controlled by the Voltha cluster
-func ListDevices(stub voltha.VolthaServiceClient) (*voltha.Devices, error) {
-	ui := uuid.New()
-	ctx := metadata.NewOutgoingContext(context.Background(), metadata.Pairs(VolthaSerialNumberKey, ui.String()))
-	return getDevices(ctx, stub)
-}
-
-func sendFlow(ctx context.Context, stub voltha.VolthaServiceClient, flow *ofp.FlowTableUpdate, ch chan interface{}) {
-	if response, err := stub.UpdateLogicalDeviceFlowTable(ctx, flow); err != nil {
-		ch <- err
-	} else {
-		ch <- response
-	}
-}
-
-// SetupGrpcConnectionToCore sets up client connection to an RPC server.
-func SetupGrpcConnectionToCore(grpcHostIP string, grpcPort int) (voltha.VolthaServiceClient, error) {
-	grpcHost := fmt.Sprintf("%s:%d", grpcHostIP, grpcPort)
-	fmt.Println("Connecting to voltha using:", grpcHost)
-	conn, err := grpc.Dial(grpcHost, grpc.WithInsecure())
-	if err != nil {
-		return nil, err
-	}
-	return voltha.NewVolthaServiceClient(conn), nil
-}
-
-// VerifyLogicalDevices verifies all logical devices managed by the Voltha cluster
-func VerifyLogicalDevices(stub voltha.VolthaServiceClient, parentDevice *voltha.Device, numONUsPerOLT int) (*voltha.LogicalDevices, error) {
-	ui := uuid.New()
-	ctx := metadata.NewOutgoingContext(context.Background(), metadata.Pairs(VolthaSerialNumberKey, ui.String()))
-	retrievedLogicalDevices, err := getLogicalDevices(ctx, stub)
-	if err != nil {
-		return nil, err
-	}
-	if len(retrievedLogicalDevices.Items) != 1 {
-		return nil, status.Errorf(codes.Internal, "Logical device number incorrect. Expected:{%d}, Created:{%d}", 1, len(retrievedLogicalDevices.Items))
-	}
-
-	// Verify that each device has two ports
-	for _, ld := range retrievedLogicalDevices.Items {
-		if ld.Id == "" ||
-			ld.DatapathId == uint64(0) ||
-			ld.Desc.HwDesc != "simulated_pon" ||
-			ld.Desc.SwDesc != "simulated_pon" ||
-			ld.RootDeviceId == "" ||
-			ld.Desc.SerialNum == "" ||
-			ld.SwitchFeatures.NBuffers != uint32(256) ||
-			ld.SwitchFeatures.NTables != uint32(2) ||
-			ld.SwitchFeatures.Capabilities != uint32(15) ||
-			len(ld.Ports) != 1+numONUsPerOLT ||
-			ld.RootDeviceId != parentDevice.Id {
-			return nil, status.Errorf(codes.Internal, "incorrect logical device status:{%v}", ld)
-		}
-		for _, p := range ld.Ports {
-			if p.DevicePortNo != p.OfpPort.PortNo ||
-				p.OfpPort.State != uint32(4) {
-				return nil, status.Errorf(codes.Internal, "incorrect logical ports status:{%v}", p)
-			}
-			if strings.HasPrefix(p.Id, "nni") {
-				if !p.RootPort || fmt.Sprintf("nni-%d", p.DevicePortNo) != p.Id {
-					return nil, status.Errorf(codes.Internal, "incorrect nni port status:{%v}", p)
-				}
-			} else {
-				if p.RootPort || fmt.Sprintf("uni-%d", p.DevicePortNo) != p.Id {
-					return nil, status.Errorf(codes.Internal, "incorrect uni port status:{%v}", p)
-				}
-			}
-		}
-	}
-	return retrievedLogicalDevices, nil
-}
-
-// VerifyDevices verifies all physical devices controlled by the Voltha cluster
-func VerifyDevices(stub voltha.VolthaServiceClient, numONUsPerOLT int) error {
-	ui := uuid.New()
-	ctx := metadata.NewOutgoingContext(context.Background(), metadata.Pairs(VolthaSerialNumberKey, ui.String()))
-	retrievedDevices, err := getDevices(ctx, stub)
-	if err != nil {
-		return err
-	}
-	if len(retrievedDevices.Items) != 1+numONUsPerOLT {
-		return status.Errorf(codes.Internal, "Device number incorrect. Expected:{%d}, Created:{%d}", 1, len(retrievedDevices.Items))
-	}
-	// Verify that each device has two ports
-	for _, d := range retrievedDevices.Items {
-		if d.AdminState != voltha.AdminState_ENABLED ||
-			d.ConnectStatus != voltha.ConnectStatus_REACHABLE ||
-			d.OperStatus != voltha.OperStatus_ACTIVE ||
-			d.Type != d.Adapter ||
-			d.Id == "" ||
-			d.MacAddress == "" ||
-			d.SerialNumber == "" {
-			return status.Errorf(codes.Internal, "incorrect device state - %s", d.Id)
-		}
-
-		if d.Type == "simulated_olt" && (!d.Root || d.ProxyAddress != nil) {
-			return status.Errorf(codes.Internal, "invalid olt status:{%v}", d)
-		} else if d.Type == "simulated_onu" && (d.Root ||
-			d.Vlan == uint32(0) ||
-			d.ParentId == "" ||
-			d.ProxyAddress.DeviceId == "" ||
-			d.ProxyAddress.DeviceType != "simulated_olt") {
-			return status.Errorf(codes.Internal, "invalid onu status:{%s}", d.Id)
-		}
-
-		if len(d.Ports) != 2 {
-			return status.Errorf(codes.Internal, "invalid number of ports:{%s, %v}", d.Id, d.Ports)
-		}
-
-		for _, p := range d.Ports {
-			if p.AdminState != voltha.AdminState_ENABLED ||
-				p.OperStatus != voltha.OperStatus_ACTIVE {
-				return status.Errorf(codes.Internal, "invalid port state:{%s, %v}", d.Id, p)
-			}
-
-			if p.Type == voltha.Port_ETHERNET_NNI || p.Type == voltha.Port_ETHERNET_UNI {
-				if len(p.Peers) != 0 {
-					return status.Errorf(codes.Internal, "invalid length of peers:{%s, %d}", d.Id, p.Type)
-				}
-			} else if p.Type == voltha.Port_PON_OLT {
-				if len(p.Peers) != numONUsPerOLT ||
-					p.PortNo != uint32(1) {
-					return status.Errorf(codes.Internal, "invalid length of peers for PON OLT port:{%s, %v}", d.Id, p)
-				}
-			} else if p.Type == voltha.Port_PON_ONU {
-				if len(p.Peers) != 1 ||
-					p.PortNo != uint32(1) {
-					return status.Errorf(codes.Internal, "invalid length of peers for PON ONU port:{%s, %v}", d.Id, p)
-				}
-			}
-		}
-	}
-	return nil
-}
-
-func areAdaptersPresent(requiredAdapterNames []string, retrievedAdapters *voltha.Adapters) bool {
-	if len(requiredAdapterNames) == 0 {
-		return true
-	}
-	for _, nAName := range requiredAdapterNames {
-		found := false
-		for _, rA := range retrievedAdapters.Items {
-			if nAName == rA.Id {
-				found = true
-				break
-			}
-		}
-		if !found {
-			return false
-		}
-	}
-	return true
-}
-
-// WaitForAdapterRegistration waits on channel for response of list adapters
-func WaitForAdapterRegistration(stub voltha.VolthaServiceClient, requiredAdapterNames []string, timeout int) (*voltha.Adapters, error) {
-	fmt.Println("Waiting for adapter registration ...")
-	ui := uuid.New()
-	ctx := metadata.NewOutgoingContext(context.Background(), metadata.Pairs(VolthaSerialNumberKey, ui.String()))
-	ch := make(chan interface{})
-	defer close(ch)
-	for {
-		go sendListAdapters(ctx, stub, ch)
-		select {
-		case res, ok := <-ch:
-			if !ok {
-				return nil, status.Error(codes.Aborted, "channel closed")
-			} else if er, ok := res.(error); ok {
-				return nil, er
-			} else if a, ok := res.(*voltha.Adapters); ok {
-				if areAdaptersPresent(requiredAdapterNames, a) {
-					fmt.Println("All adapters registered:", a.Items)
-					return a, nil
-				}
-			}
-		case <-time.After(time.Duration(timeout) * time.Second):
-			return nil, status.Error(codes.Aborted, "timeout while waiting for adapter registration")
-		}
-		time.Sleep(1 * time.Second)
-	}
-}
-
-// PreProvisionDevice pre-provisions a new physical device
-func PreProvisionDevice(stub voltha.VolthaServiceClient) (*voltha.Device, error) {
-	ui := uuid.New()
-	ctx := metadata.NewOutgoingContext(context.Background(), metadata.Pairs(VolthaSerialNumberKey, ui.String()))
-	randomMacAddress := strings.ToUpper(com.GetRandomMacAddress())
-	device := &voltha.Device{Type: "simulated_olt", MacAddress: randomMacAddress}
-	ch := make(chan interface{})
-	defer close(ch)
-	go sendCreateDeviceRequest(ctx, stub, device, ch)
-	res, ok := <-ch
-	if !ok {
-		return nil, status.Error(codes.Aborted, "channel closed")
-	} else if er, ok := res.(error); ok {
-		return nil, er
-	} else if d, ok := res.(*voltha.Device); ok {
-		return d, nil
-	}
-	return nil, status.Errorf(codes.Unknown, "cannot provision device:{%v}", device)
-}
-
-// EnableDevice - if the device was in pre-provisioned state then it
-// will transition to ENABLED state.  If it was is DISABLED state then it
-// will transition to ENABLED state as well.
-func EnableDevice(stub voltha.VolthaServiceClient, device *voltha.Device, numONUs int) error {
-	if device.AdminState == voltha.AdminState_PREPROVISIONED {
-		ui := uuid.New()
-		ctx := metadata.NewOutgoingContext(context.Background(), metadata.Pairs(VolthaSerialNumberKey, ui.String()))
-		ch := make(chan interface{})
-		defer close(ch)
-		go sendEnableDeviceRequest(ctx, stub, device.Id, ch)
-		res, ok := <-ch
-		if !ok {
-			return status.Error(codes.Aborted, "channel closed")
-		} else if er, ok := res.(error); ok {
-			return er
-		} else if _, ok := res.(*empty.Empty); ok {
-			return nil
-		}
-	}
-	return status.Errorf(codes.Unknown, "cannot enable device:{%s}", device.Id)
-}
-
-// UpdateFlow updates flow table for logical device
-func UpdateFlow(stub voltha.VolthaServiceClient, flow *ofp.FlowTableUpdate) error {
-	ui := uuid.New()
-	ctx := metadata.NewOutgoingContext(context.Background(), metadata.Pairs(VolthaSerialNumberKey, ui.String()))
-	ch := make(chan interface{})
-	defer close(ch)
-	go sendFlow(ctx, stub, flow, ch)
-	res, ok := <-ch
-	if !ok {
-		return status.Error(codes.Aborted, "channel closed")
-	} else if er, ok := res.(error); ok {
-		return er
-	} else if _, ok := res.(*empty.Empty); ok {
-		return nil
-	}
-	return status.Errorf(codes.Unknown, "cannot add flow:{%v}", flow)
-}
-
-// StartSimulatedEnv starts kafka, etcd, olt, onu adapters, core
-func StartSimulatedEnv(composePath string) error {
-	fmt.Println("Starting simulated environment ...")
-	// Start kafka and Etcd
-	if err := startKafka(composePath); err != nil {
-		return err
-	}
-	if err := startEtcd(composePath); err != nil {
-		return err
-	}
-	time.Sleep(5 * time.Second)
-
-	//Start the simulated adapters
-	if err := startSimulatedOLTAndONUAdapters(composePath); err != nil {
-		return err
-	}
-
-	//Start the core
-	if err := startCore(composePath); err != nil {
-		return err
-	}
-
-	time.Sleep(10 * time.Second)
-
-	fmt.Println("Simulated environment started.")
-	return nil
-}
-
-// StopSimulatedEnv stops kafka, etcd, olt, onu adapters, core
-func StopSimulatedEnv(ctx context.Context, composePath string) error {
-	err := stopSimulatedOLTAndONUAdapters(composePath)
-	if err != nil {
-		logger.Errorw(ctx, "unable-to-stop-simulated-olt-onu-adapters", log.Fields{"error": err})
-	}
-	err = stopCore(composePath)
-	if err != nil {
-		logger.Errorw(ctx, "unable-to-stop-core", log.Fields{"error": err})
-	}
-	err = stopKafka(composePath)
-	if err != nil {
-		logger.Errorw(ctx, "unable-to-stop-kafka", log.Fields{"error": err})
-	}
-	err = stopEtcd(composePath)
-	if err != nil {
-		logger.Errorw(ctx, "unable-to-stop-etcd", log.Fields{"error": err})
-	}
-	return nil
-}
diff --git a/vendor/github.com/opencord/voltha-lib-go/v3/pkg/adapters/adapterif/core_proxy_if.go b/vendor/github.com/opencord/voltha-lib-go/v3/pkg/adapters/adapterif/core_proxy_if.go
index 9636a7d..a7ab6dc 100644
--- a/vendor/github.com/opencord/voltha-lib-go/v3/pkg/adapters/adapterif/core_proxy_if.go
+++ b/vendor/github.com/opencord/voltha-lib-go/v3/pkg/adapters/adapterif/core_proxy_if.go
@@ -18,6 +18,7 @@
 
 import (
 	"context"
+
 	"github.com/opencord/voltha-protos/v3/go/voltha"
 )
 
@@ -25,14 +26,13 @@
 type CoreProxy interface {
 	UpdateCoreReference(deviceID string, coreReference string)
 	DeleteCoreReference(deviceID string)
-	// getCoreTopic(deviceID string) kafka.Topic
-	//GetAdapterTopic(args ...string) kafka.Topic
-	// getAdapterTopic(args ...string) kafka.Topic
 	RegisterAdapter(ctx context.Context, adapter *voltha.Adapter, deviceTypes *voltha.DeviceTypes) error
 	DeviceUpdate(ctx context.Context, device *voltha.Device) error
 	PortCreated(ctx context.Context, deviceID string, port *voltha.Port) error
-	PortsStateUpdate(ctx context.Context, deviceID string, operStatus voltha.OperStatus_Types) error
+	PortsStateUpdate(ctx context.Context, deviceID string, portTypeFilter uint32, operStatus voltha.OperStatus_Types) error
 	DeleteAllPorts(ctx context.Context, deviceID string) error
+	GetDevicePort(ctx context.Context, deviceID string, portNo uint32) (*voltha.Port, error)
+	ListDevicePorts(ctx context.Context, deviceID string) ([]*voltha.Port, error)
 	DeviceStateUpdate(ctx context.Context, deviceID string,
 		connStatus voltha.ConnectStatus_Types, operStatus voltha.OperStatus_Types) error
 
diff --git a/vendor/github.com/opencord/voltha-lib-go/v3/pkg/adapters/common/core_proxy.go b/vendor/github.com/opencord/voltha-lib-go/v3/pkg/adapters/common/core_proxy.go
index 28b532f..505dc79 100644
--- a/vendor/github.com/opencord/voltha-lib-go/v3/pkg/adapters/common/core_proxy.go
+++ b/vendor/github.com/opencord/voltha-lib-go/v3/pkg/adapters/common/core_proxy.go
@@ -175,24 +175,22 @@
 	return unPackResponse(ctx, rpc, deviceId, success, result)
 }
 
-func (ap *CoreProxy) PortsStateUpdate(ctx context.Context, deviceId string, operStatus voltha.OperStatus_Types) error {
+func (ap *CoreProxy) PortsStateUpdate(ctx context.Context, deviceId string, portTypeFilter uint32, operStatus voltha.OperStatus_Types) error {
 	logger.Debugw(ctx, "PortsStateUpdate", log.Fields{"deviceId": deviceId})
 	rpc := "PortsStateUpdate"
 	// Use a device specific topic to send the request.  The adapter handling the device creates a device
 	// specific topic
 	toTopic := ap.getCoreTopic(deviceId)
-	args := make([]*kafka.KVArg, 2)
-	id := &voltha.ID{Id: deviceId}
-	oStatus := &ic.IntType{Val: int64(operStatus)}
-
-	args[0] = &kafka.KVArg{
+	args := []*kafka.KVArg{{
 		Key:   "device_id",
-		Value: id,
-	}
-	args[1] = &kafka.KVArg{
+		Value: &voltha.ID{Id: deviceId},
+	}, {
+		Key:   "port_type_filter",
+		Value: &ic.IntType{Val: int64(portTypeFilter)},
+	}, {
 		Key:   "oper_status",
-		Value: oStatus,
-	}
+		Value: &ic.IntType{Val: int64(operStatus)},
+	}}
 
 	// Use a device specific topic as we are the only adaptercore handling requests for this device
 	replyToTopic := ap.getAdapterTopic()
@@ -222,6 +220,77 @@
 	return unPackResponse(ctx, rpc, deviceId, success, result)
 }
 
+func (ap *CoreProxy) GetDevicePort(ctx context.Context, deviceID string, portNo uint32) (*voltha.Port, error) {
+	logger.Debugw(ctx, "GetDevicePort", log.Fields{"device-id": deviceID})
+	rpc := "GetDevicePort"
+
+	toTopic := ap.getCoreTopic(deviceID)
+	replyToTopic := ap.getAdapterTopic()
+
+	args := []*kafka.KVArg{{
+		Key:   "device_id",
+		Value: &voltha.ID{Id: deviceID},
+	}, {
+		Key:   "port_no",
+		Value: &ic.IntType{Val: int64(portNo)},
+	}}
+
+	success, result := ap.kafkaICProxy.InvokeRPC(context.Background(), rpc, &toTopic, &replyToTopic, true, deviceID, args...)
+	logger.Debugw(ctx, "GetDevicePort-response", log.Fields{"device-id": deviceID, "success": success})
+
+	if success {
+		port := &voltha.Port{}
+		if err := ptypes.UnmarshalAny(result, port); err != nil {
+			logger.Warnw(ctx, "cannot-unmarshal-response", log.Fields{"error": err})
+			return nil, status.Error(codes.InvalidArgument, err.Error())
+		}
+		return port, nil
+	} else {
+		unpackResult := &ic.Error{}
+		var err error
+		if err = ptypes.UnmarshalAny(result, unpackResult); err != nil {
+			logger.Warnw(ctx, "cannot-unmarshal-response", log.Fields{"error": err})
+		}
+		logger.Debugw(ctx, "GetDevicePort-return", log.Fields{"device-id": deviceID, "success": success, "error": err})
+		// TODO:  Need to get the real error code
+		return nil, status.Error(ICProxyErrorCodeToGrpcErrorCode(ctx, unpackResult.Code), unpackResult.Reason)
+	}
+}
+
+func (ap *CoreProxy) ListDevicePorts(ctx context.Context, deviceID string) ([]*voltha.Port, error) {
+	logger.Debugw(ctx, "ListDevicePorts", log.Fields{"device-id": deviceID})
+	rpc := "ListDevicePorts"
+
+	toTopic := ap.getCoreTopic(deviceID)
+	replyToTopic := ap.getAdapterTopic()
+
+	args := []*kafka.KVArg{{
+		Key:   "device_id",
+		Value: &voltha.ID{Id: deviceID},
+	}}
+
+	success, result := ap.kafkaICProxy.InvokeRPC(context.Background(), rpc, &toTopic, &replyToTopic, true, deviceID, args...)
+	logger.Debugw(ctx, "ListDevicePorts-response", log.Fields{"device-id": deviceID, "success": success})
+
+	if success {
+		ports := &voltha.Ports{}
+		if err := ptypes.UnmarshalAny(result, ports); err != nil {
+			logger.Warnw(ctx, "cannot-unmarshal-response", log.Fields{"error": err})
+			return nil, status.Error(codes.InvalidArgument, err.Error())
+		}
+		return ports.Items, nil
+	} else {
+		unpackResult := &ic.Error{}
+		var err error
+		if err = ptypes.UnmarshalAny(result, unpackResult); err != nil {
+			logger.Warnw(ctx, "cannot-unmarshal-response", log.Fields{"error": err})
+		}
+		logger.Debugw(ctx, "ListDevicePorts-return", log.Fields{"device-id": deviceID, "success": success, "error": err})
+		// TODO:  Need to get the real error code
+		return nil, status.Error(ICProxyErrorCodeToGrpcErrorCode(ctx, unpackResult.Code), unpackResult.Reason)
+	}
+}
+
 func (ap *CoreProxy) DeviceStateUpdate(ctx context.Context, deviceId string,
 	connStatus voltha.ConnectStatus_Types, operStatus voltha.OperStatus_Types) error {
 	logger.Debugw(ctx, "DeviceStateUpdate", log.Fields{"deviceId": deviceId})
diff --git a/vendor/github.com/opencord/voltha-protos/v3/go/voltha/adapter.pb.go b/vendor/github.com/opencord/voltha-protos/v3/go/voltha/adapter.pb.go
index 9359dc1..3d12f3f 100644
--- a/vendor/github.com/opencord/voltha-protos/v3/go/voltha/adapter.pb.go
+++ b/vendor/github.com/opencord/voltha-protos/v3/go/voltha/adapter.pb.go
@@ -238,34 +238,34 @@
 func init() { proto.RegisterFile("voltha_protos/adapter.proto", fileDescriptor_7e998ce153307274) }
 
 var fileDescriptor_7e998ce153307274 = []byte{
-	// 463 bytes of a gzipped FileDescriptorProto
+	// 455 bytes of a gzipped FileDescriptorProto
 	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x52, 0xdd, 0x6e, 0xd3, 0x30,
-	0x14, 0x56, 0xda, 0x35, 0x6d, 0x3d, 0x15, 0x3a, 0x43, 0x91, 0x09, 0x9a, 0x16, 0x55, 0x80, 0x72,
-	0xc1, 0x12, 0xb1, 0xbd, 0x00, 0xed, 0x76, 0xb3, 0x5b, 0x6b, 0xe2, 0x82, 0x9b, 0xca, 0xb5, 0xbd,
-	0xcc, 0x52, 0xe2, 0x13, 0xc5, 0x6e, 0xa4, 0x3e, 0x24, 0x2f, 0xc0, 0x13, 0xf0, 0x04, 0x5c, 0xa3,
-	0x3a, 0x0e, 0xfd, 0x41, 0xda, 0x55, 0x72, 0xbe, 0xef, 0x3b, 0xdf, 0xf9, 0x33, 0xfa, 0xd0, 0x40,
-	0x61, 0x9f, 0xd9, 0xaa, 0xaa, 0xc1, 0x82, 0xc9, 0x98, 0x60, 0x95, 0x95, 0x75, 0xea, 0x42, 0x1c,
-	0xb6, 0x64, 0xf4, 0x3e, 0x07, 0xc8, 0x0b, 0x99, 0x39, 0x74, 0xbd, 0x79, 0xca, 0x98, 0xde, 0xb6,
-	0x92, 0x28, 0x3a, 0xce, 0xe7, 0x50, 0x96, 0xa0, 0x3d, 0x47, 0x8e, 0xb9, 0x52, 0x5a, 0xe6, 0x99,
-	0xab, 0x53, 0x43, 0xab, 0x4a, 0x69, 0x2c, 0x2b, 0xab, 0x56, 0x30, 0xa7, 0x68, 0xb2, 0x68, 0x5b,
-	0xb9, 0x03, 0xfd, 0xa4, 0x72, 0xbc, 0x40, 0x17, 0x4c, 0x08, 0x65, 0x15, 0x68, 0x56, 0xac, 0xb8,
-	0x03, 0xc9, 0xb7, 0x38, 0x48, 0xce, 0x6f, 0xde, 0xa6, 0xad, 0x5b, 0xda, 0xb9, 0xa5, 0x0b, 0xbd,
-	0xa5, 0xd3, 0xbd, 0xbc, 0xb5, 0x98, 0xff, 0xea, 0xa3, 0xa1, 0x37, 0xc5, 0x33, 0xd4, 0x53, 0x82,
-	0x04, 0x71, 0x90, 0x8c, 0x97, 0x83, 0xdf, 0x7f, 0x7e, 0x5e, 0x06, 0xb4, 0xa7, 0x04, 0xbe, 0x44,
-	0x61, 0x23, 0xb5, 0x80, 0x9a, 0xf4, 0x0e, 0x29, 0x0f, 0xe2, 0x2b, 0x34, 0x6c, 0x64, 0x6d, 0x14,
-	0x68, 0xd2, 0x3f, 0xe4, 0x3b, 0x14, 0x5f, 0xa3, 0xd0, 0xb7, 0x36, 0x75, 0xad, 0xcd, 0xd2, 0x76,
-	0x05, 0xe9, 0xd1, 0x30, 0xd4, 0x8b, 0x30, 0x45, 0xef, 0x0e, 0x86, 0x12, 0xd2, 0xf0, 0x5a, 0x55,
-	0xbb, 0xe8, 0xa5, 0xc9, 0xba, 0xa2, 0xb3, 0x7d, 0xea, 0xfd, 0x3e, 0x13, 0x7f, 0x41, 0xb8, 0x80,
-	0x5c, 0x71, 0x67, 0xd8, 0x28, 0x2e, 0x57, 0x4a, 0x18, 0x72, 0x16, 0xf7, 0x93, 0x31, 0x9d, 0x7a,
-	0xe6, 0xde, 0x11, 0x0f, 0xc2, 0xe0, 0x07, 0x84, 0x0b, 0x66, 0xec, 0x6a, 0x77, 0xb7, 0x8d, 0x56,
-	0x9c, 0xb9, 0xea, 0x03, 0x57, 0x3d, 0xfa, 0xaf, 0xfa, 0x63, 0x77, 0x25, 0x7a, 0xb1, 0xcb, 0xba,
-	0x3b, 0x4c, 0xc2, 0x9f, 0xd1, 0x2b, 0xbe, 0xa9, 0x6b, 0xa9, 0x2d, 0x95, 0x55, 0xa1, 0x38, 0x23,
-	0x61, 0x1c, 0x24, 0x03, 0x7a, 0x82, 0xe2, 0x8f, 0x68, 0x62, 0xc1, 0xb2, 0xc2, 0xc7, 0x86, 0x0c,
-	0x9d, 0xec, 0x18, 0xc4, 0x11, 0x1a, 0x49, 0x2d, 0x2a, 0x50, 0xda, 0x92, 0xd1, 0x6e, 0xd7, 0xf4,
-	0x5f, 0x8c, 0x31, 0x3a, 0xb3, 0xdb, 0x4a, 0x92, 0xb1, 0xc3, 0xdd, 0xff, 0xfc, 0x2b, 0x1a, 0xf9,
-	0x1d, 0x1b, 0xfc, 0x09, 0x0d, 0x94, 0x95, 0xa5, 0x21, 0x41, 0xdc, 0x4f, 0xce, 0x6f, 0x5e, 0x9f,
-	0x1c, 0x81, 0xb6, 0xec, 0xf2, 0x11, 0xbd, 0x81, 0x3a, 0x4f, 0xa1, 0x92, 0x9a, 0x43, 0x2d, 0xbc,
-	0x6a, 0x39, 0xf9, 0xee, 0xbe, 0x5e, 0xfc, 0x23, 0xcd, 0x95, 0x7d, 0xde, 0xac, 0x53, 0x0e, 0x65,
-	0xd6, 0x49, 0xb3, 0x56, 0x7a, 0xed, 0x1f, 0x76, 0x73, 0x9b, 0xe5, 0xe0, 0xb1, 0x75, 0xe8, 0xc0,
-	0xdb, 0xbf, 0x01, 0x00, 0x00, 0xff, 0xff, 0xef, 0x64, 0x5e, 0x10, 0x59, 0x03, 0x00, 0x00,
+	0x14, 0x56, 0xda, 0xf5, 0xcf, 0x53, 0xa1, 0x33, 0x14, 0x99, 0xa2, 0x69, 0x51, 0x05, 0x28, 0x17,
+	0x2c, 0x11, 0xdb, 0x0b, 0xd0, 0x6e, 0x37, 0xbb, 0xb5, 0x26, 0x2e, 0xb8, 0xa9, 0x5c, 0xdb, 0xcb,
+	0x2c, 0x25, 0x3e, 0x51, 0xec, 0x46, 0xea, 0x43, 0xf2, 0x02, 0x3c, 0x01, 0x4f, 0xc0, 0x35, 0xaa,
+	0xed, 0xd0, 0x1f, 0xa4, 0x5d, 0x25, 0xe7, 0xfb, 0x39, 0x9f, 0xcf, 0xb1, 0xd1, 0x87, 0x06, 0x0a,
+	0xfb, 0xcc, 0x56, 0x55, 0x0d, 0x16, 0x4c, 0xc6, 0x04, 0xab, 0xac, 0xac, 0x53, 0x57, 0xe2, 0xbe,
+	0x27, 0x67, 0xef, 0x73, 0x80, 0xbc, 0x90, 0x99, 0x43, 0xd7, 0x9b, 0xa7, 0x8c, 0xe9, 0xad, 0x97,
+	0xcc, 0xc8, 0xb1, 0xbf, 0x94, 0x96, 0x05, 0xe6, 0xea, 0xd4, 0x64, 0x55, 0x29, 0x8d, 0x65, 0x65,
+	0xe5, 0x05, 0x73, 0x8a, 0xc6, 0x0b, 0x1f, 0x77, 0x07, 0xfa, 0x49, 0xe5, 0x78, 0x81, 0x2e, 0x98,
+	0x10, 0xca, 0x2a, 0xd0, 0xac, 0x58, 0x71, 0x07, 0x92, 0x6f, 0x71, 0x94, 0x9c, 0xdf, 0xbc, 0x4d,
+	0x7d, 0xb7, 0xb4, 0xed, 0x96, 0x2e, 0xf4, 0x96, 0x4e, 0xf6, 0x72, 0xdf, 0x62, 0xfe, 0xab, 0x8b,
+	0x06, 0xa1, 0x29, 0x9e, 0xa2, 0x8e, 0x12, 0x24, 0x8a, 0xa3, 0x64, 0xb4, 0xec, 0xfd, 0xfe, 0xf3,
+	0xf3, 0x32, 0xa2, 0x1d, 0x25, 0xf0, 0x25, 0xea, 0x37, 0x52, 0x0b, 0xa8, 0x49, 0xe7, 0x90, 0x0a,
+	0x20, 0xbe, 0x42, 0x83, 0x46, 0xd6, 0x46, 0x81, 0x26, 0xdd, 0x43, 0xbe, 0x45, 0xf1, 0x35, 0xea,
+	0x87, 0xa3, 0x4d, 0xdc, 0xd1, 0xa6, 0xa9, 0x5f, 0x41, 0x7a, 0x34, 0x0c, 0x0d, 0x22, 0x4c, 0xd1,
+	0xbb, 0x83, 0xa1, 0x84, 0x34, 0xbc, 0x56, 0xd5, 0xae, 0x7a, 0x69, 0xb2, 0x36, 0x74, 0xba, 0xb7,
+	0xde, 0xef, 0x9d, 0xf8, 0x0b, 0xc2, 0x05, 0xe4, 0x8a, 0xbb, 0x86, 0x8d, 0xe2, 0x72, 0xa5, 0x84,
+	0x21, 0x67, 0x71, 0x37, 0x19, 0xd1, 0x49, 0x60, 0xee, 0x1d, 0xf1, 0x20, 0x0c, 0x7e, 0x40, 0xb8,
+	0x60, 0xc6, 0xae, 0x38, 0x94, 0xe5, 0x46, 0x2b, 0xce, 0x5c, 0x7a, 0xcf, 0xa5, 0xcf, 0xfe, 0x4b,
+	0x7f, 0x6c, 0x6f, 0x89, 0x5e, 0xec, 0x5c, 0x77, 0x87, 0x26, 0xfc, 0x19, 0xbd, 0xe2, 0x9b, 0xba,
+	0x96, 0xda, 0x52, 0x59, 0x15, 0x8a, 0x33, 0xd2, 0x8f, 0xa3, 0xa4, 0x47, 0x4f, 0x50, 0xfc, 0x11,
+	0x8d, 0x2d, 0x58, 0x56, 0x84, 0xda, 0x90, 0x81, 0x93, 0x1d, 0x83, 0x78, 0x86, 0x86, 0x52, 0x8b,
+	0x0a, 0x94, 0xb6, 0x64, 0xb8, 0xdb, 0x35, 0xfd, 0x57, 0x63, 0x8c, 0xce, 0xec, 0xb6, 0x92, 0x64,
+	0xe4, 0x70, 0xf7, 0x3f, 0xff, 0x8a, 0x86, 0x61, 0xc7, 0x06, 0x7f, 0x42, 0x3d, 0x65, 0x65, 0x69,
+	0x48, 0x14, 0x77, 0x93, 0xf3, 0x9b, 0xd7, 0x27, 0x97, 0x40, 0x3d, 0xbb, 0x7c, 0x44, 0x6f, 0xa0,
+	0xce, 0x53, 0xa8, 0xa4, 0xe6, 0x50, 0x8b, 0xa0, 0x5a, 0x8e, 0xbf, 0xbb, 0x6f, 0x10, 0xff, 0x48,
+	0x73, 0x65, 0x9f, 0x37, 0xeb, 0x94, 0x43, 0x99, 0xb5, 0xd2, 0xcc, 0x4b, 0xaf, 0xc3, 0xc3, 0x6e,
+	0x6e, 0xb3, 0x1c, 0x02, 0xb6, 0xee, 0x3b, 0xf0, 0xf6, 0x6f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x4c,
+	0x2f, 0x33, 0x61, 0x3d, 0x03, 0x00, 0x00,
 }
diff --git a/vendor/github.com/opencord/voltha-protos/v3/go/voltha/device.pb.go b/vendor/github.com/opencord/voltha-protos/v3/go/voltha/device.pb.go
index ebbd8dc..764edcf 100644
--- a/vendor/github.com/opencord/voltha-protos/v3/go/voltha/device.pb.go
+++ b/vendor/github.com/opencord/voltha-protos/v3/go/voltha/device.pb.go
@@ -501,6 +501,7 @@
 	FreqOverride         bool             `protobuf:"varint,4,opt,name=freq_override,json=freqOverride,proto3" json:"freq_override,omitempty"`
 	Groups               []*PmGroupConfig `protobuf:"bytes,5,rep,name=groups,proto3" json:"groups,omitempty"`
 	Metrics              []*PmConfig      `protobuf:"bytes,6,rep,name=metrics,proto3" json:"metrics,omitempty"`
+	MaxSkew              uint32           `protobuf:"varint,7,opt,name=max_skew,json=maxSkew,proto3" json:"max_skew,omitempty"`
 	XXX_NoUnkeyedLiteral struct{}         `json:"-"`
 	XXX_unrecognized     []byte           `json:"-"`
 	XXX_sizecache        int32            `json:"-"`
@@ -573,6 +574,13 @@
 	return nil
 }
 
+func (m *PmConfigs) GetMaxSkew() uint32 {
+	if m != nil {
+		return m.MaxSkew
+	}
+	return 0
+}
+
 // Describes instance of software image on the device
 type Image struct {
 	Name            string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
@@ -712,6 +720,7 @@
 	return nil
 }
 
+//TODO: ImageDownload is not actively used (05/19/2020).  When this is tackled, can remove extra/unnecessary fields.
 type ImageDownload struct {
 	// Device Identifier
 	Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
@@ -1172,10 +1181,7 @@
 	Reason        string                     `protobuf:"bytes,22,opt,name=reason,proto3" json:"reason,omitempty"`
 	ConnectStatus common.ConnectStatus_Types `protobuf:"varint,18,opt,name=connect_status,json=connectStatus,proto3,enum=common.ConnectStatus_Types" json:"connect_status,omitempty"`
 	// Device type specific attributes
-	Custom     *any.Any                `protobuf:"bytes,64,opt,name=custom,proto3" json:"custom,omitempty"`
-	Ports      []*Port                 `protobuf:"bytes,128,rep,name=ports,proto3" json:"ports,omitempty"`
-	Flows      *openflow_13.Flows      `protobuf:"bytes,129,opt,name=flows,proto3" json:"flows,omitempty"`
-	FlowGroups *openflow_13.FlowGroups `protobuf:"bytes,130,opt,name=flow_groups,json=flowGroups,proto3" json:"flow_groups,omitempty"`
+	Custom *any.Any `protobuf:"bytes,64,opt,name=custom,proto3" json:"custom,omitempty"`
 	// PmConfigs will eventually converted to a child node of the
 	// device to falicitata callbacks and to simplify manipulation.
 	PmConfigs            *PmConfigs       `protobuf:"bytes,131,opt,name=pm_configs,json=pmConfigs,proto3" json:"pm_configs,omitempty"`
@@ -1414,27 +1420,6 @@
 	return nil
 }
 
-func (m *Device) GetPorts() []*Port {
-	if m != nil {
-		return m.Ports
-	}
-	return nil
-}
-
-func (m *Device) GetFlows() *openflow_13.Flows {
-	if m != nil {
-		return m.Flows
-	}
-	return nil
-}
-
-func (m *Device) GetFlowGroups() *openflow_13.FlowGroups {
-	if m != nil {
-		return m.FlowGroups
-	}
-	return nil
-}
-
 func (m *Device) GetPmConfigs() *PmConfigs {
 	if m != nil {
 		return m.PmConfigs
@@ -1724,154 +1709,152 @@
 func init() { proto.RegisterFile("voltha_protos/device.proto", fileDescriptor_200940f73d155856) }
 
 var fileDescriptor_200940f73d155856 = []byte{
-	// 2383 bytes of a gzipped FileDescriptorProto
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x58, 0x4d, 0x6f, 0xdb, 0xc8,
-	0xf9, 0x8f, 0x64, 0x93, 0x12, 0x1f, 0xbd, 0x98, 0x99, 0x38, 0x1b, 0x26, 0xfe, 0x1b, 0xc9, 0x5f,
-	0xd9, 0xa2, 0xde, 0x6c, 0x63, 0xa7, 0x9b, 0x62, 0x77, 0x7b, 0x28, 0x10, 0x59, 0x62, 0x12, 0xa2,
-	0xae, 0xec, 0x8e, 0x24, 0x6f, 0xdb, 0x0b, 0x41, 0x8b, 0x23, 0x9b, 0x08, 0xc9, 0x51, 0x86, 0x94,
-	0xe3, 0xec, 0xa9, 0xed, 0xa2, 0x3d, 0xf5, 0xd6, 0x2f, 0xd1, 0x6f, 0xb0, 0xc7, 0x16, 0xe8, 0x79,
-	0xd1, 0xef, 0xd0, 0x02, 0x45, 0x3f, 0xc1, 0x9e, 0x8b, 0x79, 0x86, 0x23, 0x91, 0x49, 0x9a, 0x6d,
-	0x2f, 0xb6, 0xe6, 0xf7, 0xbc, 0xcc, 0xcc, 0x6f, 0x66, 0x9e, 0x17, 0xc2, 0x9d, 0x4b, 0x1e, 0xe7,
-	0x17, 0x81, 0xbf, 0x10, 0x3c, 0xe7, 0xd9, 0x41, 0xc8, 0x2e, 0xa3, 0x19, 0xdb, 0xc7, 0x11, 0x31,
-	0x95, 0xec, 0xce, 0xed, 0x73, 0xce, 0xcf, 0x63, 0x76, 0x80, 0xe8, 0xd9, 0x72, 0x7e, 0x10, 0xa4,
-	0xaf, 0x95, 0xca, 0x9d, 0x37, 0xcc, 0x67, 0x3c, 0x49, 0x78, 0x5a, 0xc8, 0x9c, 0xaa, 0x2c, 0x61,
-	0x79, 0x50, 0x48, 0xee, 0x56, 0x25, 0x7c, 0xc1, 0xd2, 0x79, 0xcc, 0x5f, 0xf9, 0x3f, 0x7c, 0xac,
-	0x14, 0x7a, 0x7f, 0xae, 0x03, 0x0c, 0x71, 0x29, 0x93, 0xd7, 0x0b, 0x46, 0xba, 0x50, 0x8f, 0x42,
-	0xa7, 0x76, 0xaf, 0xb6, 0x67, 0xd1, 0x7a, 0x14, 0x92, 0x1d, 0xb0, 0x2e, 0x59, 0x1a, 0x72, 0xe1,
-	0x47, 0xa1, 0x63, 0x20, 0xdc, 0x54, 0x80, 0x17, 0x92, 0x5d, 0x80, 0x95, 0x30, 0x73, 0xcc, 0x7b,
-	0x1b, 0x7b, 0x16, 0xb5, 0xb4, 0x34, 0x23, 0x0e, 0x34, 0x82, 0x30, 0x58, 0xe4, 0x4c, 0x38, 0x75,
-	0xb4, 0xd4, 0x43, 0xf2, 0x19, 0x38, 0xc1, 0x6c, 0xc6, 0x16, 0x79, 0xe6, 0x9f, 0x2d, 0xe3, 0x17,
-	0x3e, 0x2e, 0x69, 0xb9, 0x08, 0x83, 0x9c, 0x39, 0x1b, 0xf7, 0x6a, 0x7b, 0x4d, 0x7a, 0xb3, 0x90,
-	0x1f, 0x2e, 0xe3, 0x17, 0x4f, 0x63, 0xfe, 0x6a, 0x8a, 0x42, 0x32, 0x84, 0xbb, 0xda, 0x30, 0x08,
-	0x43, 0x5f, 0xb0, 0x84, 0x5f, 0xb2, 0xb2, 0x79, 0xe6, 0x6c, 0xa2, 0xfd, 0x4e, 0xa1, 0xd6, 0x0f,
-	0x43, 0x8a, 0x4a, 0x6b, 0x27, 0x19, 0x39, 0x82, 0xfb, 0xda, 0x4b, 0x18, 0x09, 0x36, 0xcb, 0xfd,
-	0x98, 0x9f, 0x47, 0xb3, 0x20, 0x46, 0x4f, 0x99, 0x5e, 0x49, 0x03, 0x3d, 0xe9, 0x09, 0x87, 0xa8,
-	0x79, 0xa4, 0x14, 0xa5, 0xb7, 0x4c, 0xb9, 0xeb, 0x7d, 0x06, 0xad, 0x35, 0x81, 0x19, 0xd9, 0x03,
-	0x23, 0xca, 0x59, 0x92, 0x39, 0xb5, 0x7b, 0x1b, 0x7b, 0xad, 0x4f, 0xc8, 0xbe, 0x3a, 0x81, 0xfd,
-	0xb5, 0x0e, 0x55, 0x0a, 0xbd, 0xbf, 0xd4, 0xa0, 0x79, 0x92, 0x0c, 0x78, 0x3a, 0x8f, 0xce, 0x09,
-	0x81, 0xcd, 0x34, 0x48, 0x58, 0x41, 0x3d, 0xfe, 0x26, 0x1f, 0xc3, 0x66, 0xfe, 0x7a, 0xc1, 0x90,
-	0xbd, 0xee, 0x27, 0xb7, 0xb4, 0x27, 0x6d, 0xb3, 0x7f, 0x92, 0xa0, 0x3b, 0x54, 0x92, 0x6c, 0xb3,
-	0x34, 0x38, 0x8b, 0x59, 0x58, 0x50, 0xa8, 0x87, 0xe4, 0x2e, 0xb4, 0xb2, 0x20, 0x59, 0xc4, 0xcc,
-	0x9f, 0x0b, 0xf6, 0x12, 0x09, 0xea, 0x50, 0x50, 0xd0, 0x53, 0xc1, 0x5e, 0xf6, 0x3e, 0x07, 0x53,
-	0xb9, 0x22, 0x2d, 0x68, 0x0c, 0x8e, 0xa7, 0xa3, 0x89, 0x4b, 0xed, 0x6b, 0xc4, 0x02, 0xe3, 0x59,
-	0x7f, 0xfa, 0xcc, 0xb5, 0x6b, 0xf2, 0xe7, 0x78, 0xd2, 0x9f, 0xb8, 0x76, 0x5d, 0xa9, 0x8c, 0x26,
-	0xee, 0x2f, 0x26, 0xf6, 0x46, 0xef, 0x8f, 0x35, 0xe8, 0x9c, 0x24, 0xcf, 0x04, 0x5f, 0x2e, 0x8a,
-	0x7d, 0xec, 0x02, 0x9c, 0xcb, 0xa1, 0x5f, 0xda, 0x8d, 0x85, 0xc8, 0x48, 0x6e, 0x69, 0x25, 0xc6,
-	0xa5, 0xd4, 0x71, 0x29, 0x4a, 0x2c, 0x57, 0xf2, 0x9e, 0x4d, 0x3c, 0x80, 0x46, 0xc2, 0x72, 0x11,
-	0xcd, 0xe4, 0x09, 0x4b, 0x62, 0xed, 0x37, 0xe9, 0xa0, 0x5a, 0xa1, 0xf7, 0xcf, 0x1a, 0x58, 0x1a,
-	0xcd, 0xde, 0xba, 0xd2, 0xff, 0x0f, 0xed, 0x90, 0xcd, 0x83, 0x65, 0x9c, 0x97, 0x17, 0xd1, 0x2a,
-	0x30, 0x5c, 0xc6, 0x5d, 0x68, 0xe0, 0x9a, 0xf4, 0x32, 0x0e, 0x8d, 0x7f, 0x7d, 0xfb, 0xcd, 0x6e,
-	0x8d, 0x6a, 0x94, 0x3c, 0x80, 0x8e, 0xb4, 0xf5, 0xf9, 0x25, 0x13, 0x22, 0x0a, 0x99, 0xba, 0x75,
-	0x5a, 0xad, 0x2d, 0x65, 0xc7, 0x85, 0x88, 0x3c, 0x04, 0x13, 0xcd, 0x32, 0xc7, 0xc0, 0x85, 0xdf,
-	0x5c, 0x2f, 0xbc, 0x44, 0x1c, 0x2d, 0x94, 0xca, 0x1b, 0x35, 0xbf, 0x6b, 0xa3, 0x7f, 0xab, 0x81,
-	0xe1, 0x25, 0xc1, 0x39, 0x7b, 0xe7, 0xf5, 0x71, 0xa0, 0x71, 0xc9, 0x44, 0x16, 0xf1, 0x54, 0xbf,
-	0xbf, 0x62, 0x28, 0xb5, 0x2f, 0x82, 0xec, 0x02, 0x37, 0x67, 0x51, 0xfc, 0x4d, 0x3e, 0x02, 0x3b,
-	0x4a, 0xb3, 0x3c, 0x88, 0x63, 0x5f, 0x5e, 0xeb, 0x3c, 0x4a, 0xd4, 0xae, 0x2c, 0xba, 0x55, 0xe0,
-	0xc3, 0x02, 0x96, 0x41, 0x21, 0xca, 0xfc, 0x60, 0x96, 0x47, 0x97, 0x0c, 0x83, 0x42, 0x93, 0x36,
-	0xa3, 0xac, 0x8f, 0x63, 0x49, 0x6f, 0x94, 0xf9, 0x32, 0x3c, 0x45, 0x79, 0xce, 0x42, 0xc7, 0x44,
-	0x79, 0x2b, 0xca, 0x06, 0x1a, 0x22, 0xb7, 0xa1, 0x19, 0x65, 0xfe, 0x65, 0x10, 0x47, 0x61, 0xf1,
-	0xc8, 0x1a, 0x51, 0x76, 0x2a, 0x87, 0xbd, 0x87, 0x60, 0xe2, 0x86, 0x32, 0x72, 0x1f, 0x8c, 0x48,
-	0xfe, 0x2a, 0xde, 0x51, 0x47, 0xb3, 0x80, 0x62, 0xaa, 0x64, 0xbd, 0x7f, 0x34, 0xa0, 0x83, 0xc0,
-	0x90, 0xbf, 0x4a, 0x63, 0x1e, 0x84, 0x6f, 0x9d, 0xb6, 0x26, 0xa6, 0x5e, 0x22, 0xc6, 0x86, 0x8d,
-	0xa5, 0x88, 0x8b, 0xdd, 0xcb, 0x9f, 0x12, 0x99, 0x89, 0x59, 0xf1, 0x34, 0xe4, 0x4f, 0x72, 0x0c,
-	0xdd, 0xb0, 0xf0, 0xe9, 0x67, 0xb9, 0x0c, 0x07, 0x06, 0xbe, 0xc2, 0xbd, 0xca, 0x3a, 0xf4, 0xb4,
-	0xd5, 0xd1, 0x58, 0xea, 0xd3, 0x4e, 0x58, 0x1e, 0x92, 0xfb, 0xd0, 0xc1, 0x35, 0xfb, 0xfa, 0x4c,
-	0x4c, 0x9c, 0xbe, 0x8d, 0xe0, 0x69, 0x71, 0x30, 0x1f, 0x81, 0xad, 0xad, 0x58, 0xe8, 0x9f, 0xbd,
-	0x96, 0x01, 0xad, 0x81, 0x8b, 0xda, 0x5a, 0xe3, 0x87, 0x12, 0x26, 0xcf, 0xc1, 0x14, 0x2c, 0xc8,
-	0x78, 0xea, 0x34, 0x71, 0x61, 0x8f, 0xfe, 0x8b, 0x85, 0x3d, 0x0d, 0xa2, 0x78, 0x29, 0x18, 0x45,
-	0x3b, 0x5a, 0xd8, 0x93, 0xef, 0xc3, 0x56, 0x10, 0x86, 0x51, 0x1e, 0xf1, 0x34, 0x88, 0xfd, 0x28,
-	0x9d, 0x73, 0xc7, 0xc2, 0xb5, 0x75, 0xd7, 0xb0, 0x97, 0xce, 0xb9, 0x0a, 0x24, 0x97, 0xcc, 0x9f,
-	0xe1, 0x35, 0x74, 0x00, 0x8f, 0x0e, 0x24, 0x54, 0x3c, 0xfe, 0x1d, 0xb0, 0x62, 0x2e, 0xe3, 0x68,
-	0x18, 0x09, 0xa7, 0xa5, 0xb2, 0x05, 0x02, 0xc3, 0x48, 0x10, 0x0f, 0x5a, 0x8a, 0x00, 0x45, 0x67,
-	0xfb, 0x3b, 0xe9, 0xc4, 0x0b, 0x15, 0xe4, 0x4c, 0xd1, 0x09, 0x68, 0xac, 0xb8, 0xdc, 0x01, 0x6b,
-	0x1e, 0xc5, 0xcc, 0xcf, 0xa2, 0x2f, 0x99, 0xd3, 0x41, 0x7e, 0x9a, 0x12, 0x18, 0x47, 0x5f, 0xb2,
-	0xde, 0xd7, 0x35, 0x20, 0x6f, 0x1f, 0x07, 0xd9, 0x06, 0x7b, 0x78, 0xfc, 0xc5, 0xe8, 0xe8, 0xb8,
-	0x3f, 0xf4, 0xa7, 0xa3, 0x9f, 0x8e, 0x8e, 0xbf, 0x18, 0xd9, 0xd7, 0xc8, 0x07, 0x40, 0x56, 0xe8,
-	0x78, 0x3a, 0x18, 0xb8, 0xee, 0xd0, 0x1d, 0xda, 0xb5, 0x0a, 0x4e, 0xdd, 0x9f, 0x4f, 0xdd, 0xf1,
-	0xc4, 0x1d, 0xda, 0xf5, 0x8a, 0x97, 0xf1, 0xa4, 0x4f, 0x25, 0xba, 0x41, 0x6e, 0xc0, 0xd6, 0x0a,
-	0x7d, 0xda, 0xf7, 0x8e, 0xdc, 0xa1, 0xbd, 0x49, 0x1c, 0xd8, 0x2e, 0x4d, 0x38, 0x9e, 0x9e, 0x9c,
-	0x1c, 0xa3, 0xba, 0x51, 0x71, 0x3e, 0xe8, 0x8f, 0x06, 0xee, 0x91, 0xb4, 0x30, 0x7b, 0xbf, 0xaf,
-	0xc1, 0x9d, 0xff, 0x7c, 0x5e, 0xa4, 0x0d, 0xcd, 0xd1, 0xb1, 0xef, 0x52, 0x7a, 0x2c, 0xa3, 0xf3,
-	0x16, 0xb4, 0xbc, 0xd1, 0x69, 0xff, 0xc8, 0x1b, 0xfa, 0x53, 0x7a, 0x64, 0xd7, 0x24, 0x30, 0x74,
-	0x4f, 0xbd, 0x81, 0xeb, 0x1f, 0x4e, 0xc7, 0xbf, 0xb4, 0xeb, 0x72, 0x1a, 0x6f, 0x34, 0x9e, 0x3e,
-	0x7d, 0xea, 0x0d, 0x3c, 0x77, 0x34, 0xf1, 0xc7, 0x27, 0xfd, 0x81, 0x6b, 0x6f, 0x90, 0xeb, 0xd0,
-	0x29, 0x08, 0x28, 0x9c, 0x6d, 0x92, 0x0e, 0x58, 0xeb, 0x85, 0x18, 0xbd, 0x3f, 0x68, 0x0a, 0x2b,
-	0x47, 0x20, 0x0d, 0xbd, 0x9f, 0xf5, 0x9f, 0xb9, 0x25, 0xfe, 0x08, 0x74, 0x15, 0xe4, 0x8d, 0xfa,
-	0x83, 0x89, 0x77, 0x2a, 0x93, 0xc5, 0x36, 0xd8, 0x0a, 0x43, 0xa4, 0x3f, 0xf1, 0x46, 0xcf, 0xec,
-	0x3a, 0xb1, 0xa1, 0x5d, 0x42, 0x5d, 0xc5, 0x9a, 0x42, 0xa8, 0x7b, 0xea, 0x52, 0x54, 0xdb, 0x5c,
-	0x3b, 0x54, 0x20, 0x2e, 0xe7, 0x27, 0xd0, 0xad, 0xd0, 0x92, 0x91, 0x8f, 0x75, 0x92, 0xad, 0x57,
-	0x43, 0x6a, 0x45, 0x4d, 0xe7, 0xd9, 0xaf, 0x0d, 0xd8, 0x3c, 0xe1, 0x22, 0x27, 0xb7, 0xa0, 0xb1,
-	0xe0, 0x22, 0xf7, 0x53, 0x8e, 0x01, 0xa2, 0x43, 0x4d, 0x39, 0x1c, 0x71, 0xb2, 0x0d, 0x46, 0x1c,
-	0x9c, 0xb1, 0xb8, 0x88, 0x12, 0x6a, 0x40, 0x3e, 0x2a, 0xd2, 0xef, 0x06, 0xde, 0xd4, 0x75, 0xd8,
-	0xe6, 0x22, 0xc7, 0x3f, 0xa5, 0xe4, 0xfb, 0x63, 0x68, 0x05, 0x61, 0x12, 0xa5, 0x95, 0x50, 0xe1,
-	0xec, 0x17, 0x45, 0x5a, 0x5f, 0x8a, 0x90, 0xc2, 0x7d, 0xac, 0x11, 0x28, 0x04, 0x2b, 0x44, 0x9a,
-	0xf2, 0x05, 0x13, 0x68, 0xb9, 0xcc, 0x30, 0x2a, 0x94, 0x4c, 0x8f, 0x17, 0x4c, 0x8c, 0x51, 0xa2,
-	0x4d, 0xf9, 0x0a, 0x91, 0xcf, 0x40, 0x55, 0x91, 0x7e, 0x11, 0x48, 0x2d, 0xda, 0x54, 0x80, 0x17,
-	0x4a, 0x8a, 0x16, 0x8c, 0x89, 0xcc, 0x69, 0xbe, 0x91, 0x75, 0x70, 0xf9, 0x8c, 0x09, 0xf9, 0x83,
-	0x2a, 0x1d, 0x99, 0x96, 0xc5, 0x95, 0xbf, 0x08, 0x66, 0x2f, 0x58, 0x9e, 0xe1, 0xeb, 0x37, 0xa9,
-	0x25, 0xae, 0x4e, 0x14, 0x20, 0x03, 0xb6, 0xb8, 0x2a, 0xc2, 0x11, 0xa0, 0xb0, 0x21, 0xae, 0x54,
-	0x18, 0xda, 0x01, 0x4b, 0x5c, 0xf9, 0x4c, 0x08, 0x2e, 0x32, 0x7c, 0xf2, 0x26, 0x6d, 0x8a, 0x2b,
-	0x17, 0xc7, 0xd2, 0x6d, 0xbe, 0x76, 0xdb, 0x56, 0x6e, 0xf3, 0xb2, 0xdb, 0x5c, 0xbb, 0xed, 0x28,
-	0xb7, 0xf9, 0xda, 0x6d, 0xbe, 0x72, 0xdb, 0x55, 0x6e, 0x73, 0xed, 0xf6, 0x11, 0x34, 0xf9, 0x7c,
-	0xe1, 0xcb, 0xc3, 0x73, 0xb6, 0xee, 0xd5, 0x70, 0x77, 0xe5, 0xca, 0x56, 0x0b, 0x69, 0x83, 0xcf,
-	0x17, 0x72, 0x9b, 0x77, 0x9e, 0x40, 0x53, 0x6f, 0xb9, 0xca, 0x5a, 0xed, 0x0d, 0xd6, 0x4a, 0x57,
-	0xa4, 0x5e, 0xbe, 0x22, 0xbd, 0x0c, 0x9a, 0xfa, 0xcc, 0x65, 0x09, 0xb4, 0x7e, 0x01, 0x36, 0xb4,
-	0xdd, 0xc9, 0x73, 0x97, 0x8e, 0xdc, 0x89, 0x3f, 0x1a, 0x79, 0x76, 0xad, 0x82, 0x4c, 0x47, 0x9e,
-	0xaa, 0x99, 0x4e, 0x8e, 0x47, 0xfe, 0xf1, 0xd1, 0xc4, 0xde, 0x58, 0x0d, 0x46, 0x53, 0xf5, 0xf0,
-	0x4e, 0x5d, 0xa9, 0x28, 0x65, 0x46, 0x69, 0x38, 0x9a, 0xda, 0x66, 0xef, 0x63, 0x30, 0xe4, 0xa4,
-	0x19, 0xe9, 0x55, 0x8b, 0xca, 0x76, 0xf9, 0x30, 0xf5, 0x35, 0xff, 0x6b, 0x1b, 0x4c, 0x55, 0x64,
-	0x92, 0x9b, 0xeb, 0x24, 0xa8, 0x6b, 0x12, 0x99, 0x0b, 0x6f, 0x97, 0xea, 0xc9, 0x95, 0x40, 0x5d,
-	0xe0, 0xdb, 0xb0, 0x29, 0x38, 0xcf, 0xab, 0xe5, 0x0e, 0x42, 0xa4, 0x07, 0xd6, 0x22, 0x10, 0x2c,
-	0xcd, 0x25, 0x5f, 0x9b, 0x65, 0xd3, 0xa6, 0xc2, 0xf1, 0xb2, 0x75, 0x0b, 0x1d, 0xcd, 0xde, 0xb6,
-	0x64, 0x6f, 0x55, 0x10, 0x29, 0xe1, 0x89, 0x7a, 0x6d, 0xbb, 0x60, 0xaa, 0x26, 0x41, 0x35, 0x14,
-	0x5a, 0xa9, 0x00, 0xc9, 0x0e, 0x18, 0x09, 0x0f, 0x59, 0xac, 0x12, 0xa4, 0x96, 0x2a, 0x8c, 0x3c,
-	0x02, 0xfb, 0x22, 0x10, 0xe1, 0xab, 0x40, 0xac, 0x13, 0x69, 0xa3, 0xac, 0xb7, 0xa5, 0xc5, 0x3a,
-	0xa5, 0x3e, 0x02, 0x7b, 0x1e, 0x89, 0xa4, 0x62, 0xd1, 0xac, 0x58, 0x68, 0xb1, 0xb6, 0x78, 0x08,
-	0x26, 0xe6, 0x1a, 0xf5, 0x10, 0x5a, 0x9f, 0x74, 0x2b, 0xd1, 0x25, 0x5b, 0xad, 0x57, 0x29, 0xc9,
-	0x5a, 0x30, 0x63, 0x22, 0x0a, 0x62, 0x3f, 0x5d, 0x26, 0x67, 0x4c, 0xe0, 0x0b, 0x59, 0x79, 0x6f,
-	0x2b, 0xd9, 0x08, 0x45, 0x92, 0xcb, 0x75, 0x3b, 0xe5, 0x54, 0xb8, 0x5c, 0x75, 0x55, 0x77, 0xd7,
-	0x6d, 0x53, 0xab, 0xac, 0xb1, 0xea, 0x9e, 0x08, 0x6c, 0x5e, 0xc6, 0x41, 0x8a, 0xef, 0xa9, 0x43,
-	0xf1, 0xb7, 0x4c, 0xcd, 0x49, 0x30, 0x93, 0x4d, 0x91, 0x60, 0x99, 0x7a, 0x4d, 0x16, 0x85, 0x24,
-	0x98, 0xf5, 0x15, 0x42, 0xee, 0x43, 0x3b, 0x5a, 0x5c, 0xfe, 0x68, 0xa5, 0x21, 0xdf, 0x94, 0xf5,
-	0xfc, 0x1a, 0x6d, 0x49, 0xb4, 0xaa, 0xf4, 0xe9, 0x4a, 0x69, 0xab, 0xa4, 0xf4, 0xa9, 0x56, 0xfa,
-	0x10, 0x3a, 0x17, 0x3c, 0xcb, 0xfd, 0x20, 0x0d, 0xd5, 0x13, 0xbc, 0xa9, 0xb5, 0x24, 0xdc, 0x4f,
-	0x43, 0x7c, 0x65, 0xbb, 0x00, 0xec, 0x2a, 0x17, 0x81, 0x1f, 0x88, 0xf3, 0xcc, 0xb9, 0xa5, 0xfa,
-	0x00, 0x44, 0xfa, 0xe2, 0x3c, 0x23, 0x4f, 0xa0, 0xb3, 0x10, 0xfc, 0xea, 0xf5, 0x6a, 0xaa, 0x1b,
-	0x48, 0xf5, 0x4e, 0xb5, 0x5b, 0xda, 0x3f, 0x91, 0x3a, 0xc5, 0xc4, 0xb4, 0xbd, 0x28, 0x8d, 0xde,
-	0x0c, 0xb9, 0xf6, 0xff, 0x10, 0x72, 0x9f, 0x54, 0x43, 0xee, 0xf5, 0xf7, 0x87, 0x5c, 0xcd, 0x7f,
-	0x39, 0xf2, 0xee, 0xae, 0x8a, 0xaf, 0x0f, 0x2a, 0x57, 0xb8, 0xa8, 0xa8, 0x3c, 0xe8, 0xce, 0x78,
-	0x9a, 0xca, 0xce, 0xb2, 0x98, 0x83, 0xe0, 0x1c, 0x3b, 0x7a, 0x8e, 0x81, 0x92, 0xbe, 0x6b, 0x9a,
-	0xce, 0xac, 0x2c, 0x23, 0x3f, 0x00, 0x73, 0xb6, 0xcc, 0x72, 0x9e, 0x38, 0x4f, 0x90, 0xa1, 0xed,
-	0x7d, 0xf5, 0x89, 0x60, 0x5f, 0x7f, 0x22, 0xd8, 0xef, 0xa7, 0xaf, 0x69, 0xa1, 0x43, 0x1e, 0x83,
-	0x21, 0x8f, 0x24, 0x73, 0x7e, 0xfd, 0x8e, 0x40, 0x71, 0xd8, 0xfd, 0xfb, 0xb7, 0xdf, 0xec, 0x5a,
-	0xab, 0x08, 0x47, 0x95, 0x2e, 0x79, 0x04, 0x06, 0xf6, 0xbd, 0xce, 0x6f, 0x6a, 0x38, 0x05, 0xa9,
-	0x04, 0x53, 0x6c, 0x75, 0x0f, 0x0d, 0x69, 0x7a, 0x8d, 0x2a, 0x45, 0x49, 0x20, 0x8a, 0x8b, 0xbe,
-	0xe6, 0xb7, 0xca, 0xee, 0xd6, 0x5b, 0x76, 0xd8, 0xdf, 0xac, 0x8c, 0x61, 0xbe, 0x82, 0xc8, 0xe7,
-	0x00, 0x8b, 0xa4, 0x28, 0x24, 0x33, 0xe7, 0x2b, 0xe5, 0xe0, 0xfa, 0x9b, 0x9d, 0xce, 0xca, 0xd4,
-	0x5a, 0xac, 0xda, 0xb9, 0x23, 0xd8, 0x52, 0x65, 0xa4, 0x2e, 0x88, 0x33, 0xe7, 0x77, 0xb5, 0xf7,
-	0x54, 0x01, 0x87, 0x2d, 0xe9, 0xc2, 0x54, 0x6d, 0x00, 0xed, 0x46, 0x95, 0x42, 0xe2, 0xce, 0x57,
-	0x75, 0x68, 0x97, 0x2f, 0xd9, 0xfb, 0xb3, 0xc3, 0x5d, 0x68, 0x15, 0xc2, 0x75, 0x1c, 0xa5, 0x10,
-	0xae, 0x3f, 0x9f, 0xec, 0x02, 0xcc, 0x2e, 0x82, 0x34, 0x65, 0xb1, 0x34, 0xdf, 0x50, 0xed, 0x6d,
-	0x81, 0x78, 0x21, 0xd9, 0x03, 0x5b, 0x8b, 0x55, 0x17, 0x5c, 0x44, 0xd4, 0x0e, 0xed, 0x16, 0x38,
-	0xd2, 0xe3, 0x85, 0xe4, 0x00, 0x6e, 0x68, 0xcd, 0x9c, 0x89, 0x24, 0x4a, 0x03, 0x59, 0x87, 0x17,
-	0x5f, 0x60, 0x48, 0x21, 0x9a, 0xac, 0x25, 0xe4, 0x26, 0x98, 0x3c, 0x5d, 0x4a, 0x87, 0x26, 0x3a,
-	0x34, 0x78, 0xba, 0xf4, 0x42, 0xf2, 0x21, 0x74, 0x25, 0x9c, 0xb1, 0x4c, 0x86, 0x36, 0x5d, 0x27,
-	0x74, 0x68, 0x9b, 0xa7, 0xcb, 0xb1, 0x02, 0xbd, 0xf0, 0xd0, 0x92, 0x21, 0x07, 0xf7, 0xdf, 0x3b,
-	0x80, 0x86, 0x7a, 0x7b, 0xf2, 0xa1, 0x57, 0x92, 0x4e, 0xb7, 0xfa, 0x36, 0x75, 0xda, 0xf9, 0xd3,
-	0x06, 0x6c, 0x8f, 0xa3, 0x64, 0x19, 0x07, 0x39, 0xeb, 0xc7, 0x81, 0x48, 0x28, 0x7b, 0xb9, 0x64,
-	0x59, 0xfe, 0x56, 0x27, 0xf6, 0x7f, 0x60, 0x45, 0x69, 0x18, 0xcd, 0x82, 0x9c, 0xeb, 0x0f, 0x42,
-	0x6b, 0x40, 0x26, 0xde, 0x28, 0xcd, 0xe7, 0x9a, 0x36, 0x8b, 0x9a, 0x72, 0xa8, 0x76, 0x80, 0xf7,
-	0x55, 0x32, 0xae, 0x3e, 0x2a, 0xa8, 0xae, 0xb4, 0xbd, 0x28, 0xd2, 0x31, 0x7e, 0x57, 0xe8, 0x41,
-	0x47, 0xee, 0x73, 0x7d, 0x74, 0x8a, 0xa9, 0x16, 0x4f, 0x97, 0x43, 0x7d, 0x7a, 0x8f, 0xe1, 0x83,
-	0x28, 0x95, 0x29, 0x80, 0xf9, 0x67, 0x51, 0xae, 0x8a, 0x0b, 0x5f, 0xc8, 0xe0, 0x21, 0x29, 0x33,
-	0xe8, 0x8d, 0x42, 0x7a, 0x18, 0xe5, 0x58, 0x68, 0x50, 0xd5, 0x36, 0x18, 0xa1, 0x88, 0xe6, 0x39,
-	0xf2, 0x66, 0x50, 0x35, 0x90, 0xab, 0x4d, 0xd9, 0x2b, 0x9f, 0xbd, 0x0c, 0x31, 0x97, 0x18, 0xd4,
-	0x4c, 0xd9, 0x2b, 0xf7, 0x65, 0x48, 0x1e, 0xc0, 0x75, 0xc5, 0x77, 0x39, 0x21, 0xa8, 0x6e, 0x6a,
-	0x0b, 0x29, 0x2f, 0x25, 0x83, 0xe7, 0x60, 0xc9, 0x90, 0xa2, 0x4e, 0x16, 0x30, 0x40, 0x3c, 0xd0,
-	0x1c, 0xbf, 0x8b, 0x51, 0x8c, 0x4c, 0xa8, 0x8d, 0x95, 0xe7, 0xda, 0xb8, 0xf7, 0x3d, 0xe8, 0x54,
-	0x64, 0xc4, 0x02, 0x83, 0xf6, 0xbd, 0xb1, 0xab, 0xbe, 0xe2, 0x0c, 0x8e, 0xdc, 0x3e, 0xb5, 0x6b,
-	0x87, 0x63, 0xb8, 0xc1, 0xc5, 0x39, 0xbe, 0xd2, 0x19, 0x17, 0x61, 0x31, 0xd7, 0x61, 0xfb, 0x14,
-	0xff, 0x2b, 0x9e, 0x7e, 0xb5, 0x7f, 0x1e, 0xe5, 0x17, 0xcb, 0x33, 0x19, 0xa9, 0x0e, 0xb4, 0xe6,
-	0x81, 0xd2, 0x7c, 0x58, 0x7c, 0x45, 0xbc, 0x7c, 0x7c, 0x70, 0xce, 0x0b, 0xec, 0xcc, 0x44, 0xf0,
-	0xf1, 0xbf, 0x03, 0x00, 0x00, 0xff, 0xff, 0x4e, 0x2a, 0x8d, 0xf0, 0xdf, 0x14, 0x00, 0x00,
+	// 2341 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x58, 0xcd, 0x72, 0x1b, 0xb7,
+	0x1d, 0x37, 0x29, 0x71, 0xc9, 0xfd, 0xf3, 0x43, 0x6b, 0x58, 0x4e, 0xd6, 0x56, 0x35, 0x76, 0xe9,
+	0x74, 0xaa, 0x24, 0xb5, 0xe4, 0xc6, 0x9d, 0x24, 0x3d, 0x74, 0xc6, 0x14, 0xb9, 0xb6, 0x77, 0xaa,
+	0x92, 0x2a, 0x48, 0x2a, 0x6d, 0x2f, 0x3b, 0x2b, 0x2e, 0x28, 0x61, 0xbc, 0xbb, 0xa0, 0x81, 0x25,
+	0x25, 0xe7, 0xd6, 0xc9, 0xb4, 0xa7, 0xde, 0x7a, 0xeb, 0x13, 0xf4, 0x0d, 0x72, 0x6c, 0x5f, 0x20,
+	0xd3, 0x77, 0x68, 0x2f, 0x7d, 0x82, 0x9c, 0x3b, 0x00, 0x16, 0xe4, 0xae, 0x9c, 0x3a, 0xed, 0x45,
+	0x5a, 0xfc, 0xfe, 0x1f, 0x00, 0x7e, 0xc0, 0xff, 0x03, 0x84, 0xfb, 0x2b, 0x16, 0x67, 0x97, 0x61,
+	0xb0, 0xe0, 0x2c, 0x63, 0xe2, 0x28, 0x22, 0x2b, 0x3a, 0x23, 0x87, 0x6a, 0x84, 0x2c, 0x2d, 0xbb,
+	0x7f, 0xef, 0x82, 0xb1, 0x8b, 0x98, 0x1c, 0x29, 0xf4, 0x7c, 0x39, 0x3f, 0x0a, 0xd3, 0x37, 0x5a,
+	0xe5, 0xfe, 0x0d, 0xf3, 0x19, 0x4b, 0x12, 0x96, 0xe6, 0x32, 0xb7, 0x2c, 0x4b, 0x48, 0x16, 0xe6,
+	0x92, 0x07, 0x65, 0x09, 0x5b, 0x90, 0x74, 0x1e, 0xb3, 0xab, 0xe0, 0xa7, 0x4f, 0xb5, 0x42, 0xf7,
+	0x6f, 0x55, 0x80, 0x81, 0x5a, 0xca, 0xe4, 0xcd, 0x82, 0xa0, 0x0e, 0x54, 0x69, 0xe4, 0x56, 0x1e,
+	0x56, 0x0e, 0x6c, 0x5c, 0xa5, 0x11, 0xda, 0x03, 0x7b, 0x45, 0xd2, 0x88, 0xf1, 0x80, 0x46, 0x6e,
+	0x4d, 0xc1, 0x0d, 0x0d, 0xf8, 0x11, 0xda, 0x07, 0x58, 0x0b, 0x85, 0x6b, 0x3d, 0xdc, 0x3a, 0xb0,
+	0xb1, 0x6d, 0xa4, 0x02, 0xb9, 0x50, 0x0f, 0xa3, 0x70, 0x91, 0x11, 0xee, 0x56, 0x95, 0xa5, 0x19,
+	0xa2, 0xcf, 0xc0, 0x0d, 0x67, 0x33, 0xb2, 0xc8, 0x44, 0x70, 0xbe, 0x8c, 0x5f, 0x05, 0x6a, 0x49,
+	0xcb, 0x45, 0x14, 0x66, 0xc4, 0xdd, 0x7a, 0x58, 0x39, 0x68, 0xe0, 0xbb, 0xb9, 0xfc, 0x78, 0x19,
+	0xbf, 0x7a, 0x1e, 0xb3, 0xab, 0xa9, 0x12, 0xa2, 0x01, 0x3c, 0x30, 0x86, 0x61, 0x14, 0x05, 0x9c,
+	0x24, 0x6c, 0x45, 0x8a, 0xe6, 0xc2, 0xdd, 0x56, 0xf6, 0x7b, 0xb9, 0x5a, 0x2f, 0x8a, 0xb0, 0x52,
+	0xda, 0x38, 0x11, 0xe8, 0x04, 0x1e, 0x19, 0x2f, 0x11, 0xe5, 0x64, 0x96, 0x05, 0x31, 0xbb, 0xa0,
+	0xb3, 0x30, 0x56, 0x9e, 0x84, 0x59, 0x49, 0x5d, 0x79, 0x32, 0x13, 0x0e, 0x94, 0xe6, 0x89, 0x56,
+	0x94, 0xde, 0x84, 0x76, 0xd7, 0xfd, 0x0c, 0x9a, 0x1b, 0x02, 0x05, 0x3a, 0x80, 0x1a, 0xcd, 0x48,
+	0x22, 0xdc, 0xca, 0xc3, 0xad, 0x83, 0xe6, 0x27, 0xe8, 0x50, 0x9f, 0xc0, 0xe1, 0x46, 0x07, 0x6b,
+	0x85, 0xee, 0xdf, 0x2b, 0xd0, 0x38, 0x4d, 0xfa, 0x2c, 0x9d, 0xd3, 0x0b, 0x84, 0x60, 0x3b, 0x0d,
+	0x13, 0x92, 0x53, 0xaf, 0xbe, 0xd1, 0xc7, 0xb0, 0x9d, 0xbd, 0x59, 0x10, 0xc5, 0x5e, 0xe7, 0x93,
+	0xf7, 0x8d, 0x27, 0x63, 0x73, 0x78, 0x9a, 0x28, 0x77, 0x4a, 0x49, 0xb2, 0x4d, 0xd2, 0xf0, 0x3c,
+	0x26, 0x51, 0x4e, 0xa1, 0x19, 0xa2, 0x07, 0xd0, 0x14, 0x61, 0xb2, 0x88, 0x49, 0x30, 0xe7, 0xe4,
+	0xb5, 0x22, 0xa8, 0x8d, 0x41, 0x43, 0xcf, 0x39, 0x79, 0xdd, 0xfd, 0x1c, 0x2c, 0xed, 0x0a, 0x35,
+	0xa1, 0xde, 0x1f, 0x4d, 0x87, 0x13, 0x0f, 0x3b, 0xb7, 0x90, 0x0d, 0xb5, 0x17, 0xbd, 0xe9, 0x0b,
+	0xcf, 0xa9, 0xc8, 0xcf, 0xf1, 0xa4, 0x37, 0xf1, 0x9c, 0xaa, 0x56, 0x19, 0x4e, 0xbc, 0xdf, 0x4c,
+	0x9c, 0xad, 0xee, 0x9f, 0x2b, 0xd0, 0x3e, 0x4d, 0x5e, 0x70, 0xb6, 0x5c, 0xe4, 0xfb, 0xd8, 0x07,
+	0xb8, 0x90, 0xc3, 0xa0, 0xb0, 0x1b, 0x5b, 0x21, 0x43, 0xb9, 0xa5, 0xb5, 0x58, 0x2d, 0xa5, 0xaa,
+	0x96, 0xa2, 0xc5, 0x72, 0x25, 0xef, 0xd8, 0xc4, 0x47, 0x50, 0x4f, 0x48, 0xc6, 0xe9, 0x4c, 0x9e,
+	0xb0, 0x24, 0xd6, 0xb9, 0x49, 0x07, 0x36, 0x0a, 0xdd, 0xdf, 0x57, 0xc1, 0x36, 0xa8, 0x78, 0xeb,
+	0x4a, 0xff, 0x10, 0x5a, 0x11, 0x99, 0x87, 0xcb, 0x38, 0x2b, 0x2e, 0xa2, 0x99, 0x63, 0x6a, 0x19,
+	0x0f, 0xa0, 0xae, 0xd6, 0x64, 0x96, 0x71, 0x5c, 0xfb, 0xf7, 0xb7, 0xdf, 0xec, 0x57, 0xb0, 0x41,
+	0xd1, 0x47, 0xd0, 0x96, 0xb6, 0x01, 0x5b, 0x11, 0xce, 0x69, 0x44, 0xf4, 0xad, 0x33, 0x6a, 0x2d,
+	0x29, 0x1b, 0xe5, 0x22, 0xf4, 0x18, 0x2c, 0x65, 0x26, 0xdc, 0x9a, 0x5a, 0xf8, 0xdd, 0xcd, 0xc2,
+	0x0b, 0xc4, 0xe1, 0x5c, 0xa9, 0xb8, 0x51, 0xeb, 0x7b, 0x36, 0x8a, 0xee, 0x41, 0x23, 0x09, 0xaf,
+	0x03, 0xf1, 0x8a, 0x5c, 0xa9, 0xdb, 0xda, 0xc6, 0xf5, 0x24, 0xbc, 0x1e, 0xbf, 0x22, 0x57, 0xdd,
+	0x7f, 0x54, 0xa0, 0xe6, 0x27, 0xe1, 0x05, 0xf9, 0xce, 0x9b, 0xe5, 0x42, 0x7d, 0x45, 0xb8, 0xa0,
+	0x2c, 0x35, 0xa1, 0x99, 0x0f, 0xa5, 0xf6, 0x65, 0x28, 0x2e, 0xd5, 0xbe, 0x6d, 0xac, 0xbe, 0xd1,
+	0x87, 0xe0, 0xd0, 0x54, 0x64, 0x61, 0x1c, 0x07, 0xf2, 0xc6, 0x67, 0x34, 0xd1, 0x1b, 0xb6, 0xf1,
+	0x4e, 0x8e, 0x0f, 0x72, 0x58, 0xe6, 0x0b, 0x2a, 0x82, 0x70, 0x96, 0xd1, 0x15, 0x51, 0xf9, 0xa2,
+	0x81, 0x1b, 0x54, 0xf4, 0xd4, 0x58, 0x32, 0x4f, 0x45, 0x20, 0x33, 0x17, 0xcd, 0x32, 0x12, 0xb9,
+	0x96, 0x92, 0x37, 0xa9, 0xe8, 0x1b, 0x48, 0xee, 0x88, 0x8a, 0x60, 0x15, 0xc6, 0x34, 0xca, 0xe3,
+	0xaf, 0x4e, 0xc5, 0x99, 0x1c, 0x76, 0x1f, 0x83, 0xa5, 0x36, 0x24, 0xd0, 0x23, 0xa8, 0x51, 0xf9,
+	0x95, 0x87, 0x58, 0xdb, 0x10, 0xa4, 0xc4, 0x58, 0xcb, 0xba, 0xff, 0xaa, 0x43, 0x5b, 0x01, 0x03,
+	0x76, 0x95, 0xc6, 0x2c, 0x8c, 0xde, 0xba, 0x08, 0x86, 0x98, 0x6a, 0x81, 0x18, 0x07, 0xb6, 0x96,
+	0x3c, 0xce, 0x77, 0x2f, 0x3f, 0x25, 0x32, 0xe3, 0xb3, 0x3c, 0x6a, 0xe4, 0x27, 0x1a, 0x41, 0x27,
+	0xca, 0x7d, 0x06, 0x22, 0x93, 0x99, 0xa2, 0xa6, 0x02, 0xf4, 0xa0, 0xb4, 0x0e, 0x33, 0x6d, 0x79,
+	0x34, 0x96, 0xfa, 0xb8, 0x1d, 0x15, 0x87, 0xe8, 0x11, 0xb4, 0xd5, 0x9a, 0x03, 0x73, 0x26, 0x96,
+	0x9a, 0xbe, 0xa5, 0xc0, 0xb3, 0xfc, 0x60, 0x3e, 0x04, 0xc7, 0x58, 0x91, 0x28, 0x38, 0x7f, 0x23,
+	0x73, 0x9d, 0x3e, 0xf3, 0x9d, 0x0d, 0x7e, 0x2c, 0x61, 0xf4, 0x12, 0x2c, 0x4e, 0x42, 0xc1, 0x52,
+	0xb7, 0xa1, 0x16, 0xf6, 0xe4, 0x7f, 0x58, 0xd8, 0xf3, 0x90, 0xc6, 0x4b, 0x4e, 0xb0, 0xb2, 0xc3,
+	0xb9, 0x3d, 0xfa, 0x31, 0xec, 0x84, 0x51, 0x44, 0x33, 0xca, 0xd2, 0x30, 0x0e, 0x68, 0x3a, 0x67,
+	0xae, 0xad, 0xd6, 0xd6, 0xd9, 0xc0, 0x7e, 0x3a, 0x67, 0x3a, 0xc7, 0xac, 0x48, 0x30, 0x53, 0x37,
+	0xd4, 0x05, 0x75, 0x74, 0x20, 0xa1, 0x3c, 0x2f, 0xec, 0x81, 0x1d, 0x33, 0x99, 0x62, 0x23, 0xca,
+	0xdd, 0xa6, 0x2e, 0x24, 0x0a, 0x18, 0x50, 0x8e, 0x7c, 0x68, 0x6a, 0x02, 0x34, 0x9d, 0xad, 0xef,
+	0xa5, 0x53, 0x5d, 0xa8, 0x30, 0x23, 0x9a, 0x4e, 0x50, 0xc6, 0x9a, 0xcb, 0x3d, 0xb0, 0xe7, 0x34,
+	0x26, 0x81, 0xa0, 0x5f, 0x12, 0xb7, 0xad, 0xf8, 0x69, 0x48, 0x60, 0x4c, 0xbf, 0x24, 0xdd, 0xaf,
+	0x2b, 0x80, 0xde, 0x3e, 0x0e, 0xb4, 0x0b, 0xce, 0x60, 0xf4, 0xc5, 0xf0, 0x64, 0xd4, 0x1b, 0x04,
+	0xd3, 0xe1, 0x2f, 0x87, 0xa3, 0x2f, 0x86, 0xce, 0x2d, 0xf4, 0x1e, 0xa0, 0x35, 0x3a, 0x9e, 0xf6,
+	0xfb, 0x9e, 0x37, 0xf0, 0x06, 0x4e, 0xa5, 0x84, 0x63, 0xef, 0xd7, 0x53, 0x6f, 0x3c, 0xf1, 0x06,
+	0x4e, 0xb5, 0xe4, 0x65, 0x3c, 0xe9, 0x61, 0x89, 0x6e, 0xa1, 0x3b, 0xb0, 0xb3, 0x46, 0x9f, 0xf7,
+	0xfc, 0x13, 0x6f, 0xe0, 0x6c, 0x23, 0x17, 0x76, 0x0b, 0x13, 0x8e, 0xa7, 0xa7, 0xa7, 0x23, 0xa5,
+	0x5e, 0x2b, 0x39, 0xef, 0xf7, 0x86, 0x7d, 0xef, 0x44, 0x5a, 0x58, 0xdd, 0x3f, 0x56, 0xe0, 0xfe,
+	0x7f, 0x3f, 0x2f, 0xd4, 0x82, 0xc6, 0x70, 0x14, 0x78, 0x18, 0x8f, 0x64, 0xe2, 0xde, 0x81, 0xa6,
+	0x3f, 0x3c, 0xeb, 0x9d, 0xf8, 0x83, 0x60, 0x8a, 0x4f, 0x9c, 0x8a, 0x04, 0x06, 0xde, 0x99, 0xdf,
+	0xf7, 0x82, 0xe3, 0xe9, 0xf8, 0xb7, 0x4e, 0x55, 0x4e, 0xe3, 0x0f, 0xc7, 0xd3, 0xe7, 0xcf, 0xfd,
+	0xbe, 0xef, 0x0d, 0x27, 0xc1, 0xf8, 0xb4, 0xd7, 0xf7, 0x9c, 0x2d, 0x74, 0x1b, 0xda, 0x39, 0x01,
+	0xb9, 0xb3, 0x6d, 0xd4, 0x06, 0x7b, 0xb3, 0x90, 0x5a, 0xf7, 0x4f, 0x86, 0xc2, 0xd2, 0x11, 0x48,
+	0x43, 0xff, 0x57, 0xbd, 0x17, 0x5e, 0x81, 0x3f, 0x04, 0x1d, 0x0d, 0xf9, 0xc3, 0x5e, 0x7f, 0xe2,
+	0x9f, 0xc9, 0x3a, 0xb2, 0x0b, 0x8e, 0xc6, 0x14, 0xd2, 0x9b, 0xf8, 0xc3, 0x17, 0x4e, 0x15, 0x39,
+	0xd0, 0x2a, 0xa0, 0x9e, 0x66, 0x4d, 0x23, 0xd8, 0x3b, 0xf3, 0xb0, 0x52, 0xdb, 0xde, 0x38, 0xd4,
+	0xa0, 0x5a, 0xce, 0x2f, 0xa0, 0x53, 0xa2, 0x45, 0xa0, 0x8f, 0x4d, 0xfd, 0xad, 0x96, 0xb3, 0x6d,
+	0x49, 0xcd, 0x94, 0xe0, 0xaf, 0x6b, 0xb0, 0x7d, 0xca, 0x78, 0x86, 0xde, 0x87, 0xfa, 0x82, 0xf1,
+	0x2c, 0x48, 0x99, 0x4a, 0x10, 0x6d, 0x6c, 0xc9, 0xe1, 0x90, 0xa1, 0x5d, 0xa8, 0xc5, 0xe1, 0x39,
+	0x89, 0xf3, 0x2c, 0xa1, 0x07, 0xe8, 0xc3, 0xbc, 0x32, 0x6f, 0xa9, 0x9b, 0xba, 0xc9, 0xe8, 0x8c,
+	0x67, 0xea, 0x4f, 0xa1, 0x2e, 0xff, 0x1c, 0x9a, 0x61, 0x94, 0xd0, 0xb4, 0x94, 0x2a, 0xdc, 0xc3,
+	0xbc, 0x7f, 0xeb, 0x49, 0x91, 0xa2, 0xf0, 0x50, 0xb5, 0x0f, 0x18, 0xc2, 0x35, 0x22, 0x4d, 0xd9,
+	0x82, 0x70, 0x65, 0xb9, 0x14, 0x2a, 0x2b, 0x14, 0x4c, 0x47, 0x0b, 0xc2, 0xc7, 0x4a, 0x62, 0x4c,
+	0xd9, 0x1a, 0x91, 0x61, 0xa0, 0x1b, 0xcc, 0x20, 0x4f, 0xa4, 0x36, 0x6e, 0x68, 0xc0, 0x8f, 0x24,
+	0x45, 0x0b, 0x42, 0xb8, 0x70, 0x1b, 0x37, 0x0a, 0x92, 0x5a, 0x3e, 0x21, 0x5c, 0x7e, 0x60, 0xad,
+	0x23, 0x2b, 0x36, 0xbf, 0x0e, 0x16, 0xe1, 0xec, 0x15, 0xc9, 0x84, 0x8a, 0x7e, 0x0b, 0xdb, 0xfc,
+	0xfa, 0x54, 0x03, 0x32, 0x61, 0xf3, 0xeb, 0x3c, 0x1d, 0x81, 0x12, 0xd6, 0xf9, 0xb5, 0x4e, 0x43,
+	0x7b, 0x60, 0xf3, 0xeb, 0x80, 0x70, 0xce, 0xb8, 0x50, 0x21, 0x6f, 0xe1, 0x06, 0xbf, 0xf6, 0xd4,
+	0x58, 0xba, 0xcd, 0x36, 0x6e, 0x5b, 0xda, 0x6d, 0x56, 0x74, 0x9b, 0x19, 0xb7, 0x6d, 0xed, 0x36,
+	0xdb, 0xb8, 0xcd, 0xd6, 0x6e, 0x3b, 0xda, 0x6d, 0x66, 0xdc, 0x3e, 0x81, 0x06, 0x9b, 0x2f, 0x02,
+	0x79, 0x78, 0xee, 0xce, 0xc3, 0x8a, 0xda, 0x5d, 0xb1, 0xe9, 0x35, 0x42, 0x5c, 0x67, 0xf3, 0x85,
+	0xdc, 0xe6, 0xfd, 0x67, 0xd0, 0x30, 0x5b, 0x2e, 0xb3, 0x56, 0xb9, 0xc1, 0x5a, 0xe1, 0x8a, 0x54,
+	0x8b, 0x57, 0xa4, 0x2b, 0xa0, 0x61, 0xce, 0x5c, 0x76, 0x47, 0x9b, 0x08, 0x70, 0xa0, 0xe5, 0x4d,
+	0x5e, 0x7a, 0x78, 0xe8, 0x4d, 0x82, 0xe1, 0xd0, 0x77, 0x2a, 0x25, 0x64, 0x3a, 0xf4, 0x75, 0x3b,
+	0x75, 0x3a, 0x1a, 0x06, 0xa3, 0x93, 0x89, 0xb3, 0xb5, 0x1e, 0x0c, 0xa7, 0x3a, 0xf0, 0xce, 0x3c,
+	0xa9, 0x28, 0x65, 0xb5, 0xc2, 0x70, 0x38, 0x75, 0xac, 0xee, 0xc7, 0x50, 0x93, 0x93, 0x0a, 0xd4,
+	0x2d, 0xf7, 0x9b, 0xad, 0xe2, 0x61, 0x9a, 0x6b, 0xfe, 0x97, 0x26, 0x58, 0xba, 0xff, 0x44, 0x77,
+	0x37, 0x45, 0xd0, 0xb4, 0x2b, 0xb2, 0x16, 0xde, 0x2b, 0xb4, 0x9a, 0x6b, 0x81, 0xbe, 0xc0, 0xf7,
+	0x60, 0x9b, 0x33, 0x96, 0x95, 0x3b, 0x21, 0x05, 0xa1, 0x2e, 0xd8, 0x8b, 0x90, 0x93, 0x34, 0x93,
+	0x7c, 0x6d, 0x17, 0x4d, 0x1b, 0x1a, 0x57, 0x97, 0xad, 0x93, 0xeb, 0x18, 0xf6, 0x76, 0x25, 0x7b,
+	0xeb, 0x5e, 0x49, 0x0b, 0x4f, 0x75, 0xb4, 0xed, 0x83, 0xa5, 0xdf, 0x0f, 0xfa, 0xad, 0x61, 0x94,
+	0x72, 0x10, 0xed, 0x41, 0x2d, 0x61, 0x11, 0x89, 0x75, 0x81, 0x34, 0x52, 0x8d, 0xa1, 0x27, 0xe0,
+	0x5c, 0x86, 0x3c, 0xba, 0x0a, 0xf9, 0xa6, 0x90, 0xd6, 0x8b, 0x7a, 0x3b, 0x46, 0x6c, 0x4a, 0xea,
+	0x13, 0x70, 0xe6, 0x94, 0x27, 0x25, 0x8b, 0x46, 0xc9, 0xc2, 0x88, 0x8d, 0xc5, 0x63, 0xb0, 0x54,
+	0xad, 0xd1, 0x81, 0xd0, 0xfc, 0xa4, 0x53, 0xca, 0x2e, 0x62, 0xbd, 0x5e, 0xad, 0x24, 0xdb, 0x44,
+	0x41, 0x38, 0x0d, 0xe3, 0x20, 0x5d, 0x26, 0xe7, 0x84, 0xab, 0x08, 0x59, 0x7b, 0x6f, 0x69, 0xd9,
+	0x50, 0x89, 0x24, 0x97, 0x9b, 0x97, 0x96, 0x5b, 0xe2, 0x72, 0xfd, 0xe0, 0x7a, 0xb0, 0x79, 0x51,
+	0x35, 0x8b, 0x1a, 0xeb, 0x87, 0x15, 0x82, 0xed, 0x55, 0x1c, 0xa6, 0x2a, 0x9e, 0xda, 0x58, 0x7d,
+	0xcb, 0xd2, 0x9c, 0x84, 0x33, 0xf9, 0x5e, 0xe2, 0x44, 0xe8, 0x68, 0xb2, 0x31, 0x24, 0xe1, 0xac,
+	0xa7, 0x11, 0xf4, 0x08, 0x5a, 0x74, 0xb1, 0xfa, 0xd9, 0x5a, 0x43, 0xc6, 0x94, 0xfd, 0xf2, 0x16,
+	0x6e, 0x4a, 0xb4, 0xac, 0xf4, 0xe9, 0x5a, 0x69, 0xa7, 0xa0, 0xf4, 0xa9, 0x51, 0xfa, 0x00, 0xda,
+	0x97, 0x4c, 0x64, 0x41, 0x98, 0x46, 0x3a, 0x04, 0xef, 0x1a, 0x2d, 0x09, 0xf7, 0xd2, 0x48, 0x45,
+	0xd9, 0x3e, 0x00, 0xb9, 0xce, 0x78, 0x18, 0x84, 0xfc, 0x42, 0xb8, 0xef, 0xeb, 0x27, 0x82, 0x42,
+	0x7a, 0xfc, 0x42, 0xa0, 0x67, 0xd0, 0x5e, 0x70, 0x76, 0xfd, 0x66, 0x3d, 0xd5, 0x1d, 0x45, 0xf5,
+	0x5e, 0xf9, 0x21, 0x75, 0x78, 0x2a, 0x75, 0xf2, 0x89, 0x71, 0x6b, 0x51, 0x18, 0xdd, 0x4c, 0xb9,
+	0xce, 0xff, 0x91, 0x72, 0x9f, 0x95, 0x53, 0xee, 0xed, 0x77, 0xa7, 0x5c, 0xc3, 0x7f, 0x31, 0xf3,
+	0xee, 0xaf, 0x9b, 0xaf, 0xf7, 0x4a, 0x57, 0x38, 0xef, 0xa8, 0x7c, 0xe8, 0xcc, 0x58, 0x9a, 0xca,
+	0x47, 0x67, 0x3e, 0x07, 0x52, 0x73, 0xec, 0x99, 0x39, 0xfa, 0x5a, 0xfa, 0x5d, 0xd3, 0xb4, 0x67,
+	0x45, 0x19, 0xfa, 0x09, 0x58, 0xb3, 0xa5, 0xc8, 0x58, 0xe2, 0x3e, 0x53, 0x0c, 0xed, 0x1e, 0xea,
+	0x5f, 0x0f, 0x0e, 0xcd, 0xaf, 0x07, 0x87, 0xbd, 0xf4, 0x0d, 0xce, 0x75, 0xd0, 0xe7, 0x00, 0x8b,
+	0x24, 0xef, 0xcf, 0x84, 0xfb, 0x55, 0x45, 0x99, 0xdc, 0xbe, 0xf9, 0xb6, 0x10, 0xc7, 0xb5, 0x7f,
+	0x7e, 0xfb, 0xcd, 0xfe, 0x2d, 0x6c, 0x2f, 0xd6, 0x0f, 0xa8, 0x13, 0xd8, 0xd1, 0xdd, 0x99, 0xe9,
+	0x33, 0x85, 0xfb, 0x87, 0xca, 0x3b, 0x8a, 0xeb, 0x71, 0x53, 0xba, 0xb0, 0x74, 0x77, 0x8d, 0x3b,
+	0xb4, 0x54, 0x9f, 0xef, 0x7f, 0x55, 0x85, 0x56, 0xf1, 0xec, 0xde, 0x9d, 0x74, 0x1f, 0x40, 0x33,
+	0x17, 0x6e, 0xd2, 0x13, 0x86, 0x68, 0xf3, 0x83, 0xc5, 0x3e, 0xc0, 0xec, 0x32, 0x4c, 0x53, 0x12,
+	0x4b, 0xf3, 0x2d, 0xfd, 0xa0, 0xcc, 0x11, 0x3f, 0x42, 0x07, 0xe0, 0x18, 0xb1, 0x7e, 0x77, 0xe6,
+	0x89, 0xaa, 0x8d, 0x3b, 0x39, 0xae, 0xde, 0x60, 0x7e, 0x84, 0x8e, 0xe0, 0x8e, 0xd1, 0xcc, 0x08,
+	0x4f, 0x68, 0x1a, 0xca, 0xf6, 0x36, 0xff, 0xcd, 0x03, 0xe5, 0xa2, 0xc9, 0x46, 0x82, 0xee, 0x82,
+	0xc5, 0xd2, 0xa5, 0x74, 0x68, 0x29, 0x87, 0x35, 0x96, 0x2e, 0xfd, 0x08, 0x7d, 0x00, 0x1d, 0x09,
+	0x0b, 0x22, 0x64, 0xc6, 0x30, 0xe5, 0xb7, 0x8d, 0x5b, 0x2c, 0x5d, 0x8e, 0x35, 0xe8, 0x47, 0xc7,
+	0xb6, 0x8c, 0x64, 0xb5, 0xff, 0xee, 0x11, 0xd4, 0xf5, 0x95, 0x96, 0xf1, 0x53, 0xca, 0xe5, 0x9d,
+	0xf2, 0x95, 0x37, 0xd9, 0xfc, 0xaf, 0x5b, 0xb0, 0x3b, 0xa6, 0xc9, 0x32, 0x0e, 0x33, 0xd2, 0x8b,
+	0x43, 0x9e, 0x60, 0xf2, 0x7a, 0x49, 0x44, 0xf6, 0xd6, 0x03, 0xe7, 0x07, 0x60, 0xd3, 0x34, 0xa2,
+	0xb3, 0x30, 0x63, 0xe6, 0x27, 0x98, 0x0d, 0x20, 0xeb, 0x19, 0x4d, 0xb3, 0xb9, 0xa1, 0xcd, 0xc6,
+	0x96, 0x1c, 0xea, 0x1d, 0xa8, 0x54, 0x2d, 0x19, 0xd7, 0xcf, 0x78, 0xfd, 0xd8, 0x6b, 0x2d, 0xf2,
+	0x2a, 0xa7, 0x5e, 0xf2, 0x5d, 0x68, 0xcb, 0x7d, 0x6e, 0x8e, 0x4e, 0x33, 0xd5, 0x64, 0xe9, 0x72,
+	0x60, 0x4e, 0xef, 0x29, 0xbc, 0x47, 0x53, 0x99, 0x59, 0x49, 0x70, 0x4e, 0x33, 0x5d, 0xb3, 0x03,
+	0x2e, 0x63, 0x52, 0x52, 0x56, 0xc3, 0x77, 0x72, 0xe9, 0x31, 0xcd, 0x54, 0xfd, 0xc6, 0xba, 0x1b,
+	0xaf, 0x45, 0x9c, 0xce, 0x33, 0xc5, 0x5b, 0x0d, 0xeb, 0x81, 0x5c, 0x6d, 0x4a, 0xae, 0x02, 0xf2,
+	0x3a, 0x52, 0x29, 0xba, 0x86, 0xad, 0x94, 0x5c, 0x79, 0xaf, 0xe5, 0x53, 0xfc, 0xb6, 0xe6, 0xbb,
+	0x98, 0x67, 0xf5, 0x23, 0x65, 0x47, 0x51, 0x5e, 0xc8, 0xb1, 0x2f, 0xc1, 0x96, 0x91, 0xaa, 0x4f,
+	0x16, 0x54, 0xdc, 0x7d, 0x64, 0x38, 0xfe, 0x2e, 0x46, 0x55, 0xc0, 0x2b, 0x6d, 0xd5, 0xd0, 0x6d,
+	0x8c, 0xbb, 0x3f, 0x82, 0x76, 0x49, 0x86, 0x6c, 0xa8, 0xe1, 0x9e, 0x3f, 0xf6, 0xf4, 0xef, 0x26,
+	0xfd, 0x13, 0xaf, 0x87, 0x9d, 0xca, 0xf1, 0x18, 0xee, 0x30, 0x7e, 0xa1, 0x3a, 0x90, 0x19, 0xe3,
+	0x51, 0x3e, 0xd7, 0x71, 0xeb, 0x4c, 0xfd, 0xd7, 0x3c, 0xfd, 0xee, 0xf0, 0x82, 0x66, 0x97, 0xcb,
+	0x73, 0x99, 0x00, 0x8e, 0x8c, 0xe6, 0x91, 0xd6, 0x7c, 0x9c, 0xff, 0x6e, 0xb7, 0x7a, 0x7a, 0x74,
+	0xc1, 0x72, 0xec, 0xdc, 0x52, 0xe0, 0xd3, 0xff, 0x04, 0x00, 0x00, 0xff, 0xff, 0xc5, 0x1d, 0x9a,
+	0xe9, 0x51, 0x14, 0x00, 0x00,
 }
diff --git a/vendor/github.com/opencord/voltha-protos/v3/go/voltha/logical_device.pb.go b/vendor/github.com/opencord/voltha-protos/v3/go/voltha/logical_device.pb.go
index 8ebaa02..7aef243 100644
--- a/vendor/github.com/opencord/voltha-protos/v3/go/voltha/logical_device.pb.go
+++ b/vendor/github.com/opencord/voltha-protos/v3/go/voltha/logical_device.pb.go
@@ -200,18 +200,10 @@
 	// device features
 	SwitchFeatures *openflow_13.OfpSwitchFeatures `protobuf:"bytes,4,opt,name=switch_features,json=switchFeatures,proto3" json:"switch_features,omitempty"`
 	// name of the root device anchoring logical device
-	RootDeviceId string `protobuf:"bytes,5,opt,name=root_device_id,json=rootDeviceId,proto3" json:"root_device_id,omitempty"`
-	// logical device ports
-	Ports []*LogicalPort `protobuf:"bytes,128,rep,name=ports,proto3" json:"ports,omitempty"`
-	// flows configured on the logical device
-	Flows *openflow_13.Flows `protobuf:"bytes,129,opt,name=flows,proto3" json:"flows,omitempty"`
-	// flow groups configured on the logical device
-	FlowGroups *openflow_13.FlowGroups `protobuf:"bytes,130,opt,name=flow_groups,json=flowGroups,proto3" json:"flow_groups,omitempty"`
-	// meters configured on the logical device
-	Meters               *openflow_13.Meters `protobuf:"bytes,131,opt,name=meters,proto3" json:"meters,omitempty"`
-	XXX_NoUnkeyedLiteral struct{}            `json:"-"`
-	XXX_unrecognized     []byte              `json:"-"`
-	XXX_sizecache        int32               `json:"-"`
+	RootDeviceId         string   `protobuf:"bytes,5,opt,name=root_device_id,json=rootDeviceId,proto3" json:"root_device_id,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
 }
 
 func (m *LogicalDevice) Reset()         { *m = LogicalDevice{} }
@@ -274,34 +266,6 @@
 	return ""
 }
 
-func (m *LogicalDevice) GetPorts() []*LogicalPort {
-	if m != nil {
-		return m.Ports
-	}
-	return nil
-}
-
-func (m *LogicalDevice) GetFlows() *openflow_13.Flows {
-	if m != nil {
-		return m.Flows
-	}
-	return nil
-}
-
-func (m *LogicalDevice) GetFlowGroups() *openflow_13.FlowGroups {
-	if m != nil {
-		return m.FlowGroups
-	}
-	return nil
-}
-
-func (m *LogicalDevice) GetMeters() *openflow_13.Meters {
-	if m != nil {
-		return m.Meters
-	}
-	return nil
-}
-
 type LogicalDevices struct {
 	Items                []*LogicalDevice `protobuf:"bytes,1,rep,name=items,proto3" json:"items,omitempty"`
 	XXX_NoUnkeyedLiteral struct{}         `json:"-"`
@@ -352,40 +316,34 @@
 func init() { proto.RegisterFile("voltha_protos/logical_device.proto", fileDescriptor_caf139ab3abc8240) }
 
 var fileDescriptor_caf139ab3abc8240 = []byte{
-	// 550 bytes of a gzipped FileDescriptorProto
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x93, 0xcf, 0x6a, 0xdb, 0x40,
-	0x10, 0xc6, 0xab, 0xd8, 0x72, 0xec, 0x91, 0xe3, 0xc0, 0x9a, 0x10, 0x91, 0xb4, 0xc4, 0x88, 0x1e,
-	0x1c, 0x4a, 0xa5, 0xd4, 0xa6, 0xd0, 0x1e, 0x0a, 0xad, 0x09, 0x2e, 0x86, 0xfe, 0x63, 0x0b, 0x3d,
-	0xf4, 0x22, 0x36, 0xd2, 0x5a, 0x16, 0xd8, 0x1a, 0xa1, 0x5d, 0x3b, 0xd7, 0xfe, 0x79, 0xad, 0xbe,
-	0x42, 0x5f, 0xa2, 0x8f, 0xd0, 0x43, 0xcf, 0x65, 0x77, 0xa5, 0xd4, 0x8a, 0xd3, 0xa3, 0xbe, 0xf9,
-	0x7d, 0x33, 0xb3, 0xdf, 0x20, 0xf0, 0x36, 0xb8, 0x94, 0x0b, 0x16, 0xe6, 0x05, 0x4a, 0x14, 0xc1,
-	0x12, 0x93, 0x34, 0x62, 0xcb, 0x30, 0xe6, 0x9b, 0x34, 0xe2, 0xbe, 0x56, 0x49, 0xcb, 0x30, 0x27,
-	0xf7, 0x13, 0xc4, 0x64, 0xc9, 0x03, 0x96, 0xa7, 0x01, 0xcb, 0x32, 0x94, 0x4c, 0xa6, 0x98, 0x09,
-	0x43, 0x9d, 0xb8, 0xf5, 0x4e, 0x2b, 0x2e, 0x59, 0x59, 0x39, 0xab, 0x57, 0x30, 0xe7, 0xd9, 0x7c,
-	0x89, 0xd7, 0xe1, 0x93, 0xb1, 0x01, 0xbc, 0x67, 0x70, 0xf0, 0xc6, 0x0c, 0xfe, 0x80, 0x85, 0x9c,
-	0xc5, 0xa4, 0x07, 0x7b, 0x69, 0xec, 0x5a, 0x03, 0x6b, 0xd8, 0xa1, 0x7b, 0x69, 0x4c, 0x8e, 0x61,
-	0x3f, 0xc7, 0x42, 0x86, 0x69, 0xec, 0xee, 0x69, 0xb1, 0x95, 0x6b, 0xd0, 0xfb, 0x6d, 0x81, 0xb3,
-	0x65, 0xdd, 0x31, 0x5e, 0x40, 0x1b, 0xe7, 0x79, 0xa8, 0x68, 0xed, 0x74, 0x46, 0x47, 0xfe, 0xf6,
-	0xfc, 0xaa, 0x48, 0xf7, 0x71, 0x9e, 0xeb, 0x0e, 0xa7, 0xd0, 0x31, 0x8f, 0x57, 0xc3, 0x1a, 0xba,
-	0x51, 0xdb, 0x08, 0xb3, 0x98, 0x3c, 0x84, 0x5e, 0x59, 0xd4, 0xeb, 0x64, 0xe8, 0x36, 0x07, 0xd6,
-	0xf0, 0x80, 0x76, 0x8d, 0xaa, 0x1a, 0xbc, 0x43, 0xd5, 0xa2, 0x40, 0x94, 0x66, 0xaa, 0x3d, 0xb0,
-	0x86, 0x6d, 0xda, 0x56, 0x82, 0xee, 0xff, 0x0a, 0x7a, 0xd5, 0xd0, 0x50, 0x48, 0x26, 0x85, 0xdb,
-	0xd2, 0x7b, 0x9d, 0xde, 0xb9, 0x97, 0x41, 0x68, 0xb7, 0xdc, 0xee, 0xa3, 0xfa, 0xf2, 0x9e, 0x43,
-	0x77, 0xeb, 0xcd, 0x82, 0x9c, 0x83, 0x9d, 0x4a, 0xbe, 0x12, 0xae, 0x35, 0x68, 0x0c, 0x9d, 0x51,
-	0xdf, 0x37, 0x79, 0xfb, 0x5b, 0x10, 0x35, 0x84, 0xf7, 0xa3, 0x71, 0x13, 0xf5, 0xa5, 0x5e, 0x79,
-	0x27, 0xb1, 0x33, 0x70, 0x62, 0x26, 0x59, 0xce, 0xe4, 0xa2, 0x8a, 0xbb, 0x49, 0xa1, 0x92, 0x66,
-	0x31, 0x39, 0x87, 0x66, 0xcc, 0x45, 0xa4, 0xb3, 0xb9, 0x2b, 0x4e, 0x55, 0xa4, 0x1a, 0x21, 0x33,
-	0x38, 0x14, 0xd7, 0xa9, 0x8c, 0x16, 0xe1, 0x9c, 0x33, 0xb9, 0x2e, 0xb8, 0xd0, 0x79, 0x39, 0xa3,
-	0xc1, 0x8e, 0xeb, 0x16, 0x47, 0x7b, 0x46, 0x98, 0x96, 0xdf, 0x2a, 0x79, 0x9d, 0xe9, 0xbf, 0xdb,
-	0xd8, 0x7a, 0xe5, 0xae, 0x52, 0x2f, 0xab, 0xfb, 0x3c, 0x05, 0x5b, 0xa5, 0x26, 0xdc, 0x2f, 0xff,
-	0x8f, 0x62, 0xd2, 0xf9, 0xf5, 0xe7, 0xe7, 0x83, 0xa6, 0x7a, 0x36, 0x35, 0x34, 0xb9, 0x00, 0x5b,
-	0xed, 0x22, 0xdc, 0xaf, 0x96, 0x5e, 0x8f, 0xd4, 0xd6, 0x9b, 0xaa, 0xd2, 0xc4, 0x56, 0xae, 0x7b,
-	0xd4, 0x80, 0xe4, 0x25, 0x38, 0xba, 0x9c, 0x14, 0xb8, 0xce, 0x85, 0xfb, 0xcd, 0xf8, 0x8e, 0x77,
-	0x7c, 0xaf, 0x75, 0xbd, 0x32, 0xc3, 0xfc, 0x46, 0x22, 0x63, 0x68, 0xad, 0xb8, 0xe4, 0x85, 0x70,
-	0xbf, 0x1b, 0x73, 0xbf, 0x66, 0x7e, 0xab, 0x6b, 0x95, 0xb1, 0x44, 0xbd, 0x17, 0xd0, 0xab, 0x5d,
-	0x4f, 0x90, 0x47, 0xf5, 0xdb, 0x1f, 0xdd, 0x7a, 0xb0, 0xc1, 0xca, 0xeb, 0x4f, 0x3e, 0x41, 0x1f,
-	0x8b, 0x44, 0xcf, 0x89, 0xb0, 0x88, 0x4b, 0x76, 0x72, 0xf8, 0x7e, 0x5a, 0xc3, 0x3f, 0xfb, 0x49,
-	0x2a, 0x17, 0xeb, 0x2b, 0x3f, 0xc2, 0x55, 0x50, 0xc1, 0x81, 0x81, 0x1f, 0x97, 0x3f, 0xf1, 0x66,
-	0x1c, 0x24, 0x58, 0x6a, 0x57, 0x2d, 0x2d, 0x8e, 0xff, 0x06, 0x00, 0x00, 0xff, 0xff, 0xdd, 0xad,
-	0x36, 0xdf, 0x4d, 0x04, 0x00, 0x00,
+	// 456 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x92, 0xc1, 0x6a, 0xdb, 0x40,
+	0x10, 0x86, 0x91, 0x63, 0x3b, 0xce, 0xca, 0x51, 0x40, 0x21, 0x54, 0x24, 0x85, 0x08, 0xd1, 0x83,
+	0x43, 0xa9, 0xd4, 0xda, 0x97, 0xf6, 0xd0, 0x43, 0x43, 0x08, 0x18, 0x4a, 0x5b, 0xb6, 0xd0, 0x43,
+	0x2f, 0x62, 0xa3, 0x5d, 0xcb, 0x0b, 0xb2, 0x46, 0x68, 0x37, 0xce, 0xcb, 0xf6, 0x29, 0xfa, 0x04,
+	0x65, 0x67, 0x57, 0x8d, 0x15, 0xfb, 0xa8, 0x7f, 0xbe, 0x99, 0xf9, 0xe7, 0x5f, 0x91, 0x64, 0x0b,
+	0x95, 0x5e, 0xb3, 0xbc, 0x69, 0x41, 0x83, 0xca, 0x2a, 0x28, 0x65, 0xc1, 0xaa, 0x9c, 0x8b, 0xad,
+	0x2c, 0x44, 0x8a, 0x6a, 0x38, 0xb6, 0xcc, 0xe5, 0xeb, 0x12, 0xa0, 0xac, 0x44, 0xc6, 0x1a, 0x99,
+	0xb1, 0xba, 0x06, 0xcd, 0xb4, 0x84, 0x5a, 0x59, 0xea, 0x32, 0xea, 0x4f, 0xda, 0x08, 0xcd, 0x5c,
+	0xe5, 0xba, 0x5f, 0x81, 0x46, 0xd4, 0xab, 0x0a, 0x9e, 0xf2, 0x0f, 0x0b, 0x0b, 0x24, 0x1f, 0xc9,
+	0xe9, 0x57, 0xbb, 0xf8, 0x07, 0xb4, 0x7a, 0xc9, 0xc3, 0x80, 0x0c, 0x24, 0x8f, 0xbc, 0xd8, 0x9b,
+	0x9d, 0xd0, 0x81, 0xe4, 0xe1, 0x2b, 0x72, 0xdc, 0x40, 0xab, 0x73, 0xc9, 0xa3, 0x01, 0x8a, 0xe3,
+	0x06, 0xc1, 0xe4, 0xaf, 0x47, 0xfc, 0x9d, 0xd6, 0xbd, 0xc6, 0xf7, 0x64, 0x02, 0xab, 0x26, 0x37,
+	0x34, 0x76, 0xfa, 0xf3, 0x8b, 0x74, 0x77, 0x7f, 0x57, 0xa4, 0xc7, 0xb0, 0x6a, 0x70, 0xc2, 0x15,
+	0x39, 0xb1, 0xc7, 0x9b, 0x65, 0x47, 0x38, 0x68, 0x62, 0x85, 0x25, 0x0f, 0xdf, 0x90, 0xc0, 0x15,
+	0xd1, 0x4e, 0x0d, 0xd1, 0x30, 0xf6, 0x66, 0xa7, 0x74, 0x6a, 0x55, 0x33, 0xe0, 0x1b, 0x98, 0x11,
+	0x2d, 0x80, 0xb6, 0x5b, 0x47, 0xb1, 0x37, 0x9b, 0xd0, 0x89, 0x11, 0x70, 0xfe, 0x17, 0x12, 0x74,
+	0x4b, 0x73, 0xa5, 0x99, 0x56, 0xd1, 0x18, 0x7d, 0x5d, 0x1d, 0xf4, 0x65, 0x11, 0x3a, 0x75, 0xee,
+	0x7e, 0x9a, 0xaf, 0xe4, 0x13, 0x99, 0xee, 0xdc, 0xac, 0xc2, 0x1b, 0x32, 0x92, 0x5a, 0x6c, 0x54,
+	0xe4, 0xc5, 0x47, 0x33, 0x7f, 0x7e, 0x9e, 0xda, 0xbc, 0xd3, 0x1d, 0x88, 0x5a, 0x22, 0xf9, 0xe3,
+	0xfd, 0x8f, 0xfa, 0x0e, 0x2d, 0xef, 0x25, 0x76, 0x4d, 0x7c, 0xce, 0x34, 0x6b, 0x98, 0x5e, 0x77,
+	0x71, 0x0f, 0x29, 0xe9, 0xa4, 0x25, 0x0f, 0x6f, 0xc8, 0x90, 0x0b, 0x55, 0x60, 0x36, 0x87, 0xe2,
+	0x34, 0x45, 0x8a, 0x48, 0xb8, 0x24, 0x67, 0xea, 0x49, 0xea, 0x62, 0x9d, 0xaf, 0x04, 0xd3, 0x8f,
+	0xad, 0x50, 0x98, 0x97, 0x3f, 0x8f, 0xf7, 0xba, 0x5e, 0x70, 0x34, 0xb0, 0xc2, 0xbd, 0xfb, 0x36,
+	0xc9, 0x63, 0xa6, 0xcf, 0x6f, 0x33, 0x42, 0xcb, 0x53, 0xa3, 0xde, 0xb9, 0xf7, 0x49, 0x3e, 0x93,
+	0xa0, 0x77, 0x9d, 0x0a, 0xdf, 0xf6, 0xb3, 0xb9, 0x78, 0x91, 0x8d, 0xc5, 0x5c, 0x3a, 0xb7, 0xbf,
+	0xc8, 0x39, 0xb4, 0x25, 0x7a, 0x2b, 0xa0, 0xe5, 0x8e, 0xbd, 0x3d, 0xfb, 0x7e, 0xdf, 0xc3, 0x7f,
+	0xa7, 0xa5, 0xd4, 0xeb, 0xc7, 0x87, 0xb4, 0x80, 0x4d, 0xd6, 0xc1, 0x99, 0x85, 0xdf, 0xb9, 0x9f,
+	0x7c, 0xbb, 0xc8, 0x4a, 0x70, 0xda, 0xc3, 0x18, 0xc5, 0xc5, 0xbf, 0x00, 0x00, 0x00, 0xff, 0xff,
+	0x91, 0x0c, 0xf4, 0xf2, 0x6d, 0x03, 0x00, 0x00,
 }
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 013efb0..526fc15 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -99,7 +99,7 @@
 github.com/modern-go/concurrent
 # github.com/modern-go/reflect2 v1.0.1
 github.com/modern-go/reflect2
-# github.com/opencord/voltha-lib-go/v3 v3.2.0
+# github.com/opencord/voltha-lib-go/v3 v3.2.1
 github.com/opencord/voltha-lib-go/v3/pkg/adapters
 github.com/opencord/voltha-lib-go/v3/pkg/adapters/adapterif
 github.com/opencord/voltha-lib-go/v3/pkg/adapters/common
@@ -114,7 +114,7 @@
 github.com/opencord/voltha-lib-go/v3/pkg/mocks/kafka
 github.com/opencord/voltha-lib-go/v3/pkg/probe
 github.com/opencord/voltha-lib-go/v3/pkg/version
-# github.com/opencord/voltha-protos/v3 v3.3.9
+# github.com/opencord/voltha-protos/v3 v3.4.1
 github.com/opencord/voltha-protos/v3/go/common
 github.com/opencord/voltha-protos/v3/go/inter_container
 github.com/opencord/voltha-protos/v3/go/omci