Sandeep,

This is a sample config from the StoreUDPTimeSeqRecord.hh file

    src :: RatedSource(\<00>, LENGTH 22, RATE 1, LIMIT 100)
        -> UDPIPEncap(10.0.1.1, 6667, 20.0.0.2, 6667)
        -> EtherEncap(0x0800, 00:04:23:D0:93:63, 00:17:cb:0d:f8:db)
        -> StoreUDPTimeSeqRecord(OFFSET 14, DELTA false)
        -> DelayShaper(100msec)
        -> StoreUDPTimeSeqRecord(OFFSET 14, DELTA true)
        -> ToDump("dump.dmp");


I have attached a piece of code that I use to print out arrival times, delays,
inter-arrivals, etc. (results go into MATLAB for plotting) The code is not very
polished but should give you an idea what is going on.  

Let me know if you have any questions.

Roman

On Tue, 6 Sep 2011 11:10:34 +0100 sandeep <sandeep...@gmail.com> wrote

> Dear Roman,
> 
> Thanks for your email. Can you please send a sample click script used
> with StoreUDPTimeSeqRecord element and C program to decipher the pcap dump.
> 
> Kind Regards,
> Sandeep
> 
> On Monday, September 5, 2011, Roman Chertov wrote:
> 
> > Sandeep,
> >
> > You might also want to use StoreUDPTimeSeqRecord element to embed time and
> > sequence number information into packets.
> >
> >
http://read.cs.ucla.edu/click/**elements/storeudptimeseqrecord<http://read.cs
> > .ucla.edu/click/elements/storeudptimeseqrecord>
> >
> > In my experiments, I typically always save the packets to a PCAP file
> > (ToDump) element, and then use a C program to look at the PCAP file and
> > extract the appropriate statistics.  I can send the code which computes
> > delays, inter-arrival times, arrival times, etc. to the list tomorrow.
> >
> > Roman
> >
> > On 09/05/2011 04:45 AM, sandeep wrote:
> >
> >> Hi,
> >>
> >> I am using StoreTimestamp element to put a timestamp at the tail of a
> >> packet. Can anyone tell me how to extract the timestamp value out of it on
> >> the receive end or from the dump file.
> >>
> >> -----
> >> My analysis is as follows:
> >> The source code which does this is.
> >> memcpy(q->data() + offset,&q->timestamp_anno(), 8);
> >>
> >> I looks like pointer to Timestamp is written during this memcpy operation.
> >>
> >> I managed to print the timestamp string using
> >> printf("Timestamp is %s\n",
> >> ((&q->timestamp_anno())->**unparse()).mutable_data());
> >> -------
> >>
> >> Kind Regards,
> >> Sandeep,
> >> PhD Student,
> >> CTVR<http://ctvr.ie/>  - Trinity College Dublin
> >> ______________________________**_________________
> >> click mailing list
> >> click@amsterdam.lcs.mit.edu
> >>
> >>
https://amsterdam.lcs.mit.edu/**mailman/listinfo/click<https://amsterdam.lcs.
> >> mit.edu/mailman/listinfo/click>
> >>
> >>
> >

/*
Programmer: Roman Chertov
 * Copyright (c) 2011 The Aerospace Corporation

 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, subject to the conditions
 * listed in the Click LICENSE file. These conditions include: you must
 * preserve this copyright notice, and you cannot mention the copyright
 * holders in advertising related to the Software without their permission.
 * The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This
 * notice is a summary of the Click LICENSE file; the license in that file is
 * legally binding.
*/


#include <stdio.h>
#include <pcap.h>
#include <stdlib.h>
#include <netdb.h>
#include <netinet/ip.h>
#include <netinet/ip6.h>
#include <netinet/udp.h>
#include <arpa/inet.h>
#include <string.h>

#define IP6_DSCP_SHIFT 22

struct PData
{
    uint32_t  seq_num;
    uint32_t  data[4];
};

enum {DELAY, ARRIVAL, ARRIVAL_TIME, DEPARTURE, SHOW_LOSS, PCAP_TS};

void process(pcap_t *handle, int dscp_filter, int option, int loss_opt, int pcap_ts)
{
    pcap_pkthdr    header;      /* The header that pcap gives us */
    const u_char  *packet;           /* The actual packet */
    const iphdr   *ip_hdr;
    const ip6_hdr *ip6hdr;
    uint32_t       offset = 14;
    uint64_t       prev_ts = 0;
    int            dscp_val;
    uint64_t       count = 0;
    uint64_t       loss_count = 0;
    uint64_t       total_count = 0;

    while((packet = pcap_next(handle, &header)))
    {
        offset = 14;

        // see if we are dealing with an IPv4 of IPv6 packet
        if (header.caplen < offset + sizeof(uint32_t) * 2) // get the first two words of the IP header to see
        {                                                // what it is to determine how to proceed further
            printf("Captured data is too short\n");
            exit(1);
        }
        // here need to get to the right offset.  The IP header can be of variable length due to options
        // also, the header might be IPv4 of IPv6
        u_char version = packet[offset] >> 4;
        if (version == 0x04)
        {
            ip_hdr = reinterpret_cast<const iphdr *>(packet + offset);
            offset += ip_hdr->ihl << 2;
            dscp_val = ip_hdr->tos >> 2;
        }
        else if (version == 0x06)
        {
            // IPv6 header is
            ip6hdr = reinterpret_cast<const struct ip6_hdr *>(packet + offset);
            if (ip6hdr->ip6_nxt == 0x11) // UDP is the next header
                offset += sizeof(struct ip6_hdr);
            else // the next header is not UDP so stop now
            {
                printf("Next header is not UDP\n");
                exit(1);
            }
            dscp_val = (ntohl(ip6hdr->ip6_flow) >> IP6_DSCP_SHIFT) & 0x3F;
        }
        else
        {
            printf("Unknown IP version!");
            exit(1);
        }

        if (header.caplen < offset + sizeof(udphdr) + sizeof(PData))
        {
            printf("Packet is too short");
            exit(1);
        }

        offset += sizeof(struct udphdr);
        PData   *pdata = (struct PData*)(packet + offset);
        //uint32_t sec;
        //uint32_t nsec;
        uint64_t diff;
        uint64_t curr_ts;

        // check if we need to rely on the time stamp of the PCAP header
        if (!pcap_ts)
            curr_ts = (uint64_t)ntohl(pdata->data[0]) * 1000000000L +  (uint64_t)ntohl(pdata->data[1]);
        else
            curr_ts = (uint64_t)header.ts.tv_sec * 1000000000L + (uint64_t)header.ts.tv_usec * 1000;

        //printf("%lu %d,%d\n", curr_ts, ntohl(pdata->data[0]), ntohl(pdata->data[1]));
        pdata->seq_num = ntohl(pdata->seq_num);

        if (!count)
            count = pdata->seq_num;
        // the sequence number seen is larger than current + 1, meaning there is a whole.  This could
        // be due to re-ordering, but we will assume it is a loss event
        if (count + 1 < pdata->seq_num)
        {
            for(int i = pdata->seq_num - count - 1; i > 0; i--) // count the entire lost range
                loss_count++;
            //printf("Lost seq: %lu vs %u tstamp: %lu vs. %lu diff: %lu\n", count, pdata->seq_num, prev_ts, curr_ts, curr_ts - prev_ts);
            count = pdata->seq_num;
        }
        else if (count + 1 > pdata->seq_num) // This indicates a new flow started
            count = pdata->seq_num;
        else
            count++;
        pdata->data[2] = ntohl(pdata->data[2]);
        pdata->data[3] = ntohl(pdata->data[3]);
        if (!pcap_ts)
            diff = (uint64_t)pdata->data[2] * 1000000000L +  (uint64_t)pdata->data[3];
        else
            diff = 0;
        //nsec = ntohl(pdata->data[1]);
        //sec = ntohl(pdata->data[0]);

        // if we want to look at the arrival times, we need to add the delay to the departure time
        // to know the arrival time
        if (option == ARRIVAL || option == ARRIVAL_TIME)
            curr_ts += diff;

        if (dscp_filter == -1 || dscp_val == dscp_filter)
        {
            if (!prev_ts)
                prev_ts = curr_ts;
            else if (option == ARRIVAL || option == DEPARTURE)
                printf("%lu\n", curr_ts - prev_ts);
            prev_ts = curr_ts;

            if (option == DELAY)
            {
                //printf("%lu\n", 1);
                printf("%lu\n", diff);
            }
            else if (option == ARRIVAL_TIME)
                printf("%lu\n", curr_ts);
        }
        else if (dscp_filter != -1 && dscp_val != dscp_filter)
            printf("0\n");
        total_count++;
    }
    if (loss_opt == SHOW_LOSS)
        printf("Lost count: %lu Total Seen: %lu Estimated Total: %lu\n", loss_count, total_count, loss_count + total_count);
}

int main(int argc, char **argv)
{
    char    errbuf[PCAP_ERRBUF_SIZE];
    pcap_t *handle;
    int     dscp_filter = -1;
    int     option = DELAY;
    int     loss_opt = 0;
    int     pcap_ts = 0;
    int     i;

    if (argc < 2)
    {
        fprintf(stderr, "Usage: %s [-dscp value, -pcap_ts, -delay|-arrival|-arrival_time|-departure, -show_loss] file\n", argv[0]);
        exit(1);
    }
    for(i = 1; i < argc - 1; i++)
    {
        if (!strcmp("-dscp", argv[i]))
            dscp_filter = atoi(argv[++i]);
        else if (!strcmp("-delay", argv[i]))
            option = DELAY;
        else if (!strcmp("-arrival", argv[i]))
            option = ARRIVAL;
        else if (!strcmp("-arrival_time", argv[i]))
            option = ARRIVAL_TIME;
        else if (!strcmp("-departure", argv[i]))
            option = DEPARTURE;
        else if (!strcmp("-show_loss", argv[i]))
            loss_opt = SHOW_LOSS;
        else if (!strcmp("-pcap_ts", argv[i]))
            pcap_ts = 1;
        else
        {
            fprintf(stderr, "Unknown option %s!", argv[i]);
            exit(1);
        }
    }
    handle = pcap_open_offline(argv[argc - 1], errbuf);
    // no need to worry about filters here
    if (!handle)
    {
        fprintf(stderr, "Failed to open the dump file %s\n", argv[argc - 1]);
        exit(1);
    }
    fprintf(stderr, "Using dscp %d and option %d show_loss %d pcap_ts %d\n", dscp_filter, option, loss_opt == SHOW_LOSS, pcap_ts);
    process(handle, dscp_filter, option, loss_opt, pcap_ts);
    pcap_close(handle);
    return 0;
}
_______________________________________________
click mailing list
click@amsterdam.lcs.mit.edu
https://amsterdam.lcs.mit.edu/mailman/listinfo/click

Reply via email to