1 /* For terms of usage/redistribution/modification see the LICENSE file */
2 /* For authors and contributors see the AUTHORS file */
6 pktsize.c - the packet size breakdown facility
10 #include "iptraf-ng-compat.h"
12 #include "tui/winops.h"
37 unsigned long size_in
[SIZES
+ 1]; /* +1 for oversized count */
38 unsigned long size_out
[SIZES
+ 1];
40 unsigned int interval
;
41 unsigned int maxsize_in
;
42 unsigned int maxsize_out
;
46 static void rotate_size_log(int s __unused
)
49 strcpy(target_logname
, current_logfile
);
50 signal(SIGUSR1
, rotate_size_log
);
53 static void write_size_log(struct psizetab
*table
, unsigned long nsecs
,
54 char *ifname
, FILE *logfile
)
56 char atime
[TIME_TARGET_MAX
];
59 genatime(time(NULL
), atime
);
60 fprintf(logfile
, "*** Packet Size Distribution, generated %s\n\n",
62 fprintf(logfile
, "Interface: %s MTU: %u\n\n", ifname
, table
->mtu
);
63 fprintf(logfile
, "Packet Size (bytes)\tIn\t\tOut\n");
65 for (i
= 0; i
< SIZES
; i
++) {
66 fprintf(logfile
, "%u to %u:\t\t%8lu\t%8lu\n",
67 table
->interval
* i
+ 1,
68 table
->interval
* (i
+ 1),
72 fprintf(logfile
, "\nRunning time: %lu seconds\n", nsecs
);
76 static void psizetab_init(struct psizetab
*table
, char *ifname
)
78 table
->borderwin
= newwin(LINES
- 2, COLS
, 1, 0);
79 table
->borderpanel
= new_panel(table
->borderwin
);
81 wattrset(table
->borderwin
, BOXATTR
);
82 tx_box(table
->borderwin
, ACS_VLINE
, ACS_HLINE
);
83 mvwprintw(table
->borderwin
, 0, 1, " Packet Distribution by Size for interface %s ", ifname
);
85 table
->win
= newwin(LINES
- 4, COLS
- 2, 2, 1);
86 table
->panel
= new_panel(table
->win
);
88 tx_stdwinset(table
->win
);
89 wtimeout(table
->win
, -1);
90 wattrset(table
->win
, STDATTR
);
91 tx_colorwin(table
->win
);
93 wattrset(table
->win
, BOXATTR
);
94 mvwprintw(table
->win
, 1, 1, "Packet Size (bytes)");
95 mvwprintw(table
->win
, 1, 23, "In Out");
96 mvwprintw(table
->win
, 1, 42, "Packet Size (bytes)");
97 mvwprintw(table
->win
, 1, 64, "In Out");
98 wattrset(table
->win
, HIGHATTR
);
107 static void psizetab_destroy(struct psizetab
*table
)
109 del_panel(table
->panel
);
112 del_panel(table
->borderpanel
);
113 delwin(table
->borderwin
);
119 static void sizes_init(struct psizetab
*table
, unsigned int mtu
)
123 unsigned int interval
= mtu
/ SIZES
;
125 table
->interval
= interval
;
127 wattrset(table
->win
, STDATTR
);
128 for(unsigned int i
= 0; i
< SIZES
; i
++) {
131 table
->size_in
[i
] = 0UL; /* initialize counters */
132 table
->size_out
[i
] = 0UL;
141 mvwprintw(table
->win
, row
, column
, "%5u to %5u:",
142 interval
* i
+ 1, interval
* (i
+ 1));
145 table
->size_in
[SIZES
] = 0UL; /* initialize oversized counters */
146 table
->size_out
[SIZES
] = 0UL;
147 table
->maxsize_in
= 0UL; /* initialize maxsize counters */
148 table
->maxsize_out
= 0UL;
150 mvwprintw(table
->win
, 12, 47, "oversized:");
151 mvwprintw(table
->win
, 14, 1, "max packet size in (bytes):");
152 mvwprintw(table
->win
, 15, 1, "max packet size out (bytes):");
154 mvwprintw(table
->win
, 17, 1,
155 "Interface MTU is %u bytes, not counting the data-link header.",
157 mvwprintw(table
->win
, 18, 1,
158 "Maximum packet size is the MTU plus the data-link header length, but can be");
159 mvwprintw(table
->win
, 19, 1,
160 " bigger due to various offloading techniques of the interface.");
161 mvwprintw(table
->win
, 20, 1,
162 "Packet size computations include data-link headers, if any.");
165 static void update_size_distrib(struct psizetab
*table
, struct pkt_hdr
*pkt
)
167 /* -1 is to keep interval boundary lengths within the proper brackets */
168 unsigned int i
= (pkt
->pkt_len
- 1) / table
->interval
;
171 i
= SIZES
; /* last entry is for lengths > MTU */
173 if (pkt
->from
->sll_pkttype
== PACKET_OUTGOING
) {
174 table
->size_out
[i
]++;
175 if (table
->maxsize_out
< pkt
->pkt_len
)
176 table
->maxsize_out
= pkt
->pkt_len
;
179 if (table
->maxsize_in
< pkt
->pkt_len
)
180 table
->maxsize_in
= pkt
->pkt_len
;
184 static void print_size_distrib(struct psizetab
*table
)
186 wattrset(table
->win
, HIGHATTR
);
187 for (unsigned int i
= 0; i
< SIZES
+ 1; i
++) { /* include oversized */
189 wmove(table
->win
, i
+ 2, 17);
191 wmove(table
->win
, (i
- 10) + 2, 58);
193 wprintw(table
->win
, "%8lu %8lu",
194 table
->size_in
[i
], table
->size_out
[i
]);
196 mvwprintw(table
->win
, 14, 33, "%5u", table
->maxsize_in
);
197 mvwprintw(table
->win
, 15, 33, "%5u", table
->maxsize_out
);
200 static void psize_process_key(int ch
)
218 static void psize_process_packet(struct psizetab
*table
, struct pkt_hdr
*pkt
)
220 int pkt_result
= packet_process(pkt
, NULL
, NULL
, NULL
,
221 MATCH_OPPOSITE_USECONFIG
, 0);
223 if (pkt_result
== PACKET_OK
)
224 update_size_distrib(table
, pkt
);
227 void packet_size_breakdown(char *ifname
, time_t facilitytime
)
231 int logging
= options
.logging
;
232 FILE *logfile
= NULL
;
234 struct psizetab table
;
240 if (!dev_up(ifname
)) {
245 psizetab_init(&table
, ifname
);
248 if (options
.promisc
) {
249 promisc_init(&promisc
, ifname
);
250 promisc_set_list(&promisc
);
253 if (capt_init(&capt
, ifname
) == -1) {
254 write_error("Unable to initialize packet capture interface");
258 int mtu
= dev_get_mtu(ifname
);
260 write_error("Unable to obtain interface MTU");
264 sizes_init(&table
, mtu
);
266 print_size_distrib(&table
);
271 if (strcmp(current_logfile
, "") == 0) {
272 snprintf(current_logfile
, 80, "%s-%s.log", PKTSIZELOG
,
276 input_logfile(current_logfile
, &logging
);
281 opentlog(&logfile
, current_logfile
);
287 signal(SIGUSR1
, rotate_size_log
);
290 writelog(logging
, logfile
,
291 "******** Packet size distribution facility started ********");
299 gettimeofday(&now
, NULL
);
300 struct timeval last_time
= now
;
301 struct timeval last_update
= now
;
303 time_t starttime
= now
.tv_sec
;
304 time_t endtime
= INT_MAX
;
305 if (facilitytime
!= 0)
306 endtime
= now
.tv_sec
+ facilitytime
* 60;
308 time_t log_next
= INT_MAX
;
310 log_next
= now
.tv_sec
+ options
.logspan
;
313 gettimeofday(&now
, NULL
);
315 if (now
.tv_sec
> last_time
.tv_sec
) {
316 printelapsedtime(now
.tv_sec
- starttime
, 1, table
.borderwin
);
318 print_packet_drops(capt_get_dropped(&capt
), table
.borderwin
, 49);
320 if (logging
&& (now
.tv_sec
> log_next
)) {
321 check_rotate_flag(&logfile
);
322 write_size_log(&table
, now
.tv_sec
- starttime
,
324 log_next
= now
.tv_sec
+ options
.logspan
;
327 if (now
.tv_sec
> endtime
)
333 if (screen_update_needed(&now
, &last_update
)) {
334 print_size_distrib(&table
);
342 if (capt_get_packet(&capt
, &pkt
, &ch
, table
.win
) == -1) {
343 write_error("Packet receive failed");
349 psize_process_key(ch
);
351 if (pkt
.pkt_len
> 0) {
352 psize_process_packet(&table
, &pkt
);
353 capt_put_packet(&capt
, &pkt
);
357 packet_destroy(&pkt
);
360 signal(SIGUSR1
, SIG_DFL
);
361 write_size_log(&table
, time(NULL
) - starttime
, ifname
, logfile
);
362 writelog(logging
, logfile
,
363 "******** Packet size distribution facility stopped ********");
366 strcpy(current_logfile
, "");
371 if (options
.promisc
) {
372 promisc_restore_list(&promisc
);
373 promisc_destroy(&promisc
);
376 psizetab_destroy(&table
);