Commit a2e8f826 authored by Simon Pastor's avatar Simon Pastor
Browse files

l2meas endpoint

parent fde46d69
Loading
Loading
Loading
Loading
+169 −41
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@ import (

const rnisBasePath = "/rni/v2/"
const rnisKey string = "rnis:"
const msKey string = "metric-store:network:"
const logModuleRNIS string = "meep-rnis"

//const module string = "rnis"
@@ -84,6 +85,7 @@ var hostUrl *url.URL
var sandboxName string
var basePath string
var baseKey string
var msBaseKey string
var mutex sync.Mutex

var expiryTicker *time.Ticker
@@ -107,6 +109,7 @@ type RabInfoData struct {
}

type L2MeasData struct {
	queryAppInsId      string
	queryCellIds       []string
	queryIpv4Addresses []string
	l2Meas             *L2Meas
@@ -133,6 +136,14 @@ type InRangePoa struct {
	Rsrq int32  `json:"rsrq"`
}

type SumAppInfo 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"`
@@ -198,7 +209,9 @@ func Init() (err error) {
	basePath = "/" + sandboxName + rnisBasePath

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

	// Connect to Redis DB (RNIS_DB)
	rc[RNIS_DB_CONNECTOR_INDEX], err = redis.NewConnector(redisAddr, RNIS_DB)
@@ -2556,6 +2569,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"]

@@ -2620,7 +2634,7 @@ func layer2MeasInfoGet(w http.ResponseWriter, r *http.Request) {
}

func populateL2MeasPOA(key string, jsonInfo string, l2MeasData interface{}) error {
	// Get query params & userlist from user data
	// et query params & userlist from user data
	data := l2MeasData.(*L2MeasData)
	if data == nil || data.l2Meas == nil {
		return errors.New("l2Meas not found in l2MeasData")
@@ -2730,15 +2744,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 {
@@ -2754,6 +2769,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
@@ -2782,16 +2798,128 @@ func populateL2Meas(key string, jsonInfo string, l2MeasData interface{}) error {
		cellIndex = len(data.l2Meas.CellInfo) - 1
	}

	jsonPoaData, _ := rc[RNIS_DB_CONNECTOR_INDEX].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 := SumAppInfo{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
		}
		keyName := msBaseKey + "*" + appName
		appStats := SumAppInfo{appName, 0, 0, 0, 0}

		err = rc[DATA_DB_CONNECTOR_INDEX].ForEachEntry(keyName, calculateSum, &appStats)
		if err != nil {
			log.Error(err.Error())
			return err
		}
		ueStats.DlTraffic += appStats.DlTraffic
		ueStats.DlTrafficLoss += appStats.DlTrafficLoss

		ueStats.UlTraffic += appStats.UlTraffic
		ueStats.UlTrafficLoss += appStats.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++

	//update cellInfo pdr
	data.l2Meas.CellInfo[cellIndex].DlNongbrPdrCell = poaPacketLoss
	data.l2Meas.CellInfo[cellIndex].UlNongbrPdrCell = poaPacketLoss

	//update ueInfo delay
	//delay is the latency between air interface (POA<->UE)
	//parentPoaName = ueData.ParentPoaName
	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 calculateSum(key string, fields map[string]string, appStats interface{}) error {
	// Get query params & userlist from user data
	data := appStats.(*SumAppInfo)
	if data == nil {
		return errors.New("Uninitialised object")
	}

	//downlink direction
	tput, _ := strconv.ParseFloat(fields["dl"], 32)
	data.DlTraffic += int32(1000000 * tput)

	ploss, _ := strconv.ParseFloat(fields["dlos"], 32)
	//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)

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

	//uplink direction
	tput, _ = strconv.ParseFloat(fields["ul"], 32)
	data.UlTraffic += int32(1000000 * tput)

	ploss, _ = strconv.ParseFloat(fields["ulos"], 32)
	//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)

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

	return nil
}
+17 −29
Original line number Diff line number Diff line
@@ -2181,18 +2181,15 @@ func TestSbi(t *testing.T) {
	var expectedUeDataStr [2]string
	var expectedUeData [2]UeData

	expectedUeData[INITIAL] = UeData{ueName, 1, &Ecgi{"2345678", &Plmn{"123", "456"}}, &NRcgi{"", &Plmn{"123", "456"}}, 80, "", nil, nil, 0, 1000, 1000, 0}
	expectedUeData[UPDATED] = UeData{ueName, -1, &Ecgi{"", &Plmn{"123", "456"}}, &NRcgi{"", &Plmn{"123", "456"}}, 80, "", nil, nil, 0, 1000, 1000, 0}
	expectedAppNames := []string{"ue1-iperf"}
	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 expectedAppEcgiStr [2]string
	var expectedAppEcgi [2]Ecgi
	expectedAppEcgi[INITIAL] = Ecgi{"", &Plmn{"123", "456"}, 0, 1000, 1000, 0}
	expectedAppEcgi[UPDATED] = Ecgi{"", &Plmn{"123", "456"}, 0, 1000, 1000, 0}
	var expectedAppInfoStr string
	expectedAppInfo := AppInfo{"EDGE", "zone1-edge1", 0, 1000, 1000, 0}

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

	j, err := json.Marshal(expectedUeData[INITIAL])
	if err != nil {
@@ -2227,37 +2224,28 @@ func TestSbi(t *testing.T) {

	time.Sleep(1000 * time.Millisecond)

	jsonEcgiInfo, _ := rc[RNIS_DB_CONNECTOR_INDEX].JSONGetEntry(baseKey+"UE:"+ueName, ".")
	if string(jsonEcgiInfo) != expectedUeDataStr[INITIAL] {
	jsonInfo, _ := rc[RNIS_DB_CONNECTOR_INDEX].JSONGetEntry(baseKey+"UE:"+ueName, ".")
	if string(jsonInfo) != expectedUeDataStr[INITIAL] {
		t.Fatalf("Failed to get expected response")
	}

	jsonEcgiInfo, _ = rc[RNIS_DB_CONNECTOR_INDEX].JSONGetEntry(baseKey+"APP:"+appName, ".")
	if string(jsonEcgiInfo) != expectedAppEcgiStr[INITIAL] {
	jsonInfo, _ = rc[RNIS_DB_CONNECTOR_INDEX].JSONGetEntry(baseKey+"APP:"+appName, ".")
	if string(jsonInfo) != expectedAppInfoStr {
		t.Fatalf("Failed to get expected response")
	}

	jsonPoaInfo, _ := rc[RNIS_DB_CONNECTOR_INDEX].JSONGetEntry(baseKey+"POA:"+poaName, ".")
	if string(jsonPoaInfo) != expectedPoaInfoStr[INITIAL] {
	jsonInfo, _ = rc[RNIS_DB_CONNECTOR_INDEX].JSONGetEntry(baseKey+"POA:"+poaName, ".")
	if string(jsonInfo) != expectedPoaInfoStr {
		log.Info("SIMON  ", string(jsonInfo))
		log.Info("SIMON2 ", expectedPoaInfoStr)
		t.Fatalf("Failed to get expected response")
	}

	updateScenario("mobility1")
	time.Sleep(1000 * time.Millisecond)

	jsonEcgiInfo, _ = rc[RNIS_DB_CONNECTOR_INDEX].JSONGetEntry(baseKey+"UE:"+ueName, ".")
	if string(jsonEcgiInfo) != expectedUeDataStr[UPDATED] {
		fmt.Println("TEST FAILED but commented out, TODO")
		//t.Fatalf("Failed to get expected response")
	}

	jsonEcgiInfo, _ = rc[RNIS_DB_CONNECTOR_INDEX].JSONGetEntry(baseKey+"APP:"+appName, ".")
	if string(jsonEcgiInfo) != expectedAppEcgiStr[UPDATED] {
		t.Fatalf("Failed to get expected response")
	}

	jsonPoaInfo, _ = rc[RNIS_DB_CONNECTOR_INDEX].JSONGetEntry(baseKey+"POA:"+poaName, ".")
	if string(jsonPoaInfo) != expectedPoaInfoStr[UPDATED] {
	jsonInfo, _ = rc[RNIS_DB_CONNECTOR_INDEX].JSONGetEntry(baseKey+"UE:"+ueName, ".")
	if string(jsonInfo) != expectedUeDataStr[UPDATED] {
		t.Fatalf("Failed to get expected response")
	}

+21 −21

File changed.

Contains only whitespace changes.