# 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