4/27 (土)
ヨコハマフリューリングスフェスト2013@横浜赤レンガ
YOKOHAMA FRÜHLINGSFEST2013 が横浜赤レンガで開催された。 Frühlingsfest はドイツのお祭りらしい。 オクトーバーフェストをこの時期からやるのは変だと思い名前を変えたのだろう。 結局、日本各地で開催されている「オクトーバフェスト」とほとんど同形式で、出展店も被っている。
Flamm(炎) Kuchen(お菓子)はピザである。 でも正直ピザのほうが美味しい。
4/21 (日)
[Movie] STEINS;GATE 負荷領域のデジャヴ
川崎 TOHO シネマズで STEINS;GATE 劇場版 を観てきた。 川崎で上映しているのが TOHO シネマズだけということもあり、定員が 500人の箱が満員になる。 17:30 からの鑑賞したが、周囲の客層が普段と全然違うのに戸惑う。
4/20 (土)
[時事] 中国四川で M7.0 の地震
イランに続き、今度は中国で。 四川省雅安市蘆山県で現地時間8時2分(日本時間の9時2分)に M 7.0 の地震が発生。
四川省では5年前の2008年5月12日にも M8.0 の地震が発生している。
4/18 (木)
[MyWeb] OpenSSL と OpenSSH のバージョンアップ
脆弱性に対するセキュリティアドバイザリがでていたので、自サーバの OpenSSL と OpenSSH を openssl-1.0.1e と openssh-6.2p1 にアップデートした。
先に OpenSSL をアップデートしてから、OpenSSH をインストール。
OpenSSH のインストール手順は以下の通り。
$ ./configure --with-tcp-wrappers --with-pam --with-ssl-dir=/usr/local/ssl --sysconfdir=/etc/ssh $ make # make install-nosysconf
最後のインストールは make install
、make install-nokeys
、make install-nosysconf
が選択できる。
すでに設定ファイルの配置やホストキーが存在しているなら、make install-nokeys
、make install-nosysconf
を使えば、設定ファイルやホストキーの生成を飛ばすことができる。
4/16 (火)
[時事] イラン南東部地震・パキスタン南西部で M 7.8
イラン南東部で現地時間の15時14分(日本時間7時44分)に M 7.8 (報道によっては M8) の地震が発生。 BBC NEWSの地図が見易い。
イランと周辺国で被害多数。 遠くドバイも揺れたそうだ。
4/14 (日)
[Movie] シュガー・ラッシュ
川崎ラゾーナ 109 シネマで3月23日に引き続き「シュガー・ラッシュ」の2回目を見てきた。 IMAX 上映を期待したのだが MASTERIMAGE3D 方式だった。
あらためて見直すと、版権もののゲームのキャラクタが大量に登場して大変そうな映画だ。 その上ナビスコの「オレオ」とかシュークリームの「ビアードパパ」とかまで出てくる。 というかこの映画を観た後の調べて、初めてビアードパパが海外展開していたことを知った。
4/13 (土)
第八回 カーネル/VM探検隊
第八回 カーネル/VM探検隊に参加してきた。
その中で聞いた Linux の ftrace 機構で CPU 毎のコンテキストスイッチの情報がとれるかどうか気になったので試してみる。
まず debugfs を導入して、tracing/available_tracers 以下を確認。
# mount -t debugfs nodev /sys/kernel/debug # cat /sys/kernel/debug/tracing/available_tracers blk kmemtrace function_graph wakeup_rt wakeup function sysprof sched_switch initcall nop
sched_switch トレーサーがそれのようだ。 有効化する。
# echo sched_switch > /sys/kernel/debug/tracing/current_tracer
/sys/kernel/debug/tracing/per_cpu/cpu0/trace の内容を表示すると表示される。
# tracer: sched_switch # # TASK-PID CPU# TIMESTAMP FUNCTION # | | | | | <...>-48497 [000] 303960.341351: 48497:120:S + [000] 48497:120:S <...> <...>-48497 [000] 303960.341369: 48497:120:S ==> [000] 0:120:R <idle> <idle>-0 [000] 303960.350952: 0:120:R + [000] 11:120:R events/0 <idle>-0 [000] 303960.350974: 0:120:R ==> [000] 11:120:R events/0 events/0-11 [000] 303960.350980: 11:120:R + [000] 48466:120:R <...> events/0-11 [000] 303960.350983: 11:120:S ==> [000] 48466:120:R <...> <...>-48466 [000] 303960.351317: 48466:120:S ==> [000] 0:120:R <idle> <idle>-0 [000] 303960.440904: 0:120:R + [000] 11:120:R events/0 <idle>-0 [000] 303960.440915: 0:120:R ==> [000] 11:120:R events/0 events/0-11 [000] 303960.442042: 11:120:S ==> [000] 0:120:R <idle> <idle>-0 [000] 303960.540875: 0:120:R + [000] 2518:120:R cimserver <idle>-0 [000] 303960.541003: 0:120:R ==> [000] 2518:120:R cimserver cimserver-2518 [000] 303960.541025: 2518:120:S ==> [000] 0:120:R <idle> <idle>-0 [000] 303960.680850: 0:120:R + [000] 11:120:R events/0 <idle>-0 [000] 303960.680854: 0:120:R + [000] 664:120:R vmmemctl <idle>-0 [000] 303960.680868: 0:120:R ==> [000] 664:120:R vmmemctl vmmemctl-664 [000] 303960.680881: 664:120:S ==> [000] 11:120:R events/0
採れているよう見える。
4/10 (水)
[Prog] InfiniBand の Unreliable Datagram(UD)
これまでずっと Relaiable Connection(RC) を使ってきたが、Unreliable Datagram(UD) の調査もはじめる。 RC が TCP 的な到達保証がある1対1の通信なら、UD は UDP 的な到達保証がない多対多の通信である。
- 送信側 QP は
ibv_post_send
毎に送信先を指定できる。- 送信先となる LID は
ibv_create_ah
で作成する address handle で指定する。 - QPN は
ibv_post_send
時に直接指定する。
- 送信先となる LID は
- 受信側 QP は複数の QP からのメッセージを受信する。送信元を示す LID と QPN がもらえる(RC 通信は LID のチェックが、QPN は未チェックでかつどの QPN から来たのか分からない)。
- 受信側 QP に Q_Key という 32 ビットのキー値を設定する。送信側は
ibv_post_send
に受信側の Q_Key を指定し、これが一致しないとメッセージは受信側で勝手に破棄される。 - 到達保証がない。送信側は Local Error Detection にさえ引っかからなければ、送信成功として CQ に Work Completion が積まれる。実際にメッセージが受信側に届くのを待たない。
- 受信データの先頭 40 バイトは Global Routing Header (GRH) が入る。
これは Work Completion の
wc_flags
に IBV_WC_GRH が立っている時にセットされる。 IBV_WC_GRH が立っていない場合でも 40 バイトに何が書き込まれるか不定である。 ただし Mellanox の HCA では 40 バイトはスキップされて何も書かれない。
4/9 (火)
TCP の選択的確認応答(Selective-ACK; SACK)
TCP/IP には Selective Acknowledgement Options があるとのこと。
@nminoru_jp いいかげん知識なんですがTCPはselective-ACKがオプションでありNAK相当かとおもいます。(うそかもしれません)
— 鯉江さん (@koie) 2013年4月9日
SYN パケットのオプションの中に TCP Sack-Permitted Option (TCPOPT_SACK_PERMITTED)を含めると、すでに受信した領域のリストを送ることで未受信のデータを申告できるようになる。 これは TCP パケットのオプション部に TCPOPT_SACK オプションで入っている。 TCP スタックとしては TCPOPT_SACK オプションを無視しても通信が成立するが、未受信部分だけを送信することで無駄な再送を防ぐことが可能だ。
InfiniBand の NACK(Negative ACK) との対比で言えば、
- InfiniBand の RC 通信はデータの真ん中のパケットがロストした場合でも、抜けた部分だけを再送してもらう機構にはなっていない。
- InfiniBand の NAK は受信側のバッファが不足していることを通知することができるが、TCP SACK ではできないだろう。
参考
4/8 (月)
[Prog] InfiniBand RC 通信の再送の仕組み
Figure 115 Requester /Responder Error Detection

InfiniBand の RC(Reliable Connection) 通信は送信に失敗した場合、タイマーによって再送を行う。 ただしこの仕組みは IB Verbs のマニュアルを読んでも分からず、InfiniBand Trade Association の仕様書を丹念に読まないと理解できないので、ここにメモを残しておく。
右にある Figure 115 は InfiniBand Architecture Specification Volume 1 Release 1.2.1 からの抜粋である。 RC 通信のエラーはこの図を元に考えると理解し易い。
RC 通信はエラー検知の方法から見ると、送信側(requester)の内部で検知する(1. 2.)、受信側(responder)に届かない(3.)、受信側が NAK(Negative ACK) を返す(4.)と大きく 3 種類に分かれる。 ただし受信側が NAK を返す時に、RNR(Receiver Not Ready) NAK という特別な NAK を返すことがあり、これは別扱いとなる。
- 送信側(requester)の Send Queue に送信の処理要求(Work Request; WR)が WQE(Work Queue Elements) 数の上限まで滞在し、新規の送信 WR を登録できない。この場合、
ibv_post_send
は -1 で復帰し、errno が ENOMEM になり失敗する。
右図で言うと Send Queue のに挿入位置で折り返している。 - 送信側(requester)に送信できない要因がある。例えば送信側の QP が IBV_QPS_ERR だったりする。この場合、WR は失敗し Completion Queue にエラーとして載る。エラーは
ibv_poll_cq
で取得できる。
右図で言うと requester の Local Error Detection によって検出されている。
- 送信側(requester)から受信側(responder)の間にある InfiniBand ネットワークに問題があり、パケットが受信側(responder)の届かない。この場合、ACK も NAK(Negative ACK) も返ってこない。この場合、送信側の Local ACK Timeout の再送制御がはたらく。
- 受信側(responder)に届いても、受信側 QP の準備ができていなければ(例えば QP が IBV_QPS_ERR であれば)、InfiniBand ネットワーク不通と同じ扱いである。
- 受信側(responder)がパケットを受理したが、条件の不一致によって silently drop すると、これも InfiniBand ネットワーク不通と同じ扱いである。
- 受信側(responder)がパケットを受理したが、R_Key の不一致、受信したデータに対して Receive Queue の受信バッファのサイズが小さいなどの問題があると、受信側から送信側(requester)に NAK が返る。この場合、NAK を受理した送信側は Local ACK Timeout の再送制御がはたらく。
- 受信側(responder)がパケットを受理したが、Receive Queue の受信バッファが枯渇した場合には、受信側から送信側(requester)に RNR NAK が返る。この場合、RNR NAK を受理した送信側は RNR NAK Timer を働かせる。
Local ACK Timeout
QP に設定する timeout
(Local ACK Timeout) と retry_cnt
(Retry count) で設定する。
QP からメッセージ送信後にタイマー時間内に ACK が返って来ない場合には、再送が行われる。
タイマー時間が経過する度に retry_cnt
が減算され、これがマイナスになるとタイムアウトで送信の Work Request は エラー(IBV_WC_RETRY_EXC_ERR)となる。
retry_cnt
は 3 ビットカウンターで 0〜7 が指定できる。

もし retry_cnt
が 0 の場合は 1 回だけ送信し、タイマー時間だけ待って ACK が返ってこなければタイムアウトする。

タイマー時間は timeout
で決まる。
これは 5 ビットのカウンタで、1回のタイマー間隔を Ttr = 4.096 us * 2timeout で指定する。
ただし仕様上、タイマー時間は誤差を許容しており Ttr 〜 4 * Ttr であればよい。
また仕様上、HCA によって最低分解能を決めることができ、小さなタイマー時間を指定しても有効にならない。
0.1秒以下の精度があると考えてはいけない。
timeout
に 0 を指定した場合はタイマーは無効(再送時間無限)になり、再送が発生しなくなる。
ただしタイムアウトも起きないので、Send Queue の中で WQE は留まり、ibv_poll_cq
で CQE が返ってくることもない。
|
|
minimum RNR NAK Timer
RC 通信は Local ACK Timeout で再送制御を行うが、RNR(Receiver Not Ready) NAK だけは RNR NAK Timer でタイムアウト制御がしている。
RNR NAK は、RC のメッセージが受信側に届いた時に、Receive Queue の WQE が枯渇している時に送信側に返される特別な NAK である。
送信側は RNR NAK が来た場合のみ minimum RNR NAK Timer 時間だけ待って、再送を試みる。
その間に受信側が ibv_post_recv
で WQE を積んでいれば、RC メッセージの送信は成功する。
minimum RNR NAK Timer 時間は min_rnr_timer
が決定する。
min_rnr_timer
は 5 ビットの値で、各値のタイマー時間は下記の表のように決められている。
Local ACK Timeout と異なり min_rnr_timer
が 0 の場合は無効ではない。
HCA によっては Local ACK Timeout のタイマー時間はいい加減だが、minimum RNR NAK Timer のタイマー時間はそれよりは正確である。
|
|
再送回数は rnr_retry
が決める。
このパラメータは 3 ビットで 0〜7 を指定できる。
送信側が RNR NAK を受け取る度に rnr_retry
が減算して行き、0 の時にさらに RNR NAK を受けると、送信の Work Request はエラー(IBV_WC_RNR_RETRY_EXC_ERR)となる(タイマーの数え方は Local ACK Timeout の図と同じ)。
ただし rnr_retry
が 7 は特別値で、この場合は何回 RNR NAK を受けても無限に再送を繰り返すようになる。
追記:2013/10/11
Local ACK Timeout の精度は HCA が自己報告をしている。
ibv_query_device
が返すデバイス属性の中に local_ca_ack_delay
というメンバ変数があり、timeout
に設定できる最小の有効値が入っているようだ。
local_ca_ack_delay
はプログラムを書かなくても ibv_devinfo コマンドを使えば表示できる。
# ibv_devinfo -v | grep grep local_ca_ack_delay local_ca_ack_delay: 15
4/5 (金)
[MyWeb] Twitter ボタンを修正
この日記につけているTwitterボタンだが、いつのまにかイメージリンクがテキストリンクに変わって、個別の日付の日記のツイートができなくなっていた。 この HTML は ISO-2022-JP で書かれているが、Twitter ボタンの JavaScript が ISO-2022-JP 対応を止めたようだ。
いい加減 HTML を UTF-8 に変更すべきかもしれないが、とりあえず文字コードを変換するリダイレクションページを挟んで応急処置とする。
4/4 (木)
[Food] DB's-KITCHEN@武蔵中原
会社の近くにできたインド・ネパール・アジアンレストランに行ってみた。 グリルセットが980円で、カレーが2種類とタンドリーチキンとシークカバブがつくのでとってもお徳。 でもなぜか味噌汁がついてきた。 Why?
4/3 (水)
[Linux] 最近追加された prctl の機能
プロセスの特殊な機能を操作するために用意された prctl
が、Linux カーネルのアップデートのために増えてゆく。
英語のマニュアルは機能追加に追従しているが、日本語訳には載っていない機能があるのでまとめておく。
prctl
のプロトタイプ宣言は以下のようになっている。
#include <sys/prctl.h> int prctl(int option, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5);
Child Subreaper
この機能は [PATCH] prctl: add PR_{SET,GET}_CHILD_SUBREAPER to allow simple process supervision へ対応したもの。 プロセスがデーモン化する場合、親プロセスとの対応関係が切れて PID 1 の init プロセスの養子となることになる。 そのためデーモンプロセスに対しては、その死活監視を行って必要とあればプロセスを立ち上げ直すようなサービスマネージャを作る場合、子プロセスが死亡した場合に親プロセスに送られる SIGCHLD シグナルを使うことができない。
この prctl を呼び出したプロセスは、そのプロセスの子孫のプロセスが孤児(orphaned)になった時に、init(1) の代わりに SIGCHLD の送り先になってくる。
- PR_SET_CHILD_SUBREAPER (since Linux 3.4)
-
arg2 が非 0 の場合、 呼び出しプロセスの "child subreaper" 属性を設定する。
arg2 が 0 の場合は、"child subreaper" 属性を解除する。
プロセスが child subreaper と設定されている場合、そのプロセスが作った全ての子プロセスとそれ以降の祖先も「subreaper を持っている」と設定される。
この効果は、subreaper 設定されたプロセスは、その祖先プロセスに対して init(1) のような役目を果たす。 「subreaper を持っている」孤児(orphaned)のプロセスが終了した場合に、init(1) ではなく、もっとも近い subreaper プロセスに SIGCHLD が送信され、そのプロセスは wait(2) で終了ステータスを 取得できるようになる。 - PR_GET_CHILD_SUBREAPER (since Linux 3.4)
- arg2 には int 型のポインタを渡と、これを呼び出したプロセスが "child subreaper" かどうかを格納して返す。
No New Priviledge
execve で新しいプログラムを走行させる時に、親プロセスが持っていない権限(privileges)が付与される場合がある。 例えば setuid/setguid プログラムや file capabilities である。 このため親プログラムが子プログラムの拡張された権限を奪取できないような工夫がされている。
Linux 3.5 から no_new_privs bit が設けられ、これを有効にした場合には execve で親プロセスの持たない権限を拡張することが禁止される。 例えば setuid や setgid がプログラムについていても、uid や gid は変わらない。
no_new_privs bit の設定は以下のように行う。
prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
- PR_SET_NO_NEW_PRIVS (since Linux 3.5)
- 呼び出しプロセスの no_new_privs bit を arg2 に設定する。 no_new_privs bit に 1 を設定すると、privilege-restricting mode となる。 1 度 no_new_privs bit を立てると、0 に戻すことはできない。 この設定は fork(2)、clone(2)、execve(2) で作成した子プロセスにも継承される。
- PR_GET_NO_NEW_PRIVS (since Linux 3.5)
- 呼び出しプロセスの no_new_privs bit を返す。 0 ならデフォルトの execve(2) の動作である。 1 なら execve(2) は privilege-restricting mode で動作する。
ptrace を許可する PID を指定
PR_SET_PTRACER は ptrace を実行できるプロセスを限定する。 Yama LSM(Linux Security Module) が有効で、mode 1 ("restricted ptrace"、/proc/sys/kernel/yama/ptrace_scope で確認できる) の場合のみ意味がある。
- PR_SET_PTRACER (since Linux 3.4)
-
arg2 に "ptracer process ID" を渡して呼び出すと、呼び出しプロセスは "ptracer process ID" からのみ ptrace(2) を実行できるようになる。
また PR_SET_PTRACER を呼び出したプロセスの子孫も "ptracer process ID" の適用を受ける。
PR_SET_PTRACER を 2 度以上呼び出すと、最新の呼び出しの arg2 が "ptracer process ID" となる。 また arg2 に 0 を設定すると "ptracer process ID" はクリアされる。 arg2 に PR_SET_PTRACER_ANY を指定すると、どのプロセスからでも ptrace が可能になる。
Timer slack
タイマーを指定するシステムコールに対して「遊び」を指定する。 複数のタイマーの発火タイミングが「遊び」の範囲にある場合、タイマーをまとめて1回の発火で処理することで CPU の起動を抑えて電力消費を抑える。
Timer slack の効果があるのは、select(2)、pselect(2)、poll(2)、ppoll(2)、epoll_wait(2)、poll_pwait(2)、clock_nanosleep(2)、nanosleep(2)、futex(2) である。 futex が内部実装として使われるライブラリ関数 pthread_cond_timedwait(3)、pthread_mutex_timedlock(3)、pthread_rwlock_timedrdlock(3)、pthread_rwlock_timedwrlock(3)、sem_timedwait(3) なども影響範囲となる。
Timer slack は realtime scheduling policy の制御化のスレッドには影響を与えない。
Timer slack 値は新しいスレッドを作成した場合にも継承される。 execve(2) でも変わらない。 デフォルトの timer slack 値は、init (PID 1) の子孫では、50,000 nanoseconds (50 microseconds) となる。
- PR_SET_TIMERSLACK (since Linux 2.6.28)
-
arg2 で指定されたナノ秒を呼び出しスレッドの現在の timer slack 値として設定する。
arg2 が 0 以下の場合は、スレッドの timer slack 値はデフォルトの値にリセットされる。
- PR_GET_TIMERSLACK (since Linux 2.6.28)
- 呼び出しスレッドの現在の timer slack 値を戻り値として返す。