HackToTech

Hack To Technology

BPF本を読みながら学ぶ10

BPF本を読みながら学ぶ10

10章、ネットワークについて
割と知らない単語があって調べるのに苦労した
後半はbpftraceを用いたツールの説明が多い

目次

用語

  • Queueing Discipline(キューイングの規則)
    • 入力側 (ingress: 入口)、出力側 (egress: 出口) いずれかの デバイスのキューを管理するアルゴリズムのこと。

  • AQM(Active Queue Management)
    • CoDel(Controlled Delay)
    • RED(Random Early Detection)
  • XDP(eXpress Data Path)
    • NICドライバー内でのeBPFによるフックを介したパケット処理
    • 柔軟で処理速度が優秀(ACMの動画を見るにDDoS攻撃とかに対しても有用っぽい(BPF本側でも言及されてた))
    • 無駄なコンテキストスイッチが走らない(カーネル空間側で処理する)
  • TCP輻輳制御
    • Cubic(default)
    • Reno
    • Tahoe
    • DCTCP
    • BBR

参考

ネットワークのパフォーマンス分析

  1. ネットワークの統計情報を確認する
    パケットレート/スループット、およびTCP接続がある場合はTCPの接続/再送信のレート
    ss / nstat / netstat / sar
  2. TCP接続の特徴を観測し、非効率部分を探す
    tcplife
  3. ネットワークインタフェースのスループット制限に達しているかを確認する
    sar / nicstat
  4. TCPの再送信やドロップなどの異常なTCPイベントをトレースする
    tcpretrans / tcpdrop / skb:kfree_skb tracepoint
  5. DNSの名前解決の遅延を測定する
    gethostlatency
  6. コネクションの遅延、TTFBの遅延、スタックの遅延など様々な箇所からネットワークの遅延状況を測定する
  7. bufferbloatなど負荷によって遅延時間を大きく変化するので注意すること
  8. 負荷生成ツールでホスト間のネットワークスループットを調べて既知のワークロードに対するネットワークイベントを調べる
    iperf / netperf
  9. bpftoolを使用する
  10. カーネルのスタックトレースのCPUプロファイリングを使用して、プロトコルおよびドライバーの処理に費やされるCPU時間を定量化する
  11. トレースポイントとkprobes

ss

ソケットの統計をダンプする
netstatと同様の情報を表示できる

フィールド1

Netid 接続の種類
u_str: TCP
u_dgr: UDP
v_str: vSocket
State ESTAB: Established
UNCONN: Close
Recv-Q
Send-Q
Local Address:Port ローカルのホスト or IPアドレス + Port
Peer Address:Port リモートのホスト or IPアドレス + Port
❯ ss | head -n10
Netid   State   Recv-Q   Send-Q                 Local Address:Port   Peer Address:Port
u_str   ESTAB   0         0                                 * 47233              * 47234
u_str   ESTAB   0         0                                 * 45092              * 44080
u_str   ESTAB   0         0                                 * 44587              * 44588
u_str   ESTAB   0         0       /run/systemd/journal/stdout 43268              * 42713
u_str   ESTAB   0         0                                 * 43077              * 44112
u_str   ESTAB   0         0   /var/run/dbus/system_bus_socket 42983              * 44430
u_str   ESTAB   0         0                                 * 53695              * 48964
u_str   ESTAB   0         0                /run/user/1000/bus 45967              * 46626
u_str   ESTAB   0         0                                 * 44351              * 44352
u_str   ESTAB   0         0                                 * 230142             * 230141
u_str   ESTAB   0         0                                 * 44138              * 44139
u_str   ESTAB   0         0                                 * 42390              * 45199
u_str   ESTAB   0         0   /run/containerd/containerd.sock 33779              * 34376
u_str   ESTAB   0         0                                 * 30251              * 30252
icmp6   UNCONN  0         0                                 *:ipv6-icmp          *:*
tcp     ESTAB   0         0                                 192.168.221.129:49716 192.30.253.124:https
tcp     ESTAB   0         0                                 192.168.221.129:40098 35.161.236.240:https
v_str   ESTAB   0         0                                 1081845576:1023 0:976
v_str   ESTAB   0         0                                 1081845576:3128913646 0:976

フィールド2

users プロセス名
プロセスID
ファイルディスクリプタ
timer タイマー名
タイマーの有効期限
再送の発生回数
uid ソケットの属するユーザーID
ino VFSのソケットのinodeの番号
sk ソケットのUUID
skmem r?: パケットを受信するために割り当てられたメモリ
rb?: パケットの受信に割り当てることができる合計のメモリ
t?: パケットを送信するのに使用しているメモリ(レイヤー3へ送信済み)
tb?: パケットの送信に割り当てることができる合計のメモリ
f?: ソケットによってキャッシュとして割り当てられたが、パケットの送受信にはまだ使われていないメモリ
(パケットの送受信にメモリが必要な場合、追加のメモリを割り当てる前にこのキャッシュ内のメモリが使用される)
w?: パケットの送信に割り当てられたメモリ(レイヤー3へ未送信)
o?: ソケットオプションの保存に使用されるメモリ(例えばTCP MD5署名のkey)
bl?: skバックログキューに使用されるメモリ
(プロセスのコンテキストでは、プロセスがパケットを受信しているところで、新たにパケットを受信した際にskバックログキューに入れられ、プロセスは即座に受信することができる)
d?: 生のUDPのドロップカウンターっぽい?
おそらく、この辺この辺
cubic 輻輳のアルゴリズム名が表示される(デフォルトなのでcubic)
rto TCPの再送信タイムアウト値(ミリ秒)
rtt 平均ラウンドトリップタイム(ミリ秒)/ラウンドトリップタイムの平均偏差(ミリ秒)
ato ACKのタイムアウト(ミリ秒)、遅延ACKモードで使用する
mss 最大セグメントサイズ
pmtu パスのMTU値
rcvmss ピアに知らせる最大セグメントサイズ(MTU - 40(TCPヘッダとIPヘッダ分) bytes)
advmss Advertised MSS(適切な和訳がわからなかった)
cwnd 輻輳ウィンドウサイズ
bytes_acked 正常に送信されたバイト数
bytes_received 受信したバイト数
segs_out 送信されたセグメント数
segs_in 受信したセグメント数
data_segs_out RFC4898 tcpEStatsDataSegsOut(tcpi_data_segs_out)
send egressのbps
lastsnd 最後のパケットが送信されてからの時間(ミリ秒)
lastrcv 最後にパケットを受信してからの時間(ミリ秒)
lastack 最後にACKを受信してからの時間(ミリ秒)
pacing_rate ペーシングのレート(bps)/最大ペーシングのレート(bps)
delivery_rate tcp_rate_gen()で測定された最新のgoodput(詳細)値
app_limited ソケットのスループットが送信アプリケーションによって制限されたときにgoodputが測定されたかどうかを示すbool値
busy データを送信中の時間(ミリ秒)
rcv_space 受信バッファのソケットオートチューニングをするヘルパー変数
rcv_ssthresh 受信のスロースタートサイズの閾値(現在のウィンドウクランプ)
minrtt 最小ラウンドトリップタイム
❯ ss -tiepm
State Recv-Q   Send-Q   Local Address:Port    Peer Address:Port
ESTAB 0        0      192.168.221.129:49716 192.30.253.124:https
users:(("firefox",pid=4300,fd=44)) timer:(keepalive,71582min,0) uid:1000 ino:233806 sk:2d4 <->
     skmem:(r0,rb131072,t0,tb87040,f0,w0,o0,bl0,d0) cubic rto:300 rtt:28.715/50.18 ato:40 mss:1460 pmtu:1500 rcvmss:1460 advmss:1460 cwnd:10 bytes_acked:1631 bytes_received:4091 segs_out:20 segs_in:31 data_segs_out:14 data_segs_in:16 send 4.1Mbps lastsnd:17864 lastrcv:17864 lastack:17864 pacing_rate 8.1Mbps delivery_rate 132.7Mbps app_limited rcv_space:14600 rcv_ssthresh:64076 minrtt:0.235
ESTAB  0        0     192.168.221.129:40098 35.161.236.240:https
users:(("firefox",pid=4300,fd=70)) timer:(keepalive,5min42sec,0) uid:1000 ino:88797 sk:2d1 <->
     skmem:(r0,rb131072,t0,tb87040,f0,w0,o0,bl0,d0) cubic rto:204 rtt:0.227/0.044 ato:40 mss:1460 pmtu:1500 rcvmss:1460 advmss:1460 cwnd:10 bytes_acked:10911 bytes_received:12344 segs_out:359 segs_in:552 data_segs_out:274 data_segs_in:277 send 514.5Mbps lastsnd:257984 lastrcv:257984 lastack:257984 pacing_rate 1027.4Mbps delivery_rate 108.1Mbps app_limited busy:80ms rcv_space:14600 rcv_ssthresh:64076 minrtt:0.223

参考

ip

ルーティング、ネットワークデバイス、インターフェイス、トンネルの表示/操作

フィールド

interface name インターフェイス名(lo, ens33)
interface flag UP: インターフェイスが有効である状態
LOWER_UP: イーサネットケーブルが差し込まれ、デバイスがネットワークに接続されている
LOOPBACK: インターフェイスは他のホストと通信を行わない(バウンスされたパケットのみを受信可能)
BROADCAST: 同じリンクを共有するすべてのホストにパケットを送信する機能がある(例: イーサネットリンク)
MULTICAST: マルチキャスト機能が有効
mtu Maximum Transmission Unit
qdisc インターフェイスキューイングアルゴリズム
noqueue: キューに入れない
fq_codel: 詳細
state 状態
mode おそらくLINKモード
DEFAULT or DORMANT
group デバイスグループ(/etc/iproute2/groupに載っているものが指定できる)
qlen デバイスのデフォルトの送信キューの長さ
link リンク(loopback, ethernet)
brd ブロードキャストアドレス
RX bytes: 受信したバイト数の合計
packets: 受信したパケット数の合計
errors: 受信したエラーパケット数の合計
dropped: 受信した際にバッファに空きがなかったりしてドロップしたパケット数の合計
overrun: 受信リングバッファのオーバーフローの合計
mcast: 受信したマルチキャストの合計
TX bytes: 送信したバイト数の合計
packets: 送信したパケット数の合計
errors: 送信した問題のあるパケット数の合計
dropped: 送信したパケットのドロップした回数(レアらしい)
carrier: シグナルの変調に問題があった数の合計(デュプレックスミスマッチとか物理ケーブル/コネクタの問題とか)
collsns: 衝突(コリジョン)した回数
❯ ip -s link
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    RX: bytes  packets  errors  dropped overrun mcast   
    696562     8158     0       0       0       0       
    TX: bytes  packets  errors  dropped carrier collsns 
    696562     8158     0       0       0       0       
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000
    link/ether 00:0c:29:7b:a7:48 brd ff:ff:ff:ff:ff:ff
    RX: bytes  packets  errors  dropped overrun mcast   
    65473200   82427    0       0       0       0       
    TX: bytes  packets  errors  dropped carrier collsns 
    7752597    46923    0       0       0       0       
❯ ip route
default via 192.168.221.2 dev ens33 proto dhcp metric 100 
169.254.0.0/16 dev ens33 scope link metric 1000 
192.168.221.0/24 dev ens33 proto kernel scope link src 192.168.221.129 metric 100 

参考

nstat

カーネルのSNMPカウンターとネットワークインターフェースの統計を確認するシンプルなツール

統計情報の確認

❯ nstat -s
#kernel
IpInReceives                    37402              0.0
IpInAddrErrors                  3                  0.0
# 省略

参考

netstat

ネットワーク接続、経路テーブル、インターフェースの状態、マスカレード接続、 netlink メッセージ、マルチキャストのメンバーシップを表示する

フィールド

Proto ソケットのプロトコル
RefCnt 参照カウント(このソケットに接続されているプロセスの数)
Flags ACC: SO_ACCEPTON(ソケットが接続されておらず、かつそれを用いるプログラムが接続要求を待っている場合に用いられる)
W: SO_WAITDATA
N: SO_NOSPACE
Type ソケットのアクセスタイプ
SOCK_DGRAM: データグラム(connectionsless)モードのソケット
SOCK_STREAM: ストリーム(connection)ソケット
SOCK_RAW: RAWソケット
SOCK_RDM: 信頼性の高いメッセージを届けるソケット
SOCK_SEQPACKET: シーケンシャルパケットのソケット
SOCK_PACKET: RAWインターフェースアクセスのソケット
UNKNOWN: 不明
State FREE: ソケットは割り当てられていない
LISTENING: ソケットは接続要求の待ち状態
CONNECTING: ソケットは接続中の状態
CONNECTED: ソケットは接続状態
DISCONNECTING: ソケットは切断中の状態
空欄: ソケットは他のソケットに接続されていない
UNKNOWN: 基本的に現れない
I-Node inodeの番号
PID/Program name このソケットをオープンしているプロセスID/プロセス名
Path ソケットに結び付けられているプロセスのパス
❯ netstat -anp
稼働中のインターネット接続 (サーバと確立)
Proto 受信-Q 送信-Q 内部アドレス            外部アドレス            状態       PID/Program name    
tcp        0      0 192.168.122.1:53        0.0.0.0:*               LISTEN      -                   
tcp        0      0 127.0.0.53:53           0.0.0.0:*               LISTEN      -                   
tcp        0      0 127.0.0.1:631           0.0.0.0:*               LISTEN      -                   
tcp        0      0 192.168.221.129:42142   13.35.67.43:443         ESTABLISHED 8601/firefox        
tcp        0      0 192.168.221.129:42340   99.84.55.56:443         TIME_WAIT   -                   
tcp        0      0 192.168.221.129:53566   172.217.25.206:443      ESTABLISHED 8601/firefox        
tcp        0      0 192.168.221.129:45744   107.178.248.96:443      ESTABLISHED 8601/firefox        
tcp        0      0 192.168.221.129:47086   104.107.111.107:443     ESTABLISHED 8601/firefox
# 省略
稼働中のUNIXドメインソケット (サーバと確立)
Proto RefCnt Flags       Type       State         I-Node   PID/Program name     パス
unix  2      [ ]         DGRAM                    31499    -                    /var/spool/postfix/dev/log
unix  2      [ ACC ]     STREAM     LISTENING     41813    2880/gnome-session-  @/tmp/.ICE-unix/2880
unix  2      [ ]         DGRAM                    43395    2859/systemd         /run/user/1000/systemd/notify
unix  2      [ ACC ]     SEQPACKET  LISTENING     25863    -                    /run/udev/control
unix  2      [ ACC ]     STREAM     LISTENING     43398    2859/systemd         /run/user/1000/systemd/private
unix  2      [ ACC ]     STREAM     LISTENING     43402    2859/systemd         /run/user/1000/gnupg/S.gpg-agent.ssh
unix  2      [ ACC ]     STREAM     LISTENING     43403    2859/systemd         /run/user/1000/gnupg/S.dirmngr
unix  2      [ ACC ]     STREAM     LISTENING     43404    2859/systemd         /run/user/1000/gnupg/S.gpg-agent.browser
unix  2      [ ACC ]     STREAM     LISTENING     43405    2859/systemd         /run/user/1000/snapd-session-agent.socket
❯ netstat -s
Ip:
    Forwarding: 1
    15127 total packets received
    3 with invalid addresses
    0 forwarded
    0 incoming packets discarded
    15122 incoming packets delivered
    14728 requests sent out
Icmp:
    1 ICMP messages received
    0 input ICMP message failed
    ICMP入力ヒストグラム:
        echo requests: 1
    4 ICMP messages sent
    0 ICMP messages failed
    ICMP出力ヒストグラム:
        destination unreachable: 3
        echo replies: 1
IcmpMsg:
        InType8: 1
        OutType0: 1
        OutType3: 3
Tcp:
    53 active connection openings
    0 passive connection openings
    2 failed connection attempts
    3 connection resets received
    0 connections established
    14109 segments received
    13845 segments sent out
    3 segments retransmitted
    0 bad segments received
    15 resets sent
Udp:
    954 packets received
    3 packets to unknown port received
    0 packet receive errors
    872 packets sent
    0 receive buffer errors
    0 send buffer errors
    IgnoredMulti: 57

参考

nicstat

パケット、キロバイト/秒、平均パケットサイズなど、すべてのNICのネットワーク統計を出力する

フィールド

Time 時間(HH:MM:SS)
Int インターフェイス名
rKB/s キロバイト/秒の読み取り(受信)
wKB/s キロバイト/秒の書き込み(送信)
rPk/s パケット(TCP Segments, UDP Datagrams)/秒の読み取り(受信)
wPk/s パケット(TCP Segments, UDP Datagrams)/秒の書き込み(送信)
rAvs 読み取りのパケットの平均サイズ(受信)
wAvs 書き込みのパケットの平均サイズ(送信)
%Util インターフェイスの使用率
Sat 飽和(Saturation)/インターフェイスのエラー/秒の数
❯ nicstat
    Time      Int   rKB/s   wKB/s   rPk/s   wPk/s    rAvs    wAvs %Util    Sat
01:02:50    ens33   27.27    0.31   19.31    4.04  1446.1   78.08  0.02   0.00
01:02:50       lo    0.02    0.02    0.19    0.19   87.71   87.71  0.00   0.00

ethtool

ネットワークドライバーとハードウェア設定のクエリもしくはコントロール

-Sでデバイスの統計情報の確認

❯ ethtool -S ens33
NIC statistics:
     rx_packets: 82901
     tx_packets: 17923
     rx_bytes: 119175472
     tx_bytes: 1435399
     rx_broadcast: 0
     tx_broadcast: 0
     rx_multicast: 0
     tx_multicast: 0
     rx_errors: 0
     tx_errors: 0
     tx_dropped: 0
     multicast: 0
     collisions: 0
     rx_length_errors: 0
     rx_over_errors: 0
     rx_crc_errors: 0
     rx_frame_errors: 0
     rx_no_buffer_count: 0
     rx_missed_errors: 0
     tx_aborted_errors: 0
     tx_carrier_errors: 0
     tx_fifo_errors: 0
     tx_heartbeat_errors: 0
     tx_window_errors: 0
     tx_abort_late_coll: 0
     tx_deferred_ok: 0
     tx_single_coll_ok: 0
     tx_multi_coll_ok: 0
     tx_timeout_count: 0
     tx_restart_queue: 0
     rx_long_length_errors: 0
     rx_short_length_errors: 0
     rx_align_errors: 0
     tx_tcp_seg_good: 15
     tx_tcp_seg_failed: 0
     rx_flow_control_xon: 0
     rx_flow_control_xoff: 0
     tx_flow_control_xon: 0
     tx_flow_control_xoff: 0
     rx_long_byte_count: 119175472
     rx_csum_offload_good: 82844
     rx_csum_offload_errors: 0
     alloc_rx_buff_failed: 0
     tx_smbus: 0
     rx_smbus: 0
     dropped_smbus: 0

-iでドライバーの詳細の表示

❯ ethtool -i ens33
driver: e1000
version: 7.3.21-k8-NAPI
firmware-version: 
expansion-rom-version: 
bus-info: 0000:02:01.0
supports-statistics: yes
supports-test: yes
supports-eeprom-access: yes
supports-register-dump: yes
supports-priv-flags: no