wmnsk / go-pfcp Goto Github PK
View Code? Open in Web Editor NEWPFCP (Packet Forwarding Control Protocol) in pure Go.
License: MIT License
PFCP (Packet Forwarding Control Protocol) in pure Go.
License: MIT License
Hi,
Many thanks for the last fixes and merge.
Looking further, I have a couple more observations:
1/ In f-teid.go at line 215 (v0.0.8) where the CH bit is set, I don't believe there is meant to be an IP address (v4 or v6) expected. If the IPv4 or IPv6 bit is set then that means that the UPF should allocate/choose an IP address, not that one is provided in this message.
2/ In ie.go UnmarshalBinary(), I believe:
if i.IsVendorSpecific() && l >= 6 {
i.EnterpriseID = binary.BigEndian.Uint16(b[4:6])
offset += 2
}
should be
if i.IsVendorSpecific() && l >= 6 {
i.EnterpriseID = binary.BigEndian.Uint16(b[4:6])
offset += 2
i.Length -= 2
}
Otherwise it panics lower down because the slice upper range is out of bounds.
Many thanks
I'm trying through your library to mount a session on the travelping UPF but it can't read Network Instance IE. when i asked them they told me it was related to the encoding (your IE instance is encoded as a DNN name while theirs is encoded as an APN name).
My question is if it would be possible to adapt your Network Instance IE?
Thanks in advance
here his the full upg-travelping response:
Network Instance IE encoding is wrong. The value is encoded as DNN name, but UPG expects a APN name there.
TS 29.244 is very confusing on the details of how Network Instance needs to be encoded. It states that APN is not encoded as FQDN string, that implies the same encoding as in the GTP APN IE is used. The specification is silent about how a DNN is encoded into that IE. That has lead some implementations to encode DNN's as plain binary (FQDN with dots in there, no length indicators).
UPG only understands APN encoding at the moment.
Hi,
Most IEs in 29.244 are optional or conditional.
But from what I can see, the functions such as NewPDI() expect all parameters to be present and non-nil.
If any parmeter is nil, eg to indicate that the application doesn't wish to specify that parm, then the code fails within ie.newGroupedIE() because it tries to dereference pointers at line 563, without checking for nil ones, as it ranges through the provided child IEs, some of which will be nil.
Or have I misunderstood how optional parameters are skipped when creating IEs (or messages)?
Thanks
Hi,
First of all, thanks for the prompt fixes from previous issues raised.
Couple more:
1/ FTEID encoding: When the CH bit is set, the IPv4 address field is still present. It should be omitted, even though the IPv4 bit may still be set.
2/ UEIPAddress encoding: In func (f *UEIPAddressFields) MarshalLen() and others in the file it references the 5th bit twice. The second one should be has6thbit, for IPv6. Also if say the CHV4 bit is set then MarshalLen() returns 1, which then makes MarshalTo() return io.ErrUnexpectedEOF because a length of 1 is < 2 in the check even though an IE of just the flags octet is valid. Handling IPv6PL field is also missing.
Hope the feedback helps further the project.
Many thanks
Currently NewSMFSetID
encodes string, but should be same way as NewNodeID
instead
Some of the IE fields that are defined as OctetString type should perhaps accept []byte
or something instead of string
in their constructors, as they expect more complicated contents than just a string (and most of which are defined in another specification 😡).
e.g., PortManagementInformationContainer, BridgeManagementInformationContainer
This is just a reminder issue, to be considered some time later (hopefully).
Hi,
I am tryring to parse UserPlane Information from the Setup Association Response provided by Traveling VPP :
https://github.com/travelping/upg-vpp
I got this payoad : []uint8 len: 13, cap: 1456, [41,0,192,168,1,120,6,97,99,99,101,115,115]
I do not really understund the condition l< offset-n , since l=n from above, this mean the offset must be 0 in my case.
In my opinion, offset+n must be < l in order to remain in the array size.
Parsing works great without this Eof check.
go-pfcp/ie/user-plane-ip-resource-information.go
Lines 150 to 162 in 1f550dd
Thanks you
Leaving an idea that I may actually work on or I may just discarded.
// instead of this;
nodeID, err := assocSetupRes.NodeID.NodeID()
cause, err := assocSetupRes.Cause.Cause()
// this would be more useful
nodeID, err := assocSetupRes.NodeID.Value()
cause, err := assocSetupRes.Cause.Value()
// especially when iterating over multiple IEs
for _, i := range multipleIEs {
v, err := i.Value()
if err != nil {
log.Println(v, err)
continue
}
// switch-case is necessary anyway, but no need to call `.IEName()` within it
// `.Value()` will be less efficient, as its implementation will be a huge switch-case, though
switch i.Type {
case ie.NodeID:
log.Println("NodeID:", v)
case ie.Cause:
log.Println("Cause:", v)
default:
log.Println("Unknown:", v)
}
}
Hi,
In ie/ue-ip-address-pool-identity.go shouldn't line 68 be:
return string(v[1:(idlen+1)]), nil
instead of
return string(v[1:idlen]), nil
The last character of the name is dropped otherwise?
Thanks
Line 8 in c1d4b29
Parameter's name should be far
, to not create confusion.
Type | IE | comment | # octets |
---|---|---|---|
272 | Partial Failure Information (PFCP Session Establishment Response) | Extendable / Table 7.5.3.1-2 | Not Applicable |
273 | Partial Failure Information (PFCP Session Modification Response) | Extendable / Table 7.5.5.1-2 | Not Applicable |
274 | Offending IE Information | Variable Length / Clause 8.2.152 | Not Applicable |
275 | RAT Type | Extendable / Table 8.2.186 | 1 |
to be examined...
Hi, thanks for your gorgeous code, it really helps a lot!
I know that this code done perfect with single IE & group IE & all kinds of messages, but I don't know how to code with array IEs, like multi CreatePDR in one SessionEstablishmentRequest,or multi URRID in one CreatePDR. Does this code done with this kind of array IEs, how to use it? Please tell me, thanks a lot!
You can use this IE, give me an example, how do you encapsulate it? For example, how do you judge the type of each field in IE?
The following code is packaged according to my understanding. Can you see what is wrong?
type UserPlaneIpResourceInformation struct {
Flags uint8
TEIDRange uint32
IPv4 net.IP
IPv6 net.IP
NetworkInstance string
SourceInterface uint8
}
What types should TEIDRange, NetworkInstance, and SourceInterface take?
Thank you for your help and guidance
To ensure each method returns the expected value, we should add unit tests for them.
ie_uint8_test.go
/ #63, #69)ie_uint16_test.go
/ #66)ie_uint32_test.go
/ WIP / 9389c03)ie_uint64_test.go
/ 9389c03)ie_string_test.go
/ #60 / WIP: tests for grouped IE should be added)ie_duration_test.go
/ #67)ie_time_test.go
/ #68)I found many helper functions will ParseMultiIEs(i.Payload) directly even it was already parsed. Fox example:
func (i *IE) CreatePDR() ([]*IE, error) {
if i.Type != CreatePDR {
return nil, &InvalidTypeError{Type: i.Type}
}
return ParseMultiIEs(i.Payload)
}
I think it can enhance performance to add ChildIEs length checking to determine if this IE was parsed.
func (i *IE) CreatePDR() ([]*IE, error) {
if i.Type != CreatePDR {
return nil, &InvalidTypeError{Type: i.Type}
}
if len(i.ChildIEs) > 0 {
return i.ChildIEs
}
return ParseMultiIEs(i.Payload)
}
Or something I missed?
It's like this, I researched and understood that the news is just a combination of various IEs, and some IEs are also a combination of other IEs. I found that the IE codes given in the agreement are those independent IE. Therefore, I want to finish the independent IE that has not been completed first.I would like to ask, how do you determine what type of IE this IE belongs to through the agreement.
hi @wmnsk
It'll be safer to check if offset>offset+end before
https://github.com/wmnsk/go-pfcp/blob/master/ie/ie.go#L557
also, check if i.MarshalLen()>len(b) before
https://github.com/wmnsk/go-pfcp/blob/master/ie/ie.go#L500
we found "slice bounds out of range" error if
pfcp_heartbeat_request = b'\x20\x01\x00\x0c\x00\x00\x02\x00\x00\x60\x00\x00\xe8\x1f\xe7\xb4'
or
pfcp_heartbeat_request = b'\x20\x01\x00\x0f\x00\x00\x00\xff\xff\xff\x00\x00\x60\x00\x04\xe8\x1f\xdc\x30'
BRs,
Linpoyi
My encapsulation code:
dl := ie.NewDestinationInterface(1)
nt := ie.NewNetworkInstance("11")
ie.NewRemoteGTPUPeer("192.168.2.1", "", dl, nt)
Your encapsulation logic
go-pfcp/ie/remote-gtp-u-peer.go
Lines 197 to 212 in e45192e
PCAP file
s_5.zip
As in 3GPP TS 29.244 version 16.5.0 Release 16
8.2.132 Quota Validity Time
: It contains the quota validity time in seconds
.
Current implementation parses and creates it as time.Time
go-pfcp/ie/outer-header-removal.go
Line 64 in 1f550dd
- func (i *IE) GTPUExternsionHeaderDeletion() (uint8, error) {
+ func (i *IE) GTPUExtensionHeaderDeletion() (uint8, error) {
Commit b6fbe25 introduced parsing of UserPlaneIPResourceInformation
for association setup response but allows only one ie of that type. We were looking at upf which sends some flows to N9 vs N6, The SMF would probably need to know the Core IP and we were thinking of sending it via AssociationSetupRespoinse. We cannot do that anymore since Access details get overwritten with Core details. Does this sound right? Should i send 2 responses instead?
@TheWayYouMakeMeFeel @wmnsk
Library
case ie.UserPlaneIPResourceInformation:
m.UserPlaneIPResourceInformation = i
App
asres, err := message.NewAssociationSetupResponse(asreq.SequenceNumber,
ie.NewRecoveryTimeStamp(time.Now()),
ie.NewNodeID(sourceIP, "", ""), /* node id (IPv4) */
ie.NewCause(ie.CauseRequestAccepted), /* accept it blindly for the time being */
// 0x41 = Spare (0) | Assoc Src Inst (1) | Assoc Net Inst (0) | Tied Range (000) | IPV6 (0) | IPV4 (1)
// = 01000001
ie.NewUserPlaneIPResourceInformation(0x41, 0, accessIP, "", "", ie.SrcInterfaceAccess),
//ie.NewUserPlaneIPResourceInformation(0x41, 0, coreIP, "", "", ie.SrcInterfaceCore),
).Marshal() /* userplane ip resource info */
It can possibly be useful if the IEs can be retrieved all at once regardless of the message type (without asserting by the message type). The example implementation for AssociationSetupRequest
would be like this.
func (m *AssociationSetupRequest) AllIEs() []*ie.IE {
ies := []*ie.IE{
m.NodeID,
m.RecoveryTimeStamp,
m.UPFunctionFeatures,
m.CPFunctionFeatures,
m.SMFSetID,
m.PFCPSessionRetentionInformation,
m.PFCPASReqFlags,
}
ies = append(ies, m.UserPlaneIPResourceInformation...)
ies = append(ies, m.AlternativeSMFIPAddress...)
ies = append(ies, m.UEIPAddressPoolInformation...)
ies = append(ies, m.GTPUPathQoSControlInformation...)
ies = append(ies, m.ClockDriftControlInformation...)
ies = append(ies, m.IEs...)
return ies
}
*Maybe the inefficient append
can be avoided, as the length of returned slice (=number of IEs) can be determined beforehand.
Currently we need to iterate over children to find specific IEs and to get its values, which is a bit painful considering the number of children. Adding a struct for them and set values directly to its fields would make it easier for users.
cf. README
type CreatePDRFields struct {
PDRID uint16
FARID uint32
...
}
Here is the list of IEs defined in Table 7.x
instead of Clause 8.x
in TS 29.244
In message/header.go
the documentation says GTP
instead of PFCP
for the following functions:
Adding more strict rules(c0519d2) made golangci-lint mad. We need to follow its advice.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.