dstatのコードから読み解くLinux入門＠tcpオプション編

# みんな大好きdstatコマンド！
恐らくサーバ運用をされている方なら一度は叩いたことあるのではないでしょうか。
どんなコマンドでもそうですが、自分が今どんな情報を出力して見ているをきちんと理解するのかは非常に重要ですよね :smiley: 
ということで、身近なdstatのコードを眺めてLinux（CentOS）の世界を少しだけ眺めてみたいと思います！
今回tcpオプションから見ていくのは、たまたまお仕事で見ることがあったためです(笑)

# dstatコマンドってなに？
vmstatのリッチな感じ
詳細はこちらに素晴らしいまとめが！ありがたや！ :pray: 
[dstatの便利なオプションまとめ](http://qiita.com/harukasan/items/b18e484662943d834901)

ちなみに私は何かが起きたらとりあえずこのオプションでコマンド叩いて眺めています :muscle: 

```bash
$ dstat -V
Dstat 0.7.0
(略)
$ dstat -tlcmgdn --socket --tcp --io
----system---- ---load-avg--- ----total-cpu-usage---- ------memory-usage----- ---paging-- -dsk/total- -net/total- ------sockets------ ----tcp-sockets---- --io/total-
  date/time   | 1m   5m  15m |usr sys idl wai hiq siq| used  buff  cach  free|  in   out | read  writ| recv  send|tot tcp udp raw frg|lis act syn tim clo| read  writ
25-03 10:04:20|   0    0    0|  1   2  98   0   0   0| 452M  425M  665M  328M|   0     0 |   0    76k| 560B  794B|224   7  12   0   0| 10   2   0   0   0|   0  7.00 
25-03 10:04:21|   0    0    0|  0   1  99   0   0   0| 447M  425M  665M  332M|   0     0 |   0   296k| 390B 2078B|224   7  12   0   0| 10   2   0   0   0|   0  44.0 
25-03 10:04:22|   0    0    0|  0   1  99   0   0   0| 448M  425M  665M  332M|   0     0 |   0     0 |  60B  664B|224   7  12   0   0| 10   2   0   0   0|   0     0 
25-03 10:04:23|   0    0    0|  0   2  98   0   0   0| 454M  425M  665M  326M|   0     0 |   0     0 | 206B  820B|224   7  12   0   0| 10   2   0   0   0|   0     0 
25-03 10:04:24|   0    0    0|  0   1  99   0   0   0| 448M  425M  665M  332M|   0     0 |   0     0 | 390B  810B|224   7  12   0   0| 10   2   0   0   0|   0     0 
```

# dstat --tcpオプションについて
manから引用
>
--tcp  enable tcp stats (listen, established, syn, time_wait, close)

ふんふん、tcpの状態遷移を表示してくれるのか

## 出力例
```bash
$ dstat --tcp
----tcp-sockets----
lis act syn tim clo
 10   2   0   1   0
 10   2   0   1   0
```

# あれ？
TCPの状態遷移ってもっといっぱいなかったっけ？

# TCPの状態遷移について
詳細はこちらに素晴らしいまとめが！ありがたや！ :pray: 
[TCPの状態遷移@Qiita](http://qiita.com/mogulla3/items/196124b9fb36578e5c80)

# listen, established, syn, time_wait, close以外は何にカウントしてる？
コードを眺めてみよう！

```bash
$ git clone https://github.com/dagwieers/dstat.git
```
```py3:dstat/dstat
1603 class dstat_tcp(dstat):
1604     def __init__(self):
1605         self.name = 'tcp sockets'
1606         self.nick = ('lis', 'act', 'syn', 'tim', 'clo')
1607         self.vars = ('listen', 'established', 'syn', 'wait', 'close')
1608         self.type = 'd'
1609         self.width = 4
1610         self.scale = 100
1611         self.open('/proc/net/tcp', '/proc/net/tcp6')
1612 
1613     def extract(self):
1614         for name in self.vars: self.val[name] = 0
1615         for l in self.splitlines():
1616             if len(l) < 12: continue
1617             ### 01: established, 02: syn_sent,  03: syn_recv, 04: fin_wait1,
1618             ### 05: fin_wait2,   06: time_wait, 07: close,    08: close_wait,
1619             ### 09: last_ack,    0A: listen,    0B: closing
1620             if l[3] in ('0A',): self.val['listen'] += 1
1621             elif l[3] in ('01',): self.val['established'] += 1
1622             elif l[3] in ('02', '03', '09',): self.val['syn'] += 1
1623             elif l[3] in ('06',): self.val['wait'] += 1
1624             elif l[3] in ('04', '05', '07', '08', '0B',): self.val['close'] += 1
```

ふんふん、どうやら/proc/net/配下のファイルを読んで
closeに複数のステータス状態をマージしてインクリメントしているっぽい！

**・・・ところで/proc/net/{tcp,tcp6}ってなんだっけ** :sweat: 

# /proc/net/tcpってなんだっけ？
## どんな情報が入っているのか
```bash
$ head -n 3 /proc/net/tcp
  sl  local_address rem_address   st tx_queue rx_queue tr tm->when retrnsmt   uid  timeout inode                                                     
   0: 00000000:0016 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 12288 1 ffff88007d7eb580 99 0 0 10 -1
```

これだけじゃよくわからん。。。
ドキュメントを。。。
[Linux Kernel.org@proc_net_tcp](https://www.kernel.org/doc/Documentation/networking/proc_net_tcp.txt)
ふんふん、まとめるとこんな感じ？

| sl | local_address | rem_address | st | tx_queue | rx_queue | tr | tm->when |  retrnsmt | uid | timeout | inode|socket reference count|location of socket in memory|retransmit timeout|Predicted tick of soft clock|(ack.quick<<1)|ack.pingpong|sending congestion window|
|:---| :-------------|:------------|:---|:---------|:---------|:---|:---------|:----------|:----|:--------|:------|:---------------------|:---------------------------|:-----------------|:---------------------------|:-------------|:-----------|:------------------------|
|項番|local IP:Port|remote IP:Port|TCP状態|送信キュー|受信キュー|再送タイマー|タイマーがタイムアウトするまでの時間(jiffies単位)|retrnsmt|uid|timeout|inode||socket reference count|location of socket in memory|retransmit timeout|Predicted tick of soft clock|(ack.quick<<1)|ack.pingpong|sending congestion window|
|0|00000000:0016|00000000:0000|0A|00000000|00000000|00|00000000|00000000|0|0|12288|1|ffff88007d7eb580|99|0|0|10|-1|

jiffiesについてはこの辺りに素晴らしい情報が！ :pray: 
[カーネルにおけるタイマー事情 ～第2回 カーネル内の時刻/時間関連サブシステム～](http://www.valinux.co.jp/technologylibrary/document/linuxkernel/timer0002/)

もうちょっと細かい説明は分かり次第追記していきます。。。
inode以降の部分はまだまだお勉強が必要そうです。。。

# tcpオプションは/proc/net/tcpのstをカウントしていた！
## stカラムの詳細は？
dstatのコードにコメントがあったけど、それじゃちょっとつまらない。。。

**💡・・・そうだ、Kernelも見てみよう！（白目**

しかし、悲しいかな、私にはCで詳細を読み解く力はありません。。。
ので、コードを落としてcsearchでそれっぽいところだけでも探してみました。

```c:linux-2.6.32.69/include/net/tcp_states.h
 34 #define TCP_ACTION_FIN  (1 << 7)
 35 
 36 enum {
 37         TCPF_ESTABLISHED = (1 << 1),
 38         TCPF_SYN_SENT    = (1 << 2),
 39         TCPF_SYN_RECV    = (1 << 3),
 40         TCPF_FIN_WAIT1   = (1 << 4),
 41         TCPF_FIN_WAIT2   = (1 << 5),
 42         TCPF_TIME_WAIT   = (1 << 6),
 43         TCPF_CLOSE       = (1 << 7),
 44         TCPF_CLOSE_WAIT  = (1 << 8),
 45         TCPF_LAST_ACK    = (1 << 9),
 46         TCPF_LISTEN      = (1 << 10),
 47         TCPF_CLOSING     = (1 << 11)
 48 };
```

dstatのコメント比較してみると、構造体的にもそれっぽい！

```py3:dstat/dstat
1617             ### 01: established, 02: syn_sent,  03: syn_recv, 04: fin_wait1,
1618             ### 05: fin_wait2,   06: time_wait, 07: close,    08: close_wait,
1619             ### 09: last_ack,    0A: listen,    0B: closing
```

というわけで、私のC戦闘力が著しく低いことが見事に露呈した悲しい感じですが、
身近なdstatを使ってちょこっとだけLinuxの世界を覗いてみました。
また近いうちに別のオプションについても出来るだけ書いてみようとおもいます :muscle: