【5G核心网】free5GC SMF源码分析

PFCP 消息头

字节1 按位设置:
        - 位1: 代表 SEID 标记

        - 位2: 代表 MP 标记(message priority)

       - 位3-5: spare,发送者设置为0,接收将忽略

        - 位6-8: 版本

  字节 2 是消息类型
  字节3、4是两字节的消息长度
  可选项 SEID,占8字节
  最后3字节序列号.

【5G核心网】free5GC SMF源码分析_第1张图片

                                                         Figure 7.2.2.1-1: General format of PFCP Header                                                                 

     - if S = 0, SEID field is not present, k = 0, m = 0 and n = 5;

     - if S = 1, SEID field is present, k = 1, m = 5 and n = 13.
 

    结构体 PFCP Header

type Header struct {
	Version         uint8
	MP              uint8
	S               uint8
	MessageType     MessageType
	MessageLength   uint16
	SEID            uint64
	SequenceNumber  uint32
	MessagePriority uint8
}

 

1. PFCP Association PFCP 关联请求

    参看: https://blog.csdn.net/zhonglinzhang/article/details/107542866 第 2.1 章节

    1.1 由 SMF 向 UPF 发起 PFCP 关联请求

      根据所有配置文件定义的 UPF 发起 PFCP 关联请求,SMF PFCP 服务端端口 8805

for _, upf := range context.SMF_Self().UserPlaneInformation.UPFs {
	addr := new(net.UDPAddr)
	addr.IP = net.IP(upf.NodeID.NodeIdValue)

	addr.Port = pfcpUdp.PFCP_PORT

	logger.AppLog.Infof("Send PFCP Association Request to UPF[%s]\n", addr.String())
	message.SendPfcpAssociationSetupRequest(addr)
}

    1.1.1 SendPfcpAssociationSetupRequest 函数

    创建 body,这里发送方未 CP 功能

    - Node ID,发送方以为的标识符

    - Recovery Time Stamp,当 CP 或 CP 已经启动的时间戳

    - UP Function Features,指示 UP 功能支持的特性(UP 发送)

    - CP Function Features,指示 CP 功能支持的特性(CP 发送)

    - User Plane IP Resource Information,包含 IPv4 / IPv6,还有 TEID,用来在 UP 分配 GTP-U F-TEID(UP 发送)

func BuildPfcpAssociationSetupRequest() (pfcp.PFCPAssociationSetupRequest, error) {
	msg := pfcp.PFCPAssociationSetupRequest{}

	msg.NodeID = &context.SMF_Self().CPNodeID

	msg.RecoveryTimeStamp = &pfcpType.RecoveryTimeStamp{
		RecoveryTimeStamp: udp.ServerStartTime,
	}

	msg.CPFunctionFeatures = &pfcpType.CPFunctionFeatures{
		SupportedFeatures: 0,
	}

	return msg, nil
}

    1.1.1.1 PFCP 消息填充

    消息类型为:PFCP_ASSOCIATION_SETUP_REQUEST,S 设置为 0

message := pfcp.Message{
	Header: pfcp.Header{
		Version:        pfcp.PfcpVersion,
		MP:             0,
		S:              pfcp.SEID_NOT_PRESENT,
		MessageType:    pfcp.PFCP_ASSOCIATION_SETUP_REQUEST,
		SequenceNumber: getSeqNumber(),
	},
	Body: pfcpMsg,
}

    1.1.2 SMF 处理 PFCP Association Response

    如果原因设置为 CauseRequestAccepted 更新 UPF 信息状态为 AssociatedSetUpSuccess

func HandlePfcpAssociationSetupResponse(msg *pfcpUdp.Message) {
	req := msg.PfcpMessage.Body.(pfcp.PFCPAssociationSetupResponse)

	nodeID := req.NodeID
	if req.Cause.CauseValue == pfcpType.CauseRequestAccepted {
		if nodeID == nil {
			logger.PfcpLog.Errorln("pfcp association needs NodeID")
			return
		}

		upf := smf_context.RetrieveUPFNodeByNodeID(*req.NodeID)
		upf.UPFStatus = smf_context.AssociatedSetUpSuccess

		if req.UserPlaneIPResourceInformation != nil {
			upf.UPIPInfo = *req.UserPlaneIPResourceInformation
			logger.PfcpLog.Infof("UPF(%s)[%s] setup association", upf.NodeID.ResolveNodeIdToIp().String(), upf.UPIPInfo.NetworkInstance)
		} else {
			logger.PfcpLog.Errorln("pfcp association setup response has no UserPlane IP Resource Information")
		}
	}
}

 

2. PDU 会话建立流程

    SMF 从 AMF 接收 Nsmf_PDUSession_CreateSMContext 请求,/sm-contexts,则进入 PostSmContexts 函数处理,设置为 PDUSessionSMContextCreate 类型消息,丢进 channel 进行集中处理

    2.1 HandlePDUSessionSMContextCreate 函数

      2.1.1 SMF 创建会话管理上下文,实例化 SMContext

    - supi

    - pduSessionID

    - gpsi

    - DNn

    - SNssai

    - HplmnSnssai

    - ServingNetwork

    - AnType

    - RatType

    - UeLocation

    - OldPduSessionId

    - ServingNfId

    - SmContextStatusUri

      2.1.2 向 UDM 发起 Nudm_SubscriberDataManagement.请求 /{supi}/sm-data 步骤 4

为 UE 分配 IP 地址,PCF 选择,smContext.PCFSelection,调用 Nnrf_NFDiscovery /nf-instances 向 NRF 进行服务发现,实例化 SmPolicyContextData 并填充 Supi,PDUSessionID,Dnn,Snssai 等等。调用 /sm-policies 更新 PCF 策略配置

     2.1.3 PCF 选择 4.3.2.2.1-1 步骤 7a

     2.1.4 SM Policy /sm-policies 步骤 7b

     2.1.6 ApplySmPolicyFromDecision 函数(新增)

      应用 session rule

     2.1.7 设置拓扑 (未预先设置 UE SUPI 的配置)

     例如官方例子:

userplane_information:

  • up_nodes:
    • gNB1:
      • type: AN
      • an_ip: 192.188.2.3
    • BranchingUPF:
      • type: UPF
      • node_id: 10.200.200.102
      • up_resource_ip: 192.188.2.2
    • AnchorUPF1:
      • type: UPF
      • node_id: 10.200.200.101
      • up_resource_ip: 192.188.2.23
    • AnchorUPF2:
      • type: UPF
      • node_id: 10.200.200.103
      • up_resource_ip: 192.188.2.24
    • links:
      • A: gNB1 B: BranchingUPF
      • A: BranchingUPF B: AnchorUPF1
      • A: BranchingUPF B: AnchorUPF2

【5G核心网】free5GC SMF源码分析_第2张图片

    GenerateDataPath 终于更改了,原来写的不知道要干什么

   在这里区分预先配置和未预先配置 UE SUPI 路径

 

   2.3 SendPFCPRule

    对于首次没有 session 的情况,上行链路和下行链路 PDR (包检测规则)和 FAR (转发行为规则)

func SendPFCPRule(smContext *smf_context.SMContext, dataPath *smf_context.DataPath) {

	logger.PduSessLog.Infof("Send PFCP Rule")
	logger.PduSessLog.Infof("DataPath: ", dataPath)
	for curDataPathNode := dataPath.FirstDPNode; curDataPathNode != nil; curDataPathNode = curDataPathNode.Next() {
		pdrList := make([]*smf_context.PDR, 0, 2)
		farList := make([]*smf_context.FAR, 0, 2)
		if !curDataPathNode.HaveSession {
			if curDataPathNode.UpLinkTunnel != nil && curDataPathNode.UpLinkTunnel.PDR != nil {
				pdrList = append(pdrList, curDataPathNode.UpLinkTunnel.PDR)
				farList = append(farList, curDataPathNode.UpLinkTunnel.PDR.FAR)
			}
			if curDataPathNode.DownLinkTunnel != nil && curDataPathNode.DownLinkTunnel.PDR != nil {
				pdrList = append(pdrList, curDataPathNode.DownLinkTunnel.PDR)
				farList = append(farList, curDataPathNode.DownLinkTunnel.PDR.FAR)
			}

			pfcp_message.SendPfcpSessionEstablishmentRequest(curDataPathNode.UPF.NodeID, smContext, pdrList, farList, nil)
			curDataPathNode.HaveSession = true

    2.3.1 SendPfcpSessionEstablishmentRequest 步骤 10a

    建立 PFCP 会话建立请求到 UPF,包括 SM 上下文,PDR,FAR,BAR(目前空)

    BuildPfcpSessionEstablishmentRequestForULCL 函数主要用来实例化 PFCPSessionEstablishmentRequest,并填充 CP NodeID,CreatePDR,CreateFAR 等,

    创建的 PFCP 消息头,消息类型为 PFCP_SESSION_ESTABLISHMENT_REQUEST

func SendPfcpSessionEstablishmentRequest(upNodeID pfcpType.NodeID, ctx *context.SMContext, pdrList []*context.PDR, farList []*context.FAR, barList []*context.BAR) {
	pfcpMsg, err := BuildPfcpSessionEstablishmentRequest(upNodeID, ctx, pdrList, farList, barList)
	if err != nil {
		logger.PfcpLog.Errorf("Build PFCP Session Establishment Request failed: %v", err)
		return
	}

	message := pfcp.Message{
		Header: pfcp.Header{
			Version:         pfcp.PfcpVersion,
			MP:              1,
			S:               pfcp.SEID_PRESENT,
			MessageType:     pfcp.PFCP_SESSION_ESTABLISHMENT_REQUEST,
			SEID:            0,
			SequenceNumber:  getSeqNumber(),
			MessagePriority: 0,
		},
		Body: pfcpMsg,
	}

	upaddr := &net.UDPAddr{
		IP:   upNodeID.ResolveNodeIdToIp(),
		Port: pfcpUdp.PFCP_PORT,
	}

    2.3.2 SendPfcpSessionModificationRequest 函数

    对于已经存在的会话,修改的情况

 

3 HandlePfcpSessionEstablishmentResponse 函数

    从 UPF 收到回复请求,类型为 PFCP_SESSION_ESTABLISHMENT_RESPONSE

func HandlePfcpSessionEstablishmentResponse(msg *pfcpUdp.Message) {
	rsp := msg.PfcpMessage.Body.(pfcp.PFCPSessionEstablishmentResponse)

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

	if rsp.UPFSEID != nil {
		UPFSEID := rsp.UPFSEID
		smContext.RemoteSEID = UPFSEID.Seid
	}

   3.1 BuildGSMPDUSessionEstablishmentAccept 函数

    实例化 NAS 消息,填充 GSM 消息,设置类型为 MsgTypePDUSessionEstablishmentAccept,PDUSessionEstablishmentAccept 结构体如下

type PDUSessionEstablishmentAccept struct {
	nasType.ExtendedProtocolDiscriminator
	nasType.PDUSessionID
	nasType.PTI
	nasType.PDUSESSIONESTABLISHMENTACCEPTMessageIdentity
	nasType.SelectedSSCModeAndSelectedPDUSessionType
	nasType.AuthorizedQosRules
	nasType.SessionAMBR
	*nasType.Cause5GSM
	*nasType.PDUAddress
	*nasType.RQTimerValue
	*nasType.SNSSAI
	*nasType.AlwaysonPDUSessionIndication
	*nasType.MappedEPSBearerContexts
	*nasType.EAPMessage
	*nasType.AuthorizedQosFlowDescriptions
	*nasType.ExtendedProtocolConfigurationOptions
	*nasType.DNN
}

     3.1.1 填充 PDUSessionEstablishmentAccept 结构体

  •      PDUSessionID
  •      消息类型 MsgTypePDUSessionEstablishmentAccept
  •      PTI:0x00
  •      PDU 会话类型:这里实现为 IPv4
  •      SSC 模式,这里设置为 1
  •      SessionAMBR
  •      QOS 规则
  •     【PDU Address】
pDUSessionEstablishmentAccept.SetPDUSessionID(uint8(smContext.PDUSessionID))
pDUSessionEstablishmentAccept.SetMessageType(nas.MsgTypePDUSessionEstablishmentAccept)
pDUSessionEstablishmentAccept.SetExtendedProtocolDiscriminator(nasMessage.Epd5GSSessionManagementMessage)
pDUSessionEstablishmentAccept.SetPTI(0x00)
pDUSessionEstablishmentAccept.SetPDUSessionType(smContext.SelectedPDUSessionType)
pDUSessionEstablishmentAccept.SetSSCMode(1)
pDUSessionEstablishmentAccept.SessionAMBR = nasConvert.ModelsToSessionAMBR(smContext.SessionRule.AuthSessAmbr)
pDUSessionEstablishmentAccept.SessionAMBR.SetLen(uint8(len(pDUSessionEstablishmentAccept.SessionAMBR.Octet)))

   3.2 BuildPDUSessionResourceSetupRequestTransfer 函数

    实例化 PDUSessionResourceSetupRequestTransfer 对象,主要包含的是 IE 信息元素

func BuildPDUSessionResourceSetupRequestTransfer(ctx *SMContext) (buf []byte, err error) {
	var UpNode = ctx.Tunnel.UpfRoot.UPF
	var teidOct = make([]byte, 4)
	binary.BigEndian.PutUint32(teidOct, ctx.Tunnel.UpfRoot.UpLinkTunnel.TEID)

	resourceSetupRequestTransfer := ngapType.PDUSessionResourceSetupRequestTransfer{}

    PDUSessionResourceSetupRequestTransferIEs 结构定义如下:

type PDUSessionResourceSetupRequestTransferIEs struct {
   Id          ProtocolIEID
   Criticality Criticality
   Value       PDUSessionResourceSetupRequestTransferIEsValue `aper:"openType,referenceFieldName:Id"`
}

    3.2.1 UL NG-U UP TNL Information

    3.2.2 PDU Session Type

    3.2.3 QoS Flow Setup Request List,use Default 5qi, arp

   3.3 实例化 N1N2MessageTransferRequest

     官方 3GPP 提供的 openapi 生成,包括 PDU 会话 ID,包括 N1,N2 消息,N2 信息包括 Snssai

n1n2Request := models.N1N2MessageTransferRequest{}
n1n2Request.JsonData = &models.N1N2MessageTransferReqData{
	PduSessionId: smContext.PDUSessionID,
	N1MessageContainer: &models.N1MessageContainer{
		N1MessageClass:   "SM",
		N1MessageContent: &models.RefToBinaryData{ContentId: "GSM_NAS"},
	},
	N2InfoContainer: &models.N2InfoContainer{
		N2InformationClass: models.N2InformationClass_SM,
		SmInfo: &models.N2SmInformation{
			PduSessionId: smContext.PDUSessionID,
			N2InfoContent: &models.N2InfoContent{
				NgapIeType: models.NgapIeType_PDU_RES_SETUP_REQ,
				NgapData: &models.RefToBinaryData{
					ContentId: "N2SmInformation",
				},
			},
			SNssai: smContext.Snssai,
		},
	},
}
n1n2Request.BinaryDataN1Message = smNasBuf
n1n2Request.BinaryDataN2Information = n2Pdu

    3.4 SMF 发送消息到 AMF

     /ue-contexts/{ueContextId}/n1-n2-messages

 

 

   SMF 配置文件

info:
  version: 1.0.0
  description: AMF initial local configuration

configuration:
  amfName: AMF
  ngapIpList:
    - 127.0.0.10
  sbi:
    scheme: http
    ipv4Addr: 127.0.0.1
    port: 29518
  serviceNameList:
    - namf-comm
    - namf-evts
    - namf-mt
    - namf-loc
    - namf-oam
  servedGuamiList:
    - plmnId:
        mcc: 208
        mnc: 93
      amfId: cafe00
  supportTaiList:
    - plmnId:
        mcc: 208
        mnc: 93
      tac: 1
  plmnSupportList:
    - plmnId:
        mcc: 208
        mnc: 93
      snssaiList:
        - sst: 1
          sd: 010203
        - sst: 1
          sd: 112233
  supportDnnList:
    - internet
  nrfUri: http://localhost:29510
  security:
    integrityOrder:
      - NIA2
      - NIA0
    cipheringOrder:
      - NEA2
      - NEA0
  networkName:
    full: free5GC
    short: free
  t3502: 720
  t3512: 3600
  non3gppDeregistrationTimer: 3240

    NRF 中注册的 SMF

{
    "_id": ObjectId("5f1a9c2364d2e538cb1309d4"),
    "ipv4Addresses": [
        "smf"
    ],
    "smfInfo": {
        "sNssaiSmfInfoList": null
    },
    "nfServices": [
        {
            "serviceInstanceId": "e1b3436a-f9b9-4820-b075-d16fb4814ddansmf-pdusession",
            "serviceName": "nsmf-pdusession",
            "versions": [
                {
                    "expiry": "2020-07-24T08:30:27Z",
                    "apiVersionInUri": "v1",
                    "apiFullVersion": "https://smf:29502/nsmf-pdusession/v1"
                }
            ],
            "scheme": "https",
            "nfServiceStatus": "REGISTERED",
            "apiPrefix": "https://smf:29502"
        },
        {
            "serviceName": "nsmf-event-exposure",
            "versions": [
                {
                    "apiVersionInUri": "v1",
                    "apiFullVersion": "https://smf:29502/nsmf-pdusession/v1",
                    "expiry": "2020-07-24T08:30:27Z"
                }
            ],
            "scheme": "https",
            "nfServiceStatus": "REGISTERED",
            "apiPrefix": "https://smf:29502",
            "serviceInstanceId": "e1b3436a-f9b9-4820-b075-d16fb4814ddansmf-event-exposure"
        }
    ],
    "nfInstanceId": "e1b3436a-f9b9-4820-b075-d16fb4814dda",
    "nfType": "SMF",
    "nfStatus": "REGISTERED",
    "plmnList": [
        {
            "mcc": "208",
            "mnc": "93"
        }
    ]

你可能感兴趣的:(5G)