Unverified Commit 1fad54c9 authored by Kevin Di Lallo's avatar Kevin Di Lallo Committed by GitHub
Browse files

Merge pull request #200 from pastorsx/sp_dev_l2meas_netchar

L2Meas endpoint implementation
parents 714677f3 7a4bee2d
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -18,10 +18,12 @@ require (
	github.com/gorilla/handlers v1.5.1
	github.com/gorilla/mux v1.7.4
	github.com/lkysow/go-gitlab v0.7.1
	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
	github.com/prometheus/client_golang v1.9.0
	github.com/roymx/viper v1.3.3-0.20190416163942-b9a223fc58a3
	golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43
	google.golang.org/protobuf v1.25.0 // indirect
	gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
)

replace (
+126 −12
Original line number Diff line number Diff line
@@ -28,13 +28,49 @@ import (

const moduleName string = "meep-rnis-sbi"

type UeDataSbi struct {
	Name         string
	Mnc          string
	Mcc          string
	CellId       string
	NrCellId     string
	ErabIdValid  bool
	AppNames     []string
	Latency      int32
	ThroughputUL int32
	ThroughputDL int32
	PacketLoss   float64
}

type PoaInfoSbi struct {
	Name         string
	PoaType      string
	Mnc          string
	Mcc          string
	CellId       string
	Latency      int32
	ThroughputUL int32
	ThroughputDL int32
	PacketLoss   float64
}

type AppInfoSbi struct {
	Name         string
	ParentType   string
	ParentName   string
	Latency      int32
	ThroughputUL int32
	ThroughputDL int32
	PacketLoss   float64
}

type SbiCfg struct {
	SandboxName    string
	RedisAddr      string
	UeDataCb       func(string, string, string, string, string, bool, []string)
	UeDataCb       func(UeDataSbi)
	MeasInfoCb     func(string, string, []string, []int32, []int32)
	PoaInfoCb      func(string, string, string, string, string)
	AppInfoCb      func(string, string, string)
	PoaInfoCb      func(PoaInfoSbi)
	AppInfoCb      func(AppInfoSbi)
	DomainDataCb   func(string, string, string, string)
	ScenarioNameCb func(string)
	CleanUpCb      func()
@@ -47,10 +83,10 @@ type RnisSbi struct {
	activeModel          *mod.Model
	gisCache             *gc.GisCache
	refreshTicker        *time.Ticker
	updateUeDataCB       func(string, string, string, string, string, bool, []string)
	updateUeDataCB       func(UeDataSbi)
	updateMeasInfoCB     func(string, string, []string, []int32, []int32)
	updatePoaInfoCB      func(string, string, string, string, string)
	updateAppInfoCB      func(string, string, string)
	updatePoaInfoCB      func(PoaInfoSbi)
	updateAppInfoCB      func(AppInfoSbi)
	updateDomainDataCB   func(string, string, string, string)
	updateScenarioNameCB func(string)
	cleanUpCB            func()
@@ -269,14 +305,41 @@ func processActiveScenarioUpdate() {
						cellId = ""
					}

					node := sbi.activeModel.GetNodeChild(name)
					node := sbi.activeModel.GetNode(name)
					ue := node.(*dataModel.PhysicalLocation)

					node = sbi.activeModel.GetNodeChild(name)
					apps := node.(*[]dataModel.Process)

					var appNames []string
					for _, process := range *apps {
						appNames = append(appNames, process.Name)
					}
					sbi.updateUeDataCB(name, mnc, mcc, cellId, nrcellId, erabIdValid, appNames)
					latency := int32(0)
					ploss := float64(0.0)
					throughputDL := int32(0)
					throughputUL := int32(0)
					if ue.NetChar != nil {
						latency = ue.NetChar.Latency
						ploss = ue.NetChar.PacketLoss
						throughputDL = ue.NetChar.ThroughputDl
						throughputUL = ue.NetChar.ThroughputUl
					}

					var ueDataSbi = UeDataSbi{
						Name:         name,
						Mnc:          mnc,
						Mcc:          mcc,
						CellId:       cellId,
						NrCellId:     nrcellId,
						ErabIdValid:  erabIdValid,
						AppNames:     appNames,
						Latency:      latency,
						ThroughputUL: throughputUL,
						ThroughputDL: throughputDL,
						PacketLoss:   ploss,
					}
					sbi.updateUeDataCB(ueDataSbi)
				}
			}
		}
@@ -292,7 +355,12 @@ func processActiveScenarioUpdate() {
			}
		}
		if !found {
			sbi.updateUeDataCB(prevUeName, "", "", "", "", false, nil)
			var ueDataSbi = UeDataSbi{
				Name:        prevUeName,
				ErabIdValid: false,
			}

			sbi.updateUeDataCB(ueDataSbi)
			log.Info("Ue removed : ", prevUeName)
		}
	}
@@ -313,7 +381,27 @@ func processActiveScenarioUpdate() {
				continue
			}
			appNames = append(appNames, appName)
			sbi.updateAppInfoCB(appName, pl.Type_, pl.Name)
			latency := int32(0)
			ploss := float64(0.0)
			throughputDL := int32(0)
			throughputUL := int32(0)
			if pl.NetChar != nil {
				latency = pl.NetChar.Latency
				ploss = pl.NetChar.PacketLoss
				throughputDL = pl.NetChar.ThroughputDl
				throughputUL = pl.NetChar.ThroughputUl
			}

			var appInfoSbi = AppInfoSbi{
				Name:         appName,
				ParentType:   pl.Type_,
				ParentName:   pl.Name,
				Latency:      latency,
				ThroughputUL: throughputUL,
				ThroughputDL: throughputDL,
				PacketLoss:   ploss,
			}
			sbi.updateAppInfoCB(appInfoSbi)
		}
	}

@@ -327,7 +415,11 @@ func processActiveScenarioUpdate() {
			}
		}
		if !found {
			sbi.updateAppInfoCB(prevApp, "", "")
			var appInfoSbi = AppInfoSbi{
				Name: prevApp,
			}

			sbi.updateAppInfoCB(appInfoSbi)
			log.Info("App removed : ", prevApp)
		}
	}
@@ -362,7 +454,29 @@ func processActiveScenarioUpdate() {
					cellId = nl.Poa5GConfig.CellId
				}

				sbi.updatePoaInfoCB(name, nl.Type_, mnc, mcc, cellId)
				latency := int32(0)
				ploss := float64(0.0)
				throughputDL := int32(0)
				throughputUL := int32(0)
				if nl.NetChar != nil {
					latency = nl.NetChar.Latency
					ploss = nl.NetChar.PacketLoss
					throughputDL = nl.NetChar.ThroughputDl
					throughputUL = nl.NetChar.ThroughputUl
				}

				var poaInfoSbi = PoaInfoSbi{
					Name:         name,
					PoaType:      nl.Type_,
					Mnc:          mnc,
					Mcc:          mcc,
					CellId:       cellId,
					Latency:      latency,
					ThroughputUL: throughputUL,
					ThroughputDL: throughputDL,
					PacketLoss:   ploss,
				}
				sbi.updatePoaInfoCB(poaInfoSbi)
			}
		}
	}
+223 −45
Original line number Diff line number Diff line
@@ -34,7 +34,9 @@ import (
	dkm "github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-data-key-mgr"
	httpLog "github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-http-logger"
	log "github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-logger"
	ms "github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-metric-store"
	redis "github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-redis"

	"github.com/gorilla/mux"
)

@@ -42,7 +44,8 @@ const rnisBasePath = "/rni/v2/"
const rnisKey string = "rnis:"
const logModuleRNIS string = "meep-rnis"

//const module string = "rnis"
var metricStore *ms.MetricStore

var redisAddr string = "meep-redis-master.default.svc.cluster.local:6379"
var influxAddr string = "http://meep-influxdb.default.svc.cluster.local:8086"

@@ -104,6 +107,7 @@ type RabInfoData struct {
}

type L2MeasData struct {
	queryAppInsId      string
	queryCellIds       []string
	queryIpv4Addresses []string
	l2Meas             *L2Meas
@@ -118,6 +122,10 @@ type UeData struct {
	ParentPoaName string       `json:"parentPoaName"`
	InRangePoas   []InRangePoa `json:"inRangePoas"`
	AppNames      []string     `json:"appNames"`
	Latency       int32        `json:"latency"`
	ThroughputUL  int32        `json:"throughputUL"`
	ThroughputDL  int32        `json:"throughputDL"`
	PacketLoss    float64      `json:"packetLoss"`
}

type InRangePoa struct {
@@ -126,15 +134,31 @@ type InRangePoa struct {
	Rsrq int32  `json:"rsrq"`
}

type AppStats struct {
	AppName       string `json:"name"`
	UlTraffic     int32  `json:"ul"`
	DlTraffic     int32  `json:"dl"`
	UlTrafficLoss int32  `json:"ulos"`
	DlTrafficLoss int32  `json:"dlos"`
}

type PoaInfo struct {
	Type         string  `json:"type"`
	Ecgi         Ecgi    `json:"ecgi"`
	Nrcgi        NRcgi   `json:"nrcgi"`
	Latency      int32   `json:"latency"`
	ThroughputUL int32   `json:"throughputUL"`
	ThroughputDL int32   `json:"throughputDL"`
	PacketLoss   float64 `json:"packetLoss"`
}

type AppInfo struct {
	ParentType   string  `json:"parentType"`
	ParentName   string  `json:"parentName"`
	Latency      int32   `json:"latency"`
	ThroughputUL int32   `json:"throughputUL"`
	ThroughputDL int32   `json:"throughputDL"`
	PacketLoss   float64 `json:"packetLoss"`
}

type DomainData struct {
@@ -183,12 +207,13 @@ func Init() (err error) {
	basePath = "/" + sandboxName + rnisBasePath

	// Get base store key
	baseKey = dkm.GetKeyRoot(sandboxName) + rnisKey
	sandboxNameRoot := dkm.GetKeyRoot(sandboxName)
	baseKey = sandboxNameRoot + rnisKey

	// Connect to Redis DB
	// Connect to Redis DB (RNIS_DB)
	rc, err = redis.NewConnector(redisAddr, RNIS_DB)
	if err != nil {
		log.Error("Failed connection to Redis DB. Error: ", err)
		log.Error("Failed connection to Redis DB (RNIS_DB). Error: ", err)
		return err
	}
	_ = rc.DBFlush(baseKey)
@@ -264,25 +289,29 @@ func Stop() (err error) {
	return sbi.Stop()
}

func updateUeData(name string, mnc string, mcc string, cellId string, nrcellId string, erabIdValid bool, appNames []string) {
func updateUeData(obj sbi.UeDataSbi) {

	var plmn Plmn
	var newEcgi Ecgi
	plmn.Mnc = mnc
	plmn.Mcc = mcc
	newEcgi.CellId = cellId
	plmn.Mnc = obj.Mnc
	plmn.Mcc = obj.Mcc
	newEcgi.CellId = obj.CellId
	newEcgi.Plmn = &plmn

	var newNrcgi NRcgi
	newNrcgi.NrcellId = nrcellId
	newNrcgi.NrcellId = obj.NrCellId
	newNrcgi.Plmn = &plmn

	var ueData UeData
	ueData.Ecgi = &newEcgi
	ueData.Nrcgi = &newNrcgi
	ueData.Name = name
	ueData.Name = obj.Name
	ueData.Qci = defaultSupportedQci //only supporting one value
	ueData.AppNames = appNames
	ueData.AppNames = obj.AppNames
	ueData.Latency = obj.Latency
	ueData.ThroughputUL = obj.ThroughputUL
	ueData.ThroughputDL = obj.ThroughputDL
	ueData.PacketLoss = obj.PacketLoss

	oldPlmn := new(Plmn)
	oldPlmnMnc := ""
@@ -294,7 +323,7 @@ func updateUeData(name string, mnc string, mcc string, cellId string, nrcellId s
	oldNrCellId := ""

	//get from DB
	jsonUeData, _ := rc.JSONGetEntry(baseKey+"UE:"+name, ".")
	jsonUeData, _ := rc.JSONGetEntry(baseKey+"UE:"+obj.Name, ".")

	if jsonUeData != "" {
		ueDataObj := convertJsonToUeData(jsonUeData)
@@ -319,7 +348,7 @@ func updateUeData(name string, mnc string, mcc string, cellId string, nrcellId s

		//allocating a new erabId if entering a 4G environment (using existence of an erabId)
		if oldErabId == -1 { //if no erabId established (== -1), means not coming from a 4G environment
			if erabIdValid { //if a new erabId should be allocated (meaning entering into a 4G environment)
			if obj.ErabIdValid { //if a new erabId should be allocated (meaning entering into a 4G environment)
				//rab establishment case
				ueData.ErabId = int32(nextAvailableErabId)
				nextAvailableErabId++
@@ -327,7 +356,7 @@ func updateUeData(name string, mnc string, mcc string, cellId string, nrcellId s
				ueData.ErabId = oldErabId // = -1
			}
		} else {
			if erabIdValid { //was connected to a 4G POA and still is, so, no change
			if obj.ErabIdValid { //was connected to a 4G POA and still is, so, no change
				ueData.ErabId = oldErabId // = sameAsBefore
			} else { //was connected to a 4G POA, but now not connected to one, so need to release the 4G connection
				//rab release case
@@ -335,16 +364,16 @@ func updateUeData(name string, mnc string, mcc string, cellId string, nrcellId s
			}
		}

		_ = rc.JSONSetEntry(baseKey+"UE:"+name, ".", convertUeDataToJson(&ueData))
		_ = rc.JSONSetEntry(baseKey+"UE:"+obj.Name, ".", convertUeDataToJson(&ueData))
		assocId := new(AssociateId)
		assocId.Type_ = 1 //UE_IPV4_ADDRESS
		assocId.Value = name
		assocId.Value = obj.Name

		//log to model for all apps on that UE
		checkCcNotificationRegisteredSubscriptions("", assocId, &plmn, oldPlmn, "", cellId, oldCellId)
		checkCcNotificationRegisteredSubscriptions("", assocId, &plmn, oldPlmn, "", obj.CellId, oldCellId)
		//ueData contains newErabId
		if oldErabId == -1 && ueData.ErabId != -1 {
			checkReNotificationRegisteredSubscriptions("", assocId, &plmn, oldPlmn, -1, cellId, oldCellId, ueData.ErabId)
			checkReNotificationRegisteredSubscriptions("", assocId, &plmn, oldPlmn, -1, obj.CellId, oldCellId, ueData.ErabId)
		}
		if oldErabId != -1 && ueData.ErabId == -1 { //sending oldErabId to release and no new 4G cellId
			checkRrNotificationRegisteredSubscriptions("", assocId, &plmn, oldPlmn, -1, "", oldCellId, oldErabId)
@@ -353,7 +382,7 @@ func updateUeData(name string, mnc string, mcc string, cellId string, nrcellId s
		//5G section
		if newNrcgi.Plmn.Mnc != oldNrPlmnMnc || newNrcgi.Plmn.Mcc != oldNrPlmnMcc || newNrcgi.NrcellId != oldNrCellId {
			//update because nrcgi changed
			_ = rc.JSONSetEntry(baseKey+"UE:"+name, ".", convertUeDataToJson(&ueData))
			_ = rc.JSONSetEntry(baseKey+"UE:"+obj.Name, ".", convertUeDataToJson(&ueData))
		}
	}
}
@@ -381,24 +410,28 @@ func updateMeasInfo(name string, parentPoaName string, inRangePoaNames []string,
	}
}

func updatePoaInfo(name string, poaType string, mnc string, mcc string, cellId string) {
func updatePoaInfo(obj sbi.PoaInfoSbi) {

	var plmn Plmn
	plmn.Mnc = mnc
	plmn.Mcc = mcc
	plmn.Mnc = obj.Mnc
	plmn.Mcc = obj.Mcc

	var poaInfo PoaInfo
	poaInfo.Type = poaType
	poaInfo.Type = obj.PoaType
	poaInfo.Latency = obj.Latency
	poaInfo.ThroughputUL = obj.ThroughputUL
	poaInfo.ThroughputDL = obj.ThroughputDL
	poaInfo.PacketLoss = obj.PacketLoss

	switch poaType {
	switch obj.PoaType {
	case poaType4G:
		var ecgi Ecgi
		ecgi.CellId = cellId
		ecgi.CellId = obj.CellId
		ecgi.Plmn = &plmn
		poaInfo.Ecgi = ecgi
	case poaType5G:
		var nrcgi NRcgi
		nrcgi.NrcellId = cellId
		nrcgi.NrcellId = obj.CellId
		nrcgi.Plmn = &plmn
		poaInfo.Nrcgi = nrcgi
	default:
@@ -406,20 +439,20 @@ func updatePoaInfo(name string, poaType string, mnc string, mcc string, cellId s
	}

	//updateDB
	_ = rc.JSONSetEntry(baseKey+"POA:"+name, ".", convertPoaInfoToJson(&poaInfo))
	_ = rc.JSONSetEntry(baseKey+"POA:"+obj.Name, ".", convertPoaInfoToJson(&poaInfo))
}

func updateAppInfo(name string, parentType string, parentName string) {
func updateAppInfo(obj sbi.AppInfoSbi) {

	//get from DB
	jsonAppInfo, _ := rc.JSONGetEntry(baseKey+"APP:"+name+"*", ".")
	jsonAppInfo, _ := rc.JSONGetEntry(baseKey+"APP:"+obj.Name+"*", ".")

	if jsonAppInfo != "" {
		//delete entry if parent name is different; means it moved
		currentAppInfo := convertJsonToAppInfo(jsonAppInfo)
		if currentAppInfo.ParentName != parentName {
		if currentAppInfo.ParentName != obj.ParentName {
			if currentAppInfo.ParentType == plTypeUE {
				_ = rc.JSONDelEntry(baseKey+"APP:"+name+":"+currentAppInfo.ParentName, ".")
				_ = rc.JSONDelEntry(baseKey+"APP:"+obj.Name+":"+currentAppInfo.ParentName, ".")
			}
		} else {
			//no changes.. just get out
@@ -429,12 +462,17 @@ func updateAppInfo(name string, parentType string, parentName string) {

	//updateDB
	var appInfo AppInfo
	appInfo.ParentType = parentType
	appInfo.ParentName = parentName
	if parentType == plTypeUE {
		_ = rc.JSONSetEntry(baseKey+"APP:"+name+":"+parentName, ".", convertAppInfoToJson(&appInfo))
	appInfo.ParentType = obj.ParentType
	appInfo.ParentName = obj.ParentName
	appInfo.Latency = obj.Latency
	appInfo.ThroughputUL = obj.ThroughputUL
	appInfo.ThroughputDL = obj.ThroughputDL
	appInfo.PacketLoss = obj.PacketLoss

	if obj.ParentType == plTypeUE {
		_ = rc.JSONSetEntry(baseKey+"APP:"+obj.Name+":"+obj.ParentName, ".", convertAppInfoToJson(&appInfo))
	} else {
		_ = rc.JSONSetEntry(baseKey+"APP:"+name, ".", convertAppInfoToJson(&appInfo))
		_ = rc.JSONSetEntry(baseKey+"APP:"+obj.Name, ".", convertAppInfoToJson(&appInfo))
	}
}

@@ -2520,6 +2558,7 @@ func layer2MeasInfoGet(w http.ResponseWriter, r *http.Request) {
	q := u.Query()
	//meAppName := q.Get("app_ins_id")

	l2MeasData.queryAppInsId = q.Get("app_ins_id")
	l2MeasData.queryCellIds = q["cell_id"]
	l2MeasData.queryIpv4Addresses = q["ue_ipv4_address"]

@@ -2694,15 +2733,16 @@ func populateL2Meas(key string, jsonInfo string, l2MeasData interface{}) error {
	found := false

	//find if cellUeInfo already exists

	var cellUeIndex int
	assocId := new(AssociateId)
	assocId.Type_ = 1 //UE_IPV4_ADDRESS
	subKeys := strings.Split(key, ":")
	assocId.Value = subKeys[len(subKeys)-1]

	for _, currentCellUeInfo := range data.l2Meas.CellUEInfo {
	for index, currentCellUeInfo := range data.l2Meas.CellUEInfo {
		if assocId.Type_ == currentCellUeInfo.AssociateId.Type_ && assocId.Value == currentCellUeInfo.AssociateId.Value {
			found = true
			cellUeIndex = index
		}
	}
	if !found {
@@ -2718,6 +2758,7 @@ func populateL2Meas(key string, jsonInfo string, l2MeasData interface{}) error {
		newCellUeInfo.AssociateId = assocId

		data.l2Meas.CellUEInfo = append(data.l2Meas.CellUEInfo, *newCellUeInfo)
		cellUeIndex = len(data.l2Meas.CellUEInfo) - 1
	}

	//find if cellInfo already exists
@@ -2746,13 +2787,137 @@ func populateL2Meas(key string, jsonInfo string, l2MeasData interface{}) error {
		cellIndex = len(data.l2Meas.CellInfo) - 1
	}

	jsonPoaData, _ := rc.JSONGetEntry(baseKey+"POA:"+ueData.ParentPoaName, ".")

	latency := int32(0)
	poaPacketLoss := int32(0)
	if jsonPoaData != "" {
		poaDataObj := convertJsonToPoaInfo(jsonPoaData)
		if poaDataObj != nil {
			latency = poaDataObj.Latency
			ploss := poaDataObj.PacketLoss
			//return between 10^-4 t 10^-6
			ploss = ploss * 1000000 //10^-6
			if ploss > 100 {
				poaPacketLoss = 100
			} else {
				poaPacketLoss = int32(ploss)
			}
		}
	}

	ueStats := AppStats{data.queryAppInsId, 0, 0, 0, 0}

	//loop through each APP to get throuput
	for _, appName := range ueData.AppNames {

		//we calculate stats for the queried app only or for all if none provided
		if appName != data.queryAppInsId && data.queryAppInsId != "" {
			continue
		}

		metricsArray, err := metricStore.GetCachedNetworkMetrics("*", appName)
		if err != nil {
			log.Error("Failed to get network metric:", err)
		}
		sumAppStats := AppStats{appName, 0, 0, 0, 0}

		for _, metrics := range metricsArray {

			appStats := calculateMetrics(metrics)
			sumAppStats.DlTraffic += appStats.DlTraffic
			sumAppStats.DlTrafficLoss += appStats.DlTrafficLoss

			sumAppStats.UlTraffic += appStats.UlTraffic
			sumAppStats.UlTrafficLoss += appStats.UlTrafficLoss
		}

		ueStats.DlTraffic += sumAppStats.DlTraffic
		ueStats.DlTrafficLoss += sumAppStats.DlTrafficLoss

		ueStats.UlTraffic += sumAppStats.UlTraffic
		ueStats.UlTrafficLoss += sumAppStats.UlTrafficLoss

	}

	//update cellInfo counters
	//need to do a qci mapping... since qci can only be 80 for now, using the one that correlates to that
	data.l2Meas.CellInfo[cellIndex].NumberOfActiveUeDlNongbrCell++
	data.l2Meas.CellInfo[cellIndex].NumberOfActiveUeUlNongbrCell++
	data.l2Meas.CellInfo[cellIndex].DlNongbrPdrCell = poaPacketLoss
	data.l2Meas.CellInfo[cellIndex].UlNongbrPdrCell = poaPacketLoss

	//update ueInfo delay
	//delay is the latency between air interface (POA<->UE)
	data.l2Meas.CellUEInfo[cellUeIndex].DlNongbrDelayUe = latency //latency from the air interface only (POA)
	data.l2Meas.CellUEInfo[cellUeIndex].UlNongbrDelayUe = latency
	data.l2Meas.CellUEInfo[cellUeIndex].DlNongbrDataVolumeUe = ueStats.DlTraffic / 1000 //kbits
	data.l2Meas.CellUEInfo[cellUeIndex].UlNongbrDataVolumeUe = ueStats.UlTraffic / 1000 //kbits
	data.l2Meas.CellUEInfo[cellUeIndex].DlNongbrThroughputUe = ueStats.DlTraffic / 1000 //kbits/s
	data.l2Meas.CellUEInfo[cellUeIndex].UlNongbrThroughputUe = ueStats.UlTraffic / 1000 //kbits/s

	plossFloat := float32(0.0)
	ploss := int32(0)
	if ueStats.DlTraffic != 0 {
		plossFloat = float32((float32(ueStats.DlTrafficLoss) / float32(ueStats.DlTrafficLoss+ueStats.DlTraffic)))
		ploss = int32(1000000 * plossFloat)

		if ploss > 100 {
			ploss = 100
		}
	}
	data.l2Meas.CellUEInfo[cellUeIndex].DlNongbrPdrUe = ploss

	ploss = int32(0)
	if ueStats.UlTraffic != 0 {
		plossFloat = float32((float32(ueStats.UlTrafficLoss) / float32(ueStats.UlTrafficLoss+ueStats.UlTraffic)))
		ploss = int32(1000000 * plossFloat)

		if ploss > 100 {
			ploss = 100
		}
	}

	data.l2Meas.CellUEInfo[cellUeIndex].UlNongbrPdrUe = ploss

	return nil
}

func calculateMetrics(metrics ms.NetworkMetric) (appStats AppStats) {

	//downlink direction
	tput := metrics.DlTput
	appStats.DlTraffic += int32(1000000 * tput)

	ploss := metrics.DlLoss
	//traffic lost because of packet drop
	//details
	//a = float32(ploss/100)
	//b = float32(1.0 - a)
	//c = float32(1000000 * tput)
	//d = float32(a*c/b)
	//e = int32(d)

	appStats.DlTrafficLoss += int32(float32(float32(ploss/100) * float32(1000000*tput) / float32(1.0-float32(ploss/100))))

	//uplink direction
	tput = metrics.UlTput
	appStats.UlTraffic += int32(1000000 * tput)

	ploss = metrics.UlLoss
	//traffic lost because of packet drop
	//details
	//a = float32(ploss/100)
	//b = float32(1.0 - a)
	//c = float32(1000000 * tput)
	//d = float32(a*c/b)
	//e = int32(d)

	appStats.UlTrafficLoss += int32(float32(float32(ploss/100) * float32(1000000*tput) / float32(1.0-float32(ploss/100))))

	return appStats
}

func rabInfoGet(w http.ResponseWriter, r *http.Request) {

	w.Header().Set("Content-Type", "application/json; charset=UTF-8")
@@ -3069,7 +3234,7 @@ func subscriptionLinkListSubscriptionsGet(w http.ResponseWriter, r *http.Request
					break
				}
			}
			if !found {
			if found {
				break
			}
		}
@@ -3115,6 +3280,19 @@ func cleanUp() {
func updateStoreName(storeName string) {
	if currentStoreName != storeName {
		currentStoreName = storeName
		_ = httpLog.ReInit(logModuleRNIS, sandboxName, storeName, redisAddr, influxAddr)

		err := httpLog.ReInit(logModuleRNIS, sandboxName, storeName, redisAddr, influxAddr)
		if err != nil {
			log.Error("Failed to initialise httpLog: ", err)
			return
		}

		// Connect to Metric Store
		metricStore, err = ms.NewMetricStore(storeName, sandboxName, influxAddr, redisAddr)
		if err != nil {
			log.Error("Failed connection to metric-store: ", err)
			return
		}

	}
}
+5 −4
Original line number Diff line number Diff line
@@ -2180,15 +2180,16 @@ func TestSbi(t *testing.T) {
	 ******************************/
	var expectedUeDataStr [2]string
	var expectedUeData [2]UeData

	expectedAppNames := []string{"ue1-iperf"}
	expectedUeData[INITIAL] = UeData{ueName, 1, &Ecgi{"2345678", &Plmn{"123", "456"}}, &NRcgi{"", &Plmn{"123", "456"}}, 80, poaName, nil, expectedAppNames}
	expectedUeData[UPDATED] = UeData{ueName, -1, &Ecgi{"", &Plmn{"123", "456"}}, &NRcgi{"", &Plmn{"123", "456"}}, 80, poaNameAfter, nil, expectedAppNames}
	expectedUeData[INITIAL] = UeData{ueName, 1, &Ecgi{"2345678", &Plmn{"123", "456"}}, &NRcgi{"", &Plmn{"123", "456"}}, 80, poaName, nil, expectedAppNames, 0, 1000, 1000, 0.0}
	expectedUeData[UPDATED] = UeData{ueName, -1, &Ecgi{"", &Plmn{"123", "456"}}, &NRcgi{"", &Plmn{"123", "456"}}, 80, poaNameAfter, nil, expectedAppNames, 0, 1000, 1000, 0.0}

	var expectedAppInfoStr string
	expectedAppInfo := AppInfo{"EDGE", "zone1-edge1"}
	expectedAppInfo := AppInfo{"EDGE", "zone1-edge1", 0, 1000, 1000, 0}

	var expectedPoaInfoStr string
	expectedPoaInfo := PoaInfo{"POA-4G", Ecgi{"2345678", &Plmn{"123", "456"}}, NRcgi{"", nil}}
	expectedPoaInfo := PoaInfo{"POA-4G", Ecgi{"2345678", &Plmn{"123", "456"}}, NRcgi{"", nil}, 1, 1000, 1000, 0}

	j, err := json.Marshal(expectedUeData[INITIAL])
	if err != nil {
+33 −0
Original line number Diff line number Diff line
@@ -79,6 +79,38 @@ func (ms *MetricStore) SetCachedNetworkMetric(metric NetworkMetric) (err error)
	return nil
}

// GetCachedNetworkMetrics
func (ms *MetricStore) GetCachedNetworkMetrics(src string, dst string) (metric []NetworkMetric, err error) {
        // Make sure we have set a store
        if ms.name == "" {
                err = errors.New("Store name not specified")
                return
        }

        // Get current Network metric
        tagStr := src + ":" + dst
        var valuesArray []map[string]interface{}
        valuesArray, err = ms.GetRedisMetric(NetMetName, tagStr)
        if err != nil {
                log.Error("Failed to retrieve metrics with error: ", err.Error())
                return
        }

        metricList := make([]NetworkMetric, len(valuesArray))
        for index, values := range valuesArray {
                // Format network metric
                nm, err := ms.formatCachedNetworkMetric(values)
                if err != nil {
                        continue
                }
                // Add metric to list
                metricList[index] = nm
        }

        // Return formatted metric
        return metricList, nil
}

// GetCachedNetworkMetric
func (ms *MetricStore) GetCachedNetworkMetric(src string, dst string) (metric NetworkMetric, err error) {
	// Make sure we have set a store
@@ -95,6 +127,7 @@ func (ms *MetricStore) GetCachedNetworkMetric(src string, dst string) (metric Ne
		log.Error("Failed to retrieve metrics with error: ", err.Error())
		return
	}

	if len(valuesArray) != 1 {
		err = errors.New("Metric list length != 1")
		return
Loading