memo.log

技術情報の雑なメモ

Raspberry Pi 4 のカーネルビルドの最低限の手順メモ

www.raspberrypi.org

結局のところ、上記公式ドキュメントを見るのが一番正確なわけだけど、何も考えずにコピペするための手順メモ。

ラズパイのモデル

$ cat /proc/device-tree/model
Raspberry Pi 4 Model B Rev 1.2

手順

git clone --depth=1 https://github.com/raspberrypi/linux
cd linux
KERNEL=kernel7l
vim Makefile # 必要に応じて
# EXTRAVERSION=kure # ビルドしたことが後で分かるように適当に名前付けておく
make bcm2711_defconfig
sudo make -j4 zImage modules dtbs
sudo make modules_install
sudo cp arch/arm/boot/dts/*.dtb /boot/
sudo cp arch/arm/boot/dts/overlays/*.dtb* /boot/overlays/
sudo cp arch/arm/boot/dts/overlays/README /boot/overlays/
sudo cp arch/arm/boot/zImage /boot/$KERNEL.img
sudo reboot
uname -a #確認。多分↓みたいに kure がついた出力になるはず。
# Linux kure10 5.10.33kure-v7l+ #3 SMP Sun May 2 18:41:49 BST 2021 armv7l GNU/Linux

参考

qiita.com

日経Linux 2009/09号「仮想ネットワーク・ドライバとVPN」のメモ

kure.hatenablog.jp

記事の深堀り。

bizboard.nikkeibp.co.jp

が、仮想ネットワークドライバの簡単なサンプルプログラムとVPNの仕組みの解説が書かれており、参考になりそうだった。が、記事のサンプルプログラムはカーネル 2.6 向けのもののようで、今普通に使えるOSだと動かないようだった。

例えば、出来るだけ古めでパッと使えたUbuntu 16.04 だと make 時に以下のエラーが出た。

/home/ubuntu/net3/vn.c: In function ‘vn_init’:
/home/ubuntu/net3/vn.c:252:5: error: ‘struct net_device’ has no member named ‘open’
  dev->open=vn_open;
     ^
/home/ubuntu/net3/vn.c:253:5: error: ‘struct net_device’ has no member named ‘stop’
  dev->stop=vn_stop;
     ^
/home/ubuntu/net3/vn.c:254:5: error: ‘struct net_device’ has no member named ‘set_config’
  dev->set_config=vn_config;
     ^
/home/ubuntu/net3/vn.c:255:5: error: ‘struct net_device’ has no member named ‘hard_start_xmit’
  dev->hard_start_xmit=vn_tx;
     ^
/home/ubuntu/net3/vn.c:256:5: error: ‘struct net_device’ has no member named ‘do_ioctl’
  dev->do_ioctl=vn_ioctl;
     ^
/home/ubuntu/net3/vn.c:257:5: error: ‘struct net_device’ has no member named ‘get_stats’
  dev->get_stats=vn_stats;

どうやら struct net_device 周りが古いようで、<linux/netdevice.h> を見てみると、それっぽい定義が無かった。もしかしたら無くなっている?のかも。

いずれにせよ、かなり書き換えないと動かなそうではある。。 とりあえず、仮想ネットワークデバイスドライバとキャラクタデバイスとトンネルや暗号化のアプリケーションとの関係性がわかればいいので、そのあたりのコマンドや関数( mknod 等)の仕様を確認してみる。

www.mech.tohoku-gakuin.ac.jp → mknod の簡単なサンプルがあった。 デバイスドライバを insmod で登録したらその番号を覚えておき、 mknod でデバイスファイルを作成しつつその番号に紐付けるようにすればいい。 そうすれば、そのファイルにアクセスされたらデバイスドライバにアクセスがされるらしい。

ただし、雑誌のサンプルでは、mknod した後にそのデバイス名で ifconfig .. 192.168.0.1 みたいにアドレスを指定できるネットワークインターフェースとして認識されているので、単純なファイルの作成とは違うみたい。 register_netdev 関数あたりかな。

と思っていると、この前号↓に詳細な解説が書いてあった。 register_netdev 関数でカーネルにデバイスを登録すると、そのときに登録した設定内容にしたがって、カーネルから指定の関数が呼び出されるようになるらしい。このサンプルプログラムも見てみたいところだ。

bizboard.nikkeibp.co.jp

ちなみに、Amazon Linuxのネットワークドライバ ena のソースは↓みたい。 github.com

register_netdev してる箇所は↓。 amzn-drivers/ena_netdev.c at b91fcd346b903fd2006cea79da7c13993bce5c4b · amzn/amzn-drivers · GitHub

ちょっと書き換えて実験してみたいけど、Amazon Linuxじゃ無理だな。。 オープンソースRaspberry Pi(Rasbpian)でやってみるか。

カーネルからパケット送信時とかに呼び出されるときのイメージとかをつかめるとTUN/TAPの動作イメージも掴めそう。 TUN/TAPも結局は、仮想ネットワークドライバとネットワークデバイスの1種だろうから。

参考

https://h2plus.biz/hiromitsu/entry/227

コマンドで TUN/TAP デバイスを試すメモ

VPN(トンネル)技術のポイントにTUN/TAPデバイスというのがあるということで、少し触ってみた。イマイチ良くはわかっていない。

TUN

# TUN デバイス作成
% sudo ip tuntap add dev kure_tun mode tun 
% ip link show
9: kure_tun: <POINTOPOINT,MULTICAST,NOARP> mtu 1500 qdisc noop state DOWN mode DEFAULT group default 
qlen 500
    link/none
# どういうIFなのだ…?
% ifconfig kure_tun
kure_tun: flags=4240<POINTOPOINT,NOARP,MULTICAST>  mtu 1500
        unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00  txqueuelen 500  (UNSPEC)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
# IPアドレスを設定してみる
% sudo ifconfig kure_tun 172.31.7.57 netmask 255.255.240.0
% ifconfig kure_tun
kure_tun: flags=4241<UP,POINTOPOINT,NOARP,MULTICAST>  mtu 1500
        inet 172.31.7.57  netmask 255.255.240.0  destination 172.31.7.57
        unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00  txqueuelen 500  (UN
SPEC)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
# ping も返ってくる
 % ping 172.31.7.57                           
PING 172.31.7.57 (172.31.7.57) 56(84) bytes of data.
64 bytes from 172.31.7.57: icmp_seq=1 ttl=255 time=0.030 ms

TAP

% sudo ip tuntap add dev kure_tap mode tap
# こっちはMACアドレスがついてる
% ifconfig kure_tap
kure_tap: flags=4098<BROADCAST,MULTICAST>  mtu 1500
        ether 9e:53:c6:5c:63:df  txqueuelen 1000  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
# 同じ感じでIPアドレスも付けられるし、pingも返ってくる
% sudo ifconfig kure_tap 172.31.7.57 netmask 255.255.240.0
% ifconfig kure_tap                                       
kure_tap: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 172.31.7.57  netmask 255.255.240.0  broadcast 172.31.15.255
        ether 9e:53:c6:5c:63:df  txqueuelen 1000  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

消す時

sudo ip tuntap del dev tun0 mode tun   

参考/メモ

hogem.hatenablog.com

hichtakk.hateblo.jp

https://www.kernel.org/doc/Documentation/networking/tuntap.txt →一番オフィシャルなドキュメントぽい。

vtun.sourceforge.net →上記ドキュメントからリンクされているサンプルアプリ的な。

そもそもPoint to Point Interface というのがあるっぽい?→TUN

www.oreilly.com

unix.stackexchange.comイーサネットはポイントツーマルチ、TUNはポイントツーポイント

stackoverflow.com

ip route や /proc/net/route のFlagsについて

/proc/net/route を見ると Flags というカラムがある。

% cat /proc/net/route
Iface   Destination     Gateway         Flags   RefCnt  Use     Metric  Mask            MTU     Window  IRTT                                                       
eth0    00000000        01001FAC        0003    0       0       0       00000000        0       0       0
eth1    00000000        01001FAC        0003    0       0       10001   00000000        0       0       0
eth2    00000000        01001FAC        0003    0       0       10002   00000000        0       0       0
eth0    FEA9FEA9        00000000        0005    0       0       0       FFFFFFFF        0       0       0 
eth0    00001FAC        00000000        0001    0       0       0       00F0FFFF        0       0       0
eth1    00001FAC        00000000        0001    0       0       0       00F0FFFF        0       0       0
eth2    00001FAC        00000000        0001    0       0       0       00F0FFFF        0       0       0

これはなんだろうと思って、 ip route コマンドの結果をみてみると、 scope link (隣接(直接宛先と通信できる)のネットワーク)が 0001 と整合しているように見える。

% ip route
default via 172.31.0.1 dev eth0 
default via 172.31.0.1 dev eth1 metric 10001 
default via 172.31.0.1 dev eth2 metric 10002 
169.254.169.254 dev eth0 
172.31.0.0/20 dev eth0 proto kernel scope link src 172.31.7.56 
172.31.0.0/20 dev eth1 proto kernel scope link src 172.31.11.244 
172.31.0.0/20 dev eth2 proto kernel scope link src 172.31.11.75 

route コマンドで見ると Flags が U という文字列で表現されている。

% route                         
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         ip-172-31-0-1.a 0.0.0.0         UG    0      0        0 eth0
default         ip-172-31-0-1.a 0.0.0.0         UG    10001  0        0 eth1
default         ip-172-31-0-1.a 0.0.0.0         UG    10002  0        0 eth2
instance-data.a 0.0.0.0         255.255.255.255 UH    0      0        0 eth0
172.31.0.0      0.0.0.0         255.255.240.0   U     0      0        0 eth0
172.31.0.0      0.0.0.0         255.255.240.0   U     0      0        0 eth1
172.31.0.0      0.0.0.0         255.255.240.0   U     0      0        0 eth2

以下のファイルを見ると、 RTF_UP 0x0001 / route usable /ということで、上記認識で合っているみたい。

/usr/include/linux/route.h

#define RTF_UP          0x0001          /* route usable                 */
#define RTF_GATEWAY     0x0002          /* destination is a gateway     */
#define RTF_HOST        0x0004          /* host entry (net otherwise)   */
#define RTF_REINSTATE   0x0008          /* reinstate route after tmout  */
#define RTF_DYNAMIC     0x0010          /* created dyn. (by redirect)   */
#define RTF_MODIFIED    0x0020          /* modified dyn. (by redirect)  */
#define RTF_MTU         0x0040          /* specific MTU for this route  */
#define RTF_MSS         RTF_MTU         /* Compatibility :-(            */
#define RTF_WINDOW      0x0080          /* per route window clamping    */
#define RTF_IRTT        0x0100          /* Initial round trip time      */
#define RTF_REJECT      0x0200          /* Reject route                 */

参考

android - What's the meaning of /proc/net/rotue columns? especially Flags column - Stack Overflow https://stackoverflow.com/questions/33231034/whats-the-meaning-of-proc-net-rotue-columns-especially-flags-column

【Ruby】ビッグエンディアン・ネットワークバイトオーダー、サンプルメモ

pack("n") で、ネットワークバイトオーダー(ビッグエンディアン)のunsigned short (16bit 符号なし整数)に変換できる。 ビッグエンディアンなので、バイトの上位から並べていく。 例えば、 0xAABBCCDD だったら、0xDDが低い(1桁目側)側なので逆から、AA, BB, CC, DD というふうに格納するのがビッグエンディアンpack("n") の場合は、16bit = 2Byte に変換する。1Byte=16進数で2桁なので2Byteは \xNN\xNN みたいな出力になる。

例)

> [1].pack("n")
=> "\x00\x01"
> [1].pack("n")[0]
=> "\x00"
> [1].pack("n")[1]
=> "\x01"

もとの数値は1、もし2Byteで表現するなら 00000000 00000001 = \x00\x01 で、 pack すると "\x00\x01" になる。見た目は低い方が1だが、Ruby文字列的には

[1].pack("n")[0] => "\x00"

のように下位が0、上位が1なので、人間の見た目にすると、 00000001 00000000 と解釈できる。 つまり、1をバイト上位から並べている=ビッグエンディアン

参考

pack テンプレート文字列 (Ruby 3.0.0 リファレンスマニュアル) https://docs.ruby-lang.org/ja/latest/doc/pack_template.html