OpenFlow PacketOut消息机制

OpenFlow PacketOut消息机制

前言

由于最近实验的进行,遇到一个比较棘手的问题,就是利用控制器主动发送packet消息的问题,期间遇到一些问题,后来在RYU群中得到群友左木的帮助成功解决,记录一下这些问题,由于是昨天的问题,就没有把错误截图给截下来了(不想在重做一遍了)。

实验工具

  • RYU
  • mininet
  • wireshark

问题描述与解决

ryu指南中的packetout消息(OF1.3)

class ryu.ofproto.ofproto_v1_3_parser.OFPPacketOut(datapath, buffer_id=None, in_port=None, actions=None, data=None, actions_len=None)

Packet-Out message

The controller uses this message to send a packet out throught the switch.

Attribute Description
buffer_id ID assigned by datapath (OFP_NO_BUFFER if none)
in_port Packet's input port or OFPP_CONTROLLER
actions list of OpenFlow action class
data Packet data of a binary type value or an instances of packet.Packet.

Example:

def send_packet_out(self, datapath, buffer_id, in_port):
    ofp = datapath.ofproto
    ofp_parser = datapath.ofproto_parser

    actions = [ofp_parser.OFPActionOutput(ofp.OFPP_FLOOD, 0)]
    req = ofp_parser.OFPPacketOut(datapath, buffer_id,
                                  in_port, actions)
    datapath.send_msg(req)

于是我照猫画虎的来下来如下代码:

        ofp = datapath.ofproto
        ofp_parser = datapath.ofproto_parser
        actions = [ofp_parser.OFPActionOutput(port=1)]
        req = ofp_parser.OFPPacketOut(datapath=datapath, buffer_id=ofp.OFP_NO_BUFFER, in_port=1,
                                      actions=actions)
        datapath.send_msg(req)

这样下来运行也没有错误,可是就是无法在端口一抓到包,心生疑惑又在控制器的那一端抓了一次,结果抓到了这个包。后来在群友耐心指导下,原来是没加data下去,所以在端口一无法抓到包。


于是我就构造了一个arp报文重新发了一次,改了一下代码

        ofp = datapath.ofproto
        ofp_parser = datapath.ofproto_parser
        e = ethernet.ethernet(dst='00:00:00:00:ff:ff',
                              src='08:60:6e:7f:74:e7',
                              ethertype=ether.ETH_TYPE_ARP)
        
        a = arp.arp(hwtype=1, proto=0x0800, hlen=6, plen=4, opcode=2,
                    src_mac='08:60:6e:7f:74:e7', src_ip='192.0.2.1',
                    dst_mac='00:00:00:00:00:00', dst_ip='192.0.2.2')
        p = packet.Packet()
        p.add_protocol(e)
        p.add_protocol(a)
        p.serialize()
        
        actions = [ofp_parser.OFPActionOutput(1)]
        req = ofp_parser.OFPPacketOut(datapath=datapath, buffer_id=ofp.OFP_NO_BUFFER, in_port=1,
                                      actions=actions, data=p)
        datapath.send_msg(req)

这回确实是抓到了,可是又心生疑惑,我明明有一条流表,为什么这个包不会先匹配一下流表吗?于是又向群友求助,原来是:

Action 是一个行动列表定义交换机如何处理数据包的字段。可包括包修改,组处理和一
个输出端口。 一个 OFPT_PACKET_OUT 行动清单消息也可以指定 OFPP_TABLE 保留端口
作为输出行动来处理 OpenFlow 流水线中的数据包,从第一个流表开始(见 4.5) 。如果
OFPP_TABLE 被指定,in_port 作为查找时流表的入端口。

于是我又改了一下代码,把动作改成output到OFPP_TABLE去

       ofp = datapath.ofproto
        ofp_parser = datapath.ofproto_parser
        e = ethernet.ethernet(dst='00:00:00:00:ff:ff',
                              src='08:60:6e:7f:74:e7',
                              ethertype=ether.ETH_TYPE_ARP)

        a = arp.arp(hwtype=1, proto=0x0800, hlen=6, plen=4, opcode=2,
                    src_mac='08:60:6e:7f:74:e7', src_ip='192.0.2.1',
                    dst_mac='00:00:00:00:00:00', dst_ip='192.0.2.2')
        p = packet.Packet()
        p.add_protocol(e)
        p.add_protocol(a)
        p.serialize()
        actions = [ofp_parser.OFPActionOutput(port=ofp.OFPP_TABLE)]
        req = ofp_parser.OFPPacketOut(datapath=datapath, buffer_id=ofp.OFP_NO_BUFFER, in_port=1,
                                      actions=actions, data=p)
        datapath.send_msg(req)

这下确实是大功告成了。


途中也遇到了一个疑惑,buffer_id的作用,相信的可以看这篇Openflow细节理解之—Buffer_id篇

总结

如果是OpenFlow消息交互的问题,还是得回归OpenFlow白皮书。

posted @ 2017-03-18 22:43  考拉小无  阅读(1525)  评论(6编辑  收藏  举报