美文网首页
ONOS-P4-Tutorial-Ⅰ

ONOS-P4-Tutorial-Ⅰ

作者: SmartSloth | 来源:发表于2020-05-20 13:57 被阅读0次

练习1: 软件工具基础知识和数据包I/O

说明:本文翻译自onos-p4-tutorialExercise 1: Software tools basics and packet I/O,由于对ACL不甚理解而做此纪录

本练习提供了本教程在其余部分中使用的软件工具介绍。

首先,您将在本练习中学习如何:

  1. 使用stratum_bmv2软件交换机的2x2叶子-主干拓扑启动Mininet
  2. 启动ONOS以及一组用于基础服务(例如拓扑发现)的内置应用程序
  3. 将网络配置文件推送到ONOS以stratum_bmv2使用P4Runtime发现和控制交换机
  4. 通过使用P4Runtime数据包入/出验证ONOS是否能够自动发现所有链接

为此,将要求您对原始P4代码进行简单的更改以增加对数据包输入的支持,使用基于PTF的数据平面单元测试来验证P4更改,最后将更改应用于pipeconf Java实现以启用ONOS。内置应用程序使用输入/输出数据包执行拓扑发现。

要进行此练习,您将需要多个终端窗口(或标签页)以使用Mininet,ONOS和BMv2的CLI进行操作。我们使用以下约定来区分不同CLI的命令:

  • 开头的命令$旨在在Ubuntu终端提示符下执行;
  • onos> 用于ONOS CLI中的命令;
  • mininet> 用于Mininet CLI;
  • RuntimeCmd: 用于BMv2 CLI。

带有P4Runtime的控制器数据包I/O

下面的P4程序p4src/支持在P4RuntimePacketInPacketOut消息中携带任意元数据。定义了两个特殊的标头,并使用标准P4注释进行了注释@controller_header

@controller_header("packet_in")
header packet_in_header_t {
    port_num_t ingress_port;
    bit<7> _pad;
}

@controller_header("packet_out")
header packet_out_header_t {
    port_num_t egress_port;
    bit<7> _pad;
}

这些标头用于携带输入包的原始交换机入口端口,并指定输出包的预期输出端口。

当Stratum中的P4Runtime代理从CPU端口接收到一个数据包时,它希望找到packet_in_header_t标头作为帧中的第一个报头。实际上,它会查看P4Info文件的ControllerPacketMetadata,以确定从帧开始处要剥离的位数,并填充相应的PacketIn.metadata字段(包括本例中的入端口)。

同样,当Stratum收到P4RuntimePacketOut消息时,它将把在PacketOut.metadata字段中找到的值进行序列化并在PacketOut.payload之前加上一个packet_out_header_t,然后将其提供给管道解析器。

练习步骤

1. 修改P4程序

P4入门代码已经提供了对以下功能的支持:

  • 解析packet_out报头(如果入端口是CPU端口)
  • packet_in标头发送为Deparser中的第一个报头
  • 跳过处理数据包输出的入口流水线处理以,并将出口端口设置为packet-out标头中指定的端口
  • 提供具有三元匹配字段的类ACL表,以及将数据包克隆到CPU端口的操作(用于生成数据包输入)

为了提供完整的打包支持,缺少了一个组件,您必须修改P4程序才能实现它:

  1. 打开p4src/main.p4;
  2. 找到出口pipeline的实现(control EgressPipeImpl);
  3. 在提示的地方修改代码(查找TODO EXERCISE 1);
  4. 使用make p4命令编译修改后的P4程序。在继续操作之前,请确保解决所有编译器错误。

最后一条命令将在以下位置生成两个输出文件p4src/build

  • bmv2.json:BMv2 JSON管道配置
  • p4info.txt:protobuf文本格式的P4Info文件

此时,我们的P4 pipeline已经准备好进行测试。

2. 运行PTF测试

在启动ONOS之前,让我们通过运行一些PTF测试来确保P4的更改符合预期。但是首先,您需要对测试用例进行一些简单的修改。

打开ptf/tests/packetio.py文件并在提示的地方进行修改(查找TODO EXERCISE 1)。该测试文件提供了两个测试用例:一个用于输入数据包,另一个用于输出数据包。在这两个测试用例中,您都必须修改实现以对P4Runtime实体使用与在编译P4程序后获得的P4Info文件(p4src/build/p4info.txt)中指定的名称相同的名称。

要运行此练习的所有测试:

cd ptf
make packetio

此命令将运行packetio组中的所有测试(即ptf/tests/packetio.py的内容)。要运行特定的测试用例,可以使用:

make <PYTHON MODULE>.<TEST CASE NAME>

例如:

make packetio.PacketOutTest

如果所有测试成功,那么恭喜!您可以转到下一步。

如何调试失败的测试?

运行PTF测试时,会产生多个文件,可用于发现错误:

  • ptf/bmv2.log:具有跟踪级别的BMv2日志(显示匹配的表以及每个数据包的其他信息)
  • ptf/ptf.pcap:PCAP文件,其中包含在测试期间发送和接收的所有数据包(教程VM随Wireshark一起提供,以便于可视化)
  • ptf/ptf.log:所有包操作(发送和接收)的PTF日志

3. 修改ONOS管道解释器

PipelineInterpreter是ONOS驱动程序行为,用于将数据包入/出的ONOS表示映射到与P4管道一致的映射(以及其他类似的映射)。

具体来说,要使用基于LLDP的链接发现之类的服务,ONOS内置应用程序需要能够设置数据包输出的输出端口并访问数据包输入的原始入口端口。

在下面,将提示您对PipelineInterpreter实现进行一些简单的更改:

  1. 打开文件:app/src/main/java/org/p4/p4d2/tutorial/pipeconf/InterpreterImpl.java

  2. 根据提示修改(查找TODO EXERCISE 1),详细来说是:

    • 查找一个名为的方法buildPacketOut,修改实现以使用与 P4Info文件中指定的标头相同的出口端口元数据字段名称packet_out

    • 查找mapInboundPacket方法,修改实现以对P4Info文件中指定的packet_in标头使用与入口端口元数据字段相同的名称。

  1. 使用命令构建ONOS应用(包括pipeconf)make app-build

如果需要,最后一条命令将触发P4程序的构建。P4编译器的输出(bmv2.jsonp4info.txt)在应用程序资源文件夹(app/src/main/resources)中进行符号链接,并将收入在ONOS应用程序二进制文件中。启动连接后,ONOS应用程序中包含的副本将是ONOS部署到设备上的副本。

4. 启动ONOS

在终端窗口中,键入:

$ make onos-run

此命令将重新安装ONOS(即从以前的执行中删除所有状态)。在启动过程中,环境变量$ONOS_APPS的值用于定义要在启动期间加载的内置应用程序。

在教程VM中,此变量为以下几个组件:

$ echo $ONOS_APPS
gui,drivers.bmv2,lldpprovider,hostprovider

请求ONOS预加载以下内置应用程序:

  • gui:ONOS Web用户界面(即http:/localhost:181/onos/ui
  • drivers.bmv2:基于P4Runtime、gNMI和gNOI的BMv2/Stratum驱动程序
  • lldpprovider:基于LLDP的链路发现应用程序
  • hostprovider:主机发现应用程序

ONOS启动后,您应该会在屏幕上看到正在打印的日志。在打印以下日志消息时,ONOS已准备就绪(应该是最后一条):

INFO  [AtomixClusterStore] Updated node 127.0.0.1 state to READY

验证是否已激活所有必需的应用程序,请在新的终端窗口中运行以下命令以访问ONOS CLI:

$ make onos-cli

在ONOS CLI中键入以下命令以显示正在运行的应用程序的列表:

onos> apps -a -s

确保您看到以下显示的应用程序列表:

* ... org.onosproject.lldpprovider          ... LLDP Link Provider
* ... org.onosproject.drivers               ... Default Drivers
* ... org.onosproject.protocols.grpc        ... gRPC Protocol Subsystem
* ... org.onosproject.protocols.gnmi        ... gNMI Protocol Subsystem
* ... org.onosproject.generaldeviceprovider ... General Device Provider
* ... org.onosproject.protocols.p4runtime   ... P4Runtime Protocol Subsystem
* ... org.onosproject.p4runtime             ... P4Runtime Provider
* ... org.onosproject.drivers.p4runtime     ... P4Runtime Drivers
* ... org.onosproject.pipelines.basic       ... Basic Pipelines
* ... org.onosproject.drivers.gnmi          ... gNMI Drivers
* ... org.onosproject.protocols.gnoi        ... gNOI Protocol Subsystem
* ... org.onosproject.drivers.gnoi          ... gNOI Drivers
* ... org.onosproject.drivers.stratum       ... Stratum Drivers
* ... org.onosproject.hostprovider          ... Host Location Provider
* ... org.onosproject.gui                   ... ONOS Legacy GUI
* ... org.onosproject.drivers.bmv2          ... BMv2 Drivers

绝对比$ONOS_APPS定义的应用更多。这是因为ONOS中的每个应用程序都可以将其他应用程序定义为依赖项。加载应用程序时,ONOS会自动解决依赖关系并加载所有其他必需的应用程序。

要退出ONOS CLI,请使用Ctrl-D。这只会结束CLI进程,而不会停止ONOS进程。

发生错误时重新启动ONOS

如果出现任何问题,您需要终止/重新启动ONOS,请在启动ONOS的同一终端窗口中按Ctrl+C(并打印日志)。另外,您也可以使用命令make reset。要重新启动ONOS,请执行make onos-run`。

5. 加载应用程序并注册pipeconf

在第二个终端窗口中,键入:

$ make app-reload

此命令将上传到ONOS并激活先前构建的应用程序二进制文件(位于app/target/srv6-tutorial-1.0-SNAPSHOT.oar)。

激活应用程序后,您应该在日志中看到以下消息,表明pipeconf已注册并且不同的应用程序组件已启动(在第一个运行ONOS的窗口中):

INFO  [PiPipeconfManager] New pipeconf registered: org.p4.srv6-tutorial (fingerprint=...)
INFO  [MainComponent] Started

另外,您可以使用ONOS CLI命令显示已注册pipeconf的列表:

onos> pipeconfs

提示:make onos-cli用于启动ONOS CLI。

第一次启动ONOS后重新加载应用

如果同一应用程序的另一个实例正在运行,该命令make app-reload 将首先停用正在运行的实例并加载新实例。

要将新更改应用于P4程序或应用实现,请随意使用 make app-build app-reload任意多次。该应用程序已包含在每次重新加载时从ONOS清除任何表条目和其他转发状态的逻辑。

6. 启动Mininet拓扑

在第三个终端窗口上,键入:

$ make topo

该命令将启动基于Mininet的拓扑脚本(mininet/topo.py)。该脚本创建了前面描述的2x2结构拓扑,并启动了Mininet CLI。

作为此过程的一部分,在/tmp中生成了一组文件。例如,可以在/tmp/bmv2-log-<switch-name>中找到每个stratum_bmv2实例的日志,其中交换机名称可以是leaf1leaf2spine1spine2。该日志文件结合了Stratum进程(例如P4Runtime操作)和BMv2的simple_switch消息。

如果要stratum_bmv2实时跟踪日志更新,可以使用以下命令在屏幕上打印所有新消息:

$ bm-log leaf1

7. 将netcfg推送到ONOS

现在,ONOS和Mininet正在运行,现在该让ONOS知道如何到达这四个交换机并对其进行控制了。

在第四个终端窗口(如果要保留shell,则在第二个窗口)上,键入:

$ make netcfg

此命令将推送netcfg的JSON文件(netcfg.json)到ONOS,以触发4个交换机的发现和配置。

您应该在日志消息中看到以下内容:

INFO  [GrpcChannelControllerImpl] Creating new gRPC channel grpc://127.0.0.1:50001?device_id=1...
...
INFO  [StreamClientImpl] Setting mastership on device:leaf1...
...
INFO  [PipelineConfigClientImpl] Setting pipeline config for device:leaf1 to org.p4.srv6-tutorial...
...
INFO  [GnmiDeviceStateSubscriber] Started gNMI subscription for 6 ports on device:leaf1
...
INFO  [DeviceManager] Device device:leaf1 port [leaf1-eth1](1) status changed (enabled=true)
INFO  [DeviceManager] Device device:leaf1 port [leaf1-eth2](2) status changed (enabled=true)
INFO  [DeviceManager] Device device:leaf1 port [leaf1-eth3](3) status changed (enabled=true)
INFO  [DeviceManager] Device device:leaf1 port [leaf1-eth4](4) status changed (enabled=true)
INFO  [DeviceManager] Device device:leaf1 port [leaf1-eth5](5) status changed (enabled=true)
INFO  [DeviceManager] Device device:leaf1 port [leaf1-eth6](6) status changed (enabled=true)

8. 使用ONOS CLI验证网络配置

使用make onos-cli访问ONOS CLI。输入以下命令以验证之前推送的网络配置:

onos> netcfg

设备

验证是否已找到并连接了所有4个设备:

onos> devices -s
id=device:leaf1, available=true, role=MASTER, type=SWITCH, driver=stratum-bmv2:org.p4.srv6-tutorial
id=device:leaf2, available=true, role=MASTER, type=SWITCH, driver=stratum-bmv2:org.p4.srv6-tutorial
id=device:spine1, available=true, role=MASTER, type=SWITCH, driver=stratum-bmv2:org.p4.srv6-tutorial
id=device:spine2, available=true, role=MASTER, type=SWITCH, driver=stratum-bmv2:org.p4.srv6-tutorial

确保所有设备的available=true

接口

验证是否像netcfg文件中一样在ONOS中配置了6个接口,为leaf1配置4个接口,为leaf2配置2个接口,每个接口都分配了一个IPv6地址:

onos> interfaces
leaf1-3: port=device:leaf1/3 ips=[2001:1:1::ff/64]
leaf1-4: port=device:leaf1/4 ips=[2001:1:1::ff/64]
leaf1-5: port=device:leaf1/5 ips=[2001:1:1::ff/64]
leaf1-6: port=device:leaf1/6 ips=[2001:1:2::ff/64]
leaf2-3: port=device:leaf2/3 ips=[2001:2:3::ff/64]
leaf2-4: port=device:leaf2/4 ips=[2001:2:4::ff/64]

此IPv6地址配置将在以后用于提供路由功能。

链接

验证是否已找到所有链接。您应该总共看到8个链接:

onos> links
src=device:leaf1/1, dst=device:spine1/1, type=DIRECT, state=ACTIVE, expected=false
src=device:leaf1/2, dst=device:spine2/1, type=DIRECT, state=ACTIVE, expected=false
src=device:leaf2/1, dst=device:spine1/2, type=DIRECT, state=ACTIVE, expected=false
src=device:leaf2/2, dst=device:spine2/2, type=DIRECT, state=ACTIVE, expected=false
src=device:spine1/1, dst=device:leaf1/1, type=DIRECT, state=ACTIVE, expected=false
src=device:spine1/2, dst=device:leaf2/1, type=DIRECT, state=ACTIVE, expected=false
src=device:spine2/1, dst=device:leaf1/2, type=DIRECT, state=ACTIVE, expected=false
src=device:spine2/2, dst=device:leaf2/2, type=DIRECT, state=ACTIVE, expected=false

如果您没有看到任何链接,请检查ONOS日志中检查是否有进出报文处理错误。如果发生错误,则可能是您未将InterpreterImpl.java正确修改。在这种情况下,请关闭ONOS,然后重新执行步骤3。

注意:从理论上讲,无需关闭并重新启动ONOS。但尽管ONOS支持使用修改后的版本(例如,更新的bmv2.jsonp4info.txt)重新加载pipeconf,但本教程中使用的ONOS版本(2.1.0,是撰写本文时的最新版本)不支持重新加载pipeconf行为类,在这种情况下,仍将使用旧类。因此,要重新加载InterpreterImpl.java的修改版本,您需要先关闭ONOS。

流规则(Flow rules)和组(groups)

验证流规则,您应该看到每个设备的5条流规则。例如,显示到目前为止在设备leaf1上安装的所有流规则:

onos> flows -s any device:leaf1
deviceId=device:leaf1, flowRuleCount=5
    ADDED, ..., table=IngressPipeImpl.acl, priority=40000, selector=[ETH_TYPE:ipv6, IP_PROTO:58, ICMPV6_TYPE:136], treatment=[immediate=[IngressPipeImpl.clone_to_cpu()]]
    ADDED, ..., table=IngressPipeImpl.acl, priority=40000, selector=[ETH_TYPE:arp], treatment=[immediate=[IngressPipeImpl.clone_to_cpu()]]
    ADDED, ..., table=IngressPipeImpl.acl, priority=40000, selector=[ETH_TYPE:ipv6, IP_PROTO:58, ICMPV6_TYPE:135], treatment=[immediate=[IngressPipeImpl.clone_to_cpu()]]
    ADDED, ..., table=IngressPipeImpl.acl, priority=40000, selector=[ETH_TYPE:lldp], treatment=[immediate=[IngressPipeImpl.clone_to_cpu()]]
    ADDED, ..., table=IngressPipeImpl.acl, priority=40000, selector=[ETH_TYPE:bddp], treatment=[immediate=[IngressPipeImpl.clone_to_cpu()]]

这些流规则(flow rules)是hostproviderlldpprovider应用为每个设备自动生成的流目标(flow objectives)转换的结果。

hostprovider应用程序通过嗅探克隆到控制器的ARP(selector=[ETH_TYPE:arp])和NDP数据包(selector=[ETH_TYPE:ipv6, IP_PROTO:58, ICMPV6_TYPE:...])来提供主机发现功能treatment=[immediate=[IngressPipeImpl.clone_to_cpu()]]。类似地,lldpprovider产生流目标(flow objectives),以嗅探在所有设备端口上定期作为P4Runtime数据包输出发出的LLDP和BBDP数据包(selector=[ETH_TYPE:lldp]selector=[ETH_TYPE:bbdp]),从而实现自动链路发现。

流目标(Flow objectives)由pipeconf转换为流规则(flow rules)和组(groups),pipeconf在(PipelinerImpl.java)提供了Pipeliner的行为实现。此外,这些流规则(flow rules)使用ETH_TYPEICMPV6_TYPE等ONOS标准/已知报头字段(或使用ONOS术语的“Criteria”)指定匹配键。这些类型通过在InterpreterImpl.java之前修改的同一管道interpreter映射到P4程序/ P4Info进行特定字段的匹配(查找方法mapCriterionType

流目标由pipeconf转换为流规则和组,pipeconf提供了Pipeliner行为实现(PipelinerImpl.java)。此外,这些流规则使用ETH_TYPE,ICMPV6_TYPE等ONOS标准/已知标头字段(或使用ONOS术语的“准则”)指定匹配键。
要显示到目前为止已安装的所有组,可以使用groups命令。例如,要显示leaf1的组:

sdn@root > groups any device:leaf1
deviceId=device:leaf1, groupCount=1
   id=0x63, state=ADDED, type=CLONE, ..., appId=org.onosproject.core, referenceCount=0
       id=0x63, bucket=1, ..., weight=-1, actions=[OUTPUT:CONTROLLER]

在这种情况下,您应该只会看到一组类型为CLONE的组,该组用于将数据包克隆到控制器(或使用数据平面术语到CPU的数据包)。 CLONE组是ONOS北向抽象,等同于P4Runtime的数据包复制引擎(PRE)CloneSessionEntry

9. 用ONOS Web UI进行拓扑可视化

从教程VM中打开浏览器(例如Firefox),前往http://127.0.0.1:8181/onos/ui。访问时,请使用用户名onos和密码rocks

在这里,您可以随时与之互动并发现ONOS UI。有关如何使用ONOS网络用户界面的更多信息,请参阅以下指南:

https://wiki.onosproject.org/x/OYMg

要显示或隐藏开关标签,请按L键。

恭喜你!

您已完成第一个练习。您可以移至下一个,或查看以下bonus任务。

Bonus:检查BMv2内部状态

您可以使用BMv2 CLI转储ONOS当前在交换机上安装的所有表条目。在单独的终端窗口上键入:

$ bm-cli leaf1

此命令(在教程VM中定义为bash别名)将启动Mininet中名称为“ leaf1”的BMv2交换机的CLI。

在BMv2 CLI提示符下,键入以下命令:

RuntimeCmd: table_dump IngressPipeImpl.acl

您应该看到恰好5个条目,每个条目对应于ONOS中的流规则(flow rule)。例如,在BMv2 CLI中,与ARP数据包匹配的流规则(flow rule)应如下所示:

Dumping entry 0x4
Match key:
* standard_metadata.ingress_port       : TERNARY   0000 &&& 0000
* ethernet.dst_addr                    : TERNARY   000000000000 &&& 000000000000
* ethernet.src_addr                    : TERNARY   000000000000 &&& 000000000000
* ethernet.ether_type                  : TERNARY   0806 &&& ffff
* scalars.local_metadata_t.ip_proto   : TERNARY   00 &&& 00
* scalars.local_metadata_t.icmp_type  : TERNARY   00 &&& 00
* scalars.local_metadata_t.l4_src_port: TERNARY   0000 &&& 0000
* scalars.local_metadata_t.l4_dst_port: TERNARY   0000 &&& 0000
Priority: 2147443646
Action entry: IngressPipeImpl.clone_to_cpu -

注意这里是如何将ONOS选择器[ETH_TYPE:arp]转换为与BMv2特定的头字段ethernet.ether_type(P4程序和P4Info中的ethernet.ether_type)匹配的条目,同时设置所有其他字段的位如“无关”(掩码全为零)。

同样,您可以使用mc_dump命令显示BMv2多播引擎的状态,该引擎用于实现数据包复制功能(例如克隆会话)。在这种情况下,对于CPU克隆会话,您应该只看到一个条目:

RuntimeCmd: mc_dump
==========
MC ENTRIES
**********
mgrp(32867)
  -> (L1h=0, rid=1) -> (ports=[255], lags=[])
==========
...

stratum_bmv2在Mininet(mininet / topo.py)中运行时,以及在ONOS(AppConstants.java)中写入克隆会话时,设置的CPU端口为255。

BMv2 CLI是调试BMv2交换机状态的强大工具。键入help以显示可使用的命令列表。按下tab键时,此CLI还提供自动完成功能。

警告:BMv2 CLI使用simple_switch公开的Thrift服务器。因为Thrift服务器的功能与Stratum提供的gRPC/P4Runtime的功能重叠(例如,两者都公开了表管理API),所以在使用两者将状态写入交换机时可能会出现不一致的问题。因此,我们建议仅使用此CLI读取状态

相关文章

  • ONOS-P4-Tutorial-Ⅱ

    练习2:桥接 说明:本文翻译自onos-p4-tutorial的Exercise 2: Bridging,用于理解...

  • ONOS-P4-Tutorial-Ⅲ

    练习3:IPv6路由 说明:本文翻译自onos-p4-tutorial的Exercise 3: IPv6 rout...

  • ONOS-P4-Tutorial-Ⅳ

    练习4:IPv6 Segment Routing(SRv6) 说明:本文翻译自onos-p4-tutorial的E...

  • ONOS-P4-Tutorial-Ⅰ

    练习1: 软件工具基础知识和数据包I/O 说明:本文翻译自onos-p4-tutorial的Exercise 1:...

网友评论

      本文标题:ONOS-P4-Tutorial-Ⅰ

      本文链接:https://www.haomeiwen.com/subject/xlmgohtx.html