free5gc AMF 源码分析
结构体 Sbi
type Sbi struct {
Scheme string `yaml:"scheme"`
RegisterIPv4 string `yaml:"registerIPv4,omitempty"` // IP that is registered at NRF.
// IPv6Addr string `yaml:"ipv6Addr,omitempty"`
BindingIPv4 string `yaml:"bindingIPv4,omitempty"` // IP used to run the server in the node.
Port int `yaml:"port,omitempty"`
}
1. AMF 程序初始化以及启动
1.1 启动 httpcallback 服务
httpcallback.AddService(router),实现在 afm/httpcallback 中,URL 以及 handler 如下所示:
Name | Pattern | HandlerFunc |
| | |
| | |
| | |
| | |
| | |
1.2 根据配置文件中的服务列表启动服务
serviceNameList: - namf-comm - namf-evts - namf-mt - namf-loc - namf-oam
for _, serviceName := range factory.AmfConfig.Configuration.ServiceNameList {
switch models.ServiceName(serviceName) {
case models.ServiceName_NAMF_COMM:
communication.AddService(router)
case models.ServiceName_NAMF_EVTS:
eventexposure.AddService(router)
case models.ServiceName_NAMF_MT:
mt.AddService(router)
case models.ServiceName_NAMF_LOC:
location.AddService(router)
}
}
1.3 初始化 amf 上下文
通过配置文件,较简单,amf 监听端口为 29518
self := context.AMF_Self()
util.InitAmfContext(self)
addr := fmt.Sprintf("%s:%d", self.HttpIPv4Address, self.HttpIpv4Port)
1.4 根据 ngap IP 列表建立 SCTP 服务
TCP是以字节为单位传输的,SCTP是以数据块为单位传输的
TCP通常是单路径传输,SCTP可以多路径传输
for _, ngapAddr := range self.NgapIpList {
sctpListener = sctp.Server(ngapAddr)
}
1.4.1 SCTP Server
每次新建立的连接,将消息设置为 EventNGAPAcceptConn 丢进 channel 进行处理,丢进 channel 处理, 处理函数 NewAmfRan 则实例化 AmfRan, 存贮在 AmfRanPool 中,key 为对端 IP 地址
forwardData 函数根据接收到的数据包,统一设置类型为 EventNGAPMessage,丢进 chanel,等待函数 ngap.Dispatch(msg.NgapAddr, msg.Value.([]byte)) 处理
func Server(addrStr string) (listener *SCTPListener) {
ln := ngapSctp.Server(addrStr)
listener = &SCTPListener{
ln: ln,
conn: make(map[string]net.Conn),
}
go listener.forwardData()
// Wait for accept connection
go func(l *SCTPListener) {
for {
conn, err := ngapSctp.Accept(ln)
if err != nil {
logger.NgapLog.Warn(err.Error())
continue
}
logger.NgapLog.Infof("[AMF] NGAP SCTP Accept from: %s", conn.RemoteAddr().String())
// send connection to amf handler
msg := amf_message.HandlerMessage{}
msg.Event = amf_message.EventNGAPAcceptConn
msg.Value = conn
amf_message.SendMessage(msg)
l.mtx.Lock()
l.conn[conn.RemoteAddr().String()] = conn
l.mtx.Unlock()
go ngapSctp.Start(conn, readChan)
// put connection into global conn
// SctpConnection = append(SctpConnection, conn)
}
}(listener)
return
}
1.5 核心处理流程
实现在 amf/handler/hander.go
go handler.Handle()
1.6 注册到 NRF
amf id 组成 regionId: 16bits, setId: 10bits, ptrId: 6bits <AMF Identifier> = <AMF Region ID><AMF Set ID><AMF Pointer>
调用 NRF Nnrf_NFManagement,注册
// Register to NRF
profile, err := consumer.BuildNFInstance(self)
if err != nil {
initLog.Error("Build AMF Profile Error")
}
_, self.NfId, _ = consumer.SendRegisterNFInstance(self.NrfUri, self.NfId, profile)
2. RAN 发起的 NGSetupRequest 消息
NG Setup 流程用来交换 NG-RAN 节点和 AMF 在 NG-C 接口上正确互操作所需的应用程序数据,该程序应是 TNL 关联开始运行后触发的第一个 NGAP 程序。该过程使用 非UE 相关的信令。
2.1 NGAP 结构体
type NGAPPDU struct {
Present int
InitiatingMessage *InitiatingMessage
SuccessfulOutcome *SuccessfulOutcome
UnsuccessfulOutcome *UnsuccessfulOutcome
}
Present 设置为 NGAPPDUPresentInitiatingMessage
2.2 InitiatingMessage 结构体
type InitiatingMessage struct {
ProcedureCode ProcedureCode
Criticality Criticality
Value InitiatingMessageValue `aper:"openType,referenceFieldName:ProcedureCode"`
}
initiatingMessage ProcedureCode 设置为 ProcedureCodeNGSetup InitiatingMessagePresentNGSetupRequest

当使用 NG-RAN 时,N2 参数包括所选的 PLMN ID、位置信息和与 Ue 所在小区相关的身份、Ue 上下文请求,该请求指明需要在 NG-RAN 中设置一个包含安全信息的 Ue 上下文 。也包括建立的原因,
如果可用的话,才提供请求的 NSSAI 映射
如果 UE 注册类型指明是定期注册更新,则省略 4 - 19 步骤
如果 UE 包含首选的网络行为
2.3 AMF 接收 NGSetupRequest 消息
根据 NGAPPDUPresentInitiatingMessage 和 ProcedureCodeNGSetup 定位到 HandleNGSetupRequest
func HandleNGSetupRequest(ran *context.AmfRan, message *ngapType.NGAPPDU) {
var globalRANNodeID *ngapType.GlobalRANNodeID
var rANNodeName *ngapType.RANNodeName
var supportedTAList *ngapType.SupportedTAList
var pagingDRX *ngapType.PagingDRX
var cause ngapType.Cause
主要是验证信息,如果验证通过则 SendNGSetupResponse,失败则调用 SendNGSetupFailure
如果成功则发送 NGAPPDUPresentSuccessfulOutcome,类型为 SuccessfulOutcomePresentNGSetupResponse,包括 IE:AMFName,ServedGUAMIList,relativeAMFCapacity,pLMNSupportList