//
// Copyright 2013-2014 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// 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 .
//
#include
#include
#include
#include
#include
#include
#include
#include "uhd_dump.h"
//#define DEBUG 1
void usage()
{
fprintf(stderr,"Usage: chdr_dump [-h host_ip] filename.pcap\n");
exit(2);
}
int main(int argc, char *argv[])
{
struct pbuf_info *packet_buffer; // Store all packets of interest here
struct in_addr host_addr; // Apparent Host IP addr in this capture
struct in_addr usrp_addr; // Apparent USRP IP addr in this capture
struct timeval *origin_ts; // Timestamp of first packet in file.
long long origin_ts_in_us;
int direction; // Flag to show direction of packet flow. 0=H->U, 1=U->H.
int packet_count[2]; // Number of packets that match filter
double size_average[2]; // Average size of packets Host to USRP
int size_histogram[90][2]; // Array captures histogram of packet sizes Host to USRP in 100 byte bins
int x; // Local integer scratch variables
char *conversion_error[1];
int c;
char buffer[26]; // Buffer to format GMT time stamp strings for output
double time_since_start; // Time elapsed in seconds since start
const struct ip_header *ip_header;
u32 *dump_header;
host_addr.s_addr = 0x0;
//usrp_addr.s_addr = 0x0;
while ((c = getopt(argc, argv, "h:u:")) != -1) {
switch(c) {
case 'h':
// Explicit IP address for host on command line
if (*optarg == '\0')
usage();
host_addr.s_addr = strtol(strtok(optarg,"."),conversion_error,10) ;
if (**conversion_error != '\0')
usage();
host_addr.s_addr = host_addr.s_addr | strtol(strtok(NULL,"."),conversion_error,10) << 8;
if (**conversion_error != '\0')
usage();
host_addr.s_addr = host_addr.s_addr | strtol(strtok(NULL,"."),conversion_error,10) << 16;
if (**conversion_error != '\0')
usage();
host_addr.s_addr = host_addr.s_addr | strtol(strtok(NULL,"\0"),conversion_error,10) << 24;
if (**conversion_error != '\0')
usage();
break;
case 'u':
// Explicit IP address for USRP on command line
if (*optarg == '\0')
usage();
usrp_addr.s_addr = strtol(strtok(optarg,"."),conversion_error,10) ;
if (**conversion_error != '\0')
usage();
usrp_addr.s_addr = usrp_addr.s_addr | strtol(strtok(NULL,"."),conversion_error,10) << 8;
if (**conversion_error != '\0')
usage();
usrp_addr.s_addr = usrp_addr.s_addr | strtol(strtok(NULL,"."),conversion_error,10) << 16;
if (**conversion_error != '\0')
usage();
usrp_addr.s_addr = usrp_addr.s_addr | strtol(strtok(NULL,"\0"),conversion_error,10) << 24;
if (**conversion_error != '\0')
usage();
break;
case'?':
default:
usage();
}
}
argc -= (optind - 1);
argv += (optind -1);
// Just a mandatory pcap filename for now, better parser and options later.
if (argc != 2) {
usage();
}
// Init packet buffer
packet_buffer = malloc(sizeof(struct pbuf_info));
// Init origin timestamp
origin_ts = malloc(sizeof(struct timeval));
// Go read matching packets from capture file into memory
get_udp_port_from_file(CHDR_PORT,argv[1],packet_buffer,origin_ts);
// Extract origin tome of first packet and convert to uS.
origin_ts_in_us = origin_ts->tv_sec * 1000000 + origin_ts->tv_usec;
// Count number of packets in capture
packet_buffer->current = packet_buffer->start;
x = 0;
while (packet_buffer->current != NULL) {
x++;
packet_buffer->current = packet_buffer->current->next;
}
fprintf(stdout,"\n===================================================================\n");
fprintf(stdout,"\n Total matching packet count in capture file: %d\n",x);
fprintf(stdout,"\n===================================================================\n\n");
// If no packets were CHDR then just exit now
if (x == 0) {
exit(0);
}
// Determine host and USRP IP addresses so that we can classify direction of packet flow later.
if (host_addr.s_addr == 0x0)
get_connection_endpoints(packet_buffer,&host_addr,&usrp_addr);
// Count packets in list.
// Build histogram of packet sizes
// Build histogram of Stream ID's
packet_buffer->current = packet_buffer->start;
for (x=0;x<90;x+=1)
size_histogram[x][H2U] = size_histogram[x][U2H] = 0;
size_average[H2U] = size_average[U2H] = 0;
packet_count[H2U] = packet_count[U2H] = 0;
while (packet_buffer->current != NULL) {
// Overlay IP header on packet payload
ip_header = (struct ip_header *)(packet_buffer->current->payload+ETH_SIZE);
// Identify packet direction
if (ip_header->ip_src.s_addr == host_addr.s_addr)
direction = H2U;
else
direction = U2H;
packet_count[direction]++;
size_average[direction]+=(double)packet_buffer->current->size;
if ((x=packet_buffer->current->size) > 9000)
fprintf(stderr,"Current packet size = %d at absolute time %s, relative time %f, exceeds MTU! Skip counting.",
x,format_gmt(&packet_buffer->current->ts,buffer),(relative_time(&packet_buffer->current->ts,origin_ts)));
else
size_histogram[x/100][direction]++;
packet_buffer->current = packet_buffer->current->next;
}
fprintf(stdout,"\n===================================================================\n");
fprintf(stdout,"\n Average packet size Host -> USRP: %d\n",(int)(size_average[H2U]/packet_count[H2U]));
fprintf(stdout,"\n Average packet size USRP -> Host: %d\n",(int)(size_average[U2H]/packet_count[U2H]));
fprintf(stdout,"\n===================================================================\n\n");
//
// Now produce packet by packet log
//
packet_buffer->current = packet_buffer->start;
x = 0;
while (packet_buffer->current != NULL) {
x++;
// Calculate time offset of this packet from start
time_since_start = ((double) packet_buffer->current->ts.tv_sec * 1000000 + packet_buffer->current->ts.tv_usec - origin_ts_in_us)/1000000;
dump_header = (u32 *) (packet_buffer->current->payload+ETH_SIZE+IP_SIZE+UDP_SIZE);
/* fprintf(stdout,"DUMP: %08x %08x %08x %08x %08x %08x\n", */
/* swapint((int) *(dump_header)), */
/* swapint((int) *(dump_header+1)), */
/* swapint((int) *(dump_header+2)), */
/* swapint((int) *(dump_header+3)), */
/* swapint((int) *(dump_header+4)), */
/* swapint((int) *(dump_header+5))); */
// Extract the device portion of the SID to see which packet flow this belongs in
fprintf(stdout,"%8d %f \t",x,time_since_start);
print_direction(packet_buffer,&host_addr,&usrp_addr);
fprintf(stdout,"\t");
print_size(packet_buffer);
fprintf(stdout,"\t");
print_sid(packet_buffer);
fprintf(stdout,"\t");
print_vita_header(packet_buffer,&host_addr);
fprintf(stdout,"\n");
packet_buffer->current = packet_buffer->current->next;
}
// Normal Exit
return(0);
}