1% PFCP tests 2 3# Type the following command to launch start the tests: 4# $ test/run_tests -P "load_contrib('pfcp')" -t test/contrib/pfcp.uts 5 6+ Build packets & dissect 7 8= Verify IEs 9 10import scapy.contrib.pfcp as pfcp_mod 11 12skip_IEs = [ 13 IE_Base, 14 IE_Compound 15] 16 17for name, cls in pfcp_mod.__dict__.items(): 18 if name.startswith("IE_") and type(cls) == Packet_metaclass and cls not in skip_IEs: 19 print("testing %s" % name) 20 pkt = cls() 21 bs = bytes(pkt) 22 restored = cls(bs) 23 assert bytes(restored) == bs 24 # TODO: also test packet field equality 25 26= Verify PCAPs 27 28~ pcaps 29 30# the following can be useful while adding more IE types 31# (e.g. updating for a newer version of the spec) 32 33def command(pkt): 34 f = [] 35 for fn, fv in sorted(pkt.fields.items(), key=lambda item: item[0]): 36 if fn in ("length", "message_type"): 37 continue 38 if fn == "ietype" and not isinstance(pkt, IE_EnterpriseSpecific) and \ 39 not isinstance(pkt, IE_NotImplemented): 40 continue 41 if fn.startswith("num_") or fn.endswith("_length"): 42 continue 43 if fv is None: 44 continue 45 fld = pkt.get_field(fn) 46 if isinstance(fld, ConditionalField) and not fld._evalcond(pkt): 47 continue 48 # if fv == fld.default: 49 # continue 50 if isinstance(fv, (list, dict, set)) and len(fv) == 0: 51 continue 52 if isinstance(fv, Packet): 53 fv = command(fv) 54 elif fld.islist and fld.holds_packets and isinstance(fv, list): 55 fv = "[%s]" % ",".join(map(command, fv)) 56 elif isinstance(fld, FlagsField): 57 fv = int(fv) 58 else: 59 fv = repr(fv) 60 f.append("%s=%s" % (fn, fv)) 61 c = "%s(%s)" % (pkt.__class__.__name__, ", ".join(f)) 62 if not isinstance(pkt.payload, NoPayload): 63 pc = command(pkt.payload) 64 if pc: 65 c += "/" + pc 66 return c 67 68broken_ies = set([]) 69 70broken_ie_types = set([ 71 cls.ie_type for cls in broken_ies 72]) 73 74ignore = set([]) 75 76def find_raw_or_not_implemented(pkt, prefix=""): 77 if prefix in ignore: 78 return False, False 79 if hasattr(pkt, "IE_list"): 80 prev = None 81 found_any = False 82 for n, ie in enumerate(pkt.IE_list, 1): 83 if type(ie) in broken_ies: 84 return False, False 85 name = "%s-%d-%s" % (prefix, n, type(ie).__name__) 86 found, leaf = find_raw_or_not_implemented(ie, prefix=name) 87 if found: 88 found_any = True 89 if found and leaf: 90 print("gotcha: %s %r" % (prefix, ie)) 91 bs = b"" 92 if prev is not None: 93 bs = bytes(prev) 94 bs += bytes(ie) 95 if prev is not None: 96 prev.show2() 97 ie.show2() 98 print("%s -- bad val: %s" % (prefix, bytes_hex(bs).decode())) 99 if len(bs) > 4: 100 l = bs[2] * 256 + bs[3] 101 if len(bs) >= l + 4: 102 print("bad val (length-limited): %s" % bytes_hex(bs[:l + 4]).decode()) 103 print("bad val (short): %s" % bytes_hex(bytes(ie)).decode()) 104 prev = ie 105 return found_any, False 106 if isinstance(pkt, Raw): 107 bs = bytes(pkt) 108 if len(bs) > 4: 109 ie_type = bs[0] * 256 + bs[1] 110 if ie_type in broken_ie_types: 111 return False, True 112 return True, True 113 if isinstance(pkt, Padding) or isinstance(pkt, IE_NotImplemented): 114 return True, True 115 return False, True 116 117def find_mismatching_command(pkt, prefix=""): 118 c = command(pkt) 119 if hasattr(pkt, "IE_list"): 120 for n, ie in enumerate(pkt.IE_list, 1): 121 name = "%s-%d-%s" % (prefix, n, type(ie).__name__) 122 find_mismatching_command(ie, prefix=name) 123 if bytes(eval(c)) != bytes(pkt): 124 print(prefix) 125 print("ORIG: %s" % bytes_hex(bytes(pkt))) 126 print("EVAL: %s" % bytes_hex(bytes(eval(c)))) 127 raise AssertionError("bad command: %s" % c) 128 129for n, pkt in enumerate(rdpcap("test/pcaps/pfcp.pcap"), 1): 130 if PFCP in pkt: 131 # if IE_DLBufferingSuggestedPacketCount in pkt: 132 # continue 133 pkt0 = pkt[PFCP] 134 if IE_NotImplemented in pkt0 or Raw in pkt0 or IE_NotImplemented in pkt0 or Padding in pkt0: 135 found, leaf = find_raw_or_not_implemented(pkt, prefix=str(n)) 136 if not found: 137 # ignored 138 continue 139 pkt0.show2() 140 raise AssertionError("IE_NotImplemented / Raw / Padding detected") 141 bs = bytes(pkt0) 142 pkt1 = PFCP(bs) 143 # TODO: diff show2() result 144 c0 = command(pkt0) 145 c1 = command(pkt1) 146 pkt2 = eval(c1) 147 c2 = command(pkt2) 148 if bytes(pkt2) != bs: 149 find_mismatching_command(pkt0, prefix=str(n)) 150 print(bytes_hex(bytes(pkt2))) 151 print(bytes_hex(bs)) 152 raise AssertionError("bytes(pkt2) != bs") 153 if bs != pkt0.original: 154 print(bytes_hex(bs)) 155 print(bytes_hex(pkt0.original)) 156 raise AssertionError("bs != pkt0.original") 157 if bytes(pkt1) != bs: 158 print(bytes_hex(bytes(pkt1))) 159 print(bytes_hex(bs)) 160 raise AssertionError("bytes(pkt1) != bs") 161 if c0 != c1: 162 print("COMMAND MISMATCH:\n----\n%s\n----\n%s\n\n" % (c0, c1)) 163 pkt0.show2() 164 pkt1.show2() 165 print(bytes_hex(bytes(pkt0))) 166 print("packet index: %d\n" % n) 167 raise AssertionError("c0 != c1") 168 if c0 != c2: 169 print("EVAL COMMAND MISMATCH:\n----\n%s\n----\n%s\n\n" % (c0, c2)) 170 pkt0.show2() 171 pkt2.show2() 172 print(bytes_hex(bytes(pkt0))) 173 print("packet index: %d\n" % n) 174 raise AssertionError("c0 != c2") 175 176= Build and dissect PFCP Association Setup Request 177 178pfcpASReqBytes = hex_bytes("200500160000010000600004e1a47d08003c0006020465726777") 179 180pfcpASReq = PFCP(version=1, S=0, seq=1) / \ 181 PFCPAssociationSetupRequest(IE_list=[ 182 IE_RecoveryTimeStamp(timestamp=3785653512), 183 IE_NodeId(id_type="FQDN", id="ergw") 184 ]) 185 186# print("%r" % bytes(pfcpASReq)) 187# print("%r" % pfcpASReqBytes) 188assert bytes(pfcpASReq) == pfcpASReqBytes 189 190pfcpASReq = PFCP(pfcpASReqBytes) 191assert pfcpASReq.version == 1 192assert pfcpASReq.MP == 0 193assert pfcpASReq.S == 0 194assert pfcpASReq.message_type == 5 195assert pfcpASReq.length == 22 196ies = pfcpASReq[PFCPAssociationSetupRequest].IE_list 197assert isinstance(ies[0], IE_RecoveryTimeStamp) 198assert ies[0].ietype == 96 199assert ies[0].length == 4 200assert ies[0].timestamp == 3785653512 201assert isinstance(ies[1], IE_NodeId) 202assert ies[1].ietype == 60 203assert ies[1].length == 6 204assert ies[1].id_type == 2 205assert ies[1].id == b"ergw" 206 207= Build and dissect PFCP Association Setup Response 208 209pfcpASRespBytes = hex_bytes("2006008c00000100001300010100600004e1a47af9002b00020001007400092980ac1201020263708002006448f9767070207631392e30382e312d3339377e673465333431343066612d6469727479206275696c7420627920726f6f74206f6e206275696c646b697473616e64626f7820617420576564204465632031312031353a30323a3535205554432032303139") 210 211pfcpASResp = PFCP(version=1, S=0, seq=1) / \ 212 PFCPAssociationSetupResponse(IE_list=[ 213 IE_Cause(cause="Request accepted"), 214 IE_RecoveryTimeStamp(timestamp=3785652985), 215 IE_UPFunctionFeatures( 216 TREU=0, HEEU=0, PFDM=0, FTUP=0, TRST=0, DLBD=0, DDND=0, BUCP=0, 217 spare=0, PFDE=0, FRRT=0, TRACE=0, QUOAC=0, UDBC=0, PDIU=0, EMPU=1), 218 IE_UserPlaneIPResourceInformation( 219 ASSOSI=0, ASSONI=1, TEIDRI=2, V6=0, V4=1, teid_range=0x80, 220 ipv4="172.18.1.2", network_instance="cp"), 221 IE_EnterpriseSpecific( 222 ietype=32770, 223 enterprise_id=18681, 224 data="vpp v19.08.1-397~g4e34140fa-dirty built by root on buildkitsandbox at Wed Dec 11 15:02:55 UTC 2019") 225 ]) 226 227 228pfcpASResp.show2() 229assert bytes(pfcpASResp) == pfcpASRespBytes 230 231pfcpASResp = PFCP(pfcpASRespBytes) 232assert pfcpASResp.version == 1 233assert pfcpASResp.MP == 0 234assert pfcpASResp.S == 0 235assert pfcpASResp.message_type == 6 236assert pfcpASResp.length == 140 237 238ies = pfcpASResp[PFCPAssociationSetupResponse].IE_list 239assert isinstance(ies[0], IE_Cause) 240assert ies[0].ietype == 19 241assert ies[0].length == 1 242assert ies[0].cause == 1 243assert isinstance(ies[1], IE_RecoveryTimeStamp) 244assert ies[1].ietype == 96 245assert ies[1].length == 4 246assert ies[1].timestamp == 3785652985 247assert isinstance(ies[2], IE_UPFunctionFeatures) 248assert ies[2].ietype == 43 249assert ies[2].length == 2 250assert ies[2].TREU == 0 251assert ies[2].HEEU == 0 252assert ies[2].PFDM == 0 253assert ies[2].FTUP == 0 254assert ies[2].TRST == 0 255assert ies[2].DLBD == 0 256assert ies[2].DDND == 0 257assert ies[2].BUCP == 0 258assert ies[2].spare == 0 259assert ies[2].PFDE == 0 260assert ies[2].FRRT == 0 261assert ies[2].TRACE == 0 262assert ies[2].QUOAC == 0 263assert ies[2].UDBC == 0 264assert ies[2].PDIU == 0 265assert ies[2].EMPU == 1 266assert isinstance(ies[3], IE_UserPlaneIPResourceInformation) 267assert ies[3].ASSOSI == 0 268assert ies[3].ASSONI == 1 269assert ies[3].TEIDRI == 2 270assert ies[3].V6 == 0 271assert ies[3].V4 == 1 272assert ies[3].teid_range == 0x80 273assert ies[3].ipv4 == "172.18.1.2" 274assert ies[3].network_instance == b"cp" 275assert isinstance(ies[4], IE_EnterpriseSpecific) 276assert ies[4].ietype == 32770 277assert ies[4].enterprise_id == 18681 278assert ies[4].data == b"vpp v19.08.1-397~g4e34140fa-dirty built by root on buildkitsandbox at Wed Dec 11 15:02:55 UTC 2019" 279 280assert pfcpASResp.answers(pfcpASReq) 281 282# = Build and dissect PFCP Session Establishment Request 283 284pfcpSEReq1Bytes = hex_bytes("2132011300000000000000000000020000030021002c000102006c00040000000200040010002a00010000160007066163636573730003000d002c000101006c00040000000100010038006c000400000002005f000100000200190015000901104c9033ac120102001600030263700014000103003800020002001d00040000006400010057006c000400000001000200350016000706616363657373001700210100001d7065726d6974206f75742069702066726f6d20616e7920746f20616e790014000100003800020001001d00040000fde800510004000000010006001b003e000104002500021000004a00040000003c00510004000000010039000d02ffde7210bf97810aac120101003c0006020465726777") 285 286pfcpSEReq1 = PFCP(version=1, S=1, seq=2, seid=0, spare_oct=0) / \ 287 PFCPSessionEstablishmentRequest(IE_list=[ 288 IE_CreateFAR(IE_list=[ 289 IE_ApplyAction(FORW=1), 290 IE_FAR_Id(id=2), 291 IE_ForwardingParameters(IE_list=[ 292 IE_DestinationInterface(interface="Access"), 293 IE_NetworkInstance(instance="access"), 294 ]) 295 ]), 296 IE_CreateFAR(IE_list=[ 297 IE_ApplyAction(DROP=1), 298 IE_FAR_Id(id=1) 299 ]), 300 IE_CreatePDR(IE_list=[ 301 IE_FAR_Id(id=2), 302 IE_OuterHeaderRemoval(header="GTP-U/UDP/IPv4"), 303 IE_PDI(IE_list=[ 304 IE_FTEID(V4=1, TEID=0x104c9033, ipv4="172.18.1.2"), 305 IE_NetworkInstance(instance="cp"), 306 IE_SourceInterface(interface="CP-function"), 307 ]), 308 IE_PDR_Id(id=2), 309 IE_Precedence(precedence=100) 310 ]), 311 IE_CreatePDR(IE_list=[ 312 IE_FAR_Id(id=1), 313 IE_PDI(IE_list=[ 314 IE_NetworkInstance(instance="access"), 315 IE_SDF_Filter(FD=1, flow_description="permit out ip from any to any"), 316 IE_SourceInterface(interface="Access"), 317 ]), 318 IE_PDR_Id(id=1), 319 IE_Precedence(precedence=65000), 320 IE_URR_Id(id=1) 321 ]), 322 IE_CreateURR(IE_list=[ 323 IE_MeasurementMethod(EVENT=1), 324 IE_ReportingTriggers(start_of_traffic=1), 325 IE_TimeQuota(quota=60), 326 IE_URR_Id(id=1) 327 ]), 328 IE_FSEID(v4=1, seid=0xffde7210bf97810a, ipv4="172.18.1.1"), 329 IE_NodeId(id_type="FQDN", id="ergw") 330 ]) 331 332assert bytes(pfcpSEReq1) == pfcpSEReq1Bytes 333assert bytes(PFCP(pfcpSEReq1Bytes)) == pfcpSEReq1Bytes 334 335pfcpSEReq2Bytes = hex_bytes("213202ba00000000000000000000080000030037002c000102006c00040000000400040026002a000102001600040373676900260015020012687474703a2f2f6578616d706c652e636f6d0003001e002c000102006c0004000000020004000d002a000102001600040373676900030021002c000102006c00040000000300040010002a000100001600070661636365737300030021002c000102006c00040000000100040010002a00010000160007066163636573730001006d006c0004000000040002004b00160007066163636573730017002e0100002a7065726d6974206f75742069702066726f6d203139382e31392e36352e3420746f2061737369676e65640014000100005d0005020ac00000003800020004001d00040000006400510004000000020001006d006c0004000000020002004b00160007066163636573730017002e0100002a7065726d6974206f75742069702066726f6d203139382e31392e36352e3220746f2061737369676e65640014000100005d0005020ac00000003800020002001d0004000000c800510004000000010001006a006c0004000000030002004800160004037367690017002e0100002a7065726d6974206f75742069702066726f6d203139382e31392e36352e3420746f2061737369676e65640014000102005d0005060ac00000003800020003001d00040000006400510004000000020001006a006c0004000000010002004800160004037367690017002e0100002a7065726d6974206f75742069702066726f6d203139382e31392e36352e3220746f2061737369676e65640014000102005d0005060ac00000003800020001001d0004000000c8005100040000000100060013003e000102002500020000005100040000000200060013003e00010200250002000000510004000000010039000d02ffde7210d971c146ac120101003c0006020465726777") 336 337pfcpSEReq2 = PFCP(seq=8) / PFCPSessionEstablishmentRequest(IE_list=[ 338 IE_CreateFAR(IE_list=[ 339 IE_ApplyAction(FORW=1), 340 IE_FAR_Id(id=4), 341 IE_ForwardingParameters(IE_list=[ 342 IE_DestinationInterface(interface="SGi-LAN/N6-LAN"), 343 IE_NetworkInstance(instance="sgi"), 344 IE_RedirectInformation(type="URL", address="http://example.com"), 345 ]) 346 ]), 347 IE_CreateFAR(IE_list=[ 348 IE_ApplyAction(FORW=1), 349 IE_FAR_Id(id=2), 350 IE_ForwardingParameters(IE_list=[ 351 IE_DestinationInterface(interface="SGi-LAN/N6-LAN"), 352 IE_NetworkInstance(instance="sgi"), 353 ]) 354 ]), 355 IE_CreateFAR(IE_list=[ 356 IE_ApplyAction(FORW=1), 357 IE_FAR_Id(id=3), 358 IE_ForwardingParameters(IE_list=[ 359 IE_DestinationInterface(interface="Access"), 360 IE_NetworkInstance(instance="access") 361 ]) 362 ]), 363 IE_CreateFAR(IE_list=[ 364 IE_ApplyAction(FORW=1), 365 IE_FAR_Id(id=1), 366 IE_ForwardingParameters(IE_list=[ 367 IE_DestinationInterface(interface="Access"), 368 IE_NetworkInstance(instance="access") 369 ]) 370 ]), 371 IE_CreatePDR(IE_list=[ 372 IE_FAR_Id(id=4), 373 IE_PDI(IE_list=[ 374 IE_NetworkInstance(instance="access"), 375 IE_SDF_Filter( 376 FD=1, flow_description="permit out ip from 198.19.65.4 to assigned"), 377 IE_SourceInterface(interface="Access"), 378 IE_UE_IP_Address(ipv4="10.192.0.0", V4=1) 379 ]), 380 IE_PDR_Id(id=4), 381 IE_Precedence(precedence=100), 382 IE_URR_Id(id=2) 383 ]), 384 IE_CreatePDR(IE_list=[ 385 IE_FAR_Id(id=2), 386 IE_PDI(IE_list=[ 387 IE_NetworkInstance(instance="access"), 388 IE_SDF_Filter(FD=1, flow_description="permit out ip from 198.19.65.2 to assigned"), 389 IE_SourceInterface(interface="Access"), 390 IE_UE_IP_Address(ipv4="10.192.0.0", V4=1) 391 ]), 392 IE_PDR_Id(id=2), 393 IE_Precedence(precedence=200), 394 IE_URR_Id(id=1) 395 ]), 396 IE_CreatePDR(IE_list=[ 397 IE_FAR_Id(id=3), 398 IE_PDI(IE_list=[ 399 IE_NetworkInstance(instance="sgi"), 400 IE_SDF_Filter(FD=1, flow_description="permit out ip from 198.19.65.4 to assigned"), 401 IE_SourceInterface(interface="SGi-LAN/N6-LAN"), 402 IE_UE_IP_Address(ipv4="10.192.0.0", SD=1, V4=1) 403 ]), 404 IE_PDR_Id(id=3), 405 IE_Precedence(precedence=100), 406 IE_URR_Id(id=2) 407 ]), 408 IE_CreatePDR(IE_list=[ 409 IE_FAR_Id(id=1), 410 IE_PDI(IE_list=[ 411 IE_NetworkInstance(instance="sgi"), 412 IE_SDF_Filter(FD=1, flow_description="permit out ip from 198.19.65.2 to assigned"), 413 IE_SourceInterface(interface="SGi-LAN/N6-LAN"), 414 IE_UE_IP_Address(ipv4="10.192.0.0", SD=1, V4=1) 415 ]), 416 IE_PDR_Id(id=1), 417 IE_Precedence(precedence=200), 418 IE_URR_Id(id=1) 419 ]), 420 IE_CreateURR(IE_list=[ 421 IE_MeasurementMethod(VOLUM=1), 422 IE_ReportingTriggers(), 423 IE_URR_Id(id=2) 424 ]), 425 IE_CreateURR(IE_list=[ 426 IE_MeasurementMethod(VOLUM=1), 427 IE_ReportingTriggers(), 428 IE_URR_Id(id=1) 429 ]), 430 IE_FSEID(ipv4="172.18.1.1", v4=1, seid=0xffde7210d971c146), 431 IE_NodeId(id_type="FQDN", id="ergw")]) 432 433assert bytes(pfcpSEReq2) == pfcpSEReq2Bytes 434assert bytes(PFCP(pfcpSEReq2Bytes)) == pfcpSEReq2Bytes 435 436pfcpSEReq3Bytes = hex_bytes("213203a10000000000000000000003000003001e002c000102006c0004000000060004000d002a000102001600040373676900030037002c000102006c00040000000400040026002a000102001600040373676900260015020012687474703a2f2f6578616d706c652e636f6d0003001e002c000102006c0004000000020004000d002a000102001600040373676900030021002c000102006c00040000000500040010002a000100001600070661636365737300030021002c000102006c00040000000300040010002a000100001600070661636365737300030021002c000102006c00040000000100040010002a000100001600070661636365737300010042006c000400000006000200200018000354535400160007066163636573730014000100005d0005020ac00000003800020006001d00040000009600510004000000030001006d006c0004000000040002004b00160007066163636573730017002e0100002a7065726d6974206f75742069702066726f6d203139382e31392e36352e3420746f2061737369676e65640014000100005d0005020ac00000003800020004001d00040000006400510004000000020001006d006c0004000000020002004b00160007066163636573730017002e0100002a7065726d6974206f75742069702066726f6d203139382e31392e36352e3220746f2061737369676e65640014000100005d0005020ac00000003800020002001d0004000000c800510004000000010001003f006c0004000000050002001d0018000354535400160004037367690014000102005d0005060ac00000003800020005001d00040000009600510004000000030001006a006c0004000000030002004800160004037367690017002e0100002a7065726d6974206f75742069702066726f6d203139382e31392e36352e3420746f2061737369676e65640014000102005d0005060ac00000003800020003001d00040000006400510004000000020001006a006c0004000000010002004800160004037367690017002e0100002a7065726d6974206f75742069702066726f6d203139382e31392e36352e3220746f2061737369676e65640014000102005d0005060ac00000003800020001001d0004000000c8005100040000000100060013003e000102002500020000005100040000000200060013003e000103002500020000005100040000000300060013003e00010200250002000000510004000000010039000d02ffde7211a5ab800aac120101003c0006020465726777") 437 438pfcpSEReq3 = PFCP(seq=3) / \ 439 PFCPSessionEstablishmentRequest(IE_list=[ 440 IE_CreateFAR(IE_list=[ 441 IE_ApplyAction(FORW=1), 442 IE_FAR_Id(id=6), 443 IE_ForwardingParameters(IE_list=[ 444 IE_DestinationInterface(interface="SGi-LAN/N6-LAN"), 445 IE_NetworkInstance(instance="sgi") 446 ]) 447 ]), 448 IE_CreateFAR(IE_list=[ 449 IE_ApplyAction(FORW=1), 450 IE_FAR_Id(id=4), 451 IE_ForwardingParameters(IE_list=[ 452 IE_DestinationInterface(interface="SGi-LAN/N6-LAN"), 453 IE_NetworkInstance(instance="sgi"), 454 IE_RedirectInformation(type="URL", address="http://example.com") 455 ]) 456 ]), 457 IE_CreateFAR(IE_list=[ 458 IE_ApplyAction(FORW=1), 459 IE_FAR_Id(id=2), 460 IE_ForwardingParameters(IE_list=[ 461 IE_DestinationInterface(interface="SGi-LAN/N6-LAN"), 462 IE_NetworkInstance(instance="sgi") 463 ]) 464 ]), 465 IE_CreateFAR(IE_list=[ 466 IE_ApplyAction(FORW=1), 467 IE_FAR_Id(id=5), 468 IE_ForwardingParameters(IE_list=[ 469 IE_DestinationInterface(interface="Access"), 470 IE_NetworkInstance(instance="access") 471 ]) 472 ]), 473 IE_CreateFAR(IE_list=[ 474 IE_ApplyAction(FORW=1), 475 IE_FAR_Id(id=3), 476 IE_ForwardingParameters(IE_list=[ 477 IE_DestinationInterface(interface="Access"), 478 IE_NetworkInstance(instance="access") 479 ]) 480 ]), 481 IE_CreateFAR(IE_list=[ 482 IE_ApplyAction(FORW=1), 483 IE_FAR_Id(id=1), 484 IE_ForwardingParameters(IE_list=[ 485 IE_DestinationInterface(interface="Access"), 486 IE_NetworkInstance(instance="access") 487 ]) 488 ]), 489 IE_CreatePDR(IE_list=[ 490 IE_FAR_Id(id=6), 491 IE_PDI(IE_list=[ 492 IE_ApplicationId(id="TST"), 493 IE_NetworkInstance(instance="access"), 494 IE_SourceInterface(interface="Access"), 495 IE_UE_IP_Address(ipv4='10.192.0.0', V4=1) 496 ]), 497 IE_PDR_Id(id=6), 498 IE_Precedence(precedence=150), 499 IE_URR_Id(id=3) 500 ]), 501 IE_CreatePDR(IE_list=[ 502 IE_FAR_Id(id=4), 503 IE_PDI(IE_list=[ 504 IE_NetworkInstance(instance="access"), 505 IE_SDF_Filter(FD=1, flow_description="permit out ip from 198.19.65.4 to assigned"), 506 IE_SourceInterface(interface="Access"), 507 IE_UE_IP_Address(ipv4='10.192.0.0', V4=1) 508 ]), 509 IE_PDR_Id(id=4), 510 IE_Precedence(precedence=100), 511 IE_URR_Id(id=2) 512 ]), 513 IE_CreatePDR(IE_list=[ 514 IE_FAR_Id(id=2), 515 IE_PDI(IE_list=[ 516 IE_NetworkInstance(instance="access"), 517 IE_SDF_Filter(FD=1, flow_description="permit out ip from 198.19.65.2 to assigned"), 518 IE_SourceInterface(interface="Access"), 519 IE_UE_IP_Address(ipv4='10.192.0.0', V4=1) 520 ]), 521 IE_PDR_Id(id=2), 522 IE_Precedence(precedence=200), 523 IE_URR_Id(id=1) 524 ]), 525 IE_CreatePDR(IE_list=[ 526 IE_FAR_Id(id=5), 527 IE_PDI(IE_list=[ 528 IE_ApplicationId(id="TST"), 529 IE_NetworkInstance(instance="sgi"), 530 IE_SourceInterface(interface="SGi-LAN/N6-LAN"), 531 IE_UE_IP_Address(ipv4='10.192.0.0', SD=1, V4=1) 532 ]), 533 IE_PDR_Id(id=5), 534 IE_Precedence(precedence=150), 535 IE_URR_Id(id=3) 536 ]), 537 IE_CreatePDR(IE_list=[ 538 IE_FAR_Id(id=3), 539 IE_PDI(IE_list=[ 540 IE_NetworkInstance(instance="sgi"), 541 IE_SDF_Filter(FD=1, flow_description="permit out ip from 198.19.65.4 to assigned"), 542 IE_SourceInterface(interface="SGi-LAN/N6-LAN"), 543 IE_UE_IP_Address(ipv4='10.192.0.0', SD=1, V4=1) 544 ]), 545 IE_PDR_Id(id=3), 546 IE_Precedence(precedence=100), 547 IE_URR_Id(id=2) 548 ]), 549 IE_CreatePDR(IE_list=[ 550 IE_FAR_Id(id=1), 551 IE_PDI(IE_list=[ 552 IE_NetworkInstance(instance="sgi"), 553 IE_SDF_Filter(FD=1, flow_description="permit out ip from 198.19.65.2 to assigned"), 554 IE_SourceInterface(interface="SGi-LAN/N6-LAN"), 555 IE_UE_IP_Address(ipv4='10.192.0.0', SD=1, V4=1) 556 ]), 557 IE_PDR_Id(id=1), 558 IE_Precedence(precedence=200), 559 IE_URR_Id(id=1) 560 ]), 561 IE_CreateURR(IE_list=[ 562 IE_MeasurementMethod(VOLUM=1), 563 IE_ReportingTriggers(), 564 IE_URR_Id(id=2) 565 ]), 566 IE_CreateURR(IE_list=[ 567 IE_MeasurementMethod(VOLUM=1, DURAT=1), 568 IE_ReportingTriggers(), 569 IE_URR_Id(id=3) 570 ]), 571 IE_CreateURR(IE_list=[ 572 IE_MeasurementMethod(VOLUM=1), 573 IE_ReportingTriggers(), 574 IE_URR_Id(id=1) 575 ]), 576 IE_FSEID(ipv4='172.18.1.1', v4=1, seid=0xffde7211a5ab800a), 577 IE_NodeId(id_type="FQDN", id="ergw") 578 ]) 579 580assert bytes(pfcpSEReq3) == pfcpSEReq3Bytes 581assert bytes(PFCP(pfcpSEReq3Bytes)) == pfcpSEReq3Bytes 582 583= Build and dissect PFCP Session Establishment Response 584 585pfcpSERespBytes = hex_bytes("21330022ffde7210bf97810a0000020000130001010039000d02ffde7210bf97810aac120102") 586 587pfcpSEResp = PFCP(version=1, S=1, seq=2, seid=0xffde7210bf97810a) / \ 588 PFCPSessionEstablishmentResponse(IE_list=[ 589 IE_Cause(cause="Request accepted"), 590 IE_FSEID(ipv4="172.18.1.2", v4=1, seid=0xffde7210bf97810a), 591 ]) 592 593assert bytes(pfcpSEResp) == pfcpSERespBytes 594assert bytes(PFCP(pfcpSERespBytes)) == pfcpSERespBytes 595assert pfcpSEResp.answers(pfcpSEReq1) 596 597= Build and dissect PFCP Heartbeat Request 598 599pfcpHReqBytes = hex_bytes("2001000c0000030000600004e1a47d08") 600 601pfcpHReq = PFCP(version=1, S=0, seq=3) / \ 602 PFCPHeartbeatRequest(IE_list=[ 603 IE_RecoveryTimeStamp(timestamp=3785653512) 604 ]) 605 606assert bytes(pfcpHReq) == pfcpHReqBytes 607assert bytes(PFCP(pfcpHReqBytes)) == pfcpHReqBytes 608 609# = Build and dissect PFCP Heartbeat Response 610 611pfcpHRespBytes = hex_bytes("2002000c0000030000600004e1a47af9") 612 613pfcpHResp = PFCP(version=1, S=0, seq=3) / \ 614 PFCPHeartbeatResponse(IE_list=[ 615 IE_RecoveryTimeStamp(timestamp=3785652985) 616 ]) 617 618assert bytes(pfcpHResp) == pfcpHRespBytes 619assert bytes(PFCP(pfcpHRespBytes)) == pfcpHRespBytes 620assert pfcpHResp.answers(pfcpHReq) 621 622# = Build and dissect PFCP Session Report Request 623 624pfcpSRReq1Bytes = hex_bytes("21380034ffde7210bf99c00300006b0000270001020050001f00510004000000010068000400000001003f00021000005d0005020ac00001") 625 626pfcpSRReq1 = PFCP(seq=107, version=1, S=1, seid=18437299340760956931) / \ 627 PFCPSessionReportRequest(IE_list=[ 628 IE_ReportType(USAR=1), 629 IE_UsageReport_SRR(IE_list=[ 630 IE_URR_Id(id=1), 631 IE_UR_SEQN(number=1), 632 IE_UsageReportTrigger(START=1), 633 IE_UE_IP_Address(ipv4="10.192.0.1", V4=1) 634 ]) 635 ]) 636 637assert bytes(pfcpSRReq1) == pfcpSRReq1Bytes 638assert bytes(PFCP(pfcpSRReq1Bytes)) == pfcpSRReq1Bytes 639 640pfcpSRReq2Bytes = hex_bytes("2138008a0ffde7210bf940000000310000270001020050007500510004000000030068000400000018003f00020100004b0004e1b44787004c0004e1b447910042001907000000000000000000000000000000000000000000000000004300040000000a8003000a48f9e1b4479137cbd8008004000a48f9e1b4478737cbd8008005000a48f9e1b4479137cbd800") 641 642pfcpSRReq2 = PFCP(seq=49, seid=1152331208797536256) / \ 643 PFCPSessionReportRequest(IE_list=[ 644 IE_ReportType(USAR=1), 645 IE_UsageReport_SRR(IE_list=[ 646 IE_URR_Id(id=3), 647 IE_UR_SEQN(number=24), 648 IE_UsageReportTrigger(PERIO=1), 649 IE_StartTime(timestamp=3786688391), 650 IE_EndTime(timestamp=3786688401), 651 IE_VolumeMeasurement( 652 DLVOL=1, ULVOL=1, TOVOL=1, total=0, uplink=0, downlink=0), 653 IE_DurationMeasurement(duration=10), 654 IE_EnterpriseSpecific( 655 ietype=32771, 656 enterprise_id=18681, 657 data=b'\xe1\xb4G\x917\xcb\xd8\x00'), 658 IE_EnterpriseSpecific( 659 ietype=32772, 660 enterprise_id=18681, 661 data=b'\xe1\xb4G\x877\xcb\xd8\x00'), 662 IE_EnterpriseSpecific( 663 ietype=32773, 664 enterprise_id=18681, 665 data=b'\xe1\xb4G\x917\xcb\xd8\x00') 666 ]) 667 ]) 668 669assert bytes(pfcpSRReq2) == pfcpSRReq2Bytes 670assert bytes(PFCP(pfcpSRReq2Bytes)) == pfcpSRReq2Bytes 671 672pfcpSRReq3Bytes = hex_bytes("21380035a2a2aa9ad7f316fd0000010000270001020050002000510004000000010068000400000000003f0003100000005d000502ac100202") 673 674pfcpSRReq3 = PFCP(seq=1, seid=11719116762396169981) / \ 675 PFCPSessionReportRequest(IE_list=[ 676 IE_ReportType(USAR=1), 677 IE_UsageReport_SRR(IE_list=[ 678 IE_URR_Id(id=1), 679 IE_UR_SEQN(number=0), 680 IE_UsageReportTrigger(START=1, extra_data=b'\x00'), 681 IE_UE_IP_Address(ipv4='172.16.2.2', V4=1) 682 ]) 683 ]) 684 685assert bytes(pfcpSRReq3) == pfcpSRReq3Bytes 686assert bytes(PFCP(pfcpSRReq3Bytes)) == pfcpSRReq3Bytes 687 688= Build and dissect PFCP Session Report Response 689 690pfcpSRRespBytes = hex_bytes("21390011ffde7210bf99c00300006b000013000101") 691 692pfcpSRResp = PFCP(version=1, S=1, seq=107, seid=0xffde7210bf99c003) / \ 693 PFCPSessionReportResponse(IE_list=[ 694 IE_Cause(cause="Request accepted") 695 ]) 696 697assert bytes(pfcpSRResp) == pfcpSRRespBytes 698assert bytes(PFCP(pfcpSRRespBytes)) == pfcpSRRespBytes 699assert pfcpSRResp.answers(pfcpSRReq1) 700 701= Build and dissect PFCP Session Modification Request 702 703pfcpSMReqBytes = hex_bytes("21340018ffde72125aeb00a300000600004d00080051000400000001") 704pfcpSMReq = PFCP(pfcpSMReqBytes) 705 706pfcpSMReq = PFCP(version=1, seq=6, seid=0xffde72125aeb00a3) / \ 707 PFCPSessionModificationRequest(IE_list=[ 708 IE_QueryURR(IE_list=[IE_URR_Id(id=1)]) 709 ]) 710assert bytes(pfcpSMReq) == pfcpSMReqBytes 711assert bytes(PFCP(pfcpSMReqBytes)) == pfcpSMReqBytes 712 713= Build and dissect PFCP Session Modification Response 714 715pfcpSMRespBytes = hex_bytes("2135008affde72125aeb00a3000006000013000101004e007500510004000000010068000400000000003f00028000004b0004e16e7efa004c0004e16e7efa004200190700000000000000000000000000000000000000000000000000430004000000008003000a48f9e16e7efa05566c008004000a48f9e16e7efa027f08008005000a48f9e16e7efa027f0800") 716 717pfcpSMResp = PFCP(version=1, seq=6, seid=0xffde72125aeb00a3) / \ 718 PFCPSessionModificationResponse(IE_list=[ 719 IE_Cause(cause=1), 720 IE_UsageReport_SMR(IE_list=[ 721 IE_URR_Id(id=1), 722 IE_UR_SEQN(number=0), 723 IE_UsageReportTrigger(IMMER=1), 724 IE_StartTime(timestamp=3782115066), 725 IE_EndTime(timestamp=3782115066), 726 IE_VolumeMeasurement(DLVOL=1, ULVOL=1, TOVOL=1), 727 IE_DurationMeasurement(), 728 IE_EnterpriseSpecific(ietype=32771, enterprise_id=18681, data=b'\xe1n~\xfa\x05Vl\x00'), 729 IE_EnterpriseSpecific(ietype=32772, enterprise_id=18681, data=b'\xe1n~\xfa\x02\x7f\x08\x00'), 730 IE_EnterpriseSpecific(ietype=32773, enterprise_id=18681, data=b'\xe1n~\xfa\x02\x7f\x08\x00') 731 ]) 732 ]) 733 734assert bytes(pfcpSMResp) == pfcpSMRespBytes 735assert bytes(PFCP(pfcpSMRespBytes)) == pfcpSMRespBytes 736assert pfcpSMResp.answers(pfcpSMReq) 737 738= Verify IEs 739 740from difflib import unified_diff 741cases = [ 742 dict( 743 hex="0054000a0100010000000a177645", 744 expect=IE_OuterHeaderCreation(GTPUUDPIPV4=1, TEID=0x01000000, ipv4="10.23.118.69")), 745 dict( 746 hex="002900050461626364", 747 expect=IE_ForwardingPolicy(policy_identifier="abcd")), 748 dict( 749 hex="002e0001ae", 750 expect=IE_DownlinkDataNotificationDelay(delay=174)), 751 dict( 752 hex="003d00020000", 753 expect=IE_PFDContents()), 754 dict( 755 hex="005e00070300205903e95d", 756 expect=IE_PacketRate(ULPR=1, DLPR=1, 757 ul_time_unit="minute", ul_max_packet_rate=8281, 758 dl_time_unit="day", dl_max_packet_rate=59741)), 759 dict( 760 hex="00850007010906638dccd5", 761 expect=IE_MACAddress(SOUR=1, source_mac="09:06:63:8d:cc:d5")), 762 dict( 763 hex="00540014080017d0bd69dceb747a1e036c0f9c8d4af115d0", 764 expect=IE_OuterHeaderCreation(UDPIPV6=1, 765 ipv6="17d0:bd69:dceb:747a:1e03:6c0f:9c8d:4af1", 766 port=5584)), 767 dict( 768 hex="006700050280df69b2", 769 expect=IE_RemoteGTP_U_Peer(V4=1, ipv4="128.223.105.178")), 770] 771 772for case in cases: 773 bs = hex_bytes(case["hex"]) 774 exp = case["expect"] 775 dissected = type(exp)(bs) 776 exp_text = exp.show2(dump=True) 777 dissected_text = dissected.show2(dump=True) 778 if exp_text != dissected_text: 779 print("---\n%s\n---\n%s\n" % (exp_text, dissected_text)) 780 for line in unified_diff(exp_text.split("\n"), dissected_text.split("\n"), 781 fromfile="expected", tofile="dissected"): 782 print(line) 783 raise AssertionError("text mismatch") 784 assert bytes(dissected) == bs 785 assert bytes(exp) == bs 786 787# from difflib import unified_diff 788# expected = PFCP(pfcpSRReq2Bytes).show2(dump=True).split("\n") 789# actual = pfcpSRReq2.show2(dump=True).split("\n") 790# for line in unified_diff(expected, actual, fromfile="expected", tofile="actual"): 791# print(line) 792