【5G核心网】 free5gc Network Triggered Service Request源码分析

   本文分析 free5gc Network Triggered Service Request 网络触发的业务请求流程。当网络侧需要向 UE 发出信号时(例如向 UE 发出 N1 信令,移动端应用等推送(比如视频,微信),对 PDU 会话的用户平面连接激活以传递移动端用户数据),将使用此过程。

 

1. UPF 向 SMF 发送 PFCP Sesssion Report request

    UP 功能应使用 PFCP Session Report 流程将与 PFCP 会话有关的信息报告给 CP 功能。

UPF -> SMF PFCP Session Report request
UPF->SMF PFCP Session Report request

   1.1 SMF 处理 PFCP Sesssion Report request

func HandlePfcpSessionReportRequest(msg *pfcpUdp.Message) {
	req := msg.PfcpMessage.Body.(pfcp.PFCPSessionReportRequest)

	SEID := msg.PfcpMessage.Header.SEID
	smContext := smf_context.GetSMContextBySEID(SEID)
	seqFromUPF := msg.PfcpMessage.Header.SequenceNumber

    目前只实现类型为 DLDR(Downlink Data Report)

if req.ReportType.Dldr {
	downlinkDataReport := req.DownlinkDataReport
	pdrID := downlinkDataReport.PDRID.RuleId

	if downlinkDataReport.DownlinkDataServiceInformation != nil {
		logger.PfcpLog.Warnf("PFCP Session Report Request DownlinkDataServiceInformation handling is not implemented")
	}

    如果 SM 上下文的 PDR ID 相同则发送 PFCP Session Report response 

ANUPF := smContext.Tunnel.DataPathPool.GetDefaultPath().FirstDPNode
DLPDR := ANUPF.DownLinkTunnel.PDR
if DLPDR.PDRID == pdrID {
	// TS 23.502 4.2.3.3 2b. Send Data Notification Ack, SMF->UPF
	cause.CauseValue = pfcpType.CauseRequestAccepted
	// TODO fix: SEID should be the value sent by UPF but now the SEID value is from sm context
	pfcp_message.SendPfcpSessionReportResponse(msg.RemoteAddr, cause, seqFromUPF, SEID)

    BuildPDUSessionResourceSetupRequestTransfer 函数创建 NGAP 消息,包括:

  •   UL-NGU-UP-TNLInformation
  •   PDUSessionType
  •   QosFlowSetupRequestList
N1N2消息中的NGAP

    SMF 向 AMF 发送 N1N2 请求 /ue-contexts/{ueContextId}/n1-n2-messages

SMF->AMF /ue-contexts/{ueContextId}/n1-n2-messages

2. AMF 处理 N1N2 消息

// TS23502 4.2.3.3, 4.2.4.3, 4.3.2.2, 4.3.2.3, 4.3.3.2, 4.3.7
func HandleN1N2MessageTransferRequest(request *http_wrapper.Request) *http_wrapper.Response {

	logger.ProducerLog.Infof("Handle N1N2 Message Transfer Request")

	n1n2MessageTransferRequest := request.Body.(models.N1N2MessageTransferRequest)
	ueContextID := request.Params["ueContextId"]
	reqUri := request.Params["reqUri"]

   2.1 N1N2MessageTransferProcedure 函数

// There are 4 possible return value for this function:
//   - n1n2MessageTransferRspData: if AMF handle N1N2MessageTransfer Request successfully.
//   - locationHeader: if response status code is 202, then it will return a non-empty string location header for
//     response
//   - problemDetails: if AMF reject the request due to application error, e.g. UE context not found.
//   - TransferErr: if AMF reject the request due to procedure error, e.g. UE has an ongoing procedure.
// see TS 29.518 6.1.3.5.3.1 for more details.
func N1N2MessageTransferProcedure(ueContextID string, reqUri string,
	n1n2MessageTransferRequest models.N1N2MessageTransferRequest) (
	n1n2MessageTransferRspData *models.N1N2MessageTransferRspData,
	locationHeader string, problemDetails *models.ProblemDetails,
	transferErr *models.N1N2MessageTransferError) {
  
  

   2.1.1 UE 处于 CM-IDLE 状态

    将 onGoing 设置为 Paging,BuildPaging 创建 NGAP 消息,向 RAN 发送

// Case A (UE is CM-IDLE in 3GPP access and the associated access type is 3GPP access)
// in subclause 5.2.2.3.1.2 of TS29518
if anType == models.AccessType__3_GPP_ACCESS {
	if requestData.SkipInd && n2Info == nil {
		n1n2MessageTransferRspData.Cause = models.N1N2MessageTransferCause_N1_MSG_NOT_TRANSFERRED
	} else {
		n1n2MessageTransferRspData.Cause = models.N1N2MessageTransferCause_ATTEMPTING_TO_REACH_UE
		message := context.N1N2Message{
			Request:     n1n2MessageTransferRequest,
			Status:      n1n2MessageTransferRspData.Cause,
			ResourceUri: locationHeader,
		}
		ue.N1N2Message = &message
		onGoing.Procedure = context.OnGoingProcedurePaging
		onGoing.Ppi = requestData.Ppi
		if onGoing.Ppi != 0 {
			pagingPriority = new(ngapType.PagingPriority)
			pagingPriority.Value = aper.Enumerated(onGoing.Ppi)
		}
		pkg, err := ngap_message.BuildPaging(ue, pagingPriority, false)
		if err != nil {
			logger.NgapLog.Errorf("Build Paging failed : %s", err.Error())
			return n1n2MessageTransferRspData, locationHeader, problemDetails, transferErr
		}
		ngap_message.SendPaging(ue, pkg)
	}
	// TODO: WAITING_FOR_ASYNCHRONOUS_TRANSFER
	return n1n2MessageTransferRspData, locationHeader, problemDetails, transferErr
}
AMF->AN NGAP Paging

    AMF 回复 SMF N1N2 消息,cause 设置为 ATTEMPTING_TO_REACH_UE

n1n2MessageTransferRspData, locationHeader, problemDetails, transferErr := N1N2MessageTransferProcedure(
	ueContextID, reqUri, n1n2MessageTransferRequest)

if n1n2MessageTransferRspData != nil {
	switch n1n2MessageTransferRspData.Cause {
	case models.N1N2MessageTransferCause_N1_MSG_NOT_TRANSFERRED:
		fallthrough
	case models.N1N2MessageTransferCause_N1_N2_TRANSFER_INITIATED:
		return http_wrapper.NewResponse(http.StatusOK, nil, n1n2MessageTransferRspData)
	case models.N1N2MessageTransferCause_ATTEMPTING_TO_REACH_UE:
		headers := http.Header{
			"Location": {locationHeader},
		}
		return http_wrapper.NewResponse(http.StatusAccepted, headers, n1n2MessageTransferRspData)
	}
}

 

3.  向 AMF 发送

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章