CoregaのCG-LAPCIGTをCentOS6.2で動かす為にやった事

# まえおき

CG-LAPCIGTはかなり昔の製品で、これです。
http://corega.jp/product/list/lanadp/lapcigt.htm

Linux関連の情報はこんな感じでRedHat9の時代です。ふるっ
http://corega.jp/product/os/pc_unix.htm

何故にこんな組み合わせで動かそうと思ったかといいますと、うるう秒です。

クラウドじゃない社内の数台のサーバはバグ持ちカーネルだったので、カーネルアップデートしてしまおうと思ってyum update kernelしたら一台だけ起動してこなくなってハマりました。

待てど暮らせど上がってこないので、直接繋がってるLCDで画面を見たら

```radeon: ring 0 test failed```

という感じの画面で止まってて、起動しなくなっていました。。。orz

grubのメニューで古い方のカーネルを手動で選べば起動しますが、それじゃ意味ないので新しいカーネルで起動させる為にまず、radeonのtest failにならないようにスキップさせて、且つランレベルを5じゃなくて3にする設定変更をしました、GUIなんてサーバには不要なので。

/boot/grub/grub.confに、以下のオプションを追加。
radeon.modeset=0

/etc/inittabを以下の様に編集
id:3:initdefault:

参考URL：
http://docs.oracle.com/cd/E40528_01/b71926/vmrns-bugs.html#idm47387775559376

これで起動するようにはなりましたが、今度はネットワークが死んでる！

調べてみたら、オンボードのNICを新しいカーネルでうまく認識できなくて、ドライバがちゃんと動いてませんでした。

そこで手動で正しいと思われるドライバを組み込ませたところ、何故かマックアドレスがオールFという謎のNICになってしまいました。。。orz

ダメだこりゃ、次行ってみよう！という事で取り出したのが、昔使ってて余ってたCoregaのCG-LAPCIGTだったという訳ですが、それもやはり一筋縄では動かなかったので、ドライバのソース修正＆ビルド＆initrd再構築の流れを書きたいと思います。

# NIC装着後の展開

まず挿して起動したら、認識せずに動かなかった訳ですが、そういう時はlspciですね。

```# lspci
中略
03:02.0 Ethernet controller: Allied Telesyn International Device c107 (rev 10)
```

なんということでしょう、CoregaはRealtekのチップを積んでるはずなのに、アライドとして認識されちゃってます。
これじゃ動かないわけです。

# ドライバソースコードの入手

Coregaの情報でr8169なのはわかってるので、公式に行ってドライバ貰ってきます
http://www.realtek.com.tw/downloads/searchView.aspx?keyword=r8169

Versionが6.020という今年5月にアップデートされたばかりの真新しいドライバがありました！
最近更新されてるなんて珍しいなーって思いながら、ありがたく頂いてきました。

ドライバの修正ポイントは以下のサイトを参考にしました。
http://blog.goo.ne.jp/kazuau/e/217ae711ddc0a68c0c7c55e2b13d180b

10年も前のブログなので、現在とソースコードの感じが変わってますが、やりたい事は分かりました。
というか、昔デバドラを１から作る側の人だったので、見たらすぐ分かった感じです。
ソースの修正は、今回こんな感じでいけました。

```c:r8169_n.c
修正前
static struct pci_device_id rtl8169_pci_tbl[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_REALTEK,     0x8167), 0, 0, RTL_CFG_0 },
        { PCI_DEVICE(PCI_VENDOR_ID_REALTEK,     0x8169), 0, 0, RTL_CFG_0 },
        { PCI_VENDOR_ID_DLINK, 0x4300, PCI_VENDOR_ID_DLINK, 0x4300, 0, 0,
RTL_CFG_0 },
        { PCI_VENDOR_ID_DLINK, 0x4302, PCI_VENDOR_ID_DLINK, 0x4302, 0, 0,
RTL_CFG_0 },
        { PCI_VENDOR_ID_DLINK, 0x4300, PCI_VENDOR_ID_DLINK, 0x4c00, 0, 0,
RTL_CFG_0 },
        {0,},
};

修正後
static struct pci_device_id rtl8169_pci_tbl[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_REALTEK,     0x8167), 0, 0, RTL_CFG_0 },
        { PCI_DEVICE(PCI_VENDOR_ID_REALTEK,     0x8169), 0, 0, RTL_CFG_0 },
        { PCI_DEVICE(0x1259,    0xc107), 0, 0, RTL_CFG_0 },
        { PCI_VENDOR_ID_DLINK, 0x4300, PCI_VENDOR_ID_DLINK, 0x4300, 0, 0,
RTL_CFG_0 },
        { PCI_VENDOR_ID_DLINK, 0x4302, PCI_VENDOR_ID_DLINK, 0x4302, 0, 0,
RTL_CFG_0 },
        { PCI_VENDOR_ID_DLINK, 0x4300, PCI_VENDOR_ID_DLINK, 0x4c00, 0, 0,
RTL_CFG_0 },
        {0,},
};
```

4行目を増やしてます。
0x1259というのは、アライドのベンダーIDです、今回lspciで見えちゃってる奴ですね。
ベンダーIDは以下の様なサイトで調べられます。
参考URL：http://www.pcidatabase.com/vendor_details.php?id=1125

0xc107はデバイスIDです、これはlspciにもそのまんま見えてますね。

ドライバというものは、ベンダーIDとデバイスIDを見て、組み込むか組み込まないか判断しているので、その組み合わせ候補の中に、今回見えちゃってるベンダーIDとデバイスIDの組み合わせを追加してあげてるという訳です。

※2016/10/28追記
最近のカーネルバージョン(2.6.32-642.6.2.el6.x86_64)では、上記の修正だけではビルドできなくなっていました。
新しいカーネルではドライバで使用される関数が使えなくなってしまっているので、更に以下の修正が必要です。

関数名：static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp, struct sk_buff *skb)
修正箇所：870行目あたり

修正前

```
{
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0)
        return (tp->vlgrp && vlan_tx_tag_present(skb)) ?
               TxVlanTag | swab16(vlan_tx_tag_get(skb)) : 0x00;
#elif LINUX_VERSION_CODE < KERNEL_VERSION(4,0,0)
        return (vlan_tx_tag_present(skb)) ?
               TxVlanTag | swab16(vlan_tx_tag_get(skb)) : 0x00;
#else
        return (skb_vlan_tag_present(skb)) ?
               TxVlanTag | swab16(skb_vlan_tag_get(skb)) : 0x00;
#endif
}
```

修正後

```
{
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0)
//        return (tp->vlgrp && vlan_tx_tag_present(skb)) ?
//               TxVlanTag | swab16(vlan_tx_tag_get(skb)) : 0x00;
        return (skb_vlan_tag_present(skb)) ?
               TxVlanTag | swab16(skb_vlan_tag_get(skb)) : 0x00;
#elif LINUX_VERSION_CODE < KERNEL_VERSION(4,0,0)
//        return (vlan_tx_tag_present(skb)) ?
//               TxVlanTag | swab16(vlan_tx_tag_get(skb)) : 0x00;
        return (skb_vlan_tag_present(skb)) ?
               TxVlanTag | swab16(skb_vlan_tag_get(skb)) : 0x00;
#else
        return (skb_vlan_tag_present(skb)) ?
               TxVlanTag | swab16(skb_vlan_tag_get(skb)) : 0x00;
#endif
}
```

参考URL：http://kusoneko.blogspot.jp/2016/05/centos-7.2-r8169-driver-update.html

修正が終わったらビルドしますが、ドライバのビルドには以下が必要なので、事前にイン
ストールしておきます。

```
kernel-devel-2.6.32-504.23.4.el6.x86_64
kernel-headers-2.6.32-504.23.4.el6.x86_64
```

ドライバは別名カーネルモジュールとも言いますので、カーネルのヘッダーやソースが無
いと単体ではビルドできません。

ビルドはMakefileのある場所でやります。
もらってきたソース一式を解凍すると出てきます。
makeとインストールは以下の様な感じです。

```
# make
# make install
# cp ./r8169.ko /lib/modules/2.6.32-504.23.4.el6.x86_64/kernel/net/
```

make installでインストールして欲しいですが、してくれなかったので、cpで手動コピー
しました。
以上でドライバのビルドとインストールは終了です。次はカーネルモジュールとしての設
定です。

# カーネルモジュールとしての設定

ひとまずドライバを手動組み込みしてみましょう

```
# modprobe r8169
# dmesg | less
```

dmesgの後ろのほうで、今組み込んだドライバの事が色々と出てるはずです。

ifconfigでも組み込まれたデバイスが見えるようになってるはずなので、そのマックアド
レスをメモっておきましょう。

次に、とりあえずdepmodしてみます。

```
# depmod -a
# tac /lib/modules/2.6.32-504.23.4.el6.x86_64/modules.dep | grep r8169
kernel/net/r8169.ko
```

8169が居るので大丈夫そうです。

次にinitrdイメージを作ります。

```
# cd /boot
# dracut initramfs-2.6.32-504.23.4.el6.x86_64_new.img 2.6.32-504.23.4.el6.x86_64
```

GRUBの設定を変えます。

<pre>
# vi grub/grub.conf
修正前
        initrd /initramfs-2.6.32-504.23.4.el6.x86_64.img
修正後
        initrd /initramfs-2.6.32-504.23.4.el6.x86_64_new.img
</pre>

ifcfgの設定ファイルを追加します。
今回はeth0の代わりのeth1を作ります。

<pre>
# cd /etc/sysconfig/network-scripts/
# cp ifcfg-eth0 ifcfg-eth1
# vi ifcfg-eth1
修正前
HWADDR="xx:xx:xx:xx:xx:E0"
修正後
HWADDR="xx:xx:xx:xx:xx:D9"
※一応マックアドレスを一部以外伏せてます。
</pre>

HWアドレスを今回追加したLANボードに書き換えてるだけです。
eth0をeth1に変更してる箇所もありますが、一目瞭然なので説明は省略します。
後は再起動するだけで完了！のはずでしたが、ドライバが組み込まれませんでした。

こういう時は慌てず騒がずlsinitrdです。

<pre>
# cd /boot
# lsinitrd initramfs-2.6.32-504.23.4.el6.x86_64_new.img | grep r8169
-rw-r--r--   1 root     root           16 Oct  9  2014
etc/modprobe.d/blacklist-r8169.conf
</pre>

するとなんということでしょう、ブラックリストに入れられてる！こりゃ動かんわ！
というわけで、ブラックリストを消します。

<pre>
# cd /etc/modprobe.d/
mv blacklist-r8169.conf /home/hogehoge/
</pre>

はい、これでブラックリストから消えました。
再び上記のdepmod -aの手順からやり直して今度こそ完了しました。めでたしめでたし。

（あれ、もしかして最初からブラックリストさえ消しておけば良かっただけの罠？・・・orz）