[VOL-4589] Remove hardcoding of port speed for NNIs

Change-Id: I118a820749af936ce84933c35a3a0f4e16122626
diff --git a/internal/pkg/core/device_handler.go b/internal/pkg/core/device_handler.go
index 2bdbbb1..9ae21dd 100644
--- a/internal/pkg/core/device_handler.go
+++ b/internal/pkg/core/device_handler.go
@@ -69,6 +69,8 @@
 	McastFlowOrGroupModify = "McastFlowOrGroupModify"
 	McastFlowOrGroupRemove = "McastFlowOrGroupRemove"
 	oltPortInfoTimeout     = 3
+
+	defaultPortSpeedMbps = 1000
 )
 
 //DeviceHandler will interact with the OLT device.
@@ -316,7 +318,48 @@
 	return "", olterrors.NewErrInvalidValue(log.Fields{"port-type": portType}, nil)
 }
 
-func (dh *DeviceHandler) addPort(ctx context.Context, intfID uint32, portType voltha.Port_PortType, state string) error {
+func makeOfpPort(macAddress string, speedMbps uint32) *of.OfpPort {
+	if speedMbps == 0 {
+		//In case it was not set in the indication
+		//and no other value was provided
+		speedMbps = defaultPortSpeedMbps
+	}
+
+	ofpPortSpeed := of.OfpPortFeatures_OFPPF_OTHER
+	switch speedMbps {
+	case 1000000:
+		ofpPortSpeed = of.OfpPortFeatures_OFPPF_1TB_FD
+	case 100000:
+		ofpPortSpeed = of.OfpPortFeatures_OFPPF_100GB_FD
+	case 40000:
+		ofpPortSpeed = of.OfpPortFeatures_OFPPF_40GB_FD
+	case 10000:
+		ofpPortSpeed = of.OfpPortFeatures_OFPPF_10GB_FD
+	case 1000:
+		ofpPortSpeed = of.OfpPortFeatures_OFPPF_1GB_FD
+	case 100:
+		ofpPortSpeed = of.OfpPortFeatures_OFPPF_100MB_FD
+	case 10:
+		ofpPortSpeed = of.OfpPortFeatures_OFPPF_10MB_FD
+	}
+
+	capacity := uint32(ofpPortSpeed | of.OfpPortFeatures_OFPPF_FIBER)
+
+	port := &of.OfpPort{
+		HwAddr:     macAddressToUint32Array(macAddress),
+		Config:     0,
+		State:      uint32(of.OfpPortState_OFPPS_LIVE),
+		Curr:       capacity,
+		Advertised: capacity,
+		Peer:       capacity,
+		CurrSpeed:  speedMbps * 1000, //kbps
+		MaxSpeed:   speedMbps * 1000, //kbps
+	}
+
+	return port
+}
+
+func (dh *DeviceHandler) addPort(ctx context.Context, intfID uint32, portType voltha.Port_PortType, state string, speedMbps uint32) error {
 	var operStatus common.OperStatus_Types
 	if state == "up" {
 		operStatus = voltha.OperStatus_ACTIVE
@@ -355,23 +398,13 @@
 	}
 
 	// Now create Port
-	capacity := uint32(of.OfpPortFeatures_OFPPF_1GB_FD | of.OfpPortFeatures_OFPPF_FIBER)
 	port = &voltha.Port{
 		DeviceId:   dh.device.Id,
 		PortNo:     portNum,
 		Label:      label,
 		Type:       portType,
 		OperStatus: operStatus,
-		OfpPort: &of.OfpPort{
-			HwAddr:     macAddressToUint32Array(dh.device.MacAddress),
-			Config:     0,
-			State:      uint32(of.OfpPortState_OFPPS_LIVE),
-			Curr:       capacity,
-			Advertised: capacity,
-			Peer:       capacity,
-			CurrSpeed:  uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
-			MaxSpeed:   uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
-		},
+		OfpPort:    makeOfpPort(dh.device.MacAddress, speedMbps),
 	}
 	logger.Debugw(ctx, "sending-port-update-to-core", log.Fields{"port": port})
 	// Synchronous call to update device - this method is run in its own go routine
@@ -557,7 +590,7 @@
 
 		intfInd := indication.GetIntfInd()
 		go func() {
-			if err := dh.addPort(ctx, intfInd.GetIntfId(), voltha.Port_PON_OLT, intfInd.GetOperState()); err != nil {
+			if err := dh.addPort(ctx, intfInd.GetIntfId(), voltha.Port_PON_OLT, intfInd.GetOperState(), defaultPortSpeedMbps); err != nil {
 				_ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface", "device-id": dh.device.Id}, err).Log()
 			}
 		}()
@@ -569,7 +602,7 @@
 		intfOperInd := indication.GetIntfOperInd()
 		if intfOperInd.GetType() == "nni" {
 			go func() {
-				if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_ETHERNET_NNI, intfOperInd.GetOperState()); err != nil {
+				if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_ETHERNET_NNI, intfOperInd.GetOperState(), intfOperInd.GetSpeed()); err != nil {
 					_ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface-oper-nni", "device-id": dh.device.Id}, err).Log()
 				}
 			}()
@@ -577,7 +610,7 @@
 			// TODO: Check what needs to be handled here for When PON PORT down, ONU will be down
 			// Handle pon port update
 			go func() {
-				if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_PON_OLT, intfOperInd.GetOperState()); err != nil {
+				if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_PON_OLT, intfOperInd.GetOperState(), defaultPortSpeedMbps); err != nil {
 					_ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface-oper-pon", "device-id": dh.device.Id}, err).Log()
 				}
 			}()
diff --git a/internal/pkg/core/device_handler_test.go b/internal/pkg/core/device_handler_test.go
index f95856e..9c5961c 100644
--- a/internal/pkg/core/device_handler_test.go
+++ b/internal/pkg/core/device_handler_test.go
@@ -907,44 +907,89 @@
 func TestDeviceHandler_addPort(t *testing.T) {
 	dh1 := newMockDeviceHandler()
 	dh2 := negativeDeviceHandler()
+
+	const defaultCapacity = uint32(of.OfpPortFeatures_OFPPF_1GB_FD | of.OfpPortFeatures_OFPPF_FIBER)
 	type args struct {
-		intfID   uint32
-		portType voltha.Port_PortType
-		state    string
+		intfID    uint32
+		portType  voltha.Port_PortType
+		state     string
+		speedMbps uint32
 	}
 	tests := []struct {
-		name          string
-		devicehandler *DeviceHandler
-		args          args
+		name             string
+		devicehandler    *DeviceHandler
+		args             args
+		expectedCapacity uint32
 	}{
 		// State up
-		{"addPort.1", dh1, args{intfID: 1, portType: voltha.Port_UNKNOWN, state: "up"}},
-		{"addPort.2", dh1, args{intfID: 1, portType: voltha.Port_VENET_OLT, state: "up"}},
-		{"addPort.3", dh1, args{intfID: 1, portType: voltha.Port_VENET_ONU, state: "up"}},
-		{"addPort.4", dh1, args{intfID: 1, portType: voltha.Port_ETHERNET_NNI, state: "up"}},
-		{"addPort.5", dh1, args{intfID: 1, portType: voltha.Port_ETHERNET_UNI, state: "up"}},
-		{"addPort.6", dh1, args{intfID: 1, portType: voltha.Port_PON_OLT, state: "up"}},
-		{"addPort.7", dh1, args{intfID: 1, portType: voltha.Port_PON_ONU, state: "up"}},
-		{"addPort.8", dh1, args{intfID: 1, portType: 8, state: "up"}},
+		{"addPort.1", dh1, args{intfID: 1, portType: voltha.Port_UNKNOWN, state: "up"}, defaultCapacity},
+		{"addPort.2", dh1, args{intfID: 1, portType: voltha.Port_VENET_OLT, state: "up"}, defaultCapacity},
+		{"addPort.3", dh1, args{intfID: 1, portType: voltha.Port_VENET_ONU, state: "up"}, defaultCapacity},
+		{"addPort.4", dh1, args{intfID: 1, portType: voltha.Port_ETHERNET_NNI, state: "up", speedMbps: defaultPortSpeedMbps}, defaultCapacity},
+		{"addPort.5", dh1, args{intfID: 1, portType: voltha.Port_ETHERNET_UNI, state: "up"}, defaultCapacity},
+		{"addPort.6", dh1, args{intfID: 1, portType: voltha.Port_PON_OLT, state: "up"}, defaultCapacity},
+		{"addPort.7", dh1, args{intfID: 1, portType: voltha.Port_PON_ONU, state: "up"}, defaultCapacity},
+		{"addPort.8", dh1, args{intfID: 1, portType: 8, state: "up"}, defaultCapacity},
 		// state discovery
-		{"addPort.9", dh1, args{intfID: 1, portType: voltha.Port_UNKNOWN, state: "down"}},
-		{"addPort.10", dh1, args{intfID: 1, portType: voltha.Port_VENET_OLT, state: "down"}},
-		{"addPort.11", dh1, args{intfID: 1, portType: voltha.Port_VENET_ONU, state: "down"}},
-		{"addPort.12", dh1, args{intfID: 1, portType: voltha.Port_ETHERNET_NNI, state: "down"}},
-		{"addPort.13", dh1, args{intfID: 1, portType: voltha.Port_ETHERNET_UNI, state: "down"}},
-		{"addPort.14", dh1, args{intfID: 1, portType: voltha.Port_PON_OLT, state: "down"}},
-		{"addPort.15", dh1, args{intfID: 1, portType: voltha.Port_PON_ONU, state: "down"}},
-		{"addPort.16", dh1, args{intfID: 1, portType: 8, state: "down"}},
+		{"addPort.9", dh1, args{intfID: 1, portType: voltha.Port_UNKNOWN, state: "down"}, defaultCapacity},
+		{"addPort.10", dh1, args{intfID: 1, portType: voltha.Port_VENET_OLT, state: "down"}, defaultCapacity},
+		{"addPort.11", dh1, args{intfID: 1, portType: voltha.Port_VENET_ONU, state: "down"}, defaultCapacity},
+		{"addPort.12", dh1, args{intfID: 1, portType: voltha.Port_ETHERNET_NNI, state: "down", speedMbps: defaultPortSpeedMbps}, defaultCapacity},
+		{"addPort.13", dh1, args{intfID: 1, portType: voltha.Port_ETHERNET_UNI, state: "down"}, defaultCapacity},
+		{"addPort.14", dh1, args{intfID: 1, portType: voltha.Port_PON_OLT, state: "down"}, defaultCapacity},
+		{"addPort.15", dh1, args{intfID: 1, portType: voltha.Port_PON_ONU, state: "down"}, defaultCapacity},
+		{"addPort.16", dh1, args{intfID: 1, portType: 8, state: "down"}, defaultCapacity},
 
-		{"addPort.17", dh2, args{intfID: 1, portType: voltha.Port_ETHERNET_NNI, state: "up"}},
-		{"addPort.18", dh2, args{intfID: 1, portType: voltha.Port_ETHERNET_UNI, state: "up"}},
-		{"addPort.19", dh2, args{intfID: 1, portType: voltha.Port_ETHERNET_NNI, state: "down"}},
-		{"addPort.20", dh2, args{intfID: 1, portType: voltha.Port_ETHERNET_UNI, state: "down"}},
+		{"addPort.17", dh2, args{intfID: 1, portType: voltha.Port_ETHERNET_NNI, state: "up", speedMbps: defaultPortSpeedMbps}, defaultCapacity},
+		{"addPort.18", dh2, args{intfID: 1, portType: voltha.Port_ETHERNET_UNI, state: "up"}, defaultCapacity},
+		{"addPort.19", dh2, args{intfID: 1, portType: voltha.Port_ETHERNET_NNI, state: "down", speedMbps: defaultPortSpeedMbps}, defaultCapacity},
+		{"addPort.20", dh2, args{intfID: 1, portType: voltha.Port_ETHERNET_UNI, state: "down"}, defaultCapacity},
+
+		// NNI speeds
+		{"addPort.21", dh2, args{intfID: 1, portType: voltha.Port_ETHERNET_NNI, state: "up", speedMbps: 0}, defaultCapacity},
+		{"addPort.22", dh2, args{intfID: 1, portType: voltha.Port_ETHERNET_NNI, state: "up", speedMbps: 10}, uint32(of.OfpPortFeatures_OFPPF_10MB_FD | of.OfpPortFeatures_OFPPF_FIBER)},
+		{"addPort.23", dh2, args{intfID: 1, portType: voltha.Port_ETHERNET_NNI, state: "up", speedMbps: 100}, uint32(of.OfpPortFeatures_OFPPF_100MB_FD | of.OfpPortFeatures_OFPPF_FIBER)},
+		{"addPort.24", dh2, args{intfID: 1, portType: voltha.Port_ETHERNET_NNI, state: "up", speedMbps: 1000}, uint32(of.OfpPortFeatures_OFPPF_1GB_FD | of.OfpPortFeatures_OFPPF_FIBER)},
+		{"addPort.25", dh2, args{intfID: 1, portType: voltha.Port_ETHERNET_NNI, state: "up", speedMbps: 10000}, uint32(of.OfpPortFeatures_OFPPF_10GB_FD | of.OfpPortFeatures_OFPPF_FIBER)},
+		{"addPort.26", dh2, args{intfID: 1, portType: voltha.Port_ETHERNET_NNI, state: "up", speedMbps: 40000}, uint32(of.OfpPortFeatures_OFPPF_40GB_FD | of.OfpPortFeatures_OFPPF_FIBER)},
+		{"addPort.27", dh2, args{intfID: 1, portType: voltha.Port_ETHERNET_NNI, state: "up", speedMbps: 100000}, uint32(of.OfpPortFeatures_OFPPF_100GB_FD | of.OfpPortFeatures_OFPPF_FIBER)},
+		{"addPort.28", dh2, args{intfID: 1, portType: voltha.Port_ETHERNET_NNI, state: "up", speedMbps: 1000000}, uint32(of.OfpPortFeatures_OFPPF_1TB_FD | of.OfpPortFeatures_OFPPF_FIBER)},
+		{"addPort.29", dh2, args{intfID: 1, portType: voltha.Port_ETHERNET_NNI, state: "up", speedMbps: 12345}, uint32(of.OfpPortFeatures_OFPPF_OTHER | of.OfpPortFeatures_OFPPF_FIBER)},
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
-			_ = tt.devicehandler.addPort(context.Background(), tt.args.intfID, tt.args.portType, tt.args.state)
-			//TODO: actually verify test cases
+			_ = tt.devicehandler.addPort(context.Background(), tt.args.intfID, tt.args.portType, tt.args.state, tt.args.speedMbps)
+
+			//Check if the correct state is stored
+			storedState, ok := tt.devicehandler.activePorts.Load(tt.args.intfID)
+			expectedState := tt.args.state == "up"
+
+			if !ok {
+				t.Errorf("Port state not stored in test %v", tt.name)
+			} else if storedState != expectedState {
+				t.Errorf("Expected stored port state: %v, found: %v in test %v", expectedState, storedState, tt.name)
+			}
+
+			//Check if the reported speed values are correct
+			ofpPort := makeOfpPort(tt.devicehandler.device.MacAddress, tt.args.speedMbps)
+
+			if ofpPort.Curr != tt.expectedCapacity ||
+				ofpPort.Advertised != tt.expectedCapacity ||
+				ofpPort.Peer != tt.expectedCapacity {
+				t.Errorf("Expected port capacity: %v, found: (%v,%v,%v) in test %v", tt.expectedCapacity, ofpPort.Curr, ofpPort.Advertised, ofpPort.Peer, tt.name)
+			}
+
+			var expectedSpeedKbps uint32
+			if tt.args.speedMbps == 0 {
+				expectedSpeedKbps = defaultPortSpeedMbps * 1000
+			} else {
+				expectedSpeedKbps = tt.args.speedMbps * 1000
+			}
+
+			if ofpPort.CurrSpeed != expectedSpeedKbps ||
+				ofpPort.MaxSpeed != expectedSpeedKbps {
+				t.Errorf("Expected port speed: %v, found: (%v,%v) in test %v", expectedSpeedKbps, ofpPort.CurrSpeed, ofpPort.MaxSpeed, tt.name)
+			}
 		})
 	}
 }