補充:
(一)Ubuntu下安裝Notepadqq
背景:為什么安裝Notepadqq
Notepad++ 不僅有語法高亮度顯示,也有語法折疊功能,並且支持宏以及擴充基本功能的外掛模組。
但是可惜的是Notepad++只能在Windows平台下使用。 工作中必須使用Windows時,Notepad++是眾多程序員最喜愛的文本編輯器,
在Ubuntu下是否能夠使用到相同的軟件呢?
Notepadqq就是這樣一款與Notepad++非常接近的編輯器,擁有幾乎相同的功能。
安裝:
sudo add-apt-repository ppa:notepadqq-team/notepadqq sudo apt-get update sudo apt-get install notepadqq
安裝(2):
snap install --classic notepadqq
補充:什么是snap軟件包?
卸載:
sudo apt-get remove notepadqq sudo add-apt-repository --remove ppa:notepadqq-team/notepadqq
(二)Ubuntu下安裝 sublime
優點:
一流的Git集成 增量差異功能可跟蹤正在編輯的文件的更改。 移動到GTK3,以及針對Linux的各種高DPI修復。 新的主題功能和塊插入支持。 支持Unicode 11.0 對代碼塊(block caret)的支持 語法高亮增加對 Clojure, D, Go, Lua 語言的支持
安裝:
1.由於最近下載速度太慢: http://pan.baidu.com/s/1kURLcZt 密碼: acm6
2.進行安裝:sudo dpkg -i sublime-text_build-3126_amd64.deb
3.安裝package control以及Anaconda插件https://www.jianshu.com/p/36df65bc78f9
卸載編輯器
sudo apt remove --autoremove sublime-text
零:如何編程
一:Hub/集線器 (編程思路)《重點》
(一)明確問題
如何實現軟件定義的集線器?
(二)設計解決方案
通過控制器來實現集線器算法(泛洪),然后知道數據平面實現集線器操作
(三)確定具體的技術方案
控制器選用Ryu,數據平面通過Mininet模擬
(四)部署實施
在控制器上編程開發集線器應用,創建實驗網絡為驗證方案做准備
(五)驗證方案
運行程序,調試程序,驗證程序
(六)優化
驗證成功后,優化程序
二:集線器原理---設計解決方案
一個數據包從port1進入,會被復制,泛洪轉發到其他所有端口發出
三:部署實施---Ryu控制器API學習和使用(Hub集線器開發)
(一)代碼實現
from ryu.base import app_manager from ryu.ofproto import ofproto_v1_3 from ryu.controller import ofp_event from ryu.controller.handler import MAIN_DISPATCHER,CONFIG_DISPATCHER from ryu.controller.handler import set_ev_cls class Hub(app_manager.RyuApp): OFP_VERSIONS = [ofproto_v1_3.OFP_VERSION] def __init__(self,*args,**kwargs): super(Hub,self).__init__(*args,**kwargs) @set_ev_cls(ofp_event.EventOFPSwitchFeatures,CONFIG_DISPATCHER) def switch_features_handler(self,ev): datapath = ev.msg.datapath ofproto = datapath.ofproto ofp_parser = datapath.ofproto_parser match = ofp_parser.OFPMatch() actions = [ofp_parser.OFPActionOutput(ofproto.OFPP_CONTROLLER,ofproto.OFPCML_NO_BUFFER)] self.add_flow(datapath,0,match,actions,"default flow entry") def add_flow(self,datapath,priority,match,actions,remind_content): ofproto = datapath.ofproto ofp_parser = datapath.ofproto_parser inst = [ofp_parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions)] mod = ofp_parser.OFPFlowMod(datapath=datapath,priority=priority, match=match,instructions=inst); print("install to datapath,"+remind_content) datapath.send_msg(mod); @set_ev_cls(ofp_event.EventOFPPacketIn,MAIN_DISPATCHER) def packet_in_handler(self,ev): msg = ev.msg datapath = msg.datapath ofproto = datapath.ofproto ofp_parser = datapath.ofproto_parser in_port = msg.match['in_port'] print("get packet in, install flow entry,and lookback parket to datapath") match = ofp_parser.OFPMatch(); actions = [ofp_parser.OFPActionOutput(ofproto.OFPP_FLOOD)] self.add_flow(datapath,1,match,actions,"hub flow entry") out = ofp_parser.OFPPacketOut(datapath=datapath,buffer_id=msg.buffer_id, in_port=in_port,actions=actions) datapath.send_msg(out);
注意:注釋可能為你帶來不少錯誤...盡可能寫兩個版本,一個不帶注釋,用於調試。一個寫注釋,用於學習,回顧
(二)啟動控制器
ryu-manager hub.py --verbose #進入目錄,在hub.py文件目錄下 --verbose顯示調試信息
(二)啟動Mininet進行連接測試
sudo mn --topo=linear,4 --controller=remote
Ryu控制器端響應:(注意:啟動mininet后,再先關閉Ryu,重新進入,測試效果更好)
openvswitch交換機與Ryu控制器連接,控制器下發默認流表,提示信息install to datapath,default flow entry
(三)使用pingall命令,使得主機向交換機發送數據包---從而實現交換機上傳數據包到控制器,實現流表獲取
獲取提示信息get packet in, install flow entry,and lookback parket to datapath
四: Hub代碼講解(注釋版)
from ryu.base import app_manager from ryu.ofproto import ofproto_v1_3 from ryu.controller import ofp_event from ryu.controller.handler import MAIN_DISPATCHER,CONFIG_DISPATCHER from ryu.controller.handler import set_ev_cls class Hub(app_manager.RyuApp): '''明確控制器所用OpenFlow版本''' OFP_VERSIONS = [ofproto_v1_3.OFP_VERSION] def __init__(self,*args,**kwargs): super(Hub,self).__init__(*args,**kwargs) @set_ev_cls(ofp_event.EventOFPSwitchFeatures,CONFIG_DISPATCHER) def switch_features_handler(self,ev): ''' 在Ryu控制器上,我們需要寫一個函數去處理openvswitch的連接 CONFIG_DISPATCHER : Version negotiated and sent features-request message ''' #對事件進行解析 datapath = ev.msg.datapath #從連接中獲取數據平面的datapath數據結構 ofproto = datapath.ofproto #獲取OpenFlow協議信息 ofp_parser = datapath.ofproto_parser #獲取協議解析 #解析完成 '''在連接建立成功以后,需要控制器下發一個默認流表 來指揮所有匹配不到交換機的數據,把他上傳到控制器上 ''' #install the table-miss flow entry match = ofp_parser.OFPMatch() #匹配域 #OFPActionOutput將數據包發送出去, #第一個參數OFPP_CONTROLLER是接收端口, #第二個是數據包在交換機上緩存buffer_id,由於我們將數據包全部傳送到控制器,所以不在交換機上緩存 actions = [ofp_parser.OFPActionOutput(ofproto.OFPP_CONTROLLER,ofproto.OFPCML_NO_BUFFER)] self.add_flow(datapath,0,match,actions,"default flow entry") #默認缺省流表項,設置優先級最低即可 ''' 數據平面 是由若干網元(Network Element)組成,每個網元包含一個或多個SDN數據路徑(SDN Datapath)。 SDN Datapath是邏輯上的網絡設備,負責轉發和處理數據無控制能力, 一個SDN DataPath包含控制數據平面接口(Control Data Plane Interface,CDPI)、代理、轉發引擎(Forwarding Engine)表和處理功能(Processing Function) SDN數據面(轉發面)的關鍵技術:對數據面進行抽象建模。 ''' def add_flow(self,datapath,priority,match,actions,remind_content): '''構建流表項 : add a flow entry, install it into datapath datapath:表示給哪一個邏輯設備下發流表 priority:表示優先級 match,actions:匹配域和動作 ''' #datapath屬性 ofproto = datapath.ofproto ofp_parser = datapath.ofproto_parser #在OpenFlow1.3版本中定義了instruct指令集(交換機內部的一些操作) #construct a flow msg and send it inst = [ofp_parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions)] mod = ofp_parser.OFPFlowMod(datapath=datapath,priority=priority, match=match,instructions=inst); print("install to datapath,"+remind_content) #發送出去 datapath.send_msg(mod); '''接收數據 Ryu控制器通過裝飾器去注冊監聽某些事件,去處理這些事件。 從而實現從數據平面的消息上傳到控制器,再從控制器平面到應用平面,應用程序去處理事件,再逐跳返回到openvswitch ''' '''要處理這個事件,需要先去注冊監聽他 EventOFPPacketIn: 是我們要監聽的事件 MAIN_DISPATCHER : 是什么狀態下,去監聽該事件---Switch-features message received and sent set-config message ''' @set_ev_cls(ofp_event.EventOFPPacketIn,MAIN_DISPATCHER) def packet_in_handler(self,ev): '''Hub集線器類,所實現的功能: 1.接收從OpenVSwitch發送過來的數據包 2.將數據包泛洪到Hub中的其他端口中 ''' #解析數據結構 msg = ev.msg datapath = msg.datapath ofproto = datapath.ofproto ofp_parser = datapath.ofproto_parser in_port = msg.match['in_port'] #獲取源端口 print("get packet in, install flow entry,and lookback parket to datapath") match = ofp_parser.OFPMatch(); #因為我們是將所有轉發,所以不用管匹配,填空表示全部匹配 actions = [ofp_parser.OFPActionOutput(ofproto.OFPP_FLOOD)] #注意:FLOOD是OpenFlow協議保留端口---泛洪使用 #調用add_flow,將流表項發送 ,指導后續數據包轉發 install flwo entry to avoid packet in next time self.add_flow(datapath,1,match,actions,"hub flow entry") #等級稍微比默認流表項高級 #注意:我們將流表項下發了,但是數據包我們這次接收的,並沒有處理 #就是再將控制器上的數據包,重新發送給datapath,讓他按照流表項處理 #buffer_id是這個數據包,存放在控制器中的緩沖區位置,是在事件中的buffer_id獲取 out = ofp_parser.OFPPacketOut(datapath=datapath,buffer_id=msg.buffer_id, in_port=in_port,actions=actions,data=msg.data) datapath.send_msg(out);
通信流程:《重點》
1.當開始一個Hub集線器時,會先與控制器進行連接,我們需要在Ryu中設置函數去處理連接,設置並下發默認流表---------函數switch_features_handler實現
2.當主機之間通信時,主機上傳信息到OpenVSwitch交換機,而交換機無法匹配到流表項時,我們設置將數據全部上傳給Ryu控制器,我們在控制器端實現Hub集線器的泛洪功能,即設置流表項(match-actions為所有匹配數據包的動作為ofproto.OFPP_FLOOD,並且將該流變下發給原來datapath,同時我們要將之前交換機發送過來的數據包重新發送給交換機(讓其按照新的流表項進行處理)--------函數packet_in_handler實現
3.我們將公共函數add_flow,構建流表項並且下發流表提出
五:實現整體程序運行了解《重點》
(一)程序入口在哪?------app_manager.RyuApp
""" The base class for Ryu applications. RyuApp subclasses are instantiated after ryu-manager loaded all requested Ryu application modules. __init__ should call RyuApp.__init__ with the same arguments. It's illegal to send any events in __init__. The instance attribute 'name' is the name of the class used for message routing among Ryu applications. (Cf. send_event) It's set to __class__.__name__ by RyuApp.__init__. It's discouraged for subclasses to override this. """
1.app_manager.RyuApp是所有Ryu Applications的基類,我們要實現一個控制器應用,必須繼承該基類
2.我們自定義的子類(繼承於RyuAPP的子類),將在ryu-manager命令加載中被實例化(它是在ryu管理器加載所有請求的ryu應用程序模塊后實例化的)
即我們執行ryu-manager hub.py --verbose命令開啟Ryu控制器時,並且處理了所有請求的ryu應用程序模塊,之后Hub子類就被實例化了
3.子類中的__init__方法需要調用父類的__init__方法,並且保持參數一致
def __init__(self,*args,**kwargs):
super(Hub,self).__init__(*args,**kwargs)
(二)設置OpenFlow協議---OFP_VERSIONS
OFP_VERSIONS = None """ A list of supported OpenFlow versions for this RyuApp. The default is all versions supported by the framework. Examples:: OFP_VERSIONS = [ofproto_v1_0.OFP_VERSION, ofproto_v1_2.OFP_VERSION] If multiple Ryu applications are loaded in the system, the intersection of their OFP_VERSIONS is used. """
我們設置的協議類型是1.3版本OFP_VERSIONS = [ofproto_v1_3.OFP_VERSION],其中協議在 from ryu.ofproto import ofproto_v1_3 中
(三)事件監聽----裝飾器實現set_ev_cls
1.from ryu.controller.handler import set_ev_cls
# should be named something like 'observe_event' def set_ev_cls(ev_cls, dispatchers=None): """ A decorator for Ryu application to declare an event handler. Decorated method will become an event handler. ev_cls is an event class whose instances this RyuApp wants to receive. dispatchers argument specifies one of the following negotiation phases (or a list of them) for which events should be generated for this handler. Note that, in case an event changes the phase, the phase before the change is used to check the interest. .. tabularcolumns:: |l|L| =========================================== =============================== Negotiation phase Description =========================================== =============================== ryu.controller.handler.HANDSHAKE_DISPATCHER Sending and waiting for hello message ryu.controller.handler.CONFIG_DISPATCHER Version negotiated and sent features-request message ryu.controller.handler.MAIN_DISPATCHER Switch-features message received and sent set-config message ryu.controller.handler.DEAD_DISPATCHER Disconnect from the peer. Or disconnecting due to some unrecoverable errors. =========================================== =============================== """ def _set_ev_cls_dec(handler): if 'callers' not in dir(handler): handler.callers = {} for e in _listify(ev_cls): handler.callers[e] = _Caller(_listify(dispatchers), e.__module__) return handler return _set_ev_cls_dec
2.被set_ev_cls裝飾的函數將成為一個事件處理器,參數ev_cls是一個事件類,在controller下的ofp_event下(未找到....動態創建類type實現??),dispatchers參數是事件的協商階段
@set_ev_cls(ofp_event.EventOFPSwitchFeatures,CONFIG_DISPATCHER)
(1)協商階段
=========================================== =============================== Negotiation phase Description =========================================== =============================== ryu.controller.handler.HANDSHAKE_DISPATCHER Sending and waiting for hello message ryu.controller.handler.CONFIG_DISPATCHER Version negotiated and sent features-request message ryu.controller.handler.MAIN_DISPATCHER Switch-features message received and sent set-config message ryu.controller.handler.DEAD_DISPATCHER Disconnect from the peer. Or disconnecting due to some unrecoverable errors. =========================================== ===============================
發送並等待Hello消息
雙方通過握手消息Hello建立安全連接
版本協商並發送功能請求消息
雙方建立TLS隧道后,方法發送hello消息進行版本協商
如果協議版本協商成功,則連接建立。否則發送Error消息描述協商失敗原因,並終止連接
交換機特征消息接收和發送設置配置消息
協商完成后,控制器和交換機之間發送Features消息,獲取交換機參數
參數包括支持的buffer數目、流表數、Actions等
控制器發送SET_CONFIG消息向交換機發送配置參數
通過GET_CONFIG消息得到交換機修改后的配置信息
控制器與OpenFlow交換機之間,發送PACKET_OUT和PACKET_IN消息。通過PACKET_OUT中內置的LLDP包進行網絡拓撲的探測
控制器通過FLOW_MOD向控制器下發流表操作
斷開與對等方的連接。或者由於一些不可恢復的錯誤而斷開連接
3.裝飾器實現代碼
def set_ev_cls(ev_cls, dispatchers=None): def _set_ev_cls_dec(handler): if 'callers' not in dir(handler): handler.callers = {} for e in _listify(ev_cls): handler.callers[e] = _Caller(_listify(dispatchers), e.__module__) return handler return _set_ev_cls_dec
外部函數是用來接收事件處理函數和函數參數 內聯函數是用來
@set_ev_cls(ofp_event.EventOFPSwitchFeatures,CONFIG_DISPATCHER) def switch_features_handler(self,ev):
(四)協議解析
1.def switch_features_handler(self,ev):自定義函數參數中ev
get ev info: <ryu.controller.ofp_event.EventOFPSwitchFeatures object at 0x7f659220f668> 就是我們監聽的事件類實例
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__',
'msg', 'timestamp']
2.查看事件中的msg類信息
EVENT ofp_event->Hub EventOFPPacketIn version=0x4,
msg_type=0xa,
msg_len=0x80,
xid=0x0,
OFPPacketIn(
buffer_id=4294967295,
cookie=0,
data=b'33\xff\x9a\xd7\xb1\x1aj\xff\x9a\xd7\xb1\x86\xdd`\x00\x00\x00\x00 :\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xff\x9a\xd7\xb1\x87\x00~f\x00\x00\x00\x00\xfe\x80\x00\x00\x00\x00\x00\x00\x18j\xff\xff\xfe\x9a\xd7\xb1\x0e\x01\x1c\xddV\xff\xb4\xd8',
match=OFPMatch(oxm_fields={'in_port': 2}),
reason=0,
table_id=0,
total_len=86)
['_TYPE', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_base_attributes', '_class_prefixes', '_class_suffixes', '_decode_value', '_encode_value', '_get_decoder', '_get_default_decoder', '_get_default_encoder', '_get_encoder', '_get_type', '_is_class', '_opt_attributes', '_reserved', '_restore_args', '_serialize_body', '_serialize_header', '_serialize_pre',
'auxiliary_id', 'buf', 'capabilities', 'cls_from_jsondict_key', 'cls_msg_type', 'datapath', 'datapath_id', 'from_jsondict', 'msg_len', 'msg_type', 'n_buffers', 'n_tables', 'obj_from_jsondict', 'parser', 'serialize', 'set_buf', 'set_classes', 'set_headers', 'set_xid', 'stringify_attrs', 'to_jsondict', 'version', 'xid']
msg所提供的方法和屬性 'auxiliary_id', 'buf', 'capabilities', 'cls_from_jsondict_key', 'cls_msg_type',
'datapath', 'datapath_id',
'from_jsondict', 'msg_len', 'msg_type', 'n_buffers', 'n_tables',
'obj_from_jsondict', 'parser', 'serialize',
'set_buf', 'set_classes', 'set_headers', 'set_xid',
'stringify_attrs', 'to_jsondict', 'version', 'xid']
3.獲取邏輯設備datapath類信息
<ryu.controller.controller.Datapath object at 0x7fe1560c6048>
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_close_write', '_echo_request_loop', '_ports', '_recv_loop', '_send_loop', '_send_q_sem',
'acknowledge_echo_reply', 'address', 'close', 'echo_request_interval', 'flow_format',
'id', 'is_active', 'is_reserved_port', 'max_unreplied_echo_requests', 'ofp_brick', 'ofproto', 'ofproto_parser',
'ports', 'send',
'send_barrier', 'send_delete_all_flows', 'send_flow_del', 'send_flow_mod', 'send_msg', 'send_nxt_set_flow_format', 'send_packet_out', 'send_q',
'serve', 'set_state', 'set_version', 'set_xid', 'socket', 'state', 'supported_ofp_version', 'unreplied_echo_requests', 'xid']
4.獲取邏輯設備datapath中OpenFlow協議信息
<module 'ryu.ofproto.ofproto_v1_3' from '/usr/local/lib/python3.6/dist-packages/ryu/ofproto/ofproto_v1_3.py'>

['DESC_STR_LEN', 'DESC_STR_LEN_STR', 'MAX_XID', 'OFPAT_COPY_TTL_IN', 'OFPAT_COPY_TTL_OUT', 'OFPAT_DEC_MPLS_TTL', 'OFPAT_DEC_NW_TTL', 'OFPAT_EXPERIMENTER', 'OFPAT_GROUP', 'OFPAT_OUTPUT', 'OFPAT_POP_MPLS', 'OFPAT_POP_PBB', 'OFPAT_POP_VLAN', 'OFPAT_PUSH_MPLS', 'OFPAT_PUSH_PBB', 'OFPAT_PUSH_VLAN', 'OFPAT_SET_FIELD', 'OFPAT_SET_MPLS_TTL', 'OFPAT_SET_NW_TTL', 'OFPAT_SET_QUEUE', 'OFPBAC_BAD_ARGUMENT', 'OFPBAC_BAD_EXPERIMENTER', 'OFPBAC_BAD_EXP_TYPE', 'OFPBAC_BAD_LEN', 'OFPBAC_BAD_OUT_GROUP', 'OFPBAC_BAD_OUT_PORT', 'OFPBAC_BAD_QUEUE', 'OFPBAC_BAD_SET_ARGUMENT', 'OFPBAC_BAD_SET_LEN', 'OFPBAC_BAD_SET_TYPE', 'OFPBAC_BAD_TAG', 'OFPBAC_BAD_TYPE', 'OFPBAC_EPERM', 'OFPBAC_MATCH_INCONSISTENT', 'OFPBAC_TOO_MANY', 'OFPBAC_UNSUPPORTED_ORDER', 'OFPBIC_BAD_EXPERIMENTER', 'OFPBIC_BAD_EXP_TYPE', 'OFPBIC_BAD_LEN', 'OFPBIC_BAD_TABLE_ID', 'OFPBIC_EPERM', 'OFPBIC_UNKNOWN_INST', 'OFPBIC_UNSUP_INST', 'OFPBIC_UNSUP_METADATA', 'OFPBIC_UNSUP_METADATA_MASK', 'OFPBMC_BAD_DL_ADDR_MASK', 'OFPBMC_BAD_FIELD', 'OFPBMC_BAD_LEN', 'OFPBMC_BAD_MASK', 'OFPBMC_BAD_NW_ADDR_MASK', 'OFPBMC_BAD_PREREQ', 'OFPBMC_BAD_TAG', 'OFPBMC_BAD_TYPE', 'OFPBMC_BAD_VALUE', 'OFPBMC_BAD_WILDCARDS', 'OFPBMC_DUP_FIELD', 'OFPBMC_EPERM', 'OFPBRC_BAD_EXPERIMENTER', 'OFPBRC_BAD_EXP_TYPE', 'OFPBRC_BAD_LEN', 'OFPBRC_BAD_MULTIPART', 'OFPBRC_BAD_PACKET', 'OFPBRC_BAD_PORT', 'OFPBRC_BAD_TABLE_ID', 'OFPBRC_BAD_TYPE', 'OFPBRC_BAD_VERSION', 'OFPBRC_BUFFER_EMPTY', 'OFPBRC_BUFFER_UNKNOWN', 'OFPBRC_EPERM', 'OFPBRC_IS_SLAVE', 'OFPBRC_MULTIPART_BUFFER_OVERFLOW', 'OFPCML_MAX', 'OFPCML_NO_BUFFER', 'OFPCR_ROLE_EQUAL', 'OFPCR_ROLE_MASTER', 'OFPCR_ROLE_NOCHANGE', 'OFPCR_ROLE_SLAVE', 'OFPC_FLOW_STATS', 'OFPC_FRAG_DROP', 'OFPC_FRAG_MASK', 'OFPC_FRAG_NORMAL', 'OFPC_FRAG_REASM', 'OFPC_GROUP_STATS', 'OFPC_IP_REASM', 'OFPC_PORT_BLOCKED', 'OFPC_PORT_STATS', 'OFPC_QUEUE_STATS', 'OFPC_TABLE_STATS', 'OFPET_BAD_ACTION', 'OFPET_BAD_INSTRUCTION', 'OFPET_BAD_MATCH', 'OFPET_BAD_REQUEST', 'OFPET_EXPERIMENTER', 'OFPET_FLOW_MOD_FAILED', 'OFPET_GROUP_MOD_FAILED', 'OFPET_HELLO_FAILED', 'OFPET_METER_MOD_FAILED', 'OFPET_PORT_MOD_FAILED', 'OFPET_QUEUE_OP_FAILED', 'OFPET_ROLE_REQUEST_FAILED', 'OFPET_SWITCH_CONFIG_FAILED', 'OFPET_TABLE_FEATURES_FAILED', 'OFPET_TABLE_MOD_FAILED', 'OFPFC_ADD', 'OFPFC_DELETE', 'OFPFC_DELETE_STRICT', 'OFPFC_MODIFY', 'OFPFC_MODIFY_STRICT', 'OFPFF_CHECK_OVERLAP', 'OFPFF_NO_BYT_COUNTS', 'OFPFF_NO_PKT_COUNTS', 'OFPFF_RESET_COUNTS', 'OFPFF_SEND_FLOW_REM', 'OFPFMFC_BAD_COMMAND', 'OFPFMFC_BAD_FLAGS', 'OFPFMFC_BAD_TABLE_ID', 'OFPFMFC_BAD_TIMEOUT', 'OFPFMFC_EPERM', 'OFPFMFC_OVERLAP', 'OFPFMFC_TABLE_FULL', 'OFPFMFC_UNKNOWN', 'OFPGC_ADD', 'OFPGC_DELETE', 'OFPGC_MODIFY', 'OFPGFC_CHAINING', 'OFPGFC_CHAINING_CHECKS', 'OFPGFC_SELECT_LIVENESS', 'OFPGFC_SELECT_WEIGHT', 'OFPGMFC_BAD_BUCKET', 'OFPGMFC_BAD_COMMAND', 'OFPGMFC_BAD_TYPE', 'OFPGMFC_BAD_WATCH', 'OFPGMFC_CHAINED_GROUP', 'OFPGMFC_CHAINING_UNSUPPORTED', 'OFPGMFC_EPERM', 'OFPGMFC_GROUP_EXISTS', 'OFPGMFC_INVALID_GROUP', 'OFPGMFC_LOOP', 'OFPGMFC_OUT_OF_BUCKETS', 'OFPGMFC_OUT_OF_GROUPS', 'OFPGMFC_UNKNOWN_GROUP', 'OFPGMFC_WATCH_UNSUPPORTED', 'OFPGMFC_WEIGHT_UNSUPPORTED', 'OFPGT_ALL', 'OFPGT_FF', 'OFPGT_INDIRECT', 'OFPGT_SELECT', 'OFPG_ALL', 'OFPG_ANY', 'OFPG_MAX', 'OFPHET_VERSIONBITMAP', 'OFPHFC_EPERM', 'OFPHFC_INCOMPATIBLE', 'OFPIEH_AUTH', 'OFPIEH_DEST', 'OFPIEH_ESP', 'OFPIEH_FRAG', 'OFPIEH_HOP', 'OFPIEH_NONEXT', 'OFPIEH_ROUTER', 'OFPIEH_UNREP', 'OFPIEH_UNSEQ', 'OFPIT_APPLY_ACTIONS', 'OFPIT_CLEAR_ACTIONS', 'OFPIT_EXPERIMENTER', 'OFPIT_GOTO_TABLE', 'OFPIT_METER', 'OFPIT_WRITE_ACTIONS', 'OFPIT_WRITE_METADATA', 'OFPMBT_DROP', 'OFPMBT_DSCP_REMARK', 'OFPMBT_EXPERIMENTER', 'OFPMC_ADD', 'OFPMC_DELETE', 'OFPMC_MODIFY', 'OFPMF_BURST', 'OFPMF_KBPS', 'OFPMF_PKTPS', 'OFPMF_STATS', 'OFPMMFC_BAD_BAND', 'OFPMMFC_BAD_BAND_VALUE', 'OFPMMFC_BAD_BURST', 'OFPMMFC_BAD_COMMAND', 'OFPMMFC_BAD_FLAGS', 'OFPMMFC_BAD_RATE', 'OFPMMFC_INVALID_METER', 'OFPMMFC_METER_EXISTS', 'OFPMMFC_OUT_OF_BANDS', 'OFPMMFC_OUT_OF_METERS', 'OFPMMFC_UNKNOWN', 'OFPMMFC_UNKNOWN_METER', 'OFPMPF_REPLY_MORE', 'OFPMPF_REQ_MORE', 'OFPMP_AGGREGATE', 'OFPMP_DESC', 'OFPMP_EXPERIMENTER', 'OFPMP_FLOW', 'OFPMP_GROUP', 'OFPMP_GROUP_DESC', 'OFPMP_GROUP_FEATURES', 'OFPMP_METER', 'OFPMP_METER_CONFIG', 'OFPMP_METER_FEATURES', 'OFPMP_PORT_DESC', 'OFPMP_PORT_STATS', 'OFPMP_QUEUE', 'OFPMP_TABLE', 'OFPMP_TABLE_FEATURES', 'OFPMT_OXM', 'OFPMT_STANDARD', 'OFPM_ALL', 'OFPM_CONTROLLER', 'OFPM_MAX', 'OFPM_SLOWPATH', 'OFPPC_NO_FWD', 'OFPPC_NO_PACKET_IN', 'OFPPC_NO_RECV', 'OFPPC_PORT_DOWN', 'OFPPF_100GB_FD', 'OFPPF_100MB_FD', 'OFPPF_100MB_HD', 'OFPPF_10GB_FD', 'OFPPF_10MB_FD', 'OFPPF_10MB_HD', 'OFPPF_1GB_FD', 'OFPPF_1GB_HD', 'OFPPF_1TB_FD', 'OFPPF_40GB_FD', 'OFPPF_AUTONEG', 'OFPPF_COPPER', 'OFPPF_FIBER', 'OFPPF_OTHER', 'OFPPF_PAUSE', 'OFPPF_PAUSE_ASYM', 'OFPPMFC_BAD_ADVERTISE', 'OFPPMFC_BAD_CONFIG', 'OFPPMFC_BAD_HW_ADDR', 'OFPPMFC_BAD_PORT', 'OFPPMFC_EPERM', 'OFPPR_ADD', 'OFPPR_DELETE', 'OFPPR_MODIFY', 'OFPPS_BLOCKED', 'OFPPS_LINK_DOWN', 'OFPPS_LIVE', 'OFPP_ALL', 'OFPP_ANY', 'OFPP_CONTROLLER', 'OFPP_FLOOD', 'OFPP_IN_PORT', 'OFPP_LOCAL', 'OFPP_MAX', 'OFPP_NORMAL', 'OFPP_TABLE', 'OFPQCFC_EPERM', 'OFPQOFC_BAD_PORT', 'OFPQOFC_BAD_QUEUE', 'OFPQOFC_EPERM', 'OFPQT_EXPERIMENTER', 'OFPQT_MAX_RATE', 'OFPQT_MIN_RATE', 'OFPQ_ALL', 'OFPRRFC_BAD_ROLE', 'OFPRRFC_STALE', 'OFPRRFC_UNSUP', 'OFPRR_DELETE', 'OFPRR_GROUP_DELETE', 'OFPRR_HARD_TIMEOUT', 'OFPRR_IDLE_TIMEOUT', 'OFPR_ACTION', 'OFPR_INVALID_TTL', 'OFPR_NO_MATCH', 'OFPSCFC_BAD_FLAGS', 'OFPSCFC_BAD_LEN', 'OFPSCFC_EPERM', 'OFPTFFC_BAD_ARGUMENT', 'OFPTFFC_BAD_LEN', 'OFPTFFC_BAD_METADATA', 'OFPTFFC_BAD_TABLE', 'OFPTFFC_BAD_TYPE', 'OFPTFFC_EPERM', 'OFPTFPT_APPLY_ACTIONS', 'OFPTFPT_APPLY_ACTIONS_MISS', 'OFPTFPT_APPLY_SETFIELD', 'OFPTFPT_APPLY_SETFIELD_MISS', 'OFPTFPT_EXPERIMENTER', 'OFPTFPT_EXPERIMENTER_MISS', 'OFPTFPT_INSTRUCTIONS', 'OFPTFPT_INSTRUCTIONS_MISS', 'OFPTFPT_MATCH', 'OFPTFPT_NEXT_TABLES', 'OFPTFPT_NEXT_TABLES_MISS', 'OFPTFPT_WILDCARDS', 'OFPTFPT_WRITE_ACTIONS', 'OFPTFPT_WRITE_ACTIONS_MISS', 'OFPTFPT_WRITE_SETFIELD', 'OFPTFPT_WRITE_SETFIELD_MISS', 'OFPTMFC_BAD_CONFIG', 'OFPTMFC_BAD_TABLE', 'OFPTMFC_EPERM', 'OFPTT_ALL', 'OFPTT_MAX', 'OFPT_BARRIER_REPLY', 'OFPT_BARRIER_REQUEST', 'OFPT_ECHO_REPLY', 'OFPT_ECHO_REQUEST', 'OFPT_ERROR', 'OFPT_EXPERIMENTER', 'OFPT_FEATURES_REPLY', 'OFPT_FEATURES_REQUEST', 'OFPT_FLOW_MOD', 'OFPT_FLOW_REMOVED', 'OFPT_GET_ASYNC_REPLY', 'OFPT_GET_ASYNC_REQUEST', 'OFPT_GET_CONFIG_REPLY', 'OFPT_GET_CONFIG_REQUEST', 'OFPT_GROUP_MOD', 'OFPT_HELLO', 'OFPT_METER_MOD', 'OFPT_MULTIPART_REPLY', 'OFPT_MULTIPART_REQUEST', 'OFPT_PACKET_IN', 'OFPT_PACKET_OUT', 'OFPT_PORT_MOD', 'OFPT_PORT_STATUS', 'OFPT_QUEUE_GET_CONFIG_REPLY', 'OFPT_QUEUE_GET_CONFIG_REQUEST', 'OFPT_ROLE_REPLY', 'OFPT_ROLE_REQUEST', 'OFPT_SET_ASYNC', 'OFPT_SET_CONFIG', 'OFPT_TABLE_MOD', 'OFPVID_NONE', 'OFPVID_PRESENT', 'OFPXMC_EXPERIMENTER', 'OFPXMC_NXM_0', 'OFPXMC_NXM_1', 'OFPXMC_OPENFLOW_BASIC', 'OFPXMT_OFB_ARP_OP', 'OFPXMT_OFB_ARP_SHA', 'OFPXMT_OFB_ARP_SPA', 'OFPXMT_OFB_ARP_THA', 'OFPXMT_OFB_ARP_TPA', 'OFPXMT_OFB_ETH_DST', 'OFPXMT_OFB_ETH_SRC', 'OFPXMT_OFB_ETH_TYPE', 'OFPXMT_OFB_ICMPV4_CODE', 'OFPXMT_OFB_ICMPV4_TYPE', 'OFPXMT_OFB_ICMPV6_CODE', 'OFPXMT_OFB_ICMPV6_TYPE', 'OFPXMT_OFB_IN_PHY_PORT', 'OFPXMT_OFB_IN_PORT', 'OFPXMT_OFB_IPV4_DST', 'OFPXMT_OFB_IPV4_SRC', 'OFPXMT_OFB_IPV6_DST', 'OFPXMT_OFB_IPV6_EXTHDR', 'OFPXMT_OFB_IPV6_FLABEL', 'OFPXMT_OFB_IPV6_ND_SLL', 'OFPXMT_OFB_IPV6_ND_TARGET', 'OFPXMT_OFB_IPV6_ND_TLL', 'OFPXMT_OFB_IPV6_SRC', 'OFPXMT_OFB_IP_DSCP', 'OFPXMT_OFB_IP_ECN', 'OFPXMT_OFB_IP_PROTO', 'OFPXMT_OFB_METADATA', 'OFPXMT_OFB_MPLS_BOS', 'OFPXMT_OFB_MPLS_LABEL', 'OFPXMT_OFB_MPLS_TC', 'OFPXMT_OFB_PBB_ISID', 'OFPXMT_OFB_SCTP_DST', 'OFPXMT_OFB_SCTP_SRC', 'OFPXMT_OFB_TCP_DST', 'OFPXMT_OFB_TCP_SRC', 'OFPXMT_OFB_TUNNEL_ID', 'OFPXMT_OFB_UDP_DST', 'OFPXMT_OFB_UDP_SRC', 'OFPXMT_OFB_VLAN_PCP', 'OFPXMT_OFB_VLAN_VID', 'OFP_ACTION_EXPERIMENTER_HEADER_PACK_STR', 'OFP_ACTION_EXPERIMENTER_HEADER_SIZE', 'OFP_ACTION_GROUP_PACK_STR', 'OFP_ACTION_GROUP_SIZE', 'OFP_ACTION_HEADER_PACK_STR', 'OFP_ACTION_HEADER_SIZE', 'OFP_ACTION_MPLS_TTL_PACK_STR', 'OFP_ACTION_MPLS_TTL_SIZE', 'OFP_ACTION_NW_TTL_PACK_STR', 'OFP_ACTION_NW_TTL_SIZE', 'OFP_ACTION_OUTPUT_PACK_STR', 'OFP_ACTION_OUTPUT_SIZE', 'OFP_ACTION_POP_MPLS_PACK_STR', 'OFP_ACTION_POP_MPLS_SIZE', 'OFP_ACTION_PUSH_PACK_STR', 'OFP_ACTION_PUSH_SIZE', 'OFP_ACTION_SET_FIELD_PACK_STR', 'OFP_ACTION_SET_FIELD_SIZE', 'OFP_ACTION_SET_QUEUE_PACK_STR', 'OFP_ACTION_SET_QUEUE_SIZE', 'OFP_AGGREGATE_STATS_REPLY_PACK_STR', 'OFP_AGGREGATE_STATS_REPLY_SIZE', 'OFP_AGGREGATE_STATS_REQUEST_0_PACK_STR', 'OFP_AGGREGATE_STATS_REQUEST_0_SIZE', 'OFP_AGGREGATE_STATS_REQUEST_PACK_STR', 'OFP_AGGREGATE_STATS_REQUEST_SIZE', 'OFP_ASYNC_CONFIG_PACK_STR', 'OFP_ASYNC_CONFIG_SIZE', 'OFP_BUCKET_COUNTER_PACK_STR', 'OFP_BUCKET_COUNTER_SIZE', 'OFP_BUCKET_PACK_STR', 'OFP_BUCKET_SIZE', 'OFP_DEFAULT_PRIORITY', 'OFP_DESC_PACK_STR', 'OFP_DESC_SIZE', 'OFP_ERROR_EXPERIMENTER_MSG_PACK_STR', 'OFP_ERROR_EXPERIMENTER_MSG_SIZE', 'OFP_ERROR_MSG_PACK_STR', 'OFP_ERROR_MSG_SIZE', 'OFP_ETH_ALEN', 'OFP_ETH_ALEN_STR', 'OFP_EXPERIMENTER_HEADER_PACK_STR', 'OFP_EXPERIMENTER_HEADER_SIZE', 'OFP_EXPERIMENTER_MULTIPART_HEADER_PACK_STR', 'OFP_EXPERIMENTER_MULTIPART_HEADER_SIZE', 'OFP_FLOW_MOD_PACK_STR', 'OFP_FLOW_MOD_PACK_STR0', 'OFP_FLOW_MOD_SIZE', 'OFP_FLOW_REMOVED_PACK_STR', 'OFP_FLOW_REMOVED_PACK_STR0', 'OFP_FLOW_REMOVED_SIZE', 'OFP_FLOW_STATS_0_PACK_STR', 'OFP_FLOW_STATS_0_SIZE', 'OFP_FLOW_STATS_PACK_STR', 'OFP_FLOW_STATS_REQUEST_0_PACK_STR', 'OFP_FLOW_STATS_REQUEST_0_SIZE', 'OFP_FLOW_STATS_REQUEST_PACK_STR', 'OFP_FLOW_STATS_REQUEST_SIZE', 'OFP_FLOW_STATS_SIZE', 'OFP_GROUP_DESC_PACK_STR', 'OFP_GROUP_DESC_SIZE', 'OFP_GROUP_DESC_STATS_PACK_STR', 'OFP_GROUP_DESC_STATS_SIZE', 'OFP_GROUP_FEATURES_PACK_STR', 'OFP_GROUP_FEATURES_SIZE', 'OFP_GROUP_MOD_PACK_STR', 'OFP_GROUP_MOD_SIZE', 'OFP_GROUP_STATS_PACK_STR', 'OFP_GROUP_STATS_REQUEST_PACK_STR', 'OFP_GROUP_STATS_REQUEST_SIZE', 'OFP_GROUP_STATS_SIZE', 'OFP_HEADER_PACK_STR', 'OFP_HEADER_SIZE', 'OFP_HELLO_ELEM_HEADER_PACK_STR', 'OFP_HELLO_ELEM_HEADER_SIZE', 'OFP_HELLO_ELEM_VERSIONBITMAP_HEADER_PACK_STR', 'OFP_HELLO_ELEM_VERSIONBITMAP_HEADER_SIZE', 'OFP_HELLO_HEADER_SIZE', 'OFP_INSTRUCTION_ACTIONS_PACK_STR', 'OFP_INSTRUCTION_ACTIONS_SIZE', 'OFP_INSTRUCTION_GOTO_TABLE_PACK_STR', 'OFP_INSTRUCTION_GOTO_TABLE_SIZE', 'OFP_INSTRUCTION_METER_PACK_STR', 'OFP_INSTRUCTION_METER_SIZE', 'OFP_INSTRUCTION_WRITE_METADATA_PACK_STR', 'OFP_INSTRUCTION_WRITE_METADATA_SIZE', 'OFP_MATCH_PACK_STR', 'OFP_MATCH_SIZE', 'OFP_MAX_PORT_NAME_LEN', 'OFP_MAX_TABLE_NAME_LEN', 'OFP_MAX_TABLE_NAME_LEN_STR', 'OFP_METER_BAND_DROP_PACK_STR', 'OFP_METER_BAND_DROP_SIZE', 'OFP_METER_BAND_DSCP_REMARK_PACK_STR', 'OFP_METER_BAND_DSCP_REMARK_SIZE', 'OFP_METER_BAND_EXPERIMENTER_PACK_STR', 'OFP_METER_BAND_EXPERIMENTER_SIZE', 'OFP_METER_BAND_HEADER_PACK_STR', 'OFP_METER_BAND_HEADER_SIZE', 'OFP_METER_BAND_STATS_PACK_STR', 'OFP_METER_BAND_STATS_SIZE', 'OFP_METER_CONFIG_PACK_STR', 'OFP_METER_CONFIG_SIZE', 'OFP_METER_FEATURES_PACK_STR', 'OFP_METER_FEATURES_SIZE', 'OFP_METER_MOD_PACK_STR', 'OFP_METER_MOD_SIZE', 'OFP_METER_MULTIPART_REQUEST_PACK_STR', 'OFP_METER_MULTIPART_REQUEST_SIZE', 'OFP_METER_STATS_PACK_STR', 'OFP_METER_STATS_SIZE', 'OFP_MULTIPART_REPLY_PACK_STR', 'OFP_MULTIPART_REPLY_SIZE', 'OFP_MULTIPART_REQUEST_PACK_STR', 'OFP_MULTIPART_REQUEST_SIZE', 'OFP_NO_BUFFER', 'OFP_OXM_EXPERIMENTER_HEADER_PACK_STR', 'OFP_OXM_EXPERIMENTER_HEADER_SIZE', 'OFP_PACKET_IN_PACK_STR', 'OFP_PACKET_IN_SIZE', 'OFP_PACKET_OUT_PACK_STR', 'OFP_PACKET_OUT_SIZE', 'OFP_PACKET_QUEUE_PACK_STR', 'OFP_PACKET_QUEUE_SIZE', 'OFP_PORT_MOD_PACK_STR', 'OFP_PORT_MOD_SIZE', 'OFP_PORT_PACK_STR', 'OFP_PORT_SIZE', 'OFP_PORT_STATS_PACK_STR', 'OFP_PORT_STATS_REQUEST_PACK_STR', 'OFP_PORT_STATS_REQUEST_SIZE', 'OFP_PORT_STATS_SIZE', 'OFP_PORT_STATUS_DESC_OFFSET', 'OFP_PORT_STATUS_PACK_STR', 'OFP_PORT_STATUS_SIZE', 'OFP_PROP_EXPERIMENTER_PACK_STR', 'OFP_PROP_EXPERIMENTER_SIZE', 'OFP_QUEUE_GET_CONFIG_REPLY_PACK_STR', 'OFP_QUEUE_GET_CONFIG_REPLY_SIZE', 'OFP_QUEUE_GET_CONFIG_REQUEST_PACK_STR', 'OFP_QUEUE_GET_CONFIG_REQUEST_SIZE', 'OFP_QUEUE_PROP_EXPERIMENTER_PACK_STR', 'OFP_QUEUE_PROP_EXPERIMENTER_SIZE', 'OFP_QUEUE_PROP_HEADER_PACK_STR', 'OFP_QUEUE_PROP_HEADER_SIZE', 'OFP_QUEUE_PROP_MAX_RATE_PACK_STR', 'OFP_QUEUE_PROP_MAX_RATE_SIZE', 'OFP_QUEUE_PROP_MIN_RATE_PACK_STR', 'OFP_QUEUE_PROP_MIN_RATE_SIZE', 'OFP_QUEUE_STATS_PACK_STR', 'OFP_QUEUE_STATS_REQUEST_PACK_STR', 'OFP_QUEUE_STATS_REQUEST_SIZE', 'OFP_QUEUE_STATS_SIZE', 'OFP_ROLE_REQUEST_PACK_STR', 'OFP_ROLE_REQUEST_SIZE', 'OFP_SWITCH_CONFIG_PACK_STR', 'OFP_SWITCH_CONFIG_SIZE', 'OFP_SWITCH_FEATURES_PACK_STR', 'OFP_SWITCH_FEATURES_SIZE', 'OFP_TABLE_FEATURES_PACK_STR', 'OFP_TABLE_FEATURES_SIZE', 'OFP_TABLE_FEATURE_PROP_ACTIONS_PACK_STR', 'OFP_TABLE_FEATURE_PROP_ACTIONS_SIZE', 'OFP_TABLE_FEATURE_PROP_INSTRUCTIONS_PACK_STR', 'OFP_TABLE_FEATURE_PROP_INSTRUCTIONS_SIZE', 'OFP_TABLE_FEATURE_PROP_NEXT_TABLES_PACK_STR', 'OFP_TABLE_FEATURE_PROP_NEXT_TABLES_SIZE', 'OFP_TABLE_FEATURE_PROP_OXM_PACK_STR', 'OFP_TABLE_FEATURE_PROP_OXM_SIZE', 'OFP_TABLE_MOD_PACK_STR', 'OFP_TABLE_MOD_SIZE', 'OFP_TABLE_STATS_PACK_STR', 'OFP_TABLE_STATS_SIZE', 'OFP_TCP_PORT', 'OFP_VERSION', 'ONFERR_DUP_INSTRUCTION', 'ONFERR_ET_ASYNC_EPERM', 'ONFERR_ET_ASYNC_INVALUD', 'ONFERR_ET_ASYNC_UNSUPPORTED', 'ONFERR_ET_BAD_FLAGS', 'ONFERR_ET_BAD_ID', 'ONFERR_ET_BAD_PRIORITY', 'ONFERR_ET_BAD_TYPE', 'ONFERR_ET_BUNDLE_CLOSED', 'ONFERR_ET_BUNDLE_EXIST', 'ONFERR_ET_BUNDLE_IN_PROGRESS', 'ONFERR_ET_CANT_SYNC', 'ONFERR_ET_EPERM', 'ONFERR_ET_FAILED', 'ONFERR_ET_MPART_REPLY_TIMEOUT', 'ONFERR_ET_MPART_REQUEST_TIMEOUT', 'ONFERR_ET_MSG_BAD_LEN', 'ONFERR_ET_MSG_BAD_XID', 'ONFERR_ET_MSG_CONFLICT', 'ONFERR_ET_MSG_TOO_MANY', 'ONFERR_ET_MSG_UNSUP', 'ONFERR_ET_OUT_OF_BUNDLES', 'ONFERR_ET_TIMEOUT', 'ONFERR_ET_UNKNOWN', 'ONFFME_ABBREV', 'ONFFME_ADDED', 'ONFFME_DELETED', 'ONFFME_MODIFIED', 'ONFFMF_ACTIONS', 'ONFFMF_ADD', 'ONFFMF_DELETE', 'ONFFMF_INITIAL', 'ONFFMF_MODIFY', 'ONFFMF_OWN', 'ONFMP_FLOW_MONITOR', 'ONFT_FLOW_MONITOR_CANCEL', 'ONFT_FLOW_MONITOR_PAUSED', 'ONFT_FLOW_MONITOR_RESUMED', 'ONF_BCT_CLOSE_REPLY', 'ONF_BCT_CLOSE_REQUEST', 'ONF_BCT_COMMIT_REPLY', 'ONF_BCT_COMMIT_REQUEST', 'ONF_BCT_DISCARD_REPLY', 'ONF_BCT_DISCARD_REQUEST', 'ONF_BCT_OPEN_REPLY', 'ONF_BCT_OPEN_REQUEST', 'ONF_BF_ATOMIC', 'ONF_BF_ORDERED', 'ONF_BUNDLE_ADD_MSG_PACK_STR', 'ONF_BUNDLE_ADD_MSG_SIZE', 'ONF_BUNDLE_CTRL_PACK_STR', 'ONF_BUNDLE_CTRL_SIZE', 'ONF_ET_BPT_EXPERIMENTER', 'ONF_ET_BUNDLE_ADD_MESSAGE', 'ONF_ET_BUNDLE_CONTROL', 'ONF_FLOW_MONITOR_REQUEST_PACK_STR', 'ONF_FLOW_MONITOR_REQUEST_SIZE', 'ONF_FLOW_UPDATE_ABBREV_PACK_STR', 'ONF_FLOW_UPDATE_ABBREV_SIZE', 'ONF_FLOW_UPDATE_FULL_PACK_STR', 'ONF_FLOW_UPDATE_FULL_SIZE', 'ONF_FLOW_UPDATE_HEADER_PACK_STR', 'ONF_FLOW_UPDATE_HEADER_SIZE', 'OXM_OF_ARP_OP', 'OXM_OF_ARP_OP_W', 'OXM_OF_ARP_SHA', 'OXM_OF_ARP_SHA_W', 'OXM_OF_ARP_SPA', 'OXM_OF_ARP_SPA_W', 'OXM_OF_ARP_THA', 'OXM_OF_ARP_THA_W', 'OXM_OF_ARP_TPA', 'OXM_OF_ARP_TPA_W', 'OXM_OF_ETH_DST', 'OXM_OF_ETH_DST_W', 'OXM_OF_ETH_SRC', 'OXM_OF_ETH_SRC_W', 'OXM_OF_ETH_TYPE', 'OXM_OF_ETH_TYPE_W', 'OXM_OF_ICMPV4_CODE', 'OXM_OF_ICMPV4_CODE_W', 'OXM_OF_ICMPV4_TYPE', 'OXM_OF_ICMPV4_TYPE_W', 'OXM_OF_ICMPV6_CODE', 'OXM_OF_ICMPV6_CODE_W', 'OXM_OF_ICMPV6_TYPE', 'OXM_OF_ICMPV6_TYPE_W', 'OXM_OF_IN_PHY_PORT', 'OXM_OF_IN_PHY_PORT_W', 'OXM_OF_IN_PORT', 'OXM_OF_IN_PORT_W', 'OXM_OF_IPV4_DST', 'OXM_OF_IPV4_DST_W', 'OXM_OF_IPV4_SRC', 'OXM_OF_IPV4_SRC_W', 'OXM_OF_IPV6_DST', 'OXM_OF_IPV6_DST_W', 'OXM_OF_IPV6_EXTHDR', 'OXM_OF_IPV6_EXTHDR_W', 'OXM_OF_IPV6_FLABEL', 'OXM_OF_IPV6_FLABEL_W', 'OXM_OF_IPV6_ND_SLL', 'OXM_OF_IPV6_ND_SLL_W', 'OXM_OF_IPV6_ND_TARGET', 'OXM_OF_IPV6_ND_TARGET_W', 'OXM_OF_IPV6_ND_TLL', 'OXM_OF_IPV6_ND_TLL_W', 'OXM_OF_IPV6_SRC', 'OXM_OF_IPV6_SRC_W', 'OXM_OF_IP_DSCP', 'OXM_OF_IP_DSCP_W', 'OXM_OF_IP_ECN', 'OXM_OF_IP_ECN_W', 'OXM_OF_IP_PROTO', 'OXM_OF_IP_PROTO_W', 'OXM_OF_METADATA', 'OXM_OF_METADATA_W', 'OXM_OF_MPLS_BOS', 'OXM_OF_MPLS_BOS_W', 'OXM_OF_MPLS_LABEL', 'OXM_OF_MPLS_LABEL_W', 'OXM_OF_MPLS_TC', 'OXM_OF_MPLS_TC_W', 'OXM_OF_PBB_ISID', 'OXM_OF_PBB_ISID_W', 'OXM_OF_SCTP_DST', 'OXM_OF_SCTP_DST_W', 'OXM_OF_SCTP_SRC', 'OXM_OF_SCTP_SRC_W', 'OXM_OF_TCP_DST', 'OXM_OF_TCP_DST_W', 'OXM_OF_TCP_SRC', 'OXM_OF_TCP_SRC_W', 'OXM_OF_TUNNEL_ID', 'OXM_OF_TUNNEL_ID_W', 'OXM_OF_UDP_DST', 'OXM_OF_UDP_DST_W', 'OXM_OF_UDP_SRC', 'OXM_OF_UDP_SRC_W', 'OXM_OF_VLAN_PCP', 'OXM_OF_VLAN_PCP_W', 'OXM_OF_VLAN_VID', 'OXM_OF_VLAN_VID_W', 'SERIAL_NUM_LEN', 'SERIAL_NUM_LEN_STR', '_OFP_AGGREGATE_STATS_REQUEST_0_PACK_STR', '_OFP_FLOW_MOD_PACK_STR0', '_OFP_FLOW_REMOVED_PACK_STR0', '_OFP_FLOW_STATS_0_PACK_STR', '_OFP_FLOW_STATS_REQUEST_0_PACK_STR', '_OFP_MATCH_PACK_STR', '_OFP_PORT_PACK_STR', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', '_oxm_field_desc', '_oxm_tlv_header', 'calcsize', 'nicira_ext', 'ofp_error_code_to_str', 'ofp_error_to_jsondict', 'ofp_error_type_to_str', 'ofp_msg_type_to_str', 'ofproto_utils', 'oxm_fields', 'oxm_from_jsondict', 'oxm_from_user', 'oxm_from_user_header', 'oxm_get_field_info_by_name', 'oxm_normalize_user', 'oxm_parse', 'oxm_parse_header', 'oxm_serialize', 'oxm_serialize_header', 'oxm_tlv_header', 'oxm_tlv_header_extract_hasmask', 'oxm_tlv_header_extract_length', 'oxm_tlv_header_w', 'oxm_to_jsondict', 'oxm_to_user', 'oxm_to_user_header', 'oxm_types', 'type_desc']
5.獲取邏輯設備datapath中OpenFlow協議解析信息
<module 'ryu.ofproto.ofproto_v1_3_parser' from '/usr/local/lib/python3.6/dist-packages/ryu/ofproto/ofproto_v1_3_parser.py'>

['Flow', 'FlowWildcards', 'LOG', 'MTArpOp', 'MTArpSha', 'MTArpSpa', 'MTArpTha', 'MTArpTpa', 'MTEthDst', 'MTEthSrc', 'MTEthType', 'MTICMPV4Code', 'MTICMPV4Type', 'MTICMPV6Code', 'MTICMPV6Type', 'MTIPDscp', 'MTIPECN', 'MTIPProto', 'MTIPV4Dst', 'MTIPV4Src', 'MTIPv6', 'MTIPv6Dst', 'MTIPv6ExtHdr', 'MTIPv6Flabel', 'MTIPv6NdSll', 'MTIPv6NdTarget', 'MTIPv6NdTll', 'MTIPv6Src', 'MTInPhyPort', 'MTInPort', 'MTMetadata', 'MTMplsBos', 'MTMplsLabel', 'MTMplsTc', 'MTPbbIsid', 'MTSCTPDst', 'MTSCTPSrc', 'MTTCPDst', 'MTTCPSrc', 'MTTunnelId', 'MTUDPDst', 'MTUDPSrc', 'MTVlanPcp', 'MTVlanVid', 'MsgBase', 'NXAction', 'NXActionBundle', 'NXActionBundleLoad', 'NXActionCT', 'NXActionCTClear', 'NXActionConjunction', 'NXActionController', 'NXActionController2', 'NXActionDecMplsTtl', 'NXActionDecNshTtl', 'NXActionDecTtl', 'NXActionDecTtlCntIds', 'NXActionEncapEther', 'NXActionEncapNsh', 'NXActionExit', 'NXActionFinTimeout', 'NXActionLearn', 'NXActionMultipath', 'NXActionNAT', 'NXActionNote', 'NXActionOutputReg', 'NXActionOutputReg2', 'NXActionOutputTrunc', 'NXActionPopMpls', 'NXActionPopQueue', 'NXActionPushMpls', 'NXActionRegLoad', 'NXActionRegLoad2', 'NXActionRegMove', 'NXActionResubmit', 'NXActionResubmitTable', 'NXActionSample', 'NXActionSample2', 'NXActionSetMplsLabel', 'NXActionSetMplsTc', 'NXActionSetMplsTtl', 'NXActionSetQueue', 'NXActionSetTunnel', 'NXActionSetTunnel64', 'NXActionStackPop', 'NXActionStackPush', 'NXActionUnknown', 'NXFlowSpecLoad', 'NXFlowSpecMatch', 'NXFlowSpecOutput', 'OFPAction', 'OFPActionCopyTtlIn', 'OFPActionCopyTtlOut', 'OFPActionDecMplsTtl', 'OFPActionDecNwTtl', 'OFPActionExperimenter', 'OFPActionExperimenterUnknown', 'OFPActionGroup', 'OFPActionHeader', 'OFPActionId', 'OFPActionOutput', 'OFPActionPopMpls', 'OFPActionPopPbb', 'OFPActionPopVlan', 'OFPActionPushMpls', 'OFPActionPushPbb', 'OFPActionPushVlan', 'OFPActionSetField', 'OFPActionSetMplsTtl', 'OFPActionSetNwTtl', 'OFPActionSetQueue', 'OFPAggregateStats', 'OFPAggregateStatsReply', 'OFPAggregateStatsRequest', 'OFPBarrierReply', 'OFPBarrierRequest', 'OFPBucket', 'OFPBucketCounter', 'OFPDescStats', 'OFPDescStatsReply', 'OFPDescStatsRequest', 'OFPEchoReply', 'OFPEchoRequest', 'OFPErrorExperimenterMsg', 'OFPErrorMsg', 'OFPExperimenter', 'OFPExperimenterMultipart', 'OFPExperimenterOxmId', 'OFPExperimenterStatsReply', 'OFPExperimenterStatsRequest', 'OFPExperimenterStatsRequestBase', 'OFPFeaturesRequest', 'OFPFlowMod', 'OFPFlowRemoved', 'OFPFlowStats', 'OFPFlowStatsReply', 'OFPFlowStatsRequest', 'OFPFlowStatsRequestBase', 'OFPGetAsyncReply', 'OFPGetAsyncRequest', 'OFPGetConfigReply', 'OFPGetConfigRequest', 'OFPGroupDescStats', 'OFPGroupDescStatsReply', 'OFPGroupDescStatsRequest', 'OFPGroupFeaturesStats', 'OFPGroupFeaturesStatsReply', 'OFPGroupFeaturesStatsRequest', 'OFPGroupMod', 'OFPGroupStats', 'OFPGroupStatsReply', 'OFPGroupStatsRequest', 'OFPHello', 'OFPHelloElemVersionBitmap', 'OFPInstruction', 'OFPInstructionActions', 'OFPInstructionGotoTable', 'OFPInstructionId', 'OFPInstructionMeter', 'OFPInstructionWriteMetadata', 'OFPMatch', 'OFPMatchField', 'OFPMeterBand', 'OFPMeterBandDrop', 'OFPMeterBandDscpRemark', 'OFPMeterBandExperimenter', 'OFPMeterBandHeader', 'OFPMeterBandStats', 'OFPMeterConfigStats', 'OFPMeterConfigStatsReply', 'OFPMeterConfigStatsRequest', 'OFPMeterFeaturesStats', 'OFPMeterFeaturesStatsReply', 'OFPMeterFeaturesStatsRequest', 'OFPMeterMod', 'OFPMeterStats', 'OFPMeterStatsReply', 'OFPMeterStatsRequest', 'OFPMultipartReply', 'OFPMultipartRequest', 'OFPOxmId', 'OFPPacketIn', 'OFPPacketOut', 'OFPPacketQueue', 'OFPPort', 'OFPPortDescStatsReply', 'OFPPortDescStatsRequest', 'OFPPortMod', 'OFPPortStats', 'OFPPortStatsReply', 'OFPPortStatsRequest', 'OFPPortStatus', 'OFPPropBase', 'OFPPropCommonExperimenter4ByteData', 'OFPPropUnknown', 'OFPQueueGetConfigReply', 'OFPQueueGetConfigRequest', 'OFPQueueProp', 'OFPQueuePropExperimenter', 'OFPQueuePropHeader', 'OFPQueuePropMaxRate', 'OFPQueuePropMinRate', 'OFPQueueStats', 'OFPQueueStatsReply', 'OFPQueueStatsRequest', 'OFPRoleReply', 'OFPRoleRequest', 'OFPSetAsync', 'OFPSetConfig', 'OFPSwitchFeatures', 'OFPTableFeatureProp', 'OFPTableFeaturePropActions', 'OFPTableFeaturePropExperimenter', 'OFPTableFeaturePropInstructions', 'OFPTableFeaturePropNextTables', 'OFPTableFeaturePropOxm', 'OFPTableFeaturePropUnknown', 'OFPTableFeaturesStats', 'OFPTableFeaturesStatsReply', 'OFPTableFeaturesStatsRequest', 'OFPTableMod', 'OFPTableStats', 'OFPTableStatsReply', 'OFPTableStatsRequest', 'ONFBundleAddMsg', 'ONFBundleCtrlMsg', 'ONFFlowMonitorRequest', 'ONFFlowMonitorStatsRequest', 'StringifyMixin', 'UINT16_MAX', 'UINT32_MAX', 'UINT64_MAX', '_MSG_PARSERS', '_NXFlowSpec', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', '_register_exp_type', '_register_parser', '_set_msg_type', '_set_stats_type', 'addrconv', 'base64', 'ether', 'exception', 'logging', 'mac', 'msg_pack_into', 'msg_parser', 'nx_actions', 'ofproto', 'ofproto_common', 'ofproto_parser', 'packet', 'six', 'struct', 'utils']
https://blog.csdn.net/Neo233/article/details/79933849
5.通過ofp_parser中獲取match類匹配
OFPMatch(oxm_fields={})

['_TYPE', '__class__', '__contains__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_base_attributes', '_class_prefixes', '_class_suffixes', '_composed_with_old_api', '_decode_value', '_encode_value', '_fields2', '_flow', '_get_decoder', '_get_default_decoder', '_get_default_encoder', '_get_encoder', '_get_type', '_is_class', '_opt_attributes', '_restore_args', '_wc', 'append_field', 'cls_from_jsondict_key', 'fields', 'from_jsondict', 'get', 'items', 'iteritems', 'length', 'obj_from_jsondict', 'parser', 'parser_old', 'serialize', 'serialize_old', 'set_arp_opcode', 'set_arp_sha', 'set_arp_sha_masked', 'set_arp_spa', 'set_arp_spa_masked', 'set_arp_tha', 'set_arp_tha_masked', 'set_arp_tpa', 'set_arp_tpa_masked', 'set_classes', 'set_dl_dst', 'set_dl_dst_masked', 'set_dl_src', 'set_dl_src_masked', 'set_dl_type', 'set_icmpv4_code', 'set_icmpv4_type', 'set_icmpv6_code', 'set_icmpv6_type', 'set_in_phy_port', 'set_in_port', 'set_ip_dscp', 'set_ip_ecn', 'set_ip_proto', 'set_ipv4_dst', 'set_ipv4_dst_masked', 'set_ipv4_src', 'set_ipv4_src_masked', 'set_ipv6_dst', 'set_ipv6_dst_masked', 'set_ipv6_exthdr', 'set_ipv6_exthdr_masked', 'set_ipv6_flabel', 'set_ipv6_flabel_masked', 'set_ipv6_nd_sll', 'set_ipv6_nd_target', 'set_ipv6_nd_tll', 'set_ipv6_src', 'set_ipv6_src_masked', 'set_metadata', 'set_metadata_masked', 'set_mpls_bos', 'set_mpls_label', 'set_mpls_tc', 'set_pbb_isid', 'set_pbb_isid_masked', 'set_sctp_dst', 'set_sctp_src', 'set_tcp_dst', 'set_tcp_src', 'set_tunnel_id', 'set_tunnel_id_masked', 'set_udp_dst', 'set_udp_src', 'set_vlan_pcp', 'set_vlan_vid', 'set_vlan_vid_masked', 'set_vlan_vid_none', 'stringify_attrs', 'to_jsondict', 'type']
5.通過ofp_parser中獲取actions類匹配
[OFPActionOutput(len=16,max_len=65535,port=4294967293,type=0)]

['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
6.match = ofp_parser.OFPMatch()中OFPMatch類協議支持的匹配方式
class OFPMatch(StringifyMixin): """ Flow Match Structure This class is implementation of the flow match structure having compose/query API. There are new API and old API for compatibility. the old API is supposed to be removed later. You can define the flow match by the keyword arguments. The following arguments are available. ================ =============== ================================== Argument Value Description ================ =============== ================================== in_port Integer 32bit Switch input port in_phy_port Integer 32bit Switch physical input port metadata Integer 64bit Metadata passed between tables eth_dst MAC address Ethernet destination address eth_src MAC address Ethernet source address eth_type Integer 16bit Ethernet frame type vlan_vid Integer 16bit VLAN id vlan_pcp Integer 8bit VLAN priority ip_dscp Integer 8bit IP DSCP (6 bits in ToS field) ip_ecn Integer 8bit IP ECN (2 bits in ToS field) ip_proto Integer 8bit IP protocol ipv4_src IPv4 address IPv4 source address ipv4_dst IPv4 address IPv4 destination address tcp_src Integer 16bit TCP source port tcp_dst Integer 16bit TCP destination port udp_src Integer 16bit UDP source port udp_dst Integer 16bit UDP destination port sctp_src Integer 16bit SCTP source port sctp_dst Integer 16bit SCTP destination port icmpv4_type Integer 8bit ICMP type icmpv4_code Integer 8bit ICMP code arp_op Integer 16bit ARP opcode arp_spa IPv4 address ARP source IPv4 address arp_tpa IPv4 address ARP target IPv4 address arp_sha MAC address ARP source hardware address arp_tha MAC address ARP target hardware address ipv6_src IPv6 address IPv6 source address ipv6_dst IPv6 address IPv6 destination address ipv6_flabel Integer 32bit IPv6 Flow Label icmpv6_type Integer 8bit ICMPv6 type icmpv6_code Integer 8bit ICMPv6 code ipv6_nd_target IPv6 address Target address for ND ipv6_nd_sll MAC address Source link-layer for ND ipv6_nd_tll MAC address Target link-layer for ND mpls_label Integer 32bit MPLS label mpls_tc Integer 8bit MPLS TC mpls_bos Integer 8bit MPLS BoS bit pbb_isid Integer 24bit PBB I-SID tunnel_id Integer 64bit Logical Port Metadata ipv6_exthdr Integer 16bit IPv6 Extension Header pseudo-field pbb_uca Integer 8bit PBB UCA header field (EXT-256 Old version of ONF Extension) tcp_flags Integer 16bit TCP flags (EXT-109 ONF Extension) actset_output Integer 32bit Output port from action set metadata (EXT-233 ONF Extension) ================ =============== ================================== Example:: >>> # compose >>> match = parser.OFPMatch( ... in_port=1, ... eth_type=0x86dd, ... ipv6_src=('2001:db8:bd05:1d2:288a:1fc0:1:10ee', ... 'ffff:ffff:ffff:ffff::'), ... ipv6_dst='2001:db8:bd05:1d2:288a:1fc0:1:10ee') >>> # query >>> if 'ipv6_src' in match: ... print match['ipv6_src'] ... ('2001:db8:bd05:1d2:288a:1fc0:1:10ee', 'ffff:ffff:ffff:ffff::') .. Note:: For the list of the supported Nicira experimenter matches, please refer to :ref:`ryu.ofproto.nx_match <nx_match_structures>`. .. Note:: For VLAN id match field, special values are defined in OpenFlow Spec. 1) Packets with and without a VLAN tag - Example:: match = parser.OFPMatch() - Packet Matching ====================== ===== non-VLAN-tagged MATCH VLAN-tagged(vlan_id=3) MATCH VLAN-tagged(vlan_id=5) MATCH ====================== ===== 2) Only packets without a VLAN tag - Example:: match = parser.OFPMatch(vlan_vid=0x0000) - Packet Matching ====================== ===== non-VLAN-tagged MATCH VLAN-tagged(vlan_id=3) x VLAN-tagged(vlan_id=5) x ====================== ===== 3) Only packets with a VLAN tag regardless of its value - Example:: match = parser.OFPMatch(vlan_vid=(0x1000, 0x1000)) - Packet Matching ====================== ===== non-VLAN-tagged x VLAN-tagged(vlan_id=3) MATCH VLAN-tagged(vlan_id=5) MATCH ====================== ===== 4) Only packets with VLAN tag and VID equal - Example:: match = parser.OFPMatch(vlan_vid=(0x1000 | 3)) - Packet Matching ====================== ===== non-VLAN-tagged x VLAN-tagged(vlan_id=3) MATCH VLAN-tagged(vlan_id=5) x ====================== ===== """
7.out = ofp_parser.OFPPacketOut(datapath=datapath,buffer_id=msg.buffer_id,in_port=in_port,actions=actions,data=msg.data)
out = ofp_parser.OFPPacketOut(datapath=datapath,buffer_id=msg.buffer_id, in_port=in_port,actions=actions) datapath.send_msg(out);
控制器使用此消息通過交換機發送數據包(存在控制器的消息緩存,我們需要發送給交換機,讓他進行發送)---注意我們不僅要傳遞buffer_id還要傳遞data才可以實現將數據返回
@_set_msg_type(ofproto.OFPT_PACKET_OUT) class OFPPacketOut(MsgBase): """ 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) """ def __init__(self, datapath, buffer_id=None, in_port=None, actions=None, data=None, actions_len=None): assert in_port is not None super(OFPPacketOut, self).__init__(datapath) self.buffer_id = buffer_id self.in_port = in_port self.actions_len = 0 self.actions = actions self.data = data def _serialize_body(self): self.actions_len = 0 offset = ofproto.OFP_PACKET_OUT_SIZE for a in self.actions: a.serialize(self.buf, offset) offset += a.len self.actions_len += a.len if self.data is not None: assert self.buffer_id == 0xffffffff if isinstance(self.data, packet.Packet): self.data.serialize() self.buf += self.data.data else: self.buf += self.data msg_pack_into(ofproto.OFP_PACKET_OUT_PACK_STR, self.buf, ofproto.OFP_HEADER_SIZE, self.buffer_id, self.in_port, self.actions_len) @classmethod def from_jsondict(cls, dict_, decode_string=base64.b64decode, **additional_args): if isinstance(dict_['data'], dict): data = dict_.pop('data') ins = super(OFPPacketOut, cls).from_jsondict(dict_, decode_string, **additional_args) ins.data = packet.Packet.from_jsondict(data['Packet']) dict_['data'] = data else: ins = super(OFPPacketOut, cls).from_jsondict(dict_, decode_string, **additional_args) return ins
8.inst = [ofp_parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS,actions)]
inst = [ofp_parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions)] mod = ofp_parser.OFPFlowMod(datapath=datapath,priority=priority, match=match,instructions=inst) datapath.send_msg(mod);
此指令寫入/應用/清除操作。就是說通過這個類實現我們對聲明的actions行為進行應用(應用這個動作)、還是清除(不需要這個動作了)、還是寫入操作
class OFPInstruction(StringifyMixin): _INSTRUCTION_TYPES = {} @staticmethod def register_instruction_type(types): def _register_instruction_type(cls): for type_ in types: OFPInstruction._INSTRUCTION_TYPES[type_] = cls return cls return _register_instruction_type @classmethod def parser(cls, buf, offset): (type_, len_) = struct.unpack_from('!HH', buf, offset) cls_ = cls._INSTRUCTION_TYPES.get(type_) return cls_.parser(buf, offset)
@OFPInstruction.register_instruction_type([ofproto.OFPIT_WRITE_ACTIONS, ofproto.OFPIT_APPLY_ACTIONS, ofproto.OFPIT_CLEAR_ACTIONS]) class OFPInstructionActions(OFPInstruction): """ Actions instruction This instruction writes/applies/clears the actions. ================ ====================================================== Attribute Description ================ ====================================================== type One of following values. | OFPIT_WRITE_ACTIONS | OFPIT_APPLY_ACTIONS | OFPIT_CLEAR_ACTIONS actions list of OpenFlow action class ================ ====================================================== ``type`` attribute corresponds to ``type_`` parameter of __init__. """ def __init__(self, type_, actions=None, len_=None): super(OFPInstructionActions, self).__init__() self.type = type_ for a in actions: assert isinstance(a, OFPAction) self.actions = actions @classmethod def parser(cls, buf, offset): (type_, len_) = struct.unpack_from( ofproto.OFP_INSTRUCTION_ACTIONS_PACK_STR, buf, offset) offset += ofproto.OFP_INSTRUCTION_ACTIONS_SIZE actions = [] actions_len = len_ - ofproto.OFP_INSTRUCTION_ACTIONS_SIZE exc = None try: while actions_len > 0: a = OFPAction.parser(buf, offset) actions.append(a) actions_len -= a.len offset += a.len except struct.error as e: exc = e inst = cls(type_, actions) inst.len = len_ if exc is not None: raise exception.OFPTruncatedMessage(ofpmsg=inst, residue=buf[offset:], original_exception=exc) return inst def serialize(self, buf, offset): action_offset = offset + ofproto.OFP_INSTRUCTION_ACTIONS_SIZE if self.actions: for a in self.actions: a.serialize(buf, action_offset) action_offset += a.len self.len = action_offset - offset pad_len = utils.round_up(self.len, 8) - self.len msg_pack_into("%dx" % pad_len, buf, action_offset) self.len += pad_len msg_pack_into(ofproto.OFP_INSTRUCTION_ACTIONS_PACK_STR, buf, offset, self.type, self.len)
9.mod = ofp_parser.OFPFlowMod(datapath=datapath,priority=priority,match=match,instructions=inst); 修改流表項消息 控制器發送此消息以修改流表。
@_register_parser
@_set_msg_type(ofproto.OFPT_FLOW_MOD)
class OFPFlowMod(MsgBase): """ Modify Flow entry message The controller sends this message to modify the flow table. ================ ====================================================== Attribute Description ================ ====================================================== cookie Opaque controller-issued identifier cookie_mask Mask used to restrict the cookie bits that must match when the command is ``OPFFC_MODIFY*`` or ``OFPFC_DELETE*`` table_id ID of the table to put the flow in command One of the following values. | OFPFC_ADD | OFPFC_MODIFY | OFPFC_MODIFY_STRICT | OFPFC_DELETE | OFPFC_DELETE_STRICT idle_timeout Idle time before discarding (seconds) hard_timeout Max time before discarding (seconds) priority Priority level of flow entry buffer_id Buffered packet to apply to (or OFP_NO_BUFFER) out_port For ``OFPFC_DELETE*`` commands, require matching entries to include this as an output port out_group For ``OFPFC_DELETE*`` commands, require matching entries to include this as an output group flags Bitmap of the following flags. | OFPFF_SEND_FLOW_REM | OFPFF_CHECK_OVERLAP | OFPFF_RESET_COUNTS | OFPFF_NO_PKT_COUNTS | OFPFF_NO_BYT_COUNTS match Instance of ``OFPMatch`` instructions list of ``OFPInstruction*`` instance ================ ====================================================== Example:: def send_flow_mod(self, datapath): ofp = datapath.ofproto ofp_parser = datapath.ofproto_parser cookie = cookie_mask = 0 table_id = 0 idle_timeout = hard_timeout = 0 priority = 32768 buffer_id = ofp.OFP_NO_BUFFER match = ofp_parser.OFPMatch(in_port=1, eth_dst='ff:ff:ff:ff:ff:ff') actions = [ofp_parser.OFPActionOutput(ofp.OFPP_NORMAL, 0)] inst = [ofp_parser.OFPInstructionActions(ofp.OFPIT_APPLY_ACTIONS, actions)] req = ofp_parser.OFPFlowMod(datapath, cookie, cookie_mask, table_id, ofp.OFPFC_ADD, idle_timeout, hard_timeout, priority, buffer_id, ofp.OFPP_ANY, ofp.OFPG_ANY, ofp.OFPFF_SEND_FLOW_REM, match, inst) datapath.send_msg(req) """ def __init__(self, datapath, cookie=0, cookie_mask=0, table_id=0, command=ofproto.OFPFC_ADD, idle_timeout=0, hard_timeout=0, priority=ofproto.OFP_DEFAULT_PRIORITY, buffer_id=ofproto.OFP_NO_BUFFER, out_port=0, out_group=0, flags=0, match=None, instructions=None): instructions = instructions if instructions else [] super(OFPFlowMod, self).__init__(datapath) self.cookie = cookie self.cookie_mask = cookie_mask self.table_id = table_id self.command = command self.idle_timeout = idle_timeout self.hard_timeout = hard_timeout self.priority = priority self.buffer_id = buffer_id self.out_port = out_port self.out_group = out_group self.flags = flags if match is None: match = OFPMatch() assert isinstance(match, OFPMatch) self.match = match for i in instructions: assert isinstance(i, OFPInstruction) self.instructions = instructions def _serialize_body(self): msg_pack_into(ofproto.OFP_FLOW_MOD_PACK_STR0, self.buf, ofproto.OFP_HEADER_SIZE, self.cookie, self.cookie_mask, self.table_id, self.command, self.idle_timeout, self.hard_timeout, self.priority, self.buffer_id, self.out_port, self.out_group, self.flags) offset = (ofproto.OFP_FLOW_MOD_SIZE - ofproto.OFP_MATCH_SIZE) match_len = self.match.serialize(self.buf, offset) offset += match_len for inst in self.instructions: inst.serialize(self.buf, offset) offset += inst.len @classmethod def parser(cls, datapath, version, msg_type, msg_len, xid, buf): msg = super(OFPFlowMod, cls).parser( datapath, version, msg_type, msg_len, xid, buf) (msg.cookie, msg.cookie_mask, msg.table_id, msg.command, msg.idle_timeout, msg.hard_timeout, msg.priority, msg.buffer_id, msg.out_port, msg.out_group, msg.flags) = struct.unpack_from( ofproto.OFP_FLOW_MOD_PACK_STR0, msg.buf, ofproto.OFP_HEADER_SIZE) offset = ofproto.OFP_FLOW_MOD_SIZE - ofproto.OFP_HEADER_SIZE try: msg.match = OFPMatch.parser(buf, offset) except exception.OFPTruncatedMessage as e: msg.match = e.ofpmsg e.ofpmsg = msg raise e offset += utils.round_up(msg.match.length, 8) instructions = [] try: while offset < msg_len: i = OFPInstruction.parser(buf, offset) instructions.append(i) offset += i.len except exception.OFPTruncatedMessage as e: instructions.append(e.ofpmsg) msg.instructions = instructions e.ofpmsg = msg raise e except struct.error as e: msg.instructions = instructions raise exception.OFPTruncatedMessage(ofpmsg=msg, residue=buf[offset:], original_exception=e) msg.instructions = instructions return msg
10.actions = [ofp_parser.OFPActionOutput(ofproto.OFPP_CONTROLLER,ofproto.OFPCML_NO_BUFFER)]---此操作表示將數據包輸出到交換機端口
@OFPAction.register_action_type(ofproto.OFPAT_OUTPUT,
ofproto.OFP_ACTION_OUTPUT_SIZE)
class OFPActionOutput(OFPAction): """ Output action This action indicates output a packet to the switch port. ================ ====================================================== Attribute Description ================ ====================================================== port Output port max_len Max length to send to controller ================ ====================================================== """ def __init__(self, port, max_len=ofproto.OFPCML_MAX, type_=None, len_=None): super(OFPActionOutput, self).__init__() self.port = port self.max_len = max_len @classmethod def parser(cls, buf, offset): type_, len_, port, max_len = struct.unpack_from( ofproto.OFP_ACTION_OUTPUT_PACK_STR, buf, offset) return cls(port, max_len) def serialize(self, buf, offset): msg_pack_into(ofproto.OFP_ACTION_OUTPUT_PACK_STR, buf, offset, self.type, self.len, self.port, self.max_len)
11.ofproto.OFPP_CONTROLLER,ofproto.OFPCML_NO_BUFFER 一個輸出端口,一個是數據包最大長度
<module 'ryu.ofproto.ofproto_v1_3' from '/usr/local/lib/python3.6/dist-packages/ryu/ofproto/ofproto_v1_3.py'>
# enum ofp_port_no OFPP_MAX = 0xffffff00 OFPP_IN_PORT = 0xfffffff8 # Send the packet out the input port. This # virtual port must be explicitly used # in order to send back out of the input # port. OFPP_TABLE = 0xfffffff9 # Perform actions in flow table. # NB: This can only be the destination # port for packet-out messages. OFPP_NORMAL = 0xfffffffa # Process with normal L2/L3 switching. OFPP_FLOOD = 0xfffffffb # All physical ports except input port and # those disabled by STP. OFPP_ALL = 0xfffffffc # All physical ports except input port. OFPP_CONTROLLER = 0xfffffffd # Send to controller. 這是讓交換機將數據包發送給控制器《重點》 OFPP_LOCAL = 0xfffffffe # Local openflow "port". OFPP_ANY = 0xffffffff # Not associated with a physical port.
actions = [ofp_parser.OFPActionOutput(ofproto.OFPP_CONTROLLER,ofproto.OFPCML_NO_BUFFER)] 流表項動作表示將數據包發送給控制器
# enum ofp_controller_max_len OFPCML_MAX = 0xffe5 # maximum max_len value which can be used to 可用於請求特定字節長度的最大Max值。(是向控制器請求的最大數據長度) # request a specific byte length. OFPCML_NO_BUFFER = 0xffff # indicates that no buffering should be 指示不應應用緩沖,並且將整個數據包發送到控制器 # applied and the whole packet is to be # sent to the controller.
actions = [ofp_parser.OFPActionOutput(ofproto.OFPP_CONTROLLER,ofproto.OFPCML_NO_BUFFER)] 表示交換機中不用緩存數據包,全部發送給控制器即可
12.@set_ev_cls(ofp_event.EventOFPSwitchFeatures,CONFIG_DISPATCHER)中的事件,由ofp_event下面的代碼動態生成
NAME = 'ofp_event' class EventOFPMsgBase(event.EventBase): """ The base class of OpenFlow event class. OpenFlow event classes have at least the following attributes. .. tabularcolumns:: |l|L| ============ ============================================================== Attribute Description ============ ============================================================== msg An object which describes the corresponding OpenFlow message. msg.datapath A ryu.controller.controller.Datapath instance which describes an OpenFlow switch from which we received this OpenFlow message. timestamp Timestamp when Datapath instance generated this event. ============ ============================================================== The msg object has some more additional members whose values are extracted from the original OpenFlow message. """ def __init__(self, msg): self.timestamp = time.time() super(EventOFPMsgBase, self).__init__() self.msg = msg # # Create ofp_event type corresponding to OFP Msg # _OFP_MSG_EVENTS = {} def _ofp_msg_name_to_ev_name(msg_name): return 'Event' + msg_name def ofp_msg_to_ev(msg): return ofp_msg_to_ev_cls(msg.__class__)(msg) def ofp_msg_to_ev_cls(msg_cls): name = _ofp_msg_name_to_ev_name(msg_cls.__name__) return _OFP_MSG_EVENTS[name] def _create_ofp_msg_ev_class(msg_cls): name = _ofp_msg_name_to_ev_name(msg_cls.__name__) # print 'creating ofp_event %s' % name if name in _OFP_MSG_EVENTS: return cls = type(name, (EventOFPMsgBase,), dict(__init__=lambda self, msg: super(self.__class__, self).__init__(msg))) globals()[name] = cls _OFP_MSG_EVENTS[name] = cls def _create_ofp_msg_ev_from_module(ofp_parser): # print mod for _k, cls in inspect.getmembers(ofp_parser, inspect.isclass): if not hasattr(cls, 'cls_msg_type'): continue _create_ofp_msg_ev_class(cls) for ofp_mods in ofproto.get_ofp_modules().values(): ofp_parser = ofp_mods[1] # print 'loading module %s' % ofp_parser _create_ofp_msg_ev_from_module(ofp_parser)