You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

基于OpenFlow 13的RYU SDN控制器中buffer_id作用及开发疑问

搞懂OpenFlow 1.3里的buffer_id,结合你的RYU代理应用讲明白

嘿,我太懂你这种困惑了!当初我在搞RYU开发的时候,也对着buffer_id懵了好久,今天结合你写的代理应用代码,给你掰扯清楚它到底是干啥的。

首先,buffer_id的核心作用:交换机的“临时数据包储物柜”

说白了,当交换机收到一个数据包,没在流表里找到匹配的转发规则时,它会把这个数据包暂时存在自己的缓冲区里,然后给控制器发一条PacketIn消息——这个buffer_id就是缓冲区里这个数据包的唯一门牌号码

控制器回复PacketOut的时候,用这个门牌号码,交换机就知道直接从自己的储物柜里拿出对应的数据包,执行你指定的动作,不用你把整个数据包再从控制器传回去,能省不少带宽,效率高多了!

结合你的代码分析:用buffer_id到底行不行?

你的代码是收到目的IP为192.168.2.2的数据包,修改成172.10.2.2后从端口2输出,用了buffer_id=msg.buffer_id——这完全没问题!

这里要澄清一个常见误区:修改数据包字段(比如你用的OFPActionSetField)不影响buffer_id的使用。因为SetField是转发时的动作,交换机从缓冲区取出原始数据包后,会先执行你设置的字段修改,再转发到指定端口,整个流程是通顺的。

必须注意的两个关键点

  • 不是所有PacketIn都带有效buffer_id:如果交换机的缓冲区满了,它会把buffer_id设为OFP_NO_BUFFER,这时候你必须在PacketOut里带上原始数据包的data字段,交换机才能处理。所以你的代码最好加个判断,让它更健壮:
# 先获取交换机的协议对象
ofproto = datapath.ofproto
parser = datapath.ofproto_parser

# 你的动作定义
actions = [
    parser.OFPActionSetField(eth_dst=pkt_ethernet.dst),
    parser.OFPActionSetField(ipv4_dst='172.10.2.2'),  # 这里替换为你要修改的目标IP
    parser.OFPActionOutput(2)
]

# 处理buffer_id的两种情况
if msg.buffer_id != ofproto.OFP_NO_BUFFER:
    out = parser.OFPPacketOut(
        datapath=datapath,
        buffer_id=msg.buffer_id,
        in_port=msg.match['in_port'],
        actions=actions
    )
else:
    out = parser.OFPPacketOut(
        datapath=datapath,
        buffer_id=ofproto.OFP_NO_BUFFER,
        in_port=msg.match['in_port'],
        actions=actions,
        data=msg.data
    )

# 发送PacketOut消息
datapath.send_msg(out)
  • buffer_id和流表项没关系:别把它和流表项的缓存搞混了!buffer_id只是临时存单个数据包的标识,流表项是存在交换机流表中的长期规则,两者完全不是一回事。

什么时候必须用OFP_NO_BUFFER?

只有当你直接修改了数据包的二进制内容(比如把msg.data拆包修改后重新封装),这时候交换机缓存的原始数据包已经不符合你的需求了,你才需要把buffer_id设为OFP_NO_BUFFER,并把修改后的data传给交换机。

内容的提问来源于stack exchange,提问作者Srikanth Gopalakrishnan

火山引擎 最新活动