SEBA-300 Add ponsim_onu performance metrics

Change-Id: I8d43293511d38006d1a5495d99bf2e968cdb6241
diff --git a/ponsim/v2/core/ponsim_metric.go b/ponsim/v2/core/ponsim_metric.go
index 953a438..e9e1585 100644
--- a/ponsim/v2/core/ponsim_metric.go
+++ b/ponsim/v2/core/ponsim_metric.go
@@ -114,6 +114,7 @@
  */
 type PonSimMetricCounter struct {
 	Name       string
+	Device_Type string
 	TxCounters map[txMetricCounterType]*metricCounter
 	RxCounters map[rxMetricCounterType]*metricCounter
 }
@@ -121,8 +122,8 @@
 /*
 NewPonSimMetricCounter instantiates new metric counters for a PON device
 */
-func NewPonSimMetricCounter(name string) *PonSimMetricCounter {
-	counter := &PonSimMetricCounter{Name: name}
+func NewPonSimMetricCounter(name string, device_type string) *PonSimMetricCounter {
+	counter := &PonSimMetricCounter{Name: name, Device_Type: device_type}
 
 	counter.TxCounters = map[txMetricCounterType]*metricCounter{
 		tx_64_pkts:        newTxMetricCounter(tx_64_pkts, 1, 64),
@@ -186,7 +187,18 @@
 func (mc *PonSimMetricCounter) MakeProto() *voltha.PonSimMetrics {
 	simMetrics := &voltha.PonSimMetrics{Device: mc.Name}
 	ponMetrics := &voltha.PonSimPortMetrics{PortName: "pon"}
-	nniMetrics := &voltha.PonSimPortMetrics{PortName: "nni"}
+	portMetrics := &voltha.PonSimPortMetrics{}
+
+	if (mc.Device_Type == "ONU") {
+	    portMetrics.PortName = "uni"
+	} else if (mc.Device_Type == "OLT") {
+	    portMetrics.PortName = "nni"
+	} else {
+	    common.Logger().WithFields(logrus.Fields{
+		"counters": mc.RxCounters,
+	    }).Error("Unknown Device_Type in PonSimMetricCounter")
+	    portMetrics.PortName = "unknown"
+	}
 
 	// Collect RX metrics
 	for _, c := range mc.RxCounters {
@@ -198,9 +210,9 @@
 				Value: int64(c.Value[0]),
 			},
 		)
-		// NNI values
-		nniMetrics.Packets = append(
-			nniMetrics.Packets,
+		// NNI/UNI values
+		portMetrics.Packets = append(
+			portMetrics.Packets,
 			&voltha.PonSimPacketCounter{
 				Name:  c.Name,
 				Value: int64(c.Value[1]),
@@ -217,9 +229,9 @@
 				Value: int64(c.Value[0]),
 			},
 		)
-		// NNI values
-		nniMetrics.Packets = append(
-			nniMetrics.Packets,
+		// NNI/UNI values
+		portMetrics.Packets = append(
+			portMetrics.Packets,
 			&voltha.PonSimPacketCounter{
 				Name:  c.Name,
 				Value: int64(c.Value[1]),
@@ -229,7 +241,7 @@
 
 	// Populate GRPC proto structure
 	simMetrics.Metrics = append(simMetrics.Metrics, ponMetrics)
-	simMetrics.Metrics = append(simMetrics.Metrics, nniMetrics)
+	simMetrics.Metrics = append(simMetrics.Metrics, portMetrics)
 
 	return simMetrics
 }
diff --git a/ponsim/v2/grpc/nbi/ponsim_handler.go b/ponsim/v2/grpc/nbi/ponsim_handler.go
index ec64d5c..df73a34 100644
--- a/ponsim/v2/grpc/nbi/ponsim_handler.go
+++ b/ponsim/v2/grpc/nbi/ponsim_handler.go
@@ -266,7 +266,7 @@
 */
 func (handler *PonSimHandler) GetStats(
 	ctx context.Context,
-	empty *empty.Empty,
+	req *voltha.PonSimMetricsRequest,
 ) (*voltha.PonSimMetrics, error) {
 	common.Logger().WithFields(logrus.Fields{
 		"handler": handler,
@@ -280,35 +280,47 @@
 			"olt":     olt,
 		}).Debug("Retrieving stats for OLT")
 
-		// Get stats for current device
+		if req.Port == 0 {
+			// port == 0, return the OLT statistics
+			metrics = (handler.device).(*core.PonSimOltDevice).Counter.MakeProto()
+		} else {
+			common.Logger().WithFields(logrus.Fields{
+			    "handler": handler,
+			    "port":   req.Port,
+			}).Debug("Request is for ONU")
 
-		// Loop through each onus to get stats from those as well?
-		// send grpc request to each onu
-		for _, child := range (handler.device).(*core.PonSimOltDevice).GetOnus() {
+			// port != 0, contact the ONU, retrieve onu statistics, and return to the caller
+			if child, ok := (handler.device).(*core.PonSimOltDevice).GetOnus()[req.Port]; ok {
+				host := strings.Join([]string{child.Device.Address, strconv.Itoa(int(child.Device.Port))}, ":")
+				conn, err := grpc.Dial(
+					host,
+					grpc.WithInsecure(),
+				)
+				if err != nil {
+					common.Logger().WithFields(logrus.Fields{
+					    "handler": handler,
+					    "error":   err.Error(),
+					}).Error("GRPC Connection problem")
+				}
+				defer conn.Close()
+				client := voltha.NewPonSimClient(conn)
 
-			host := strings.Join([]string{child.Device.Address, strconv.Itoa(int(child.Device.Port))}, ":")
-			conn, err := grpc.Dial(
-				host,
-				grpc.WithInsecure(),
-			)
-			if err != nil {
+				if onu_stats, err := client.GetStats(ctx, req); err != nil {
+					common.Logger().WithFields(logrus.Fields{
+					    "handler": handler,
+					    "host":    host,
+					    "error":   err.Error(),
+					}).Error("Problem forwarding stats request to ONU")
+				} else {
+					metrics = onu_stats
+				}
+			} else {
 				common.Logger().WithFields(logrus.Fields{
 					"handler": handler,
-					"error":   err.Error(),
-				}).Error("GRPC Connection problem")
-			}
-			defer conn.Close()
-			client := voltha.NewPonSimClient(conn)
-
-			if _, err = client.GetStats(ctx, empty); err != nil {
-				common.Logger().WithFields(logrus.Fields{
-					"handler": handler,
-					"host":    host,
-					"error":   err.Error(),
-				}).Error("Problem forwarding stats request to ONU")
+					"port":    req.Port,
+				}).Warn("Unable to find ONU")
 			}
 		}
-		metrics = (handler.device).(*core.PonSimOltDevice).Counter.MakeProto()
 
 		common.Logger().WithFields(logrus.Fields{
 			"handler": handler,
@@ -320,6 +332,11 @@
 			"handler": handler,
 			"onu":     onu,
 		}).Debug("Retrieving stats for ONU")
+		metrics = (handler.device).(*core.PonSimOnuDevice).Counter.MakeProto()
+		common.Logger().WithFields(logrus.Fields{
+			"handler": handler,
+			"metrics": metrics,
+		}).Debug("ONU Metrics")
 	} else {
 		common.Logger().WithFields(logrus.Fields{
 			"handler": handler,
diff --git a/ponsim/v2/ponsim.go b/ponsim/v2/ponsim.go
index cbb863d..0981351 100644
--- a/ponsim/v2/ponsim.go
+++ b/ponsim/v2/ponsim.go
@@ -263,7 +263,7 @@
 		Port:        int32(grpc_port),
 		AlarmsOn:    alarm_sim,
 		AlarmsFreq:  alarm_freq,
-		Counter:     core.NewPonSimMetricCounter(name),
+		Counter:     core.NewPonSimMetricCounter(name, device_type),
 
 		// TODO: pass certificates
 		//GrpcSecurity: certs,