http://blog.chinaunix.net/uid-20043340-id-2984198.html
最近在總結2.6.32與2.6.18的差異,我特别有興趣的是網絡部分,但猛然發現其實SNMP counters我也并不能準确解釋它們的含義,于是就有了以下總結,還不完整,持續總結中:
加粗的項代表TODO,還有一些counters沒有列出來。
難免有錯誤,請大家指正吧,我的codebase是linux2.6.git~
TCP Basic
類别 | 名稱 | 描述 |
---|---|---|
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 | |
Tcp | InSegs | tcp_v4_rcv(),收到一個skb,加1 |
Tcp | InErrs |
|
Tcp | OutSegs |
|
Tcp | OutRsts | tcp_v4_send_reset(), tcp_send_active_reset()加1 |
TCP Loss & Retrans
類别 | 名稱 | 描述 |
---|---|---|
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 |
TCP ACK & SACK
類别 | 名稱 | 描述 |
---|---|---|
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之後。 根據SACK的觀點,如果“舊的skb”(變小了)能夠與它之前的skb合并,本計數器,就加1。 這個合并過程,叫作shift |
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 |
TCP TIME_WAIT
類别 | 名稱 | 描述 |
---|---|---|
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狀态的次數 |
此外,可以用這個腳本收集這些counters:
- #! /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)