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/api/grpc_nbi_handler_test.go b/rw_core/core/api/grpc_nbi_handler_test.go
index 5801f27..2eff4a4 100755
--- a/rw_core/core/api/grpc_nbi_handler_test.go
+++ b/rw_core/core/api/grpc_nbi_handler_test.go
@@ -150,6 +150,9 @@
 	assert.Equal(t, 1, len(logicalDevices.Items))
 
 	ld := logicalDevices.Items[0]
+	ports, err := nbi.ListLogicalDevicePorts(getContext(), &voltha.ID{Id: ld.Id})
+	assert.Nil(t, err)
+
 	assert.NotEqual(t, "", ld.Id)
 	assert.NotEqual(t, uint64(0), ld.DatapathId)
 	assert.Equal(t, "olt_adapter_mock", ld.Desc.HwDesc)
@@ -159,7 +162,7 @@
 	assert.Equal(t, uint32(256), ld.SwitchFeatures.NBuffers)
 	assert.Equal(t, uint32(2), ld.SwitchFeatures.NTables)
 	assert.Equal(t, uint32(15), ld.SwitchFeatures.Capabilities)
-	assert.Equal(t, 1+nb.numONUPerOLT, len(ld.Ports))
+	assert.Equal(t, 1+nb.numONUPerOLT, len(ports.Items))
 	assert.Equal(t, oltDevice.ParentId, ld.Id)
 	//Expected port no
 	expectedPortNo := make(map[uint32]bool)
@@ -167,7 +170,7 @@
 	for i := 0; i < nb.numONUPerOLT; i++ {
 		expectedPortNo[uint32(i+100)] = false
 	}
-	for _, p := range ld.Ports {
+	for _, p := range ports.Items {
 		assert.Equal(t, p.OfpPort.PortNo, p.DevicePortNo)
 		assert.Equal(t, uint32(4), p.OfpPort.State)
 		expectedPortNo[p.OfpPort.PortNo] = true
@@ -393,10 +396,10 @@
 	assert.Nil(t, err)
 
 	// Wait for the logical device to be in the ready state
-	var vldFunction isLogicalDeviceConditionSatisfied = func(ld *voltha.LogicalDevice) bool {
-		return ld != nil && len(ld.Ports) == nb.numONUPerOLT+1
+	var vldFunction = func(ports []*voltha.LogicalPort) bool {
+		return len(ports) == nb.numONUPerOLT+1
 	}
-	err = waitUntilLogicalDeviceReadiness(oltDevice.Id, nb.maxTimeout, nbi, vldFunction)
+	err = waitUntilLogicalDevicePortsReadiness(oltDevice.Id, nb.maxTimeout, nbi, vldFunction)
 	assert.Nil(t, err)
 
 	// Verify that the devices have been setup correctly
@@ -439,11 +442,8 @@
 	}
 
 	// Wait for the logical device to satisfy the expected condition
-	var vlFunction isLogicalDeviceConditionSatisfied = func(ld *voltha.LogicalDevice) bool {
-		if ld == nil {
-			return false
-		}
-		for _, lp := range ld.Ports {
+	var vlFunction = func(ports []*voltha.LogicalPort) bool {
+		for _, lp := range ports {
 			if (lp.OfpPort.Config&uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN) != lp.OfpPort.Config) ||
 				lp.OfpPort.State != uint32(ofp.OfpPortState_OFPPS_LINK_DOWN) {
 				return false
@@ -451,7 +451,7 @@
 		}
 		return true
 	}
-	err = waitUntilLogicalDeviceReadiness(oltDevice.Id, nb.maxTimeout, nbi, vlFunction)
+	err = waitUntilLogicalDevicePortsReadiness(oltDevice.Id, nb.maxTimeout, nbi, vlFunction)
 	assert.Nil(t, err)
 
 	// Reenable the oltDevice
@@ -474,11 +474,8 @@
 	}
 
 	// Wait for the logical device to satisfy the expected condition
-	vlFunction = func(ld *voltha.LogicalDevice) bool {
-		if ld == nil {
-			return false
-		}
-		for _, lp := range ld.Ports {
+	vlFunction = func(ports []*voltha.LogicalPort) bool {
+		for _, lp := range ports {
 			if (lp.OfpPort.Config&^uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN) != lp.OfpPort.Config) ||
 				lp.OfpPort.State != uint32(ofp.OfpPortState_OFPPS_LIVE) {
 				return false
@@ -486,7 +483,7 @@
 		}
 		return true
 	}
-	err = waitUntilLogicalDeviceReadiness(oltDevice.Id, nb.maxTimeout, nbi, vlFunction)
+	err = waitUntilLogicalDevicePortsReadiness(oltDevice.Id, nb.maxTimeout, nbi, vlFunction)
 	assert.Nil(t, err)
 }
 
@@ -581,10 +578,10 @@
 	assert.Nil(t, err)
 
 	// Wait for the logical device to be in the ready state
-	var vldFunction isLogicalDeviceConditionSatisfied = func(ld *voltha.LogicalDevice) bool {
-		return ld != nil && len(ld.Ports) == nb.numONUPerOLT+1
+	var vldFunction = func(ports []*voltha.LogicalPort) bool {
+		return len(ports) == nb.numONUPerOLT+1
 	}
-	err = waitUntilLogicalDeviceReadiness(oltDevice.Id, nb.maxTimeout, nbi, vldFunction)
+	err = waitUntilLogicalDevicePortsReadiness(oltDevice.Id, nb.maxTimeout, nbi, vldFunction)
 	assert.Nil(t, err)
 
 	//Get all child devices
@@ -664,11 +661,8 @@
 	err = waitUntilDeviceReadiness(oltDevice.Id, nb.maxTimeout, vdFunction, nbi)
 	assert.Nil(t, err)
 	// Wait for the logical device to satisfy the expected condition
-	var vlFunction = func(ld *voltha.LogicalDevice) bool {
-		if ld == nil {
-			return false
-		}
-		for _, lp := range ld.Ports {
+	var vlFunction = func(ports []*voltha.LogicalPort) bool {
+		for _, lp := range ports {
 			if (lp.OfpPort.Config&^uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN) != lp.OfpPort.Config) ||
 				lp.OfpPort.State != uint32(ofp.OfpPortState_OFPPS_LIVE) {
 				return false
@@ -676,7 +670,7 @@
 		}
 		return true
 	}
-	err = waitUntilLogicalDeviceReadiness(oltDevice.Id, nb.maxTimeout, nbi, vlFunction)
+	err = waitUntilLogicalDevicePortsReadiness(oltDevice.Id, nb.maxTimeout, nbi, vlFunction)
 	assert.Nil(t, err)
 
 	// Enable the NW Port of oltDevice
@@ -695,11 +689,8 @@
 	err = waitUntilDeviceReadiness(oltDevice.Id, nb.maxTimeout, vdFunction, nbi)
 	assert.Nil(t, err)
 	// Wait for the logical device to satisfy the expected condition
-	vlFunction = func(ld *voltha.LogicalDevice) bool {
-		if ld == nil {
-			return false
-		}
-		for _, lp := range ld.Ports {
+	vlFunction = func(ports []*voltha.LogicalPort) bool {
+		for _, lp := range ports {
 			if (lp.OfpPort.Config&^uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN) != lp.OfpPort.Config) ||
 				lp.OfpPort.State != uint32(ofp.OfpPortState_OFPPS_LIVE) {
 				return false
@@ -707,7 +698,7 @@
 		}
 		return true
 	}
-	err = waitUntilLogicalDeviceReadiness(oltDevice.Id, nb.maxTimeout, nbi, vlFunction)
+	err = waitUntilLogicalDevicePortsReadiness(oltDevice.Id, nb.maxTimeout, nbi, vlFunction)
 	assert.Nil(t, err)
 
 	// Disable a non-PON port
@@ -876,10 +867,10 @@
 	assert.Nil(t, err)
 
 	// Wait for the logical device to be in the ready state
-	var vldFunction isLogicalDeviceConditionSatisfied = func(ld *voltha.LogicalDevice) bool {
-		return ld != nil && len(ld.Ports) == nb.numONUPerOLT+1
+	var vldFunction = func(ports []*voltha.LogicalPort) bool {
+		return len(ports) == nb.numONUPerOLT+1
 	}
-	err = waitUntilLogicalDeviceReadiness(oltDevice.Id, nb.maxTimeout, nbi, vldFunction)
+	err = waitUntilLogicalDevicePortsReadiness(oltDevice.Id, nb.maxTimeout, nbi, vldFunction)
 	assert.Nil(t, err)
 
 	// Wait for the olt device to be enabled
@@ -939,11 +930,11 @@
 	assert.Nil(t, err)
 }
 
-func (nb *NBTest) sendTrapFlows(t *testing.T, nbi *NBIHandler, logicalDevice *voltha.LogicalDevice, meterID uint64, startingVlan int) (numNNIPorts, numUNIPorts int) {
+func (nb *NBTest) sendTrapFlows(t *testing.T, nbi *NBIHandler, logicalDeviceID string, ports []*voltha.LogicalPort, meterID uint64, startingVlan int) (numNNIPorts, numUNIPorts int) {
 	// Send flows for the parent device
 	var nniPorts []*voltha.LogicalPort
 	var uniPorts []*voltha.LogicalPort
-	for _, p := range logicalDevice.Ports {
+	for _, p := range ports {
 		if p.RootPort {
 			nniPorts = append(nniPorts, p)
 		} else {
@@ -966,7 +957,7 @@
 			flows.Output(controllerPortMask),
 		},
 	}
-	flowLLDP := ofp.FlowTableUpdate{FlowMod: makeSimpleFlowMod(fa), Id: logicalDevice.Id}
+	flowLLDP := ofp.FlowTableUpdate{FlowMod: makeSimpleFlowMod(fa), Id: logicalDeviceID}
 	_, err := nbi.UpdateLogicalDeviceFlowTable(getContext(), &flowLLDP)
 	assert.Nil(t, err)
 
@@ -983,7 +974,7 @@
 			flows.Output(controllerPortMask),
 		},
 	}
-	flowIPV4 := ofp.FlowTableUpdate{FlowMod: makeSimpleFlowMod(fa), Id: logicalDevice.Id}
+	flowIPV4 := ofp.FlowTableUpdate{FlowMod: makeSimpleFlowMod(fa), Id: logicalDeviceID}
 	_, err = nbi.UpdateLogicalDeviceFlowTable(getContext(), &flowIPV4)
 	assert.Nil(t, err)
 
@@ -1000,7 +991,7 @@
 			flows.Output(controllerPortMask),
 		},
 	}
-	flowIPV6 := ofp.FlowTableUpdate{FlowMod: makeSimpleFlowMod(fa), Id: logicalDevice.Id}
+	flowIPV6 := ofp.FlowTableUpdate{FlowMod: makeSimpleFlowMod(fa), Id: logicalDeviceID}
 	_, err = nbi.UpdateLogicalDeviceFlowTable(getContext(), &flowIPV6)
 	assert.Nil(t, err)
 
@@ -1059,9 +1050,13 @@
 		}
 		// Ensure there are both NNI ports and at least one UNI port on the logical device
 		ld := lds.Items[0]
+		ports, err := nbi.ListLogicalDevicePorts(getContext(), &voltha.ID{Id: ld.Id})
+		if err != nil {
+			return false
+		}
 		nniPort := false
 		uniPort := false
-		for _, p := range ld.Ports {
+		for _, p := range ports.Items {
 			nniPort = nniPort || p.RootPort == true
 			uniPort = uniPort || p.RootPort == false
 			if nniPort && uniPort {
@@ -1078,7 +1073,7 @@
 	assert.NotNil(t, logicalDevices)
 	assert.Equal(t, 1, len(logicalDevices.Items))
 
-	logicalDevice := logicalDevices.Items[0]
+	logicalDeviceID := logicalDevices.Items[0].Id
 	meterID := rand.Uint32()
 
 	// Add a meter to the logical device
@@ -1094,12 +1089,15 @@
 			},
 		},
 	}
-	_, err = nbi.UpdateLogicalDeviceMeterTable(getContext(), &ofp.MeterModUpdate{Id: logicalDevice.Id, MeterMod: meterMod})
+	_, err = nbi.UpdateLogicalDeviceMeterTable(getContext(), &ofp.MeterModUpdate{Id: logicalDeviceID, MeterMod: meterMod})
+	assert.Nil(t, err)
+
+	ports, err := nbi.ListLogicalDevicePorts(getContext(), &voltha.ID{Id: logicalDeviceID})
 	assert.Nil(t, err)
 
 	// Send initial set of Trap flows
 	startingVlan := 4091
-	nb.sendTrapFlows(t, nbi, logicalDevice, uint64(meterID), startingVlan)
+	nb.sendTrapFlows(t, nbi, logicalDeviceID, ports.Items, uint64(meterID), startingVlan)
 
 	// Listen for port events
 	start := time.Now()
@@ -1113,7 +1111,7 @@
 			if ps.Reason == ofp.OfpPortReason_OFPPR_ADD {
 				if ps.Desc.PortNo >= uint32(nb.startingUNIPortNo) {
 					processedUniLogicalPorts++
-					nb.sendEAPFlows(t, nbi, logicalDevice.Id, ps.Desc, startingVlan, uint64(meterID))
+					nb.sendEAPFlows(t, nbi, logicalDeviceID, ps.Desc, startingVlan, uint64(meterID))
 				} else {
 					processedNniLogicalPorts++
 				}
@@ -1174,10 +1172,10 @@
 	assert.Nil(t, err)
 
 	// Wait for the logical device to be in the ready state
-	var vldFunction isLogicalDeviceConditionSatisfied = func(ld *voltha.LogicalDevice) bool {
-		return ld != nil && len(ld.Ports) == nb.numONUPerOLT+1
+	var vldFunction = func(ports []*voltha.LogicalPort) bool {
+		return len(ports) == nb.numONUPerOLT+1
 	}
-	err = waitUntilLogicalDeviceReadiness(oltDevice.Id, nb.maxTimeout, nbi, vldFunction)
+	err = waitUntilLogicalDevicePortsReadiness(oltDevice.Id, nb.maxTimeout, nbi, vldFunction)
 	assert.Nil(t, err)
 
 	// Verify that the devices have been setup correctly