Sonic测试架构介绍

Sonic项目简介

  • Sonic:Software for Open Networking in the Cloud
  • Sonic是基于Linux的开源网络操作系统,可以跑在多个不同芯片厂商交换机上
  • Sonic在2016年OCP峰会上,由微软发布
  • Sonic提供了全套的网络功能,并且都是开源的,如BGP、RDMA等协议
  • Sonic项目更多信息请查阅Github:github.com/Azure/SONic

Sonic测试框架介绍

Sonic项目专门成立了一个子项目Sonic-mgmt来负责Sonic交换机测试一块的事情

整个测试框架图如下

设备信息

  • 这套测试框架由TestBed Server、两级Fanout交换机、Sonic被测交换机组成
  • TestBed Server上主要起两个docker(Sonic-mgmt、Docker-ptf)
    • Sonic-mgmt 主要负责调配整个测试流程,包括启动协议VM、调用ptf等
    • Docker-Ptf 主要负责收发报文以及数据平面的校验
  • Fanout交换机主要负责将Testbed Server上逻辑模拟出的端口跟被测设备物理对接起来
  • Sonic-DUT被测设备,启动Sonic软件的交换机

架构图逻辑解析

  • 物理上TestBed-Server通过两级Fanout交换机连接到被测设备
    • TestBed-Server内部通过Vlantag划分出多个逻辑端口(可以把每个逻辑端口想象成测试仪端口)
    • RootFanout进行设备级的Vlan隔离,实现多组被测设备同时进行验证
    • LeafFanout进行端口级的vlan隔离,实现Testbed逻辑端口与被测Sonic设备物理端口一一对应
  • 逻辑上TestBed-Server上通过vlan隔离出来的各个逻辑端口与物理上被测Sonic设备进行一对一端口连接

TestBed Server内部结构

网络连接

  • TestBed Server有两个网络端口
    • Mgmt口:管理端口,连接到实验室的管理网络
    • Trunk口:数据端口,连接Fanout交换机,负责数据层面业务发包/收包验证

VM虚拟机

  • VM按照测试场景需要,由Mgmt-Sonic Docker负责调用启动,实际跑在TestBed Server上
    • VM使用的是Arista vEOS 镜像
    • VM主要负责跑各种协议,如BGP、LACP、LLDP,然后跟被测设备做协议层面的对接
    • 每个VM由10个逻辑口,8个数据口逻辑上跟交换机各个物理端口相连,另外还有一个背板口负责VM之间互联,还有一个管理口

Docker-ptf

  • Ptf(python test framework) docker由Mgmt-Sonic Docker负责调用启动,跑在TestBed Server上
    • Ptf docker可以按照实际场景,启动不同数量的逻辑端口与被测设备互联
    • Ptf docker负责测试过程中数据层面,收发报文,以及报文验证
    • Ptf 主要通过调用scapy库完成上述动作,并且可以灵活扩展,比如适配Ixia测试仪等

自动化脚本处理流程详解

  • 控制执行层面
    • 脚本以aniable-playbook的形式在Sonic-mgmt-docker上进行调用执行
    • playbook中可以包含配置下发、状态查看、配置清空等动作
    • playbook中可以通过调用ptf-docker来实现收发报文、验证报文
  • 数据层面(以server发出为例)
    • 数据层面Docker-Ptf、VM通过Server发送出来的报文都会携带不同的vlantag,用于区分内部逻辑端口(所以服务器数据出口是trunk口)
    • RootFanout交换机收到带vlantag的报文之后,通过出口vlan过滤,将携带特定vlan范围的报文发送到特定的LeafFanout交换机上(所以Root Fanout入口和出口都是trunk口,只是过滤的范围不同)
    • LeafFanout交换机收到带vlantag的报文之后,通过出口vlan过滤,并去除相应过滤tag之后,转发到被测设备的不同物理端口上,最终这个Tag对于被测设备来说是不可见的(所以LeafFanout连接RootFanout的是trunk口,连接被测设备的是Access端口)

简化逻辑图举例

  • 这个示例图是去掉fanout交换机后的逻辑topo示例,摘自官网说明文档topo中其中一个
  • PTF这里的连接端口数是可以自己定义改变的
  • VM连接数量也是可以自己定义改变的

Sonic测试脚本

PTF发包原理

  • PTF发包实际都是调用的scapy来完成,跟oftest如出一辙
  • 如果熟悉openflow oftest的小伙伴应该对这块会非常亲切

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

    '''

    When receiving gratuitous ARP packet, if it was not resolved in ARP table before,

    SONiC should discard the request and won't add ARP entry for the GARP

    '''

    def runTest(self):

        acs_mac = self.test_params['acs_mac']

        pkt = simple_arp_packet(pktlen=60,

                      eth_dst='ff:ff:ff:ff:ff:ff',

                      eth_src='00:05:07:08:09:0a',

                      vlan_vid=0,

                      vlan_pcp=0,

                      arp_op=1,

                      ip_snd='10.10.1.7',

                      ip_tgt='10.10.1.7',

                      hw_snd='00:05:07:08:09:0a',

                      hw_tgt='ff:ff:ff:ff:ff:ff',

                      )

        exp_pkt = simple_arp_packet(eth_dst='00:05:07:08:09:0a',

                        eth_src=acs_mac,

                        arp_op=2,

                        ip_snd='10.10.1.2',

                        ip_tgt='10.10.1.7',

                        hw_tgt='00:05:07:08:09:0a',

                        hw_snd=acs_mac,

                   )

        send_packet(self, self.test_params['port'], pkt)

        verify_no_packet(self, exp_pkt, self.test_params['port'])

Sonic-Mgmt执行脚本

  • 执行脚本、配置等操作流程实际都是调用的ansible-playbook来完成
  • 脚本都比较长,下述截取部分arpall.yml中内容

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

    - name: wait for interfaces to be up after removed from portchannel

      pause: seconds=40

      when: (po1 is defined) or (po2 is defined)

    - name: copy test files over

      copy: src=roles/test/files/ptftests

            dest=/root

      delegate_to: "{ { ptf_host }}"

    - name: Clear DUT arp cache

      command: ip -stats neigh flush all

      ignore_errors: yes

      become: yes

    - name: Start PTF runner and Send correct unicast arp packets (10.10.1.3 to 10.10.1.2 with src_mac=00:06:07:08:09:00)

      include_tasks: ptf_runner.yml

      vars:

         ptf_test_name: ARP test

         ptf_test_dir: ptftests

         ptf_test_path: arptest.VerifyUnicastARPReply

         ptf_platform: remote

         ptf_platform_dir: ptftests

         ptf_test_params:

            - acs_mac='{ { ansible_interface_facts[intf1]['macaddress'] }}'

            - port='{ { intf1_indice }}'

         ptf_extra_options: "--relax --debug info --log-file /tmp/arptest.VerifyUnicastARPReply.{ {lookup('pipe','date +%Y-%m-%d-%H:%M:%S')}}.log "

    - name: Get DUT arp table

      switch_arptable:

    - name: Check SONiC ARP table and confirm macaddress and interface are correct

      assert:

        that:

          - "{ { arptable['v4']['10.10.1.3']['macaddress'] == '00:06:07:08:09:00' }}"

          - "{ { arptable['v4']['10.10.1.3']['interface'] == intf1 }}"

    - name: Clear DUT arp cache

      command: ip -stats neigh flush all

      ignore_errors: yes

      become: yes

    # Send correct ARP request from correct interface, expecting normal behavior

    - name: PTF funner Send correct arp packets (10.10.1.3 to 10.10.1.2 with src_mac=00:06:07:08:09:0a)

      include_tasks: ptf_runner.yml

      vars:

         ptf_test_name: ARP test

         ptf_test_dir: ptftests

         ptf_test_path: arptest.ExpectReply

         ptf_platform: remote

         ptf_platform_dir: ptftests

         ptf_test_params:

            - acs_mac='{ { ansible_interface_facts[intf1]['macaddress'] }}'

            - port='{ { intf1_indice }}'

         ptf_extra_options: "--relax --debug info --log-file /tmp/arptest.VerifyARPReply.{ {lookup('pipe','date +%Y-%m-%d-%H:%M:%S')}}.log "

    - name: Get DUT arp table

      switch_arptable:

    - name: Check SONiC ARP table and confirm macaddress and interface are correct

      assert:

        that:

          - "{ { arptable['v4']['10.10.1.3']['macaddress'] == '00:06:07:08:09:0a' }}"

          - "{ { arptable['v4']['10.10.1.3']['interface'] == intf1 }}"

    ## check DUT won't reply ARP and install ARP entry when ARP request coming from other interfaces

    - name: Clear DUT arp cache

      command: ip -stats neigh flush all

      ignore_errors: yes

      become: yes

最后号召一下,有没有也在搭这套测试环境的小伙伴加我微信feng_891005,一起讨论,一个人研究太累了。

猜你喜欢

转载自blog.csdn.net/weixin_39094034/article/details/115009577