source: tools/tracetop/tracetop.cc @ a6da077

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

Add new tracetop utility

  • Property mode set to 100644
File size: 4.8 KB
Line 
1/* Show the top 'n' flows from a libtrace source
2 *
3 */
4#define __STDC_FORMAT_MACROS 1
5#include "libtrace.h"
6#include <stdio.h>
7#include <getopt.h>
8#include <stdlib.h>
9#include <map>
10#include <queue>
11#include <inttypes.h>
12#include <ncurses.h>
13
14struct flowkey_t {
15        uint32_t sip;
16        uint32_t dip;
17        uint16_t sport;
18        uint16_t dport;
19        uint8_t protocol;
20
21        bool operator <(const flowkey_t &b) const {
22                if (sip != b.sip) return sip < b.sip;
23                if (dip != b.dip) return dip < b.dip;
24                if (sport != b.sport) return sport < b.sport;
25                if (dport != b.dport) return dport < b.dport;
26                return protocol < b.protocol;
27        }
28};
29
30struct flowdata_t {
31        uint64_t packets;
32        uint64_t bytes;
33};
34
35typedef std::map<flowkey_t,flowdata_t> flows_t;
36
37flows_t flows;
38
39static void per_packet(libtrace_packet_t *packet)
40{
41        flowkey_t flowkey;
42        flows_t::iterator it;
43        libtrace_ip_t *ip = trace_get_ip(packet);
44        if (!ip) {
45                flowkey.sip = 0;
46                flowkey.dip = 0;
47                flowkey.sport = 0;
48                flowkey.dport = 0;
49                flowkey.protocol = 0;
50        }
51        else {
52                flowkey.sip = ntohs(ip->ip_src.s_addr);
53                flowkey.dip = ntohs(ip->ip_dst.s_addr);
54                flowkey.protocol = ip->ip_p;
55                flowkey.sport = trace_get_source_port(packet);
56                flowkey.dport = trace_get_destination_port(packet);
57        }
58        it = flows.find(flowkey);
59        if (it == flows.end()) {
60                flowdata_t flowdata = { 0, 0 };
61                flows_t::value_type insdata(flowkey,flowdata);
62                std::pair<flows_t::iterator,bool> ins= flows.insert(insdata);
63                it = ins.first;
64        }
65
66        ++it->second.packets;
67        it->second.bytes+=trace_get_capture_length(packet);
68}
69
70struct flow_data_t {
71        uint64_t bytes;
72        uint64_t packets;
73        uint32_t sip;
74        uint32_t dip;
75        uint16_t sport;
76        uint16_t dport;
77        uint8_t protocol;
78
79        bool operator< (const flow_data_t &b) const {
80                if (bytes != b.bytes) return bytes < b.bytes;
81                return packets < b.packets;
82        }
83};
84
85static void do_report()
86{
87        typedef  std::priority_queue<flow_data_t> pq_t;
88        int row,col;
89        pq_t pq;
90        for(flows_t::const_iterator it=flows.begin();it!=flows.end();++it) {
91                flow_data_t data;
92                data.bytes = it->second.bytes,
93                data.packets = it->second.packets,
94                data.sip = it->first.sip;
95                data.dip = it->first.dip;
96                data.sport = it->first.sport;
97                data.dport = it->first.dport;
98                data.protocol = it->first.protocol;
99                pq.push(data);
100        }
101        getmaxyx(stdscr,row,col);
102        attrset(A_REVERSE);
103        mvprintw(0,0,"%08s:%s\t%8s:%s\tproto\tbytes\tpackets\n",
104                "sip","sport",
105                "dip","dport"
106                );
107        attrset(A_NORMAL);
108        for(int i=0; i<row-2 && !pq.empty(); ++i) {
109                mvprintw(i+1,0,"%08x:%d\t%08x:%d\t%d\t%"PRIu64"\t%"PRIu64"\n",
110                                pq.top().sip, pq.top().sport,
111                                pq.top().dip, pq.top().dport,
112                                pq.top().protocol,
113                                pq.top().bytes,
114                                pq.top().packets);
115                pq.pop();
116        }
117        flows.clear();
118
119        refresh();
120}
121
122static void usage(char *argv0)
123{
124        fprintf(stderr,"usage: %s [ --filter | -f bpfexp ]  [ --snaplen | -s snap ]\n\t\t[ --promisc | -p flag] [ --help | -h ] [ --libtrace-help | -H ] libtraceuri...\n",argv0);
125}
126
127int main(int argc, char *argv[])
128{
129        libtrace_t *trace;
130        libtrace_packet_t *packet;
131        libtrace_filter_t *filter=NULL;
132        int snaplen=-1;
133        int promisc=-1;
134        double last_report=0;
135
136        while(1) {
137                int option_index;
138                struct option long_options[] = {
139                        { "filter",             1, 0, 'f' },
140                        { "snaplen",            1, 0, 's' },
141                        { "promisc",            1, 0, 'p' },
142                        { "help",               0, 0, 'h' },
143                        { "libtrace-help",      0, 0, 'H' },
144                        { NULL,                 0, 0, 0 }
145                };
146
147                int c= getopt_long(argc, argv, "f:s:p:hH",
148                                long_options, &option_index);
149
150                if (c==-1)
151                        break;
152
153                switch (c) {
154                        case 'f':
155                                filter=trace_create_filter(optarg);
156                                break;
157                        case 's':
158                                snaplen=atoi(optarg);
159                                break;
160                        case 'p':
161                                promisc=atoi(optarg);
162                                break;
163                        case 'H':
164                                trace_help();
165                                return 1;
166                        default:
167                                fprintf(stderr,"Unknown option: %c\n",c);
168                                /* FALL THRU */
169                        case 'h':
170                                usage(argv[0]);
171                                return 1;
172                }
173        }
174
175        if (optind>=argc) {
176                fprintf(stderr,"Missing input uri\n");
177                usage(argv[0]);
178                return 1;
179        }
180
181        initscr(); cbreak(); noecho();
182
183        while (optind<argc) {
184                trace = trace_create(argv[optind]);
185                ++optind;
186
187                if (trace_is_err(trace)) {
188                        endwin();
189                        trace_perror(trace,"Opening trace file");
190                        return 1;
191                }
192
193                if (snaplen>0)
194                        if (trace_config(trace,TRACE_OPTION_SNAPLEN,&snaplen)) {
195                                trace_perror(trace,"ignoring: ");
196                        }
197                if (filter)
198                        if (trace_config(trace,TRACE_OPTION_FILTER,filter)) {
199                                trace_perror(trace,"ignoring: ");
200                        }
201                if (promisc!=-1) {
202                        if (trace_config(trace,TRACE_OPTION_PROMISC,&promisc)) {
203                                trace_perror(trace,"ignoring: ");
204                        }
205                }
206
207                if (trace_start(trace)) {
208                        endwin();
209                        trace_perror(trace,"Starting trace");
210                        trace_destroy(trace);
211                        return 1;
212                }
213
214                packet = trace_create_packet();
215
216                while (trace_read_packet(trace,packet)>0) {
217                        if (trace_get_seconds(packet) - last_report > 1) {
218                                do_report();
219                                       
220                                last_report=trace_get_seconds(packet);
221                        }
222                        per_packet(packet);
223                }
224
225                trace_destroy_packet(packet);
226
227                if (trace_is_err(trace)) {
228                        trace_perror(trace,"Reading packets");
229                }
230
231                trace_destroy(trace);
232        }
233
234        endwin();
235
236        return 0;
237}
Note: See TracBrowser for help on using the repository browser.