Share
Embed
Transcript
45 slides
-
Yoshiyuki Kurauchi / ENOG63 Meeting (2020.6.26) PFCP in Go 3GPPྲྀCUPSΛGoͰ࣮͢Δ
#4G #5G #CUPS #PFCP #ϓϩτί ϧLOVE #3GPP͓ͦΖ͍͠ࢠ #ΘΓ ͱϓϩάϥϛϯάدΓ #Go #Gopher ͔Θ͍͍ #͓खΘΒ͔ʹ -
ࣗݾհͱ͔ #ฏݩେࡕੜ·Ε #ฌݿ #ಸྑ #ੴ #ਆಸ #ࠓϤίϋϚ #͘ւ֎ཱྀߦ ͍ͨ͠ #Ϗʔϧ
#ΟεΩʔ #ຊञ # ϩοΫ #ϝλϧ #ϩʔυόΠΫ -
ࣗݾհ • ৬ྺ • 2013.02 - 2015.01: SES (NWӡ༻ɺݕূΒ) •
2015.02 - 2018.10: ࣾܥ (ςϨίϜؔ࿈ɾαʔϏε୲) • 2018.12 - Now: LTE over IPͳձࣾ (։ൃΛத৺ʹ͍Ζ͍Ζ) • ݴޠ • Go, Python, C/C++, Swift, etc. • ΤσΟλVSCode https://wmnsk.com/about/ Twitter: @wmnskdmms GitHub: @wmnsk -
OSS׆ಈͳͲ • ࣗ࡞ϥΠϒϥϦ (جຊGo) • ओʹNWϓϩτίϧ • 3G > 4G
> 5G… ϨΨγʔେ͖ʂ • CNF Testbedʹgo-gtp࠾༻ • ίϯτϦϏϡʔγϣϯྫ • Wireshark • Linux kernel driver (GTP-U) ͳͲ https://wmnsk.com/posts/20200116_gw-tester/ https://github.com/wmnsk -
CUPSͱʁ • Control and User Plane Separation • Rel14(2017): 4G/LTEظ
ʙ Rel16(2020.4): 5GऔΓࠐΜͰઈࢍංେԽத • 4GͰ్த͔Βಋೖ • 5G͔ΒωΠςΟϒ -
CUPSͱʁ • ༻ޠ • CP/UP function: C-Planeଆϊʔυ / U-Planeଆϊʔυ •
Association: ϊʔυؒʹ͓͚ΔϐΞϦϯά • Session: ݸผͷ੍ޚద༻୯Ґ • Rule: ੍ޚϧʔϧ (ޙड़) CP function UP function ⚠ ҎޙɺUP functionΛʑUPFͱུ͠·͕͢ɺ 5Gͷϊʔυͷ͜ͱͰ͋Γ·ͤΜɻ -
CUPSͱʁ • ༻ޠ • CP/UP function: C-Planeଆϊʔυ / U-Planeଆϊʔυ •
Association: ϊʔυؒʹ͓͚ΔϐΞϦϯά • Session: ݸผͷ੍ޚద༻୯Ґ • Rule: ੍ޚϧʔϧ (ޙड़) Association -
CUPSͱʁ • ༻ޠ • CP/UP function: C-Planeଆϊʔυ / U-Planeଆϊʔυ •
Association: ϊʔυؒʹ͓͚ΔϐΞϦϯά • Session: ݸผͷ੍ޚద༻୯Ґ • Rule: ੍ޚϧʔϧ (ޙड़) Session -
PFCPͱʁ • Packet Forwarding Control Protocol ͷ͜ͱ • CPFͱUPFͷίϛϡχέʔγϣϯํ๏ɾखଓ͖Λنఆ •
ؔ࿈Spec: TS 23.214(Architecture), TS 29.244(Protocol) • ॳEPCͰΘΕΔI/F໊͔Β”Sx”ͱݺΕ͓ͯΓɺະͩʹͦͷ໊͕ࢄ ݟ͞ΕΔ -
• جຊγʔέϯε • §6.2 PFCP Node Related Procedures • AssociationΛுͬͨΓ͢Δ
• §6.3 PFCP Session Related Procedures • ηογϣϯɺ੍ޚϧʔϧΛཧ͢Δ PFCPͱʁ -
• جຊγʔέϯε • §6.2 PFCP Node Related Procedures • Heartbeat
Procedure • Load/Overload Control Procedure • PFD Management Procedure • Association Setup/Update/Release Procedure • Node Report Procedure PFCPͱʁ CPF UPF Association Setup Request Association Setup Response Heartbeat Request/Response Association Release Request Association Release Response (Session-related messages) -
• جຊγʔέϯε • §6.2 PFCP Node Related Procedures • Heartbeat
Procedure • Load/Overload Control Procedure • Overload Control Procedure • PFD Management Procedure • Association Setup/Update/Release • Node Report Procedure PFCPͱʁ CPF UPF Association Setup Request Association Setup Response Heartbeat Request/Response Association Release Request Association Release Response (Session-related messages) -
• جຊγʔέϯε • §6.3 PFCP Session Related Procedures • Session
… Procedure • Establishment • Modification • Deletion • Report PFCPͱʁ CPF UPF Session Establishment Request Session Establishment Response Session Modification Request/Response Session Deletion Request Session Deletion Response (enforcing rules) Association -
• جຊγʔέϯε • §6.3 PFCP Session Related Procedures • Sessio
• Establishment • Modification • Deletion • Report PFCPͱʁ CPF UPF Session Establishment Request Session Establishment Response Session Modification Request/Response Session Deletion Request Session Deletion Response (enforcing rules) Association -
PFCPͱʁ • ͜͜ͰύέοτΛ͝ཡ͍ͩ͘͞ • Session Establishment Request • Create PDR
• … • PDI • … • Create FAR • … https://gist.github.com/wmnsk/3e8073d3404d8eb36f33300b7a8babe5 -
PFCPͱʁ • ͜͜ͰύέοτΛ͝ཡ͍ͩ͘͞ • Session Establishment Request • Create PDR
• … • PDI • … • Create FAR • … https://gist.github.com/wmnsk/3e8073d3404d8eb36f33300b7a8babe5 -
PFCPͱʁ • ੍ޚॲཧ • Packet Detection Rule • Forwarding Action
Rule • Usage Reporting Rule • QoS Enforcement Rule • Buffering Action Rule • Multi-Access Rule • େ·͔ͳྲྀΕ • PDRʹج͍ͮͯύέοτΛৼΓ͚Δ • సૹઌΛܾΊΔ (υϩοϓͱ͔͋Δ) • CPF͕FARͰࢦࣔ͢Δ • UPFଆʹ͋ΔPredefinedϧʔϧΛ͏ • ͦͷଞϧʔϧΛద༻͢Δ • Usage ReportɺQoS EnforcementͳͲ -
PFCPͱʁ • ੍ޚॲཧ • Packet Detection Rule • Forwarding Action
Rule • Usage Reporting Rule • QoS Enforcement Rule • Buffering Action Rule • Multi-Access Rule • ύέοτΛྨ͢ΔϧʔϧͷΑ͏ͳͷ • Outer (GTP-Uϔομ) / InnerͲͪΒݟΔ • GTPͷTEID • Flow Description ͳͲ • PDR͕ܾ·ΔͱɺFAR, URR, QER, MAR Ұҙʹܾ·Δ -
PFCPͱʁ • ੍ޚॲཧ • Packet Detection Rule • Forwarding Action
Rule • Usage Reporting Rule • QoS Enforcement Rule • Buffering Action Rule • Multi-Access Rule • సૹؔ࿈ͷϧʔϧ • Drop, Forward, Buffer, DuplicateͳͲɺUPF ଆ͕औΔ͖ΞΫγϣϯΛܾΊΔ • Header EnrichmentͳΜ͔ʂ -
PFCPͱʁ • ੍ޚॲཧ • Packet Detection Rule • Forwarding Action
Rule • Usage Reporting Rule • QoS Enforcement Rule • Buffering Action Rule • Multi-Access Rule • Usage Reporting Ruleɿ • ར༻ঢ়گΛͲ͏Χϯτ͢Δ͔ • ͲͷλΠϛϯάͰϨϙʔτ͢Δ͔ ͳͲ • QoS Enforcement Ruleɿ • ଳҬ੍ޚ (MBR/GBR, Packet rate) • τϥϑΟοΫϚʔΩϯά ͳͲ -
PFCPͱʁ • ੍ޚॲཧ • Packet Detection Rule • Forwarding Action
Rule • Usage Reporting Rule • QoS Enforcement Rule • Buffering Action Rule • Multi-Access Rule • ׂѪ͠·͢ • ࡉׂ͔͍ʹɺ໘ന͘ͳ͍ͷͰ • ͦͯ͠ࢲ͕ͪΌΜͱΘ͔ͬͯͳ͍ͷͰ • ͦΕͧΕɺTS 29.244 5.2.4, 5.2.7Λࢀর • ͋ͱSRR(Session Reporting Rule / 5.2.8)ͳ Μ͔͋Γ·͢ -
go-pfcp: PFCP implementation in Golang • PFCPΛGoϓϩάϥϜ͔Βѻ͏ͨΊͷϥΠϒϥϦ • Message /
IEͷϑΥʔϚοτ • ͔ΜͨΜʹύέοτΛ࡞Δ͜ͱ͕Ͱ͖Δ • TS 29.244 V16.3.1(2020-04) ࣌ͷͷ࣮ͯ͢ࡁΈ (ͨͿΜ) • Association / SessionΛखܰʹѻ͏ͨΊͷAPI • ଓ͢ΔͨΊͷؔϐΞͷࣗಈཧͳͲ • Ӷҙ࣮தɾɾɾ https://github.com/wmnsk/go-pfcp -
go-pfcp: PFCP implementation in Golang • ͳͥ࡞ͬͨͷ͔ • ͨͩͷझຯ •
·ͩSpec͕ൺֱతബ͔ͬͨͷͰ https://github.com/wmnsk/go-pfcp -
go-pfcp: PFCP implementation in Golang • ͍ํ1: ϝοηʔδͷΤϯίʔυ asr :=
message.NewAssociationSetupRequest( ie.NewNodeID("", "", "go-pfcp.epc.3gppnetwork.org"), ie.NewRecoveryTimeStamp(time.Date(2019, time.January, 1, 0, 0, 0, 0, time.UTC)), ie.NewUPFunctionFeatures(0x01, 0x02), ie.NewAlternativeSMFIPAddress(net.ParseIP("127.0.0.1"), net.ParseIP("2001::1")), ie.NewSMFSetID("go-pfcp.epc.3gppnetwork.org"), ie.NewClockDriftControlInformation( ie.NewTimeOffsetThreshold(10*time.Second), ), // … ) b, err := asr.Marshal() // serializes req into []byte n, err := udpConn.WriteTo(b, raddr) // sends serialized req over UDP -
go-pfcp: PFCP implementation in Golang • ͍ํ1: ϝοηʔδͷΤϯίʔυ asr :=
message.NewAssociationSetupRequest( ie.NewNodeID("", "", "go-pfcp.epc.3gppnetwork.org"), ie.NewRecoveryTimeStamp(time.Date(2019, time.January, 1, 0, 0, 0, 0, time.UTC)), ie.NewUPFunctionFeatures(0x01, 0x02), ie.NewAlternativeSMFIPAddress(net.ParseIP("127.0.0.1"), net.ParseIP("2001::1")), ie.NewSMFSetID("go-pfcp.epc.3gppnetwork.org"), ie.NewClockDriftControlInformation( ie.NewTimeOffsetThreshold(10*time.Second), ), // … ) b, err := asr.Marshal() // serializes req into []byte n, err := udpConn.WriteTo(b, raddr) // sends serialized req over UDP શͯͷmessage / IEͷίϯετϥΫλ -
go-pfcp: PFCP implementation in Golang • ͍ํ1: ϝοηʔδͷΤϯίʔυ asr :=
message.NewAssociationSetupRequest( ie.NewNodeID("", "", "go-pfcp.epc.3gppnetwork.org"), ie.NewRecoveryTimeStamp(time.Date(2019, time.January, 1, 0, 0, 0, 0, time.UTC)), ie.NewUPFunctionFeatures(0x01, 0x02), ie.NewAlternativeSMFIPAddress(net.ParseIP("127.0.0.1"), net.ParseIP("2001::1")), ie.NewSMFSetID("go-pfcp.epc.3gppnetwork.org"), ie.NewClockDriftControlInformation( ie.NewTimeOffsetThreshold(10*time.Second), ), // … ) b, err := asr.Marshal() // serializes req into []byte n, err := udpConn.WriteTo(b, raddr) // sends serialized req over UDP ֤छIEͷ࣋ͭͱGoͷܕ͕ରԠ (Ͱ͖Δ͚ͩ) ϓϦϛςΟϒ͚ͩͰͳ͘time.Timenet.IPͳͲ -
go-pfcp: PFCP implementation in Golang • ͍ํ1: ϝοηʔδͷΤϯίʔυ asr :=
message.NewAssociationSetupRequest( ie.NewNodeID("", "", "go-pfcp.epc.3gppnetwork.org"), ie.NewRecoveryTimeStamp(time.Date(2019, time.January, 1, 0, 0, 0, 0, time.UTC)), ie.NewUPFunctionFeatures(0x01, 0x02), ie.NewAlternativeSMFIPAddress(net.ParseIP("127.0.0.1"), net.ParseIP("2001::1")), ie.NewSMFSetID("go-pfcp.epc.3gppnetwork.org"), ie.NewClockDriftControlInformation( ie.NewTimeOffsetThreshold(10*time.Second), ), // … ) b, err := asr.Marshal() // serializes req into []byte n, err := udpConn.WriteTo(b, raddr) // sends serialized req over UDP []byteܕʹγϦΞϥΠζͯ͠ૹ৴ -
go-pfcp: PFCP implementation in Golang • ͍ํ1: ϝοηʔδͷΤϯίʔυ asr :=
message.NewAssociationSetupRequest( ie.NewNodeID("", "", "go-pfcp.epc.3gppnetwork.org"), ie.NewRecoveryTimeStamp(time.Date(2019, time.January, 1, 0, 0, 0, 0, time.UTC)), ie.NewUPFunctionFeatures(0x01, 0x02), ie.NewAlternativeSMFIPAddress(net.ParseIP("127.0.0.1"), net.ParseIP("2001::1")), ie.NewSMFSetID("go-pfcp.epc.3gppnetwork.org"), ie.NewClockDriftControlInformation( ie.NewTimeOffsetThreshold(10*time.Second), ), // … ) b, err := asr.Marshal() // serializes req into []byte n, err := udpConn.WriteTo(b, raddr) // sends serialized req over UDP ςετίʔυ͕ࢀߟʹͳΓ·͢ https://github.com/wmnsk/go-pfcp/blob/master/message/association-setup-request_test.go -
go-pfcp: PFCP implementation in Golang • ͍ํ2: ϝοηʔδͷσίʔυ msg, err
:= message.Unmarshal(b) asr, ok := msg.(*messages.AssociationSetupRequest) // single value IE: "go-pfcp.epc.3gppnetwork.org" in string field := asr.NodeID // accesses to a field named NodeID in AssociationSetupRequest nodeID, err := field.NodeID() // retrieves value in Go-friendly type // flags: BUCP bit is set to 1 if asr.UPFunctionFeatures.HasBUCP() { … } // complex: returns a struct named XyzFields fields, err := AlternativeSMFIPAddress() // AlternativeSMFIPAddressFields struct v4 := fields.IPv4Address // 127.0.0.1 in net.IP v6 := fields.IPv6Address // 2001::1 in net.IP -
go-pfcp: PFCP implementation in Golang • ͍ํ2: ϝοηʔδͷσίʔυ msg, err
:= message.Unmarshal(b) asr, ok := msg.(*messages.AssociationSetupRequest) // single value IE: "go-pfcp.epc.3gppnetwork.org" in string field := asr.NodeID // accesses to a field named NodeID in AssociationSetupRequest nodeID, err := field.NodeID() // retrieves value in Go-friendly type // flags: BUCP bit is set to 1 if asr.UPFunctionFeatures.HasBUCP() { … } // complex: returns a struct named XyzFields fields, err := AlternativeSMFIPAddress() // AlternativeSMFIPAddressFields struct v4 := fields.IPv4Address // 127.0.0.1 in net.IP v6 := fields.IPv6Address // 2001::1 in net.IP []byteΛmessage.MessageΠϯλʔϑΣΠεʹ Unmarshal → ಛఆͷϝοηʔδܕʹassert -
go-pfcp: PFCP implementation in Golang • ͍ํ2: ϝοηʔδͷσίʔυ msg, err
:= message.Unmarshal(b) asr, ok := msg.(*messages.AssociationSetupRequest) // single value IE: "go-pfcp.epc.3gppnetwork.org" in string field := asr.NodeID // accesses to a field named NodeID in AssociationSetupRequest nodeID, err := field.NodeID() // retrieves value in Go-friendly type // flags: BUCP bit is set to 1 if asr.UPFunctionFeatures.HasBUCP() { … } // complex: returns a struct named XyzFields fields, err := AlternativeSMFIPAddress() // AlternativeSMFIPAddressFields struct v4 := fields.IPv4Address // 127.0.0.1 in net.IP v6 := fields.IPv6Address // 2001::1 in net.IP AssociationSetupRequestͷϑΟʔϧυʹ ΞΫηε (͜ͷ࣌Ͱ*ie.IEܕ) -
go-pfcp: PFCP implementation in Golang • ͍ํ2: ϝοηʔδͷσίʔυ msg, err
:= message.Unmarshal(b) asr, ok := msg.(*messages.AssociationSetupRequest) // single value IE: "go-pfcp.epc.3gppnetwork.org" in string field := asr.NodeID // accesses to a field named NodeID in AssociationSetupRequest nodeID, err := field.NodeID() // retrieves value in Go-friendly type // flags: BUCP bit is set to 1 if asr.UPFunctionFeatures.HasBUCP() { … } // complex: returns a struct named XyzFields fields, err := AlternativeSMFIPAddress() // AlternativeSMFIPAddressFields struct v4 := fields.IPv4Address // 127.0.0.1 in net.IP v6 := fields.IPv6Address // 2001::1 in net.IP *ie.IEܕ͔Βɺཉ͍͠IEͷΛऔΓग़͢ (ฦΓͷܕϝιου͝ͱʹҟͳΔ) ϑϥάࣗಈผ -
go-pfcp: PFCP implementation in Golang • ͍ํ2: ϝοηʔδͷσίʔυ msg, err
:= message.Unmarshal(b) asr, ok := msg.(*messages.AssociationSetupRequest) // single value IE: "go-pfcp.epc.3gppnetwork.org" in string field := asr.NodeID // accesses to a field named NodeID in AssociationSetupRequest nodeID, err := field.NodeID() // retrieves value in Go-friendly type // flags: BUCP bit is set to 1 if asr.UPFunctionFeatures.HasBUCP() { … } // complex: returns a struct named XyzFields fields, err := AlternativeSMFIPAddress() // AlternativeSMFIPAddressFields struct v4 := fields.IPv4Address // 127.0.0.1 in net.IP v6 := fields.IPv6Address // 2001::1 in net.IP ϑϥάͷྨɺHasSomeBit()ͰऔΓग़ͤΔ -
go-pfcp: PFCP implementation in Golang • ͍ํ2: ϝοηʔδͷσίʔυ msg, err
:= message.Unmarshal(b) asr, ok := msg.(*messages.AssociationSetupRequest) // single value IE: "go-pfcp.epc.3gppnetwork.org" in string field := asr.NodeID // accesses to a field named NodeID in AssociationSetupRequest nodeID, err := field.NodeID() // retrieves value in Go-friendly type // flags: BUCP bit is set to 1 if asr.UPFunctionFeatures.HasBUCP() { … } // complex: returns a struct named XyzFields fields, err := AlternativeSMFIPAddress() // AlternativeSMFIPAddressFields struct v4 := fields.IPv4Address // 127.0.0.1 in net.IP v6 := fields.IPv6Address // 2001::1 in net.IP ෳࡶͳߏ(ෳ)Λ࣋ͭIEͰɺstructΛฦ͢ (ͦͷதʹ֤͕ೖ͍ͬͯΔ) -
go-pfcp: PFCP implementation in Golang • ͍ํ2: ϝοηʔδͷσίʔυ msg, err
:= message.Unmarshal(b) asr, ok := msg.(*messages.AssociationSetupRequest) // single value IE: "go-pfcp.epc.3gppnetwork.org" in string field := asr.NodeID // accesses to a field named NodeID in AssociationSetupRequest nodeID, err := field.NodeID() // retrieves value in Go-friendly type // flags: BUCP bit is set to 1 if asr.UPFunctionFeatures.HasBUCP() { … } // complex: returns a struct named XyzFields fields, err := AlternativeSMFIPAddress() // AlternativeSMFIPAddressFields struct v4 := fields.IPv4Address // 127.0.0.1 in net.IP v6 := fields.IPv6Address // 2001::1 in net.IP ϑΟʔϧυ͕ົʹଟ͍IEͷྫ (ωʔϛϯά͕ϠέΫιʹͳΓ͕ͪ) -
go-pfcp: PFCP implementation in Golang • ͍ํ3: Association / Sessionͷཧ
(ԾσβΠϯ / ະ࣮) // Client conn, err := pfcp.Dial(…) assoc, err := conn.SetupAssociation(…) session, err := assoc.EstablishSession(…) // Server conn, err := pfcp.ListenAndServe(…) assoc, err := conn.GetAssociationByAAA(…) session, err := assoc.GetSessionByBBB(…) -
go-pfcp: PFCP implementation in Golang • ͭΒ͔ͬͨ͜ͱ1: ϓϩτίϧࣗମ͕݁ߏ৽͍͠ • Specͷߋ৽༰͕͙͍͑
• IE͕ͨ͘͞Μ૿͑ͨΓ͢Δ • ·ͩCR͕ੵ͍ͬͯΔ • WiresharkཔΈ࡞ઓ͕͑ͳ͍ • ࠷৽༷ʹ͍͍͍ͭͯͳ͍(ະ࣮) • ͨ·ʹόά͕͋Δ(Ϣʔβ͕গͳ͍) https://code.wireshark.org/review/q/author:+Yoshiyuki+Kurauchi -
go-pfcp: PFCP implementation in Golang • ͭΒ͔ͬͨ͜ͱ2: ༷ࣗମʹϫφ͕͋Δ • F-TEID
v.s. F-SEID: Flagsͷॱং • ·͍͊ͭͷ͜ͱͰ͕͢ -
go-pfcp: PFCP implementation in Golang • ࠓޙͷํ • Association /
SessionཧAPIͷ • αϯϓϧΛॆ࣮ͤ͞Δ • go-gtpͱΈ߹Θͤͯ؆қσϞϊʔυΛͭ͘Δ • GW TesterʹCUPSಋೖͪ͠Ό͏͔ʁ ͳΜ͔Star͕ ૿͑࢝Ίͨ ENOGͷ CfPక ೩͑ਚ͖͍ͯΔ