# Lab 5: Introdução a planos de dados programáveis com a linguagem P4
## Objetivos
Este laboratório possui como objetivo geral introduzir o conceito de planos de dados programáveis por meio da linguagem P4 (Programming Protocol-independent Packet Processors - https://p4.org). Os objetivos específicos deste laboratório incluem:
• Permitir ao aluno melhorar a sua compreensão do funcionamento de equipamentos de rede, principalmente no que diz respeito ao plano de dado em relação a funções básicas de análise de cabeçalhos (parsing), endereçamento e comutação de pacotes.
• Abordar os princípios de projeto de sistema embarcado com foco no plano de dados (datapath) de dispositivos de redes e sua programação através da linguagem P4 versão 16.
• Desenvolver atividades práticas com a linguagem P4.
O material desta atividade foi adaptado a partir do tutorial P4 disponível no endereço https://github.com/p4lang/tutorials
## Materiais necessários
Para realizar esta atividade o aluno necessitará dos seguintes pacotes
No Linux, precisamos de:
• VirtualBox
• Virtual Machine (VM) do P4
No Windows, precisamos de:
• VirtualBox
• Virtual Machine (VM) do P4
A VM do P4 pode ser baixada no link https://drive.google.com/file/d/1wWi5I-ioEUWQ_HjjcLYLWcFh7vpYYMIp/view?usp=sharing
::: warning
Atenção: Os equipamentos devem ter 25GB ou mais livres de espaço em disco para importar a VM.
:::
## Configuração
A VM roda o SO Ubuntu 16.04 e dispõe de todas as funcionalidades do Mininet e da linguagem P4 já instaladas. Além disso, a VM possui todos os arquivos e pacotes necessários para utilização nas atividades do laboratório. Dessa forma, o aluno não precisará instalar quaisquer ferramentas para realizar esta atividade.
Todas as dicas e configurações mostradas para VirtualBox e acesso SSH podem ser realizadas pelo próprio aluno em um computador pessoal.
Primeiro acesso à Máquina Virtual:
:::info
Para acessar a VM do P4 utilize as seguintes credenciais:
Login: p4
Password: p4
:::
## Contexto
### Arquitetura tradicional de equipamento de rede
Analisando uma arquitetura clássica de roteador (veja Fig. 1) nos permite observar que esta se trata de um modelo formado basicamente por dois planos distintos: o software de controle e o hardware dedicado ao processamento de pacotes. O plano de controle é encarregado de implementar protocolos de roteamento e tomar decisões tais como escolha da melhor rota, transferindo essas decisões (ex: tabela de encaminhamento) para o plano de dados através de uma API proprietária.
A única interação externa que um roteador pode receber ocorre através de interfaces de configuração, como por exemplo Web, SNMP, CLI. Isto limita o uso do dispositivo às funcionalidades programadas pelo fabricante dos circuitos integrados (ASIC - Application Specific Integrated Circuits) como funções fixas implementadas em hardware por questão de desempenho e custo. Por ser uma implementação em hardware, o usuário do dispositivo não consegue instalar ou alterar as funcionalidades do plano de dados que faz o processamento de pacotes em altas taxas de transmissão.
O Plano de dados, majoritariamente proprietário, dedicado e fixo (veja Fig. 2), torna difícil a definição de novas características para o processamento de pacotes, o que prejudica a inovação. Por exemplo, para que se modifique o plano de dados, um novo design de todo o conjunto de hardware deve ser realizado, para que então um novo ASIC seja produzido, distribuído e instalado: um processo de alto custo e longa duração. Daí a necessidade da proposta de um plano de dados flexível, cujo funcionamento possa ser alterado conforme a necessidade, isto é, um plano de dados programável.

### Plano de dados programável
Buscando a flexibilidade para definição de comportamentos específicos no tratamento do encaminhamento de pacotes em redes programáveis (veja Fig. 2), a linguagem P4 abstrai a programação do plano de dados de redes, almejando três objetivos:
• Independência do protocolo: O dispositivo deve ser capaz de analisar qualquer tipo de protocolo desde que este seja declarado anteriormente no programa . Como por exemplo, análise de cabeçalho e ações usando o modelo de Match+Action típico do protocol Openflow;
• Independência de arquitetura: O programa P4 deve abstrair a camada física, isto é, deve ser o mesmo independente do equipamento alvo (target) no qual está sendo aplicado, mesmo que diferentes tecnologias SW/HW sejam utilizadas. Dessa forma, as peculiaridades de cada equipamento devem ser tratadas pelo próprio compilador;
• Reconfiguração em campo: O processamento dos pacotes pode ser alterado uma vez implantado, até mesmo em tempo de execução.


A linguagem P4 se baseia na arquitetura PISA (Protocol-Independent Switch Architecture) caraterizado por hardware baseado em um pipeline que permite (re)configuração usando o modelo de Match+Action (veja Fig. 3). Dessa forma, diferentemente dos ASICs tradicionais com funções fixas, a arquitetura provê grande flexibilidade sem comprometer a performance (chips com capacidade na mesma ordem de Tb/s suportados em ASICs).
Na linguagem P4 os principais blocos programáveis são parsers e controls (veja Fig. 4). Parsers são implementados como máquinas de estado com o propósito de extrair campos de cabeçalhos de pacotes de forma definida pelo usuário. Controls são responsáveis pelo processamento principal de pacotes em estruturas match-action. Aqui as regras de tabelas e ações são definidas para manipular cabeçalhos de pacotes e meta-dados (metadata). O programador/usuário é responsável por realizar a codificação de parsers e controls por meio de diferentes tipos de estruturas de dados e expressões providas pela linguagem P4 [(1)](https://opennetworking.org/wp-content/uploads/2020/12/p4-cheat-sheet.pdf).
Em contrapartida, as estruturas de definição de arquitetura e bibliotecas externas podem ser definidas pelo fabricante de equipamento onde o programa P4 irá ser executado. Enquanto externs já são estruturas especializadas que definem rotinas como caixas-pretas que o programa P4 pode utilizar em sua execução.


A estrutura de um programa escrito na linguagem P4 (veja Fig. 5) possui diferentes elementos, dentre eles:
• Headers: representam estruturas de dados que referenciam campos nos cabeçalhos de pacotes
• Parser: responsáveis pela análise e extração dos campos de pacotes;
• Deparser: responsáveis pela modificação final de cabeçalhos de pacotes;
• Ingress: depois de passarem pelo parser pacotes são encaminhados a ingress onde podem ter ações aplicadas sobre eles dependendo de estruturas de tabelas, definindo assim filas e portas de saída para os pacotes;
• Egress: antes de deixar o pipeline, pacotes podem ter ações aplicadas sobre eles em egress, com a realização de modificações nos cabeçalhos de pacotes;
• Tables: mecanismo que faz o processamento de pacotes por meio de correspondên-
cias (key/matches) e suas respectivas ações associadas a serem executadas sobre os
pacotes;
• Actions: conjunto de primitivas a serem aplicadas (possivelmente por funções customizadas) sobre pacotes;
• Control: estabelece o fluxo de processamento de pacotes do programa P4 utilizando os blocos previamente declarados.

Em um exemplo de programa P4 (veja Fig. 6), temos: (1) a estrutura de controle do switch “V1Switch”2 determinando todos os blocos de control sequencialmente pelos quais os pacotes serão tratados; (2) MyParser realizando o accepts de todos os pacotes recebidos pelo switch; (3) MyIngress realizando a simples alteração de portas de encaminhamento de pacotes (onde pacotes recebidos na porta 1 são encaminhados para porta 2 e vice-versa) (4) e os outros blocos de control não realizando nenhuma operação sobre os pacotes. Note que em cada um dos blocos de controle a função apply() realiza a chamada de ações a serem realizadas em pacotes.
:::info
Obs.: O termo switch, assim como em Openflow, é usado na comunidade P4 para fazer referência ao equipamento de rede de maneira genérica e não deve ser associado ao termo tradicional de um switch de camada 2 com as funções clássicas de computação e aprendizado de endereços MAC / Ethernet.
:::

## Atividades práticas
Nas atividades a seguir iremos trabalhar na análise, no design e na implementação de um programa P4 para o encaminhamento básico de pacotes entre hosts de uma topologia emulada no Mininet (veja Fig. 7).
### Atividade 1: Análise do programa P4
Inicialize a máquina virtual, e ao realizar login na máquina virtual, abra um terminal (ctrl+alt+t), e entre na pasta:
```
$ cd /home/p4/tutorials/exercises/basic
```
Nesta pasta abra o arquivo
```
$ subl basic.p4
```
:::info
Q. 1: Analisando o programa aberto indique (referenciando a linha ou colando parte do código) onde ocorrem as seguintes operações:
• Definição dos cabeçalhos Ethernet e IPv4 de pacotes
• Parser dos cabeçalhos Ethernet e IPv4 de pacotes
• Procura de destino IPv4 na tabela de roteamento
• Atualização de endereços MAC fonte e destino
• Decremento do campo time-to-live (TTL) do pacote
• Definição da porta de saída (egress) do pacote
• Cálculo do checksum
:::

### Atividade 2: Compilação e execução do programa P4
Agora vamos realizar a execução deste programa P4 na topologia Mininet previamente mostrada. Para isto na pasta
```
cd /home/p4/tutorials/exercises/basic
```
execute o comando:
```
make
```
Este comando realiza a compilação do programa basic.p4, e utiliza o código compilado para definir o switch base a ser executado pela plataforma Mininet. Ou seja, os switches mostrados na Fig. 7 serão uma instância deste programa P4.
Em seguida o script realiza a configuração das tabelas de encaminhamento de cada um dos switches (s1, s2, s3, s4) utilizando os arquivos “s[1,2,3,4]-runtime.json”.
Após a execução do comando “$ make”, no console mostrado da plataforma Mininet execute:
```
mininet> xterm h1 h4
```
para abrir os consoles externos dos hosts h1 e h4.
Na janela do xterm de h4 execute o comando:
```
./receive.py
```
E na janela do xterm de h1 execute o comando:
```
./send.py 10.0.4.4 "P4 is cool"
```
Estes programas realizam respectivamente a captura de pacote em h4 e o envio de 1 pacote de h1.
:::info
Q. 2: Com base no comportamento dos switches, explique:
• Por quê os campos Ethernet (src e dst) do pacote enviado em h1 e recebido em h4 são diferentes?
• Quais ações foram aplicadas pelos switches sobre o pacote?
• A diferença dos valores de TTL do pacote enviado e recebido estão corretos? Por quê?
:::
Para realizar o termino da execução da topologia Mininet, execute no console o comando:
```
mininet> exit
```
### Atividade 3: Programando em P4: Comunicação entre alunos de diferentes planetas
Uma das características mais importantes do P4 é permitir definir novos protocolos (ex: definição de cabeçalhos e funcionalidades) ou modificar protocolos existentes.
Nesta atividade vamos definir um novo protocolo "planet" que vai ser encapsulado num quadro Ethernet. O arquivo P4 já vai estar disponível e precisaremos apenas adicionar o novo cabeçalho.
O nosso novo protocolo "planet" esta definido como Ethernet type 0x66AA. Ele consta de 3 campos: source (Planeta origem), destination (Planeta destino) e seq (RA do aluno).
O código do P4 também inclui funções de encaminhamento do pacote usando o valor do RA como entrada instalada pelo plano de controle na tabela do switch (Obs. a linguagem P4 só define as estruturas de dados das tabelas, o seu preenchimento com valores é função do plano de controle!).
Para adicionar nosso novo cabeçalho vamos na pasta:
```
cd /home/p4/Class/BB-Gen/
```
E abrimos o código do P4:
```
vim examples/p4_src/planets.p4
```
O código tem que se adicionar logo em baixo de:
```
//–––––TODO–––––//
```
O cabeçalho tem que ter o nome planet_t com 3 campos: source (size of 24 bits), destination (size of 24 bits) e seq (size of 32 bits).
Obs.: Dentro da pasta examples/p4_src/ tem vários exemplos de códigos P4 - é possível utilizá-los como ajuda para definir o cabeçalho.
:::info
Q. 3: Desenhe o formato do novo cabeçalho proposto seguindo as práticas usadas em protocolos padronizados pelo IETF (vide como exemplo a figura 9 no final do roteiro).
:::
Depois de ter nosso código P4 completo, vamos compilar e gerar os arquivos para sua execução e teste.
Na pasta /home/p4/Class/BB-Gen/ executamos o script:
```
./install.sh <RA>
```
por exemplo:
```
./install.sh 111111
```
Esse script vai compilar o P4 (se tiver algum error no código ele vai mostrar), vai gerar os arquivos para visualização do nosso novo protocolo em Wireshark, vai gerar o PCAP com pacotes com nosso novo protocolo e vai prepara os arquivos de teste com Mininet.
Se não tiver nenhum erro na execução do comando, vamos para a pasta:
```
cd /home/p4/tutorials/exercises/planet/
```
E executamos nossa topologia (Fig. 8):

```
make
```
para abrir os consoles externos dos hosts h1 e h2:
```
mininet> xterm h1 h2
```
Nas janelas do xterm de h1 e h2 iniciamos a captura do trafego na interface eth0 executando o seguinte comando em cada um dos hosts:
```
$ wireshark &
```
:::warning
Obs.: Se tiver o erro <em>Lua: Error during loading</em>, pode pressionar OK.
:::
Na janela do xterm de h1 execute o comando
```
./send.sh
```
:::info
Q. 4: Os pacotes foram recebidos em h2?
:::
Agora, na janela do xterm de h2 execute o comando
```
$ ./send.sh
```
:::info
Q. 5: Os pacotes foram recebidos em h1?
:::
Se olharmos no inicio da execução do Mininet (depois do comando $ make),teremos linhas como as seguintes:
```
planet_fib_match: planet.seq=111111 => fib_hit_nexthop(dmac=08:00:00:00:01:11, port=1)
planet_fib_match: planet.seq=222222 => fib_hit_nexthop(dmac=08:00:00:00:02:00, port=2)
```
Elas representam as informações (resultados da lógica do plano de controle) que estão sendo instaladas nas tabelas do switch.
:::info
Q. 6: Explique qual estado (conteúdo das entradas nas tabelas) as linhas representam.
:::
:::warning
Obs 1. Pode ser necessário olhar o código P4 modificado para uma melhor compreensão.
Obs 2. As interfaces físicas do switch são representadas por portas (port 1, port 2) na figura 8 se mostram quais são as portas da simulação.
:::
Nas capturas de Wireshark podemos observar o protocolo que criamos: P4_PLANET Protocol. Olhe o valor do seq dos pacotes enviados em h1 e em h2.
:::warning
Obs.: O valor mostrado no Wireshark esta em HEX, para saber o valor em decimal pode usar uma ferramenta online como https://www.rapidtables.com/convert/number/hex-to-decimal.html
:::
:::info
Q. 7: Qual é a relação desse valor com o resultado do comando $ ./send.sh em h1 e em h2?.
Q. 8: Envie junto com o relatório as capturas do Wireshark de h1 e h2.
Q. 9: Voltando ao contexto inicial da atividade, considerando o tamanho dos campos no cabeçalho, quantos alunos e quantos planetas poderiam ser suportados? Descreva de foram sucinta como poderiam ser usados os campos no cabeçalho para comunicações (envio e recepção de pacotes) entre alunos de diferentes planetas.
:::
### Atividade 4: Calculadora P4 (OPCIONAL)
A ideia principal desta atividade é escrever um programa P4 para realizar o cálculo simples de algumas operações matemáticas de acordo com os campos de cabeçalho de pacotes.
Para acessar a atividade vamos para a pasta:
```
$ cd /home/p4/
```
Criamos e acessamos a pasta calc:
```
mkdir calc
cd calc
```
Baixamos o repositório:
```
git clone https://github.com/p4lang/tutorials.git
``````
Agora copie a pasta "calc"da atividade para dentro do ambiente da VM:
```
cp -r tutorials/exercises/calc/ /home/p4/tutorials/exercises/
```
Entre na pasta:
```
cd /home/p4/tutorials/exercises/calc
```
Antes, é necessário instalar as dependências necessárias:
```
sudo apt-get update
sudo apt-get -y install python3-pip
pip3 install scapy
```
E a execução de todo o programa se dá de forma similar a atividade anterior com o comando:
```
make
```
Isto irá compilar o código do programa calc.p4 e instanciar uma topologia mininet com um switch e dois hosts. Para enviar os pedidos de operações matemáticas ao switch no console do mininet digite:
```
mininet> h1 python3 calc.py
```
e em seguida no prompt que abrir, apenas digite os comandos dos pedidos de cálculos para o switch (ex.: 1+1) e tecle enter. Um pacote será criado e enviado ao switch, este realizará o processamento do pacote de acordo com o programa calc.p4 e irá retornar o pacote ao host com o resultado que será mostrado na tela do console no Mininet. O cabeçalho do pacote é criado de acordo com:
• P is an ASCII Letter ’P’ (0x50)
• 4 is an ASCII Letter ’4’ (0x34)
• Version is currently 0.1 (0x01)
• Op is an operation to Perform:
• ’+’ (0x2b) Result = OperandA + OperandB
• ’-’ (0x2d) Result = OperandA - OperandB
• ’&’ (0x26) Result = OperandA & OperandB
• ’|’ (0x7c) Result = OperandA | OperandB
• ’ˆ’(0x5e) Result = OperandA ˆ OperandB

O cabeçalho da calculadora (veja Fig. 9) é enviado sobre Ethernet com tipo 0x1234. A tarefa desta atividade é realizar a codificação do arquivo calc.p4. Não há programação no plano de controle a ser feita, a única implementação se dá no arquivo calc.p4. O arquivo calc.p4 realiza o parse do cabeçalho customizado, executa a operação matemática, escreve o resultado no campo result do pacote, e retorna o pacote para o remetente.
:::info
Q. 11: Quais as modificações realizadas no programa calc.p4 que realizam a programação correta para a execução dos testes de operações matemáticas? Copie o código com as modificações no relatório.
:::