1 /*
2  * Copyright (c) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
3  *               2002, 2003, 2004
4  *	Ohio University.
5  *
6  * ---
7  *
8  * Starting with the release of tcptrace version 6 in 2001, tcptrace
9  * is licensed under the GNU General Public License (GPL).  We believe
10  * that, among the available licenses, the GPL will do the best job of
11  * allowing tcptrace to continue to be a valuable, freely-available
12  * and well-maintained tool for the networking community.
13  *
14  * Previous versions of tcptrace were released under a license that
15  * was much less restrictive with respect to how tcptrace could be
16  * used in commercial products.  Because of this, I am willing to
17  * consider alternate license arrangements as allowed in Section 10 of
18  * the GNU GPL.  Before I would consider licensing tcptrace under an
19  * alternate agreement with a particular individual or company,
20  * however, I would have to be convinced that such an alternative
21  * would be to the greater benefit of the networking community.
22  *
23  * ---
24  *
25  * This file is part of Tcptrace.
26  *
27  * Tcptrace was originally written and continues to be maintained by
28  * Shawn Ostermann with the help of a group of devoted students and
29  * users (see the file 'THANKS').  The work on tcptrace has been made
30  * possible over the years through the generous support of NASA GRC,
31  * the National Science Foundation, and Sun Microsystems.
32  *
33  * Tcptrace is free software; you can redistribute it and/or modify it
34  * under the terms of the GNU General Public License as published by
35  * the Free Software Foundation; either version 2 of the License, or
36  * (at your option) any later version.
37  *
38  * Tcptrace is distributed in the hope that it will be useful, but
39  * WITHOUT ANY WARRANTY; without even the implied warranty of
40  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
41  * General Public License for more details.
42  *
43  * You should have received a copy of the GNU General Public License
44  * along with Tcptrace (in the file 'COPYING'); if not, write to the
45  * Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
46  * MA 02111-1307 USA
47  *
48  * Author:	Shawn Ostermann
49  * 		School of Electrical Engineering and Computer Science
50  * 		Ohio University
51  * 		Athens, OH
52  *		ostermann@cs.ohiou.edu
53  *		http://www.tcptrace.org/
54  */
55 #include "tcptrace.h"
56 static char const GCC_UNUSED copyright[] =
57     "@(#)Copyright (c) 2004 -- Ohio University.\n";
58 static char const GCC_UNUSED rcsid[] =
59     "@(#)$Header$";
60 
61 
62 #include "gcache.h"
63 
64 
65 /* local routines */
66 static double Average(double, int);
67 static double Stdev(double, double, int);
68 static void StatLineP(char *, char *, char *, void *, void *);
69 static void StatLineI_L(char *, char *, u_long, u_long);
70 #ifdef HAVE_LONG_LONG
71 static void StatLineI_LL(char *, char *, u_llong, u_llong);
72 static void StatLineFieldL(char *, char *, char *, u_llong, int);
73 #endif  /* HAVE_LONG_LONG */
74 static void StatLineF(char *, char *, char *, double, double);
75 static void StatLineField(char *, char *, char *, u_long, int);
76 static void StatLineFieldF(char *, char *, char *, double, int);
77 static void StatLineOne(char *, char *, char *);
78 static char *FormatBrief(tcp_pair *ptp);
79 static char *UDPFormatBrief(udp_pair *pup);
80 
81 /* locally global variables*/
82 static u_int sv_print_count    = 0;
83 static u_int sv_expected_count = 0;
84 
85 /* global variables */
86 char *sp;  /* Separator used for long output with <SP>-separated-values */
87 
88 /* to support some of the counters being long long on some platforms, use this */
89 /* macro... */
90 #ifdef HAVE_LONG_LONG
91 #define StatLineI(label,units,ul1,ul2)  \
92 (sizeof((ul1)) == SIZEOF_UNSIGNED_LONG_LONG_INT)?\
93   StatLineI_LL((label),(units),(ul1),(ul2)):\
94   StatLineI_L ((label),(units),(ul1),(ul2))
95 #else /* HAVE_LONG_LONG */
96 #define StatLineI StatLineI_L
97 #endif /* HAVE_LONG_LONG */
98 
99 u_int
SynCount(tcp_pair * ptp)100 SynCount(
101     tcp_pair *ptp)
102 {
103     tcb *pab = &ptp->a2b;
104     tcb *pba = &ptp->b2a;
105 
106     return(((pab->syn_count >= 1)?1:0) +
107 	   ((pba->syn_count >= 1)?1:0));
108 }
109 
110 
111 
112 u_int
FinCount(tcp_pair * ptp)113 FinCount(
114     tcp_pair *ptp)
115 {
116     tcb *pab = &ptp->a2b;
117     tcb *pba = &ptp->b2a;
118 
119     return(((pab->fin_count >= 1)?1:0) +
120 	   ((pba->fin_count >= 1)?1:0));
121 }
122 
123 
124 
125 int
ConnComplete(tcp_pair * ptp)126 ConnComplete(
127     tcp_pair *ptp)
128 {
129     return(SynCount(ptp) >= 2 && FinCount(ptp) >= 2);
130 }
131 
132 
133 int
ConnReset(tcp_pair * ptp)134 ConnReset(
135     tcp_pair *ptp)
136 {
137     return(ptp->a2b.reset_count + ptp->b2a.reset_count != 0);
138 }
139 
140 
141 
142 static double
Average(double sum,int count)143 Average(
144     double sum,
145     int count)
146 {
147     return((double) sum / ((double)count+.0001));
148 }
149 
150 
151 
152 static double
Stdev(double sum,double sum2,int n)153 Stdev(
154     double sum,
155     double sum2,
156     int n)
157 {
158     double term;
159     double term1;
160     double term2;
161     double retval;
162 
163     if (n<=2)
164 	return(0.0);
165 
166     term1 = sum2;
167     term2 = (sum * sum) / (double)n;
168     term = term1-term2;
169     term /= (double)(n-1);
170     retval = sqrt(term);
171 
172 /*     printf("Stdev(%f,%f,%d) is %f\n", sum,sum2,n,retval); */
173 
174     return(retval);
175 }
176 
177 
178 
179 
180 
181 static char *
FormatBrief(tcp_pair * ptp)182 FormatBrief(
183     tcp_pair *ptp)
184 {
185     tcb *pab = &ptp->a2b;
186     tcb *pba = &ptp->b2a;
187     static char infobuf[100];
188 
189     snprintf(infobuf,sizeof(infobuf),"%s - %s (%s2%s)",
190 	    ptp->a_endpoint, ptp->b_endpoint,
191 	    pab->host_letter, pba->host_letter);
192     return(infobuf);
193 }
194 
195 
196 
197 
198 
199 void
PrintTrace(tcp_pair * ptp)200 PrintTrace(
201     tcp_pair *ptp)
202 {
203     double etime;
204     u_long etime_secs;
205     u_long etime_usecs;
206     double etime_data1;
207     double etime_data2;
208     tcb *pab = &ptp->a2b;
209     tcb *pba = &ptp->b2a;
210     char *host1 = pab->host_letter;
211     char *host2 = pba->host_letter;
212     char bufl[40],bufr[40];
213 
214     /* counters to use for seq. space wrap around calculations
215      */
216     u_llong stream_length_pab=0, stream_length_pba=0;
217     u_long pab_last, pba_last;
218 
219    /* Reset the counter for each connection */
220    sv_print_count = 1; /* The first field (conn_#) gets printed in trace.c */
221 
222 
223     /* calculate elapsed time */
224     etime = elapsed(ptp->first_time,ptp->last_time);
225     etime_secs = etime / 1000000.0;
226     etime_usecs = 1000000 * (etime/1000000.0 - (double)etime_secs);
227 
228     /* Check if comma-separated-values or tab-separated-values
229      * has been requested.
230      */
231    if(csv || tsv || (sv != NULL)) {
232        fprintf(stdout,"%s%s%s%s%s%s%s%s",
233 	       ptp->a_hostname, sp, ptp->b_hostname, sp,
234 	       ptp->a_portname, sp, ptp->b_portname, sp);
235        sv_print_count += 4;
236        /* Print the start and end times. In other words,
237 	* print the time of the first and the last packet
238 	*/
239        fprintf(stdout,"%ld.%ld %s %ld.%ld %s",
240 	       (long)ptp->first_time.tv_sec, (long)ptp->first_time.tv_usec, sp,
241 	       (long)ptp->last_time.tv_sec, (long)ptp->last_time.tv_usec, sp);
242        sv_print_count += 2;
243     }
244     else {
245        fprintf(stdout,"\thost %-4s      %s\n",
246 	       (snprintf(bufl,sizeof(bufl),"%s:", host1),bufl), ptp->a_endpoint);
247        fprintf(stdout,"\thost %-4s      %s\n",
248 	       (snprintf(bufl,sizeof(bufl),"%s:", host2),bufl), ptp->b_endpoint);
249        fprintf(stdout,"\tcomplete conn: %s",
250 	       ConnReset(ptp)?"RESET":(
251 				       ConnComplete(ptp)?"yes":"no"));
252        if (ConnComplete(ptp))
253 	 fprintf(stdout,"\n");
254        else
255 	 fprintf(stdout,"\t(SYNs: %u)  (FINs: %u)\n",
256 		 SynCount(ptp), FinCount(ptp));
257 
258        fprintf(stdout,"\tfirst packet:  %s\n", ts2ascii(&ptp->first_time));
259        fprintf(stdout,"\tlast packet:   %s\n", ts2ascii(&ptp->last_time));
260 
261        fprintf(stdout,"\telapsed time:  %s\n", elapsed2str(etime));
262 
263        fprintf(stdout,"\ttotal packets: %" FS_ULL "\n", ptp->packets);
264 
265        fprintf(stdout,"\tfilename:      %s\n", ptp->filename);
266 
267        fprintf(stdout,"   %s->%s:			      %s->%s:\n",
268 	       host1,host2,host2,host1);
269     }
270 
271     StatLineI("total packets","", pab->packets, pba->packets);
272     if (pab->reset_count || pba->reset_count || csv || tsv || (sv != NULL))
273 	StatLineI("resets sent","", pab->reset_count, pba->reset_count);
274     StatLineI("ack pkts sent","", pab->ack_pkts, pba->ack_pkts);
275     StatLineI("pure acks sent","", pab->pureack_pkts, pba->pureack_pkts);
276     StatLineI("sack pkts sent","", pab->num_sacks, pba->num_sacks);
277     StatLineI("dsack pkts sent","", pab->num_dsacks, pba->num_dsacks);
278     StatLineI("max sack blks/ack","", pab->max_sack_blocks, pba->max_sack_blocks);
279     StatLineI("unique bytes sent","",
280 	      pab->unique_bytes, pba->unique_bytes);
281     StatLineI("actual data pkts","", pab->data_pkts, pba->data_pkts);
282     StatLineI("actual data bytes","", pab->data_bytes, pba->data_bytes);
283     StatLineI("rexmt data pkts","", pab->rexmit_pkts, pba->rexmit_pkts);
284     StatLineI("rexmt data bytes","",
285 	      pab->rexmit_bytes, pba->rexmit_bytes);
286     StatLineI("zwnd probe pkts","",
287 		  pab->num_zwnd_probes, pba->num_zwnd_probes);
288     StatLineI("zwnd probe bytes","",
289 	      pab->zwnd_probe_bytes, pba->zwnd_probe_bytes);
290     StatLineI("outoforder pkts","",
291 	      pab->out_order_pkts, pba->out_order_pkts);
292     StatLineI("pushed data pkts","", pab->data_pkts_push, pba->data_pkts_push);
293     StatLineP("SYN/FIN pkts sent","","%s",
294 	      (snprintf(bufl,sizeof(bufl),"%d/%d",
295 		       pab->syn_count, pab->fin_count),bufl),
296 	      (snprintf(bufr,sizeof(bufr),"%d/%d",
297 		       pba->syn_count, pba->fin_count),bufr));
298     if (pab->f1323_ws || pba->f1323_ws || pab->f1323_ts || pba->f1323_ts || csv || tsv || (sv != NULL)) {
299 	StatLineP("req 1323 ws/ts","","%s",
300 		  (snprintf(bufl,sizeof(bufl),"%c/%c",
301 		      pab->f1323_ws?'Y':'N',pab->f1323_ts?'Y':'N'),bufl),
302 		  (snprintf(bufr,sizeof(bufr),"%c/%c",
303 		      pba->f1323_ws?'Y':'N',pba->f1323_ts?'Y':'N'),bufr));
304     }
305     if (pab->f1323_ws || pba->f1323_ws || csv || tsv || (sv != NULL)) {
306 	StatLineI("adv wind scale","",
307 		  (u_long)pab->window_scale, (u_long)pba->window_scale);
308     }
309     if (pab->fsack_req || pba->fsack_req || csv || tsv || (sv != NULL)) {
310 	StatLineP("req sack","","%s",
311 		  pab->fsack_req?"Y":"N",
312 		  pba->fsack_req?"Y":"N");
313 	StatLineI("sacks sent","",
314 		  pab->sacks_sent,
315 		  pba->sacks_sent);
316     }
317     StatLineI("urgent data pkts", "pkts",
318 	      pab->urg_data_pkts,
319 	      pba->urg_data_pkts);
320     StatLineI("urgent data bytes", "bytes",
321 	      pab->urg_data_bytes,
322 	      pba->urg_data_bytes);
323     StatLineI("mss requested","bytes", pab->mss, pba->mss);
324     StatLineI("max segm size","bytes",
325 	      pab->max_seg_size,
326 	      pba->max_seg_size);
327     StatLineI("min segm size","bytes",
328 	      pab->min_seg_size,
329 	      pba->min_seg_size);
330     StatLineI("avg segm size","bytes",
331 	      (int)((double)pab->data_bytes / ((double)pab->data_pkts+.001)),
332 	      (int)((double)pba->data_bytes / ((double)pba->data_pkts+.001)));
333     StatLineI("max win adv","bytes", pab->win_max, pba->win_max);
334     StatLineI("min win adv","bytes", pab->win_min, pba->win_min);
335     StatLineI("zero win adv","times",
336 	      pab->win_zero_ct, pba->win_zero_ct);
337     // Average window advertisement is calculated only for window scaled pkts
338     // if we have seen this connection using window scaling.
339     // Otherwise, it is just the regular way of dividing the sum of
340     // all window advertisements by the total number of packets.
341 
342     if (pab->window_stats_updated_for_scaling &&
343 	pba->window_stats_updated_for_scaling)
344 	  StatLineI("avg win adv","bytes",
345 		    pab->win_scaled_pkts==0?0:
346 		    (pab->win_tot/pab->win_scaled_pkts),
347 		    pba->win_scaled_pkts==0?0:
348 		    (pba->win_tot/pba->win_scaled_pkts));
349     else
350 	  StatLineI("avg win adv","bytes",
351 		    pab->packets==0?0:pab->win_tot/pab->packets,
352 		    pba->packets==0?0:pba->win_tot/pba->packets);
353     if (print_owin) {
354 	StatLineI("max owin","bytes", pab->owin_max, pba->owin_max);
355 	StatLineI("min non-zero owin","bytes", pab->owin_min, pba->owin_min);
356 	StatLineI("avg owin","bytes",
357 		  pab->owin_count==0?0:pab->owin_tot/pab->owin_count,
358 		  pba->owin_count==0?0:pba->owin_tot/pba->owin_count);
359 	if (etime == 0.0) {
360 		StatLineP("wavg owin", "", "%s", "NA", "NA");
361 	}
362 	else {
363 		StatLineI("wavg owin","bytes",
364 			  (u_llong)(pab->owin_wavg/((double)etime/1000000)),
365 		  	  (u_llong)(pba->owin_wavg/((double)etime/1000000)));
366    	}
367     }
368     StatLineI("initial window","bytes",
369 	      pab->initialwin_bytes, pba->initialwin_bytes);
370     StatLineI("initial window","pkts",
371 	      pab->initialwin_segs, pba->initialwin_segs);
372 
373     /* compare to theoretical length of the stream (not just what
374        we saw) using the SYN and FIN
375      * Seq. Space wrap around calculations:
376      * Calculate stream length using last_seq_num seen, first_seq_num
377      * seen and wrap_count.
378      * first_seq_num = syn
379      * If reset_set, last_seq_num = latest_seq
380      *          else last_seq_num = fin
381      */
382 
383     pab_last = (pab->reset_count>0)?pab->latest_seq:pab->fin;
384 
385     pba_last = (pba->reset_count>0)?pba->latest_seq:pba->fin;
386 
387     /* calculating stream length for direction pab */
388     if ((pab->syn_count > 0) && (pab->fin_count > 0)) {
389 	if (pab->seq_wrap_count > 0) {
390 	    if (pab_last > pab->syn) {
391 		stream_length_pab = pab_last + (MAX_32 * pab->seq_wrap_count) - pab->syn - 1;
392 	    }
393 	    else {
394 		stream_length_pab = pab_last + (MAX_32 * (pab->seq_wrap_count+1)) - pab->syn - 1;
395 	    }
396 	}
397 	else {
398 	    if (pab_last > pab->syn) {
399 		stream_length_pab = pab_last - pab->syn - 1;
400 	    }
401 	    else {
402 		stream_length_pab = MAX_32 + pab_last - pab->syn - 1;
403 	    }
404 	}
405     }
406 
407     /* calculating stream length for direction pba */
408     if ((pba->syn_count > 0) && (pba->fin_count > 0)) {
409 	if (pba->seq_wrap_count > 0) {
410 	    if (pba_last > pba->syn) {
411 		stream_length_pba = pba_last + (MAX_32 * pba->seq_wrap_count) - pba->syn - 1;
412 	    }
413 	    else {
414 		stream_length_pba = pba_last + (MAX_32 * (pba->seq_wrap_count+1)) - pba->syn - 1;
415 	    }
416 	}
417 	else {
418 	    if (pba_last > pba->syn) {
419 		stream_length_pba = pba_last - pba->syn - 1;
420 	    }
421 	    else {
422 		stream_length_pba = MAX_32 + pba_last - pba->syn - 1;
423 	    }
424 	}
425     }
426 
427     /* print out values */
428     if ((pab->fin_count > 0) && (pab->syn_count > 0)) {
429 	char *format = "%8" FS_ULL;
430 	StatLineFieldL("ttl stream length", "bytes", format, stream_length_pab, 0);
431     }
432     else {
433 	StatLineField("ttl stream length", "", "%s", (u_long)"NA", 0);
434     }
435     if ((pba->fin_count > 0) && (pba->syn_count > 0)) {
436 	char *format = "%8" FS_ULL;
437 	StatLineFieldL("ttl stream length", "bytes", format, stream_length_pba, 1);
438     }
439     else {
440 	StatLineField("ttl stream length", "", "%s", (u_long)"NA", 1);
441     }
442 
443     if ((pab->fin_count > 0) && (pab->syn_count > 0)) {
444 	char *format = "%8" FS_ULL;
445 	StatLineFieldL("missed data", "bytes", format, (stream_length_pab - pab->unique_bytes), 0);
446     }
447     else {
448 	StatLineField("missed data", "", "%s", (u_long)"NA", 0);
449     }
450     if ((pba->fin_count > 0) && (pba->syn_count > 0)) {
451 	char *format = "%8" FS_ULL;
452 	StatLineFieldL("missed data", "bytes", format, (stream_length_pba - pba->unique_bytes), 1);
453     }
454     else {
455 	StatLineField("missed data", "", "%s", (u_long)"NA", 1);
456     }
457 
458     /* tell how much data was NOT captured in the files */
459     StatLineI("truncated data","bytes",
460 	      pab->trunc_bytes, pba->trunc_bytes);
461     StatLineI("truncated packets","pkts",
462 	      pab->trunc_segs, pba->trunc_segs);
463 
464     /* stats on just the data */
465     etime_data1 = elapsed(pab->first_data_time,
466 			  pab->last_data_time); /* in usecs */
467     etime_data2 = elapsed(pba->first_data_time,
468 			  pba->last_data_time); /* in usecs */
469     /* fix from Rob Austein */
470     StatLineF("data xmit time","secs","%7.3f",
471 	      etime_data1 / 1000000.0,
472 	      etime_data2 / 1000000.0);
473     StatLineP("idletime max","ms","%s",
474 	      ZERO_TIME(&pab->last_time)?"NA":
475 	      (snprintf(bufl,sizeof(bufl),"%8.1f",(double)pab->idle_max/1000.0),bufl),
476 	      ZERO_TIME(&pba->last_time)?"NA":
477 	      (snprintf(bufr,sizeof(bufr),"%8.1f",(double)pba->idle_max/1000.0),bufr));
478 
479     if ((pab->num_hardware_dups != 0) || (pba->num_hardware_dups != 0)  || csv || tsv || (sv != NULL)) {
480 	StatLineI("hardware dups","segs",
481 		  pab->num_hardware_dups, pba->num_hardware_dups);
482 
483         if(!(csv || tsv || (sv != NULL)))
484 	  fprintf(stdout,
485 		  "       ** WARNING: presence of hardware duplicates makes these figures suspect!\n");
486     }
487 
488     /* do the throughput calcs */
489     etime /= 1000000.0;  /* convert to seconds */
490     if (etime == 0.0)
491 	StatLineP("throughput","","%s","NA","NA");
492     else
493 	StatLineF("throughput","Bps","%8.0f",
494 		  (double) (pab->unique_bytes) / etime,
495 		  (double) (pba->unique_bytes) / etime);
496 
497     if (print_rtt) {
498         if(!(csv || tsv || (sv != NULL)))
499 	  fprintf(stdout,"\n");
500 	StatLineI("RTT samples","", pab->rtt_count, pba->rtt_count);
501 	StatLineF("RTT min","ms","%8.1f",
502 		  (double)pab->rtt_min/1000.0,
503 		  (double)pba->rtt_min/1000.0);
504 	StatLineF("RTT max","ms","%8.1f",
505 		  (double)pab->rtt_max/1000.0,
506 		  (double)pba->rtt_max/1000.0);
507 	StatLineF("RTT avg","ms","%8.1f",
508 		  Average(pab->rtt_sum, pab->rtt_count) / 1000.0,
509 		  Average(pba->rtt_sum, pba->rtt_count) / 1000.0);
510 	StatLineF("RTT stdev","ms","%8.1f",
511 		  Stdev(pab->rtt_sum, pab->rtt_sum2, pab->rtt_count) / 1000.0,
512 		  Stdev(pba->rtt_sum, pba->rtt_sum2, pba->rtt_count) / 1000.0);
513         if(!(csv || tsv || (sv != NULL)))
514 	  fprintf(stdout,"\n");
515 	StatLineF("RTT from 3WHS","ms","%8.1f",
516 		  (double)pab->rtt_3WHS/1000.0,
517 		  (double)pba->rtt_3WHS/1000.0);
518         if(!(csv || tsv || (sv != NULL)))
519 	  fprintf(stdout,"\n");
520 	StatLineI("RTT full_sz smpls","",
521 		  pab->rtt_full_count, pba->rtt_full_count);
522 	StatLineF("RTT full_sz min","ms","%8.1f",
523 		  (double)pab->rtt_full_min/1000.0,
524 		  (double)pba->rtt_full_min/1000.0);
525 	StatLineF("RTT full_sz max","ms","%8.1f",
526 		  (double)pab->rtt_full_max/1000.0,
527 		  (double)pba->rtt_full_max/1000.0);
528 	StatLineF("RTT full_sz avg","ms","%8.1f",
529 		  Average(pab->rtt_full_sum, pab->rtt_full_count) / 1000.0,
530 		  Average(pba->rtt_full_sum, pba->rtt_full_count) / 1000.0);
531 	StatLineF("RTT full_sz stdev","ms","%8.1f",
532 		  Stdev(pab->rtt_full_sum, pab->rtt_full_sum2, pab->rtt_full_count) / 1000.0,
533 		  Stdev(pba->rtt_full_sum, pba->rtt_full_sum2, pba->rtt_full_count) / 1000.0);
534         if(!(csv || tsv || (sv != NULL)))
535 	  fprintf(stdout,"\n");
536 	StatLineI("post-loss acks","",
537 		  pab->rtt_nosample, pba->rtt_nosample);
538 	if (pab->rtt_amback || pba->rtt_amback || csv || tsv || (sv != NULL)) {
539 	   if(!(csv || tsv || (sv != NULL)))
540 	     fprintf(stdout, "\
541 \t  For the following 5 RTT statistics, only ACKs for\n\
542 \t  multiply-transmitted segments (ambiguous ACKs) were\n\
543 \t  considered.  Times are taken from the last instance\n\
544 \t  of a segment.\n\
545 ");
546 	    StatLineI("ambiguous acks","",
547 		      pab->rtt_amback, pba->rtt_amback);
548 	    StatLineF("RTT min (last)","ms","%8.1f",
549 		      (double)pab->rtt_min_last/1000.0,
550 		      (double)pba->rtt_min_last/1000.0);
551 	    StatLineF("RTT max (last)","ms","%8.1f",
552 		      (double)pab->rtt_max_last/1000.0,
553 		      (double)pba->rtt_max_last/1000.0);
554 	    StatLineF("RTT avg (last)","ms","%8.1f",
555 		      Average(pab->rtt_sum_last, pab->rtt_count_last) / 1000.0,
556 		      Average(pba->rtt_sum_last, pba->rtt_count_last) / 1000.0);
557 	    StatLineF("RTT sdv (last)","ms","%8.1f",
558 		      Stdev(pab->rtt_sum_last, pab->rtt_sum2_last, pab->rtt_count_last) / 1000.0,
559 		      Stdev(pba->rtt_sum_last, pba->rtt_sum2_last, pba->rtt_count_last) / 1000.0);
560 
561 	}
562 	StatLineI("segs cum acked","",
563 		  pab->rtt_cumack, pba->rtt_cumack);
564 	StatLineI("duplicate acks","",
565 		  pab->rtt_dupack, pba->rtt_dupack);
566 	StatLineI("triple dupacks","",
567 		  pab->rtt_triple_dupack, pba->rtt_triple_dupack);
568 	if (debug)
569 	    StatLineI("unknown acks:","",
570 		      pab->rtt_unkack, pba->rtt_unkack);
571 	StatLineI("max # retrans","",
572 		  pab->retr_max, pba->retr_max);
573 	StatLineF("min retr time","ms","%8.1f",
574 		  (double)((double)pab->retr_min_tm/1000.0),
575 		  (double)((double)pba->retr_min_tm/1000.0));
576 	StatLineF("max retr time","ms","%8.1f",
577 		  (double)((double)pab->retr_max_tm/1000.0),
578 		  (double)((double)pba->retr_max_tm/1000.0));
579 	StatLineF("avg retr time","ms","%8.1f",
580 		  Average(pab->retr_tm_sum, pab->retr_tm_count) / 1000.0,
581 		  Average(pba->retr_tm_sum, pba->retr_tm_count) / 1000.0);
582 	StatLineF("sdv retr time","ms","%8.1f",
583 		  Stdev(pab->retr_tm_sum, pab->retr_tm_sum2,
584 			pab->retr_tm_count) / 1000.0,
585 		  Stdev(pba->retr_tm_sum, pba->retr_tm_sum2,
586 			pba->retr_tm_count) / 1000.0);
587     }
588 
589    if(csv || tsv || (sv != NULL)) {
590       printf("\n");
591       /* Error checking: print an error message if the count of printed fields
592        * doesn't correspond to the actual fields expected.
593        */
594       if(sv_print_count != sv_expected_count) {
595 	fprintf(stderr, "output.c: Count of printed fields does not correspond to count of header fields for long output with comma/tab/<SP>-separated values.\n");
596 	fprintf(stderr,"sv_print_count=%u, sv_expected_count=%u\n",
597 		sv_print_count, sv_expected_count);
598 	exit(-1);
599       }
600    }
601 }
602 
603 void
PrintBrief(tcp_pair * ptp)604 PrintBrief(
605     tcp_pair *ptp)
606 {
607     tcb *pab = &ptp->a2b;
608     tcb *pba = &ptp->b2a;
609     static int max_width = -1;
610 
611     /* determine the maximum connection name width to make it nice */
612     if (max_width == -1) {
613 	int ix;
614 	int len;
615 	tcp_pair *tmp_ptp;
616 
617 	for (ix = 0; ix <= num_tcp_pairs; ++ix) {
618 	    tmp_ptp = ttp[ix];
619 	    if (tmp_ptp->ignore_pair)
620 		continue;
621 
622 	    len = strlen(FormatBrief(tmp_ptp));
623 	    if (len > max_width)
624 		max_width = len;
625 	}
626 	if (debug > 2)
627 	    fprintf(stderr,"Max name width: %d\n", max_width);
628     }
629 
630 
631     if (TRUE) {
632 	/* new version */
633 	fprintf(stdout,"%*s", -max_width, FormatBrief(ptp));
634 
635 	fprintf(stdout," %4" FS_ULL ">", pab->packets);
636 	fprintf(stdout," %4" FS_ULL "<", pba->packets);
637 
638     } else {
639 	/* old version */
640 	fprintf(stdout,"%s <==> %s",
641 		ptp->a_endpoint,
642 		ptp->b_endpoint);
643 
644 	fprintf(stdout,"  %s2%s:%"FS_ULL,
645 		pab->host_letter,
646 		pba->host_letter,
647 		pab->packets);
648 
649 	fprintf(stdout,"  %s2%s:%"FS_ULL,
650 		pba->host_letter,
651 		pab->host_letter,
652 		pba->packets);
653     }
654     if (ConnComplete(ptp))
655 	fprintf(stdout,"  (complete)");
656     if (ConnReset(ptp))
657         fprintf(stdout,"  (reset)");
658     if ((ptp->a2b.packets == 0) || (ptp->b2a.packets == 0))
659         fprintf(stdout,"  (unidirectional)");
660 
661     fprintf(stdout,"\n");
662 
663     /* warning for hardware duplicates */
664     if (pab->num_hardware_dups != 0) {
665 	fprintf(stdout,
666 		"    ** Warning, %s2%s: detected %lu hardware duplicate(s) (same seq # and IP ID)\n",
667 		pab->host_letter, pba->host_letter,
668 		pab->num_hardware_dups);
669     }
670     if (pba->num_hardware_dups != 0) {
671 	fprintf(stdout,
672 		"    ** Warning, %s2%s: detected %lu hardware duplicate(s) (same seq # and IP ID)\n",
673 		pba->host_letter, pab->host_letter,
674 		pba->num_hardware_dups);
675     }
676 }
677 
678 
679 
680 
681 void
UDPPrintTrace(udp_pair * pup)682 UDPPrintTrace(
683     udp_pair *pup)
684 {
685     double etime;
686     u_long etime_secs;
687     u_long etime_usecs;
688     ucb *pab = &pup->a2b;
689     ucb *pba = &pup->b2a;
690     char *host1 = pab->host_letter;
691     char *host2 = pba->host_letter;
692     char bufl[40];
693 
694     fprintf(stdout,"\thost %-4s      %s\n",
695 	    (snprintf(bufl,sizeof(bufl),"%s:", host1),bufl), pup->a_endpoint);
696     fprintf(stdout,"\thost %-4s      %s\n",
697 	    (snprintf(bufl,sizeof(bufl),"%s:", host2),bufl), pup->b_endpoint);
698     fprintf(stdout,"\n");
699 
700     fprintf(stdout,"\tfirst packet:  %s\n", ts2ascii(&pup->first_time));
701     fprintf(stdout,"\tlast packet:   %s\n", ts2ascii(&pup->last_time));
702 
703     etime = elapsed(pup->first_time,pup->last_time);
704     etime_secs = etime / 1000000.0;
705     etime_usecs = 1000000 * (etime/1000000.0 - (double)etime_secs);
706     fprintf(stdout,"\telapsed time:  %s\n", elapsed2str(etime));
707 
708     fprintf(stdout,"\ttotal packets: %" FS_ULL "\n", pup->packets);
709 
710     fprintf(stdout,"\tfilename:      %s\n", pup->filename);
711 
712     fprintf(stdout,"   %s->%s:			      %s->%s:\n",
713 	    host1,host2,host2,host1);
714 
715     StatLineI("total packets","", pab->packets, pba->packets);
716     StatLineI("data bytes sent","",
717 	      pab->data_bytes, pba->data_bytes);
718 
719     /* do the throughput calcs */
720     etime /= 1000000.0;  /* convert to seconds */
721     if (etime == 0.0)
722 	StatLineP("throughput","","%s","NA","NA");
723     else
724 	StatLineF("throughput","Bps","%8.0f",
725 		  (double) (pab->data_bytes) / etime,
726 		  (double) (pba->data_bytes) / etime);
727 }
728 
729 
730 /* with pointer args */
731 static void
StatLineP(char * label,char * units,char * format,void * argleft,void * argright)732 StatLineP(
733     char *label,
734     char *units,
735     char *format,
736     void *argleft,
737     void *argright)
738 {
739     StatLineField(label,units,format,(u_long)argleft,0);
740     StatLineField(label,units,format,(u_long)argright,1);
741 }
742 
743 
744 /* with u_long args */
745 static void
StatLineI_L(char * label,char * units,u_long argleft,u_long argright)746 StatLineI_L(
747     char *label,
748     char *units,
749     u_long argleft,
750     u_long argright)
751 {
752     char *format = "%8lu";
753     StatLineField(label,units,format,argleft,0);
754     StatLineField(label,units,format,argright,1);
755 }
756 
757 
758 #ifdef HAVE_LONG_LONG
759 /* with u_llong (long long) args, if supported */
760 static void
StatLineI_LL(char * label,char * units,u_llong argleft,u_llong argright)761 StatLineI_LL(
762     char *label,
763     char *units,
764     u_llong argleft,
765     u_llong argright)
766 {
767     char *format = "%8" FS_ULL;
768     StatLineFieldL(label,units,format,argleft,0);
769     StatLineFieldL(label,units,format,argright,1);
770 }
771 
772 static void
StatLineFieldL(char * label,char * units,char * format,u_llong arg,int f_rightside)773 StatLineFieldL(
774     char *label,
775     char *units,
776     char *format,
777     u_llong arg,
778     int	f_rightside)
779 {
780     /* bug fix: Theo Snelleman */
781     /* "The biggest number possible is 18446744073709551615 (20 digits) and
782         is too big for valbuf[20] ('\0' is the 21th character)." */
783     /* it was originally an array of [20] */
784     char valbuf[21];
785 
786     /* determine the value to print */
787     snprintf(valbuf,sizeof(valbuf),format,arg);
788 
789     /* print the field */
790     if(!(csv || tsv || (sv != NULL)))
791      printf("     ");
792     StatLineOne(label, units, valbuf);
793     if (f_rightside && !(csv || tsv || (sv != NULL)))
794 	printf("\n");
795 }
796 #endif /* HAVE_LONG_LONG */
797 
798 
799 static void
StatLineF(char * label,char * units,char * format,double argleft,double argright)800 StatLineF(
801     char *label,
802     char *units,
803     char *format,
804     double argleft,
805     double argright)
806 {
807     StatLineFieldF(label,units,format,argleft,0);
808     StatLineFieldF(label,units,format,argright,1);
809 }
810 
811 
812 
813 
814 static void
StatLineField(char * label,char * units,char * format,u_long arg,int f_rightside)815 StatLineField(
816     char *label,
817     char *units,
818     char *format,
819     u_long arg,
820     int	f_rightside)
821 {
822     char valbuf[20];
823 
824     /* determine the value to print */
825     snprintf(valbuf,sizeof(valbuf),format,arg);
826 
827     /* print the field */
828     if(!(csv || tsv || (sv != NULL)))
829      printf("     ");
830     StatLineOne(label, units, valbuf);
831     if (f_rightside && !(csv || tsv || (sv != NULL)))
832 	printf("\n");
833 }
834 
835 
836 
837 static void
StatLineFieldF(char * label,char * units,char * format,double arg,int f_rightside)838 StatLineFieldF(
839     char *label,
840     char *units,
841     char *format,
842     double arg,
843     int	f_rightside)
844 {
845     int printable;
846     char valbuf[20];
847 
848     /* see if the float argument is printable */
849     printable = finite(arg);
850 
851     /* determine the value to print */
852     if (printable)
853 	snprintf(valbuf,sizeof(valbuf),format,arg);
854 
855     /* print the field */
856     if(!(csv || tsv || (sv != NULL)))
857      printf("     ");
858     if (printable)
859 	StatLineOne(label, units, valbuf);
860     else
861 	StatLineOne(label, "", "NA");
862     if (f_rightside && !(csv || tsv || (sv != NULL)))
863 	printf("\n");
864 }
865 
866 
867 static void
StatLineOne(char * label,char * units,char * value)868 StatLineOne(
869     char *label,
870     char *units,
871     char *value)
872 {
873     char labbuf[20];
874 
875     /* format the label */
876     snprintf(labbuf,sizeof(labbuf), "%s:", label);
877 
878     /* print the field */
879     if(csv || tsv || (sv != NULL)) {
880        printf("%15s%s", value, sp);
881        /* Count the fields printed until this point. Used as a guard with the
882 	* <SP>-separated-values option to ensure correct alignment of headers
883 	* and field values.
884 	*/
885        sv_print_count++;
886     }
887     else
888      printf("%-18s %9s %-5s", labbuf, value, units);
889 }
890 
891 
892 char *
elapsed2str(double etime)893 elapsed2str(
894     double etime)
895 {
896     static char buf[80];
897     u_long etime_secs;
898     u_long etime_usecs;
899 
900     etime_secs = etime / 1000000.0;
901     etime_usecs = 1000000 * (etime/1000000.0 - (double)etime_secs);
902     snprintf(buf,sizeof(buf),"%lu:%02lu:%02lu.%06lu",
903 	    etime_secs / (60 * 60),
904 	    etime_secs % (60 * 60) / 60,
905 	    (etime_secs % (60 * 60)) % 60,
906 	    etime_usecs);
907     return(buf);
908 }
909 
910 
911 void
UDPPrintBrief(udp_pair * pup)912 UDPPrintBrief(
913     udp_pair *pup)
914 {
915     ucb *pab = &pup->a2b;
916     ucb *pba = &pup->b2a;
917     static int max_width = -1;
918 
919     /* determine the maximum connection name width to make it nice */
920     if (max_width == -1) {
921 	int ix;
922 	int len;
923 	udp_pair *tmp_pup;
924 
925 	for (ix = 0; ix <= num_udp_pairs; ++ix) {
926 	    tmp_pup = utp[ix];
927 
928 	    len = strlen(UDPFormatBrief(tmp_pup));
929 	    if (len > max_width)
930 		max_width = len;
931 	}
932 	if (debug > 2)
933 	    fprintf(stderr,"Max name width: %d\n", max_width);
934     }
935 
936 
937     /* new version */
938     fprintf(stdout,"%*s", -max_width, UDPFormatBrief(pup));
939 
940     fprintf(stdout," %4" FS_ULL ">", pab->packets);
941     fprintf(stdout," %4" FS_ULL "<", pba->packets);
942 
943     fprintf(stdout,"\n");
944 }
945 
946 
947 static char *
UDPFormatBrief(udp_pair * pup)948 UDPFormatBrief(
949     udp_pair *pup)
950 {
951     ucb *pab = &pup->a2b;
952     ucb *pba = &pup->b2a;
953     static char infobuf[100];
954 
955     snprintf(infobuf,sizeof(infobuf),"%s - %s (%s2%s)",
956 	    pup->a_endpoint, pup->b_endpoint,
957 	    pab->host_letter, pba->host_letter);
958     return(infobuf);
959 }
960 
961 
962 /* Print the header if comma-separated-values or tab-separated-values
963  * has been requested.
964  */
965 void
PrintSVHeader(void)966 PrintSVHeader(
967 	      void)
968 {
969    /* NOTE: If you have added new fields of output to be printed in
970     * PrintTrace(), make sure you update the header-list here too, so that the
971     * new field you have added also has a header in the --csv/--tsv/--sv
972     * output.
973     */
974 
975    /* Headers for long output requested with comma/tab/<SP>-separated- values
976     * Split up into two headers, since the OWIN stats printed when the
977     * -lW option is given, generates fields of output that get printed in the
978     * middle of the output generated with just the -l option.
979     */
980 
981    char *svHeader1[] = {
982         "conn_#"                   ,
983         "host_a"                   , "host_b",
984 	"port_a"                   , "port_b",
985 	"first_packet"             , "last_packet",
986 	"total_packets_a2b"        , "total_packets_b2a",
987 	"resets_sent_a2b"          , "resets_sent_b2a",
988 	"ack_pkts_sent_a2b"        , "ack_pkts_sent_b2a",
989 	"pure_acks_sent_a2b"       , "pure_acks_sent_b2a",
990 	"sack_pkts_sent_a2b"       , "sack_pkts_sent_b2a",
991         "dsack_pkts_sent_a2b"      , "dsack_pkts_sent_b2a",
992 	"max_sack_blks/ack_a2b"    , "max_sack_blks/ack_b2a",
993 	"unique_bytes_sent_a2b"    , "unique_bytes_sent_b2a",
994 	"actual_data_pkts_a2b"     , "actual_data_pkts_b2a",
995 	"actual_data_bytes_a2b"    , "actual_data_bytes_b2a",
996 	"rexmt_data_pkts_a2b"      , "rexmt_data_pkts_b2a",
997 	"rexmt_data_bytes_a2b"     , "rexmt_data_bytes_b2a",
998 	"zwnd_probe_pkts_a2b"      , "zwnd_probe_pkts_b2a",
999 	"zwnd_probe_bytes_a2b"     , "zwnd_probe_bytes_b2a",
1000 	"outoforder_pkts_a2b"      , "outoforder_pkts_b2a",
1001 	"pushed_data_pkts_a2b"     , "pushed_data_pkts_b2a",
1002 	"SYN/FIN_pkts_sent_a2b"    , "SYN/FIN_pkts_sent_b2a",
1003 	"req_1323_ws/ts_a2b"       , "req_1323_ws/ts_b2a",
1004 	"adv_wind_scale_a2b"       , "adv_wind_scale_b2a",
1005 	"req_sack_a2b"             , "req_sack_b2a",
1006 	"sacks_sent_a2b"           , "sacks_sent_b2a",
1007 	"urgent_data_pkts_a2b"     , "urgent_data_pkts_b2a",
1008 	"urgent_data_bytes_a2b"    , "urgent_data_bytes_b2a",
1009 	"mss_requested_a2b"        , "mss_requested_b2a",
1010 	"max_segm_size_a2b"        , "max_segm_size_b2a",
1011 	"min_segm_size_a2b"        , "min_segm_size_b2a",
1012 	"avg_segm_size_a2b"        , "avg_segm_size_b2a",
1013 	"max_win_adv_a2b"          , "max_win_adv_b2a",
1014 	"min_win_adv_a2b"          , "min_win_adv_b2a",
1015 	"zero_win_adv_a2b"         , "zero_win_adv_b2a",
1016 	"avg_win_adv_a2b"          , "avg_win_adv_b2a"
1017    };
1018    #define SV_HEADER1_COLUMN_COUNT (sizeof(svHeader1)/sizeof(char*))
1019 
1020    char *svHeader2[] = {
1021        "initial_window_bytes_a2b" , "initial_window_bytes_b2a",
1022        "initial_window_pkts_a2b"  , "initial_window_pkts_b2a",
1023        "ttl_stream_length_a2b"    , "ttl_stream_length_b2a",
1024        "missed_data_a2b"          , "missed_data_b2a",
1025        "truncated_data_a2b"       , "truncated_data_b2a",
1026        "truncated_packets_a2b"    , "truncated_packets_b2a",
1027        "data_xmit_time_a2b"       , "data_xmit_time_b2a",
1028        "idletime_max_a2b"         , "idletime_max_b2a",
1029        "hardware_dups_a2b"        , "hardware_dups_b2a",
1030        "throughput_a2b"           , "throughput_b2a"
1031    };
1032 
1033    #define SV_HEADER2_COLUMN_COUNT (sizeof(svHeader2)/sizeof(char*))
1034 
1035    /* Headers to be printed if the OWIN stats are requested.
1036     */
1037 
1038    char *svOWINHeader[] = {
1039        "max_owin_a2b"             , "max_owin_b2a",
1040        "min_non-zero_owin_a2b"    , "min_non-zero_owin_b2a",
1041        "avg_owin_a2b"             , "avg_owin_b2a",
1042        "wavg_owin_a2b"            , "wavg_owin_b2a"
1043    };
1044 
1045    #define SV_OWIN_HEADER_COLUMN_COUNT (sizeof(svOWINHeader)/sizeof(char*))
1046 
1047 
1048    /* Headers for RTT, to be printed for long output requested with
1049     * comma/tab/<SP>-separated- values.
1050     */
1051    char *svRTTHeader[] = {
1052         "RTT_samples_a2b"       , "RTT_samples_b2a",
1053 	"RTT_min_a2b"           , "RTT_min_b2a",
1054 	"RTT_max_a2b"           , "RTT_max_b2a",
1055 	"RTT_avg_a2b"           , "RTT_avg_b2a",
1056 	"RTT_stdev_a2b"         , "RTT_stdev_b2a",
1057 	"RTT_from_3WHS_a2b"     , "RTT_from_3WHS_b2a",
1058 	"RTT_full_sz_smpls_a2b" , "RTT_full_sz_smpls_b2a",
1059 	"RTT_full_sz_min_a2b"   , "RTT_full_sz_min_b2a",
1060 	"RTT_full_sz_max_a2b"   , "RTT_full_sz_max_b2a",
1061 	"RTT_full_sz_avg_a2b"   , "RTT_full_sz_avg_b2a",
1062 	"RTT full_sz_stdev_a2b" , "RTT_full_sz_stdev_b2a",
1063 	"post-loss_acks_a2b"    , "post-loss_acks_b2a",
1064 	"ambiguous_acks_a2b"    , "ambiguous_acks_b2a",
1065 	"RTT_min_(last)_a2b"    , "RTT_min_(last)_b2a",
1066 	"RTT_max_(last)_a2b"    , "RTT_max_(last)_b2a",
1067 	"RTT_avg_(last)_a2b"    , "RTT_avg_(last)_b2a",
1068 	"RTT_sdv_(last)_a2b"    , "RTT_sdv_(last)_b2a",
1069 	"segs_cum_acked_a2b"    , "segs_cum_acked_b2a",
1070 	"duplicate_acks_a2b"    , "duplicate_acks_b2a",
1071 	"triple_dupacks_a2b"    , "triple_dupacks_b2a",
1072 	"max_#_retrans_a2b"     , "max_#_retrans_b2a",
1073 	"min_retr_time_a2b"     , "min_retr_time_b2a",
1074 	"max_retr_time_a2b"     , "max_retr_time_b2a",
1075 	"avg_retr_time_a2b"     , "avg_retr_time_b2a",
1076 	"sdv_retr_time_a2b"     , "sdv_retr_time_b2a"
1077    };
1078    #define SV_RTT_HEADER_COLUMN_COUNT (sizeof(svRTTHeader)/sizeof(char*))
1079 
1080    /* Local Variables */
1081    u_int i = 0; /* Counter */
1082 
1083    /* Set the separator */
1084    if(csv || tsv) {
1085       /* Initialize the separator buffer */
1086       sp = (char *)malloc(sizeof(char *) * 2);
1087       memset(sp, 0, sizeof(sp));
1088       /* Set it */
1089       if(csv)
1090 	snprintf(sp, sizeof(sp), ",");
1091       else if(tsv)
1092 	snprintf(sp, sizeof(sp), "\t");
1093    }
1094    else if (sv != NULL)
1095      {
1096 	/* Look for escape sequence and remove the extra '\',
1097 	 * the shell puts it in there.
1098 	 * We will do this only for the escape sequence '\t' since that is
1099 	 * the only useful one, else the user probably meant something
1100 	 * else and things get messy.
1101 	 */
1102 	if(strncmp(sv, "\\t", 2) == 0) {
1103 	   /* Initialize the separator buffer and set it */
1104 	   sp = (char *)malloc(sizeof(char *) * 2);
1105 	   memset(sp, 0, sizeof(sp));
1106 	   snprintf(sp, sizeof(sp), "\t");
1107 	}
1108 	else /* Just use the string the user has provided */
1109 	  sp = strdup(sv);
1110      }
1111 
1112    /* Print the column headings (the field names) */
1113     for (i=0; i<SV_HEADER1_COLUMN_COUNT; i++)
1114       fprintf(stdout, "%s%s", svHeader1[i], sp);
1115 
1116     if (print_owin) {
1117        for(i=0; i<SV_OWIN_HEADER_COLUMN_COUNT; i++)
1118          fprintf(stdout, "%s%s", svOWINHeader[i], sp);
1119     }
1120 
1121     for (i=0; i<SV_HEADER2_COLUMN_COUNT; i++)
1122       fprintf(stdout, "%s%s", svHeader2[i], sp);
1123 
1124 
1125    /* Print the RTT column headings (the field names) */
1126    if(print_rtt)
1127      for(i = 0; i < SV_RTT_HEADER_COLUMN_COUNT; i++)
1128        fprintf(stdout, "%s%s", svRTTHeader[i], sp);
1129 
1130    /* Improve readability */
1131    fprintf(stdout, "\n\n");
1132 
1133    /* Set the number of columns expected to be printed. */
1134    sv_expected_count=SV_HEADER1_COLUMN_COUNT + SV_HEADER2_COLUMN_COUNT;
1135 
1136    if (print_rtt)
1137      sv_expected_count += SV_RTT_HEADER_COLUMN_COUNT;
1138 
1139    if (print_owin)
1140      sv_expected_count += SV_OWIN_HEADER_COLUMN_COUNT;
1141 
1142    if (debug>3) {
1143      fprintf(stderr,"SV_HEADER_COUNT : -l alone = %d\n", \
1144             (int)(SV_HEADER1_COLUMN_COUNT + SV_HEADER2_COLUMN_COUNT));
1145      fprintf(stderr,"                : -W alone = %d\n", \
1146             (int)SV_OWIN_HEADER_COLUMN_COUNT);
1147      fprintf(stderr,"                : -r alone = %d\n", \
1148             (int)SV_RTT_HEADER_COLUMN_COUNT);
1149 
1150      fprintf(stderr,"sv_expected_count=%u\n",sv_expected_count);
1151    }
1152 }
1153