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