OFTest(四):一种测试交换机流表下发速率的方法

引言:对于OpenFlow交换机,流表下发速率是一个非常重要的指标。虽然OpenFlow交换机的Spec定义了barrier_request和barrier_reply机制来查询交换机是否操作完毕,但是可信度是存疑的。最有说服力的方法是用匹配流表的报文来做检测。此处提供一种使用OFTest套件来测试流表下发速率的方法供参考。

环境搭建

  • 一台待测的OpenFlow交换机,配置好controller的IP和port信息,保证OFTest运行时能够正确连接
  • 安装了OFTest测试套件的PC,需要有两个网口连接到交换机上(eth1->port1,eth2->port2)
  • 一台发包测试仪,例如Ixia,用来持续发探测包(ixia->port8)
Paste_Image.png

组包发包

  • 使用发包测试仪组以太报文,并在运行OFTest脚本前就开始持续发包
  • dest mac固定为0000:ffff:ffff
  • source mac从0000:0000:0001递增,step=1,repeat=4000(后面添加flow条目数)
  • 线速发包,报文长度固定为64bytes,那么发包速率是1488095pps,意味着每秒每种报文会发1488095/4000=372.02次
  • 那么一种报文循环周期的时间就是1/372.02=0.0027s,所以在后面脚本中在端口poll的等待周期需要超过0.0027秒

测试思路

  • 首先在交换机上加一条priority为0的flow,将从port8进来的所有流量都转发到port1
  • 提前组好4000个add_flow的message,这些message会逐个匹配不同source mac,并转发到port2
  • 开始计时,并将上一步准备好的message一次性发给交换机
  • 立即开始polling交换机的port1,直到在一秒的周期内没有dest mac为0000:ffff:ffff的报文再转发出来,说明后加的4000条flow全部生效了
  • 立即再次计时
  • 4000条flow除以两次计时之差再减去等待时间,即为每秒真正下发的流表数
  • 删除所有流表,并需要抓包验证真正删除了
  • 多次重复上述步骤,取得平均值,即为最后 测试结果

脚本实现

  • 在OFTest中,一个class就是一个case,继承自base_tests.SimpleDataPlane即可
class FlowAddRate(base_tests.SimpleDataPlane):
  • 在class内部定义函数timekeeping,用来计算单次的流表下发速率
    def timekeeping(self,requests):
        detect_pkt = simple_tcp_packet(pktlen=100,eth_dst="00:00:ff:ff:ff:ff" )
        ignore_list = [(6,99)]
        start_time = time.time()
        for request in requests:    
            self.controller.message_send(request)
        while True:
           (rcv_port,rcv_pkt,pkt_time) = self.dataplane.poll_ignore_parts(port_number=self.out_port1,
           timeout=1,exp_pkt=str(detect_pkt),ignore_list=ignore_list)
           if rcv_pkt is not None:    #说明还有flow没有生效,重新poll
               continue
           else:                      #在等待的1秒时间内,没有报文再从port1转发出来,说明4000条flow全部生效
               break
        end_time = time.time()
        return TEST_FLOW_NUM / (end_time - start_time-1)  #这里需要减去多等待的1秒
  • 定义函数rateVerify,用来提前组好4000个添加flow的报文,存储在一个list里,并调用timekeeping返回单次测试结果
    def rateVerify(self):
        requests = []
        for flow_num in range(1,TEST_FLOW_NUM+1):
            match = ofp.match([
                                ofp.oxm.in_port(ofp_port_ixia_mac_inc),
                                ofp.oxm.eth_src([0x00, 0x00, 0x00, 0x00,flow_num/256,flow_num%256])
              ])
            actions =  [ofp.action.output(self.out_port2)]
            request = ofp.message.flow_add(
                    table_id=test_param_get("table", 0),
                    match=match,
                    instructions=[
                        ofp.instruction.apply_actions(actions)],
                    buffer_id=ofp.OFP_NO_BUFFER,
                    priority=1000)
            requests.append(request)
        return self.timekeeping(requests)
  • 定义函数checkNoForward,用来清除流表后确认指定端口没有报文转发出来,说明所有流表都被真正删除了
    def checkNoForward(self,chk_port):  
        detect_pkt = simple_tcp_packet(pktlen=100,eth_dst="00:00:ff:ff:ff:ff" )
        ignore_list = [(6,99)]
        while True:
           (rcv_port,rcv_pkt,pkt_time) = self.dataplane.poll_ignore_parts(port_number=chk_port,
                                     timeout=1,exp_pkt=str(detect_pkt),ignore_list=ignore_list)
           if rcv_pkt  is not None:  
               continue
           else:
               return
  • 入口函数runTest中,可以设定测试次数test_time,并把每次测试结果和最终平均速率写到log中
    def runTest(self):
        self.out_port1, self.out_port2= openflow_ports(2)
        test_time = 10
        
        #test priority increase
        record = []
        for i in range(test_time):
            delete_all_flows(self.controller,timeout=20)
            self.checkNoForward(self.out_port2)   #确保没有报文转发出来
            self.checkNoForward(self.out_port1)
            match =  ofp.match([ofp.oxm.in_port(ofp_port_ixia_mac_inc), ])
            actions = [ofp.action.output(self.out_port1)]
            request = ofp.message.flow_add(
                         table_id=test_param_get("table", 0),
                         match=match,
                         instructions=[
                             ofp.instruction.apply_actions(actions)],
                         buffer_id=ofp.OFP_NO_BUFFER,
                         priority=0)
            self.controller.message_send(request) #添加priority=0的flow,将流量都转发到port1
            (rcv_port,rcv_pkt,pkt_time)  = self.dataplane.poll(port_number=self.out_port1,exp_pkt=None)
            self.assertTrue(rcv_pkt  is not None,"Please keep transmitting source mac increase flow before test!")
            
            s=self.rateVerify()
            record.append(s)   #将每次测试结果存在列表中
             
        logging.info("~~~~~ veirfy priority fix~~~~~~~" )
        for s in record:
            logging.info("%f flows per second" % s)
        logging.info("!!!avarage=%f flows per second" % (sum(record)/test_time))
        logging.info("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" )
  • 运行脚本然后查看结果
centec@centec-28:~/workshop/oftest-new$ sudo ./oft -p 6653 -P remote -V 1.3 --test-dir tests-1.3-advance performance_validation.FLOW_ADD_RATE --log-file=flow_add_rate.txt
......
centec@centec-28:~/workshop/oftest-new$ more flow_add_rate.txt
17:43:34.908  root      : INFO    : ~~~~~ veirfy priority fix~~~~~~~
17:43:34.908  root      : INFO    : 1030.014116 flows per second
17:43:34.908  root      : INFO    : 973.554838 flows per second
17:43:34.909  root      : INFO    : 976.370872 flows per second
17:43:34.909  root      : INFO    : 1074.302799 flows per second
17:43:34.909  root      : INFO    : 1013.381452 flows per second
17:43:34.909  root      : INFO    : 1023.900947 flows per second
17:43:34.909  root      : INFO    : 1018.519737 flows per second
17:43:34.909  root      : INFO    : 957.920226 flows per second
17:43:34.910  root      : INFO    : 1025.500571 flows per second
17:43:34.910  root      : INFO    : 969.328993 flows per second
17:43:34.910  root      : INFO    : !!!avarage=1006.279455 flows per second
17:43:34.910  root      : INFO    : ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

扩展

不同priority的排列

  • 上面举例中,rateVerify中定义的所有流表的priority是固定的
  • 如果需要priority递增:priority=flow_num
  • 如果需要priority递减:priority=6000-flow_num
  • 如果需要priority随机:priority=flow_num ,然后将组好的request打乱顺序 random.shuffle(requests)

删除流表速率

  • 根据上面的思路,很容易设计出按照不同priority的顺序(升序/降序/随机)删除流表的测试速率的方法。

本文首发于SDNLAB http://www.sdnlab.com/17103.html

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容