blob: 632d23b5fe7ff3f992ddda89a0ccb0d0fa3bc4f5 [file] [log] [blame]
Pau Espin Pedrolae811952021-09-23 13:34:20 +02001#!/usr/bin/env python3
2# MIT License
3#
4# Copyright (c) 2021 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
5# Author: Pau Espin Pedrol <pespin@sysmocom.de>
6#
7# SPDX-License-Identifier: MIT
8#
9# Permission is hereby granted, free of charge, to any person obtaining a copy
10# of this software and associated documentation files (the "Software"), to deal
11# in the Software without restriction, including without limitation the rights
12# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13# copies of the Software, and to permit persons to whom the Software is
14# furnished to do so, subject to the following conditions:
15#
16# The above copyright notice and this permission notice (including the next
17# paragraph) shall be included in all copies or substantial portions of the
18# Software.
19#
20# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26# SOFTWARE.
27
28
29import socket
30import argparse
31import struct
32from ipaddress import ip_address, IPv4Address
33
34GTP1C_PORT = 2123
35BUF_SIZE = 4096
36
37GTP_HDRv1_FLAG_PN = (1<<0)
38GTP_HDRv1_FLAG_S = (1<<1)
39GTP_HDRv1_FLAG_E = (1<<2)
40GTP_HDRv1_PT_GTP = (1<<4)
41GTP_HDRv1_VER_GTP1 = (1<<5)
42
43GTP_HDRv2_FLAG_T = (1<<3)
44GTP_HDRv2_FLAG_P = (1<<4)
45GTP_HDRv2_VER_GTP2 = (2<<5)
46
47def gen_gtpc_v1_hdr(flags, type, length, tei, seq=0, npdu=0, next=0):
48 spare = 0
49 if (flags & (GTP_HDRv1_FLAG_PN|GTP_HDRv1_FLAG_S|GTP_HDRv1_FLAG_E)):
50 #long format
51 length += 4
52 d = struct.pack('!BBHIHBB', flags, type, length, tei, seq, npdu, next)
53 else:
54 #short format
55 d = struct.pack('!BBHI', flags, type, length, tei)
56 return d
57
58def gen_gtpc_v2_hdr(flags, type, length, tei=0, seq=0):
59 spare = 0
60 if (flags & (GTP_HDRv2_FLAG_T)):
61 #long format, with TEI
62 length += 4 + 4
63 d = struct.pack('!BBHIHBB', flags, type, length, tei, seq >> 8, seq & 0xff, spare)
64 else:
65 #short format
66 length += 4
67 d = struct.pack('!BBHHBB', flags, type, length, seq >> 8, seq & 0xff, spare)
68 return d
69
70def gen_gtpc_v1_echo_req(tei=0, append_flags=0, seq=0, npdu=0, next=0):
71 return gen_gtpc_v1_hdr(GTP_HDRv1_VER_GTP1 | GTP_HDRv1_PT_GTP | append_flags, 1, 0, tei, seq, npdu, next)
72
73def gen_gtpc_v2_echo_req(append_flags=0, seq=0, recovery=0, node_features=-1):
74 length = 0
75 payload = b''
76 if (recovery > 0):
77 recovery_ie = struct.pack('!BHBB', 3, 1, 0, recovery)
78 payload += recovery_ie
79 length += len(recovery_ie)
80 if (node_features > 0):
81 node_features_ie = struct.pack('!BHBB', 152, 1, 0, node_features)
82 payload += node_features_ie
83 length += len(node_features_ie)
84 return gen_gtpc_v2_hdr(GTP_HDRv2_VER_GTP2 | append_flags, 1, length, 0, seq) + payload
85
86def tx_rx(sk, rem_addr, tx_buf, exp_rx = True):
87 print('Tx ECHO_REQ to %r: %r' % (repr(rem_addr), repr(tx_buf)))
88 sk.sendto(tx_buf, rem_addr)
89 if exp_rx:
90 rx_buf = sk.recvfrom(BUF_SIZE)
91 msg = "Message from Server {}".format(rx_buf)
92 print(msg)
93
94if __name__ == '__main__':
95 p = argparse.ArgumentParser(description='Tester for gtp-echo-recorder.')
96 p.add_argument('-l', '--local-address', default='127.0.0.2', help="Local GTP address")
97 p.add_argument('-r', '--remote-address', default='127.0.0.1', help="Remote GTP address")
98 args = p.parse_args()
99
100 print('Binding socket on %r...' % repr((args.local_address, GTP1C_PORT)))
101 family = socket.AF_INET if type(ip_address(args.local_address)) is IPv4Address else socket.AF_INET6
102 sk = socket.socket(family=family, type=socket.SOCK_DGRAM)
103 sk.bind((args.local_address, GTP1C_PORT));
104
105 rem_addr = (args.remote_address, GTP1C_PORT)
106
107 tx_rx(sk, rem_addr, gen_gtpc_v1_echo_req())
108 tx_rx(sk, rem_addr, gen_gtpc_v1_echo_req(1, GTP_HDRv1_FLAG_S, seq=67))
109 tx_rx(sk, rem_addr, gen_gtpc_v2_echo_req(0, seq=300, recovery=-1, node_features=-1))
110 tx_rx(sk, rem_addr, gen_gtpc_v2_echo_req(0, seq=20, recovery=99, node_features=-1))
111 tx_rx(sk, rem_addr, gen_gtpc_v2_echo_req(0, seq=20, recovery=100, node_features=0xbb))