changeset 209:34f8549ff0b1

drop pcap component - moved to rtp-debug-utils repository
author Mychaela Falconia <falcon@freecalypso.org>
date Sun, 16 Apr 2023 08:25:19 +0000
parents 13d27ff5b5df
children 7e490a8efe8a
files .hgignore INSTALL Makefile PACKAGING doc/RTP-BFI-extension doc/RTP-analysis doc/Utils-overview pcap/Makefile pcap/rtp-cont-check.c pcap/rtp-g711-extr.c pcap/rtp-gsmfr-extr.c pcap/rtp-jitter-view.c
diffstat 12 files changed, 1 insertions(+), 1109 deletions(-) [+]
line wrap: on
line diff
--- a/.hgignore	Sat Feb 18 23:24:54 2023 +0000
+++ b/.hgignore	Sun Apr 16 08:25:19 2023 +0000
@@ -40,8 +40,3 @@
 ^miscutil/gsmrec-dump$
 ^miscutil/pcm16-raw2wav$
 ^miscutil/pcm16-wav2raw$
-
-^pcap/rtp-cont-check$
-^pcap/rtp-g711-extr$
-^pcap/rtp-gsmfr-extr$
-^pcap/rtp-jitter-view$
--- a/INSTALL	Sat Feb 18 23:24:54 2023 +0000
+++ b/INSTALL	Sun Apr 16 08:25:19 2023 +0000
@@ -82,15 +82,3 @@
 	efrtest/Makefile
 	frtest/Makefile
 	miscutil/Makefile
-	pcap/Makefile
-
-pcap subdirectory and libpcap dependency
-========================================
-
-The present package includes (as part of Division 2) a set of command line
-utilities for analyzing RTP streams that have been captured with tcpdump or
-equivalent tools in pcap format.  These utilities, described in the
-doc/RTP-analysis article, are built in the pcap subdirectory and naturally
-depend on libpcap.  If your system lacks libpcap and you don't need these RTP
-analysis utilities, you can edit the top level Makefile and remove pcap from
-the list in SUBDIR_UTILS.
--- a/Makefile	Sat Feb 18 23:24:54 2023 +0000
+++ b/Makefile	Sun Apr 16 08:25:19 2023 +0000
@@ -2,7 +2,7 @@
 CFLAGS=	-O2
 
 SUBDIR_LIBPROD=	libgsmefr libgsmfrp
-SUBDIR_UTILS=	amrconv efrtest frtest miscutil pcap
+SUBDIR_UTILS=	amrconv efrtest frtest miscutil
 SUBDIR_INT=	dev libtest
 
 SUBDIR=	${SUBDIR_LIBPROD} ${SUBDIR_UTILS} ${SUBDIR_INT}
--- a/PACKAGING	Sat Feb 18 23:24:54 2023 +0000
+++ b/PACKAGING	Sun Apr 16 08:25:19 2023 +0000
@@ -25,10 +25,6 @@
 classic libgsm - the latter is pre-existing software, not provided by
 Themyscira.
 
-themwi-pcap-utils: the set of command line utilities built in the pcap
-subdirectory, with a dependency on libpcap but no dependencies on any GSM
-libraries.
-
 With the division recommended above, the set of end-user packages will exhibit
 a sensible functional division from the user's perspective, and a clean and
 sensible dependency graph.
--- a/doc/RTP-BFI-extension	Sat Feb 18 23:24:54 2023 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,131 +0,0 @@
-We (Themyscira Wireless) have invented our own non-standard extension to the
-generally accepted standard for RTP-based transport of GSM FR and EFR traffic
-within a GSM RAN, on stretches running from a BTS to a TRAU-like component.
-
-The fundamental question is: when the radio subsystem of the BTS does not have
-any good traffic frame to send in a given 20 ms window, what should it do?  The
-generally accepted standard behavior is that no packet is sent, an intentional
-gap is created in the RTP stream (the next time an RTP packet does go out, the
-timestamp increments over the gap while the sequence number increments only by
-1, indicating an intentional gap rather than packet loss), and apparently the
-intent was/is that this gap in the RTP stream serves as the BFI (bad frame
-indication).
-
-The problem with this generally accepted gap-as-BFI approach is that it deprives
-the downstream transcoding MGW (a "soft TRAU" of sorts) of its timing source.
-If the TRAU-like entity on the receiving end of the RTP stream originating from
-the BTS were an RTP to TDM gateway, there would be no problem - such a gateway
-would have to buffer received RTP packets in order to synchronize to fixed TDM
-timing, and the absence of an RTP packet arriving in time would serve just fine
-as the BFI marker, signaling BFI condition to the Rx DTX handler.  But what if
-the G.711 interface on the 64 kbps side of the TRAU is also an RTP stream, this
-time going to a PSTN-via-SIP connectivity provider?  Now the TRAU-like component
-becomes a transcoding RTP forwarding MGW without any inherently fixed timing.
-
-If the desire is to implement a traditional TRAU in every way except for an
-RTP-based implementation instead of TDM-based, i.e., if the desire is to emit a
-fully continuous G.711 RTP stream from the MGW toward PSTN with comfort noise
-generation and in-band DTMF insertion happening inside the MGW, rather than
-emit gaps in the outgoing stream or punt CN generation (and DTMF) to VoIP
-network elements, this task becomes dramatically easier if the BTS can be
-forced to send an RTP packet in every 20 ms window, be it rain or shine,
-conveying either a good traffic frame or a BFI marker.
-
-Representing BFI markers in an RTP stream
-=========================================
-
-In the case of AMR codec, the existing standard RTP payload format already
-provides an obvious way to send a BFI marker: it is the NO_DATA frame type,
-i.e., FT=15 - see RFC 4867 section 4.3.2.  That same section also categorizes
-what we seek to do here as a "SHOULD NOT":
-
-   Note that packets containing only NO_DATA frames SHOULD NOT be
-   transmitted in any payload format configuration, [...]
-
-However, the just-quoted directive is a SHOULD NOT rather than a MUST NOT,
-and RFC 2119 states:
-
-   SHOULD NOT   This phrase, or the phrase "NOT RECOMMENDED" mean that
-   there may exist valid reasons in particular circumstances when the
-   particular behavior is acceptable or even useful, but the full
-   implications should be understood and the case carefully weighed
-   before implementing any behavior described with this label.
-
-Our situation is just that: in our particular circumstance (desire to implement
-a traditional GSM TRAU in an RTP-to-RTP environment with no TDM network to act
-as a rigid timing governor) a valid reason exists why this "SHOULD NOT" behavior
-is not only acceptable, but becomes necessary.  Thus in the case of AMR, we are
-good - there is no need to invent our own totally non-standard extensions to
-RTP payload format, it just needs to be a configurable option in the IP-based
-BTS or in OsmoMGW converting from an E1-based BTS to RTP.
-
-The same situation holds for the rarely-used HR1 codec: RFC 5993 extends GSM-HR
-RTP representation with a ToC byte modeled after the one defined for AMR in RFC
-4867.  Just like in AMR, GSM-HR ToC byte allows the possibility of a No_Data
-frame (FT=7 for GSM-HR), with exactly the same semantics - and exactly the same
-argument as above applies for sending such No_Data frames against the general
-SHOULD NOT.
-
-But what about the older FR and EFR codecs?  In the case of existing standard
-RTP payload formats for FR and EFR, there is no defined way to represent a BFI
-condition as distinct from any possible good traffic frame, and there lies our
-challenge.
-
-Inventing an RTP BFI marker for FR and EFR
-==========================================
-
-The existing code in osmo-bts-trx (but not in the osmo-bts-sysmo version of
-interest to us) already contains a partial implementation of what we seek to do
-here: it runs its own ECU instance in the case of a BFI from the channel
-decoding layer, and if there is still no luck, there is code present to send a
-BFI packet.  The implemented behavior is not useful for us because RTP output
-is still fully suppressed when the uplink is expected to be in DTX, and there
-is a higher-level check in common/l1sap.c (l1sap_tch_ind() function) that also
-suppresses RTP output, but still, the point is that someone did already write
-code for sending an RTP packet intended to serve as a BFI.  In the case of AMR,
-that code sends out the expected NO_DATA (aka AMR_BAD) frame type - but what
-about FR and EFR?
-
-The existing code in osmo-bts-trx sends its FR codec BFI as a valid-looking FR
-frame with all 260 content bits set to 0, and it sends its EFR codec BFI as a
-valid-looking EFR frame with all 244 content bits set to 0.  I (Mother Mychaela)
-have given consideration to using this all-zeros in-band BFI representation as
-our RTP BFI marker for ThemWi, but then rejected this idea and decided to
-implement our own non-standard extension to RTP payload format instead,
-described further below.
-
-The fundamental philosophical problem which I (Mother Mychaela) have with this
-in-band BFI representation is that in the world of ETSI and 3GPP standards, BFI
-has always been meant to be out-of-band, not in-band.  In the TRAU frame format
-defined in GSM 08.60 there is an explicit control bit that carries BFI - the
-condition is NOT to be derived from the 260 or 244 traffic frame bits carried
-in data bit positions.  Abusing one particular bit pattern within the regular
-260-bit or 244-bit frame, even if it happens to be all zeros, goes against the
-spirit of classic GSM and 3GPP.  Per the specs, an FR codec frame of all zeros
-would be a SID frame with all LAR coefficients set to 0, and standards-compliant
-FR decoders would accept it as a valid SID frame, not as BFI.  The situation is
-likely to be even worse with EFR, where a frame of all zeros would not be
-treated as SID (EFR SID code word is 95 ones instead of 95 zeros) and would
-probably produce garbage at the decoder output.
-
-Themyscira Wireless implemented solution
-========================================
-
-We have invented our own non-standard extension to RTP payload format for GSM
-FR and EFR codecs.  Our extension is as follows: wherever a BTS needs to send a
-BFI marker in the place of a traffic frame, instead of sending a 33-byte payload
-beginning with 0xD nibble or a 31-byte payload beginning with 0xC nibble, it
-needs to send a 2-byte payload formatted as follows:
-
-byte 0: 0xBF signature;
-byte 1: least-significant bit encoding TAF per GSM 06.31 or GSM 06.81,
-        section 6.1.1 in both documents; other bits are reserved.
-
-In the uplink direction, with an RTP stream going from a BTS to our "soft TRAU"
-MGW, our themwi-mgw recognizes these BFI packets and acts accordingly, feeding
-BFI and TAF to the spec-prescribed Rx DTX handler for FR or EFR.  However, if a
-BTS receives these BFI marker packets in the downlink direction as a result of
-TrFO (the RTP stream comes from the uplink of another GSM call), it simply
-discards them without any processing - because a BTS always runs on its own TDMA
-timing, there is no difference between receiving a BFI packet vs receiving no
-RTP packet at all for that 20 ms frame.
--- a/doc/RTP-analysis	Sat Feb 18 23:24:54 2023 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-The present package includes a number of utilities for analyzing RTP streams
-that have been captured with tcpdump or equivalent tools in pcap format.  In
-order to use any of these utilities, you need to have a pcap file (obviously),
-and you need to identify the RTP stream to be analyzed or extracted by either
-source or destination IP:port.  All tools begin by applying a filter,
-considering only those packets that are UDP in IPv4 (no IPv6 support currently),
-and only those that match the specified source or destination IP:port.  Every
-matched packet is checked for a valid RTP header, and then the actual RTP stream
-analysis or extraction takes place, depending on the specific tool:
-
-rtp-cont-check	This program checks the selected RTP stream for continuity.  It
-		verifies that every matched packet has the same SSRC, that the
-		sequence number always increments by 1 from each individual
-		packet to the next, and that the RTP header timestamp always
-		increments by 160 units.  (The assumption is that the
-		application at hand is in the traditional telephony domain,
-		with a sampling rate of 8000 samples/s and 20 ms packetization
-		for RTP.)  This tool also looks at the capture time deltas
-		between successive packets and reports the observed minimum and
-		maximum; by seeing min and max delta-T, a developer can easily
-		notice timing aberrations that aren't caught by RTP header
-		sequence number and timestamp checks.
-
-rtp-g711-extr	This program focuses on a single selected RTP stream like the
-		others, enforces its continuity just like rtp-cont-check, and
-		then further enforces that every RTP packet be a 160-byte
-		payload, presumed to be either PCMU or PCMA.  (The payload type
-		number is NOT considered, only the payload length.)  The
-		selected G.711 RTP stream is then extracted and written into a
-		raw binary file.
-
-rtp-gsmfr-extr	This program focuses on a single selected RTP stream like the
-		others, enforces its continuity just like rtp-cont-check, but
-		then further enforces that every RTP packet be one of these 3
-		possibilities: a GSM FR1 codec frame, a GSM EFR codec frame or
-		a Themyscira BFI marker as defined in the RTP-BFI-extension
-		document.  (The payload type number is NOT considered, only the
-		payload length and the characteristic signature of each of the
-		3 allowed possibilities.)  The selected RTP stream is then
-		extracted and written into a gsmx file (see Binary-file-format),
-		which can then be analyzed with gsmrec-dump or decoded to
-		playable WAV with gsmfr-decode or gsmefr-decode.
-
-rtp-jitter-view	This program analyzes a single selected RTP stream just like
-		rtp-cont-check, but instead of reporting minimum and maximum
-		time deltas for the entire stream, it prints the individual
-		capture time delta between every successive pair of packets.
--- a/doc/Utils-overview	Sat Feb 18 23:24:54 2023 +0000
+++ b/doc/Utils-overview	Sun Apr 16 08:25:19 2023 +0000
@@ -51,8 +51,3 @@
 
 pcm16-raw2wav		See PCM-file-formats article.
 pcm16-wav2raw
-
-rtp-cont-check		See RTP-analysis article.
-rtp-g711-extr
-rtp-gsmfr-extr
-rtp-jitter-view
--- a/pcap/Makefile	Sat Feb 18 23:24:54 2023 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,25 +0,0 @@
-CC=	gcc
-CFLAGS=	-O2
-PROGS=	rtp-cont-check rtp-g711-extr rtp-gsmfr-extr rtp-jitter-view
-INSTBIN=/opt/freecalypso/bin
-
-all:	${PROGS}
-
-rtp-cont-check:	rtp-cont-check.c
-	${CC} ${CFLAGS} -o $@ $@.c -lpcap
-
-rtp-g711-extr:	rtp-g711-extr.c
-	${CC} ${CFLAGS} -o $@ $@.c -lpcap
-
-rtp-gsmfr-extr:	rtp-gsmfr-extr.c
-	${CC} ${CFLAGS} -o $@ $@.c -lpcap
-
-rtp-jitter-view:	rtp-jitter-view.c
-	${CC} ${CFLAGS} -o $@ $@.c -lpcap
-
-install:
-	mkdir -p ${INSTBIN}
-	install -c ${PROGS} ${INSTBIN}
-
-clean:
-	rm -f *.o *.out ${PROGS}
--- a/pcap/rtp-cont-check.c	Sat Feb 18 23:24:54 2023 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,234 +0,0 @@
-/*
- * This program reads a pcap file, extracts packets belonging to a
- * particular RTP stream as identified by a source or destination
- * IP:port, and checks its continuity: verifies that the sequence
- * number always increments by 1 and that the timestamp always
- * increments by 160 units.  Finally, this program prints out
- * the minimum and maximum observed capture time deltas between
- * successive packets of the stream.
- *
- * The codec can be anything, and this program can also be used to
- * check continuity of RTP streams coming from PSTN/SIP, but the
- * core assumption is that packets must arrive every 20 ms, with
- * the timestamp field incrementing by 160 units each time.
- */
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/time.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <strings.h>
-#include <pcap/pcap.h>
-
-static pcap_t *pcap;
-static in_addr_t match_ip_addr;
-static u_short match_udp_port;
-static unsigned iphdr_addr_offset, udphdr_port_offset;
-static unsigned link_hdr_len, ethertype_offset;
-static int stream_init_flag, deltat_init_flag;
-static unsigned last_seq, last_tstamp, stream_ssrc;
-static struct timeval last_pkt_time;
-static unsigned deltat_min, deltat_max;
-
-static void
-check_dl_type()
-{
-	int dltype;
-
-	dltype = pcap_datalink(pcap);
-	switch (dltype) {
-	case DLT_EN10MB:
-		link_hdr_len = 14;
-		ethertype_offset = 12;
-		break;
-	case DLT_RAW:
-		link_hdr_len = 0;
-		break;
-	case DLT_LINUX_SLL:
-		link_hdr_len = 16;
-		ethertype_offset = 14;
-		break;
-	default:
-		fprintf(stderr, "error: unsupported data link type %d\n",
-			dltype);
-		exit(1);
-	}
-}
-
-static void
-rtp_stream_logic(rtp_hdr, pkt_idx, pkt_time)
-	u_char *rtp_hdr;
-	unsigned pkt_idx;
-	struct timeval *pkt_time;
-{
-	unsigned cur_seq, cur_tstamp, cur_ssrc;
-	struct timeval deltat;
-
-	cur_seq = (rtp_hdr[2] << 8) | rtp_hdr[3];
-	cur_tstamp = (rtp_hdr[4] << 24) | (rtp_hdr[5] << 16) |
-			(rtp_hdr[6] << 8) | rtp_hdr[7];
-	cur_ssrc = (rtp_hdr[8] << 24) | (rtp_hdr[9] << 16) |
-			(rtp_hdr[10] << 8) | rtp_hdr[11];
-	if (stream_init_flag) {
-		if (cur_ssrc != stream_ssrc) {
-			fprintf(stderr,
-		"error in packet #%u: SSRC change from 0x%08X to 0x%08X\n",
-				pkt_idx, stream_ssrc, cur_ssrc);
-			exit(1);
-		}
-		if (cur_seq != last_seq + 1 &&
-		    (cur_seq != 0 || last_seq != 0xFFFF)) {
-			fprintf(stderr,
-		"error in packet #%u: seq break from 0x%04X to 0x%04X\n",
-				pkt_idx, last_seq, cur_seq);
-			exit(1);
-		}
-		if (cur_tstamp != last_tstamp + 160) {
-			fprintf(stderr,
-		"error in packet #%u: timestamp break from 0x%08X to 0x%08X\n",
-				pkt_idx, last_tstamp, cur_tstamp);
-			exit(1);
-		}
-		if (timercmp(pkt_time, &last_pkt_time, <)) {
-			fprintf(stderr,
-			"packet #%u timing error: Rx time goes backward\n",
-				pkt_idx);
-			exit(1);
-		}
-		timersub(pkt_time, &last_pkt_time, &deltat);
-		if (deltat.tv_sec) {
-			fprintf(stderr,
-				"packet #%u timing error: Rx time gap >= 1 s\n",
-				pkt_idx);
-			exit(1);
-		}
-		if (deltat_init_flag) {
-			if (deltat.tv_usec < deltat_min)
-				deltat_min = deltat.tv_usec;
-			if (deltat.tv_usec > deltat_max)
-				deltat_max = deltat.tv_usec;
-		} else {
-			deltat_min = deltat.tv_usec;
-			deltat_max = deltat.tv_usec;
-			deltat_init_flag = 1;
-		}
-	} else {
-		stream_init_flag = 1;
-		stream_ssrc = cur_ssrc;
-	}
-	last_seq = cur_seq;
-	last_tstamp = cur_tstamp;
-	bcopy(pkt_time, &last_pkt_time, sizeof(struct timeval));
-}
-
-static void
-process_packet(pkt, caplen, pkt_idx, pkt_time)
-	u_char *pkt;
-	unsigned caplen, pkt_idx;
-	struct timeval *pkt_time;
-{
-	unsigned udplen;
-
-	if (caplen < link_hdr_len + 28)
-		return;
-	if (link_hdr_len) {
-		if (pkt[ethertype_offset] != 0x08)
-			return;
-		if (pkt[ethertype_offset+1] != 0x00)
-			return;
-		pkt += link_hdr_len;
-		caplen -= link_hdr_len;
-	}
-	/* check IP header */
-	if (pkt[0] != 0x45)
-		return;
-	if (pkt[9] != 17)	/* UDP */
-		return;
-	if (bcmp(pkt + iphdr_addr_offset, &match_ip_addr, 4))
-		return;
-	/* check UDP header */
-	if (bcmp(pkt + 20 + udphdr_port_offset, &match_udp_port, 2))
-		return;
-	/* it is our target - now scrutinize it */
-	udplen = (pkt[24] << 8) | pkt[25];
-	if (caplen < udplen + 20) {
-		fprintf(stderr,
-			"error: packet #%u is truncated in the capture\n",
-			pkt_idx);
-		exit(1);
-	}
-	if (udplen < 20) {
-		fprintf(stderr,
-		"error in packet #%u: UDP length is too short for RTP header\n",
-			pkt_idx);
-		exit(1);
-	}
-	if (pkt[28] != 0x80) {
-		fprintf(stderr,
-		"error in packet #%u: unsupported RTP header structure\n",
-			pkt_idx);
-		exit(1);
-	}
-	rtp_stream_logic(pkt + 28, pkt_idx, pkt_time);
-}
-
-main(argc, argv)
-	char **argv;
-{
-	char errbuf[PCAP_ERRBUF_SIZE];
-	u_char *pkt;
-	struct pcap_pkthdr pkthdr;
-	unsigned pkt_idx;
-
-	if (argc != 5) {
-		fprintf(stderr,
-			"usage: %s pcap-file src|dest ip-addr udp-port\n",
-			argv[0]);
-		exit(1);
-	}
-	pcap = pcap_open_offline(argv[1], errbuf);
-	if (!pcap) {
-		fprintf(stderr, "%s: %s\n", argv[1], errbuf);
-		exit(1);
-	}
-	check_dl_type();
-	if (!strcmp(argv[2], "src")) {
-		iphdr_addr_offset = 12;
-		udphdr_port_offset = 0;
-	} else if (!strcmp(argv[2], "dest")) {
-		iphdr_addr_offset = 16;
-		udphdr_port_offset = 2;
-	} else {
-		fprintf(stderr,
-		"error: direction argument must be \"src\" or \"dest\"\n");
-		exit(1);
-	}
-	match_ip_addr = inet_addr(argv[3]);
-	if (match_ip_addr == INADDR_NONE) {
-		fprintf(stderr, "error: IP address argument is invalid\n");
-		exit(1);
-	}
-	match_udp_port = htons(strtoul(argv[4], 0, 0));
-	for (pkt_idx = 0; ; pkt_idx++) {
-		pkt = pcap_next(pcap, &pkthdr);
-		if (!pkt)
-			break;
-		process_packet(pkt, (unsigned) pkthdr.caplen, pkt_idx,
-				&pkthdr.ts);
-	}
-	if (!stream_init_flag) {
-		fprintf(stderr, "error: specified RTP stream not found\n");
-		exit(1);
-	}
-	if (!deltat_init_flag) {
-		fprintf(stderr, "error: found only one matching packet\n");
-		exit(1);
-	}
-	printf("Minimum time delta: %u us\n", deltat_min);
-	printf("Maximum time delta: %u us\n", deltat_max);
-	exit(0);
-}
--- a/pcap/rtp-g711-extr.c	Sat Feb 18 23:24:54 2023 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,206 +0,0 @@
-/*
- * This program reads a pcap file, extracts packets belonging to a
- * particular RTP stream as identified by a source or destination
- * IP:port, and verifies that an unbroken RTP stream is present,
- * with 160-byte payloads corresponding to timestamp increments
- * of 160 units per packet, as expected for a G.711 (PCMU or PCMA)
- * RTP stream with 20 ms packetization.  The extracted G.711 stream
- * is written to a raw binary file.
- */
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <strings.h>
-#include <pcap/pcap.h>
-
-static pcap_t *pcap;
-static in_addr_t match_ip_addr;
-static u_short match_udp_port;
-static unsigned iphdr_addr_offset, udphdr_port_offset;
-static unsigned link_hdr_len, ethertype_offset;
-static FILE *outfile;
-static int stream_init_flag;
-static unsigned last_seq, last_tstamp, stream_ssrc;
-
-static void
-check_dl_type()
-{
-	int dltype;
-
-	dltype = pcap_datalink(pcap);
-	switch (dltype) {
-	case DLT_EN10MB:
-		link_hdr_len = 14;
-		ethertype_offset = 12;
-		break;
-	case DLT_RAW:
-		link_hdr_len = 0;
-		break;
-	case DLT_LINUX_SLL:
-		link_hdr_len = 16;
-		ethertype_offset = 14;
-		break;
-	default:
-		fprintf(stderr, "error: unsupported data link type %d\n",
-			dltype);
-		exit(1);
-	}
-}
-
-static void
-rtp_stream_logic(rtp_hdr, pkt_idx)
-	u_char *rtp_hdr;
-	unsigned pkt_idx;
-{
-	unsigned cur_seq, cur_tstamp, cur_ssrc;
-
-	cur_seq = (rtp_hdr[2] << 8) | rtp_hdr[3];
-	cur_tstamp = (rtp_hdr[4] << 24) | (rtp_hdr[5] << 16) |
-			(rtp_hdr[6] << 8) | rtp_hdr[7];
-	cur_ssrc = (rtp_hdr[8] << 24) | (rtp_hdr[9] << 16) |
-			(rtp_hdr[10] << 8) | rtp_hdr[11];
-	if (stream_init_flag) {
-		if (cur_ssrc != stream_ssrc) {
-			fprintf(stderr,
-		"error in packet #%u: SSRC change from 0x%08X to 0x%08X\n",
-				pkt_idx, stream_ssrc, cur_ssrc);
-			exit(1);
-		}
-		if (cur_seq != last_seq + 1 &&
-		    (cur_seq != 0 || last_seq != 0xFFFF)) {
-			fprintf(stderr,
-		"error in packet #%u: seq break from 0x%04X to 0x%04X\n",
-				pkt_idx, last_seq, cur_seq);
-			exit(1);
-		}
-		if (cur_tstamp != last_tstamp + 160) {
-			fprintf(stderr,
-		"error in packet #%u: timestamp break from 0x%08X to 0x%08X\n",
-				pkt_idx, last_tstamp, cur_tstamp);
-			exit(1);
-		}
-	} else {
-		stream_init_flag = 1;
-		stream_ssrc = cur_ssrc;
-	}
-	last_seq = cur_seq;
-	last_tstamp = cur_tstamp;
-}
-
-static void
-process_packet(pkt, caplen, pkt_idx)
-	u_char *pkt;
-	unsigned caplen, pkt_idx;
-{
-	unsigned udplen, payload_len;
-
-	if (caplen < link_hdr_len + 28)
-		return;
-	if (link_hdr_len) {
-		if (pkt[ethertype_offset] != 0x08)
-			return;
-		if (pkt[ethertype_offset+1] != 0x00)
-			return;
-		pkt += link_hdr_len;
-		caplen -= link_hdr_len;
-	}
-	/* check IP header */
-	if (pkt[0] != 0x45)
-		return;
-	if (pkt[9] != 17)	/* UDP */
-		return;
-	if (bcmp(pkt + iphdr_addr_offset, &match_ip_addr, 4))
-		return;
-	/* check UDP header */
-	if (bcmp(pkt + 20 + udphdr_port_offset, &match_udp_port, 2))
-		return;
-	/* it is our target - now scrutinize it */
-	udplen = (pkt[24] << 8) | pkt[25];
-	if (caplen < udplen + 20) {
-		fprintf(stderr,
-			"error: packet #%u is truncated in the capture\n",
-			pkt_idx);
-		exit(1);
-	}
-	if (udplen < 20) {
-		fprintf(stderr,
-		"error in packet #%u: UDP length is too short for RTP header\n",
-			pkt_idx);
-		exit(1);
-	}
-	if (pkt[28] != 0x80) {
-		fprintf(stderr,
-		"error in packet #%u: unsupported RTP header structure\n",
-			pkt_idx);
-		exit(1);
-	}
-	rtp_stream_logic(pkt + 28, pkt_idx);
-	payload_len = udplen - 20;
-	if (payload_len != 160) {
-		fprintf(stderr, "error in packet #%u: unsupported payload\n",
-			pkt_idx);
-		exit(1);
-	}
-	fwrite(pkt + 40, 1, payload_len, outfile);
-}
-
-main(argc, argv)
-	char **argv;
-{
-	char errbuf[PCAP_ERRBUF_SIZE];
-	u_char *pkt;
-	struct pcap_pkthdr pkthdr;
-	unsigned pkt_idx;
-
-	if (argc != 6) {
-		fprintf(stderr,
-		"usage: %s pcap-file src|dest ip-addr udp-port outfile\n",
-			argv[0]);
-		exit(1);
-	}
-	pcap = pcap_open_offline(argv[1], errbuf);
-	if (!pcap) {
-		fprintf(stderr, "%s: %s\n", argv[1], errbuf);
-		exit(1);
-	}
-	check_dl_type();
-	if (!strcmp(argv[2], "src")) {
-		iphdr_addr_offset = 12;
-		udphdr_port_offset = 0;
-	} else if (!strcmp(argv[2], "dest")) {
-		iphdr_addr_offset = 16;
-		udphdr_port_offset = 2;
-	} else {
-		fprintf(stderr,
-		"error: direction argument must be \"src\" or \"dest\"\n");
-		exit(1);
-	}
-	match_ip_addr = inet_addr(argv[3]);
-	if (match_ip_addr == INADDR_NONE) {
-		fprintf(stderr, "error: IP address argument is invalid\n");
-		exit(1);
-	}
-	match_udp_port = htons(strtoul(argv[4], 0, 0));
-	outfile = fopen(argv[5], "w");
-	if (!outfile) {
-		perror(argv[5]);
-		exit(1);
-	}
-	for (pkt_idx = 0; ; pkt_idx++) {
-		pkt = pcap_next(pcap, &pkthdr);
-		if (!pkt)
-			break;
-		process_packet(pkt, (unsigned) pkthdr.caplen, pkt_idx);
-	}
-	if (!stream_init_flag) {
-		fprintf(stderr, "error: specified RTP stream not found\n");
-		exit(1);
-	}
-	fclose(outfile);
-	exit(0);
-}
--- a/pcap/rtp-gsmfr-extr.c	Sat Feb 18 23:24:54 2023 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,219 +0,0 @@
-/*
- * This program reads a pcap file, extracts packets belonging to a
- * particular RTP stream as identified by a source or destination
- * IP:port, verifies that an unbroken RTP stream is present, in
- * GSM FR or EFR codec, and writes the FR/EFR frame stream to our
- * extended-libgsm format binary file, to be fed to decoding test
- * programs.
- */
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <strings.h>
-#include <pcap/pcap.h>
-
-static pcap_t *pcap;
-static in_addr_t match_ip_addr;
-static u_short match_udp_port;
-static unsigned iphdr_addr_offset, udphdr_port_offset;
-static unsigned link_hdr_len, ethertype_offset;
-static FILE *outfile;
-static int stream_init_flag;
-static unsigned last_seq, last_tstamp, stream_ssrc;
-
-static void
-check_dl_type()
-{
-	int dltype;
-
-	dltype = pcap_datalink(pcap);
-	switch (dltype) {
-	case DLT_EN10MB:
-		link_hdr_len = 14;
-		ethertype_offset = 12;
-		break;
-	case DLT_RAW:
-		link_hdr_len = 0;
-		break;
-	case DLT_LINUX_SLL:
-		link_hdr_len = 16;
-		ethertype_offset = 14;
-		break;
-	default:
-		fprintf(stderr, "error: unsupported data link type %d\n",
-			dltype);
-		exit(1);
-	}
-}
-
-static void
-rtp_stream_logic(rtp_hdr, pkt_idx)
-	u_char *rtp_hdr;
-	unsigned pkt_idx;
-{
-	unsigned cur_seq, cur_tstamp, cur_ssrc;
-
-	cur_seq = (rtp_hdr[2] << 8) | rtp_hdr[3];
-	cur_tstamp = (rtp_hdr[4] << 24) | (rtp_hdr[5] << 16) |
-			(rtp_hdr[6] << 8) | rtp_hdr[7];
-	cur_ssrc = (rtp_hdr[8] << 24) | (rtp_hdr[9] << 16) |
-			(rtp_hdr[10] << 8) | rtp_hdr[11];
-	if (stream_init_flag) {
-		if (cur_ssrc != stream_ssrc) {
-			fprintf(stderr,
-		"error in packet #%u: SSRC change from 0x%08X to 0x%08X\n",
-				pkt_idx, stream_ssrc, cur_ssrc);
-			exit(1);
-		}
-		if (cur_seq != last_seq + 1 &&
-		    (cur_seq != 0 || last_seq != 0xFFFF)) {
-			fprintf(stderr,
-		"error in packet #%u: seq break from 0x%04X to 0x%04X\n",
-				pkt_idx, last_seq, cur_seq);
-			exit(1);
-		}
-		if (cur_tstamp != last_tstamp + 160) {
-			fprintf(stderr,
-		"error in packet #%u: timestamp break from 0x%08X to 0x%08X\n",
-				pkt_idx, last_tstamp, cur_tstamp);
-			exit(1);
-		}
-	} else {
-		stream_init_flag = 1;
-		stream_ssrc = cur_ssrc;
-	}
-	last_seq = cur_seq;
-	last_tstamp = cur_tstamp;
-}
-
-static void
-process_packet(pkt, caplen, pkt_idx)
-	u_char *pkt;
-	unsigned caplen, pkt_idx;
-{
-	unsigned udplen, payload_len;
-
-	if (caplen < link_hdr_len + 28)
-		return;
-	if (link_hdr_len) {
-		if (pkt[ethertype_offset] != 0x08)
-			return;
-		if (pkt[ethertype_offset+1] != 0x00)
-			return;
-		pkt += link_hdr_len;
-		caplen -= link_hdr_len;
-	}
-	/* check IP header */
-	if (pkt[0] != 0x45)
-		return;
-	if (pkt[9] != 17)	/* UDP */
-		return;
-	if (bcmp(pkt + iphdr_addr_offset, &match_ip_addr, 4))
-		return;
-	/* check UDP header */
-	if (bcmp(pkt + 20 + udphdr_port_offset, &match_udp_port, 2))
-		return;
-	/* it is our target - now scrutinize it */
-	udplen = (pkt[24] << 8) | pkt[25];
-	if (caplen < udplen + 20) {
-		fprintf(stderr,
-			"error: packet #%u is truncated in the capture\n",
-			pkt_idx);
-		exit(1);
-	}
-	if (udplen < 20) {
-		fprintf(stderr,
-		"error in packet #%u: UDP length is too short for RTP header\n",
-			pkt_idx);
-		exit(1);
-	}
-	if (pkt[28] != 0x80) {
-		fprintf(stderr,
-		"error in packet #%u: unsupported RTP header structure\n",
-			pkt_idx);
-		exit(1);
-	}
-	rtp_stream_logic(pkt + 28, pkt_idx);
-	payload_len = udplen - 20;
-	switch (payload_len) {
-	case 2:
-		if (pkt[40] == 0xBF)
-			break;
-		goto bad_payload;
-	case 31:
-		if ((pkt[40] & 0xF0) == 0xC0)
-			break;
-		goto bad_payload;
-	case 33:
-		if ((pkt[40] & 0xF0) == 0xD0)
-			break;
-		/* FALL THRU */
-	default:
-	bad_payload:
-		fprintf(stderr, "error in packet #%u: unsupported payload\n",
-			pkt_idx);
-		exit(1);
-	}
-	fwrite(pkt + 40, 1, payload_len, outfile);
-}
-
-main(argc, argv)
-	char **argv;
-{
-	char errbuf[PCAP_ERRBUF_SIZE];
-	u_char *pkt;
-	struct pcap_pkthdr pkthdr;
-	unsigned pkt_idx;
-
-	if (argc != 6) {
-		fprintf(stderr,
-		"usage: %s pcap-file src|dest ip-addr udp-port outfile\n",
-			argv[0]);
-		exit(1);
-	}
-	pcap = pcap_open_offline(argv[1], errbuf);
-	if (!pcap) {
-		fprintf(stderr, "%s: %s\n", argv[1], errbuf);
-		exit(1);
-	}
-	check_dl_type();
-	if (!strcmp(argv[2], "src")) {
-		iphdr_addr_offset = 12;
-		udphdr_port_offset = 0;
-	} else if (!strcmp(argv[2], "dest")) {
-		iphdr_addr_offset = 16;
-		udphdr_port_offset = 2;
-	} else {
-		fprintf(stderr,
-		"error: direction argument must be \"src\" or \"dest\"\n");
-		exit(1);
-	}
-	match_ip_addr = inet_addr(argv[3]);
-	if (match_ip_addr == INADDR_NONE) {
-		fprintf(stderr, "error: IP address argument is invalid\n");
-		exit(1);
-	}
-	match_udp_port = htons(strtoul(argv[4], 0, 0));
-	outfile = fopen(argv[5], "w");
-	if (!outfile) {
-		perror(argv[5]);
-		exit(1);
-	}
-	for (pkt_idx = 0; ; pkt_idx++) {
-		pkt = pcap_next(pcap, &pkthdr);
-		if (!pkt)
-			break;
-		process_packet(pkt, (unsigned) pkthdr.caplen, pkt_idx);
-	}
-	if (!stream_init_flag) {
-		fprintf(stderr, "error: specified RTP stream not found\n");
-		exit(1);
-	}
-	fclose(outfile);
-	exit(0);
-}
--- a/pcap/rtp-jitter-view.c	Sat Feb 18 23:24:54 2023 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,220 +0,0 @@
-/*
- * This program reads a pcap file, extracts packets belonging to a
- * particular RTP stream as identified by a source or destination
- * IP:port, checks its continuity at the packet header level
- * (verifies that the sequence number always increments by 1 and
- * that the timestamp always increments by 160 units) and prints out
- * the Rx time delta of each stream packet (the capture time of
- * the current packet minus the capture time of the previous packet)
- * on stdout, allowing visual analysis of timing jitter.
- *
- * The codec can be anything, and this program can also be used to
- * examine the jitter of RTP streams coming from PSTN/SIP, but the
- * core assumption is that packets must arrive every 20 ms, with
- * the timestamp field incrementing by 160 units each time.
- */
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/time.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <strings.h>
-#include <pcap/pcap.h>
-
-static pcap_t *pcap;
-static in_addr_t match_ip_addr;
-static u_short match_udp_port;
-static unsigned iphdr_addr_offset, udphdr_port_offset;
-static unsigned link_hdr_len, ethertype_offset;
-static int stream_init_flag;
-static unsigned last_seq, last_tstamp, stream_ssrc;
-static struct timeval last_pkt_time;
-
-static void
-check_dl_type()
-{
-	int dltype;
-
-	dltype = pcap_datalink(pcap);
-	switch (dltype) {
-	case DLT_EN10MB:
-		link_hdr_len = 14;
-		ethertype_offset = 12;
-		break;
-	case DLT_RAW:
-		link_hdr_len = 0;
-		break;
-	case DLT_LINUX_SLL:
-		link_hdr_len = 16;
-		ethertype_offset = 14;
-		break;
-	default:
-		fprintf(stderr, "error: unsupported data link type %d\n",
-			dltype);
-		exit(1);
-	}
-}
-
-static void
-rtp_stream_logic(rtp_hdr, pkt_idx, pkt_time)
-	u_char *rtp_hdr;
-	unsigned pkt_idx;
-	struct timeval *pkt_time;
-{
-	unsigned cur_seq, cur_tstamp, cur_ssrc;
-	struct timeval deltat;
-
-	cur_seq = (rtp_hdr[2] << 8) | rtp_hdr[3];
-	cur_tstamp = (rtp_hdr[4] << 24) | (rtp_hdr[5] << 16) |
-			(rtp_hdr[6] << 8) | rtp_hdr[7];
-	cur_ssrc = (rtp_hdr[8] << 24) | (rtp_hdr[9] << 16) |
-			(rtp_hdr[10] << 8) | rtp_hdr[11];
-	if (stream_init_flag) {
-		if (cur_ssrc != stream_ssrc) {
-			fprintf(stderr,
-		"error in packet #%u: SSRC change from 0x%08X to 0x%08X\n",
-				pkt_idx, stream_ssrc, cur_ssrc);
-			exit(1);
-		}
-		if (cur_seq != last_seq + 1 &&
-		    (cur_seq != 0 || last_seq != 0xFFFF)) {
-			fprintf(stderr,
-		"error in packet #%u: seq break from 0x%04X to 0x%04X\n",
-				pkt_idx, last_seq, cur_seq);
-			exit(1);
-		}
-		if (cur_tstamp != last_tstamp + 160) {
-			fprintf(stderr,
-		"error in packet #%u: timestamp break from 0x%08X to 0x%08X\n",
-				pkt_idx, last_tstamp, cur_tstamp);
-			exit(1);
-		}
-		if (timercmp(pkt_time, &last_pkt_time, <)) {
-			fprintf(stderr,
-			"packet #%u timing error: Rx time goes backward\n",
-				pkt_idx);
-			exit(1);
-		}
-		timersub(pkt_time, &last_pkt_time, &deltat);
-		if (deltat.tv_sec) {
-			fprintf(stderr,
-				"packet #%u timing error: Rx time gap >= 1 s\n",
-				pkt_idx);
-			exit(1);
-		}
-		printf("Packet #%u: time delta %u us\n", pkt_idx,
-			(unsigned) deltat.tv_usec);
-	} else {
-		stream_init_flag = 1;
-		stream_ssrc = cur_ssrc;
-	}
-	last_seq = cur_seq;
-	last_tstamp = cur_tstamp;
-	bcopy(pkt_time, &last_pkt_time, sizeof(struct timeval));
-}
-
-static void
-process_packet(pkt, caplen, pkt_idx, pkt_time)
-	u_char *pkt;
-	unsigned caplen, pkt_idx;
-	struct timeval *pkt_time;
-{
-	unsigned udplen;
-
-	if (caplen < link_hdr_len + 28)
-		return;
-	if (link_hdr_len) {
-		if (pkt[ethertype_offset] != 0x08)
-			return;
-		if (pkt[ethertype_offset+1] != 0x00)
-			return;
-		pkt += link_hdr_len;
-		caplen -= link_hdr_len;
-	}
-	/* check IP header */
-	if (pkt[0] != 0x45)
-		return;
-	if (pkt[9] != 17)	/* UDP */
-		return;
-	if (bcmp(pkt + iphdr_addr_offset, &match_ip_addr, 4))
-		return;
-	/* check UDP header */
-	if (bcmp(pkt + 20 + udphdr_port_offset, &match_udp_port, 2))
-		return;
-	/* it is our target - now scrutinize it */
-	udplen = (pkt[24] << 8) | pkt[25];
-	if (caplen < udplen + 20) {
-		fprintf(stderr,
-			"error: packet #%u is truncated in the capture\n",
-			pkt_idx);
-		exit(1);
-	}
-	if (udplen < 20) {
-		fprintf(stderr,
-		"error in packet #%u: UDP length is too short for RTP header\n",
-			pkt_idx);
-		exit(1);
-	}
-	if (pkt[28] != 0x80) {
-		fprintf(stderr,
-		"error in packet #%u: unsupported RTP header structure\n",
-			pkt_idx);
-		exit(1);
-	}
-	rtp_stream_logic(pkt + 28, pkt_idx, pkt_time);
-}
-
-main(argc, argv)
-	char **argv;
-{
-	char errbuf[PCAP_ERRBUF_SIZE];
-	u_char *pkt;
-	struct pcap_pkthdr pkthdr;
-	unsigned pkt_idx;
-
-	if (argc != 5) {
-		fprintf(stderr,
-			"usage: %s pcap-file src|dest ip-addr udp-port\n",
-			argv[0]);
-		exit(1);
-	}
-	pcap = pcap_open_offline(argv[1], errbuf);
-	if (!pcap) {
-		fprintf(stderr, "%s: %s\n", argv[1], errbuf);
-		exit(1);
-	}
-	check_dl_type();
-	if (!strcmp(argv[2], "src")) {
-		iphdr_addr_offset = 12;
-		udphdr_port_offset = 0;
-	} else if (!strcmp(argv[2], "dest")) {
-		iphdr_addr_offset = 16;
-		udphdr_port_offset = 2;
-	} else {
-		fprintf(stderr,
-		"error: direction argument must be \"src\" or \"dest\"\n");
-		exit(1);
-	}
-	match_ip_addr = inet_addr(argv[3]);
-	if (match_ip_addr == INADDR_NONE) {
-		fprintf(stderr, "error: IP address argument is invalid\n");
-		exit(1);
-	}
-	match_udp_port = htons(strtoul(argv[4], 0, 0));
-	for (pkt_idx = 0; ; pkt_idx++) {
-		pkt = pcap_next(pcap, &pkthdr);
-		if (!pkt)
-			break;
-		process_packet(pkt, (unsigned) pkthdr.caplen, pkt_idx,
-				&pkthdr.ts);
-	}
-	if (!stream_init_flag) {
-		fprintf(stderr, "error: specified RTP stream not found\n");
-		exit(1);
-	}
-	exit(0);
-}