# Stratum com P4Runtime (shell) e cliente gNMI
:::info
Esta é uma breve demonstração de preparo de um ambiente de desenvolvimento para programação de um Network Interface Controller (NIC) Ethernet/Wi-Fi.
:::
:::warning
Pré-requisitos:
:grey_exclamation: Xubuntu ou Ubuntu (18.04LTS)
:grey_exclamation: Controlador SDN: ONOS
:grey_exclamation: Plataforma: Docker
:::
### OS: Linux Xubuntu & Ubuntu (18.04LTS)
### Hardware utilizado:
:::warning
Processor: Intel (R) Celeron (R) CPU N3050 @ 1.60GHz
Architecture: amd64 - Memory: 4GB - HD SSD: 120GB
:::
### Objetivo:
Demonstrar a utilização das interfaces P4Runtime e gNMI
![](https://i.imgur.com/pXLu1TZ.jpg)
<br>
![](https://i.imgur.com/P6Ill5Z.jpg)
<br>
### O que é P4Runtime ?
Uma API (Application Programming Interface) é uma interface de plano de controle SDN para controlar o comportamento de encaminhamento em tempo de execução. É a chave para preencher tabelas de encaminhamento e manipular o estado de encaminhamento, e o faz com base em um programa P4 e de forma agnóstica de hardware. Em outras palavras, a interface permanece a mesma quando seu comportamento de encaminhamento ou hardware muda. O P4Runtime foi desenvolvido por comunidades open source, com base na experiência de colocar o OpenFlow em produção, sendo assim o mesmo já está pronto para o hardware de rede de futuras gerações.
<br>
### O que é gNMI?
Uma API, conhecida como (gRPC Network Management Interface), tem como objetivo aprimorar as interfaces de configuração existentes usando uma representação binária na conexão, preferindo diffs de configuração a instantâneos e permitindo streaming bidirecional. Essas melhorias ajudam a superar as limitações de escala devido à pesquisa e grandes quantidades de transferência de dados, a gNMI utiliza os modelos OpenConfig, é totalmente independente de plataforma e pronto para SDN.
<br>
### O que é gNOI?
Uma API, conhecida como (gRPC Network Management Interface), que possui uma coleção de microsserviços que permitem operações específicas do switch, como gerenciamento de certificado, teste de dispositivo, atualização de software e solução de problemas de rede. A gNOI fornece uma API semanticamente rica que substitui as abordagens baseadas em CLI existentes.
<br>
#### Ilustração de uso das interfaces:
![](https://i.imgur.com/wBj4XQ5.png)
<br>
### O que é Stratum?
Trata-se de um um sistema operacional de switch independente de código aberto, aplicado a redes definidas por software, onde é possível construir uma distribuição aberta e mínima pronta para produção para equipamentos do tipo white box. O Stratum expõe um conjunto de interfaces SDN de próxima geração, incluindo P4Runtime e OpenConfig, permitindo a intercambialidade de dispositivos de encaminhamento e a programação de comportamentos de encaminhamento.
<br>
### Observação:
:::info
A implementação das interfaces externas baseadas em gRPC do Stratum é comum a todos os dispositivos de rede, e as chamadas que são direcionadas para o hardware passam por uma interface genérica do switch.
:::
<br>
#### <center> Topologia da demonstração:</center>
![](https://i.imgur.com/JMgEc6X.png)
<br>
### Execute os seguintes comandos para a demonstração:
sudo apt update && sudo apt upgrade -y
sudo apt install curl git tree htop vim golang -y
sudo go get -u github.com/openconfig/gnmi/cmd/gnmi_cli -y
cd /home/santorsula && sudo git clone https://github.com/stratum/tutorial
sudo mv tutorial/ projeto-feec/ && cd projeto-feec/ && sudo mv basic/ stratum/
cd stratum && sudo cp -R cfg /tmp
<br>
### Verificando a estrutura dos diretórios:
![](https://i.imgur.com/4idAacX.png)
<br>
![](https://i.imgur.com/6e4W5YB.png)
<br>
### Iniciando o Mininet e Stratum pelo Docker
sudo ./start-mn.sh
![](https://i.imgur.com/yx89198.png)
<br>
### P4Runtime Shell
O shell P4Runtime é uma CLI Python que irá se conectar a um switch (Stratum), podendo executar comandos na interface P4Runtime. Por exemplo, excluir entradas da tabela de fluxo. Quando o shell é iniciado, é preciso de uma configuração de pipeline P4, onde será necessário a ID de eleição de arbitragem de mestre e um ID de dispositivo.
Nesta demonstração, será utilizado o basic.p4 do ONOS, onde o mesmo possui uma única tabela de encaminhamento de interesse chamada table0. O ID da eleição de arbitragem de mestre pode ser um número arbitrário maior que 0, caso esteja executando com vários controladores, será preciso utilizar um mecanismo para obter consenso sobre qual controlador é o mestre.
Finalmente, é possível que os switches Stratum ofereçam suporte a vários chips de encaminhamento (ASICs). O ID do dispositivo é usado para chips diferentes no mesmo equipamento. Por padrão em switches de chip único, Stratum usa o ID de dispositivo de 1.
Nota: Se iniciar vários switches usando Mininet, será executado uma instância separada do Stratum para cada switch. Cada switch terá seu próprio servidor gRPC executando P4Runtime, e o switch terá um único "chip" de encaminhamento (instância de bmv2). Para se conectar a diferentes switches, caso seja preciso variar o endereço gRPC, por padrão, iremmos dixar o ID do dispositivo definido como 1.
sudo ./p4rt-shell.sh
![](https://i.imgur.com/DSUBMT4.png)
<br>
### Teste de ICMP entre o h1 e h2
mininet> h1 ping h2
![](https://i.imgur.com/kqwO8MX.png)
:::warning
Observamos que não temos troca de pacotes, devido a falta de duas entradas de tabelas, a primeira encaminhará o tráfego da porta 1 para a porta 2 e a segunda encaminhará o tráfego da porta 2 para a porta 1.
:::
<br>
### Criação da 1º tabela de entrada:
Criando a primeira entrada da tabela para table0 com ação definida como set_egress_port, com o shell P4Runtime sh:
```P4Runtime sh >>>```
```
te = table_entry["ingress.table0_control.table0"](action = "ingress.table0_control.set_egress_port")
te.priority = 1
te.match["standard_metadata.ingress_port"] = ("1")
te.action['port'] = ("2")
te.insert()
```
:::info
<center>Ilustração da sequencia de comandos executados na criação da 1º tabela:</center>
:::
![](https://i.imgur.com/L1VdW5t.png)
<br>
### Criação prioridades para tabelas:
Nesta etapa, a entrada da tabela para table0 com ação definida como set_egress_port, com o shell P4Runtime sh. A primeira combinação será a ingress_portde 1, em seguida será definido a saída pela porta 2, finalizado com a entrada na tabela, conforme a sequencia da programação abaixo:
```P4Runtime sh >>> te.priority = 1
te = table_entry["ingress.table0_control.table0"](action = "ingress.table0_control.set_egress_port")
te.priority = 1
te.match["standard_metadata.ingress_port"] = ("2")
te.action['port'] = ("1")
te.insert()
```
<br>
:::info
<center>Ilustração da sequencia de comandos executados na criação de prioridades:</center>
:::
![](https://i.imgur.com/AwU19rR.png)
<br>
Agora todo tráfego será encaminhado da porta 1 para a porta 2, mas nenhum tráfego fluirá na direção contrária, para finalizar, será realizado a entrada da tabela de fluxo da porta 2 para a porta 1, conforme os comandos a seguir:
```P4Runtime sh >>> te = table_entry["ingress.table0_control.table0"](action = "ingress.table0_control.set_egress_port")
P4Runtime sh >>> te.priority = 1
P4Runtime sh >>> te.match["standard_metadata.ingress_port"] = ("2")
P4Runtime sh >>> te.action['port'] = ("1")
P4Runtime sh >>> te.insert()
```
<br>
### Teste de ICMP entre o h1 e h2
mininet> h1 ping h2 -c 20
![](https://i.imgur.com/CfOEUPv.png)
<br>
### Executando leitura das tabelas:
Nesta etapa, é possível ler as entradas das tabelas table0 e verificar como foi construindo uma entrada vazia em uma tabela, com a entrada do comando a seguir:
```P4Runtime sh >>> te = table_entry["ingress.table0_control.table0"]```
<br>
Agora basta inciar a leitura com o read(), onde a entrada da tabela usa uma função que será executada para cada entrada, sendo assim apenas imprimiremos as entradas no P4Runtime sh, conforme os comandos a seguir:
```P4Runtime sh >>> te.read(lambda x: print(x))```
:::info
<center>Ilustração da leitura da tabela executado pelo comando anterior:</center>
:::
![](https://i.imgur.com/Gi6F9Gc.png)
<br>
### gNMI
Nesta etapa será utilizado gNMI CLI, que é desenvolvida em Python, onde esta CLI que permite fazer chamadas gNMI para um dispositivo Stratum, onde a cada chamada é possível listar todas as interfaces no dispositivo, para isso será preciso abrir uma nova janela de terminal para executar os comandos a seguir:
```sudo ./gnmi-cli.sh get /interfaces/interface[name=*]```
:::info
<center>Ilustração do comando executado na CLI gNMI anteriormente:</center>
:::
![](https://i.imgur.com/jCfR5Zf.png)
<br>
:::info
<center>Retorno "extenso" do comando executado na CLI gNMI anteriormente:</center>
:::
```
***************************
REQUEST
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "*"
}
}
}
encoding: PROTO
***************************
***************************
RESPONSE
notification {
timestamp: 1625677242104958473
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth1"
}
}
elem {
name: "config"
}
elem {
name: "enabled"
}
}
val {
bool_val: true
}
}
}
notification {
timestamp: 1625677242105129047
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth1"
}
}
elem {
name: "config"
}
elem {
name: "health-indicator"
}
}
val {
string_val: "GOOD"
}
}
}
notification {
timestamp: 1625677242105263057
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth1"
}
}
elem {
name: "config"
}
elem {
name: "loopback-mode"
}
}
val {
bool_val: false
}
}
}
notification {
timestamp: 1625677242105427206
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth1"
}
}
elem {
name: "ethernet"
}
elem {
name: "config"
}
elem {
name: "auto-negotiate"
}
}
val {
bool_val: false
}
}
}
notification {
timestamp: 1625677242105568129
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth1"
}
}
elem {
name: "ethernet"
}
elem {
name: "config"
}
elem {
name: "forwarding-viable"
}
}
val {
bool_val: true
}
}
}
notification {
timestamp: 1625677242105725327
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth1"
}
}
elem {
name: "ethernet"
}
elem {
name: "config"
}
elem {
name: "mac-address"
}
}
val {
string_val: "11:22:33:44:55:66"
}
}
}
notification {
timestamp: 1625677242105868125
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth1"
}
}
elem {
name: "ethernet"
}
elem {
name: "config"
}
elem {
name: "port-speed"
}
}
val {
string_val: "SPEED_10GB"
}
}
}
notification {
timestamp: 1625677242106070389
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth1"
}
}
elem {
name: "ethernet"
}
elem {
name: "state"
}
elem {
name: "auto-negotiate"
}
}
val {
bool_val: false
}
}
}
notification {
timestamp: 1625677242106229913
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth1"
}
}
elem {
name: "ethernet"
}
elem {
name: "state"
}
elem {
name: "forwarding-viable"
}
}
val {
bool_val: false
}
}
}
notification {
timestamp: 1625677242106400138
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth1"
}
}
elem {
name: "ethernet"
}
elem {
name: "state"
}
elem {
name: "mac-address"
}
}
val {
string_val: "11:22:33:44:55:66"
}
}
}
notification {
timestamp: 1625677242106568200
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth1"
}
}
elem {
name: "ethernet"
}
elem {
name: "state"
}
elem {
name: "negotiated-port-speed"
}
}
val {
string_val: "SPEED_10GB"
}
}
}
notification {
timestamp: 1625677242106727423
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth1"
}
}
elem {
name: "ethernet"
}
elem {
name: "state"
}
elem {
name: "port-speed"
}
}
val {
string_val: "SPEED_10GB"
}
}
}
notification {
timestamp: 1625677242106921037
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth1"
}
}
elem {
name: "state"
}
elem {
name: "admin-status"
}
}
val {
string_val: "UP"
}
}
}
notification {
timestamp: 1625677242107130589
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth1"
}
}
elem {
name: "state"
}
elem {
name: "counters"
}
elem {
name: "in-broadcast-pkts"
}
}
val {
uint_val: 0
}
}
}
notification {
timestamp: 1625677242107302614
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth1"
}
}
elem {
name: "state"
}
elem {
name: "counters"
}
elem {
name: "in-discards"
}
}
val {
uint_val: 0
}
}
}
notification {
timestamp: 1625677242107466813
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth1"
}
}
elem {
name: "state"
}
elem {
name: "counters"
}
elem {
name: "in-errors"
}
}
val {
uint_val: 0
}
}
}
notification {
timestamp: 1625677242107630387
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth1"
}
}
elem {
name: "state"
}
elem {
name: "counters"
}
elem {
name: "in-fcs-errors"
}
}
val {
uint_val: 0
}
}
}
notification {
timestamp: 1625677242107883593
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth1"
}
}
elem {
name: "state"
}
elem {
name: "counters"
}
elem {
name: "in-multicast-pkts"
}
}
val {
uint_val: 0
}
}
}
notification {
timestamp: 1625677242108053080
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth1"
}
}
elem {
name: "state"
}
elem {
name: "counters"
}
elem {
name: "in-octets"
}
}
val {
uint_val: 95346
}
}
}
notification {
timestamp: 1625677242108219479
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth1"
}
}
elem {
name: "state"
}
elem {
name: "counters"
}
elem {
name: "in-unicast-pkts"
}
}
val {
uint_val: 1015
}
}
}
notification {
timestamp: 1625677242108383478
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth1"
}
}
elem {
name: "state"
}
elem {
name: "counters"
}
elem {
name: "in-unknown-protos"
}
}
val {
uint_val: 0
}
}
}
notification {
timestamp: 1625677242108627408
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth1"
}
}
elem {
name: "state"
}
elem {
name: "counters"
}
elem {
name: "out-broadcast-pkts"
}
}
val {
uint_val: 0
}
}
}
notification {
timestamp: 1625677242108797395
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth1"
}
}
elem {
name: "state"
}
elem {
name: "counters"
}
elem {
name: "out-discards"
}
}
val {
uint_val: 0
}
}
}
notification {
timestamp: 1625677242108960607
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth1"
}
}
elem {
name: "state"
}
elem {
name: "counters"
}
elem {
name: "out-errors"
}
}
val {
uint_val: 0
}
}
}
notification {
timestamp: 1625677242109122568
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth1"
}
}
elem {
name: "state"
}
elem {
name: "counters"
}
elem {
name: "out-multicast-pkts"
}
}
val {
uint_val: 0
}
}
}
notification {
timestamp: 1625677242109286217
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth1"
}
}
elem {
name: "state"
}
elem {
name: "counters"
}
elem {
name: "out-octets"
}
}
val {
uint_val: 93478
}
}
}
notification {
timestamp: 1625677242109451817
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth1"
}
}
elem {
name: "state"
}
elem {
name: "counters"
}
elem {
name: "out-unicast-pkts"
}
}
val {
uint_val: 981
}
}
}
notification {
timestamp: 1625677242109601927
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth1"
}
}
elem {
name: "state"
}
elem {
name: "hardware-port"
}
}
val {
string_val: "s1-eth1"
}
}
}
notification {
timestamp: 1625677242109745287
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth1"
}
}
elem {
name: "state"
}
elem {
name: "health-indicator"
}
}
val {
string_val: "UNKNOWN"
}
}
}
notification {
timestamp: 1625677242109892510
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth1"
}
}
elem {
name: "state"
}
elem {
name: "ifindex"
}
}
val {
uint_val: 1
}
}
}
notification {
timestamp: 1625677242110041646
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth1"
}
}
elem {
name: "state"
}
elem {
name: "last-change"
}
}
val {
uint_val: 0
}
}
}
notification {
timestamp: 1625677242110384508
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth1"
}
}
elem {
name: "state"
}
elem {
name: "loopback-mode"
}
}
val {
bool_val: false
}
}
}
notification {
timestamp: 1625677242110516730
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth1"
}
}
elem {
name: "state"
}
elem {
name: "name"
}
}
val {
string_val: "s1-eth1"
}
}
}
notification {
timestamp: 1625677242110662353
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth1"
}
}
elem {
name: "state"
}
elem {
name: "oper-status"
}
}
val {
string_val: "UP"
}
}
}
notification {
timestamp: 1625677242110939722
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth2"
}
}
elem {
name: "config"
}
elem {
name: "enabled"
}
}
val {
bool_val: true
}
}
}
notification {
timestamp: 1625677242111069081
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth2"
}
}
elem {
name: "config"
}
elem {
name: "health-indicator"
}
}
val {
string_val: "GOOD"
}
}
}
notification {
timestamp: 1625677242111195753
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth2"
}
}
elem {
name: "config"
}
elem {
name: "loopback-mode"
}
}
val {
bool_val: false
}
}
}
notification {
timestamp: 1625677242111361340
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth2"
}
}
elem {
name: "ethernet"
}
elem {
name: "config"
}
elem {
name: "auto-negotiate"
}
}
val {
bool_val: false
}
}
}
notification {
timestamp: 1625677242111502162
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth2"
}
}
elem {
name: "ethernet"
}
elem {
name: "config"
}
elem {
name: "forwarding-viable"
}
}
val {
bool_val: true
}
}
}
notification {
timestamp: 1625677242111659323
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth2"
}
}
elem {
name: "ethernet"
}
elem {
name: "config"
}
elem {
name: "mac-address"
}
}
val {
string_val: "11:22:33:44:55:66"
}
}
}
notification {
timestamp: 1625677242111801758
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth2"
}
}
elem {
name: "ethernet"
}
elem {
name: "config"
}
elem {
name: "port-speed"
}
}
val {
string_val: "SPEED_10GB"
}
}
}
notification {
timestamp: 1625677242112037100
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth2"
}
}
elem {
name: "ethernet"
}
elem {
name: "state"
}
elem {
name: "auto-negotiate"
}
}
val {
bool_val: false
}
}
}
notification {
timestamp: 1625677242112202837
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth2"
}
}
elem {
name: "ethernet"
}
elem {
name: "state"
}
elem {
name: "forwarding-viable"
}
}
val {
bool_val: false
}
}
}
notification {
timestamp: 1625677242112371499
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth2"
}
}
elem {
name: "ethernet"
}
elem {
name: "state"
}
elem {
name: "mac-address"
}
}
val {
string_val: "11:22:33:44:55:66"
}
}
}
notification {
timestamp: 1625677242112575001
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth2"
}
}
elem {
name: "ethernet"
}
elem {
name: "state"
}
elem {
name: "negotiated-port-speed"
}
}
val {
string_val: "SPEED_10GB"
}
}
}
notification {
timestamp: 1625677242112737500
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth2"
}
}
elem {
name: "ethernet"
}
elem {
name: "state"
}
elem {
name: "port-speed"
}
}
val {
string_val: "SPEED_10GB"
}
}
}
notification {
timestamp: 1625677242112929763
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth2"
}
}
elem {
name: "state"
}
elem {
name: "admin-status"
}
}
val {
string_val: "UP"
}
}
}
notification {
timestamp: 1625677242113161192
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth2"
}
}
elem {
name: "state"
}
elem {
name: "counters"
}
elem {
name: "in-broadcast-pkts"
}
}
val {
uint_val: 0
}
}
}
notification {
timestamp: 1625677242113338342
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth2"
}
}
elem {
name: "state"
}
elem {
name: "counters"
}
elem {
name: "in-discards"
}
}
val {
uint_val: 0
}
}
}
notification {
timestamp: 1625677242113505479
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth2"
}
}
elem {
name: "state"
}
elem {
name: "counters"
}
elem {
name: "in-errors"
}
}
val {
uint_val: 0
}
}
}
notification {
timestamp: 1625677242113671866
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth2"
}
}
elem {
name: "state"
}
elem {
name: "counters"
}
elem {
name: "in-fcs-errors"
}
}
val {
uint_val: 0
}
}
}
notification {
timestamp: 1625677242113837465
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth2"
}
}
elem {
name: "state"
}
elem {
name: "counters"
}
elem {
name: "in-multicast-pkts"
}
}
val {
uint_val: 0
}
}
}
notification {
timestamp: 1625677242114003840
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth2"
}
}
elem {
name: "state"
}
elem {
name: "counters"
}
elem {
name: "in-octets"
}
}
val {
uint_val: 94590
}
}
}
notification {
timestamp: 1625677242114211992
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth2"
}
}
elem {
name: "state"
}
elem {
name: "counters"
}
elem {
name: "in-unicast-pkts"
}
}
val {
uint_val: 997
}
}
}
notification {
timestamp: 1625677242114375079
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth2"
}
}
elem {
name: "state"
}
elem {
name: "counters"
}
elem {
name: "in-unknown-protos"
}
}
val {
uint_val: 0
}
}
}
notification {
timestamp: 1625677242114543528
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth2"
}
}
elem {
name: "state"
}
elem {
name: "counters"
}
elem {
name: "out-broadcast-pkts"
}
}
val {
uint_val: 0
}
}
}
notification {
timestamp: 1625677242114706827
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth2"
}
}
elem {
name: "state"
}
elem {
name: "counters"
}
elem {
name: "out-discards"
}
}
val {
uint_val: 0
}
}
}
notification {
timestamp: 1625677242114871126
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth2"
}
}
elem {
name: "state"
}
elem {
name: "counters"
}
elem {
name: "out-errors"
}
}
val {
uint_val: 0
}
}
}
notification {
timestamp: 1625677242115036088
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth2"
}
}
elem {
name: "state"
}
elem {
name: "counters"
}
elem {
name: "out-multicast-pkts"
}
}
val {
uint_val: 0
}
}
}
notification {
timestamp: 1625677242115243715
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth2"
}
}
elem {
name: "state"
}
elem {
name: "counters"
}
elem {
name: "out-octets"
}
}
val {
uint_val: 93604
}
}
}
notification {
timestamp: 1625677242115408315
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth2"
}
}
elem {
name: "state"
}
elem {
name: "counters"
}
elem {
name: "out-unicast-pkts"
}
}
val {
uint_val: 984
}
}
}
notification {
timestamp: 1625677242115560513
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth2"
}
}
elem {
name: "state"
}
elem {
name: "hardware-port"
}
}
val {
string_val: "s1-eth2"
}
}
}
notification {
timestamp: 1625677242115705673
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth2"
}
}
elem {
name: "state"
}
elem {
name: "health-indicator"
}
}
val {
string_val: "UNKNOWN"
}
}
}
notification {
timestamp: 1625677242115852759
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth2"
}
}
elem {
name: "state"
}
elem {
name: "ifindex"
}
}
val {
uint_val: 2
}
}
}
notification {
timestamp: 1625677242116000832
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth2"
}
}
elem {
name: "state"
}
elem {
name: "last-change"
}
}
val {
uint_val: 0
}
}
}
notification {
timestamp: 1625677242116325630
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth2"
}
}
elem {
name: "state"
}
elem {
name: "loopback-mode"
}
}
val {
bool_val: false
}
}
}
notification {
timestamp: 1625677242116507980
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth2"
}
}
elem {
name: "state"
}
elem {
name: "name"
}
}
val {
string_val: "s1-eth2"
}
}
}
notification {
timestamp: 1625677242116654578
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth2"
}
}
elem {
name: "state"
}
elem {
name: "oper-status"
}
}
val {
string_val: "UP"
}
}
}
notification {
timestamp: 1625677242116953662
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth1"
}
}
elem {
name: "state"
}
elem {
name: "counters"
}
elem {
name: "in-broadcast-pkts"
}
}
val {
uint_val: 0
}
}
}
notification {
timestamp: 1625677242117130137
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth1"
}
}
elem {
name: "state"
}
elem {
name: "counters"
}
elem {
name: "in-discards"
}
}
val {
uint_val: 0
}
}
}
notification {
timestamp: 1625677242117296011
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth1"
}
}
elem {
name: "state"
}
elem {
name: "counters"
}
elem {
name: "in-errors"
}
}
val {
uint_val: 0
}
}
}
notification {
timestamp: 1625677242117509351
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth1"
}
}
elem {
name: "state"
}
elem {
name: "counters"
}
elem {
name: "in-fcs-errors"
}
}
val {
uint_val: 0
}
}
}
notification {
timestamp: 1625677242117674738
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth1"
}
}
elem {
name: "state"
}
elem {
name: "counters"
}
elem {
name: "in-multicast-pkts"
}
}
val {
uint_val: 0
}
}
}
notification {
timestamp: 1625677242117841350
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth1"
}
}
elem {
name: "state"
}
elem {
name: "counters"
}
elem {
name: "in-octets"
}
}
val {
uint_val: 95346
}
}
}
notification {
timestamp: 1625677242118005999
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth1"
}
}
elem {
name: "state"
}
elem {
name: "counters"
}
elem {
name: "in-unicast-pkts"
}
}
val {
uint_val: 1015
}
}
}
notification {
timestamp: 1625677242118171823
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth1"
}
}
elem {
name: "state"
}
elem {
name: "counters"
}
elem {
name: "in-unknown-protos"
}
}
val {
uint_val: 0
}
}
}
notification {
timestamp: 1625677242118334660
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth1"
}
}
elem {
name: "state"
}
elem {
name: "counters"
}
elem {
name: "out-broadcast-pkts"
}
}
val {
uint_val: 0
}
}
}
notification {
timestamp: 1625677242118542124
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth1"
}
}
elem {
name: "state"
}
elem {
name: "counters"
}
elem {
name: "out-discards"
}
}
val {
uint_val: 0
}
}
}
notification {
timestamp: 1625677242118706874
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth1"
}
}
elem {
name: "state"
}
elem {
name: "counters"
}
elem {
name: "out-errors"
}
}
val {
uint_val: 0
}
}
}
notification {
timestamp: 1625677242118869910
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth1"
}
}
elem {
name: "state"
}
elem {
name: "counters"
}
elem {
name: "out-multicast-pkts"
}
}
val {
uint_val: 0
}
}
}
notification {
timestamp: 1625677242119035209
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth1"
}
}
elem {
name: "state"
}
elem {
name: "counters"
}
elem {
name: "out-octets"
}
}
val {
uint_val: 93478
}
}
}
notification {
timestamp: 1625677242119202121
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth1"
}
}
elem {
name: "state"
}
elem {
name: "counters"
}
elem {
name: "out-unicast-pkts"
}
}
val {
uint_val: 981
}
}
}
notification {
timestamp: 1625677242119401573
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth2"
}
}
elem {
name: "state"
}
elem {
name: "counters"
}
elem {
name: "in-broadcast-pkts"
}
}
val {
uint_val: 0
}
}
}
notification {
timestamp: 1625677242119607538
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth2"
}
}
elem {
name: "state"
}
elem {
name: "counters"
}
elem {
name: "in-discards"
}
}
val {
uint_val: 0
}
}
}
notification {
timestamp: 1625677242119770149
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth2"
}
}
elem {
name: "state"
}
elem {
name: "counters"
}
elem {
name: "in-errors"
}
}
val {
uint_val: 0
}
}
}
notification {
timestamp: 1625677242119935048
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth2"
}
}
elem {
name: "state"
}
elem {
name: "counters"
}
elem {
name: "in-fcs-errors"
}
}
val {
uint_val: 0
}
}
}
notification {
timestamp: 1625677242120099022
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth2"
}
}
elem {
name: "state"
}
elem {
name: "counters"
}
elem {
name: "in-multicast-pkts"
}
}
val {
uint_val: 0
}
}
}
notification {
timestamp: 1625677242120262009
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth2"
}
}
elem {
name: "state"
}
elem {
name: "counters"
}
elem {
name: "in-octets"
}
}
val {
uint_val: 94590
}
}
}
notification {
timestamp: 1625677242120423458
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth2"
}
}
elem {
name: "state"
}
elem {
name: "counters"
}
elem {
name: "in-unicast-pkts"
}
}
val {
uint_val: 997
}
}
}
notification {
timestamp: 1625677242120662375
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth2"
}
}
elem {
name: "state"
}
elem {
name: "counters"
}
elem {
name: "in-unknown-protos"
}
}
val {
uint_val: 0
}
}
}
notification {
timestamp: 1625677242120831587
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth2"
}
}
elem {
name: "state"
}
elem {
name: "counters"
}
elem {
name: "out-broadcast-pkts"
}
}
val {
uint_val: 0
}
}
}
notification {
timestamp: 1625677242120999274
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth2"
}
}
elem {
name: "state"
}
elem {
name: "counters"
}
elem {
name: "out-discards"
}
}
val {
uint_val: 0
}
}
}
notification {
timestamp: 1625677242121202076
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth2"
}
}
elem {
name: "state"
}
elem {
name: "counters"
}
elem {
name: "out-errors"
}
}
val {
uint_val: 0
}
}
}
notification {
timestamp: 1625677242121382276
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth2"
}
}
elem {
name: "state"
}
elem {
name: "counters"
}
elem {
name: "out-multicast-pkts"
}
}
val {
uint_val: 0
}
}
}
notification {
timestamp: 1625677242121546375
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth2"
}
}
elem {
name: "state"
}
elem {
name: "counters"
}
elem {
name: "out-octets"
}
}
val {
uint_val: 93604
}
}
}
notification {
timestamp: 1625677242121791355
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth2"
}
}
elem {
name: "state"
}
elem {
name: "counters"
}
elem {
name: "out-unicast-pkts"
}
}
val {
uint_val: 984
}
}
}
notification {
timestamp: 1625677242122056711
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth1"
}
}
elem {
name: "state"
}
elem {
name: "ifindex"
}
}
val {
uint_val: 1
}
}
}
notification {
timestamp: 1625677242122204909
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth2"
}
}
elem {
name: "state"
}
elem {
name: "ifindex"
}
}
val {
uint_val: 2
}
}
}
notification {
timestamp: 1625677242122597437
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth1"
}
}
elem {
name: "state"
}
elem {
name: "name"
}
}
val {
string_val: "s1-eth1"
}
}
}
notification {
timestamp: 1625677242122796489
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth2"
}
}
elem {
name: "state"
}
elem {
name: "name"
}
}
val {
string_val: "s1-eth2"
}
}
}
***************************
```
<br>
Nesta próxima etapa, podemos ler os contadores de pacotes unicast, com o comando a seguir na CLI gNMI, com este comando, será possível imprimir o número de pacotes recebidos na porta 1 a cada segundo:
```./gnmi-cli.sh --interval 1000 sub-sample /interfaces/interface[name=s1-eth1]/state/counters/in-unicast-pkts```
:::info
<center>Retorno do comando executado na CLI gNMI anteriormente:</center>
:::
```
***************************
RESPONSE
update {
timestamp: 1564838158894794047
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth1"
}
}
elem {
name: "state"
}
elem {
name: "counters"
}
elem {
name: "in-unicast-pkts"
}
}
val {
uint_val: 585
}
}
}
***************************
```
:::warning
Observe que o uint_val aumenta 1 a cada segundo se o ping ainda estiver em execução.
:::
<br>
### Demonstrando as assinaturas gNMI com "set e on-change"
Execute o comando a seguir para iniciar o processo pela porta 1, onde iremos verificar se ela realmente esta UP:
```./gnmi-cli.sh sub-onchange /interfaces/interface[name=s1-eth1]/state/oper-status```
:::info
<center>Retorno do comando anterior na CLI gNMI de forma ilustrada:</center>
:::
![](https://i.imgur.com/FvgZV6G.png)
<br>
Execute o comando a seguir para iniciar o processo pela porta 1, onde iremos verificar se ela realmente esta DOWN e com isso o ICMP irá parar automaticamente:
```./gnmi-cli.sh set /interfaces/interface[name=s1-eth1]/config/enabled --bool-val false```
:::info
<center>Retorno do comando anterior na CLI gNMI e repare o ICMP na próxima ilustração: </center>
:::
```
***************************
RESPONSE
update {
timestamp: 1564838642886678182
update {
path {
elem {
name: "interfaces"
}
elem {
name: "interface"
key {
key: "name"
value: "s1-eth1"
}
}
elem {
name: "state"
}
elem {
name: "oper-status"
}
}
val {
string_val: "DOWN"
}
}
}
***************************
```
<br>
![](https://i.imgur.com/Hh3Llu7.png)
<br>
### Iniciando o controllador ONOS pelo Docker
Iremos iniciar o ONOS e verificar algumas configurações do Stratum e alguns detalhes importantes deste procedimento nas ilustrações a seguir dentro do controlador, antes execute o comando:
```./start-onos```
<br>
:::info
Dados de acesso do controlador: Usuário: onos - Senha: rocks
:::
```http://seu-ip:8181/onos/ui ou http://localhost:8181/onos/ui```
:::warning
Será normal a máquina utilizar mais recursos de CPU até iniciar o controlador ONOS
:::
![](https://i.imgur.com/dECifGM.png)
<br>
![](https://i.imgur.com/MNtoFjd.png)
<br>
![](https://i.imgur.com/Wr4DaOW.png)
<br>
![](https://i.imgur.com/t2s1O8I.png)
<br>
### Encaminhando o netcfg arquivo para ONOS
Depois de ver que o log do ONOS, poderemos enviar informações sobre a topologia da rede para o controlador ONOS:
![](https://i.imgur.com/aEmwpNx.png)
Em um novo terminal, execute o comando a seguir:
```./netcfg.sh```
---
### OPCIONAL:
Verificando as imagens no Docker e as tabelas inseridas no P4Runtime Shell:
![](https://i.imgur.com/g9yUAmL.png)
<br>
![](https://i.imgur.com/9dZLz1M.png)
<br>
### Fim.
---
### Fontes:
https://github.com/stratum/tutorial/tree/master/basic
http://www.netconfcentral.org/modulereport/openconfig-wifi-mac
### Autor:
Fernando Henrique Santorsula
E-mail: f208918@dac.unicamp.br
### Coautor:
Alan Teixeira da Silva
E-mail: a265560@dac.unicamp.br
FEEC/UNICAMP - Campinas/SP/BR
https://www.fee.unicamp.br