BNG statistics exported on prometheus

The BNG statistics now are single events per attachment, the attributes of the events also changed slightly.
The BNG statistics are also all optional, if not present they won't be pushed on Prometheus.

Change-Id: I361578209b35c7bbbcdd6fd8ec37df07a67eb71b
diff --git a/main.go b/main.go
index 39c4700..752882b 100644
--- a/main.go
+++ b/main.go
@@ -109,15 +109,17 @@
 	prometheus.MustRegister(onosaaaRequestRttMillis)
 	prometheus.MustRegister(onosaaaRequestReTx)
 
-	prometheus.MustRegister(onosPppoeUpTermBytes)
-	prometheus.MustRegister(onosPppoeUpTermPackets)
-	prometheus.MustRegister(onosPppoeUpDropBytes)
-	prometheus.MustRegister(onosPppoeUpDropPackets)
-	prometheus.MustRegister(onosPppoeUpControlPackets)
-	prometheus.MustRegister(onosPppoeDownRxBytes)
-	prometheus.MustRegister(onosPppoeDownRxPackets)
-	prometheus.MustRegister(onosPppoeDownTxBytes)
-	prometheus.MustRegister(onosPppoeDownTxPackets)
+	prometheus.MustRegister(onosBngUpTxBytes)
+	prometheus.MustRegister(onosBngUpTxPackets)
+	prometheus.MustRegister(onosBngUpDropBytes)
+	prometheus.MustRegister(onosBngUpDropPackets)
+	prometheus.MustRegister(onosBngControlPackets)
+	prometheus.MustRegister(onosBngDownRxBytes)
+	prometheus.MustRegister(onosBngDownRxPackets)
+	prometheus.MustRegister(onosBngDownTxBytes)
+	prometheus.MustRegister(onosBngDownTxPackets)
+	prometheus.MustRegister(onosBngDownDropPackets)
+	prometheus.MustRegister(onosBngDownDropBytes)
 
 	prometheus.MustRegister(deviceLaserBiasCurrent)
 	prometheus.MustRegister(deviceTemperature)
diff --git a/topic-exporter.go b/topic-exporter.go
index 4e8d2f6..5e49e9d 100644
--- a/topic-exporter.go
+++ b/topic-exporter.go
@@ -219,74 +219,113 @@
 			Help: "Number of access request packets retransmitted to the server",
 		})
 
-	// ONOS PPPoE kpis
+	// ONOS BNG kpis
 
-	onosPppoeUpTermBytes = prometheus.NewGaugeVec(
+	// --------------------- BNG UPSTREAM STATISTICS -----------------------------------------
+	onosBngUpTxBytes = prometheus.NewGaugeVec(
 		prometheus.GaugeOpts{
-			Name: "onosPppoeupTermBytes",
-			Help: "onosPppoeupTermBytes",
+			Name: "onosBngUpTxBytes",
+			Help: "onosBngUpTxBytes",
 		},
-		[]string{"mac_address", "ip", "session_id", "s_tag", "c_tag", "onu_serial"},
+		[]string{"mac_address", "ip", "session_id", "s_tag", "c_tag", "onu_serial", "type"},
 	)
-	onosPppoeUpTermPackets = prometheus.NewGaugeVec(
+	onosBngUpTxPackets = prometheus.NewGaugeVec(
 		prometheus.GaugeOpts{
-			Name: "onosPppoeupTermPackets",
-			Help: "onosPppoeupTermPackets",
+			Name: "onosBngUpTxPackets",
+			Help: "onosBngUpTxPackets",
 		},
-		[]string{"mac_address", "ip", "session_id", "s_tag", "c_tag", "onu_serial"},
+		[]string{"mac_address", "ip", "session_id", "s_tag", "c_tag", "onu_serial", "type"},
 	)
-	onosPppoeUpDropBytes = prometheus.NewGaugeVec(
+
+	onosBngUpRxBytes = prometheus.NewGaugeVec(
 		prometheus.GaugeOpts{
-			Name: "onosPppoeupDropBytes",
-			Help: "onosPppoeupDropBytes",
+			Name: "onosBngUpRxBytes",
+			Help: "onosBngUpRxBytes",
 		},
-		[]string{"mac_address", "ip", "session_id", "s_tag", "c_tag", "onu_serial"},
+		[]string{"mac_address", "ip", "session_id", "s_tag", "c_tag", "onu_serial", "type"},
 	)
-	onosPppoeUpDropPackets = prometheus.NewGaugeVec(
+
+	onosBngUpRxPackets = prometheus.NewGaugeVec(
 		prometheus.GaugeOpts{
-			Name: "onosPppoeupDropPackets",
-			Help: "onosPppoeupDropPackets",
+			Name: "onosBngUpRxPackets",
+			Help: "onosBngUpRxPackets",
 		},
-		[]string{"mac_address", "ip", "session_id", "s_tag", "c_tag", "onu_serial"},
+		[]string{"mac_address", "ip", "session_id", "s_tag", "c_tag", "onu_serial", "type"},
 	)
-	onosPppoeUpControlPackets = prometheus.NewGaugeVec(
+	onosBngUpDropBytes = prometheus.NewGaugeVec(
 		prometheus.GaugeOpts{
-			Name: "onosPppoeupControlPackets",
-			Help: "onosPppoeupControlPackets",
+			Name: "onosBngUpDropBytes",
+			Help: "onosBngUpDropBytes",
 		},
-		[]string{"mac_address", "ip", "session_id", "s_tag", "c_tag", "onu_serial"},
+		[]string{"mac_address", "ip", "session_id", "s_tag", "c_tag", "onu_serial", "type"},
 	)
-	onosPppoeDownRxBytes = prometheus.NewGaugeVec(
+	onosBngUpDropPackets = prometheus.NewGaugeVec(
 		prometheus.GaugeOpts{
-			Name: "onosPppoedownRxBytes",
-			Help: "onosPppoedownRxBytes",
+			Name: "onosBngUpDropPackets",
+			Help: "onosBngUpDropPackets",
 		},
-		[]string{"mac_address", "ip", "session_id", "s_tag", "c_tag", "onu_serial"},
+		[]string{"mac_address", "ip", "session_id", "s_tag", "c_tag", "onu_serial", "type"},
 	)
-	onosPppoeDownRxPackets = prometheus.NewGaugeVec(
+
+	// --------------------- BNG CONTROL STATISTICS ------------------------------------------
+	onosBngControlPackets = prometheus.NewGaugeVec(
 		prometheus.GaugeOpts{
-			Name: "onosPppoedownRxPackets",
-			Help: "onosPppoedownRxPackets",
+			Name: "onosBngControlPackets",
+			Help: "onosBngControlPackets",
 		},
-		[]string{"mac_address", "ip", "session_id", "s_tag", "c_tag", "onu_serial"},
+		[]string{"mac_address", "ip", "session_id", "s_tag", "c_tag", "onu_serial", "type"},
 	)
-	onosPppoeDownTxBytes = prometheus.NewGaugeVec(
+
+	// -------------------- BNG DOWNSTREAM STATISTICS ----------------------------------------
+	onosBngDownTxBytes = prometheus.NewGaugeVec(
 		prometheus.GaugeOpts{
-			Name: "onosPppoedownTxBytes",
-			Help: "onosPppoedownTxBytes",
+			Name: "onosBngDownTxBytes",
+			Help: "onosBngDownTxBytes",
 		},
-		[]string{"mac_address", "ip", "session_id", "s_tag", "c_tag", "onu_serial"},
+		[]string{"mac_address", "ip", "session_id", "s_tag", "c_tag", "onu_serial", "type"},
 	)
-	onosPppoeDownTxPackets = prometheus.NewGaugeVec(
+	onosBngDownTxPackets = prometheus.NewGaugeVec(
 		prometheus.GaugeOpts{
-			Name: "onosPppoedownTxPackets",
-			Help: "onosPppoedownTxPackets",
+			Name: "onosBngDownTxPackets",
+			Help: "onosBngDownTxPackets",
 		},
-		[]string{"mac_address", "ip", "session_id", "s_tag", "c_tag", "onu_serial"},
+		[]string{"mac_address", "ip", "session_id", "s_tag", "c_tag", "onu_serial", "type"},
 	)
+
+	onosBngDownRxBytes = prometheus.NewGaugeVec(
+		prometheus.GaugeOpts{
+			Name: "onosBngDownRxBytes",
+			Help: "onosBngDownRxBytes",
+		},
+		[]string{"mac_address", "ip", "session_id", "s_tag", "c_tag", "onu_serial", "type"},
+	)
+	onosBngDownRxPackets = prometheus.NewGaugeVec(
+		prometheus.GaugeOpts{
+			Name: "onosBngDownRxPackets",
+			Help: "onosBngDownRxPackets",
+		},
+		[]string{"mac_address", "ip", "session_id", "s_tag", "c_tag", "onu_serial", "type"},
+	)
+
+	onosBngDownDropBytes = prometheus.NewGaugeVec(
+		prometheus.GaugeOpts{
+			Name: "onosBngDownDropBytes",
+			Help: "onosBngDownDropBytes",
+		},
+		[]string{"mac_address", "ip", "session_id", "s_tag", "c_tag", "onu_serial", "type"},
+	)
+	onosBngDownDropPackets = prometheus.NewGaugeVec(
+		prometheus.GaugeOpts{
+			Name: "onosBngDownDropPackets",
+			Help: "onosBngDownDropPackets",
+		},
+		[]string{"mac_address", "ip", "session_id", "s_tag", "c_tag", "onu_serial", "type"},
+	)
+
+
 	deviceLaserBiasCurrent = prometheus.NewGauge(
 		prometheus.GaugeOpts{
-	                Name: "device_laser_bias_current",
+			Name: "device_laser_bias_current",
 			Help: "Device Laser Bias Current",
 		})
 	deviceTemperature = prometheus.NewGauge(
@@ -303,7 +342,7 @@
 		prometheus.GaugeOpts{
 			Name: "device_voltage",
 			Help: "Device Voltage",
-	})
+		})
 	onosaaaRxEapolLogoff = prometheus.NewGauge(
 		prometheus.GaugeOpts{
 			Name: "onosaaa_rx_eapol_Logoff",
@@ -338,7 +377,7 @@
 		prometheus.GaugeOpts{
 			Name: "onosaaa_tx_Resp_not_Nak",
 			Help: "Number of transitions to response (received response other that NAK)",
-                })
+		})
 	onosaaaEapolFramesTx = prometheus.NewGauge(
 		prometheus.GaugeOpts{
 			Name: "onosaaa_eapol_frames_tx",
@@ -735,90 +774,164 @@
 	onosaaaRxResIdEapFrames.Set(kpi.RxResIdEapFrames)
 }
 
-func exportOnosPppoeKPI(kpi OnosPppoeKPI) {
-	for _, s := range kpi.Subscribers {
+func exportOnosBngKPI(kpi OnosBngKPI) {
+	logger.WithFields(log.Fields{
+		"Mac":             kpi.Mac,
+		"Ip":              kpi.Ip,
+		"PppoeSessionId":  strconv.Itoa(kpi.PppoeSessionId),
+		"AttachmentType":  kpi.AttachmentType,
+		"STag":            strconv.Itoa(kpi.STag),
+		"CTag":            strconv.Itoa(kpi.CTag),
+		"onuSerialNumber": kpi.OnuSerialNumber,
+	}).Trace("Received OnosBngKPI message")
 
-		logger.WithFields(log.Fields{
-			"Mac":        s.Mac,
-			"Ip":         s.Ip,
-			"SessionId":  strconv.Itoa(s.SessionId),
-			"STag":       strconv.Itoa(s.STag),
-			"CTag":       strconv.Itoa(s.CTag),
-			"onuSerialNumber": s.SerialNumber,
-		}).Trace("Received OnosPppoeKPI message")
+    if kpi.UpTxBytes != nil {
+		onosBngUpTxBytes.WithLabelValues(
+			kpi.Mac,
+			kpi.Ip,
+			strconv.Itoa(kpi.PppoeSessionId),
+			strconv.Itoa(kpi.STag),
+			strconv.Itoa(kpi.CTag),
+			kpi.OnuSerialNumber,
+			kpi.AttachmentType,
+		).Set(*kpi.UpTxBytes)
+	}
+	if kpi.UpTxPackets != nil {
+		onosBngUpTxPackets.WithLabelValues(
+			kpi.Mac,
+			kpi.Ip,
+			strconv.Itoa(kpi.PppoeSessionId),
+			strconv.Itoa(kpi.STag),
+			strconv.Itoa(kpi.CTag),
+			kpi.OnuSerialNumber,
+			kpi.AttachmentType,
+		).Set(*kpi.UpTxPackets)
+	}
+	if kpi.UpRxBytes != nil {
+		onosBngUpRxBytes.WithLabelValues(
+			kpi.Mac,
+			kpi.Ip,
+			strconv.Itoa(kpi.PppoeSessionId),
+			strconv.Itoa(kpi.STag),
+			strconv.Itoa(kpi.CTag),
+			kpi.OnuSerialNumber,
+			kpi.AttachmentType,
+		).Set(*kpi.UpRxBytes)
+	}
+	if kpi.UpRxPackets != nil {
+		onosBngUpRxPackets.WithLabelValues(
+			kpi.Mac,
+			kpi.Ip,
+			strconv.Itoa(kpi.PppoeSessionId),
+			strconv.Itoa(kpi.STag),
+			strconv.Itoa(kpi.CTag),
+			kpi.OnuSerialNumber,
+			kpi.AttachmentType,
+		).Set(*kpi.UpRxPackets)
+	}
 
-		onosPppoeUpTermBytes.WithLabelValues(
-			s.Mac,
-			s.Ip,
-			strconv.Itoa(s.SessionId),
-			strconv.Itoa(s.STag),
-			strconv.Itoa(s.CTag),
-			s.SerialNumber,
-		).Set(s.UpTermBytes)
-		onosPppoeUpTermPackets.WithLabelValues(
-			s.Mac,
-			s.Ip,
-			strconv.Itoa(s.SessionId),
-			strconv.Itoa(s.STag),
-			strconv.Itoa(s.CTag),
-			s.SerialNumber,
-		).Set(s.UpTermPackets)
-		onosPppoeUpDropBytes.WithLabelValues(
-			s.Mac,
-			s.Ip,
-			strconv.Itoa(s.SessionId),
-			strconv.Itoa(s.STag),
-			strconv.Itoa(s.CTag),
-			s.SerialNumber,
-		).Set(s.UpDropBytes)
-		onosPppoeUpDropPackets.WithLabelValues(
-			s.Mac,
-			s.Ip,
-			strconv.Itoa(s.SessionId),
-			strconv.Itoa(s.STag),
-			strconv.Itoa(s.CTag),
-			s.SerialNumber,
-		).Set(s.UpDropPackets)
-		onosPppoeUpControlPackets.WithLabelValues(
-			s.Mac,
-			s.Ip,
-			strconv.Itoa(s.SessionId),
-			strconv.Itoa(s.STag),
-			strconv.Itoa(s.CTag),
-			s.SerialNumber,
-		).Set(s.UpControlPackets)
-		onosPppoeDownRxBytes.WithLabelValues(
-			s.Mac,
-			s.Ip,
-			strconv.Itoa(s.SessionId),
-			strconv.Itoa(s.STag),
-			strconv.Itoa(s.CTag),
-			s.SerialNumber,
-		).Set(s.DownRxBytes)
-		onosPppoeDownRxPackets.WithLabelValues(
-			s.Mac,
-			s.Ip,
-			strconv.Itoa(s.SessionId),
-			strconv.Itoa(s.STag),
-			strconv.Itoa(s.CTag),
-			s.SerialNumber,
-		).Set(s.DownRxPackets)
-		onosPppoeDownTxBytes.WithLabelValues(
-			s.Mac,
-			s.Ip,
-			strconv.Itoa(s.SessionId),
-			strconv.Itoa(s.STag),
-			strconv.Itoa(s.CTag),
-			s.SerialNumber,
-		).Set(s.DownTxBytes)
-		onosPppoeDownTxPackets.WithLabelValues(
-			s.Mac,
-			s.Ip,
-			strconv.Itoa(s.SessionId),
-			strconv.Itoa(s.STag),
-			strconv.Itoa(s.CTag),
-			s.SerialNumber,
-		).Set(s.DownTxPackets)
+	if kpi.UpDropBytes != nil {
+		onosBngUpDropBytes.WithLabelValues(
+			kpi.Mac,
+			kpi.Ip,
+			strconv.Itoa(kpi.PppoeSessionId),
+			strconv.Itoa(kpi.STag),
+			strconv.Itoa(kpi.CTag),
+			kpi.OnuSerialNumber,
+			kpi.AttachmentType,
+		).Set(*kpi.UpDropBytes)
+	}
+	if kpi.UpDropPackets != nil {
+		onosBngUpDropPackets.WithLabelValues(
+			kpi.Mac,
+			kpi.Ip,
+			strconv.Itoa(kpi.PppoeSessionId),
+			strconv.Itoa(kpi.STag),
+			strconv.Itoa(kpi.CTag),
+			kpi.OnuSerialNumber,
+			kpi.AttachmentType,
+		).Set(*kpi.UpDropPackets)
+	}
+
+	if kpi.ControlPackets != nil {
+		onosBngControlPackets.WithLabelValues(
+			kpi.Mac,
+			kpi.Ip,
+			strconv.Itoa(kpi.PppoeSessionId),
+			strconv.Itoa(kpi.STag),
+			strconv.Itoa(kpi.CTag),
+			kpi.OnuSerialNumber,
+			kpi.AttachmentType,
+		).Set(*kpi.ControlPackets)
+	}
+
+	if kpi.DownTxBytes != nil {
+		onosBngDownTxBytes.WithLabelValues(
+			kpi.Mac,
+			kpi.Ip,
+			strconv.Itoa(kpi.PppoeSessionId),
+			strconv.Itoa(kpi.STag),
+			strconv.Itoa(kpi.CTag),
+			kpi.OnuSerialNumber,
+			kpi.AttachmentType,
+		).Set(*kpi.DownTxBytes)
+	}
+	if kpi.DownTxPackets != nil {
+		onosBngDownTxPackets.WithLabelValues(
+			kpi.Mac,
+			kpi.Ip,
+			strconv.Itoa(kpi.PppoeSessionId),
+			strconv.Itoa(kpi.STag),
+			strconv.Itoa(kpi.CTag),
+			kpi.OnuSerialNumber,
+			kpi.AttachmentType,
+		).Set(*kpi.DownTxPackets)
+	}
+
+	if kpi.DownRxBytes != nil {
+		onosBngDownRxBytes.WithLabelValues(
+			kpi.Mac,
+			kpi.Ip,
+			strconv.Itoa(kpi.PppoeSessionId),
+			strconv.Itoa(kpi.STag),
+			strconv.Itoa(kpi.CTag),
+			kpi.OnuSerialNumber,
+			kpi.AttachmentType,
+		).Set(*kpi.DownRxBytes)
+	}
+	if kpi.DownRxPackets != nil {
+		onosBngDownRxPackets.WithLabelValues(
+			kpi.Mac,
+			kpi.Ip,
+			strconv.Itoa(kpi.PppoeSessionId),
+			strconv.Itoa(kpi.STag),
+			strconv.Itoa(kpi.CTag),
+			kpi.OnuSerialNumber,
+			kpi.AttachmentType,
+		).Set(*kpi.DownRxPackets)
+	}
+
+	if kpi.DownDropBytes != nil {
+		onosBngDownDropBytes.WithLabelValues(
+			kpi.Mac,
+			kpi.Ip,
+			strconv.Itoa(kpi.PppoeSessionId),
+			strconv.Itoa(kpi.STag),
+			strconv.Itoa(kpi.CTag),
+			kpi.OnuSerialNumber,
+			kpi.AttachmentType,
+		).Set(*kpi.DownDropBytes)
+	}
+	if kpi.DownDropPackets != nil {
+		onosBngDownDropPackets.WithLabelValues(
+			kpi.Mac,
+			kpi.Ip,
+			strconv.Itoa(kpi.PppoeSessionId),
+			strconv.Itoa(kpi.STag),
+			strconv.Itoa(kpi.CTag),
+			kpi.OnuSerialNumber,
+			kpi.AttachmentType,
+		).Set(*kpi.DownDropPackets)
 	}
 }
 
@@ -874,14 +987,14 @@
 			break
 		}
 		exportOnosAaaKPI(kpi)
-	case "pppoe.stats":
-		kpi := OnosPppoeKPI{}
+	case "bng.stats":
+		kpi := OnosBngKPI{}
 		err := json.Unmarshal(data, &kpi)
 		if err != nil {
-			logger.Error("Invalid msg on pppoe.stats: %s, Unprocessed Msg: %s", err.Error(), string(data))
+			logger.Error("Invalid msg on bng.stats: %s, Unprocessed Msg: %s", err.Error(), string(data))
 			break
 		}
-		exportOnosPppoeKPI(kpi)
+		exportOnosBngKPI(kpi)
 	default:
 		logger.Warn("Unexpected export. Topic [%s] not supported. Should not come here", *topic)
 	}
diff --git a/types.go b/types.go
index 3153b2d..657cf70 100644
--- a/types.go
+++ b/types.go
@@ -112,11 +112,11 @@
 }
 
 type ImporterKPI struct {
-        Timestamp           int64
-        LaserBiasCurrent    float64
-        Temperature         float64
-        TxPower             float64
-        Voltage             float64
+	Timestamp        int64
+	LaserBiasCurrent float64
+	Temperature      float64
+	TxPower          float64
+	Voltage          float64
 }
 
 type OnosAaaKPI struct {
@@ -139,36 +139,40 @@
 	TxStartReq            float64 `json:"eapolStartReqTrans"`
 	EapPktTxAuthChooseEap float64 `json:"eapPktTxauthChooseEap"`
 	TxResponseNotNak      float64 `json:"eapolTransRespNotNak"`
-	EapolFramesTx        float64 `json:"eapolFramesTx"`
-	AuthStateIdle        float64 `json:"authStateIdle"`
-	RequestIdFramesTx    float64 `json:"requestIdFramesTx"`
-	RequestEapFramesTx   float64 `json:"requestEapFramesTx"`
-	InvalidPktType       float64 `json:"invalidPktType"`
-	InvalidBodyLength    float64 `json:"invalidBodyLength"`
-	ValidEapolFramesRx   float64 `json:"validEapolFramesRx"`
-	PendingResSupplicant float64 `json:"pendingResSupplicant"`
-	RxResIdEapFrames     float64 `json:"resIdEapFramesRx"`
+	EapolFramesTx         float64 `json:"eapolFramesTx"`
+	AuthStateIdle         float64 `json:"authStateIdle"`
+	RequestIdFramesTx     float64 `json:"requestIdFramesTx"`
+	RequestEapFramesTx    float64 `json:"requestEapFramesTx"`
+	InvalidPktType        float64 `json:"invalidPktType"`
+	InvalidBodyLength     float64 `json:"invalidBodyLength"`
+	ValidEapolFramesRx    float64 `json:"validEapolFramesRx"`
+	PendingResSupplicant  float64 `json:"pendingResSupplicant"`
+	RxResIdEapFrames      float64 `json:"resIdEapFramesRx"`
 }
 
-type OnosPppoeSubscriberKPI struct {
-	Mac              string `json:"mac"`
-	Ip               string `json:"ip"`
-	SessionId        int `json:"sessionId"`
-	STag             int `json:"sTag"`
-	CTag             int `json:"cTag"`
-	SerialNumber 	 string `json:"serialNumber"`
-	UpTermBytes      float64 `json:"upTermBytes"`
-	UpTermPackets    float64 `json:"upTermPackets"`
-	UpDropBytes      float64 `json:"upDropBytes"`
-	UpDropPackets    float64 `json:"upDropPackets"`
-	DownRxBytes      float64 `json:"downRxBytes"`
-	DownRxPackets    float64 `json:"downRxPackets"`
-	DownTxBytes      float64 `json:"downTxBytes"`
-	DownTxPackets    float64 `json:"downTxPackets"`
-	UpControlPackets float64 `json:"upControlPackets"`
-}
 
-type OnosPppoeKPI struct {
-	Subscribers []OnosPppoeSubscriberKPI `json:"subscribers"`
-	Timestamp   string                   `json:"timestamp"`
+type OnosBngKPI struct {
+	Mac             string  `json:"macAddress"`
+	Ip              string  `json:"ipAddress"`
+	PppoeSessionId  int     `json:"pppoeSessionId"`
+	AttachmentType  string  `json:"attachmentType"`
+	STag            int     `json:"sTag"`
+	CTag            int     `json:"cTag"`
+	OnuSerialNumber string  `json:"onuSerialNumber"`
+	DeviceId        string   `json:"deviceId"`
+	PortNumber      string   `json:"portNumber"`
+	UpTxBytes       *float64 `json:"upTxBytes,omitempty"`
+	UpTxPackets     *float64 `json:"upTxPackets,omitempty"`
+	UpRxBytes       *float64 `json:"upRxBytes,omitempty"`
+	UpRxPackets     *float64 `json:"upRxPackets,omitempty"`
+	UpDropBytes     *float64 `json:"upDropBytes,omitempty"`
+	UpDropPackets   *float64 `json:"upDropPackets,omitempty"`
+	DownRxBytes     *float64 `json:"downRxBytes,omitempty"`
+	DownRxPackets   *float64 `json:"downRxPackets,omitempty"`
+	DownTxBytes     *float64 `json:"downTxBytes,omitempty"`
+	DownTxPackets   *float64 `json:"downTxPackets,omitempty"`
+	DownDropBytes   *float64 `json:"downDropBytes,omitempty"`
+	DownDropPackets *float64 `json:"downDropPackets,omitempty"`
+	ControlPackets  *float64 `json:"controlPackets,omitempty"`
+	Timestamp       string  `json:"timestamp"`
 }