【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 發送

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