Third Encore

思い出すために忘れたことたち

Raspberry PiのRoon Bridgeで設定したことまとめ

FirewallUFWを使っている際のポート解放設定

/etc/ufw/applications.d/roonbridge

[Roon Bridge]
title="Roon Bridge"
description="Roon Bridge"
ports=1025:65535/tcp|1025:65535/udp

して

$ sudo ufw allow from [Your localnet]/24 to any app "Roon Bridge"

※ポート解放範囲は多分広過ぎると思いますが、Roonが正式に使用するポートを指定していないこと、Roon Bridgeのアップデートでも使用するポートが変わる可能性があることからlocalnetからのアクセスにがばっとポートを開けてしまっています。

CPU負荷の分散

/boot/cmdline.txtに

isolcpus=1-3

を追記

/etc/systemd/system/roonbridge.serviceの[Service]欄に

CPUAffinity=1

を追記

/home/pi/postroon.shを

#!/bin/sh

sudo taskset -pc 2 `pgrep -f RoonBridgeHelper`
sudo chrt -f -p 95 `pgrep -f RoonBridgeHelper`
sudo taskset -pc 3 `pgrep -f RAATServer`
sudo chrt -f -p 95 `pgrep -f RAATServer`

として作成

/etc/systemd/system/postroon.serviceを

[Unit]
Description=Post RoonBridge script
#After=roonbridge.service
Requires=roonbridge.service

[Service]
Type=oneshot
ExecStart=/home/pi/postroon.sh

[Install]
WantedBy=multi-user.target
Also=roonbridge.service

という内容で作成

$ sudo chmod +x /home/pi/postroon.sh
$ sudo systemctl enable postroon

で有効化

OverlayFS適用時Roon Bridgeを起動するのに必要な設定

/etc/fstabに

tmpfs    /var/roon   tmpfs   defaults,size=4M,noatime

を追記

Overlay Filesystem (OverlayFS)の導入

ざっくりルート・ディレクトリのファイル類をRAM上に展開するものとのこと。

 

qiita.com

 

試した結果分かったこと:

  • 現状適用できるのはkernelのメインラインの5.15まで
  • 自分でビルドしたkernelを/bootにコピーする時にsudo make installではなくsudo cp arch/arm64/boot/Image /boot/kernel8-`make kernelrelease`.imgなどでImageをcpすること
  • RAM使用量は2GBを少し超えるくらい

音への影響としては歪み感が減ってなめらかになるように感じました。/etc/fstabやfolder2ramを使ってcacheやlog、tmpディレクトリをRAMへ移すだけでもかなり音が変わった経験があるので、ストレージへのアクセスはなにかと影響が大きいように感じます。

MacでRaspberry Pi用kernelをcross-compileする時に発生するAppArmorのエラー回避方法

security/apparmor/Makefileを下記の通り修正

# SPDX-License-Identifier: GPL-2.0
# Makefile for AppArmor Linux Security Module
#
obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o

apparmor-y := apparmorfs.o audit.o capability.o task.o ipc.o lib.o match.o \
              path.o domain.o policy.o policy_unpack.o procattr.o lsm.o \
              resource.o secid.o file.o policy_ns.o label.o mount.o net.o
apparmor-$(CONFIG_SECURITY_APPARMOR_HASH) += crypto.o

#clean-files := capability_names.h rlim_names.h net_names.h

# Build a lower case string table of address family names
# Transform lines from
#    #define AF_LOCAL       1   /* POSIX name for AF_UNIX   */
#    #define AF_INET        2   /* Internet IP Protocol     */
# to
#    [1] = "local",
#    [2] = "inet",
#
# and build the securityfs entries for the mapping.
# Transforms lines from
#    #define AF_INET        2   /* Internet IP Protocol     */
# to
#    #define AA_SFS_AF_MASK "local inet"
#quiet_cmd_make-af = GEN     $@
#cmd_make-af = echo "static const char *address_family_names[] = {" > $@ ;\
#   sed $< >>$@ -r -n -e "/AF_MAX/d" -e "/AF_LOCAL/d" -e "/AF_ROUTE/d" -e \
#    's/^\#define[ \t]+AF_([A-Z0-9_]+)[ \t]+([0-9]+)(.*)/[\2] = "\L\1",/p';\
#   echo "};" >> $@ ;\
#   printf '%s' '\#define AA_SFS_AF_MASK "' >> $@ ;\
#   sed -r -n -e "/AF_MAX/d" -e "/AF_LOCAL/d" -e "/AF_ROUTE/d" -e \
#    's/^\#define[ \t]+AF_([A-Z0-9_]+)[ \t]+([0-9]+)(.*)/\L\1/p'\
#    $< | tr '\n' ' ' | sed -e 's/ $$/"\n/' >> $@

# Build a lower case string table of sock type names
# Transform lines from
#    SOCK_STREAM    = 1,
# to
#    [1] = "stream",
#quiet_cmd_make-sock = GEN     $@
#cmd_make-sock = echo "static const char *sock_type_names[] = {" >> $@ ;\
#   sed $^ >>$@ -r -n \
#   -e 's/^\tSOCK_([A-Z0-9_]+)[\t]+=[ \t]+([0-9]+)(.*)/[\2] = "\L\1",/p';\
#   echo "};" >> $@

# Build a lower case string table of capability names
# Transforms lines from
#    #define CAP_DAC_OVERRIDE     1
# to
#    [1] = "dac_override",
#quiet_cmd_make-caps = GEN     $@
#cmd_make-caps = echo "static const char *const capability_names[] = {" > $@ ;\
#   sed $< >>$@ -r -n -e '/CAP_FS_MASK/d' \
#   -e 's/^\#define[ \t]+CAP_([A-Z0-9_]+)[ \t]+([0-9]+)/[\2] = "\L\1",/p';\
#   echo "};" >> $@ ;\
#   printf '%s' '\#define AA_SFS_CAPS_MASK "' >> $@ ;\
#   sed $< -r -n -e '/CAP_FS_MASK/d' \
#       -e 's/^\#define[ \t]+CAP_([A-Z0-9_]+)[ \t]+([0-9]+)/\L\1/p' | \
#        tr '\n' ' ' | sed -e 's/ $$/"\n/' >> $@


# Build a lower case string table of rlimit names.
# Transforms lines from
#    #define RLIMIT_STACK       3   /* max stack size */
# to
#    [RLIMIT_STACK] = "stack",
#
# and build a second integer table (with the second sed cmd), that maps
# RLIMIT defines to the order defined in asm-generic/resource.h  This is
# required by policy load to map policy ordering of RLIMITs to internal
# ordering for architectures that redefine an RLIMIT.
# Transforms lines from
#    #define RLIMIT_STACK       3   /* max stack size */
# to
# RLIMIT_STACK, 
#
# and build the securityfs entries for the mapping.
# Transforms lines from
#    #define RLIMIT_FSIZE        1   /* Maximum filesize */
#    #define RLIMIT_STACK       3   /* max stack size */
# to
# #define AA_SFS_RLIMIT_MASK "fsize stack"
#quiet_cmd_make-rlim = GEN     $@
#cmd_make-rlim = echo "static const char *const rlim_names[RLIM_NLIMITS] = {" \
#   > $@ ;\
#   sed $< >> $@ -r -n \
#       -e 's/^\# ?define[ \t]+(RLIMIT_([A-Z0-9_]+)).*/[\1] = "\L\2",/p';\
#   echo "};" >> $@ ;\
#   echo "static const int rlim_map[RLIM_NLIMITS] = {" >> $@ ;\
#   sed -r -n "s/^\# ?define[ \t]+(RLIMIT_[A-Z0-9_]+).*/\1,/p" $< >> $@ ;\
#   echo "};" >> $@ ; \
#   printf '%s' '\#define AA_SFS_RLIMIT_MASK "' >> $@ ;\
#   sed -r -n 's/^\# ?define[ \t]+RLIMIT_([A-Z0-9_]+).*/\L\1/p' $< | \
#       tr '\n' ' ' | sed -e 's/ $$/"\n/' >> $@

$(obj)/capability.o : $(obj)/capability_names.h
$(obj)/net.o : $(obj)/net_names.h
$(obj)/resource.o : $(obj)/rlim_names.h
$(obj)/capability_names.h : $(srctree)/include/uapi/linux/capability.h \
                $(src)/Makefile
    $(call cmd,make-caps)
$(obj)/rlim_names.h : $(srctree)/include/uapi/asm-generic/resource.h \
              $(src)/Makefile
    $(call cmd,make-rlim)
$(obj)/net_names.h : $(srctree)/include/linux/socket.h \
             $(srctree)/include/linux/net.h \
             $(src)/Makefile
    $(call cmd,make-af)
    $(call cmd,make-sock)

Raspberry Piでnative buildした時にRaspberry Piのsecurity/apparmorディレクトリに生成されるcapability_names.h、rlim_names.h、net_names.hをMacのsecurity/apparmorフォルダにコピーする。Raspberry Pi Model 4B 2GBでデフォルトの設定でkernel 5.18をビルドした際に生成される各ファイルの内容は下記の通り。

capability_names.h

static const char *const capability_names[] = {
[0] = "chown",
[1] = "dac_override",
[2] = "dac_read_search",
[3] = "fowner",
[4] = "fsetid",
[5] = "kill",
[6] = "setgid",
[7] = "setuid",
[8] = "setpcap",
[9] = "linux_immutable",
[10] = "net_bind_service",
[11] = "net_broadcast",
[12] = "net_admin",
[13] = "net_raw",
[14] = "ipc_lock",
[15] = "ipc_owner",
[16] = "sys_module",
[17] = "sys_rawio",
[18] = "sys_chroot",
[19] = "sys_ptrace",
[20] = "sys_pacct",
[21] = "sys_admin",
[22] = "sys_boot",
[23] = "sys_nice",
[24] = "sys_resource",
[25] = "sys_time",
[26] = "sys_tty_config",
[27] = "mknod",
[28] = "lease",
[29] = "audit_write",
[30] = "audit_control",
[31] = "setfcap",
[32] = "mac_override",
[33] = "mac_admin",
[34] = "syslog",
[35] = "wake_alarm",
[36] = "block_suspend",
[37] = "audit_read",
[38] = "perfmon",
[39] = "bpf",
[40] = "checkpoint_restore",
};
#define AA_SFS_CAPS_MASK "chown dac_override dac_read_search fowner fsetid kill setgid setuid setpcap linux_immutable net_bind_service net_broadcast net_admin net_raw ipc_lock ipc_owner sys_module sys_rawio sys_chroot sys_ptrace sys_pacct sys_admin sys_boot sys_nice sys_resource sys_time sys_tty_config mknod lease audit_write audit_control setfcap mac_override mac_admin syslog wake_alarm block_suspend audit_read perfmon bpf checkpoint_restore"

net_names.h

static const char *address_family_names[] = {
[0] = "unspec",
[1] = "unix",
[2] = "inet",
[3] = "ax25",
[4] = "ipx",
[5] = "appletalk",
[6] = "netrom",
[7] = "bridge",
[8] = "atmpvc",
[9] = "x25",
[10] = "inet6",
[11] = "rose",
[13] = "netbeui",
[14] = "security",
[15] = "key",
[16] = "netlink",
[17] = "packet",
[18] = "ash",
[19] = "econet",
[20] = "atmsvc",
[21] = "rds",
[22] = "sna",
[23] = "irda",
[24] = "pppox",
[25] = "wanpipe",
[26] = "llc",
[27] = "ib",
[28] = "mpls",
[29] = "can",
[30] = "tipc",
[31] = "bluetooth",
[32] = "iucv",
[33] = "rxrpc",
[34] = "isdn",
[35] = "phonet",
[36] = "ieee802154",
[37] = "caif",
[38] = "alg",
[39] = "nfc",
[40] = "vsock",
[41] = "kcm",
[42] = "qipcrtr",
[43] = "smc",
[44] = "xdp",
[45] = "mctp",
};
#define AA_SFS_AF_MASK "unspec unix inet ax25 ipx appletalk netrom bridge atmpvc x25 inet6 rose netbeui security key netlink packet ash econet atmsvc rds sna irda pppox wanpipe llc ib mpls can tipc bluetooth iucv rxrpc isdn phonet ieee802154 caif alg nfc vsock kcm qipcrtr smc xdp mctp"
static const char *sock_type_names[] = {
[1] = "stream",
[2] = "dgram",
[3] = "raw",
[4] = "rdm",
[5] = "seqpacket",
[6] = "dccp",
[10] = "packet",
};

rlim_names.h

static const char *const rlim_names[RLIM_NLIMITS] = {
[RLIMIT_CPU] = "cpu",
[RLIMIT_FSIZE] = "fsize",
[RLIMIT_DATA] = "data",
[RLIMIT_STACK] = "stack",
[RLIMIT_CORE] = "core",
[RLIMIT_RSS] = "rss",
[RLIMIT_NPROC] = "nproc",
[RLIMIT_NOFILE] = "nofile",
[RLIMIT_MEMLOCK] = "memlock",
[RLIMIT_AS] = "as",
[RLIMIT_LOCKS] = "locks",
[RLIMIT_SIGPENDING] = "sigpending",
[RLIMIT_MSGQUEUE] = "msgqueue",
[RLIMIT_NICE] = "nice",
[RLIMIT_RTPRIO] = "rtprio",
[RLIMIT_RTTIME] = "rttime",
};
static const int rlim_map[RLIM_NLIMITS] = {
RLIMIT_CPU,
RLIMIT_FSIZE,
RLIMIT_DATA,
RLIMIT_STACK,
RLIMIT_CORE,
RLIMIT_RSS,
RLIMIT_NPROC,
RLIMIT_NOFILE,
RLIMIT_MEMLOCK,
RLIMIT_AS,
RLIMIT_LOCKS,
RLIMIT_SIGPENDING,
RLIMIT_MSGQUEUE,
RLIMIT_NICE,
RLIMIT_RTPRIO,
RLIMIT_RTTIME,
};
#define AA_SFS_RLIMIT_MASK "cpu fsize data stack core rss nproc nofile memlock as locks sigpending msgqueue nice rtprio rttime"

以上の手順でMacのcross-compileでAppArmorがビルドできるようになりました。

Scheduling policyのFIFOとRound-robin (RR)はデフォルトでは有効になってないよって話

タイトル出オチです。RTパッチを当ててもRTなscheduling policyはデフォルトで無効です。make menuconfigする時に忘れず有効にすること。

UpmpdcliとMPDの間にSquidを挟んでキャッシュする際の設定

/etc/squid/squid.confの必要部分抜粋

refresh_pattern .(aif|aiff|wav|flac|m4a|mp3)$/i 0 0% 240 reload-into-ims ignore-reload ignore-no-cache ignore-no-store >

cache_mem 2560 MB
maximum_object_size_in_memory 2 GB
memory_cache_mode always
memory_pools on

maximum_object_size_in_memoryはとりあえずFAT32のファイルサイズの上限2GB。cache_memは2GB以上の適当な数値ということで2560 MB (=2.5 GB)。2GBのファイルが連続して送られて来た場合の動作は確認していません…。メモリが4GB以上あるモデルのラズパイ4Bを前提とした設定です。

refresh_patternは毎回新規のファイルが来るものとしてminは0、percent 0、CDクオリティ(16bit 44.1kHz)のファイルで2GBの場合ざっくり230分なので、maxは230より少し多めの240。

2022年5月21日追記:
以下はAudirvanaからのALACデコード時のUPnP出力をフリーズせずに再生するための暫定の対応。ALAC再生の際、まだ音が途切れたりするので引き続き要調査。
/etc/mime.confの必要部分抜粋

\.wav$          audio/wav                    silk/music.png                  -       ascii   +download +view
\.wav$          audio/x-wav                  silk/music.png                  -       ascii   +download +view
\.wav$          text/html                    silk/music.png                  -       ascii   +download +view

Raspberry Pi 4BのUSB 2.0バスパワーのカット方法

$ echo -n "1-1" | sudo tee /sys/bus/usb/drivers/usb/unbind

https://artfinex.co.jp/wp/wp-content/uploads/2019/03/afx_RaspberryPiRaspbianUSB_Reset_UHF.pdf

2022年5月29日追記: 上記だとデバイスが接続されているポートをunbindするだけだったので結局hub-ctrlを導入しました。

third-encore.hatenablog.com

Linuxのオーディオ / 割込関連プロセスの優先度を上げる

現状core 0にOS関連、core 1にMPD、core 2にPipeWire、core 3にupmpdcliを割り当てているのですが、OS関連プロセスの中からaudio関連のプロセスの優先度を上げる方法がALSAのサイトに載っていました。

www.alsa-project.org

 

/etc/security/limits.conf に下記を追加

@audio - rtprio 95

@audio - memlock 512000

@audio - nice -19

 

 

usermodコマンドでユーザー pi を audio グループに追加

$ usermod -aG audio pi

 

/etc/rc.local で割り込みとtimerの優先度を上げる。

sudo chrt -f -p 95 `pgrep irq_work/0`

sudo chrt -f -p 95 `pgrep irq_work/1`

sudo chrt -f -p 95 `pgrep irq_work/2`

sudo chrt -f -p 95 `pgrep irq_work/3`

sudo chrt -f -p 95 `pgrep irq/17-fe804000.i2c`

sudo chrt -f -p 95 `pgrep irq/20-DMA`

sudo chrt -f -p 95 `pgrep irq/22-DMA`

sudo chrt -f -p 95 `pgrep irq/35-eth0`

sudo chrt -f -p 95 `pgrep irq/36-eth0`

sudo chrt -f -p 95 `pgrep ksoftirqd/0`

sudo chrt -f -p 95 `pgrep ksoftirqd/1`

sudo chrt -f -p 95 `pgrep ksoftirqd/2`

sudo chrt -f -p 95 `pgrep ksoftirqd/3`

sudo chrt -f -p 95 `pgrep ktimers/0`

sudo chrt -f -p 95 `pgrep ktimers/1`

sudo chrt -f -p 95 `pgrep ktimers/2`

sudo chrt -f -p 95 `pgrep ktimers/3`

 

としました。スケジューリング・ポリシーと優先度の設定はこれから詰めます。