VOL-3121 -  Separated out logical ports from logical agent.

Similar to flows/groups/meters.
Also modified device_route tests to generate unique port IDs (`.OfpPort.PortNo`s) across all UNI ports withing each test, i.e. within an OLT.
Also replaced logicalPortsNo map & associated NNI vs UNI logic with root device checks.

Change-Id: Ib0cecbf7d4f8d509ce7c989b9ccf697c8b0d17d6
diff --git a/rw_core/core/device/logical_manager.go b/rw_core/core/device/logical_manager.go
index d6ca4ce..b3f26da 100644
--- a/rw_core/core/device/logical_manager.go
+++ b/rw_core/core/device/logical_manager.go
@@ -20,6 +20,7 @@
 	"context"
 	"errors"
 	"io"
+	"strconv"
 	"strings"
 	"sync"
 	"time"
@@ -260,6 +261,8 @@
 	}
 	// Device is child device
 	//	retrieve parent device using child device ID
+	// TODO: return (string, have) instead of *string
+	//       also: If not root device, just return device.parentID instead of loading the parent device.
 	if parentDevice := ldMgr.deviceMgr.getParentDevice(ctx, device); parentDevice != nil {
 		return &parentDevice.ParentId, nil
 	}
@@ -276,26 +279,6 @@
 	return ldMgr.getLogicalDeviceID(ctx, device)
 }
 
-func (ldMgr *LogicalManager) getLogicalPortID(ctx context.Context, device *voltha.Device) (*voltha.LogicalPortId, error) {
-	// Get the logical device where this device is attached
-	var lDeviceID *string
-	var err error
-	if lDeviceID, err = ldMgr.getLogicalDeviceID(ctx, device); err != nil {
-		return nil, err
-	}
-	var lDevice *voltha.LogicalDevice
-	if lDevice, err = ldMgr.GetLogicalDevice(ctx, &voltha.ID{Id: *lDeviceID}); err != nil {
-		return nil, err
-	}
-	// Go over list of ports
-	for _, port := range lDevice.Ports {
-		if port.DeviceId == device.Id {
-			return &voltha.LogicalPortId{Id: *lDeviceID, PortId: port.Id}, nil
-		}
-	}
-	return nil, status.Errorf(codes.NotFound, "%s", device.Id)
-}
-
 // ListLogicalDeviceFlows returns the flows of logical device
 func (ldMgr *LogicalManager) ListLogicalDeviceFlows(ctx context.Context, id *voltha.ID) (*openflow_13.Flows, error) {
 	logger.Debugw("ListLogicalDeviceFlows", log.Fields{"logicaldeviceid": id.Id})
@@ -333,22 +316,29 @@
 // ListLogicalDevicePorts returns logical device ports
 func (ldMgr *LogicalManager) ListLogicalDevicePorts(ctx context.Context, id *voltha.ID) (*voltha.LogicalPorts, error) {
 	logger.Debugw("ListLogicalDevicePorts", log.Fields{"logicaldeviceid": id.Id})
-	if agent := ldMgr.getLogicalDeviceAgent(ctx, id.Id); agent != nil {
-		return agent.ListLogicalDevicePorts(ctx)
+	agent := ldMgr.getLogicalDeviceAgent(ctx, id.Id)
+	if agent == nil {
+		return nil, status.Errorf(codes.NotFound, "%s", id.Id)
 	}
-	return nil, status.Errorf(codes.NotFound, "%s", id.Id)
+
+	ports := agent.listLogicalDevicePorts()
+	ctr, ret := 0, make([]*voltha.LogicalPort, len(ports))
+	for _, port := range ports {
+		ret[ctr] = port
+		ctr++
+	}
+	return &voltha.LogicalPorts{Items: ret}, nil
 }
 
 // GetLogicalDevicePort returns logical device port details
 func (ldMgr *LogicalManager) GetLogicalDevicePort(ctx context.Context, lPortID *voltha.LogicalPortId) (*voltha.LogicalPort, error) {
-	// Get the logical device where this device is attached
-	var err error
-	var lDevice *voltha.LogicalDevice
-	if lDevice, err = ldMgr.GetLogicalDevice(ctx, &voltha.ID{Id: lPortID.Id}); err != nil {
-		return nil, err
+	// Get the logical device where this port is attached
+	agent := ldMgr.getLogicalDeviceAgent(ctx, lPortID.Id)
+	if agent == nil {
+		return nil, status.Errorf(codes.NotFound, "%s", lPortID.Id)
 	}
-	// Go over list of ports
-	for _, port := range lDevice.Ports {
+
+	for _, port := range agent.listLogicalDevicePorts() {
 		if port.Id == lPortID.PortId {
 			return port, nil
 		}
@@ -373,30 +363,6 @@
 	return nil
 }
 
-// deleteLogicalPort removes the logical port associated with a device
-func (ldMgr *LogicalManager) deleteLogicalPort(ctx context.Context, lPortID *voltha.LogicalPortId) error {
-	logger.Debugw("deleting-logical-port", log.Fields{"LDeviceId": lPortID.Id})
-	// Get logical port
-	var logicalPort *voltha.LogicalPort
-	var err error
-	if logicalPort, err = ldMgr.GetLogicalDevicePort(ctx, lPortID); err != nil {
-		logger.Debugw("no-logical-device-port-present", log.Fields{"logicalPortId": lPortID.PortId})
-		return err
-	}
-	// Sanity check
-	if logicalPort.RootPort {
-		return errors.New("device-root")
-	}
-	if agent := ldMgr.getLogicalDeviceAgent(ctx, lPortID.Id); agent != nil {
-		if err := agent.deleteLogicalPort(ctx, logicalPort); err != nil {
-			logger.Warnw("deleting-logicalport-failed", log.Fields{"LDeviceId": lPortID.Id, "error": err})
-		}
-	}
-
-	logger.Debug("deleting-logical-port-ends")
-	return nil
-}
-
 // deleteLogicalPort removes the logical port associated with a child device
 func (ldMgr *LogicalManager) deleteLogicalPorts(ctx context.Context, deviceID string) error {
 	logger.Debugw("deleting-logical-ports", log.Fields{"device-id": deviceID})
@@ -469,7 +435,7 @@
 		return err
 	}
 	if agent := ldMgr.getLogicalDeviceAgent(ctx, *ldID); agent != nil {
-		if err := agent.updatePortState(ctx, deviceID, portNo, state); err != nil {
+		if err := agent.updatePortState(ctx, portNo, state); err != nil {
 			return err
 		}
 	}
@@ -487,7 +453,7 @@
 		return err
 	}
 	if agent := ldMgr.getLogicalDeviceAgent(ctx, *ldID); agent != nil {
-		if err := agent.updatePortsState(ctx, device, state); err != nil {
+		if err := agent.updatePortsState(ctx, device.Id, state); err != nil {
 			return err
 		}
 	}
@@ -547,7 +513,11 @@
 	if agent == nil {
 		return nil, status.Errorf(codes.NotFound, "%s", id.Id)
 	}
-	return &empty.Empty{}, agent.enableLogicalPort(ctx, id.PortId)
+	portNo, err := strconv.ParseUint(id.PortId, 10, 32)
+	if err != nil {
+		return nil, status.Errorf(codes.InvalidArgument, "failed to parse %s as a number", id.PortId)
+	}
+	return &empty.Empty{}, agent.enableLogicalPort(ctx, uint32(portNo))
 }
 
 // DisableLogicalDevicePort disables logical device port
@@ -557,7 +527,11 @@
 	if agent == nil {
 		return nil, status.Errorf(codes.NotFound, "%s", id.Id)
 	}
-	return &empty.Empty{}, agent.disableLogicalPort(ctx, id.PortId)
+	portNo, err := strconv.ParseUint(id.PortId, 10, 32)
+	if err != nil {
+		return nil, status.Errorf(codes.InvalidArgument, "failed to parse %s as a number", id.PortId)
+	}
+	return &empty.Empty{}, agent.disableLogicalPort(ctx, uint32(portNo))
 }
 
 func (ldMgr *LogicalManager) packetIn(ctx context.Context, logicalDeviceID string, port uint32, transactionID string, packet []byte) error {