TCP SNMP counters(netstat -st 输出解析)

◎目录


基于linux2.6,整理自:roveryu.blog.chinaunix.netnetstat -st输出解析(二)

计数器分类

类别涉及counters
常量RtoAlgorithm、RtoMin、RtoMax、MaxConn
建连统计ActiveOpens、PassiveOpens、AttemptFails、CurrEstab、EstabResets
数据包统计InSegs、OutSegs、RetransSegs、InErrs、OutRsts、InCsumErrors、EmbryonicRsts
syncookies功能SyncookiesSent、SyncookiesRecv、SyncookiesFailed
TIME_WAIT回收TW、TWRecycled、TWKilled、TCPTimeWaitOverflow
RTO次数TCPTimeouts、TCPSpuriousRTOs、TCPLossProbes、TCPLossProbeRecovery、
TCPRenoRecoveryFail、TCPSackRecoveryFail、
TCPRenoFailures、TCPSackFailures、
TCPLossFailures
Retrans数量TCPFastRetrans、TCPForwardRetrans、
TCPSlowStartRetrans、TCPLostRetransmit、
TCPRetransFail
FastOpenTCPFastOpenActive、TCPFastOpenPassive、
TCPFastOpenPassiveFail、TCPFastOpenListenOverflow、
TCPFastOpenCookieReqd
MD5TCPMD5NotFound、TCPMD5Unexpected
DelayedACKDelayedACKs、DelayedACKLocked、DelayedACKLost、
TCPSchedulerFailed
DSACKTCPDSACKOldSent、TCPDSACKOfoSent、
TCPDSACKRecv、TCPDSACKOfoRecv、
TCPDSACKIgnoredOld、TCPDSACKIgnoredNoUndo
ReorderTCPFACKReorder、TCPSACKReorder、
TCPRenoReorder、TCPTSReorder
RecoveryTCPRenoRecovery、TCPSackRecovery、
TCPRenoRecoveryFail、TCPSackRecoveryFail
AbortTCPAbortOnData、TCPAbortOnClose、
TCPAbortOnMemory、TCPAbortOnTimeout、
TCPAbortOnLingerTCPAbortFailed

|reset相关 | |
|内存prune | PruneCalled、RcvPruned、OfoPruned、
TCPMemoryPressures |
|PAWS相关 | PAWSPassive、PAWSActive、PAWSEstab |
|Listen相关 | ListenOverflows、ListenDrops |
|undo相关 | TCPFullUndo、TCPPartialUndo、
TCPDSACKUndo、TCPLossUndo |
|快速路径与慢速路径 | TCPHPHits、TCPHPHitsToUser、
TCPPureAcks、TCPHPAcks |



TCP Basic

类别 名称 描述
TcpActiveOpenstcp_connect(),发送 SYN 时,加1
TcpPassiveOpenstcp_create_openreq_child(), 被动三路握手完成,加1
TcpAttemptFailstcp_done(): 如果在 SYN_SENT/SYN_RECV 状态下结束一个连接,加1tcp_check_req(): 被动三路握手最后一个阶段中的输入包中如果有 RST|SYN 标志,加1
TcpCurrEstabtcp_set_state(),根据 ESTABLISHED 是新/旧状态,分别加减一。
TcpEstabResetstcp_set_state(),新状态为 TCP_CLOSE,如果旧状态是 ESTABLISHED/TCP_CLOSE_WAIT 就加1
TcpListenOverflowstcp_v4_syn_recv_sock():三路握手最后一步完全之后,Accept queue 队列超过上限时加1
TcpListenDropstcp_v4_syn_recv_sock():任何原因,包括 Accept queue 超限,创建新连接,继承端口失败等,加1
TcpMaxConn0
TcpInSegstcp_v4_rcv(), 收到一个 skb,加1
TcpInErrstcp_rcv_established()->tcp_validate_incoming():如果有 SYN 且 seq >= rcv_nxt,加1以下函数内,如果 checksum 错误或者包长度小于 TCP header,加1:tcp_v4_do_rcv()tcp_rcv_established()tcp_v4_rcv()
TcpOutSegstcp_v4_send_reset(), tcp_v4_send_ack(),加1tcp_transmit_skb(), tcp_make_synack(),加 tcp_skb_pcount(skb)(见 TCP_COOKIE_TRANSACTIONS)
TcpOutRststcp_v4_send_reset(), tcp_send_active_reset() 加1


TCP Loss & Retrans


类别 名称 描述
TcpTCPTimeouts在 RTO timer 中,从 CWR/Open 状态下第一次超时的次数,其余状态不计入这个计数器。SYN-ACK 的超时次数。
TcpRtoAlgorithm1,tcp_mib_init() 初始化
TcpRtoMax120000,tcp_mib_init() 初始化:TCP_RTO_MAX1000/HZ,TCP_RTO_MAX=120HZ
TcpRtoMin200,tcp_mib_init() 初始化:TCP_RTO_MIN*1000/HZ,TCP_RTO_MIN=HZ/5


以下计数器,统计的是调用 tcp_retransmit_skb() 的次数,由于 sysctl_tcp_retrans_collapse/TSO 的原因,一次 tcp_transmit_skb() 调用可能发送多个 segs


类别 名称 描述
TcpRetransSegs重传次数,包括 RTO timer 和常规重传,即 tcp_retransmit_skb() 中调用 tcp_transmit_skb(),成功返回即+1。
TcpExtTCPForwardRetrans(非 RTO timer)发送新数据的次数,即在 tcp_fastretrans_alert()/tcp_simple_retransmit()->tcp_xmit_retransmit_queue() 中,如果发现 skb->seq > tp->retransmit_high(一般为 snd_una),如果当前状态为 Recovery,启用了 SACK,并且发送条件允许就在这个函数中发送新数据。
TcpExtTCPFastRetrans(非 RTO timer)快速重传次数,即 tcp_fastretrans_alert()/tcp_simple_retransmit()->tcp_xmit_retransmit_queue() 中,如果不是 LOSS 状态,就加1
TcpExtTCPSlowStartRetrans(非 RTO timer)重传次数:即 tcp_fastretrans_alert()/tcp_simple_retransmit()->tcp_xmit_retransmit_queue() 中,如果是 LOSS 状态,就加1
TcpExtTCPLostRetransmit根据 SACK 数据推测出的重段包丢失计数器:在 tcp_sacktag_write_queue()->tcp_mark_lost_retrans(), 如果发现 tcp_highest_sack_seq(tp) 超过某 skb 在重传时的 snd_nxt(TCB->ack_seq),就认为这个重传包 已经丢失了,加1(加的不是段数)。tcp_highest_sack_seq(tp) 是被 SACK 过的具有最高 SEQ 号的 skb 的 seq。
TcpExtTCPSpuriousRTOstcp_process_frto(),如果 frto_counter !=0 && frto_counter != 1 加1


TCP ACK & SACK


类别 名称 描述
TcpExtDelayedACKLockedtcp_delack_timer(): delay ACK 定时器因为 user 已经锁住而无法发送 ACK 的次数。
TcpExtDelayedACKLosttcp_validate_incoming()->tcp_send_dupack():当输入包不在接收窗口内,或者 PAWS 失败后,计数器加1tcp_data_queue(): 输入包的结束序列号 < RCV_NXT 时,加1
TcpExtDelayedACKstcp_delack_timer():调用 tcp_send_ack() 的次数,无论是否是成功。
TcpExtTCPHPAckstcp_ack(): 接收到包,进入 quick path 时加1
TcpExtTCPPureAckstcp_ack(): 接收慢速路径中的 pure ACK 数量
TcpExtTCPDSACKIgnoredNoUndotcp_sacktag_write_queue(): undo_marker 为0并且接收到非法 D-SACK 块时,加1,即 SACK 中的序号太旧。
TcpExtTCPDSACKIgnoredOldtcp_sacktag_write_queue(): undo_marker 不为0,并且接收到非法 D-SACK 块时,加1,即 SACK 中的序号太旧。
TcpExtTCPSACKDiscardtcp_sacktag_write_queue(): 非法 SACK 块(不包括 D-SACK)计数,即 SACK 中的序号太旧。
TcpExtTCPDSACKOldSenttcp_dsack_set(): 如果 SACK 块开始序号小于 RCV.NXT,加1
TcpExtTCPDSACKOfoSenttcp_dsack_set(): 如果 SACK 块开始序号大于等于 RCV.NXT,加1
TcpExtTCPSACKRenegingtcp_clean_rtx_queue(): 如果 snd_una(输入 skb->ack)之后的具有最小开始序号 skb(即 sk_write_queue 中的第一个 skb)中有 TCPCB_SACKED_ACKED 标志,此时加1,这说明接收者已经丢掉了之前它已经 SACK 过的数据。
TcpExtTCPSackFailurestcp_retransmit_timer(): 在 Reorder 状态下,或者 sacked_out 不为0时,发生 RTO,并且启用了 SACK,加1
TcpExtTCPSackRecoveryFailtcp_retransmit_timer(): 在 Reovery 状态下发生 RTO,并且启用了 SACK,加1
TcpExtTCPDSACKRecvtcp_check_dsack(): 收到 D-SACK,并且 SACK0 开始序号 < ACK 号,加1
TcpExtTCPDSACKOfoRecvtcp_check_dsack(): 收到 D-SACK,并且 SACK0 开始序号>= ACK 号,但 SACK1 包括 SACK0。
TcpExtTCPSackRecoverytcp_fastretrans_alert(): SACK TCP 进入 Reovery 状态的次数
TcpExtTCPSackShiftedtcp_ack()->tcp_sacktag_write_queue()->tcp_sacktag_walk()->tcp_shift_skb_data()->tcp_shifted_data()在 tcp_sacktag_walk() 时,一个 SACK 可能会导致切割某 skb,新切出来的 skb 放到被切的 skb 之后。 根据 SACK 的观点,如果 “旧的 skb”(变小了) 能够与它之前的 skb 合并,本计数器,就加1。 这个合并过程,叫作 shift
TcpExtTCPSackShiftFallbacktcp_ack()->tcp_sacktag_write_queue()->tcp_sacktag_walk()->tcp_shift_skb_data()与上相反,如果不能 shift,本计数器加1。原因可能如下: 不支持 GSOprev skb 不完全是 paged 的SACK 的序号已经 ACK 过,等等
TcpExtTCPSackMergedtcp_ack()->tcp_sacktag_write_queue()->tcp_sacktag_walk()->tcp_shift_skb_data()->tcp_shifted_data()在上面介绍的 shift 过程中,如果发现分割之后的 skb 被它之前的 skb 完全 “吃掉”,本计数器加1


TCP TIME_WAIT


类别 名称 描述
TcpExtTWinet_twdr_do_twkill_work(): TIME_WAIT 超时的 socket 数量(timeout>= 4s) 之所以按超时分别对待 timewait socket,可能是考虑到长超时的 socket 的 timeout 时间分布比较分散,需要使用不同的查找方法。
TcpExtTWKilledinet_twdr_twcal_tick(): TIME_WAIT 超时的 socket 数量.(timeout < 4s), 仅在启用 sysctl_tw_recycle,并且使用 TCP timestamp option 时才会有这种情况,这时使用 3.5x RTO 时作为 timewait timeout,而默认 timeout 为 60s
TcpExtTWRecycledtcp_v4_connect() -> __inet_check_established(): 在建立时,如果 port 是从 TIME_WAIT socket 中复用的,加1
TcpExtTCPTimeWaitOverflowtcp_time_wait(): 当系统无法分配新的 tcp_timewait_socket,或者 tw_count(scheduled timewait sockets)超过 sysctl_max_tw_buckets 时,加1


TCP Congestion Processing


类别名称描述
TcpExtTCPDSACKUndotcp_ack() -> tcp_fastretrans_alert() -> tcp_try_undo_dsack() Disorder状态下,undo完成(undo_retrans == 0)的次数。
TcpExtTCPFullUndotcp_ack() -> tcp_fastretrans_alert() -> tcp_try_undo_recovery() Recovery状态时,接收到到全部确认(snd_una >= high_seq)后且已经undo完成(undo_retrans == 0)的次数。
TcpExtTCPPartialUndotcp_ack() -> tcp_fastretrans_alert() -> tcp_undo_partial() Recovery状态时,接收到到部分确认(snd_una < high_seq)时但已经undo完成(undo_retrans == 0)的次数。
TcpExtTCPLossUndotcp_ack() -> tcp_fastretrans_alert() -> tcp_try_undo_loss() Loss状态时,接收到到全部确认(snd_una >= high_seq)后且已经undo完成(undo_retrans == 0)的次数。
TcpExtTCPRenoReorder在tcp_update_reordering()中更新,当metric > tp->reordering并且没有启用SACK,本计数器加1 综合来说,在sacked_out“不可靠”时,tp->reordering被更新为当前窗口中的“已用seg”个数,同时包括未确认(和已确认的?)数据,但不包括lost_out。A. tcp_ack() -> tcp_fastretrans_alert() -> tcp_add_reno_sack() -> tcp_check_reno_reordering() -> tcp_update_reordering():  在Open/Recovery/Disorder/CWR状态下接收到dupACK时: 如果sacked_out + lost_out > packets_out, 用metric( = packets_out)调用tcp_update_reordering() B. tcp_ack() -> tcp_clean_rtx_queue() -> tcp_remove_reno_sacks() -> tcp_check_reno_reordering() -> tcp_update_reordering() :  在清理rtx queue时,会从packets_out, lost_out, sacked_out中减去确认了的seg数量, 如果sacked_out + lost_out > packets_out, 用metric( = packets_out + acked_pcount)调用tcp_update_reordering()注:**sacked_out : 接收到的dupACK数量lost_out : 限制最小值为1,最大值为packets_outtp->reordering: 创建socket时,被动建立连接时,进入Loss状态时,初始化为sysctl_tcp_reordering
TcpExtTCPSACKReorder在tcp_update_reordering()中更新,当metric > tp->reordering并且启用SACK但关闭FACK时,本计数器加1 A. tcp_ack() -> tcp_sacktag_write_queue() -> tcp_update_reordering()  在tcp_sacktag_walk()中会计算fackets_out(通过累加state.fack_count),这个值即从snd_una开始到已经SACK的最高序号间的seg数量(包括没有被SACK覆盖的)。判断发生乱序的条件是: (1)发现针对重传报文的D-SACK;(2)当前接收到SACK序号比以前接收到的最大SACK序号小。state.reord是发生乱序时的最小fack_count,即在“snd_una + fack_count”处发生了乱序。 metric = tp->fackets_out - state.reord,即可能发生乱序的最多报文数。 B. tcp_ack() -> tcp_clean_rtx_queue() -> tcp_update_reordering()  与A.类似,tcp_clean_rtx_queue()计算rtx queue中被SACK过的数据(非重传)中空洞,reord保存“最小号”空洞的位置(在重传队列中的“座次”)。而prior_fackets - reord即可能发生乱序的TCP segments数量。如果没有SACK,reorder = prior_fackets = 0 metric = prior_fackets - reord
TcpExtTCPFACKReorder与TCPSACKReorder类似,如果同时启用了SACK和FACK,就增加本计数器。
TcpExtTCPTSReordertcp_ack() -> tcp_fastretrans_alert() -> tcp_undo_partial() -> tcp_update_reordering()  Recovery状态时,接收到到部分确认(snd_una < high_seq)时但已经undo完成(undo_retrans == 0)的次数。 数量上与TCPPartialUndo相等。


TCP Others


类别名称描述
TcpExtTCPRenoRecoveryFailtcp_retransmit_timer(): 在Reovery状态下发生RTO,并且没有启用SACK,加1
TcpExtTCPRenoFailurestcp_retransmit_timer(): 在Reorder状态下,或者sacked_out不为0时,发生RTO,并且没有启用SACK,加1
TcpExtTCPRenoRecoverytcp_fastretrans_alert(): 不使用SACK的TCP进入Reovery状态的次数
TcpExtArpFilterarp_rcv() -> NETFILTER(ARP_IN) -> arp_process() 与TCP无关,接收到ARP packet时做一次输出路由查找(sip, tip),如果找到的路由项的device与输入device的不同,计数器加1
TcpExtEmbryonicRststcp_v4_do_rcv() -> tcp_v4_hnd_req() -> tcp_check_req(): 在三手握手时的SYN_RECV状态中接收到RST或者SYN的次数。
TcpExtLockDroppedIcmpstcp_v4_err(): 接收到ICMP错误报文,但tcp socket被user锁住
TcpExOfoPrunedtcp_data_queue() -> tcp_try_rmem_schedule() 慢速路径中,如果不能将数据直接复制到user space,需要加入到sk_receive_queue前,会检查receiver side memory是否允许,如果rcv_buf不足就可能prune ofo queue。此时计数器加1
TcpExtOutOfWindowIcmpstcp_v4_err(): 接收到的ICMP,但ICMP中的TCP头序号不在接收窗口之内的次数,有两个可能情况:(1)LISTEN状态时,序号不等待ISN;(2)其他状态时,序号不在SND_UNA .. SND_NXT之间
TcpExtPAWSActivetcp_rcv_synsent_state_process(): 在发送SYN后,接收到ACK,但PAWS检查失败的次数。
TcpExtPAWSEstabtcp_validate_incoming() tcp_timewait_state_process() tcp_check_req() 输入包PAWS失败次数。
TcpExtPAWSPassivetcp_v4_conn_request(): 三路握手最后一个ACK的PAWS检查失败次数。
TcpExtPruneCalledtcp_data_queue() -> tcp_try_rmem_schedule() 慢速路径中,如果不能将数据直接复制到user space,需要加入到sk_receive_queue前,会检查receiver side memory是否允许,如果rcv_buf不足就可能prune ofo queue。此时计数器加1
TcpExtRcvPrunedtcp_data_queue() -> tcp_try_rmem_schedule() 慢速路径中,如果不能将数据直接复制到user space,需要加入到sk_receive_queue前,会检查receiver side memory是否允许,如果rcv_buf不足就可能prune receive queue,如果prune失败了,此计数器加1。
TcpExtSyncookiesFailedcookie_v4_check(): SYN cookie检查失败次数。
TcpExtSyncookiesRecvcookie_v4_check(): 接收SYN cookie次数。
TcpExtSyncookiesSentcookie_v4_init_sequence(): 生成SYN cookie次数。
TcpExtTCPAbortFailedtcp_send_active_reset(): alloc_skb()或者tcp_transmit_skb()失败。
TcpExtTCPAbortOnClosetcp_close(): sk_receive_queue中仍有数据的次数。
TcpExtTCPAbortOnDatatcp_rcv_state_process(): 在FIN_WAIT_1/FIN_WAIT_2状态下接收到后续数据(序号>RCV_NXT);或者,TCP_LINGER2设置值<0,计数器加1 tcp_close(): 没有未读数据,但设置了SO_LINGER并且linger timeout=0, 计数器加1,此时TCP正常断开连接sk_prot->disconnect()。
TcpExtTCPAbortOnLingertcp_close(): 因TCP_LINGER2设置值<0,FIN_WAIT_2立即切换到CLOSE的次数。
TcpExtTCPAbortOnMemory在执行tcp_close()/probe timer/keepalive timer时,orphan sockets数量和tcp_memory_allocated是否超过最大值的次数。
TcpExtTCPAbortOnSyntcp_validate_incoming(): 出现SYN,并且序号大于RCV_NXT的次数。
TcpExtTCPAbortOnTimeoutRTO/probe/keepalive timer到达最大重试次数或者最长重试时间的次数


TCP Others Others


类别名称描述
TcpExtTCPBacklogDroptcp_v4_rcv() : 如果socket被user锁住,后退一步内核会把包加到sk_backlog_queue,但如果因为sk_rcv_buf不足的原因入队失败,计数器加1
TcpExtTCPDeferAcceptDroptcp_check_req(): 如果启用TCP_DEFER_ACCEPT,这个计数器统计了被丢掉了“Pure ACK”个数。 TCP_DEFER_ACCEPT:允许listener只有在连接上有数据才创建新的socket,以抵御syn-flood攻击。
TcpExtTCPDirectCopyFromBacklogtcp_recvmsg(): 如果有数据在softirq里面从backlog queue中直接复制到userland memory上,计数器加1
TcpExtTCPDirectCopyFromPrequeuetcp_recvmsg(): 如果有数据在这个syscall里从prequeue中直接复制到userland memory上,计数器加1
TcpExtTCPHPHitstcp_rcv_established(): 如果有skb通过“快速路径”进入到sk_receive_queue上,计数器加1。 特别地,Pure ACK以及直接复制到user space上的都不算在这个计数器上。
TcpExtTCPHPHitsToUsertcp_rcv_established(): 如果有skb通过“快速路径”直接复制到user space上,计数器加1。
TcpExtTCPLossFailurestcp_retransmit_timer(): icsk_retransmit==0(第一次进入重传状态)并且处于Loss状态下,计数器加1 可能情况是:因为partial ACK中从Loss中undo了一些状态,但还有完全离开Loss
TcpExtTCPMD5NotFoundtcp_v4_do_rcv() -> tcp_v4_inbound_md5_hash() : 配置了md5检查,但在输入skb中没有找到对应TCP选项。
TcpExtTCPMD5Unexpectedtcp_v4_do_rcv() -> tcp_v4_inbound_md5_hash() : 未配置md5检查,但在输入skb中找到了对应TCP选项。
TcpExtTCPMemoryPressurestcp_enter_memory_pressure()在从“非压力状态”切换到“有压力状态”时计数器加1,可能的触发点有:tcp_sendmsg()tcp_sendpage()tcp_fragment()tso_fragment()tcp_mtu_probe()tcp_data_queue()
TcpExtTCPMinTTLDroptcp_v4_err() / tcp_v4_rcv(): 在接收到TCP报文或者TCP相关的ICMP报文时,检查IP TTL,如果小于socket option设置的一个阀值,就丢包。这个功能是RFC5082(The Generalized TTL Security Mechanism, GTSM)规定的,使用GTSM的通信双方,都将TTL设置成最大值255,双方假定了解之间的链路情况,这样可以通过检查最小TTL值隔离攻击。
TcpExtTCPPrequeueDroppedtcp_v4_rcv() -> tcp_prequeue() : 如果因为内存不足(ucopy.memory < sk->rcv_buf)而加入到prequeue失败,重新由backlog处理,计数器加1
TcpExtTCPPrequeuedtcp_recvmsg() -> tcp_prequeue_process() : tcp_recvmsg()发现可以从prequeue接收到报文,计数器加1(不是每个skb加1)
TcpExtTCPRcvCollapsedtcp_prune_queue() -> tcp_collapse() -> tcp_collapse_one() tcp_prune_ofo_queue() -> tcp_collapse()  每当合并sk_receive_queue(ofo_queue)中的连续报文时,计数器加1
TcpExtTCPReqQFullDoCookiestcp_rcv_state_process() -> tcp_v4_conn_request() -> tcp_syn_flood_action() syn_table过载,进行SYN cookie的次数(取决于是否打开sysctl_tcp_syncookies)。
TcpExtTCPReqQFullDroptcp_rcv_state_process() -> tcp_v4_conn_request() -> tcp_syn_flood_action() syn_table过载,丢掉SYN的次数。
TcpExtTCPSchedulerFailedtcp_delack_timer(): 在delay ACK处理功能内,如果prequeue中仍有数据,计数器就加1 加入到prequeue,本来是期待着userspace(使用tcp_recvmsg()之类的系统调用)尽快处理之。其中仍有数据,可能隐含着userspace行为不佳。
TcpExtIPReversePathFilterip_rcv_finish() -> ip_route_input_noref(): 反向路径过滤掉的IP分组数量:要么反向路由查找失败,要么是找到的输出接口与输入接口不同。



参考资料

anzhihe 安志合个人博客,版权所有 丨 如未注明,均为原创 丨 转载请注明转自:https://chegva.com/3553.html | ☆★★每天进步一点点,加油!★★☆ | 

您可能还感兴趣的文章!

发表评论

电子邮件地址不会被公开。 必填项已用*标注