Raspberry Pi の USB-OTG ethernet の MAC address を model B の ethernet と同じ規則で設定する

Raspberry Pi model A/A+/Zero/ZeroW/ZeroHW/Compute Module/Compute module 3ではUSB-OTGが利用できます．(ZeroHW/Compute Module/Compute module 3は自分は未確認)

Raspberry PiのUSB OTGを試す – Speaker Deck

USB-OTGでHID(Raspberry Pi Zeroをマウス・キーボード化)

Simple guide for setting up OTG modes on the Raspberry Pi Zero · GitHub

USB-OTGでUSBをEthernetにしてHostPCからアクセスするようにするとUSBケーブル1本で電源と併用できて便利です．

このときMACアドレスはモジュール読み込み毎に自動生成されます．
以下の例では，接続先(PC等)から見えるMACが HOST MAC 6a:b3:b1:5e:22:89 で，Raspberry Pi の中でのMACが MAC ae:3a:c7:8e:50:38 になっています．

$ sudo modprobe g_ether
$ dmesg | tail -15
[ 88.517568] using random self ethernet address
[ 88.517590] using random host ethernet address
[ 88.519210] usb0: HOST MAC 6a:b3:b1:5e:22:89
[ 88.520195] usb0: MAC ae:3a:c7:8e:50:38
[ 88.520396] using random self ethernet address
[ 88.520412] using random host ethernet address
[ 88.520534] g_ether gadget: Ethernet Gadget, version: Memorial Day 2008
[ 88.520546] g_ether gadget: g_ether ready
[ 88.520580] dwc2 20980000.usb: bound driver g_ether
[ 88.866651] IPv6: ADDRCONF(NETDEV_UP): usb0: link is not ready
[ 94.048758] dwc2 20980000.usb: new device is high-speed
[ 94.128837] dwc2 20980000.usb: new device is high-speed
[ 94.197523] dwc2 20980000.usb: new address 9
[ 96.057234] g_ether gadget: high-speed config #1: CDC Ethernet (ECM)
[ 96.095719] IPv6: ADDRCONF(NETDEV_CHANGE): usb0: link becomes ready
$ /sbin/ifconfig usb0
usb0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 10.42.0.212 netmask 255.255.255.0 broadcast 10.42.0.255
inet6 fe80::5855:ab0c:6628:557c prefixlen 64 scopeid 0x20
ether ae:3a:c7:8e:50:38 txqueuelen 1000 (Ethernet)
RX packets 208 bytes 17243 (16.8 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 67 bytes 7696 (7.5 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

これは毎回変わるのでふと気づくとホストPCのネットワークの設定が沢山になっていたり……．

$ nmcli connection show | grep ethernet | wc -l
25

MAC addressを固定するにはモジュール読み込み時に指定してあげればOKです．

$ sudo rmmod g_ether
$ sudo modprobe g_ether host_addr=de:ad:fe:ef:00:01 dev_addr=de:ad:fe:ef:00:00
$ dmesg | egrep usb0:.*MAC | tail -2
[ 1067.248443] usb0: HOST MAC de:ad:fe:ef:00:01
[ 1067.248958] usb0: MAC de:ad:fe:ef:00:00

永続化するには，g_etherモジュールを読んでいるところで指定してあげます．

/boot/cmdline.txt の場合 rootwait の前に以下を追加

modules-load=dwc2,g_cdc g_ether.host_addr=de:ad:fe:ef:00:01 g_ether.dev_addr=de:ad:fe:ef:00:00

/etc/modules の場合

g_ether g_ether.host_addr=de:ad:fe:ef:00:01 g_ether.dev_addr=de:ad:fe:ef:00:00

Note

※g_cdcの場合はこんな感じで

g_cdc g_cdc.host_addr=de:ad:fe:ef:00:01 g_cdc.dev_addr=de:ad:fe:ef:00:00

/etc/rc.local の場合 exit より前の行に以下を追加(※model Aの場合 cmdline.txt, modules 共に module は読み込まれるけど動作はうまく行かないことが多いので rc.local が良さそう)

modprobe g_ether host_addr=de:ad:fe:ef:00:01 dev_addr=de:ad:fe:ef:00:00

このときのMAC addressは g_ether が自動生成したものを使うのが無難だとおもうのですが，ランダムとかでいんだろうか?という不安があります．

ベンダーIDに使われていない領域だったら多分問題ないですが，これから埋まることもありそうです．(IPアドレスのプライベートIPアドレスのような領域があるのかもしれ無いけど未確認)

Raspberry Pi model B シリーズのNICには Raspberry Pi Foundation のベンダーコードが使われています．

nmap のMAC addressベンダー情報のファイルから確認

$ grep -i raspberry /usr/share/nmap/nmap-mac-prefixes
B827EB Raspberry Pi Foundation

Raspberry Pi の smsc95xx の MAC address の生成は，上6桁はベンダーIDの b8:27:eb を，下6桁はボードのserialの下6桁を割り当てているようです．

MAC address generation
To have a predetermined MAC address, a given SMSC LAN9512 must be attached to an EEPROM that contains the MAC address. But on the Raspberry Pi Model B, this EEPROM is not present; therefore, this driver must assign a MAC address itself. We do this by generating a MAC address from the board’s serial number. This guarantees that a given Raspberry Pi will always have the same MAC address and that two Raspberry Pis are extremely unlikely to be assigned the same MAC address.

xinu/SMSC-LAN9512.rst at master · xinu-os/xinu · GitHub

手元の Raspberry Pi 2 Model B を確認すると確かにそうなっているようです．

$ ifconfig | grep ether
ether b8:27:eb:ff:56:0a txqueuelen 1000 (Ethernet)
$ grep Serial /proc/cpuinfo
Serial : 0000000094ff560a
$ sed -n "s/^Serial.*:.*\(..\)\(..\)\(..\)$/b8:27:eb:\1:\2:\3/p" /proc/cpuinfo
b8:27:eb:ff:56:0a
$ cat /proc/device-tree/model ;echo
Raspberry Pi 2 Model B Rev 1.1

Note

16進数6桁は 0xFFFFFF → 16777215です，Raspberry Pi は2018年3月時点で190万台出荷しているようなので2周目に入っています．低い確率でしょうが同じMAC addressが割り当てられる可能性が……．

we’ve sold 19 million Raspberry Pis in total

Raspberry Pi 3 Model B+ on sale now at $35 – Raspberry Pi

内蔵ネットワークに自分でMAC addressを指定したい場合はこんな感じでいけます．

/boot/cmdline.txt に以下を設定

smsc95xx.macaddr=b8:27:eb:00:00:00

/etc/network/interfaces でも設定できるはずだがRaspbianでは未確認

hwaddress ether b8:27:eb:00:00:00

CPU Serialを詐称する手も?

/proc/cpuinfoのSerialを詐称する – matoken’s meme

ということで，Raspberry Pi model A / Zero でもこの MAC address が利用できそうな感じです．外向けの HOST MAC をこのアドレスにしてみます．

$ sed -n "s/^Serial.*:.*\(..\)\(..\)\(..\)$/b8:27:eb:\1:\2:\3/p" /proc/cpuinfo | tee ~/macaddress
b8:27:eb:d8:63:18
$ sudo vi /boot/cmdline.txt
$ sudo reboot
:
:
$ dmesg | grep usb0
[ 4.937660] usb0: HOST MAC b8:27:eb:d8:63:18
[ 4.937845] usb0: MAC 86:d7:fe:57:f2:d5

ホストPCでもちゃんと指定したものになっています．

$ /sbin/ifconfig enxb827ebd86318 | grep ether
ether b8:27:eb:d8:63:18 txqueuelen 1000 (Ethernet)

とりあえずこれで使ってみようと思います．

環境

$ lsb_release -d
Description: Raspbian GNU/Linux 9.4 (stretch)
$ uname -m
armv6l
$ cat /proc/device-tree/model ;echo
Raspberry Pi Model A Rev 2