Thursday, January 17, 2013

sysctl.confのtokenにピリオドを使いたい

最近、LVS(UltraMonkey)の設定をしていた時に気付いたことがあったのでメモ。
この時は、事情でVLAN なインタフェース(例: eth0.123)にをつかって、LVSの DR(Direct Route)モードで設定を行う必要があった。

この場合、振り分け先のサーバ(ldirectord.cf の real= 行に記述するサーバ。いわゆる「リアルサーバ」)上に lo:0 にも /32 で VIP を設定する必要がある。
これに伴い、lo:0 が持っている VIP への ARP リクエストを無視させる/ARPを出す時にVIPを使わないように制限する必要があるので、
/etc/sysctl.conf 
に、例えばこんな感じの設定を行う必要がある。
net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.eth0.arp_ignore = 1
net.ipv4.conf.all.arp_announce = 2
net.ipv4.conf.eth0.arp_announce = 2
参考情報としては、例えば


の「Real Servers」あたりを参照のこと。

さて、ここからが本題である。
上記の eth0 の部分が、VLAN 123 に対応するインタフェースで eth0.123 だったらどうなるか?

そのまま書いてしまうと、token の部分の要素のセパレータの . (ピリオド)と、eth0 と VLAN番号の間の . (ピリオド)が被っているので /proc/sys 以下にマッピングされるときに、

net.ipv4.conf.eth0.123.arp_ignore

なら

/proc/sys/net/ipv4/conf/eth0/123/arp_ignore 

と変換されてしまい、エラーになる。クォートもできないようだ。

そこで、man  sysctl を良く読んでみると、
SYSCTL(8)                    System Administration                   SYSCTL(8)
NAME
       sysctl - configure kernel parameters at runtime
SYNOPSIS
       sysctl  [options] [variable[=value]] [...]   sysctl -p [file or regexp]
       [...]
DESCRIPTION
       sysctl is used to modify kernel parameters at runtime.  The  parameters
       available  are  those  listed under /proc/sys/.  Procfs is required for
       sysctl support in Linux.  You can use sysctl to  both  read  and  write
       sysctl data.
PARAMETERS
       variable
              The  name  of  a key to read from.  An example is kernel.ostype.
              The '/' separator is also accepted in place of a '.'.

と書いてある。特に最後の赤字で強調した行に注目。
全体としてどういう仕様になるのか、いまいちあいまいなのだが、とにかく . (ピリオド)の代わりに / (スラッシュ)も使えるように見える。

実際やってみると、上記のパターンであれば、
net.ipv4.conf.all.arp_ignore = 1
net/ipv4/conf/eth0.1110/arp_ignore = 1
net.ipv4.conf.all.arp_announce = 2
net/ipv4/conf/eth0.1110/arp_announce = 2
の2行目と4行目のように書いてやればよく、挙動としては、最初にあらわれた / (スラッシュ)か . (ピリオド)が、トークンの部分の要素のセパレータとして使われる。…ので、上記は正常に反映できるし、これは行ごとにばらばらでよい。

余談だが、sysctl は(Ubuntuでは) procps パッケージに含まれており、当該部分の処理は、sysctl.c の
 73 static void slashdot(char *restrict p, char old, char new)
 74 {
 75         int warned = 1;
 76         p = strpbrk(p, "/.");
 77         if (!p)
 78                 /* nothing -- can't be, but oh well */
 79                 return;
 80         if (*p == new)
の 76行目で strpbrk(3)関数に "/."  (スラッシュとピリオド)を渡しているところが対応する。
(procps のバージョンは 1:3.3.3-2ubuntu3)

実は、strpbrk なんて初めて知ったのだが、man してみると以下の通り。
STRPBRK(3)                 Linux Programmer's Manual                STRPBRK(3)
NAME
       strpbrk - search a string for any of a set of characters
SYNOPSIS
       #include <string.h>
       char *strpbrk(const char *s, const char *accept);
DESCRIPTION
       The  strpbrk() function locates the first occurrence in the string s of
       any of the characters in the string accept.
  :
第2引数の文字列に含まれる任意の文字が、第一引数に渡した文字列中に最初にあらわれる位置を返す…と。
いや、Cの標準ライブラリも奥が深いですね...

No comments:

Post a Comment