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
参考
- Linux Advanced Routing & Traffic Control HOWTO
- Queueing in the Linux Network Stack
- Linuxカーネルの新機能 XDP (eXpress Data Path) を触ってみる
- eXpress Data Path (XDP) の概要とLINEにおける利活用 / Brief summary of XDP and use-case at LINE
- The eXpress data path: fast programmable packet processing in the operating system kernel
ネットワークのパフォーマンス分析
- ネットワークの統計情報を確認する
パケットレート/スループット、およびTCP接続がある場合はTCPの接続/再送信のレート
ss
/nstat
/netstat
/sar
- TCP接続の特徴を観測し、非効率部分を探す
tcplife
- ネットワークインタフェースのスループット制限に達しているかを確認する
sar
/nicstat
- TCPの再送信やドロップなどの異常なTCPイベントをトレースする
tcpretrans
/tcpdrop
/skb:kfree_skb tracepoint
- DNSの名前解決の遅延を測定する
gethostlatency
- コネクションの遅延、TTFBの遅延、スタックの遅延など様々な箇所からネットワークの遅延状況を測定する
- bufferbloatなど負荷によって遅延時間を大きく変化するので注意すること
- 負荷生成ツールでホスト間のネットワークスループットを調べて既知のワークロードに対するネットワークイベントを調べる
iperf
/netperf
- bpftoolを使用する
- カーネルのスタックトレースのCPUプロファイリングを使用して、プロトコルおよびドライバーの処理に費やされるCPU時間を定量化する
- トレースポイントと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
参考
- Detailed output of ss command
- shemminger/iproute2/misc/ss.c
- 世界最速通信で考えるインターネットの将来
- パケットペーシングについて
- What is the difference between throughput & goodput?
- TCP_INFOvsWeb100Web10g
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
参考
- IP Command Reference
- Ubuntu Manpage: netdevice - Linux ネットワークデバイスへの低レベルアクセス
- Ubuntu Manpage: ip-link - network device configuration
- tc-fq_codel(8) - Linux manual page - man7.org
- linux/if_link.h at master · torvalds/linux
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