1 Star 1 Fork 1

刘昭/amf

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
context.go 12.17 KB
一键复制 编辑 原始数据 按行查看 历史
刘昭 提交于 2022-01-25 19:22 . 1.0.1
package context
import (
"fmt"
"math"
"net"
"reflect"
"strconv"
"strings"
"sync"
"time"
"gitee.com/liu-zhao234568/amf/factory"
"gitee.com/liu-zhao234568/amf/logger"
"github.com/free5gc/idgenerator"
"github.com/free5gc/openapi/models"
)
var (
amfContext = AMFContext{}
tmsiGenerator *idgenerator.IDGenerator = nil
amfUeNGAPIDGenerator *idgenerator.IDGenerator = nil
amfStatusSubscriptionIDGenerator *idgenerator.IDGenerator = nil
)
func init() {
AMF_Self().LadnPool = make(map[string]*LADN)
AMF_Self().EventSubscriptionIDGenerator = idgenerator.NewGenerator(1, math.MaxInt32)
AMF_Self().Name = "amf"
AMF_Self().UriScheme = models.UriScheme_HTTPS
AMF_Self().RelativeCapacity = 0xff
AMF_Self().ServedGuamiList = make([]models.Guami, 0, MaxNumOfServedGuamiList)
AMF_Self().PlmnSupportList = make([]factory.PlmnSupportItem, 0, MaxNumOfPLMNs)
AMF_Self().NfService = make(map[models.ServiceName]models.NfService)
AMF_Self().NetworkName.Full = "free5GC"
tmsiGenerator = idgenerator.NewGenerator(1, math.MaxInt32)
amfStatusSubscriptionIDGenerator = idgenerator.NewGenerator(1, math.MaxInt32)
amfUeNGAPIDGenerator = idgenerator.NewGenerator(1, MaxValueOfAmfUeNgapId)
}
type AMFContext struct {
EventSubscriptionIDGenerator *idgenerator.IDGenerator
EventSubscriptions sync.Map
UePool sync.Map // map[supi]*AmfUe
RanUePool sync.Map // map[AmfUeNgapID]*RanUe
AmfRanPool sync.Map // map[net.Conn]*AmfRan
LadnPool map[string]*LADN // dnn as key
SupportTaiLists []models.Tai
ServedGuamiList []models.Guami
PlmnSupportList []factory.PlmnSupportItem
RelativeCapacity int64
NfId string
Name string
NfService map[models.ServiceName]models.NfService // nfservice that amf support
UriScheme models.UriScheme
BindingIPv4 string
SBIPort int
RegisterIPv4 string
HttpIPv6Address string
TNLWeightFactor int64
SupportDnnLists []string
AMFStatusSubscriptions sync.Map // map[subscriptionID]models.SubscriptionData
NrfUri string
SecurityAlgorithm SecurityAlgorithm
NetworkName factory.NetworkName
NgapIpList []string // NGAP Server IP
T3502Value int // unit is second
T3512Value int // unit is second
Non3gppDeregistrationTimerValue int // unit is second
// read-only fields
T3513Cfg factory.TimerValue
T3522Cfg factory.TimerValue
T3550Cfg factory.TimerValue
T3560Cfg factory.TimerValue
T3565Cfg factory.TimerValue
}
type AMFContextEventSubscription struct {
IsAnyUe bool
IsGroupUe bool
UeSupiList []string
Expiry *time.Time
EventSubscription models.AmfEventSubscription
}
type SecurityAlgorithm struct {
IntegrityOrder []uint8 // slice of security.AlgIntegrityXXX
CipheringOrder []uint8 // slice of security.AlgCipheringXXX
}
func NewPlmnSupportItem() (item factory.PlmnSupportItem) {
item.SNssaiList = make([]models.Snssai, 0, MaxNumOfSlice)
return
}
func (context *AMFContext) TmsiAllocate() int32 {
tmsi, err := tmsiGenerator.Allocate()
if err != nil {
logger.ContextLog.Errorf("Allocate TMSI error: %+v", err)
return -1
}
return int32(tmsi)
}
func (context *AMFContext) AllocateAmfUeNgapID() (int64, error) {
return amfUeNGAPIDGenerator.Allocate()
}
func (context *AMFContext) AllocateGutiToUe(ue *AmfUe) {
servedGuami := context.ServedGuamiList[0]
ue.Tmsi = context.TmsiAllocate()
plmnID := servedGuami.PlmnId.Mcc + servedGuami.PlmnId.Mnc
tmsiStr := fmt.Sprintf("%08x", ue.Tmsi)
ue.Guti = plmnID + servedGuami.AmfId + tmsiStr
}
func (context *AMFContext) AllocateRegistrationArea(ue *AmfUe, anType models.AccessType) {
// clear the previous registration area if need
if len(ue.RegistrationArea[anType]) > 0 {
ue.RegistrationArea[anType] = nil
}
// allocate a new tai list as a registration area to ue
// TODO: algorithm to choose TAI list
for _, supportTai := range context.SupportTaiLists {
if reflect.DeepEqual(supportTai, ue.Tai) {
ue.RegistrationArea[anType] = append(ue.RegistrationArea[anType], supportTai)
break
}
}
}
func (context *AMFContext) NewAMFStatusSubscription(subscriptionData models.SubscriptionData) (subscriptionID string) {
id, err := amfStatusSubscriptionIDGenerator.Allocate()
if err != nil {
logger.ContextLog.Errorf("Allocate subscriptionID error: %+v", err)
return ""
}
subscriptionID = strconv.Itoa(int(id))
context.AMFStatusSubscriptions.Store(subscriptionID, subscriptionData)
return
}
// Return Value: (subscriptionData *models.SubScriptionData, ok bool)
func (context *AMFContext) FindAMFStatusSubscription(subscriptionID string) (*models.SubscriptionData, bool) {
if value, ok := context.AMFStatusSubscriptions.Load(subscriptionID); ok {
subscriptionData := value.(models.SubscriptionData)
return &subscriptionData, ok
} else {
return nil, false
}
}
func (context *AMFContext) DeleteAMFStatusSubscription(subscriptionID string) {
context.AMFStatusSubscriptions.Delete(subscriptionID)
if id, err := strconv.ParseInt(subscriptionID, 10, 64); err != nil {
logger.ContextLog.Error(err)
} else {
amfStatusSubscriptionIDGenerator.FreeID(id)
}
}
func (context *AMFContext) NewEventSubscription(subscriptionID string, subscription *AMFContextEventSubscription) {
context.EventSubscriptions.Store(subscriptionID, subscription)
}
func (context *AMFContext) FindEventSubscription(subscriptionID string) (*AMFContextEventSubscription, bool) {
if value, ok := context.EventSubscriptions.Load(subscriptionID); ok {
return value.(*AMFContextEventSubscription), ok
} else {
return nil, false
}
}
func (context *AMFContext) DeleteEventSubscription(subscriptionID string) {
context.EventSubscriptions.Delete(subscriptionID)
if id, err := strconv.ParseInt(subscriptionID, 10, 32); err != nil {
logger.ContextLog.Error(err)
} else {
context.EventSubscriptionIDGenerator.FreeID(id)
}
}
func (context *AMFContext) AddAmfUeToUePool(ue *AmfUe, supi string) {
if len(supi) == 0 {
logger.ContextLog.Errorf("Supi is nil")
}
ue.Supi = supi
context.UePool.Store(ue.Supi, ue)
}
func (context *AMFContext) NewAmfUe(supi string) *AmfUe {
ue := AmfUe{}
ue.init()
if supi != "" {
context.AddAmfUeToUePool(&ue, supi)
}
context.AllocateGutiToUe(&ue)
return &ue
}
func (context *AMFContext) AmfUeFindByUeContextID(ueContextID string) (*AmfUe, bool) {
if strings.HasPrefix(ueContextID, "imsi") {
return context.AmfUeFindBySupi(ueContextID)
}
if strings.HasPrefix(ueContextID, "imei") {
return context.AmfUeFindByPei(ueContextID)
}
if strings.HasPrefix(ueContextID, "5g-guti") {
guti := ueContextID[strings.LastIndex(ueContextID, "-")+1:]
return context.AmfUeFindByGuti(guti)
}
return nil, false
}
func (context *AMFContext) AmfUeFindBySupi(supi string) (ue *AmfUe, ok bool) {
if value, loadOk := context.UePool.Load(supi); loadOk {
ue = value.(*AmfUe)
ok = loadOk
}
return
}
func (context *AMFContext) AmfUeFindByPei(pei string) (ue *AmfUe, ok bool) {
context.UePool.Range(func(key, value interface{}) bool {
candidate := value.(*AmfUe)
if ok = (candidate.Pei == pei); ok {
ue = candidate
return false
}
return true
})
return
}
func (context *AMFContext) NewAmfRan(conn net.Conn) *AmfRan {
ran := AmfRan{}
ran.SupportedTAList = make([]SupportedTAI, 0, MaxNumOfTAI*MaxNumOfBroadcastPLMNs)
ran.Conn = conn
ran.Log = logger.NgapLog.WithField(logger.FieldRanAddr, conn.RemoteAddr().String())
context.AmfRanPool.Store(conn, &ran)
return &ran
}
// use net.Conn to find RAN context, return *AmfRan and ok bit
func (context *AMFContext) AmfRanFindByConn(conn net.Conn) (*AmfRan, bool) {
if value, ok := context.AmfRanPool.Load(conn); ok {
return value.(*AmfRan), ok
}
return nil, false
}
// use ranNodeID to find RAN context, return *AmfRan and ok bit
func (context *AMFContext) AmfRanFindByRanID(ranNodeID models.GlobalRanNodeId) (*AmfRan, bool) {
var ran *AmfRan
var ok bool
context.AmfRanPool.Range(func(key, value interface{}) bool {
amfRan := value.(*AmfRan)
switch amfRan.RanPresent {
case RanPresentGNbId:
if amfRan.RanId.GNbId.GNBValue == ranNodeID.GNbId.GNBValue {
ran = amfRan
ok = true
return false
}
case RanPresentNgeNbId:
if amfRan.RanId.NgeNbId == ranNodeID.NgeNbId {
ran = amfRan
ok = true
return false
}
case RanPresentN3IwfId:
if amfRan.RanId.N3IwfId == ranNodeID.N3IwfId {
ran = amfRan
ok = true
return false
}
}
return true
})
return ran, ok
}
func (context *AMFContext) DeleteAmfRan(conn net.Conn) {
context.AmfRanPool.Delete(conn)
}
func (context *AMFContext) InSupportDnnList(targetDnn string) bool {
for _, dnn := range context.SupportDnnLists {
if dnn == targetDnn {
return true
}
}
return false
}
func (context *AMFContext) InPlmnSupportList(snssai models.Snssai) bool {
for _, plmnSupportItem := range context.PlmnSupportList {
for _, supportSnssai := range plmnSupportItem.SNssaiList {
if reflect.DeepEqual(supportSnssai, snssai) {
return true
}
}
}
return false
}
func (context *AMFContext) AmfUeFindByGuti(guti string) (ue *AmfUe, ok bool) {
context.UePool.Range(func(key, value interface{}) bool {
candidate := value.(*AmfUe)
if ok = (candidate.Guti == guti); ok {
ue = candidate
return false
}
return true
})
return
}
func (context *AMFContext) AmfUeFindByPolicyAssociationID(polAssoId string) (ue *AmfUe, ok bool) {
context.UePool.Range(func(key, value interface{}) bool {
candidate := value.(*AmfUe)
if ok = (candidate.PolicyAssociationId == polAssoId); ok {
ue = candidate
return false
}
return true
})
return
}
func (context *AMFContext) RanUeFindByAmfUeNgapID(amfUeNgapID int64) *RanUe {
if value, ok := context.RanUePool.Load(amfUeNgapID); ok {
return value.(*RanUe)
} else {
return nil
}
}
func (context *AMFContext) GetIPv4Uri() string {
return fmt.Sprintf("%s://%s:%d", context.UriScheme, context.RegisterIPv4, context.SBIPort)
}
func (context *AMFContext) InitNFService(serivceName []string, version string) {
tmpVersion := strings.Split(version, ".")
versionUri := "v" + tmpVersion[0]
for index, nameString := range serivceName {
name := models.ServiceName(nameString)
context.NfService[name] = models.NfService{
ServiceInstanceId: strconv.Itoa(index),
ServiceName: name,
Versions: &[]models.NfServiceVersion{
{
ApiFullVersion: version,
ApiVersionInUri: versionUri,
},
},
Scheme: context.UriScheme,
NfServiceStatus: models.NfServiceStatus_REGISTERED,
ApiPrefix: context.GetIPv4Uri(),
IpEndPoints: &[]models.IpEndPoint{
{
Ipv4Address: context.RegisterIPv4,
Transport: models.TransportProtocol_TCP,
Port: int32(context.SBIPort),
},
},
}
}
}
// Reset AMF Context
func (context *AMFContext) Reset() {
context.AmfRanPool.Range(func(key, value interface{}) bool {
context.UePool.Delete(key)
return true
})
for key := range context.LadnPool {
delete(context.LadnPool, key)
}
context.RanUePool.Range(func(key, value interface{}) bool {
context.RanUePool.Delete(key)
return true
})
context.UePool.Range(func(key, value interface{}) bool {
context.UePool.Delete(key)
return true
})
context.EventSubscriptions.Range(func(key, value interface{}) bool {
context.DeleteEventSubscription(key.(string))
return true
})
for key := range context.NfService {
delete(context.NfService, key)
}
context.SupportTaiLists = context.SupportTaiLists[:0]
context.PlmnSupportList = context.PlmnSupportList[:0]
context.ServedGuamiList = context.ServedGuamiList[:0]
context.RelativeCapacity = 0xff
context.NfId = ""
context.UriScheme = models.UriScheme_HTTPS
context.SBIPort = 0
context.BindingIPv4 = ""
context.RegisterIPv4 = ""
context.HttpIPv6Address = ""
context.Name = "amf"
context.NrfUri = ""
}
// Create new AMF context
func AMF_Self() *AMFContext {
return &amfContext
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/liu-zhao234568/amf.git
git@gitee.com:liu-zhao234568/amf.git
liu-zhao234568
amf
amf
v1.0.1

搜索帮助

23e8dbc6 1850385 7e0993f3 1850385