類別 | 名稱 | 描述 |
---|---|---|
Tcp | ActiveOpens | tcp_connect(),發送SYN時,加1 |
Tcp | PassiveOpens | tcp_create_openreq_child(), 被動三路握手完成,加1 |
Tcp | AttemptFails |
|
Tcp | CurrEstab | tcp_set_state(),根據ESTABLISHED是新/舊狀態,分別加減一。 |
Tcp | EstabResets | tcp_set_state(),新狀態為TCP_CLOSE,如果舊狀態是ESTABLISHED/TCP_CLOSE_WAIT就加1 |
Tcp | ListenOverflows | tcp_v4_syn_recv_sock():三路握手最后一步完全之后,Accept queue隊列超過上限時加1 |
Tcp | ListenDrops | tcp_v4_syn_recv_sock():任何原因,包括Accept queue超限,創建新連接,繼承端口失敗等,加1 |
Tcp | MaxConn | 0 |
Tcp | InSegs | tcp_v4_rcv(),收到一個skb,加1 |
Tcp | InErrs |
|
Tcp | OutSegs |
|
Tcp | OutRsts | tcp_v4_send_reset(), tcp_send_active_reset()加1 |
類別 | 名稱 | 描述 |
---|---|---|
Tcp | TCPTimeouts |
|
Tcp | RtoAlgorithm | 1,tcp_mib_init()初始化 |
Tcp | RtoMax | 120000,tcp_mib_init()初始化:TCP_RTO_MAX*1000/HZ,TCP_RTO_MAX=120*HZ |
Tcp | RtoMin | 200,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
類別 | 名稱 | 描述 |
---|---|---|
Tcp | RetransSegs | 重傳次數,包括RTO timer和常規重傳,即tcp_retransmit_skb()中調用tcp_transmit_skb(),成功返回即+1。 |
TcpExt | TCPForwardRetrans | (非RTO timer)發送新數據的次數,即在tcp_fastretrans_alert()/tcp_simple_retransmit()->tcp_xmit_retransmit_queue()中, 如果發現skb->seq > tp->retransmit_high(一般為snd_una),如果當前狀態為Recovery,啟用了SACK,並且發送條件允許就在這個函數中發送新數據。 |
TcpExt | TCPFastRetrans | (非RTO timer)快速重傳次數,即tcp_fastretrans_alert()/tcp_simple_retransmit()->tcp_xmit_retransmit_queue()中,如果不是LOSS狀態,就加1 |
TcpExt | TCPSlowStartRetrans | (非RTO timer)重傳次數:即tcp_fastretrans_alert()/tcp_simple_retransmit()->tcp_xmit_retransmit_queue()中,如果是LOSS狀態,就加1 |
TcpExt | TCPLostRetransmit | 根據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。 |
TcpExt | TCPSpuriousRTOs | tcp_process_frto(),如果frto_counter !=0 && frto_counter != 1加1 |
類別 | 名稱 | 描述 |
---|---|---|
TcpExt | DelayedACKLocked | tcp_delack_timer(): delay ACK定時器因為user已經鎖住而無法發送ACK的次數。 |
TcpExt | DelayedACKLost |
|
TcpExt | DelayedACKs | tcp_delack_timer():調用tcp_send_ack()的次數,無論是否是成功。 |
TcpExt | TCPHPAcks | tcp_ack():接收到包,進入quick path時加1 |
TcpExt | TCPPureAcks | tcp_ack():接收慢速路徑中的pure ACK數量 |
TcpExt | TCPDSACKIgnoredNoUndo | tcp_sacktag_write_queue(): undo_marker為0並且接收到非法D-SACK塊時,加1,即SACK中的序號太舊。 |
TcpExt | TCPDSACKIgnoredOld | tcp_sacktag_write_queue(): undo_marker不為0,並且接收到非法D-SACK塊時,加1,即SACK中的序號太舊。 |
TcpExt | TCPSACKDiscard | tcp_sacktag_write_queue(): 非法SACK塊(不包括D-SACK)計數,即SACK中的序號太舊。 |
TcpExt | TCPDSACKOldSent | tcp_dsack_set():如果SACK塊開始序號小於RCV.NXT,加1 |
TcpExt | TCPDSACKOfoSent | tcp_dsack_set():如果SACK塊開始序號大於等於RCV.NXT,加1 |
TcpExt | TCPSACKReneging | tcp_clean_rtx_queue(): 如果snd_una(輸入skb->ack)之后的具有最小開始序號skb(即sk_write_queue中的第一個skb)中有TCPCB_SACKED_ACKED標志,此時加1,這說明接收者已經丟掉了之前它已經SACK過的數據。 |
TcpExt | TCPSackFailures | tcp_retransmit_timer(): 在Reorder狀態下,或者sacked_out不為0時,發生RTO,並且啟用了SACK,加1 |
TcpExt | TCPSackRecoveryFail | tcp_retransmit_timer(): 在Reovery狀態下發生RTO,並且啟用了SACK,加1 |
TcpExt | TCPDSACKRecv | tcp_check_dsack(): 收到D-SACK,並且SACK0開始序號 < ACK號,加1 |
TcpExt | TCPDSACKOfoRecv | tcp_check_dsack(): 收到D-SACK,並且SACK0開始序號 >= ACK號,但SACK1包括SACK0。 |
TcpExt | TCPSackRecovery | tcp_fastretrans_alert(): SACK TCP進入Reovery狀態的次數 |
TcpExt | TCPSackShifted | tcp_ack()->tcp_sacktag_write_queue()->tcp_sacktag_walk()->tcp_shift_skb_data()->tcp_shifted_data() 在tcp_sacktag_walk()時,一個SACK可能會導致切割某skb,新切出來的skb放到被切的skb之后。 |
TcpExt | TCPSackShiftFallback | tcp_ack()->tcp_sacktag_write_queue()->tcp_sacktag_walk()->tcp_shift_skb_data() 與上相反,如果不能shift,本計數器加1。原因可能如下:
|
TcpExt | TCPSackMerged | tcp_ack()->tcp_sacktag_write_queue()->tcp_sacktag_walk()->tcp_shift_skb_data()->tcp_shifted_data() 在上面介紹的shift過程中,如果發現分割之后的skb被它之前的skb完全“吃掉”,本計數器加1 |
類別 | 名稱 | 描述 |
---|---|---|
TcpExt | TW | inet_twdr_do_twkill_work(): TIME_WAIT超時的socket數量(timeout >= 4s) 之所以按超時分別對待timewait socket,可能是考慮到長超時的socket的timeout時間分布比較分散,需要使用不同的查找方法。 |
TcpExt | TWKilled | inet_twdr_twcal_tick(): TIME_WAIT超時的socket數量.(timeout < 4s), 僅在啟用sysctl_tw_recycle,並且使用TCP timestamp option時才會有這種情況,這時使用3.5x RTO時作為timewait timeout,而默認timeout為60s |
TcpExt | TWRecycled | tcp_v4_connect() -> __inet_check_established(): 在建立時,如果port是從TIME_WAIT socket中復用的,加1 |
TcpExt | TCPTimeWaitOverflow | tcp_time_wait(): 當系統無法分配新的tcp_timewait_socket,或者tw_count(scheduled timewait sockets)超過sysctl_max_tw_buckets時,加1 |
TCP Others
類別 | 名稱 | 描述 |
---|---|---|
TcpExt | TCPRenoRecoveryFail | tcp_retransmit_timer(): 在Reovery狀態下發生RTO,並且沒有啟用SACK,加1 |
TcpExt | TCPRenoFailures | tcp_retransmit_timer(): 在Reorder狀態下,或者sacked_out不為0時,發生RTO,並且沒有啟用SACK,加1 |
TcpExt | TCPRenoRecovery | tcp_fastretrans_alert(): 不使用SACK的TCP進入Reovery狀態的次數 |
#! /usr/bin/python proc_files = ("/proc/net/netstat", "/proc/net/snmp") def parse_proc_files(fn): stats = {} lines = file(fn).readlines() n_lines = len(lines) n = 0 while n < n_lines: titles = lines[n].split(" ") # TcpExt: TcpXX SackXX values = lines[n+1].split(" ") # TcpExt: 11 23213 kind = titles[0] del titles[0] del values[0] sub_stats = stats.get(kind, {}) n_cols = len(titles) for i in range(n_cols): sub_stats[titles[i].strip()] = values[i].strip() stats[kind] = sub_stats n += 2 return stats def show_parsed(stats): kind_list = stats.keys() kind_list.sort() for kind in kind_list: title_list = stats[kind].keys() title_list.sort() for title in title_list: print "%-10s%-25s\t%20s" % (kind, title, stats[kind][title]) s = {} for fn in proc_files: new_s = parse_proc_files(fn) for new_kind in new_s: if new_kind not in s: # unlikely s[new_kind] = new_s[new_kind] else: s[new_kind].update(new_s[new_kind]) show_parsed(s)
類別 | 名稱 | 描述 |
---|---|---|
TcpExt | TCPDSACKUndo | tcp_ack() -> tcp_fastretrans_alert() -> tcp_try_undo_dsack() Disorder狀態下,undo完成(undo_retrans == 0)的次數。 |
TcpExt | TCPFullUndo | tcp_ack() -> tcp_fastretrans_alert() -> tcp_try_undo_recovery() Recovery狀態時,接收到到全部確認(snd_una >= high_seq)后且已經undo完成(undo_retrans == 0)的次數。 |
TcpExt | TCPPartialUndo | tcp_ack() -> tcp_fastretrans_alert() -> tcp_undo_partial() Recovery狀態時,接收到到部分確認(snd_una < high_seq)時但已經undo完成(undo_retrans == 0)的次數。 |
TcpExt | TCPLossUndo | tcp_ack() -> tcp_fastretrans_alert() -> tcp_try_undo_loss() Loss狀態時,接收到到全部確認(snd_una >= high_seq)后且已經undo完成(undo_retrans == 0)的次數。 |
TcpExt | TCPRenoReorder | 在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(): 注:
|
TcpExt | TCPSACKReorder | 在tcp_update_reordering()中更新,當metric > tp->reordering並且啟用SACK但關閉FACK時,本計數器加1 |
TcpExt | TCPFACKReorder | 與TCPSACKReorder類似,如果同時啟用了SACK和FACK,就增加本計數器。 |
TcpExt | TCPTSReorder | tcp_ack() -> tcp_fastretrans_alert() -> tcp_undo_partial() -> tcp_update_reordering() Recovery狀態時,接收到到部分確認(snd_una < high_seq)時但已經undo完成(undo_retrans == 0)的次數。 數量上與TCPPartialUndo相等。 |
類別 | 名稱 | 描述 |
---|---|---|
TcpExt | TCPRenoRecoveryFail | tcp_retransmit_timer(): 在Reovery狀態下發生RTO,並且沒有啟用SACK,加1 |
TcpExt | TCPRenoFailures | tcp_retransmit_timer(): 在Reorder狀態下,或者sacked_out不為0時,發生RTO,並且沒有啟用SACK,加1 |
TcpExt | TCPRenoRecovery | tcp_fastretrans_alert(): 不使用SACK的TCP進入Reovery狀態的次數 |
TcpExt | ArpFilter | arp_rcv() -> NETFILTER(ARP_IN) -> arp_process() 與TCP無關,接收到ARP packet時做一次輸出路由查找(sip, tip),如果找到的路由項的device與輸入device的不同,計數器加1 |
TcpExt | EmbryonicRsts | tcp_v4_do_rcv() -> tcp_v4_hnd_req() -> tcp_check_req(): 在三手握手時的SYN_RECV狀態中接收到RST或者SYN的次數。 |
TcpExt | LockDroppedIcmps | tcp_v4_err(): 接收到ICMP錯誤報文,但tcp socket被user鎖住 |
TcpEx | OfoPruned | tcp_data_queue() -> tcp_try_rmem_schedule() 慢速路徑中,如果不能將數據直接復制到user space,需要加入到sk_receive_queue前,會檢查receiver side memory是否允許,如果rcv_buf不足就可能prune ofo queue。此時計數器加1 |
TcpExt | OutOfWindowIcmps | tcp_v4_err(): 接收到的ICMP,但ICMP中的TCP頭序號不在接收窗口之內的次數,有兩個可能情況:(1)LISTEN狀態時,序號不等待ISN;(2)其他狀態時,序號不在SND_UNA .. SND_NXT之間 |
TcpExt | PAWSActive | tcp_rcv_synsent_state_process(): 在發送SYN后,接收到ACK,但PAWS檢查失敗的次數。 |
TcpExt | PAWSEstab | tcp_validate_incoming() tcp_timewait_state_process() |
TcpExt | PAWSPassive | tcp_v4_conn_request(): 三路握手最后一個ACK的PAWS檢查失敗次數。 |
TcpExt | PruneCalled | tcp_data_queue() -> tcp_try_rmem_schedule() 慢速路徑中,如果不能將數據直接復制到user space,需要加入到sk_receive_queue前,會檢查receiver side memory是否允許,如果rcv_buf不足就可能prune ofo queue。此時計數器加1 |
TcpExt | RcvPruned | tcp_data_queue() -> tcp_try_rmem_schedule() 慢速路徑中,如果不能將數據直接復制到user space,需要加入到sk_receive_queue前,會檢查receiver side memory是否允許,如果rcv_buf不足就可能prune receive queue,如果prune失敗了,此計數器加1。 |
TcpExt | SyncookiesFailed | cookie_v4_check(): SYN cookie檢查失敗次數。 |
TcpExt | SyncookiesRecv | cookie_v4_check(): 接收SYN cookie次數。 |
TcpExt | SyncookiesSent | cookie_v4_init_sequence(): 生成SYN cookie次數。 |
TcpExt | TCPAbortFailed | tcp_send_active_reset(): alloc_skb()或者tcp_transmit_skb()失敗。 |
TcpExt | TCPAbortOnClose | tcp_close(): sk_receive_queue中仍有數據的次數。 |
TcpExt | TCPAbortOnData | tcp_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()。 |
TcpExt | TCPAbortOnLinger | tcp_close(): 因TCP_LINGER2設置值<0,FIN_WAIT_2立即切換到CLOSE的次數。 |
TcpExt | TCPAbortOnMemory | 在執行tcp_close()/probe timer/keepalive timer時,orphan sockets數量和tcp_memory_allocated是否超過最大值的次數。 |
TcpExt | TCPAbortOnSyn | tcp_validate_incoming(): 出現SYN,並且序號大於RCV_NXT的次數。 |
TcpExt | TCPAbortOnTimeout | RTO/probe/keepalive timer到達最大重試次數或者最長重試時間的次數 |
類別 | 名稱 | 描述 |
---|---|---|
TcpExt | TCPBacklogDrop | tcp_v4_rcv() : 如果socket被user鎖住,后退一步內核會把包加到sk_backlog_queue,但如果因為sk_rcv_buf不足的原因入隊失敗,計數器加1 |
TcpExt | TCPDeferAcceptDrop | tcp_check_req(): 如果啟用TCP_DEFER_ACCEPT,這個計數器統計了被丟掉了“Pure ACK”個數。 TCP_DEFER_ACCEPT:允許listener只有在連接上有數據才創建新的socket,以抵御syn-flood攻擊。 |
TcpExt | TCPDirectCopyFromBacklog | tcp_recvmsg(): 如果有數據在softirq里面從backlog queue中直接復制到userland memory上,計數器加1 |
TcpExt | TCPDirectCopyFromPrequeue | tcp_recvmsg(): 如果有數據在這個syscall里從prequeue中直接復制到userland memory上,計數器加1 |
TcpExt | TCPHPHits | tcp_rcv_established(): 如果有skb通過“快速路徑”進入到sk_receive_queue上,計數器加1。 特別地,Pure ACK以及直接復制到user space上的都不算在這個計數器上。 |
TcpExt | TCPHPHitsToUser | tcp_rcv_established(): 如果有skb通過“快速路徑”直接復制到user space上,計數器加1。 |
TcpExt | TCPLossFailures | tcp_retransmit_timer(): icsk_retransmit==0(第一次進入重傳狀態)並且處於Loss狀態下,計數器加1 可能情況是:因為partial ACK中從Loss中undo了一些狀態,但還有完全離開Loss |
TcpExt | TCPMD5NotFound | tcp_v4_do_rcv() -> tcp_v4_inbound_md5_hash() : 配置了md5檢查,但在輸入skb中沒有找到對應TCP選項。 |
TcpExt | TCPMD5Unexpected | tcp_v4_do_rcv() -> tcp_v4_inbound_md5_hash() : 未配置md5檢查,但在輸入skb中找到了對應TCP選項。 |
TcpExt | TCPMemoryPressures | tcp_enter_memory_pressure()在從“非壓力狀態”切換到“有壓力狀態”時計數器加1,可能的觸發點有:
|
TcpExt | TCPMinTTLDrop | tcp_v4_err() / tcp_v4_rcv(): 在接收到TCP報文或者TCP相關的ICMP報文時,檢查IP TTL,如果小於socket option設置的一個閥值,就丟包。這個功能是RFC5082(The Generalized TTL Security Mechanism, GTSM)規定的,使用GTSM的通信雙方,都將TTL設置成最大值255,雙方假定了解之間的鏈路情況,這樣可以通過檢查最小TTL值隔離攻擊。 |
TcpExt | TCPPrequeueDropped | tcp_v4_rcv() -> tcp_prequeue() : 如果因為內存不足(ucopy.memory < sk->rcv_buf)而加入到prequeue失敗,重新由backlog處理,計數器加1 |
TcpExt | TCPPrequeued | tcp_recvmsg() -> tcp_prequeue_process() : tcp_recvmsg()發現可以從prequeue接收到報文,計數器加1(不是每個skb加1) |
TcpExt | TCPRcvCollapsed | tcp_prune_queue() -> tcp_collapse() -> tcp_collapse_one() tcp_prune_ofo_queue() -> tcp_collapse() |
TcpExt | TCPReqQFullDoCookies | tcp_rcv_state_process() -> tcp_v4_conn_request() -> tcp_syn_flood_action() syn_table過載,進行SYN cookie的次數(取決於是否打開sysctl_tcp_syncookies)。 |
TcpExt | TCPReqQFullDrop | tcp_rcv_state_process() -> tcp_v4_conn_request() -> tcp_syn_flood_action() syn_table過載,丟掉SYN的次數。 |
TcpExt | TCPSchedulerFailed | tcp_delack_timer(): 在delay ACK處理功能內,如果prequeue中仍有數據,計數器就加1 加入到prequeue,本來是期待着userspace(使用tcp_recvmsg()之類的系統調用)盡快處理之。其中仍有數據,可能隱含着userspace行為不佳。 |
TcpExt | IPReversePathFilter | ip_rcv_finish() -> ip_route_input_noref(): 反向路徑過濾掉的IP分組數量:要么反向路由查找失敗,要么是找到的輸出接口與輸入接口不同。 |