1/*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2018 Chelsio Communications, Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29#include <sys/cdefs.h>
30#include "tcb_common.h"
31
32/***:-----------------------------------------------------------------------
33 ***: externals
34 ***:-----------------------------------------------------------------------
35 */
36
37extern _TCBVAR g_tcb_info4[];
38extern _TCBVAR g_scb_info4[];
39extern _TCBVAR g_fcb_info4[];
40extern void t4_display_tcb_aux_0(_TCBVAR *tvp,int aux);
41extern void t4_display_tcb_aux_1(_TCBVAR *tvp,int aux);
42extern void t4_display_tcb_aux_2(_TCBVAR *tvp,int aux);
43extern void t4_display_tcb_aux_3(_TCBVAR *tvp,int aux);
44
45extern _TCBVAR g_tcb_info5[];
46extern _TCBVAR g_scb_info5[];
47extern _TCBVAR g_fcb_info5[];
48extern void t5_display_tcb_aux_0(_TCBVAR *tvp,int aux);
49extern void t5_display_tcb_aux_1(_TCBVAR *tvp,int aux);
50extern void t5_display_tcb_aux_2(_TCBVAR *tvp,int aux);
51extern void t5_display_tcb_aux_3(_TCBVAR *tvp,int aux);
52
53extern _TCBVAR g_tcb_info6[];
54extern _TCBVAR g_scb_info6[];
55extern _TCBVAR g_fcb_info6[];
56extern void t6_display_tcb_aux_0(_TCBVAR *tvp,int aux);
57extern void t6_display_tcb_aux_1(_TCBVAR *tvp,int aux);
58extern void t6_display_tcb_aux_2(_TCBVAR *tvp,int aux);
59extern void t6_display_tcb_aux_3(_TCBVAR *tvp,int aux);
60extern void t6_display_tcb_aux_4(_TCBVAR *tvp,int aux);
61
62/***:-----------------------------------------------------------------------
63 ***: globals
64 ***:-----------------------------------------------------------------------
65 */
66
67_TCBVAR *g_tcb_info=g_tcb_info5;
68_TCBVAR *g_scb_info=g_scb_info5;
69_TCBVAR *g_fcb_info=g_fcb_info5;
70static int g_tN=0;
71
72static int g_prntstyl=PRNTSTYL_COMP;
73
74static int g_got_scb=0;
75static int g_got_fcb=0;
76
77
78/***:-----------------------------------------------------------------------
79***: error exit functions
80***:-----------------------------------------------------------------------
81*/
82
83/**: err_exit functions
84*:  ------------------
85*/
86
87void tcb_prflush(void)
88{
89    fflush(stdout);
90    fflush(stderr);
91}
92
93
94void tcb_code_err_exit(char *fmt, ...)
95{
96  va_list args;
97  va_start(args, fmt);
98  printf("Coding Error in: ");
99  vprintf(fmt, args);
100  printf("\n");
101  tcb_prflush();
102  va_end(args);
103  exit(1);
104}
105
106/***:-----------------------------------------------------------------------
107***: tcb_hexdump functions
108***:-----------------------------------------------------------------------
109*/
110
111void
112tcb_hexdump(unsigned base, unsigned char *buf, unsigned int size)
113{
114    unsigned offset;
115
116    for (offset = 0; offset < size; ++offset) {
117        if (!(offset % 16)) printf("\n0x%4.4x: ", base + offset);
118        else if (!(offset % 8)) printf(" ");
119        printf("%2.2x ", (unsigned char)buf[offset]);
120    }
121}
122
123int tcb_strmatch_nc(char *cs, char *ct) {
124    while (*cs)
125        if (tolower(*cs++) != tolower(*ct++)) return (FALSE);
126    return (!(*ct));  /*return TRUE if *ct NULL at same time as *cs==NULL*/
127}
128
129
130/*: -------------------------------------------------------------------------
131string functions
132tcb_strmatch_nc:     Similar to exact match, but case insensitive.
133*/
134
135
136int
137tcb_strncmp_nc(char *cs, char *ct, int n)
138{
139    /*case insensitive version of the standard strncmp() function */
140    int i = 0;
141    int ret;
142
143
144    ret = 0;
145    for (i = 0; i < n && 0 == ret && !(EOS == *cs && EOS == *ct); ++i) {
146        /* this is weird, but it matched GCC linux when strings don't
147        * have any upper case characters.
148        */
149        ret = tolower(*cs++) - tolower(*ct++);
150    }
151    return ret;
152}
153
154int
155tcb_startswith_nc(char *cs, char *ct)
156{ /* return true if cs start with ct */
157    return (0 == tcb_strncmp_nc(cs, ct, (int)strlen(ct)));
158}
159
160
161
162
163/***:-----------------------------------------------------------------------
164 ***: START OF WINDOWS FUNCTIONS
165 ***:-----------------------------------------------------------------------
166 */
167
168
169/***:-----------------------------------------------------------------------
170 ***: print utilities
171 ***:-----------------------------------------------------------------------
172 */
173
174static int g_PR_indent=1;
175
176void PR(char *fmt, ...)
177{
178  int fmt_len;
179  va_list args;
180  va_start(args,fmt);
181
182  if (g_PR_indent) printf("  ");
183  g_PR_indent=0;
184  fmt_len=(int) strlen(fmt);
185  if (fmt_len>0 && fmt[fmt_len-1]=='\n') g_PR_indent=1;
186
187  vprintf(fmt,args);
188  tcb_prflush();
189  va_end(args);
190}
191
192
193/***:-----------------------------------------------------------------------
194 ***: val()
195 ***:-----------------------------------------------------------------------
196 */
197
198_TCBVAR *
199lu_tcbvar(char *name)
200{
201  _TCBVAR *tvp=g_tcb_info;
202
203  while (tvp->name!=NULL) {
204    if      (tcb_strmatch_nc(name,tvp->name)) return tvp;
205    else if (tcb_strmatch_nc(name,tvp->aka )) return tvp;
206    tvp+=1;
207  }
208  tcb_code_err_exit("lu_tcbvar: bad name %s\n",name);
209  return NULL;
210}
211
212unsigned
213val(char *name)
214{
215  _TCBVAR *tvp;
216
217  tvp=lu_tcbvar(name);
218  return tvp->val;
219}
220
221ui64
222val64(char *name)
223{
224  _TCBVAR *tvp;
225
226  tvp=lu_tcbvar(name);
227  return tvp->rawval;
228}
229
230
231
232/***:-----------------------------------------------------------------------
233 ***: get_tcb_bits
234 ***:-----------------------------------------------------------------------
235 */
236
237
238static int
239get_tcb_bit(unsigned char *A, int bit)
240{
241  int ret=0;
242  int ix,shift;
243
244  ix = 127 - (bit>>3);
245  shift=bit&0x7;
246  /*  prdbg("  ix: %u, shift=%u\n",ix,shift); */
247  ret=(A[ix] >> shift) & 1;
248  return ret;
249}
250
251static ui64
252get_tcb_bits (unsigned char  *A, int hi, int lo)
253{
254  ui64 ret=0;
255
256  if (lo>hi) {
257    int temp=lo;
258    lo=hi;
259    hi=temp;
260  }
261
262  while (hi>=lo) {
263    ret = (ret<<1) | get_tcb_bit(A,hi);
264    --hi;
265  }
266
267  return ret;
268}
269
270
271void
272decompress_val(_TCBVAR *tvp,unsigned ulp_type,unsigned tx_max,
273	       unsigned rcv_nxt,unsigned rx_frag0_start_idx_raw)
274{
275  unsigned rawval=(unsigned) tvp->rawval;
276
277  switch(tvp->comp) {
278  case COMP_NONE: tvp->val=rawval;  break;
279  case COMP_ULP:  tvp->val=rawval;  break;
280  case COMP_TX_MAX:
281    tvp->val=(tx_max - rawval) & 0xFFFFFFFF;
282    break;
283  case COMP_RCV_NXT:
284    if (tcb_startswith_nc(tvp->name,"rx_frag")) {
285      unsigned fragx=0;
286      if (!tcb_strmatch_nc(tvp->name,"rx_frag0_start_idx_raw"))
287	fragx=rawval;
288      tvp->val=(rcv_nxt+rx_frag0_start_idx_raw+fragx) & 0xFFFFFFFF;
289    } else {
290      tvp->val=(rcv_nxt - rawval) & 0xFFFFFFFF;
291    }
292    break;
293  case COMP_PTR: tvp->val=rawval;  break;
294  case COMP_LEN:
295    {
296      tvp->val=rawval;
297      if (PM_MODE_RDDP==ulp_type ||  PM_MODE_DDP==ulp_type ||
298	  PM_MODE_IANDP==ulp_type) {
299	/* TP does this internally.  Not sure if I should show the
300	 *  unaltered value or the raw value.  For now I
301	 *  will display the raw value.  For now I've added the code
302	 *  mainly to stop windows compiler from warning about ulp_type
303	 *  being an unreferenced parameter.
304	 */
305	tvp->val=0;
306	tvp->val=rawval;  /* comment this out to display altered value */
307      }
308    }
309    break;
310  default:
311    tcb_code_err_exit("decompress_val, bad switch: %d",tvp->comp);
312    break;
313  }
314
315
316
317}
318
319
320void
321get_tcb_field(_TCBVAR *tvp,unsigned char *buf)
322{
323  assert(tvp->hi-tvp->lo+1<=64);
324  assert(tvp->hi>=tvp->lo);
325
326  tvp->rawval=get_tcb_bits(buf,tvp->lo,tvp->hi);
327  /* assume no compression and 32-bit value for now */
328  tvp->val=(unsigned) (tvp->rawval & 0xFFFFFFFF);
329
330
331}
332
333
334/***:-----------------------------------------------------------------------
335 ***: spr_* functions
336 ***:-----------------------------------------------------------------------
337 */
338
339char *
340spr_tcp_state (unsigned state)
341{
342  char *ret="UNKNOWN";
343
344  if      ( 0 == state) {ret = "CLOSED";}
345  else if ( 1 == state) {ret = "LISTEN";}
346  else if ( 2 == state) {ret = "SYN_SENT";}
347  else if ( 3 == state) {ret = "SYN_RCVD";}
348  else if ( 4 == state) {ret = "ESTABLISHED";}
349  else if ( 5 == state) {ret = "CLOSE_WAIT";}
350  else if ( 6 == state) {ret = "FIN_WAIT_1";}
351  else if ( 7 == state) {ret = "CLOSING";}
352  else if ( 8 == state) {ret = "LAST_ACK";}
353  else if ( 9 == state) {ret = "FIN_WAIT_2";}
354  else if (10 == state) {ret = "TIME_WAIT";}
355  else if (11 == state) {ret = "ESTABLISHED_RX";}
356  else if (12 == state) {ret = "ESTABLISHED_TX";}
357  else if (13 == state) {ret = "SYN_PEND";}
358  else if (14 == state) {ret = "ESC_1_STATE";}
359  else if (15 == state) {ret = "ESC_2_STATE";}
360
361  return ret;
362}
363
364char *
365spr_cctrl_sel(unsigned sel0,unsigned sel1)
366{
367  unsigned sel=(sel1<<1) | sel0;
368  char *ret="UNKNOWN";
369
370  if      ( 0 == sel) {ret = "Reno";}
371  else if ( 1 == sel) {ret = "Tahoe";}
372  else if ( 2 == sel) {ret = "NewReno";}
373  else if ( 3 == sel) {ret = "HighSpeed";}
374
375  return ret;
376}
377
378
379char *
380spr_ulp_type(unsigned ulp_type)
381{
382  char *ret="UNKNOWN";
383
384  /*The tp.h PM_MODE_XXX call 1 DDP and 5 IANDP, but external
385   * documentation (tcb.h" calls 5 ddp, and doesn't mention 1 or 3.
386   */
387
388  if      ( PM_MODE_PASS  == ulp_type) {ret = "TOE";}
389  else if ( PM_MODE_DDP   == ulp_type) {ret = "DDP";}
390  else if ( PM_MODE_ISCSI == ulp_type) {ret = "ISCSI";}
391  else if ( PM_MODE_IWARP == ulp_type) {ret = "IWARP";}
392  else if ( PM_MODE_RDDP  == ulp_type) {ret = "RDMA";}
393  else if ( PM_MODE_IANDP == ulp_type) {ret = "IANDP_DDP";}
394  else if ( PM_MODE_FCOE  == ulp_type) {ret = "FCoE";}
395  else if ( PM_MODE_USER  == ulp_type) {ret = "USER";}
396  else if ( PM_MODE_TLS   == ulp_type) {ret = "TLS";}
397  else if ( PM_MODE_DTLS  == ulp_type) {ret = "DTLS";}
398
399  return ret;
400}
401
402char *
403spr_ip_version(unsigned ip_version)
404{
405  char *ret="UNKNOWN";
406
407  if      ( 0 == ip_version) {ret = "IPv4";}
408  else if ( 1 == ip_version) {ret = "IPv6";}
409
410  return ret;
411}
412
413
414
415/***:-----------------------------------------------------------------------
416 ***: display_tcb()
417 ***:-----------------------------------------------------------------------
418 */
419
420void
421display_tcb_compressed(_TCBVAR *tvp,int aux)
422{
423
424  if (g_tN==4) {
425    t4_display_tcb_aux_0(tvp,aux);
426    if      (1==aux) t4_display_tcb_aux_1(tvp,aux);
427    else if (2==aux) t4_display_tcb_aux_2(tvp,aux);
428    else if (3==aux) t4_display_tcb_aux_3(tvp,aux);
429
430  } else if (g_tN==5) {
431    t5_display_tcb_aux_0(tvp,aux);
432    if      (1==aux) t5_display_tcb_aux_1(tvp,aux);
433    else if (2==aux) t5_display_tcb_aux_2(tvp,aux);
434    else if (3==aux) t5_display_tcb_aux_3(tvp,aux);
435  } else if (g_tN==6) {
436    t6_display_tcb_aux_0(tvp,aux);
437    if      (1==aux) t6_display_tcb_aux_1(tvp,aux);
438    else if (2==aux) t6_display_tcb_aux_2(tvp,aux);
439    else if (3==aux) t6_display_tcb_aux_3(tvp,aux);
440    else if (4==aux) t6_display_tcb_aux_4(tvp,aux);
441  }
442}
443
444
445
446
447/***:-----------------------------------------------------------------------
448 ***: parse_n_decode_tcb
449 ***:-----------------------------------------------------------------------
450 */
451
452
453unsigned
454parse_tcb( _TCBVAR *base_tvp, unsigned char *buf)
455{   /* parse the TCB */
456  _TCBVAR *tvp=base_tvp;
457  unsigned ulp_type;
458  int aux=1;  /* assume TOE or iSCSI */
459  unsigned tx_max=0, rcv_nxt=0, rx_frag0_start_idx_raw=0;
460  int got_tx_max=0, got_rcv_nxt=0, got_rx_frag0_start_idx_raw=0;
461
462
463  /* parse the TCB */
464  while (tvp->name!=NULL) {
465    get_tcb_field(tvp,buf);
466    if (!got_tx_max && tcb_strmatch_nc("tx_max",tvp->name)) {
467      tx_max=tvp->val;
468      got_tx_max=1;
469    }
470    if (!got_rcv_nxt && tcb_strmatch_nc("rcv_nxt",tvp->name)) {
471      rcv_nxt=tvp->val;
472      got_rcv_nxt=1;
473    }
474    if (!got_rx_frag0_start_idx_raw &&
475	tcb_strmatch_nc("rx_frag0_start_idx_raw",tvp->name)) {
476      rx_frag0_start_idx_raw=tvp->val;
477      got_rx_frag0_start_idx_raw=1;
478    }
479    tvp+=1;
480  }
481
482  tvp=base_tvp;
483  ulp_type=tvp->val;  /* ULP type is always first variable in TCB */
484  if (PM_MODE_IANDP==ulp_type || PM_MODE_FCOE==ulp_type) aux=3;
485  else if (PM_MODE_RDDP==ulp_type) aux=2;
486  else if (6==g_tN && (PM_MODE_TLS==ulp_type || PM_MODE_DTLS==ulp_type)) aux=4;
487  else aux=1;
488
489  assert(got_tx_max && got_rcv_nxt && got_rx_frag0_start_idx_raw);
490
491  /* decompress the compressed values */
492  tvp=base_tvp;
493  while (tvp->name!=NULL) {
494    decompress_val(tvp,ulp_type,tx_max,rcv_nxt,rx_frag0_start_idx_raw);
495    tvp+=1;
496  }
497
498  return aux;
499}
500
501
502
503void
504parse_scb( _TCBVAR *base_tvp, unsigned char *buf)
505{   /* parse the SCB */
506  _TCBVAR *tvp=base_tvp;
507
508  while (tvp->name!=NULL) {
509    if (tcb_strmatch_nc("scb_slush",tvp->name)) {
510      /* the scb_slush field is all of remaining memory */
511      tvp->rawval=0;
512      tvp->val=0;
513    } else {
514      get_tcb_field(tvp,buf);
515    }
516    tvp+=1;
517  }
518}
519
520
521void
522parse_fcb( _TCBVAR *base_tvp, unsigned char *buf)
523{   /* parse the FCB */
524  _TCBVAR *tvp=base_tvp;
525
526  while (tvp->name!=NULL) {
527    get_tcb_field(tvp,buf);
528    tvp+=1;
529  }
530}
531
532
533void
534display_list_tcb(_TCBVAR *base_tvp,int aux)
535{
536  _TCBVAR *tvp=base_tvp;
537  while (tvp->name!=NULL) {
538    if (tvp->aux==0 || tvp->aux==aux) {
539      if (tvp->hi-tvp->lo+1<=32) {
540	printf("  %4d:%4d %31s: %10u (0x%1x)",tvp->lo,tvp->hi,tvp->name,
541	       (unsigned) tvp->rawval,(unsigned) tvp->rawval);
542	if (COMP_TX_MAX==tvp->comp || COMP_RCV_NXT==tvp->comp)
543	  printf("  -> %1u (0x%x)", tvp->val,tvp->val);
544      } else {
545	printf("  %4d:%4d %31s: 0x%1llx",tvp->lo,tvp->hi,tvp->name,
546	       tvp->rawval);
547      }
548      printf("\n");
549    }
550    tvp+=1;
551  }
552}
553
554void
555display_tcb(_TCBVAR *tvp,unsigned char *buf,int aux)
556{
557  if (g_prntstyl==PRNTSTYL_VERBOSE ||
558      g_prntstyl==PRNTSTYL_RAW) {
559    tcb_hexdump(0,buf,128);
560    printf("\n");
561  }
562
563  if (g_prntstyl==PRNTSTYL_VERBOSE ||
564      g_prntstyl==PRNTSTYL_LIST) {
565    display_list_tcb(tvp,aux);
566  }
567
568  if (g_prntstyl==PRNTSTYL_VERBOSE ||
569      g_prntstyl==PRNTSTYL_COMP) {
570    display_tcb_compressed(tvp,aux);
571  }
572
573}
574
575void
576parse_n_display_tcb(unsigned char *buf)
577{
578  _TCBVAR *tvp=g_tcb_info;
579  int aux;
580
581  aux=parse_tcb(tvp,buf);
582  display_tcb(tvp,buf,aux);
583}
584
585void
586parse_n_display_scb(unsigned char *buf)
587{
588  _TCBVAR *tvp=g_scb_info;
589
590  parse_scb(tvp,buf);
591  if (g_prntstyl==PRNTSTYL_VERBOSE ||
592      g_prntstyl==PRNTSTYL_RAW) {
593    tcb_hexdump(0,buf,128);
594    printf("\n");
595  }
596  if (g_prntstyl==PRNTSTYL_VERBOSE ||
597      g_prntstyl==PRNTSTYL_LIST ||
598      g_prntstyl==PRNTSTYL_COMP) {
599    display_list_tcb(tvp,0);
600  }
601}
602
603void
604parse_n_display_fcb(unsigned char *buf)
605{
606  _TCBVAR *tvp=g_fcb_info;
607
608  parse_fcb(tvp,buf);
609  if (g_prntstyl==PRNTSTYL_VERBOSE ||
610      g_prntstyl==PRNTSTYL_RAW) {
611    tcb_hexdump(0,buf,128);
612    printf("\n");
613  }
614
615  if (g_prntstyl==PRNTSTYL_VERBOSE ||
616      g_prntstyl==PRNTSTYL_LIST ||
617      g_prntstyl==PRNTSTYL_COMP) {
618    display_list_tcb(tvp,0);
619  }
620}
621
622void
623parse_n_display_xcb(unsigned char *buf)
624{
625  if      (g_got_scb) parse_n_display_scb(buf);
626  else if (g_got_fcb) parse_n_display_fcb(buf);
627  else                parse_n_display_tcb(buf);
628}
629
630/***:-----------------------------------------------------------------------
631 ***: swizzle_tcb
632 ***:-----------------------------------------------------------------------
633 */
634
635void
636swizzle_tcb(unsigned char *buf)
637{
638  int i,j,k;
639
640  for (i=0, j=128-16 ; i<j ; i+=16, j-=16) {
641    unsigned char temp;
642    for (k=0; k<16; ++k) {
643      temp=buf[i+k];
644      buf[i+k]=buf[j+k];
645      buf[j+k]=temp;
646    }
647  }
648}
649
650
651/***:-----------------------------------------------------------------------
652 ***: END OF WINDOWS FUNCTIONS
653 ***:-----------------------------------------------------------------------
654 */
655
656void set_tidtype(unsigned int tidtype)
657{
658    if (tidtype == TIDTYPE_SCB)
659    {
660        g_got_scb = 1;
661    }
662    else if (tidtype == TIDTYPE_FCB)
663    {
664        g_got_fcb = 1;
665    }
666    else
667    {
668        g_got_scb = 0;
669        g_got_fcb = 0;
670    }
671
672}
673
674void
675set_tcb_info(unsigned int tidtype, unsigned int cardtype)
676{
677    set_tidtype(tidtype);
678
679    g_tN = cardtype;
680    if (4 == g_tN) {
681        g_tcb_info = g_tcb_info4;
682        g_scb_info = g_scb_info4;
683        g_fcb_info = g_fcb_info4;
684    }
685    else if (5 == g_tN) {
686        g_tcb_info = g_tcb_info5;
687        g_scb_info = g_scb_info5;
688        g_fcb_info = g_fcb_info5;
689    }
690    else if (6 == g_tN) {
691        g_tcb_info = g_tcb_info6;
692        g_scb_info = g_scb_info6;
693        g_fcb_info = g_fcb_info6;
694    }
695}
696
697void
698set_print_style(unsigned int prntstyl)
699{
700  g_prntstyl=prntstyl;
701}
702