Unverified Commit 5b850025 authored by Kevin Di Lallo's avatar Kevin Di Lallo Committed by GitHub
Browse files

Merge pull request #130 from pastorsx/sp_dev_services_multi_poa

AdvantEDGE services handling of UE movement between different RAT (4G, 5G, Wifi)
parents f0059960 23818678
Loading
Loading
Loading
Loading
+2 −3
Original line number Diff line number Diff line
@@ -2899,7 +2899,6 @@ definitions:
    type: "object"
    required:
    - "appInsId"
    - "ecgi"
    properties:
      timeStamp:
        $ref: "#/definitions/TimeStamp"
@@ -2908,8 +2907,8 @@ definitions:
        format: "string"
        example: "01"
        description: "Unique identifier for the mobile edge application instance"
      ecgi:
        $ref: "#/definitions/Ecgi"
      plmn:
        $ref: "#/definitions/Plmn"
  RabInfo:
    type: "object"
    required:
+38 −17
Original line number Diff line number Diff line
@@ -34,7 +34,7 @@ type SbiCfg struct {
	RedisAddr      string
	PostgisHost    string
	PostgisPort    string
	UeDataCb       func(string, string, string, string, int32)
	UeDataCb       func(string, string, string, string, bool)
	AppEcgiInfoCb  func(string, string, string, string)
	ScenarioNameCb func(string)
	CleanUpCb      func()
@@ -46,7 +46,7 @@ type RnisSbi struct {
	handlerId            int
	activeModel          *mod.Model
	pc                   *postgis.Connector
	updateUeDataCB       func(string, string, string, string, int32)
	updateUeDataCB       func(string, string, string, string, bool)
	updateAppEcgiInfoCB  func(string, string, string, string)
	updateScenarioNameCB func(string)
	cleanUpCB            func()
@@ -196,18 +196,32 @@ func processActiveScenarioUpdate() {
					mnc := ""
					mcc := ""
					cellId := ""
					erabIdValid := false
					if domain.CellularDomainConfig != nil {
						mnc = domain.CellularDomainConfig.Mnc
						mcc = domain.CellularDomainConfig.Mcc
						cellId = domain.CellularDomainConfig.DefaultCellId
					}
					switch poa.Type_ {
					case mod.NodeTypePoa4G:
						if poa.Poa4GConfig != nil {
							if poa.Poa4GConfig.CellId != "" {
								cellId = poa.Poa4GConfig.CellId
						} else {
							cellId = domain.CellularDomainConfig.DefaultCellId
							}
						}
					sbi.updateUeDataCB(name, mnc, mcc, cellId, -1)
						erabIdValid = true
					case mod.NodeTypePoa5G:
						if poa.Poa5GConfig != nil {
							if poa.Poa5GConfig.CellId != "" {
								cellId = poa.Poa5GConfig.CellId
							}
						}
					default:
						//empty cells for POAs not supporting RNIS
						cellId = ""
					}

					sbi.updateUeDataCB(name, mnc, mcc, cellId, erabIdValid)
				}
			}
		}
@@ -223,7 +237,7 @@ func processActiveScenarioUpdate() {
			}
		}
		if !found {
			sbi.updateUeDataCB(prevUeName, "", "", "", -1)
			sbi.updateUeDataCB(prevUeName, "", "", "", false)
			log.Info("Ue removed : ", prevUeName)
		}
	}
@@ -258,17 +272,24 @@ func processActiveScenarioUpdate() {
						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
							} else {
								cellId = domain.CellularDomainConfig.DefaultCellId
								}
						} else {
							if domain.CellularDomainConfig != nil {
								cellId = domain.CellularDomainConfig.DefaultCellId
							}
						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)
+1 −1
Original line number Diff line number Diff line
@@ -29,5 +29,5 @@ type PlmnInfo struct {
	// Unique identifier for the mobile edge application instance
	AppInsId string `json:"appInsId"`

	Ecgi *Ecgi `json:"ecgi"`
	Plmn *Plmn `json:"plmn,omitempty"`
}
+227 −121
Original line number Diff line number Diff line
@@ -196,7 +196,7 @@ func Stop() (err error) {
	return sbi.Stop()
}

func updateUeData(name string, mnc string, mcc string, cellId string, erabId int32) {
func updateUeData(name string, mnc string, mcc string, cellId string, erabIdValid bool) {

	var plmn Plmn
	var newEcgi Ecgi
@@ -232,18 +232,21 @@ func updateUeData(name string, mnc string, mcc string, cellId string, erabId int
	//updateDB if changes occur
	if newEcgi.Plmn.Mnc != oldPlmnMnc || newEcgi.Plmn.Mcc != oldPlmnMcc || newEcgi.CellId != oldCellId {

		//allocating a new erabId if entering a 3GPP environment
		if oldCellId == "" && cellId != "" {
		//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)
				//rab establishment case
				ueData.ErabId = int32(nextAvailableErabId)
				nextAvailableErabId++
			} else { //was not connected to a 4G POA and still not connected to a 4G POA, so, no change
				ueData.ErabId = oldErabId // = -1
			}
		} else {
			if oldCellId != "" && cellId == "" {
			if 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
				ueData.ErabId = -1
			} else {
				//no change
				ueData.ErabId = oldErabId
			}
		}

@@ -255,9 +258,12 @@ func updateUeData(name string, mnc string, mcc string, cellId string, erabId int
		//log to model for all apps on that UE
		checkCcNotificationRegisteredSubscriptions("", assocId, &plmn, oldPlmn, "", cellId, oldCellId)
		//ueData contains newErabId
		if oldErabId == -1 && ueData.ErabId != -1 {
			checkReNotificationRegisteredSubscriptions("", assocId, &plmn, oldPlmn, -1, cellId, oldCellId, ueData.ErabId)
		}
		if oldErabId != -1 && ueData.ErabId == -1 {
			checkRrNotificationRegisteredSubscriptions("", assocId, &plmn, oldPlmn, -1, cellId, oldCellId, oldErabId)

		}
	}
}

@@ -439,63 +445,209 @@ func repopulateRrSubscriptionMap(key string, jsonInfo string, userData interface
	return nil
}

func checkCcNotificationRegisteredSubscriptions(appId string, assocId *AssociateId, newPlmn *Plmn, oldPlmn *Plmn, hoStatus string, newCellId string, oldCellId string) {
func isMatchCcFilterCriteriaAppInsId(filterCriteria interface{}, appId string) bool {
	filter := filterCriteria.(*FilterCriteriaAssocHo)

	//no cell change if no cellIds present (cell change within 3gpp elements only)
	if newCellId == "" || oldCellId == "" {
		return
	//if filter criteria is not set, it acts as a wildcard and accepts all
	if filter.AppInsId == "" {
		return true
	}
	return (appId == filter.AppInsId)
}

	mutex.Lock()
	defer mutex.Unlock()
	//check all that applies
	for subsId, sub := range ccSubscriptionMap {
func isMatchRabFilterCriteriaAppInsId(filterCriteria interface{}, appId string) bool {
	filter := filterCriteria.(*FilterCriteriaAssocQci)

	//if filter criteria is not set, it acts as a wildcard and accepts all
	if filter.AppInsId == "" {
		return true
	}
	return (appId == filter.AppInsId)
}

func isMatchCcFilterCriteriaAssociateId(filterCriteria interface{}, assocId *AssociateId) bool {
	filter := filterCriteria.(*FilterCriteriaAssocHo)

	//if filter criteria is not set, it acts as a wildcard and accepts all
	if filter.AssociateId == nil {
		return true
	}
	//if filter accepts something specific but no assocId, then we fail right away
	if assocId == nil {
		return false
	}
	return (assocId.Value == filter.AssociateId.Value)
}

func isMatchRabFilterCriteriaAssociateId(filterCriteria interface{}, assocId *AssociateId) bool {
	filter := filterCriteria.(*FilterCriteriaAssocQci)

	//if filter criteria is not set, it acts as a wildcard and accepts all
	if filter.AssociateId == nil {
		return true
	}
	//if filter accepts something specific but no assocId, then we fail right away
	if assocId == nil {
		return false
	}
	return (assocId.Value == filter.AssociateId.Value)
}

func isMatchCcFilterCriteriaPlmn(filterCriteria interface{}, newPlmn *Plmn, oldPlmn *Plmn) bool {
	filter := filterCriteria.(*FilterCriteriaAssocHo)

	//if filter criteria is not set, it acts as a wildcard and accepts all
	if filter.Plmn == nil {
		return true
	}
	//either of the Plmn should match the filter,
	match := false

		if sub != nil {
			if (sub.FilterCriteria.AppInsId == "") || (sub.FilterCriteria.AppInsId != "" && appId == sub.FilterCriteria.AppInsId) {
	if newPlmn != nil {
		if newPlmn.Mnc == filter.Plmn.Mnc && newPlmn.Mcc == filter.Plmn.Mcc {
			match = true
			} else {
				match = false
		}

			if match && ((sub.FilterCriteria.AssociateId == nil) || (sub.FilterCriteria.AssociateId != nil && assocId != nil && assocId.Value == sub.FilterCriteria.AssociateId.Value)) {
	}
	if oldPlmn != nil {
		if oldPlmn.Mnc == filter.Plmn.Mnc && oldPlmn.Mcc == filter.Plmn.Mcc {
			match = true
			} else {
				match = false
		}
	}

			if match && ((sub.FilterCriteria.Plmn == nil) || (sub.FilterCriteria.Plmn != nil && ((newPlmn != nil && newPlmn.Mnc == sub.FilterCriteria.Plmn.Mnc && newPlmn.Mcc == sub.FilterCriteria.Plmn.Mcc) || (oldPlmn != nil && oldPlmn.Mnc == sub.FilterCriteria.Plmn.Mnc && oldPlmn.Mcc == sub.FilterCriteria.Plmn.Mcc)))) {
	return match
}

func isMatchRabFilterCriteriaPlmn(filterCriteria interface{}, newPlmn *Plmn, oldPlmn *Plmn) bool {
	filter := filterCriteria.(*FilterCriteriaAssocQci)

	//if filter criteria is not set, it acts as a wildcard and accepts all
	if filter.Plmn == nil {
		return true
	}
	//either of the Plmn should match the filter,
	match := false

	if newPlmn != nil {
		if newPlmn.Mnc == filter.Plmn.Mnc && newPlmn.Mcc == filter.Plmn.Mcc {
			match = true
			} else {
				match = false
		}
	}
	if oldPlmn != nil {
		if oldPlmn.Mnc == filter.Plmn.Mnc && oldPlmn.Mcc == filter.Plmn.Mcc {
			match = true
		}
	}

			//loop through all cellIds
			if match {
				if sub.FilterCriteria.CellId != nil {
					matchOne := false
	return match
}

					for _, cellId := range sub.FilterCriteria.CellId {
						if newCellId != oldCellId {
							if newCellId != "" && newCellId == cellId {
								matchOne = true
								break
							} else {
								if oldCellId != "" && oldCellId == cellId {
									matchOne = true
									break
func isMatchCcFilterCriteriaCellId(filterCriteria interface{}, newCellId string, oldCellId string) bool {
	filter := filterCriteria.(*FilterCriteriaAssocHo)

	if filter.CellId == nil {
		return true
	}

	//either the old of new cellId should match one of the cellId in the filter list
	for _, cellId := range filter.CellId {

		if newCellId == cellId {
			return true
		}
		if oldCellId == cellId {
			return true
		}
	}
					if matchOne {
						match = true
					} else {
						match = false

	return false
}

func isMatchRabFilterCriteriaCellId(filterCriteria interface{}, newCellId string, oldCellId string) bool {
	filter := filterCriteria.(*FilterCriteriaAssocQci)

	if filter.CellId == nil {
		return true
	}

	//either the old of new cellId should match one of the cellId in the filter list
	for _, cellId := range filter.CellId {
		if newCellId == cellId {
			return true
		}
		if oldCellId == cellId {
			return true
		}
	}

	return false
}

func isMatchFilterCriteriaAppInsId(subscriptionType string, filterCriteria interface{}, appId string) bool {
	switch subscriptionType {
	case cellChangeSubscriptionType:
		return isMatchCcFilterCriteriaAppInsId(filterCriteria, appId)
	case rabEstSubscriptionType, rabRelSubscriptionType:
		return isMatchRabFilterCriteriaAppInsId(filterCriteria, appId)
	}
	return true
}

func isMatchFilterCriteriaAssociateId(subscriptionType string, filterCriteria interface{}, assocId *AssociateId) bool {
	switch subscriptionType {
	case cellChangeSubscriptionType:
		return isMatchCcFilterCriteriaAssociateId(filterCriteria, assocId)
	case rabEstSubscriptionType, rabRelSubscriptionType:
		return isMatchRabFilterCriteriaAssociateId(filterCriteria, assocId)
	}
	return true
}

func isMatchFilterCriteriaPlmn(subscriptionType string, filterCriteria interface{}, newPlmn *Plmn, oldPlmn *Plmn) bool {
	switch subscriptionType {
	case cellChangeSubscriptionType:
		return isMatchCcFilterCriteriaPlmn(filterCriteria, newPlmn, oldPlmn)
	case rabEstSubscriptionType, rabRelSubscriptionType:
		return isMatchRabFilterCriteriaPlmn(filterCriteria, newPlmn, oldPlmn)
	}
	return true
}

func isMatchFilterCriteriaCellId(subscriptionType string, filterCriteria interface{}, newCellId string, oldCellId string) bool {
	switch subscriptionType {
	case cellChangeSubscriptionType:
		return isMatchCcFilterCriteriaCellId(filterCriteria, newCellId, oldCellId)
	case rabEstSubscriptionType, rabRelSubscriptionType:
		return isMatchRabFilterCriteriaCellId(filterCriteria, newCellId, oldCellId)
	}
	return true
}

func checkCcNotificationRegisteredSubscriptions(appId string, assocId *AssociateId, newPlmn *Plmn, oldPlmn *Plmn, hoStatus string, newCellId string, oldCellId string) {

	//no cell change if no cellIds present (cell change within 3gpp elements only)
	if newCellId == "" || oldCellId == "" {
		return
	}

	mutex.Lock()
	defer mutex.Unlock()
	//check all that applies
	for subsId, sub := range ccSubscriptionMap {

		if sub != nil {

			//verifying every criteria of the filter
			match := isMatchFilterCriteriaAppInsId(cellChangeSubscriptionType, sub.FilterCriteria, appId)
			if match {
				match = isMatchFilterCriteriaAssociateId(cellChangeSubscriptionType, sub.FilterCriteria, assocId)
			}

			if match {
				match = isMatchFilterCriteriaPlmn(cellChangeSubscriptionType, sub.FilterCriteria, newPlmn, oldPlmn)
			}

			if match {
				match = isMatchFilterCriteriaCellId(cellChangeSubscriptionType, sub.FilterCriteria, newCellId, oldCellId)
			}

			//we ignore hoStatus
@@ -559,8 +711,9 @@ func checkCcNotificationRegisteredSubscriptions(appId string, assocId *Associate

func checkReNotificationRegisteredSubscriptions(appId string, assocId *AssociateId, newPlmn *Plmn, oldPlmn *Plmn, qci int32, newCellId string, oldCellId string, erabId int32) {

	//only applies if coming from a non 3gpp element
	if oldCellId != "" || newCellId == "" {
	//checking filters only if we were not connected to a POA-4G and now connecting to one
	//condition to be connecting to a POA-4G from non POA-4G: 1) had no plmn 2) had no cellId 3) has erabId being allocated to it
	if oldPlmn != nil && oldCellId != "" && erabId == -1 {
		return
	}

@@ -569,45 +722,21 @@ func checkReNotificationRegisteredSubscriptions(appId string, assocId *Associate
	//check all that applies
	for subsId, sub := range reSubscriptionMap {

		match := false

		if sub != nil {
			if (sub.FilterCriteria.AppInsId == "") || (sub.FilterCriteria.AppInsId != "" && appId == sub.FilterCriteria.AppInsId) {
				match = true
			} else {
				match = false
			}

			if match && ((sub.FilterCriteria.AssociateId == nil) || (sub.FilterCriteria.AssociateId != nil && assocId != nil && assocId.Value == sub.FilterCriteria.AssociateId.Value)) {
				match = true
			} else {
				match = false
			}
			//verifying every criteria of the filter
			match := isMatchFilterCriteriaAppInsId(rabEstSubscriptionType, sub.FilterCriteria, appId)

			if match && (((sub.FilterCriteria.Plmn == nil) || (sub.FilterCriteria.Plmn != nil && (newPlmn != nil && newPlmn.Mnc == sub.FilterCriteria.Plmn.Mnc && newPlmn.Mcc == sub.FilterCriteria.Plmn.Mcc))) && (oldPlmn == nil || oldCellId == "")) {
				match = true
			} else {
				match = false
			if match {
				match = isMatchFilterCriteriaAssociateId(rabEstSubscriptionType, sub.FilterCriteria, assocId)
			}

			//loop through all cellIds
			if match {
				if sub.FilterCriteria.CellId != nil {
					matchOne := false

					for _, cellId := range sub.FilterCriteria.CellId {
						//if we are here, oldPlmn is null or oldCellId is ""
						if newCellId == cellId {
							matchOne = true
							break
						}
					}
					if matchOne {
						match = true
					} else {
						match = false
					}
				match = isMatchFilterCriteriaPlmn(rabEstSubscriptionType, sub.FilterCriteria, newPlmn, nil)
			}

			if match {
				match = isMatchFilterCriteriaCellId(rabEstSubscriptionType, sub.FilterCriteria, newCellId, oldCellId)
			}

			//we ignore qci
@@ -658,8 +787,9 @@ func checkReNotificationRegisteredSubscriptions(appId string, assocId *Associate

func checkRrNotificationRegisteredSubscriptions(appId string, assocId *AssociateId, newPlmn *Plmn, oldPlmn *Plmn, qci int32, newCellId string, oldCellId string, erabId int32) {

	//only applies if going to a non 3gpp element
	if newCellId != "" || oldCellId == "" {
	//checking filters only if we were connected to a POA-4G and now disconnecting from one
	//condition to be disconnecting from a POA-4G: 1) has an empty new plmn 2) has empty cellId 
	if newPlmn != nil && newCellId != "" {
		return
	}

@@ -668,45 +798,21 @@ func checkRrNotificationRegisteredSubscriptions(appId string, assocId *Associate
	//check all that applies
	for subsId, sub := range rrSubscriptionMap {

		match := false

		if sub != nil {
			if (sub.FilterCriteria.AppInsId == "") || (sub.FilterCriteria.AppInsId != "" && appId == sub.FilterCriteria.AppInsId) {
				match = true
			} else {
				match = false
			}

			if match && ((sub.FilterCriteria.AssociateId == nil) || (sub.FilterCriteria.AssociateId != nil && assocId != nil && assocId.Value == sub.FilterCriteria.AssociateId.Value)) {
				match = true
			} else {
				match = false
			}
			//verifying every criteria of the filter
			match := isMatchFilterCriteriaAppInsId(rabRelSubscriptionType, sub.FilterCriteria, appId)

			if match && (((sub.FilterCriteria.Plmn == nil) || (sub.FilterCriteria.Plmn != nil && (oldPlmn != nil && oldPlmn.Mnc == sub.FilterCriteria.Plmn.Mnc && oldPlmn.Mcc == sub.FilterCriteria.Plmn.Mcc))) && (newPlmn == nil || newCellId == "")) {
				match = true
			} else {
				match = false
			if match {
				match = isMatchFilterCriteriaAssociateId(rabRelSubscriptionType, sub.FilterCriteria, assocId)
			}

			//loop through all cellIds
			if match {
				if sub.FilterCriteria.CellId != nil {
					matchOne := false

					for _, cellId := range sub.FilterCriteria.CellId {
						//if we are here, newPlmn is null or newCellId is ""
						if oldCellId == cellId {
							matchOne = true
							break
						}
					}
					if matchOne {
						match = true
					} else {
						match = false
					}
				match = isMatchFilterCriteriaPlmn(rabRelSubscriptionType, sub.FilterCriteria, nil, oldPlmn)
			}

			if match {
				match = isMatchFilterCriteriaCellId(rabRelSubscriptionType, sub.FilterCriteria, "", oldCellId)
			}

			//we ignore qci
@@ -1429,9 +1535,9 @@ func plmnInfoGET(w http.ResponseWriter, r *http.Request) {

			ecgi := convertJsonToEcgi(jsonAppEcgiInfo)
			if ecgi != nil {
				if ecgi.Plmn.Mnc != "" && ecgi.Plmn.Mcc != "" && ecgi.CellId != "" {
				if ecgi.Plmn.Mnc != "" && ecgi.Plmn.Mcc != "" {
					var plmnInfo PlmnInfo
					plmnInfo.Ecgi = ecgi
					plmnInfo.Plmn = ecgi.Plmn
					plmnInfo.AppInsId = meAppName
					plmnInfo.TimeStamp = &timeStamp
					response.PlmnInfo = append(response.PlmnInfo, plmnInfo)
+2 −11
Original line number Diff line number Diff line
@@ -2268,11 +2268,8 @@ func TestPlmnInfoGet(t *testing.T) {
	 * expected response section
	 ******************************/
	var expectedMcc [2]string
	var expectedCellId [2]string
	expectedMcc[INITIAL] = "123"
	expectedMcc[UPDATED] = "123"
	expectedCellId[INITIAL] = "2345678"
	expectedCellId[UPDATED] = "1234567"

	/******************************
	 * request vars section
@@ -2305,10 +2302,7 @@ func TestPlmnInfoGet(t *testing.T) {
	}

	if respBody.PlmnInfo != nil {
		if respBody.PlmnInfo[0].Ecgi.Plmn.Mcc != expectedMcc[INITIAL] {
			t.Fatalf("Failed to get expected response")
		}
		if respBody.PlmnInfo[0].Ecgi.CellId != expectedCellId[INITIAL] {
		if respBody.PlmnInfo[0].Plmn.Mcc != expectedMcc[INITIAL] {
			t.Fatalf("Failed to get expected response")
		}
	} else {
@@ -2326,10 +2320,7 @@ func TestPlmnInfoGet(t *testing.T) {
		t.Fatalf("Failed to get expected response")
	}
	if respBody.PlmnInfo != nil {
		if respBody.PlmnInfo[0].Ecgi.Plmn.Mcc != expectedMcc[UPDATED] {
			t.Fatalf("Failed to get expected response")
		}
		if respBody.PlmnInfo[0].Ecgi.CellId != expectedCellId[UPDATED] {
		if respBody.PlmnInfo[0].Plmn.Mcc != expectedMcc[UPDATED] {
			t.Fatalf("Failed to get expected response")
		}
	} else {
Loading