PFCP 消息头
字节1 按位设置:
- 位1: 代表 SEID 标记- 位2: 代表 MP 标记(message priority)
- 位3-5: spare,发送者设置为0,接收将忽略
- 位6-8: 版本
字节 2 是消息类型
字节3、4是两字节的消息长度
可选项 SEID,占8字节
最后3字节序列号.
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 }
UserPlaneInformation 结构体
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
// UserPlaneInformation describe core network userplane information
type UserPlaneInformation struct {
UPNodes map[string]UPNode `yaml:"up_nodes"`
Links []UPLink `yaml:"links"`
}
UERoutingInfo 结构体
ueRoutingInfo: - SUPI: imsi-2089300007487 AN: 10.200.200.101 PathList: - DestinationIP: 60.60.0.101 UPF: !!seq - BranchingUPF - AnchorUPF1 - DestinationIP: 60.60.0.103 UPF: !!seq - BranchingUPF - AnchorUPF2
type Path struct { DestinationIP string `yaml:"DestinationIP,omitempty"` DestinationPort string `yaml:"DestinationPort,omitempty"` UPF []string `yaml:"UPF,omitempty"` } type UERoutingInfo struct { SUPI string `yaml:"SUPI,omitempty"` AN string `yaml:"AN,omitempty"` PathList []Path `yaml:"PathList,omitempty"` }
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")
}
}
}
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"
}
]
}