SDN实验---Ryu的应用开发(一)Hub实现
生活随笔
收集整理的這篇文章主要介紹了
SDN实验---Ryu的应用开发(一)Hub实现
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
補充:
(一)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向控制器下發流表操作
斷開與對等方的連接?;蛘哂捎谝恍┎豢苫謴偷腻e誤而斷開連接
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'33xffx9axd7xb1x1ajxffx9axd7xb1x86xdd`x00x00x00x00 :xffx00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00xffx02x00x00x00x00x00x00x00x00x00x01xffx9axd7xb1x87x00~fx00x00x00x00xfex80x00x00x00x00x00x00x18jxffxffxfex9axd7xb1x0ex01x1cxddVxffxb4xd8',
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']
View Code
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']
View Code
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']
View Code
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']
View Code
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)
總結
以上是生活随笔為你收集整理的SDN实验---Ryu的应用开发(一)Hub实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 前台线程与后台线程
- 下一篇: Session ,ViewState,以