SRv6项目实践(三):P4Runtime基础以及交换机控制

SRv6项目实践(三):P4Runtime基础以及交换机控制_第1张图片

在正式介绍P4runtime基础之前,先说一说P4的编译和实现的过程

  • bmv2.json:p4文件经过编译器编译以后会生成bmv2.json文件,此文件以JSON格式定义BMv2 simple_switch目标的配置。当simple_switch接收到新的数据包时,它使用此配置以与P4程序一致的方式处理数据包。
  • p4info.txt:该文件包含了各个表和操作,它们的id用一个索引值来表示,比如a表用b操作,不会直接说用名字为B的操作,而是说用索引为xxx的操作,然后锁定到b上执行相关的功能,其次,用了一个bitwith来描述,要访问的数据的比特长度是多长。

  • p4c编译器将p4编译成两份文件,其中一份是p4info.txt,另一份是bmv2.json(在bmv2这个p4target中是这种格式),将这两个文件再整合起来,作为配置,放到交换机中。另一方面,P4 Info也会将进入给控制器供控制器去查询,当控制器拿到P4 Info之后,即可透过P4 Info来产生P4 Runtime的讯息。

  • 从右边的图可以看出,控制平面和P4Runtime服务器是以p4runtime.proto的rpc支持的,具体可以看下文,介绍了P4和P4runtime的具体工作

P4 与 P4Runtime 介绍 - 知乎 (zhihu.com)

SRv6项目实践(三):P4Runtime基础以及交换机控制_第2张图片SRv6项目实践(三):P4Runtime基础以及交换机控制_第3张图片

1.创建数据平面与控制平面环境

通过make start,我们创建了两个容器,其中一个是mininet另一个是onos,但是在本文中没有被用到。(我这里用的是restart)

SRv6项目实践(三):P4Runtime基础以及交换机控制_第4张图片

用make mn-log可以查看数据平面的基本创建信息

SRv6项目实践(三):P4Runtime基础以及交换机控制_第5张图片

这个拓扑如顶上的那幅图所示,是一个2x2的拓扑,其中h1a h1b h1c被划在一个子网中,其他在别的子网,mininet容器被创建以后,在tmp文件夹的每一个转发设备下生成了三个文件

  • tmp/leaf1/stratum_bmv2.log:包含了叶节点的stratum_bmv2日志
  • tmp/leaf1/chassis-config.txt: Stratum“机箱配置”文件,用于指定交换机启动时使用的初始端口配置;该文件由mininet/topo-v6.py调用的StratumBmv2Switch类自动生成。
  • tmp/leaf1/write-reqs.txt: 交换机处理的所有P4Runtime写入请求的日志(如果交换机未接收到任何写入请求,则该文件可能不存在)。

2.使用P4Runtime

在本部分中,我们将使用P4Runtime Shell,这是一个交互式Python CLI,可用于连接P4Runtime服务器并运行P4Runtime命令。例如,它可以用于创建、读取、更新和删除流表条目。

shell可以在两种模式下启动,有或没有P4管道配置。在第一种情况下,shell将使用P4Runtime SetPipelineConfig RPC将给定的管道配置推送到交换机;在第二种情况下,shell将尝试检索交换机中当前配置的P4Info。

在这两种情况下,shell都会使用P4Info文件做如下工作:

  • 允许使用P4Info名称而不是数字ID来指定运行时实体,例如表条目(更容易记忆和读取)
  • 提供自动补全功能
  • 验证CLI命令

最后,连接P4runtime服务器,有几个重要项:

util/p4rt-sh --grpc-addr localhost:50001 --config 
p4src/build/p4info.txt,p4src/build/bmv2.json --election-id 0,1
  • util/p4rt-sh:这是一个使用p4runtime的工具
  • --grpc-addr localhost:50001:grpc的远程过程调用,下图所示,每一个p4rumtime server都对应了一个转发设备,所以如果我们要同时控制所有的交换机,我们要访问4个server,这个远程过程调用的p4runtime服务器就放在在BMV2这个转发实体上,我们在本机中,要访问他们,就等于是同时访问了4台服务器,这里只先访问一台。
  • SRv6项目实践(三):P4Runtime基础以及交换机控制_第6张图片SRv6项目实践(三):P4Runtime基础以及交换机控制_第7张图片

 

 --config p4src/build/p4info.txt,p4src/build/bmv2.json:这个配置包含了两个关键文件,一个是bmv2.json文件,另一个是P4info文件:分别描述了交换机的行为模型的具体行为,P4info则指定可通过P4Runtime访问的P4实体的元数据,实体与P4源代码中的实例化对象具有一一对应关系,在运行时安装表条目时需要该文件,额外的,还有一个重要的事情,我们可以看到这两个文件是在build下的,是编译后的,所以我们需要先make p4-build才可以使用rumtime

--election-id 0,1 当连接到P4Runtime服务器时,规范要求我们提供一个主控权选举ID,以便能够写入状态,例如管道配置和表条目,通过这个指令,我们可以访问到数据平面交换机leaf1

 好的,现在我们进来了rumtime的命令行,我们可以用各种指令访问到p4交换机它现在身上的表和操作或者计数器有哪些,也可以访问到表、操作、计数器对应的值,让我们来看看吧!如果想知道一个table的具体内容,可以用tables["IngressPipeImpl."]来访问。

SRv6项目实践(三):P4Runtime基础以及交换机控制_第8张图片SRv6项目实践(三):P4Runtime基础以及交换机控制_第9张图片

 

这里有一些功能和表是涉及到后面的代码的,我们先不在乎这些,就看看这几个访问的指令的用法就好了,分别是:tablesactionsaction_profilescountersdirect_counters

大家还可以看看添加表项或者counter的用法,这里就不多说了:

SRv6项目实践(三):P4Runtime基础以及交换机控制_第10张图片

SRv6项目实践(三):P4Runtime基础以及交换机控制_第11张图片

3.P4runtime操作leaf1

首先,使用make mn-cli这个命令,打开mininet的命令行

  • NDP:为了能够ping同一子网中的两个IPv6主机,首先,主机需要使用邻居发现协议(NDP)解析其各自的MAC地址,这相当于IPv4网络中的ARP。例如,当尝试从h1a ping h1b时,h1a将首先生成NDP邻居请求(NS)消息以解析h1b的MAC地址。一旦h1b接收到NDP NS消息,它就应该用具有它自己的MAC地址的NDP邻居广告(NA)来回复。现在,两个主机都知道彼此的MAC地址,并且可以交换ping数据包。
  • 如果使用P4Runtime正确编程,交换机应该能够处理NDP数据包(请参阅l2_ternary_table),但是,为了使事情变得简单,让我们在主机中插入两个静态NDP条目

为两个主机设计静态的条目,在这里,主机1a把1b的ipv6地址和以太网地址对上,然后用h1a的以太网0接口这个网卡来交互

h1a ip -6 neigh replace 2001:1:1::B lladdr 00:00:00:00:00:1B dev h1a-eth0
h1b ip -6 neigh replace 2001:1:1::A lladdr 00:00:00:00:00:1A dev h1b-eth0

使用ip neigh show就可以查看邻居了

 

 但是现在呢,你尝试去ping双方并没有用,因为,就算你主机知道在哪,p4交换机不知道

SRv6项目实践(三):P4Runtime基础以及交换机控制_第12张图片

 为了让交换机能够转发,我们需要做出如下设置,正好对应了顶上的图

Match (Ethernet dest) Egress port number
00:00:00:00:00:1B 4
00:00:00:00:00:1A 3

 在p4runtime的命令行中,输入:

te = table_entry['IngressPipeImpl.l2_exact_table'](action='IngressPipeImpl.set_egress_port')
te.match['hdr.ethernet.dst_addr'] = '00:00:00:00:00:1A'
te.action['port_num'] = '3'
te.insert()

te = table_entry['IngressPipeImpl.l2_exact_table'](action='IngressPipeImpl.set_egress_port')
te.match['hdr.ethernet.dst_addr'] = '00:00:00:00:00:1B'
te.action['port_num'] = '4'
te.insert()

这样就打了两个表项进去了,注意格式,是:

  • tables[要插的表](要做的操作)
  • match[匹配的数据]=数据的值
  • action[操作的数据]=数据的值
  • insert()完成插入

到此,我们就成功插入了表项了,来看看表项:

SRv6项目实践(三):P4Runtime基础以及交换机控制_第13张图片

好了,我们实现了双方的互ping,实验很简单,主要是对操作以及原理的理解。 

 SRv6项目实践(三):P4Runtime基础以及交换机控制_第14张图片

你可能感兴趣的:(服务器,java,运维)