Commit 9c2eed0d authored by Simon Pastor's avatar Simon Pastor
Browse files

l2meas endpoint basic support

parent 0dd69a83
Loading
Loading
Loading
Loading
+16 −49
Original line number Diff line number Diff line
@@ -31,10 +31,10 @@ const moduleName string = "meep-rnis-sbi"
type SbiCfg struct {
	SandboxName    string
	RedisAddr      string
	UeDataCb       func(string, string, string, string, string, bool)
	UeDataCb       func(string, string, string, string, string, bool, []string)
	MeasInfoCb     func(string, string, []string, []int32, []int32)
	PoaInfoCb      func(string, string, string, string, string)
	AppEcgiInfoCb  func(string, string, string, string)
	AppInfoCb      func(string, string, string)
	DomainDataCb   func(string, string, string, string)
	ScenarioNameCb func(string)
	CleanUpCb      func()
@@ -47,10 +47,10 @@ type RnisSbi struct {
	activeModel          *mod.Model
	gisCache             *gc.GisCache
	refreshTicker        *time.Ticker
	updateUeDataCB       func(string, string, string, string, string, bool)
	updateUeDataCB       func(string, string, string, string, string, bool, []string)
	updateMeasInfoCB     func(string, string, []string, []int32, []int32)
	updatePoaInfoCB      func(string, string, string, string, string)
	updateAppEcgiInfoCB  func(string, string, string, string)
	updateAppInfoCB      func(string, string, string)
	updateDomainDataCB   func(string, string, string, string)
	updateScenarioNameCB func(string)
	cleanUpCB            func()
@@ -70,7 +70,7 @@ func Init(cfg SbiCfg) (err error) {
	sbi.updateUeDataCB = cfg.UeDataCb
	sbi.updateMeasInfoCB = cfg.MeasInfoCb
	sbi.updatePoaInfoCB = cfg.PoaInfoCb
	sbi.updateAppEcgiInfoCB = cfg.AppEcgiInfoCb
	sbi.updateAppInfoCB = cfg.AppInfoCb
	sbi.updateDomainDataCB = cfg.DomainDataCb
	sbi.updateScenarioNameCB = cfg.ScenarioNameCb
	sbi.cleanUpCB = cfg.CleanUpCb
@@ -230,7 +230,6 @@ func processActiveScenarioUpdate() {
			continue
		}
		ueNames = append(ueNames, name)

		ueParent := sbi.activeModel.GetNodeParent(name)
		if poa, ok := ueParent.(*dataModel.NetworkLocation); ok {
			poaParent := sbi.activeModel.GetNodeParent(poa.Name)
@@ -270,7 +269,14 @@ func processActiveScenarioUpdate() {
						cellId = ""
					}

					sbi.updateUeDataCB(name, mnc, mcc, cellId, nrcellId, erabIdValid)
					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)
				}
			}
		}
@@ -286,7 +292,7 @@ func processActiveScenarioUpdate() {
			}
		}
		if !found {
			sbi.updateUeDataCB(prevUeName, "", "", "", "", false)
			sbi.updateUeDataCB(prevUeName, "", "", "", "", false, nil)
			log.Info("Ue removed : ", prevUeName)
		}
	}
@@ -307,46 +313,7 @@ func processActiveScenarioUpdate() {
				continue
			}
			appNames = append(appNames, appName)

			plParent := sbi.activeModel.GetNodeParent(pl.Name)
			if nl, ok := plParent.(*dataModel.NetworkLocation); ok {
				//nl can be either POA for {FOG or UE} or Zone Default for {Edge
				nlParent := sbi.activeModel.GetNodeParent(nl.Name)
				if zone, ok := nlParent.(*dataModel.Zone); ok {
					zoneParent := sbi.activeModel.GetNodeParent(zone.Name)
					if domain, ok := zoneParent.(*dataModel.Domain); ok {
						mnc := ""
						mcc := ""
						cellId := ""
						if domain.CellularDomainConfig != nil {
							mnc = domain.CellularDomainConfig.Mnc
							mcc = domain.CellularDomainConfig.Mcc
							cellId = domain.CellularDomainConfig.DefaultCellId
						}
						switch nl.Type_ {
						case mod.NodeTypePoa4G:
							if nl.Poa4GConfig != nil {
								if nl.Poa4GConfig.CellId != "" {
									cellId = nl.Poa4GConfig.CellId
								}
							}
						/*no support for RNIS on 5G elements anymore
						case mod.NodeTypePoa5G:
							if nl.Poa5GConfig != nil {
								if nl.Poa5GConfig.CellId != "" {
									cellId = nl.Poa5GConfig.CellId
								}
							}
						*/
						default:
							//empty cells for POAs not supporting RNIS
							cellId = ""
						}

						sbi.updateAppEcgiInfoCB(appName, mnc, mcc, cellId)
					}
				}
			}
			sbi.updateAppInfoCB(appName, pl.Type_, pl.Name)
		}
	}

@@ -360,7 +327,7 @@ func processActiveScenarioUpdate() {
			}
		}
		if !found {
			sbi.updateAppEcgiInfoCB(prevApp, "", "", "")
			sbi.updateAppInfoCB(prevApp, "", "")
			log.Info("App removed : ", prevApp)
		}
	}
+3 −3
Original line number Diff line number Diff line
@@ -22,9 +22,9 @@ import (
	log "github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-logger"
)

func convertJsonToEcgi(jsonInfo string) *Ecgi {
func convertJsonToAppInfo(jsonInfo string) *AppInfo {

	var obj Ecgi
	var obj AppInfo
	err := json.Unmarshal([]byte(jsonInfo), &obj)
	if err != nil {
		log.Error(err.Error())
@@ -33,7 +33,7 @@ func convertJsonToEcgi(jsonInfo string) *Ecgi {
	return &obj
}

func convertEcgiToJson(obj *Ecgi) string {
func convertAppInfoToJson(obj *AppInfo) string {

	jsonInfo, err := json.Marshal(*obj)
	if err != nil {
+111 −43
Original line number Diff line number Diff line
@@ -55,6 +55,7 @@ const measRepUeSubscriptionType = "meas_rep_ue"
const nrMeasRepUeSubscriptionType = "nr_meas_rep_ue"
const poaType4G = "POA-4G"
const poaType5G = "POA-5G"
const plTypeUE = "UE"

var ccSubscriptionMap = map[int]*CellChangeSubscription{}
var reSubscriptionMap = map[int]*RabEstSubscription{}
@@ -119,6 +120,7 @@ type UeData struct {
	Qci           int32        `json:"qci"`
	ParentPoaName string       `json:"parentPoaName"`
	InRangePoas   []InRangePoa `json:"inRangePoas"`
	AppNames      []string     `json:"appNames"`
}

type InRangePoa struct {
@@ -133,6 +135,11 @@ type PoaInfo struct {
	Nrcgi NRcgi  `json:"nrcgi"`
}

type AppInfo struct {
	ParentType string `json:"parentType"`
	ParentName string `json:"parentName"`
}

type DomainData struct {
	Mcc    string `json:"mcc"`
	Mnc    string `json:"mnc"`
@@ -227,7 +234,7 @@ func Init() (err error) {
		UeDataCb:       updateUeData,
		MeasInfoCb:     updateMeasInfo,
		PoaInfoCb:      updatePoaInfo,
		AppEcgiInfoCb:  updateAppEcgiInfo,
		AppInfoCb:      updateAppInfo,
		DomainDataCb:   updateDomainData,
		ScenarioNameCb: updateStoreName,
		CleanUpCb:      cleanUp,
@@ -267,7 +274,7 @@ func Stop() (err error) {
	return sbi.Stop()
}

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

	var plmn Plmn
	var newEcgi Ecgi
@@ -285,6 +292,7 @@ func updateUeData(name string, mnc string, mcc string, cellId string, nrcellId s
	ueData.Nrcgi = &newNrcgi
	ueData.Name = name
	ueData.Qci = defaultSupportedQci //only supporting one value
	ueData.AppNames = appNames

	oldPlmn := new(Plmn)
	oldPlmnMnc := ""
@@ -411,35 +419,32 @@ func updatePoaInfo(name string, poaType string, mnc string, mcc string, cellId s
	_ = rc.JSONSetEntry(baseKey+"POA:"+name, ".", convertPoaInfoToJson(&poaInfo))
}

func updateAppEcgiInfo(name string, mnc string, mcc string, cellId string) {

	var plmn Plmn
	var newEcgi Ecgi
	plmn.Mnc = mnc
	plmn.Mcc = mcc
	newEcgi.CellId = cellId
	newEcgi.Plmn = &plmn
func updateAppInfo(name string, parentType string, parentName string) {

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

	oldPlmnMnc := ""
	oldPlmnMcc := ""
	oldCellId := ""

	if jsonAppEcgiInfo != "" {

		ecgiInfo := convertJsonToEcgi(jsonAppEcgiInfo)

		oldPlmnMnc = ecgiInfo.Plmn.Mnc
		oldPlmnMcc = ecgiInfo.Plmn.Mcc
		oldCellId = ecgiInfo.CellId
	if jsonAppInfo != "" {
		//delete entry if parent name is different; means it moved
		currentAppInfo := convertJsonToAppInfo(jsonAppInfo)
		if currentAppInfo.ParentName != parentName {
			if currentAppInfo.ParentType == plTypeUE {
				_ = rc.JSONDelEntry(baseKey+"APP:"+name+":"+currentAppInfo.ParentName, ".")
			}
		} else {
			//no changes.. just get out
			return
		}
	}

	//updateDB if changes occur
	if newEcgi.Plmn.Mnc != oldPlmnMnc || newEcgi.Plmn.Mcc != oldPlmnMcc || newEcgi.CellId != oldCellId {
	//updateDB
		_ = rc.JSONSetEntry(baseKey+"APP:"+name, ".", convertEcgiToJson(&newEcgi))
	var appInfo AppInfo
	appInfo.ParentType = parentType
	appInfo.ParentName = parentName
	if parentType == plTypeUE {
		_ = rc.JSONSetEntry(baseKey+"APP:"+name+":"+parentName, ".", convertAppInfoToJson(&appInfo))
	} else {
		_ = rc.JSONSetEntry(baseKey+"APP:"+name, ".", convertAppInfoToJson(&appInfo))
	}
}

@@ -2521,6 +2526,15 @@ func layer2MeasInfoGet(w http.ResponseWriter, r *http.Request) {
		return
	}

	//loop through each POA
	keyName = baseKey + "POA:*"
	err = rc.ForEachJSONEntry(keyName, populateL2MeasPOA, &l2MeasData)
	if err != nil {
		log.Error(err.Error())
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	l2Meas.TimeStamp = &timeStamp

	// Send response
@@ -2534,6 +2548,66 @@ func layer2MeasInfoGet(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, string(jsonResponse))
}

func populateL2MeasPOA(key string, jsonInfo string, l2MeasData interface{}) error {
	// Get query params & userlist from user data
	data := l2MeasData.(*L2MeasData)
	if data == nil || data.l2Meas == nil {
		return errors.New("l2Meas not found in l2MeasData")
	}

	// Retrieve user info from DB
	var poaData PoaInfo
	err := json.Unmarshal([]byte(jsonInfo), &poaData)
	if err != nil {
		return err
	}

	//only applies for 4G poas
	if poaData.Type != poaType4G {
		return nil
	}

	partOfFilter := true
	for _, cellId := range data.queryCellIds {
		if cellId != "" {
			partOfFilter = false
			if cellId == poaData.Ecgi.CellId {
				partOfFilter = true
				break
			}
		}
	}
	if !partOfFilter {
		return nil
	}

	found := false

	//find if cellInfo already exists
	for _, currentCellInfo := range data.l2Meas.CellInfo {
		if currentCellInfo.Ecgi.Plmn.Mcc == poaData.Ecgi.Plmn.Mcc &&
			currentCellInfo.Ecgi.Plmn.Mnc == poaData.Ecgi.Plmn.Mnc &&
			currentCellInfo.Ecgi.CellId == poaData.Ecgi.CellId {
			//add ue into the existing cellUserInfo
			found = true
		}
	}
	if !found {
		newCellInfo := new(L2MeasCellInfo)
		newEcgi := new(Ecgi)
		newPlmn := new(Plmn)
		newPlmn.Mcc = poaData.Ecgi.Plmn.Mcc
		newPlmn.Mnc = poaData.Ecgi.Plmn.Mnc
		newEcgi.Plmn = newPlmn
		newEcgi.CellId = poaData.Ecgi.CellId
		newCellInfo.Ecgi = newEcgi

		data.l2Meas.CellInfo = append(data.l2Meas.CellInfo, *newCellInfo)
	}

	return nil
}

func populateL2Meas(key string, jsonInfo string, l2MeasData interface{}) error {
	// Get query params & userlist from user data
	data := l2MeasData.(*L2MeasData)
@@ -2548,7 +2622,7 @@ func populateL2Meas(key string, jsonInfo string, l2MeasData interface{}) error {
		return err
	}

	// Ignore entries with no rabId
	// Ignore entries with no rabId, meaning only applies if connected to POA-4G, no need to check for ecgi
	if ueData.ErabId == -1 {
		return nil
	}
@@ -2585,15 +2659,15 @@ func populateL2Meas(key string, jsonInfo string, l2MeasData interface{}) error {
	found := false

	//find if cellUeInfo already exists
	var cellUeIndex int

	for index, currentCellUeInfo := range data.l2Meas.CellUEInfo {
		if currentCellUeInfo.Ecgi.Plmn.Mcc == ueData.Ecgi.Plmn.Mcc &&
			currentCellUeInfo.Ecgi.Plmn.Mnc == ueData.Ecgi.Plmn.Mnc &&
			currentCellUeInfo.Ecgi.CellId == ueData.Ecgi.CellId {
			//add ue into the existing cellUserInfo
	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 {
		if assocId.Type_ == currentCellUeInfo.AssociateId.Type_ && assocId.Value == currentCellUeInfo.AssociateId.Value {
			found = true
			cellUeIndex = index
		}
	}
	if !found {
@@ -2604,18 +2678,12 @@ func populateL2Meas(key string, jsonInfo string, l2MeasData interface{}) error {
		newPlmn.Mnc = ueData.Ecgi.Plmn.Mnc
		newEcgi.Plmn = newPlmn
		newEcgi.CellId = ueData.Ecgi.CellId
		newCellUeInfo.Ecgi = newEcgi

		assocId := new(AssociateId)
		assocId.Type_ = 1 //UE_IPV4_ADDRESS
		subKeys := strings.Split(key, ":")
		assocId.Value = subKeys[len(subKeys)-1]
		newCellUeInfo.Ecgi = newEcgi
		newCellUeInfo.AssociateId = assocId

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

	//find if cellInfo already exists
	var cellIndex int
+2 −2
Original line number Diff line number Diff line
@@ -2179,8 +2179,8 @@ 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}
	expectedUeData[UPDATED] = UeData{ueName, -1, &Ecgi{"", &Plmn{"123", "456"}}, &NRcgi{"", &Plmn{"123", "456"}}, 80, "", nil}
	expectedUeData[INITIAL] = UeData{ueName, 1, &Ecgi{"2345678", &Plmn{"123", "456"}}, &NRcgi{"", &Plmn{"123", "456"}}, 80, "", nil, nil}
	expectedUeData[UPDATED] = UeData{ueName, -1, &Ecgi{"", &Plmn{"123", "456"}}, &NRcgi{"", &Plmn{"123", "456"}}, 80, "", nil, nil}

	var expectedAppEcgiStr [2]string
	var expectedAppEcgi [2]Ecgi
+13 −0
Original line number Diff line number Diff line
@@ -659,6 +659,19 @@ func (m *Model) GetNodeParent(name string) (parent interface{}) {
	return parent
}

// GetNodeChild - Get a child node by its child name
func (m *Model) GetNodeChild(name string) (child interface{}) {
        m.lock.RLock()
        defer m.lock.RUnlock()

        child = nil
        n := m.nodeMap.nameMap[name]
        if n != nil {
                child = n.child
        }
        return child
}

// GetNodeContext - Get a node context
// 		Returned value is of type interface{}
//    Good practice: returned node should be type asserted with val,ok := node.(someType) to prevent panic