/* * Mausezahn - A fast versatile traffic generator * Copyright (C) 2008 Herbert Haas * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License version 2 as published by the * Free Software Foundation. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License along with * this program; if not, see http://www.gnu.org/licenses/gpl-2.0.html * */ #include "mz.h" #include "cli.h" #include "mops.h" #define MZ_RTP_HELP \ "| RTP type: Send Real Time Protocol packets.\n" \ "|\n" \ "| This mode is solely intended to conduct delay, drop, and jitter measurements in\n" \ "| Voice (Video) over IP networks. You will typically initiate another Mausezahn\n" \ "| instance on the destination host, which will perform the measurements or even\n" \ "| 'bounce back' the packets for Round Trip Time (RTT) measurements.\n" \ "|\n" \ "| When the delay parameter is not specified, the default (inter-packet) delay is\n" \ "| set to 20 msec. You must specify the destination host using the -B option.\n" \ "| The default destination port is (UDP) 30000 but can be overridden (dp parameter).\n" \ "| You do not need to specify the count option (-c), because 'infinite' (0) is assumed.\n" \ "|\n" \ "| You can specify these additional GENERAL options:\n" \ "|\n" \ "| -c ..... use this packet count value instead of infinity.\n" \ "| -d ..... use this delay value instead of the defaul. Per default\n" \ "| the units are microseconds but you can also use msec or sec\n" \ "|\n" \ "| You can specify these additional UDP/RTP-specific arguments:\n" \ "|\n" \ "| dp = <1-65535> ..... use this UDP destination port instead of 30,000.\n" \ "| sp = <1-65535> ..... use this UDP source port instead of random.\n" \ "| ssrc = XX:XX:XX:XX ... use this hex sequence as stream identifier\n" \ "| (=SSRC, required for multiple concurrent measurements)\n" \ "| codec ..... simulate G.711 codec (other will follow).\n" \ "| pld = <1..1000> ....... create specified payload size (default=160 bytes, which results\n" \ "| in a total datagram length of 180 bytes, considering the UDP and\n" \ "| RTP header lengths (8 and 12 bytes, respectively).\n" \ "|\n" \ "| Additional help: enter 'mz -T rtp help'\n" \ "|\n" int create_rtp_packet(void) { u_int8_t byte1, byte2; u_int16_t seqnr; u_int8_t ssrc[4] = {0,0,0,0} ; int ssrc_s = 0; u_int8_t *ptr; char argval[MAX_PAYLOAD_SIZE]; unsigned int rtp_payload_size=160; struct mz_timestamp ts; if ( (getarg(tx.arg_string,"help", NULL)==1) && (mode==RTP) ) { if (mz_port) { cli_print(gcli, "%s", MZ_RTP_HELP); return -1; } else { fprintf(stderr,"\n" MAUSEZAHN_VERSION "\n%s", MZ_RTP_HELP); exit(0); } } if (getarg(tx.arg_string,"pld", argval)==1) { rtp_payload_size = (unsigned int) str2int(argval); } if (getarg(tx.arg_string,"codec", argval)==1) { tx.delay = 20000; } if (getarg(tx.arg_string,"ssrc", argval)==1) { ssrc_s = str2hex(argval, ssrc, 4); if (ssrc_s<0) { fprintf(stderr, " mz/rtp: invalid ssrc!\n"); return -1; } } // TODO: Optional arguments for RTP // Create header: // // Byte 1 // // +--+--+--+--+--+--+--+--+ // | ver | P| X| CSRC Count| // +--+--+--+--+--+--+--+--+ // // Default: ver=2, Padding=0, Extension_Header=1, CSRC_Count=0 => 10 0 1 0000 = 0x90 byte1 = 0x90; // Byte 2 // // +--+--+--+--+--+--+--+--+ // | M| Payload Type | // +--+--+--+--+--+--+--+--+ // // Marker=0, Payload Type=0 (or 8 alternatively) byte2 = 0x00; // Bytes 3,4 // // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ // | Sequence Number | // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ seqnr = 0x0000; // Bytes 5,6,7,8 // // Timestamp /* done below */ // // Bytes 9,10,11,12 // // Synchronization Source Identifier // if (ssrc_s==0) str2hex("ca:fe:fe:ed", ssrc, 4); // Bytes 13,14,15,16 // // CSRC - Contributing Source Identifiers (optional, only used by mixers) // // csrc = 0x00000000; // Bytes 17,18,19,20 // // Header Extension (optional) NOT USED HERE! // // !!! Thus payload begins with index 16 in a C array !!! // ------------ Now combine all fields: ---------------- tx.udp_payload[0] = byte1; tx.udp_payload[1] = byte2; ptr = (u_int8_t*) &seqnr; tx.udp_payload[2] = *(ptr+1); tx.udp_payload[3] = *ptr; // TIMESTAMP: will be linearly increased, e.g. using 20msec G.711: 0, 160, 320, ... tx.udp_payload[4] = 0x00; tx.udp_payload[5] = 0x00; tx.udp_payload[6] = 0x00; tx.udp_payload[7] = 0x00; tx.udp_payload[8] = ssrc[0]; tx.udp_payload[9] = ssrc[1]; tx.udp_payload[10] = ssrc[2]; tx.udp_payload[11] = ssrc[3]; /* ptr = (u_int8_t*) &csrc; tx.udp_payload[12] = *(ptr+3); tx.udp_payload[13] = *(ptr+2); tx.udp_payload[14] = *(ptr+1); tx.udp_payload[15] = *ptr; */ // Add the NEW Mausezahn extension header (see mops_ext_rtp.c) tx.udp_payload[12] = 0xca; // identifier tx.udp_payload[13] = 0xca; tx.udp_payload[14] = 0x00; tx.udp_payload[15] = 0x04; // length getcurtime(&ts); // Now add TX timestamp: mops_hton4 ((u_int32_t*) &ts.sec, &tx.udp_payload[16]); mops_hton4 ((u_int32_t*) &ts.nsec, &tx.udp_payload[20]); // NOTE: The remaining 8 bytes of this extension header are set to zero // via the following code. memset(&tx.udp_payload[24], 0x00, (rtp_payload_size-12)); // payload (considering our 8 byte timestamp) tx.udp_payload_s = 12 + rtp_payload_size; // the latter ist the payload size // ---------- now hand over to UDP ----------------- tx.dp = 30000; tx.sp = 30000; tx.udp_len = 8 + tx.udp_payload_s; return 0; }