カーネルモジュールことはじめ #9
だいぶ間があいてしまいましたが、気を取り直して再開します。「カーネルモジュールことはじめ」といいつつIPVSに偏ったネタばかりですが気にせずに進めます。今日は、こないだ書いたコード を見ながらIPVSの挙動を少しだけ追ってみたいと思います。
IPVSに新しいスケジューラを登録するには、module_init() で指定した初期化関数の中で、register_ip_vs_scheduler() を使います。登録用のエントリとして利用する ip_vs_scheduler 構造体は、include/net/ip_vs.h で以下のように定義されています。
/* * The scheduler object */ struct ip_vs_scheduler { struct list_head n_list; /* d-linked list head */ char *name; /* scheduler name */ atomic_t refcnt; /* reference counter */ struct module *module; /* THIS_MODULE/NULL */ /* scheduler initializing service */ int (*init_service)(struct ip_vs_service *svc); /* scheduling service finish */ int (*done_service)(struct ip_vs_service *svc); /* scheduler updating service */ int (*update_service)(struct ip_vs_service *svc); /* selecting a server from the given service */ struct ip_vs_dest* (*schedule)(struct ip_vs_service *svc, const struct sk_buff *skb); };
この構造体では、以下のメンバに関数ポインタを指定します。
- init_service
- done_service
- update_service
- schedule
今回は、これらの関数がどのタイミングで実行されるのかを調べてみます。こないだ書いたコードでは、それぞれの関数の中から IP_VS_DBG() を呼んでいます。これは、/proc/sys/net/ipv4/vs/debug_level で指定されたデバッグレベル未満のメッセージをカーネルログに出力するものです。ここでは、IP_VS_DBG(7,"") としているので、デバッグレベルを 8に設定します。
# sysctl -w net.ipv4.vs.debug_level=8
そして、ログを眺めながら以下の操作をやってみます
- モジュールをロード
- 仮想サービスを追加
- リアルサーバを追加
- 仮想サービスへ接続
- リアルサーバを削除
- 仮想サービスを削除
# modprobe ip_vs_test # ipvsadm -A -t 10.0.0.1:80 -s test kernel: IPVS: ip_vs_sched_getbyname(): sched_name "test" kernel: IPVS: ip_vs_test: init_svc # ipvsadm -a -t 10.0.0.1:80 -r 192.168.0.1:80 kernel: Enter: ip_vs_add_dest, net/ipv4/ipvs/ip_vs_ctl.c line 780 kernel: Enter: ip_vs_new_dest, net/ipv4/ipvs/ip_vs_ctl.c line 732 kernel: Leave: ip_vs_new_dest, net/ipv4/ipvs/ip_vs_ctl.c line 764 kernel: IPVS: ip_vs_test: update_svc kernel: Leave: ip_vs_add_dest, net/ipv4/ipvs/ip_vs_ctl.c line 869 # telnet 10.0.0.1 80 kernel: IPVS: Bind-dest TCP c:10.211.55.5:2892 v:10.0.0.1:80 d:192.168.0.1:80 fwd:R s:0 conn->flags:183 conn->refcnt:1 dest->refcnt:2 kernel: IPVS: Schedule fwd:R c:10.211.55.5:2892 v:10.0.0.1:80 d:192.168.0.1:80 conn->flags:1C3 conn->refcnt:2 kernel: IPVS: TCP input [S...] 192.168.0.1:80->10.211.55.5:2892 state: NONE->SYN_RECV conn->refcnt:2 kernel: IPVS: Unbind-dest TCP c:10.211.55.5:2892 v:10.0.0.1:80 d:192.168.0.1:80 fwd:R s:3 conn->flags:183 conn->refcnt:1 dest->refcnt:2 # ipvsadm -d -t 10.0.0.1:80 -r 192.168.0.1:80 kernel: Enter: ip_vs_del_dest, net/ipv4/ipvs/ip_vs_ctl.c line 997 kernel: IPVS: ip_vs_test: update_svc kernel: Leave: ip_vs_del_dest, net/ipv4/ipvs/ip_vs_ctl.c line 1024 # ipvsadm -D -t 10.0.0.1:80 kernel: IPVS: ip_vs_test: done_svc
今日のまとめ
init_service
仮想サービスを追加するときに呼び出されます(ipvsadm -A)
done_service
仮想サービスを削除するときに呼び出されます(ipvsadm -D)
update_service
リアルサーバを追加するときに呼び出されます(ipvsadm -a)
リアルサーバを削除するときに呼び出されます(ipvsadm -d)
schedule
仮想サービスへ接続されたときに呼び出されます