Arquivo de etiquetas: raspberry pi

Recompilando o kernel na Raspberry Pi 4

Adquiri a Raspberry Pi 4 com o objetivo de realizar alguns experimentos com eBPF/XDP para filtragem de pacotes e este modelo em específico por ter uma interface Ethernet Gigabit disponível.

O Problema

O Raspberry Pi 4 vem nativo com o Kernel 4.19.75-v7l+ e um primeiro passo é checar se os módulos que eu preciso, relativos ao eBPF/XDP, estão habilitados no kernel.

Isto é feito verificando-se o arquivo config:

$sudo modprobe configs
$ zgrep -E "(BPF|XDP)" /proc/config.gz

CONFIG_BPF=y
# CONFIG_BPF_SYSCALL is not set
CONFIG_NETFILTER_XT_MATCH_BPF=m
# CONFIG_BPFILTER is not set
# CONFIG_NET_CLS_BPF is not set
# CONFIG_NET_ACT_BPF is not set
# CONFIG_BPF_JIT is not set
CONFIG_HAVE_EBPF_JIT=y
# CONFIG_NBPFAXI_DMA is not set
# CONFIG_TEST_BPF is not set

O comando acima já permitiu verificar que alguns módulos do kernel relativos ao eBPF não estão ativos. O módulo do XDP nem apareceu na listagem.

Para ativar esses módulos no kernel é necessario realizar uma recompilação do kernel, objetivo desse texto.

Obtendo o kernel

A fonte oficial do Raspberry sobre recompilação do Kernel (em inglês chamado de build) demonstra um passo a passo que vou realizar neste texto e mostra também a possibilidade de realizar uma compilação cruzada (cross-compiling).

A compilação cruzada é muito útil quando sua plataforma embarcada não tem muita capacidade de processamento. Esta restrição em processamento pode resultar em muito tempo para compilar o kernel  ou mesmo não ter espaço suficiente para baixar o código fonte do kernel. Neste texto, farei uma compilação local.

Um primeiro passo é obter todas as ferramentas necessárias via apt:

$ sudo apt-get install git bc bison flex libssl-dev

Em seguida, deve-se baixar o código fonte do kernel no github do Raspberry Pi.

Como estou com o kernel na versão mais atual, não preciso me preocupar em qual branch do github vou pegar o kernel, o atual corresponde ao mesmo kernel que o meu (Branch: rpi-4.19.y), caso o branch atual seja uma versão mais a frente da sua e você não quer atualizar o kernel mas apenas recompilar sua versão atual, atente-se a isso.

Para quem já está acostumado ao ambiente Linux é comum pensar que todo o código do kernel deve ser baixado e compilado no diretório tradicional /usr/src/linux mas fazer isso nesse diretório envolve aspectos de segurança e por isso a boa prática é trabalhar no diretório do usuário sem privilégio root:

$ cd
$ mkdir kernel
$ cd kernel
$ git clone --depth=1 https://github.com/raspberrypi/linux

Configurando o kernel

Configurar o kernel, no nosso caso significa definir os módulos que serão compilados em conjunto com o kernel para resolver nosso problema.

Uma forma muito amigável de realizar essa tarefa é utilizar uma ferramenta chamada “menuconfig” ela apresenta uma interface gráfica que facilita a procura e escolha dos módulos mas para isso é necessário instalar a biblioteca do ncurses:

$ sudo apt-get install libncurses5-dev

Em seguida fazemos (para a Raspberry 4):

$ cd linux
$ KERNEL=kernel7l
$ make bcm2711_defconfig

E finalmente rodamos o menuconfig para configurar os módulos que desejo para essa recompilação:

$ make menuconfig

A navegação no menuconfig e intuitiva e possui as instruções logo no início (setas, barra de espaco, enter, teclas Y/N/M/*), uma dica legal no uso do menuconfig é que você pode pressionar a tecla / que irá abrir uma caixa de busca e assim você pode localizar onde estão os módulos que você deseja ativar.

Por exemplo, digitei xdp na busca e confirmei que o XDP_SOCKETS está em Networking Support -> Network options, ele também mostrou que para ativar esse módulo preciso (“depends on”) ativar o suporte a Network (NET) e a BPF_SYSCALL.

Dentro do menuconfig, faça a seguinte navegação para configurar o XDP/eBPF:

1) General setup <ENTER>
1.1) Enable bpf() system call <SPACE>
1.2) Permanently enable BPF JIT and remove BPF interpreter <SPACE>
1.3) Selecione <SAVE>

O SAVE irá gravar as modificações no arquivo .config

Em seguida, volte para o início do menuconfig e selecione:

1) Networking support <ENTER>
2) Networking options <ENTER>
2.1) XDP sockets <SPACE>
2.2) BPF based packet filtering framework <SPACE>
2.3) enable BPF Just In Time compiler <SPACE>
1.3) Selecione <SAVE>

Você ainda pode teclar / para abrir o menu de pesquisa do menuconfig e buscar por bpf para verificar os módulos que não estão selecionados (=n) e seguir o Location para incluí-los no objetivo da recompilação do kernel.

Após ativar os módulos referentes ao BPF e ao XDP, você pode sair do menuconfig… Como confirmação das modificações você pode executar os seguintes comandos:

$ cat .config | grep XDP
CONFIG_XDP_SOCKETS=y
$ cat .config | grep BPF
CONFIG_CGROUP_BPF=y
CONFIG_BPF=y
CONFIG_BPF_SYSCALL=y
CONFIG_BPF_JIT_ALWAYS_ON=y
CONFIG_NETFILTER_XT_MATCH_BPF=m
CONFIG_BPFILTER=y
CONFIG_BPFILTER_UMH=y
CONFIG_NET_CLS_BPF=m
CONFIG_NET_ACT_BPF=m
CONFIG_BPF_JIT=y
CONFIG_BPF_STREAM_PARSER=y
CONFIG_LWTUNNEL_BPF=y
CONFIG_HAVE_EBPF_JIT=y
# CONFIG_BPF_LIRC_MODE2 is not set
# CONFIG_NBPFAXI_DMA is not set
CONFIG_BPF_EVENTS=y
CONFIG_TEST_BPF=m

Recompilando o kernel

Com o arquivo .config montado corretamente via menuconfig podemos seguir com a recompilação do kernel (build):

$ 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

Detalhe que o argumento -j4 do make permite que a compilação utilize os quatro núcleos do processador da Raspberry Pi 4 acelerando este processo (vale também para a RPi 2 e 3).

Este processo leva um tempo razoável de execução e também aumenta consideravelmente a temperatura da Raspberry Pi, por isso e recomendável deixar a placa em um ambiente propício e se possível com uma ventoinha.

Verificando a recompilação

Conforme inicialmente apresentado como problema, esta etapa busca demonstrar o funcionamento do eBPF/XDP após recompilação do kernel, para isso farei uso de um script de exemplo disponível em meu github:

$ git clone https://github.com/gubertoli/ids_ml.git
$ cd ids_ml/examples/bpf
$ sudo apt-get install clang-7
$ make

Carregando na interface eth0:

$ sudo ip -force link set dev eth0 xdp obj portfilter.o sec filter

Verificando:

$ ip link show eth0

Removendo:

$ sudo ip link set dev eth0 xdp off

Configurando o RTL-SDR no Raspberry Pi 3

Este post apresenta a configuração do RTL-SDR para funcionar no Raspberry Pi 3 configurado com a distribuição Raspbian

RTL-SDR on Raspberry Pi 3
RTL-SDR no Raspberry Pi 3

Configurando tudo

Abra o terminal do Raspbian e digite os seguintes comandos:

pi@raspberrypi:~ $ sudo apt-get install gnuradio % leva algum tempo para instalar todos os pacotes

pi@raspberrypi:~ $ gnuradio-companion % se ele abrir o gnuradio-companion, está tudo ok

Instalando os pacotes RTL-SDR e gr-osmosdr

pi@raspberrypi:~ $ sudo apt-get install rtl-sdr gr-osmosdr

Após a instalação com sucesso, coloque o RTL-SDR na porta USB do Raspberry Pi 3 e então liste os dispositivos USB conectados:

pi@raspberrypi:~ $ lsusb

Procure por algo do tipo Realtek device (RTL), no exemplo abaixo “Realtek Semiconductor Corp. RTL2838 DVB-T”:

lsusb on Raspberry Pi 3
lsusb no Raspberry Pi 3

Agora é hora de verificar se o RTL-SDR está funcionando:

pi@raspberrypi:~ $ rtl_test

rtl_test on Raspberry Pi 3
rtl_test no Raspberry Pi 3

No meu caso ele funcionou na primeira tentativa no Raspberry Pi, no entanto, há um problema conhecido de conflito de drivers (já evidenciado no Ubuntu), em que ele associa um driver de TV Digital (dvb_usb_rtl28xxu) ao invés do rtl-sdr, caso tenha este problema, faça o seguinte:

pi@raspberrypi:~ $ sudo rmmod dvb_usb_rtl28xxu % para tornar este fix permanente, você deve mover o driver dvb_usb_rtl28xxu para a blacklist

e, tente novamente:

pi@raspberrypi:~ $ rtl_test

Testes

Instale o GQRX através do apt-get:

pi@raspberrypi:~ $ sudo apt-get install gqrx-sdr

Então execute-o:

pi@raspberrypi:~ $ gqrx

Se não for perguntado (pop-up) para selecionar o “I/O device”, vá em “File” > “I/O Devices” e então selecione Realtek RTL-SDR, agora você pode clicar no botão de “ligar” e será possível ouvir ruídos e ver que a tela de FFT (em cima) e a de waterfall (abaixo) funcionando…

Atenção:

Devido à limitações de processamento do Raspberry Pi, para evitar travamentos, você tem que reduzir a taxa de amostragem no GQRX, para isso acesse:: “File” > “I/O Devices” > “Sample Rate” ou edite o arquivo /home/pi/.config/gqrx/default.conf

RTL-SDR funciona com limite máximo de 2.4 Msps no Raspberry Pi 3 e até 1.44 Msps no Raspberry Pi 2.

Em muitos casos você pode reduzir a carga de processamento ainda mais, reduzindo o tamanho da tela, o sample rate, FFT rate e FFT size (tente 2048 at 10-15 Hz). Se você está interessando somente no FFT, defina Mode para “Demod Off”. Isto vai reduzir significativamente o processamento.

GQRX on Raspberry Pi 3
GQRX no Raspberry Pi 3

Outra opção devido a limitação do GQRX no  Raspberry Pi, você pode tentar o QTCSDR on GitHub que também permite fazer transmissão através do GPIO 18 do Raspberry Pi 3 (rpitx).

Para verificar a recepção:

  • git clone https://github.com/ha7ilm/qtcsdr
  • cd qtcsdr
  • ./rpi-install.sh
  • ./rpi-test.sh

Se o comando rpi-test.sh rodar sem problemas, digite qtcsdr na linha de comando.

pi@raspberrypi:~ $ qtcsdr

qtcsdr on Raspberry Pi 3
qtcsdr no Raspberry Pi 3

 

Parabéns! Agora seu RTL-SDR está funcionando no Raspberry Pi 3.