diff options
Diffstat (limited to 'usr.sbin/cxgbetool/tcb_common.c')
| -rw-r--r-- | usr.sbin/cxgbetool/tcb_common.c | 721 |
1 files changed, 721 insertions, 0 deletions
diff --git a/usr.sbin/cxgbetool/tcb_common.c b/usr.sbin/cxgbetool/tcb_common.c new file mode 100644 index 000000000000..803599696423 --- /dev/null +++ b/usr.sbin/cxgbetool/tcb_common.c @@ -0,0 +1,721 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2018 Chelsio Communications, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +#include "tcb_common.h" + +/***:----------------------------------------------------------------------- + ***: externals + ***:----------------------------------------------------------------------- + */ + +extern _TCBVAR g_tcb_info4[]; +extern _TCBVAR g_scb_info4[]; +extern _TCBVAR g_fcb_info4[]; +extern void t4_display_tcb_aux_0(_TCBVAR *tvp,int aux); +extern void t4_display_tcb_aux_1(_TCBVAR *tvp,int aux); +extern void t4_display_tcb_aux_2(_TCBVAR *tvp,int aux); +extern void t4_display_tcb_aux_3(_TCBVAR *tvp,int aux); + +extern _TCBVAR g_tcb_info5[]; +extern _TCBVAR g_scb_info5[]; +extern _TCBVAR g_fcb_info5[]; +extern void t5_display_tcb_aux_0(_TCBVAR *tvp,int aux); +extern void t5_display_tcb_aux_1(_TCBVAR *tvp,int aux); +extern void t5_display_tcb_aux_2(_TCBVAR *tvp,int aux); +extern void t5_display_tcb_aux_3(_TCBVAR *tvp,int aux); + +extern _TCBVAR g_tcb_info6[]; +extern _TCBVAR g_scb_info6[]; +extern _TCBVAR g_fcb_info6[]; +extern void t6_display_tcb_aux_0(_TCBVAR *tvp,int aux); +extern void t6_display_tcb_aux_1(_TCBVAR *tvp,int aux); +extern void t6_display_tcb_aux_2(_TCBVAR *tvp,int aux); +extern void t6_display_tcb_aux_3(_TCBVAR *tvp,int aux); +extern void t6_display_tcb_aux_4(_TCBVAR *tvp,int aux); + +extern _TCBVAR g_tcb_info7[]; +extern _TCBVAR g_scb_info7[]; +extern _TCBVAR g_fcb_info7[]; +extern void t7_display_tcb_aux_0(_TCBVAR *tvp,int aux); +extern void t7_display_tcb_aux_1(_TCBVAR *tvp,int aux); +extern void t7_display_tcb_aux_2(_TCBVAR *tvp,int aux); +extern void t7_display_tcb_aux_3(_TCBVAR *tvp,int aux); +extern void t7_display_tcb_aux_4(_TCBVAR *tvp,int aux); + +/***:----------------------------------------------------------------------- + ***: globals + ***:----------------------------------------------------------------------- + */ + +_TCBVAR *g_tcb_info=g_tcb_info5; +_TCBVAR *g_scb_info=g_scb_info5; +_TCBVAR *g_fcb_info=g_fcb_info5; +static int g_tN=0; + +static int g_prntstyl=PRNTSTYL_COMP; + +static int g_got_scb=0; +static int g_got_fcb=0; + + +/***:----------------------------------------------------------------------- +***: error exit functions +***:----------------------------------------------------------------------- +*/ + +/**: err_exit functions +*: ------------------ +*/ + +void tcb_prflush(void) +{ + fflush(stdout); + fflush(stderr); +} + + +void tcb_code_err_exit(char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + printf("Coding Error in: "); + vprintf(fmt, args); + printf("\n"); + tcb_prflush(); + va_end(args); + exit(1); +} + +/***:----------------------------------------------------------------------- +***: tcb_hexdump functions +***:----------------------------------------------------------------------- +*/ + +void +tcb_hexdump(unsigned base, unsigned char *buf, unsigned int size) +{ + unsigned offset; + + for (offset = 0; offset < size; ++offset) { + if (!(offset % 16)) printf("\n0x%4.4x: ", base + offset); + else if (!(offset % 8)) printf(" "); + printf("%2.2x ", (unsigned char)buf[offset]); + } +} + +int tcb_strmatch_nc(char *cs, char *ct) { + while (*cs) + if (tolower(*cs++) != tolower(*ct++)) return (FALSE); + return (!(*ct)); /*return TRUE if *ct NULL at same time as *cs==NULL*/ +} + + +/*: ------------------------------------------------------------------------- +string functions +tcb_strmatch_nc: Similar to exact match, but case insensitive. +*/ + + +int +tcb_strncmp_nc(char *cs, char *ct, int n) +{ + /*case insensitive version of the standard strncmp() function */ + int i = 0; + int ret; + + + ret = 0; + for (i = 0; i < n && 0 == ret && !(EOS == *cs && EOS == *ct); ++i) { + /* this is weird, but it matched GCC linux when strings don't + * have any upper case characters. + */ + ret = tolower(*cs++) - tolower(*ct++); + } + return ret; +} + +int +tcb_startswith_nc(char *cs, char *ct) +{ /* return true if cs start with ct */ + return (0 == tcb_strncmp_nc(cs, ct, (int)strlen(ct))); +} + + + + +/***:----------------------------------------------------------------------- + ***: START OF WINDOWS FUNCTIONS + ***:----------------------------------------------------------------------- + */ + + +/***:----------------------------------------------------------------------- + ***: print utilities + ***:----------------------------------------------------------------------- + */ + +static int g_PR_indent=1; + +void PR(char *fmt, ...) +{ + int fmt_len; + va_list args; + va_start(args,fmt); + + if (g_PR_indent) printf(" "); + g_PR_indent=0; + fmt_len=(int) strlen(fmt); + if (fmt_len>0 && fmt[fmt_len-1]=='\n') g_PR_indent=1; + + vprintf(fmt,args); + tcb_prflush(); + va_end(args); +} + + +/***:----------------------------------------------------------------------- + ***: val() + ***:----------------------------------------------------------------------- + */ + +_TCBVAR * +lu_tcbvar(char *name) +{ + _TCBVAR *tvp=g_tcb_info; + + while (tvp->name!=NULL) { + if (tcb_strmatch_nc(name,tvp->name)) return tvp; + else if (tcb_strmatch_nc(name,tvp->aka )) return tvp; + tvp+=1; + } + tcb_code_err_exit("lu_tcbvar: bad name %s\n",name); + return NULL; +} + +unsigned +val(char *name) +{ + _TCBVAR *tvp; + + tvp=lu_tcbvar(name); + return tvp->val; +} + +ui64 +val64(char *name) +{ + _TCBVAR *tvp; + + tvp=lu_tcbvar(name); + return tvp->rawval; +} + + + +/***:----------------------------------------------------------------------- + ***: get_tcb_bits + ***:----------------------------------------------------------------------- + */ + + +static int +get_tcb_bit(unsigned char *A, int bit) +{ + int ret=0; + int ix,shift; + + ix = 127 - (bit>>3); + shift=bit&0x7; + /* prdbg(" ix: %u, shift=%u\n",ix,shift); */ + ret=(A[ix] >> shift) & 1; + return ret; +} + +static ui64 +get_tcb_bits (unsigned char *A, int hi, int lo) +{ + ui64 ret=0; + + if (lo>hi) { + int temp=lo; + lo=hi; + hi=temp; + } + + while (hi>=lo) { + ret = (ret<<1) | get_tcb_bit(A,hi); + --hi; + } + + return ret; +} + + +void +decompress_val(_TCBVAR *tvp,unsigned ulp_type,unsigned tx_max, + unsigned rcv_nxt,unsigned rx_frag0_start_idx_raw) +{ + unsigned rawval=(unsigned) tvp->rawval; + + switch(tvp->comp) { + case COMP_NONE: tvp->val=rawval; break; + case COMP_ULP: tvp->val=rawval; break; + case COMP_TX_MAX: + tvp->val=(tx_max - rawval) & 0xFFFFFFFF; + break; + case COMP_RCV_NXT: + if (tcb_startswith_nc(tvp->name,"rx_frag")) { + unsigned fragx=0; + if (!tcb_strmatch_nc(tvp->name,"rx_frag0_start_idx_raw")) + fragx=rawval; + tvp->val=(rcv_nxt+rx_frag0_start_idx_raw+fragx) & 0xFFFFFFFF; + } else { + tvp->val=(rcv_nxt - rawval) & 0xFFFFFFFF; + } + break; + case COMP_PTR: tvp->val=rawval; break; + case COMP_LEN: + { + tvp->val=rawval; + if (PM_MODE_RDDP==ulp_type || PM_MODE_DDP==ulp_type || + PM_MODE_IANDP==ulp_type) { + /* TP does this internally. Not sure if I should show the + * unaltered value or the raw value. For now I + * will display the raw value. For now I've added the code + * mainly to stop windows compiler from warning about ulp_type + * being an unreferenced parameter. + */ + tvp->val=0; + tvp->val=rawval; /* comment this out to display altered value */ + } + } + break; + default: + tcb_code_err_exit("decompress_val, bad switch: %d",tvp->comp); + break; + } + + + +} + + +void +get_tcb_field(_TCBVAR *tvp,unsigned char *buf) +{ + assert(tvp->hi-tvp->lo+1<=64); + assert(tvp->hi>=tvp->lo); + + tvp->rawval=get_tcb_bits(buf,tvp->lo,tvp->hi); + /* assume no compression and 32-bit value for now */ + tvp->val=(unsigned) (tvp->rawval & 0xFFFFFFFF); + + +} + + +/***:----------------------------------------------------------------------- + ***: spr_* functions + ***:----------------------------------------------------------------------- + */ + +char * +spr_tcp_state (unsigned state) +{ + char *ret="UNKNOWN"; + + if ( 0 == state) {ret = "CLOSED";} + else if ( 1 == state) {ret = "LISTEN";} + else if ( 2 == state) {ret = "SYN_SENT";} + else if ( 3 == state) {ret = "SYN_RCVD";} + else if ( 4 == state) {ret = "ESTABLISHED";} + else if ( 5 == state) {ret = "CLOSE_WAIT";} + else if ( 6 == state) {ret = "FIN_WAIT_1";} + else if ( 7 == state) {ret = "CLOSING";} + else if ( 8 == state) {ret = "LAST_ACK";} + else if ( 9 == state) {ret = "FIN_WAIT_2";} + else if (10 == state) {ret = "TIME_WAIT";} + else if (11 == state) {ret = "ESTABLISHED_RX";} + else if (12 == state) {ret = "ESTABLISHED_TX";} + else if (13 == state) {ret = "SYN_PEND";} + else if (14 == state) {ret = "ESC_1_STATE";} + else if (15 == state) {ret = "ESC_2_STATE";} + + return ret; +} + +char * +spr_cctrl_sel(unsigned sel0,unsigned sel1) +{ + unsigned sel=(sel1<<1) | sel0; + char *ret="UNKNOWN"; + + if ( 0 == sel) {ret = "Reno";} + else if ( 1 == sel) {ret = "Tahoe";} + else if ( 2 == sel) {ret = "NewReno";} + else if ( 3 == sel) {ret = "HighSpeed";} + + return ret; +} + + +char * +spr_ulp_type(unsigned ulp_type) +{ + char *ret="UNKNOWN"; + + /*The tp.h PM_MODE_XXX call 1 DDP and 5 IANDP, but external + * documentation (tcb.h" calls 5 ddp, and doesn't mention 1 or 3. + */ + + if ( PM_MODE_PASS == ulp_type) {ret = "TOE";} + else if ( PM_MODE_DDP == ulp_type) {ret = "DDP";} + else if ( PM_MODE_ISCSI == ulp_type) {ret = "ISCSI";} + else if ( PM_MODE_IWARP == ulp_type) {ret = "IWARP";} + else if ( PM_MODE_RDDP == ulp_type) {ret = "RDMA";} + else if ( PM_MODE_IANDP == ulp_type) {ret = "IANDP_DDP";} + else if ( PM_MODE_FCOE == ulp_type) {ret = "FCoE";} + else if ( PM_MODE_USER == ulp_type) {ret = "USER";} + else if ( PM_MODE_TLS == ulp_type) {ret = "TLS";} + else if ( PM_MODE_DTLS == ulp_type) {ret = "DTLS";} + + return ret; +} + +char * +spr_ip_version(unsigned ip_version) +{ + char *ret="UNKNOWN"; + + if ( 0 == ip_version) {ret = "IPv4";} + else if ( 1 == ip_version) {ret = "IPv6";} + + return ret; +} + + + +/***:----------------------------------------------------------------------- + ***: display_tcb() + ***:----------------------------------------------------------------------- + */ + +void +display_tcb_compressed(_TCBVAR *tvp,int aux) +{ + + if (g_tN==4) { + t4_display_tcb_aux_0(tvp,aux); + if (1==aux) t4_display_tcb_aux_1(tvp,aux); + else if (2==aux) t4_display_tcb_aux_2(tvp,aux); + else if (3==aux) t4_display_tcb_aux_3(tvp,aux); + + } else if (g_tN==5) { + t5_display_tcb_aux_0(tvp,aux); + if (1==aux) t5_display_tcb_aux_1(tvp,aux); + else if (2==aux) t5_display_tcb_aux_2(tvp,aux); + else if (3==aux) t5_display_tcb_aux_3(tvp,aux); + } else if (g_tN==6) { + t6_display_tcb_aux_0(tvp,aux); + if (1==aux) t6_display_tcb_aux_1(tvp,aux); + else if (2==aux) t6_display_tcb_aux_2(tvp,aux); + else if (3==aux) t6_display_tcb_aux_3(tvp,aux); + else if (4==aux) t6_display_tcb_aux_4(tvp,aux); + } else if (g_tN==7) { + t7_display_tcb_aux_0(tvp,aux); + if (1==aux) t7_display_tcb_aux_1(tvp,aux); + else if (2==aux) t7_display_tcb_aux_2(tvp,aux); + else if (3==aux) t7_display_tcb_aux_3(tvp,aux); + else if (4==aux) t7_display_tcb_aux_4(tvp,aux); + } +} + + + + +/***:----------------------------------------------------------------------- + ***: parse_n_decode_tcb + ***:----------------------------------------------------------------------- + */ + + +unsigned +parse_tcb( _TCBVAR *base_tvp, unsigned char *buf) +{ /* parse the TCB */ + _TCBVAR *tvp=base_tvp; + unsigned ulp_type; + int aux=1; /* assume TOE or iSCSI */ + unsigned tx_max=0, rcv_nxt=0, rx_frag0_start_idx_raw=0; + int got_tx_max=0, got_rcv_nxt=0, got_rx_frag0_start_idx_raw=0; + + + /* parse the TCB */ + while (tvp->name!=NULL) { + get_tcb_field(tvp,buf); + if (!got_tx_max && tcb_strmatch_nc("tx_max",tvp->name)) { + tx_max=tvp->val; + got_tx_max=1; + } + if (!got_rcv_nxt && tcb_strmatch_nc("rcv_nxt",tvp->name)) { + rcv_nxt=tvp->val; + got_rcv_nxt=1; + } + if (!got_rx_frag0_start_idx_raw && + tcb_strmatch_nc("rx_frag0_start_idx_raw",tvp->name)) { + rx_frag0_start_idx_raw=tvp->val; + got_rx_frag0_start_idx_raw=1; + } + tvp+=1; + } + + tvp=base_tvp; + ulp_type=tvp->val; /* ULP type is always first variable in TCB */ + if (PM_MODE_IANDP==ulp_type || PM_MODE_FCOE==ulp_type) aux=3; + else if (PM_MODE_RDDP==ulp_type) aux=2; + else if (6==g_tN && (PM_MODE_TLS==ulp_type || PM_MODE_DTLS==ulp_type)) aux=4; + else aux=1; + + assert(got_tx_max && got_rcv_nxt && got_rx_frag0_start_idx_raw); + + /* decompress the compressed values */ + tvp=base_tvp; + while (tvp->name!=NULL) { + decompress_val(tvp,ulp_type,tx_max,rcv_nxt,rx_frag0_start_idx_raw); + tvp+=1; + } + + return aux; +} + + + +void +parse_scb( _TCBVAR *base_tvp, unsigned char *buf) +{ /* parse the SCB */ + _TCBVAR *tvp=base_tvp; + + while (tvp->name!=NULL) { + if (tcb_strmatch_nc("scb_slush",tvp->name)) { + /* the scb_slush field is all of remaining memory */ + tvp->rawval=0; + tvp->val=0; + } else { + get_tcb_field(tvp,buf); + } + tvp+=1; + } +} + + +void +parse_fcb( _TCBVAR *base_tvp, unsigned char *buf) +{ /* parse the FCB */ + _TCBVAR *tvp=base_tvp; + + while (tvp->name!=NULL) { + get_tcb_field(tvp,buf); + tvp+=1; + } +} + + +void +display_list_tcb(_TCBVAR *base_tvp,int aux) +{ + _TCBVAR *tvp=base_tvp; + while (tvp->name!=NULL) { + if (tvp->aux==0 || tvp->aux==aux) { + if (tvp->hi-tvp->lo+1<=32) { + printf(" %4d:%4d %31s: %10u (0x%1x)",tvp->lo,tvp->hi,tvp->name, + (unsigned) tvp->rawval,(unsigned) tvp->rawval); + if (COMP_TX_MAX==tvp->comp || COMP_RCV_NXT==tvp->comp) + printf(" -> %1u (0x%x)", tvp->val,tvp->val); + } else { + printf(" %4d:%4d %31s: 0x%1llx",tvp->lo,tvp->hi,tvp->name, + tvp->rawval); + } + printf("\n"); + } + tvp+=1; + } +} + +void +display_tcb(_TCBVAR *tvp,unsigned char *buf,int aux) +{ + if (g_prntstyl==PRNTSTYL_VERBOSE || + g_prntstyl==PRNTSTYL_RAW) { + tcb_hexdump(0,buf,128); + printf("\n"); + } + + if (g_prntstyl==PRNTSTYL_VERBOSE || + g_prntstyl==PRNTSTYL_LIST) { + display_list_tcb(tvp,aux); + } + + if (g_prntstyl==PRNTSTYL_VERBOSE || + g_prntstyl==PRNTSTYL_COMP) { + display_tcb_compressed(tvp,aux); + } + +} + +void +parse_n_display_tcb(unsigned char *buf) +{ + _TCBVAR *tvp=g_tcb_info; + int aux; + + aux=parse_tcb(tvp,buf); + display_tcb(tvp,buf,aux); +} + +void +parse_n_display_scb(unsigned char *buf) +{ + _TCBVAR *tvp=g_scb_info; + + parse_scb(tvp,buf); + if (g_prntstyl==PRNTSTYL_VERBOSE || + g_prntstyl==PRNTSTYL_RAW) { + tcb_hexdump(0,buf,128); + printf("\n"); + } + if (g_prntstyl==PRNTSTYL_VERBOSE || + g_prntstyl==PRNTSTYL_LIST || + g_prntstyl==PRNTSTYL_COMP) { + display_list_tcb(tvp,0); + } +} + +void +parse_n_display_fcb(unsigned char *buf) +{ + _TCBVAR *tvp=g_fcb_info; + + parse_fcb(tvp,buf); + if (g_prntstyl==PRNTSTYL_VERBOSE || + g_prntstyl==PRNTSTYL_RAW) { + tcb_hexdump(0,buf,128); + printf("\n"); + } + + if (g_prntstyl==PRNTSTYL_VERBOSE || + g_prntstyl==PRNTSTYL_LIST || + g_prntstyl==PRNTSTYL_COMP) { + display_list_tcb(tvp,0); + } +} + +void +parse_n_display_xcb(unsigned char *buf) +{ + if (g_got_scb) parse_n_display_scb(buf); + else if (g_got_fcb) parse_n_display_fcb(buf); + else parse_n_display_tcb(buf); +} + +/***:----------------------------------------------------------------------- + ***: swizzle_tcb + ***:----------------------------------------------------------------------- + */ + +void +swizzle_tcb(unsigned char *buf) +{ + int i,j,k; + + for (i=0, j=128-16 ; i<j ; i+=16, j-=16) { + unsigned char temp; + for (k=0; k<16; ++k) { + temp=buf[i+k]; + buf[i+k]=buf[j+k]; + buf[j+k]=temp; + } + } +} + + +/***:----------------------------------------------------------------------- + ***: END OF WINDOWS FUNCTIONS + ***:----------------------------------------------------------------------- + */ + +void set_tidtype(unsigned int tidtype) +{ + if (tidtype == TIDTYPE_SCB) + { + g_got_scb = 1; + } + else if (tidtype == TIDTYPE_FCB) + { + g_got_fcb = 1; + } + else + { + g_got_scb = 0; + g_got_fcb = 0; + } + +} + +void +set_tcb_info(unsigned int tidtype, unsigned int cardtype) +{ + set_tidtype(tidtype); + + g_tN = cardtype; + if (4 == g_tN) { + g_tcb_info = g_tcb_info4; + g_scb_info = g_scb_info4; + g_fcb_info = g_fcb_info4; + } + else if (5 == g_tN) { + g_tcb_info = g_tcb_info5; + g_scb_info = g_scb_info5; + g_fcb_info = g_fcb_info5; + } + else if (6 == g_tN) { + g_tcb_info = g_tcb_info6; + g_scb_info = g_scb_info6; + g_fcb_info = g_fcb_info6; + } + else if (7 == g_tN) { + g_tcb_info = g_tcb_info7; + g_scb_info = g_scb_info7; + g_fcb_info = g_fcb_info7; + } +} + +void +set_print_style(unsigned int prntstyl) +{ + g_prntstyl=prntstyl; +} |
