stateful openflow------整理openstate原理以及具体应用
论文中以端口锁定为例,提出了米粒型状态机在交换机内部的应用从而可以大大减少交换机和控制器之间的交互,减缓了控制器的性能瓶颈。
传统SDN架构,对一些安全应用如端口锁定,只有一定顺序的端口请求才会开放目标端口,如请求22端口进行数据传输,但设置的端口请求列表是[10,12,13,14,22],就是说只有在之前目标主机依次收到这些端口请求后才会开放22号端口。这个策略如果需要由控制器来完成,将会十分繁琐,每次来一个数据包请求控制器,控制器根据历史端口生成处理策略。
论文中指出,SDN的最大优势就是全局能力,而这样的操作完全是本交换机自己的事情,交给控制器处理并没有获得控制器的优势,反而增加了控制器的处理负担。因此提出了交换机内部可以维持一个状态机。
要在交换机中实现上述状态转移功能,交换机需要维持两张表,状态表和流表,流表在原来的基础上进行了扩充,增加了state的查询。具体如下:
知识补充:lookup 和 update
lookup和update是交换机实现的功能,由lookup extractor和update extractor两个功能模块完成,在交换机中实现。两个功能模块作用就是在数据包中取出唯一标识符,可以由控制器自定义。当数据包进入交换机时,调用lookup extractor,比如以源IP为标识符,则为这条数据流生成了以IP地址为标识的唯一标识符。交换机根据这条标识去state table中查找对应的状态,并以该状态和其他匹配字段去查询流表,最终完成了整个功能实现。
端口锁定的实现程序:
LOG = logging.getLogger('app.openstate.portknock')""" Last port is the one to be opened after knocking all the others """ port_list = [10, 11, 12, 13, 22] final_port = port_list[-1] second_last_port = port_list[-2]LOG.info("Port knock sequence is %s" % port_list[0:-1]) LOG.info("Final port to open is %s" % port_list[-1])class OpenStatePortKnocking(app_manager.RyuApp):def __init__(self, *args, **kwargs):super(OpenStatePortKnocking, self).__init__(*args, **kwargs)@set_ev_cls(ofp_event.EventOFPSwitchFeatures, CONFIG_DISPATCHER)def switch_features_handler(self, ev):msg = ev.msgdatapath = msg.datapathLOG.info("Configuring switch %d..." % datapath.id)""" Set table 0 as stateful """req = osparser.OFPExpMsgConfigureStatefulTable(datapath=datapath,table_id=0,stateful=1)datapath.send_msg(req)""" Set lookup extractor = {ip_src} """req = osparser.OFPExpMsgKeyExtract(datapath=datapath,command=osproto.OFPSC_EXP_SET_L_EXTRACTOR,fields=[ofproto.OXM_OF_IPV4_SRC],table_id=0)datapath.send_msg(req)""" Set update extractor = {ip_src} (same as lookup) """req = osparser.OFPExpMsgKeyExtract(datapath=datapath,command=osproto.OFPSC_EXP_SET_U_EXTRACTOR,fields=[ofproto.OXM_OF_IPV4_SRC],table_id=0)datapath.send_msg(req)""" ARP packets flooding """match = ofparser.OFPMatch(eth_type=0x0806)actions = [ofparser.OFPActionOutput(ofproto.OFPP_FLOOD)]self.add_flow(datapath=datapath, table_id=0, priority=100,match=match, actions=actions)# 提前下发状态表""" Flow entries for port knocking """for i in range(len(port_list)):match = ofparser.OFPMatch(eth_type=0x0800, ip_proto=17,state=i, udp_dst=port_list[i])if port_list[i] != final_port and port_list[i] != second_last_port:# If state not OPEN, set state and drop (implicit)actions = [osparser.OFPExpActionSetState(state=i+1, table_id=0, idle_timeout=5)] elif port_list[i] == second_last_port:# In the transaction to the OPEN state, the timeout is set to 10 secactions = [osparser.OFPExpActionSetState(state=i+1, table_id=0, idle_timeout=10)]else:actions = [ofparser.OFPActionOutput(2)]self.add_flow(datapath=datapath, table_id=0, priority=10,match=match, actions=actions)""" Get back to DEFAULT if wrong knock (UDP match, lowest priority) """match = ofparser.OFPMatch(eth_type=0x0800, ip_proto=17)actions = [osparser.OFPExpActionSetState(state=0, table_id=0)]self.add_flow(datapath=datapath, table_id=0, priority=0,match=match, actions=actions)""" Test port 1300, always forward on port 2 """match = ofparser.OFPMatch(eth_type=0x0800, ip_proto=17, udp_dst=1300)actions = [ofparser.OFPActionOutput(2)]self.add_flow(datapath=datapath, table_id=0, priority=10,match=match, actions=actions)def add_flow(self, datapath, table_id, priority, match, actions):inst = [ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions)]mod = ofparser.OFPFlowMod(datapath=datapath, table_id=table_id,priority=priority, match=match, instructions=inst)datapath.send_msg(mod)
数据流状态的转移是根据已经存在的状态表来进行查询和更新的,对一条数据流,先进行状态查询,如果符合match = ofparser.OFPMatch(eth_type=0x0800, ip_proto=17, state=i, udp_dst=port_list[i])则会执行相应的动作,actions = [osparser.OFPExpActionSetState(state=i+1, table_id=0, idle_timeout=5)](已经提前下发),所以整个的重点就是状态表的建立(对每条数据流建立一个状态表)和更新以及带状态的流表的查询。
class OpenStateMacLearning(app_manager.RyuApp):def __init__(self, *args, **kwargs):super(OpenStateMacLearning, self).__init__(*args, **kwargs)def add_flow(self, datapath, table_id, priority, match, actions):if len(actions) > 0:inst = [ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions)]else:inst = []mod = ofparser.OFPFlowMod(datapath=datapath, table_id=table_id,priority=priority, match=match, instructions=inst)datapath.send_msg(mod)@set_ev_cls(ofp_event.EventOFPSwitchFeatures, CONFIG_DISPATCHER)def switch_features_handler(self, event):""" Switche sent his features, check if OpenState supported """msg = event.msgdatapath = msg.datapathLOG.info("Configuring switch %d..." % datapath.id)""" Set table 0 as stateful """req = osparser.OFPExpMsgConfigureStatefulTable(datapath=datapath,table_id=0,stateful=1)datapath.send_msg(req)""" Set lookup extractor = {eth_dst} """req = osparser.OFPExpMsgKeyExtract(datapath=datapath,command=osproto.OFPSC_EXP_SET_L_EXTRACTOR,fields=[ofproto.OXM_OF_ETH_DST],table_id=0)datapath.send_msg(req)""" Set update extractor = {eth_src} """req = osparser.OFPExpMsgKeyExtract(datapath=datapath,command=osproto.OFPSC_EXP_SET_U_EXTRACTOR,fields=[ofproto.OXM_OF_ETH_SRC],table_id=0)datapath.send_msg(req)# for each input port, for each statefor i in range(1, N+1):for s in range(N+1):match = ofparser.OFPMatch(in_port=i, state=s)if s == 0:out_port = ofproto.OFPP_FLOODelse:out_port = sactions = [osparser.OFPExpActionSetState(state=i, table_id=0, hard_timeout=10),ofparser.OFPActionOutput(out_port)]self.add_flow(datapath=datapath, table_id=0, priority=0,match=match, actions=actions)
上面是用来进行端口学习的,乍看还是有点难懂。他最大的好处就是不用和控制器进行交互,提前预下发流表,然后在交换机内部根据状态信息进行学习。
重要的还是对状态表的查询和更新的理解。对每一条流有一个状态,流进入交换机会进行查询操作,查询字段为目的地址;查询到相应状态并进行匹配流表和实施action后,会进行更新操作,更新字段是源地址,也就是说对到来的数据会记录其IP与端口号(用状态表示)。
主要思想如下:
第一步:给所有的(假设n个)端口下发n+1个带状态的流表。如4口交换机则端口1就有生成5个匹配流表,匹配项为入端口号和state值,action为outport,出端口值就是非0的state值,state为0表示泛洪。
但交换机又是如何学习的呢,一条数据流进入,首先通过lookup查询当前流的状态,当没有学习到目的地址时,state值还是为0,泛洪。同时,因为update以源MAC地址更新,匹配到流表后会取出源MAC地址,更新state为进端口号,osparser.OFPExpActionSetState(state=i, table_id=0, hard_timeout=10)
所以下次当有该目的MAC地址来世,查询到的state也就是出端口号。设计的有点反常识,但还是证明stateful 数据平面确实是挺强大的,可以在交换机内部完成一些简单的操作。
stateful openflow 最大的问题就是需要下发的流表太多,在实际应用场景中会有很大的限制。
上述为转载内容:https://www.jianshu.com/p/4fb7f94895d5
总结:
转载于:https://www.cnblogs.com/Pan-xi-yi/p/9650278.html
stateful openflow------整理openstate原理以及具体应用相关推荐
- (转)内存整理的原理 整理自CSDN
内存整理的原理 整理自CSDN 拓荒时代 国内的程序员大多是在 Java 语言中第一次感受到垃圾收集技术的巨大魅力的,许多人也因此把 Java 和垃圾收集看成了密不可分的整体.但事实上,垃圾收集技术早 ...
- 内存整理的原理是什么?
拓荒时代 国内的程序员大多是在 Java 语言中第一次感受到垃圾收集技术的巨大魅力的,许多人也因此把 Java 和垃圾收集看成了密不可分的整体.但事实上,垃圾收集技术早在 Java 语言问世前 30 ...
- EJB3.0学习笔记-----Stateful Session Bean的原理
和Http Session十分的类似: EJB服务器返回的是一个实现了FirstEjb接口的一个代理对象. EJB池中有很多对象;一个EJB可能有多个对象,和Session对象一样,多个对 ...
- 电路原理笔记整理,电路原理知识点总结.doc
PAGE PAGE 3 1.电流的参考方向可以任意指定,分析时:若参考方向与实际方向一致,则i>0,反之i<0.电压的参考方向也可以任意指定,分析时:若参考方向与实际方向一致,则u> ...
- OpenFlow和SDN的历史和原理介绍
OpenFlow相关的历史.新闻:http://blog.csdn.net/jincm13/article/details/7825754 起源与发展 [https://36kr.com/p/5035 ...
- 微型计算机原理综合实验报告,微机原理综合实验报告[精心整理].doc
微机原理综合实验报告[精心整理] 微机原理综合实验报告 主题:数字钟的设计与实现 成员:陈天朗(P 洪 力(P 时间:2014年春季学期 实验原理 利用8254产生计时时钟信号,通过设置恰当的时间常数 ...
- 还没吃透内存缓存LruCache实现原理的看这篇文章,面试必会
前言 这篇文章主要是分享今年上半年的面试心得,现已就职于某大厂有三个月了,近期有很多公司均已启动秋招,也祝大家在 2020 的下半年面试顺利,获得理想的offer! 之前找工作的那段时间感想颇多,总结 ...
- [转]SDN与OpenFlow技术简介
http://blog.163.com/s_zhchluo/blog/static/15014708201411144727961/ 本文是2012年文章,对Openflow的发展.规范.应用和SDN ...
- SDN与OPENFLOW 简介
本文对Openflow的发展.规范.应用和SDN的提出及相关应用做出较为客观全面的介绍.笔者希望通过本文对OpenFlow/SDN做一个初步介绍,以期帮助大家能够进一步深入了解和学习OpenFlow/ ...
最新文章
- DeepChem | PyTorch中用自定义层实现DeepChem的GraphConvLayer
- android的横竖屏切换,Android横竖屏切换 初步探究
- 基于python3的一次简单的请求url接口返回json类型结果实例。
- Vuex的全面用法总结
- vcpkg安装_微软牌包管理器vcpkg更新及路线图计划
- django框架学习文档_Python四大主流网络编程框架,你知道么?
- android 底部动画,Android实现360手机助手底部的动画菜单
- Notepad++在编程使用时的小技巧
- Ubuntu 14.04安装和卸载搜狗拼音输入法
- 前景检测算法(一)--综述
- Atitit.每周末总结 于每周一计划日程表 流程表 v8
- java bat运行jar文件_利用.bat文件运行jar文件
- 联想电脑摄像头无法使用
- 强化学习评估-Doubly robust
- GB/T28181之国标编码一览表,需要自取
- 解决markdown插入图片的痛楚!!!!
- Selector空轮询
- 使用Jupyter Notebook远程连接服务器
- Esrally性能测试步骤与调优
- spice Main Channel definition