Userland PPPoEの問題点

http://www.jraitala.net/comp/articles/2002/pppoe/ などで 触れられているが、OpenBSDのPPPoE (Point to Point Protocol over Ethernet)は、 ユーザランドで実行されており、あまり効率がよくない。 というか、他のOSと比べてもダントツにパフォーマンスがよくない。

うちの環境でも、ADSL (FLETS ADSL 8M)自体は下りで7Mbps台でリンクアップ しているのだが、実行スループットは1M弱。もったいない。

2ちゃんねるの「OpenBSDユーザーコーナー」で、 OpenBSD用のin-kernel PPPoE (カーネルモードで動作するPPPoEドライバ)が紹介 されていたので試してみる。
http://www.pro-bono-publico.de/openbsd/pppoe/

パッチを試してみる

上記サイトよりパッチをダウンロードし同梱のドキュメントに従い、

  1. カーネルと関連コマンドにパッチ適用
  2. リビルド
  3. リブート
  4. NetBSDのドキュメントを参考にifconfig, pppoectlコマンドなどでi/f設定→接続

なので、ネイティブなUserland実装の2倍以上のスループットが得られる。

対応していないネットワークコマンドを発行すると、ハングアップ。
あるサイトのオープンポートを調べる目的でnmapを実行したところ、しばらくしてKernelが停止した。ifconfigやtcpdumpなどにパッチを当てるようになっているが、パッチのあたっていないraw socketを扱うネットワーク関連のコマンドを実行するのは危険かも。
ユーザモードPPPoEとは共存できない。
Userland PPPoEで接続をおこなったあと、一旦切断し、in-kernel PPPoEで接続すると、VM faultでpanicする。
デフォルトルート等の設定は行われない。
後述のifwatchdから呼び出すスクリプトに記述した方がいいかも(今回は常用するわけではないので、手動で設定した)。
ifwatchdを入れましょう
ネットワークの接続/切断時の処理を行うには、NetBSDで用いられているifwatchdというスクリプトを持ってきて移植する。その後;
/usr/sbin/ifwatchd -u /etc/ppp/ip-up.hook -d /etc/ppp/ip-down.hook pppoe0
などと実行。
ip-up.hookはUserland PPPoEと共用;
  • Dynamic DNSの設定
  • NTP daemonの立ち上げ直し
  • IPv4-IPv6 トンネルやSSH port forwardingトンネルの再接続など
リンク断が多いような気がした
Userland PPPoEだと、リンク断なることはほとんどなかった(1月に1回以下)が、 in-kernel PPPoEだと比較的多く(数日に一回~一日数回)なったようだ。 断になっている時間は短かったが、そのつどDynamic DNSの更新が発生し、 外部から参照できない場合もあった。

感想

うまく接続すると、スループットも飛躍的に伸び、Uptimeも100日近く運用できたが、前項に述べたような理由でOSごと停止してしまう場合もあるので、運用には注意が必要。CPUパワーに余裕のあるマシンなら、安全性を重視してネイティブのUserland PPPoEを使うのが無難。

そこらへんの問題が解決されて、正式に配布系に採用されるのがベストなんだけど‥。

その他

これとは別に独自に実装している人もいました。具体的なソース等は公開されていないようですが。

‥‥などとやっていたら、正式サポート

ネイティブサポートされたようです。

In kernel PPPoE client
http://undeadly.org/cgi?action=article&sid=20041130200439

使ってみる

とりあえずテスト用マシンに-current ( http://kaw.ath.cx/dl/pub/OpenBSD/current/ - 20041204) をインストール。設定は通常のネットワークインターフェースやbridgeなどとおなじ、/etc/hostname.if に記述。PPPoEなので、/etc/hostname.pppoe0 を作成した。

/etc/hostname.pppoe0

pppoedev ne0
! /sbin/ifconfig ne0 up
! /usr/sbin/spppcontrol \$if myauthproto=pap myauthname=XXX myauthkey=YYY
! /sbin/ifconfig \$if inet 0.0.0.0 0.0.0.1 netmask 0xffffffff
! /sbin/route add default 0.0.0.1
up

これでOK。

3.7のリリース時には、正式に含まれるのでは。 そうしたら、このページは用無しだな。

予想どおり含まれました

補足

再接続について

In-kernel PPPoEはADSLのリンクがダウンした場合再接続する機能はないようなので、以下のスクリプトを作成してリンクを監視;

#!/bin/sh

    interface=pppoe0
checkinterval=60
       bindir=`dirname $0`;

getstatus () {
  iface="$1"
  set `/usr/sbin/spppcontrol $iface`
  stat="$2"

  case X"$stat" in
    Xphase=dead)    echo down    ;;
    Xphase=network) echo up      ;;
    *)              echo unknown ;;
  esac
}

prestatus=unknown

while :;
do
  status=`getstatus $interface`
  case X/"$prestatus/$status" in
      X/down/up|X/unknown/up)
        if [ -x $bindir/linkup ]
        then
          echo `date` link is up >> $bindir/../logs/checklink.log
          $bindir/linkup
        fi
        ;;
      X/up/down)
        if [ -x $bindir/linkdown ]
        then
          echo `date` link is down >> $bindir/../logs/checklink.log
          $bindir/linkdown
        fi
        ;;
      *)
        # status not changed
        ;;
  esac

  prestatus=$status

  if [ X"$status" = Xdown ]
  then
    ifconfig $interface up
  fi

  sleep $checkinterval
done

リンクを$checkinterval間隔で監視。リンクがダウンしていた場合、再接続を試行する。また、リンクがupまたはdownした場合に、それぞれスクリプト$bindir/linkup , $bindir/linkdown を実行するので、dynamic DNSの更新とかはここに書けばOK。

MTU問題

MTUを調整しないとやっぱり見られないウェブサイトが出てくる。
うちの接続業者はMSS1414オクテット推奨らしいので、http://www.pro-bono-publico.de/openbsd/pppoe/の記述に倣って書いてみるとこんな感じでしょうか

イーサネットフレーム
1500オクテット
PPPoE+PPPヘッダ
8オクテット
PPPoE+PPPペイロード
1492オクテット
IPヘッダ
20オクテット
IPペイロード
1454オクテット
TCPヘッダ
40オクテット
TCPペイロード
1414オクテット

これを実現するための設定;

/etc/hostname.pppoe0

up mtu 1454

/etc/pf.conf

scrub in  on $ext_if fragment reassemble max-mss 1414
scrub out on $ext_if fragment reassemble max-mss 1414

/etc/sysctl.conf

net.inet.tcp.mssdflt=1414

FrontPage


Front page   New Page list Search Recent changes   Help   RSS of recent changes