source: examples/rtt/rtt.cc @ aca3ff4

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivegetfragoffhelplibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since aca3ff4 was 79ffccd, checked in by Perry Lorier <perry@…>, 16 years ago

Add the RTT estimator

  • Property mode set to 100644
File size: 5.5 KB
Line 
1#include <stdio.h>
2#include "libtrace.h"
3#include <map>
4
5struct flow_id_t {
6        uint32_t ip_a;
7        uint32_t ip_b;
8        uint16_t port_a;
9        uint16_t port_b;
10
11        flow_id_t(void) : 
12                ip_a(0), ip_b(0), 
13                port_a(0), port_b(0) 
14                {};
15};
16
17int cmp(const flow_id_t &a, const flow_id_t &b) {
18        if (a.ip_a < b.ip_a)    return -1;
19        if (a.ip_a > b.ip_a)    return 1;
20
21        if (a.ip_b < b.ip_b)    return -1;
22        if (a.ip_b > b.ip_b)    return 1;
23
24        if (a.port_a < b.port_a) return -1;
25        if (a.port_a > b.port_a) return 1;
26
27        if (a.port_b < b.port_b) return -1;
28        if (a.port_b > b.port_b) return 1;
29
30        return 0;
31}
32
33bool operator <(const flow_id_t &a, const flow_id_t &b) 
34{ 
35        return cmp(a,b)<0; 
36}
37
38typedef uint32_t cookie_t;
39typedef double ts_t;
40
41typedef std::map<cookie_t,ts_t> cookie_jar_t;
42
43typedef std::map<flow_id_t, cookie_jar_t > state_info_t;
44
45state_info_t state_info;
46
47struct libtrace_packet_t packet;
48
49/** parse an option
50 * @param ptr   the pointer to the current option
51 * @param plen  the length of the remaining buffer
52 * @param type  the type of the option
53 * @param optlen the length of the option
54 * @param data  the data of the option
55 *
56 * @returns bool true if there is another option (and the fields are filled in)
57 */
58int get_next_option(unsigned char **ptr,int *len,
59                        unsigned char *type,
60                        unsigned char *optlen,
61                        unsigned char **data)
62{
63        if (*len<=0)
64                return 0;
65        *type=**ptr;
66        switch(*type) {
67                case 0: /* End of options */
68                        return 0;
69                case 1: /* Pad */
70                        (*ptr)++;
71                        (*len)--;
72                        return 1;
73                default:
74                        *optlen = *(*ptr+1);
75                        if (*optlen<2)
76                                return 0; // I have no idea wtf is going on
77                                          // with these packets
78                        (*len)-=*optlen;
79                        (*data)=(*ptr+2);
80                        (*ptr)+=*optlen;
81                        if (*len<0)
82                                return 0;
83                        return 1;
84        }
85        assert(0);
86}
87
88void expire(double now)
89{
90        state_info_t::iterator flow_i = state_info.begin();
91
92        for(; flow_i != state_info.end(); ++flow_i) {
93            cookie_jar_t &cookie_jar = flow_i->second;
94            cookie_jar_t::iterator cookie_i = cookie_jar.begin();
95            for(; cookie_i != cookie_jar.end();) {
96                if(now - cookie_i->second > 180) {
97                    cookie_jar_t::iterator j = cookie_i;
98                    ++j;
99                    cookie_jar.erase(cookie_i);
100                    cookie_i = j;
101                } else {
102                    ++cookie_i;
103                }
104            }
105        }
106}
107
108void dump_db(void)
109{
110        fflush(stderr); fflush(stdout);
111        for (state_info_t::const_iterator flow_i = state_info.begin();
112                        flow_i!=state_info.end();
113                        flow_i++) {
114                fprintf(stderr,"%08x:%i -> %08x:%i\n",
115                        flow_i->first.ip_a,
116                        flow_i->first.port_a,
117                        flow_i->first.ip_b,
118                        flow_i->first.port_b);
119                for(cookie_jar_t::const_iterator cookie_i=flow_i->second.begin();
120                                cookie_i!=flow_i->second.end();
121                                cookie_i++) {
122                        fprintf(stderr," %u -> %f\n",cookie_i->first,
123                                                cookie_i->second);
124                }
125        }
126        fprintf(stderr,"\n");
127        fflush(stderr); fflush(stdout);
128}
129
130int main(int argc, char *argv[])
131{
132        struct libtrace_t *trace;
133        double last = 0;
134        struct flow_id_t a,b;
135        a.ip_a = 0x7f000001;
136        a.ip_b = 0x0ac0ffee;
137        a.port_a = 80;
138        a.port_b = 1024;
139        b.ip_a = 0x0ac0ffee;
140        b.ip_b = 0x7f000001;
141        b.port_a = 1024;
142        b.port_b = 80;
143
144        printf("%i %u %u\n",cmp(a,b),a.ip_a,b.ip_a);
145
146        assert(cmp(a,b)==1);
147
148        trace = trace_create(argv[1]);
149
150        for (;;) {
151                struct libtrace_tcp *tcpptr;
152                struct libtrace_ip *ipptr;
153                int psize;
154
155                if ((psize = trace_read_packet(trace, &packet)) <= 0) {
156                        break;
157                }
158
159                ipptr = trace_get_ip(&packet);
160                if (!ipptr)
161                        continue;
162
163                if (ipptr->ip_p!=6)
164                        continue;
165
166                tcpptr = trace_get_tcp(&packet);
167
168                if (!tcpptr)
169                        continue;
170
171                struct flow_id_t fwd; 
172                struct flow_id_t rev;
173                fwd.ip_a = ipptr->ip_src.s_addr;
174                fwd.ip_b = ipptr->ip_dst.s_addr;
175                fwd.port_a = tcpptr->source;
176                fwd.port_b = tcpptr->dest;
177
178                rev.ip_b = ipptr->ip_src.s_addr;
179                rev.ip_a = ipptr->ip_dst.s_addr;
180                rev.port_b = tcpptr->source;
181                rev.port_a = tcpptr->dest;
182
183                double now = trace_get_seconds(&packet);
184
185                /* search for the timestamp option */   
186                unsigned char *pkt = (unsigned char *)tcpptr + sizeof(*tcpptr);
187                //int plen = (packet.size-(pkt-(unsigned char*)packet.buffer)) <? (tcpptr->doff*4-sizeof *tcpptr);
188                int plen = (tcpptr->doff*4-sizeof *tcpptr);
189                unsigned char type = 0;
190                unsigned char optlen = 0;
191                unsigned char *data = 0;
192
193                while (get_next_option(&pkt,&plen,&type,&optlen,&data)) {
194                        // ignore non timestamp options
195                        if (type!=8) {
196                                continue;
197                        }
198                        uint32_t *ts=(uint32_t *)&data[0];
199                        uint32_t *tsecho=(uint32_t*)&data[4];
200
201
202                        state_info_t::iterator si = state_info.find(rev);
203                        if(si != state_info.end()) {
204
205                            cookie_jar_t &cookie_jar = si->second;
206                            cookie_jar_t::iterator ci = cookie_jar.find(*tsecho);
207                            if(ci != cookie_jar.end()) {
208                                printf("%f %.12f\n",
209                                        now,
210                                        now-ci->second);
211                                cookie_jar.erase(ci);
212                            }
213
214                            assert(state_info.find(rev)!=state_info.end());
215                        }
216
217                        if (*ts) {
218                                state_info_t::iterator si = state_info.find(fwd);
219
220
221                                if (si==state_info.end()) {
222                                        si = state_info.insert(
223                                         std::pair< flow_id_t, cookie_jar_t>(
224                                                fwd, cookie_jar_t())).first;
225                                        assert(state_info.find(fwd)!=state_info.end());
226                                }
227                                assert(state_info.find(fwd)!=state_info.end());
228                                cookie_jar_t &cookie_jar = si->second;
229                                cookie_jar[*ts]=now;
230                                assert(state_info.find(fwd)!=state_info.end());
231                        }
232                }
233
234                if (now-last>60) {
235
236                        last=now;
237
238                        expire(now);
239
240                }
241
242        }
243
244        return 0;
245}
Note: See TracBrowser for help on using the repository browser.