Openflow细节理解之—Buffer_id篇
OpenFlow消息中buffer_Id是什么?
Openflow中buffer_id分别在三类消息中定义,并且起到的作用均是不同的。
✔ Packetin消息:用于标记缓存在交换机中的数据报文id,如报文被action上送到控制器中maxlen字段或者table_miss消息限制长度,而通过bufferid将报文缓存在交换机中,以便被另外两种消息来调用;
✔ Packetout消息:用于控制器将原先buffer在交换机中的报文,通过Packetout个形式从交换机的某个物理口送出去;
✔ Flowmod消息:如果flowmod中带有bufferid,那么说明这个flowmod需要做两件事情,第一是正常下发一条flow,其次是把交换机中先前buffer的那个数据报文,Packetout到table来匹配一次下的这条flow;注意以上两个指令都是通过这个带有bufferid的消息执行的,不需要控制器另外下packet_out消息,这种设计思路是非常巧妙的。
为什么要引入buffer_Id?
优点没必要多说,Packet_in到控制器的报文决策之后,大部分报文必然还是要扔回交换机的,为何不在交换机上缓存起来,只送个tag上去呢?
Openflow针对buffer_id的设计思想
✔ 协议针对packetin/packetout中buffer_id的设计思想很简单,一个上去,一个下来,具体思路参考下面例子。
✔ 协议针对Flowmod中bufferid设计思想就非常巧妙了,前面我已经提过,如果flowmod中带有bufferid,那么说明这个flowmod需要做两件事情,第一是正常下发一条flow,其次是把交换机中先前buffer的那个数据报文,Packetout到table来匹配一次下的这条flow;我这里举个例子大家就明白为什么这么设计了:
举例
✔ 假设现在从交换机的某个口进来一个arp请求的报文,通过tablemiss直接Packetin(bufferid是0x100)上送到controller了,controller收到之后这个arp请求之后肯定会通过Packetout(bufferid填0x100)把这个报文给广播出去,这个过程数据报文不用真正整个都送到控制器,只要送上去指定长度部分,并通过bufferid来交互数据报文内容
✔ 现在又假设交换机上某个口挂的host响应了这个arp请求,并回复了arp reply,交换机收到依然果断Packetin(bufferid是0x100)送控制器,这个时候控制器已经知道了往哪里回复,那控制器这个时候不Packetout了,干脆下个flowmod(bufferid是0x100)吧,反正以后肯定还要有报文交互,那flowmod下下去了来匹配转发来个host的报文,那怎么来保证你本次这个arp应答也被转发呢?所以这个时候设计者非常巧妙地又让这个报文通过Packet_out到table再次进入交换机pipline通道一次,以保证本次交互不需要其他动作也能成功
Ryu测试buffer_id完整app代码
from ryu.base import app_manager
from ryu.controller.handler import CONFIG_DISPATCHER
from ryu.controller.handler import set_ev_cls
from ryu.controller import ofp_event
import logging
import time
import itertools
from ryu.ofproto import ofproto_v1_3
from ryu.lib import mac
LOG = logging.getLogger("buffer_id_test")
class buffer_id_test(app_manager.RyuApp):
def __init__(self, *args, **kwargs):
self.__name__ = "buffer_id_test"
super(buffer_id_test, self).__init__(*args, **kwargs)
@set_ev_cls(ofp_event.EventOFPSwitchFeatures, CONFIG_DISPATCHER)
def buffer_id_test(self, ev):
datapath = ev.msg.datapath
ofp = datapath.ofproto
parser = datapath.ofproto_parser
print "#######"
print '''Test Start'''
print "#######"
print "#######"
print '''step 1. + Add table_miss_flow'''
print "#######"
match = parser.OFPMatch()
oas = []
oa = parser.OFPActionOutput(ofproto_v1_3.OFPP_CONTROLLER, ofproto_v1_3.OFPCML_MAX)
oas.append(oa)
inst = parser.OFPInstructionActions(ofproto_v1_3.OFPIT_APPLY_ACTIONS, oas)
insts = []
insts.append(inst)
fm = parser.OFPFlowMod(datapath,
0, 0,
0, # table 0
ofproto_v1_3.OFPFC_ADD,
0, 0,
0, # must have higher priority.
0xffffffff,
ofproto_v1_3.OFPP_ANY,
0xffffffff,
0,
match,
insts)
datapath.send_msg(fm)
print "#######"
print '''step 2. + Send pkt ip_dst=1.1.1.1,send to controller'''
print "#######"
###这里报文自己拿工具去发,推荐scapy
time.sleep(10)
print "#######"
print '''step 3_1.(Flow_mod) + Add Flow with buffer_id of 0x100'''
print "#######"
match = parser.OFPMatch()
match.set_dl_type(int(int(0x800)))
match.set_ipv4_dst(int(16843009))
oas = []
oa = parser.OFPActionOutput(6, ofproto_v1_3.OFPCML_MAX)
oas.append(oa)
inst = parser.OFPInstructionActions(ofproto_v1_3.OFPIT_APPLY_ACTIONS, oas)
insts = []
insts.append(inst)
fm = parser.OFPFlowMod(datapath,
0, 0,
0, # table 0
ofproto_v1_3.OFPFC_ADD,
0, 0,
10, # must have higher priority.
0x100,
ofproto_v1_3.OFPP_ANY,
0xffffffff,
0,
match,
insts)
datapath.send_msg(fm)
print "#######"
print '''step 3_2.(Packet_out) + Add Packet_out message with buffer_id of 0x100'''
print "#######"
oa = parser.OFPActionOutput(6, ofproto_v1_3.OFPCML_MAX)
oas = []
oas.append(oa)
#pkt="x00x00x00x01x01x01x00x00x00x02x02x02x08x00x45x111111111111111111111111111111111111"
po = parser.OFPPacketOut(datapath, 0x100, 0,
oas
)
datapath.send_msg(po)
总结思考
目前ovs针对报文buffer的做法是一个报文就对应一个buffer,不管是不是同一个报文,这样的坏处浪费了交换机buffer的资源,更加优化的做法是交换机收到相同报文只buffer一次并且只上送同一个buffer_id给控制器。
- 解码针对工业工程领域的网络攻击 Operation Ghoul「食尸鬼行动」
- EndpointAddress——不只是一个Uri[上篇]
- EndpointAddress——不只是一个Uri[下篇]
- ASP.NET Core中如影随形的”依赖注入”[上]: 从两个不同的ServiceProvider说起
- ASP.NET Core中如影随形的”依赖注入”[下]: 历数依赖注入的N种玩法
- ASP.NET Core中的缓存[1]:如何在一个ASP.NET Core应用中使用缓存
- ASP.NET Core的路由[5]:内联路由约束的检验
- .NET Core跨平台的奥秘[下篇]:全新的布局
- Equation Group泄露文件分析
- ModelBinder——ASP.NET MVC Model绑定的核心
- 一句代码实现批量数据绑定[下篇]
- 三种属性操作性能比较:PropertyInfo + Expression Tree + Delegate.CreateDelegate
- 解密Myspace密码的姿势
- weblogic安全配置二三事
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Java反射
- Java Request(域对象+请求转发+原理)详解
- PHP命令执行学习总结
- win10 专业版 提示开机提示你的windows许可证即将过期
- 浅谈文件上传漏洞(其他方式绕过总结)
- 《sql必知必会》——读书笔记(1)
- JDK15已发布,网友:我还在JDK8踏步走...
- 树莓派基础实验15:电位器传感器实验
- java JDBC数据库连接池技术(Druid ,c3p0)
- Fail to start qos server: dubbo version: current host: java.net.BindException:
- JAVA JDBC Template的使用
- 《sql必知必会》——读书笔记(2)
- 2.通过QOpenGLWidget绘制三角形
- 树莓派基础实验16:霍尔传感器实验
- 1.opengl绘制三角形