如何使用 Ryu 获取 OVS 端口信息
How to fetch OVS Port Information with Ryu
我目前正在使用 OpenVSwitch 和 Ryu SDN 控制器框架设置测试平台。 OVS 是 运行 on linux,并且有三个端口(包括内部端口),如以下输出所示:
root@MOF:~# ovs-ofctl -O OpenFlow13 show br0
OFPT_FEATURES_REPLY (OF1.3) (xid=0x2): dpid:aaaaaaaaaaaaaa21
n_tables:254, n_buffers:256
capabilities: FLOW_STATS TABLE_STATS PORT_STATS QUEUE_STATS
OFPST_PORT_DESC reply (OF1.3) (xid=0x3):
6(eth1): addr:00:50:56:82:dc:83
config: 0
state: 0
current: 10GB-FD COPPER
advertised: COPPER
supported: 1GB-FD 10GB-FD COPPER
speed: 10000 Mbps now, 10000 Mbps max
10(eth2): addr:00:50:56:82:29:cb
config: 0
state: 0
current: 10GB-FD COPPER
advertised: COPPER
supported: 1GB-FD 10GB-FD COPPER
speed: 10000 Mbps now, 10000 Mbps max
LOCAL(br0): addr:00:50:56:82:29:cb
config: PORT_DOWN
state: LINK_DOWN
speed: 0 Mbps now, 0 Mbps max
OFPT_GET_CONFIG_REPLY (OF1.3) (xid=0x5): frags=normal miss_send_len=0
使用以下代码片段(最小工作示例),我设法在新交换机连接时收到通知:
class MscApp(app_manager.RyuApp):
OFP_VERSIONS = [ofproto_v1_3.OFP_VERSION]
_CONTEXTS = {
'dpset': dpset.DPSet,
}
def __init__(self, *args, **kwargs):
super(MscApp, self).__init__(*args, **kwargs)
self.dpset = kwargs['dpset']
# Initiate datapath array
self.datapaths = {
0xAAAAAAAAAAAAAA21: {
'name': 'Munic',
}
}
@set_ev_cls(ofp_event.EventOFPDescStatsReply, MAIN_DISPATCHER)
def desc_stats_reply_handler(self,msg):
ofp = msg.datapath.ofproto
body = ev.msg.body
self.logger.info('OFPDescStatsReply received: '
'mfr_desc=%d hw_desc=%s sw_desc=%s '
'serial_num=%s dp_desc=%s ',
body.mfr_desc, body.hw_desc, body.sw_desc,
body.serial_num, body.dp_desc)
@set_ev_cls(ofp_event.EventOFPSwitchFeatures, CONFIG_DISPATCHER)
def switch_features_handler(self, ev):
datapath = ev.msg.datapath
ofproto = datapath.ofproto
parser = datapath.ofproto_parser
print 'Router %s has joined!' % self.datapaths[datapath.id]['name']
# Get available ports
req = parser.OFPPortDescStatsRequest(datapath, 0)
datapath.send_msg(req)
@set_ev_cls(event.EventLinkAdd)
def link_add(self, ev):
print ev.link.src, ev.link.dst
print self._get_hwaddr(ev.link.src.dpid, ev.link.src.port_no)
当显示的开关连接时,控制器正确打印 Router Munic has joined!
。但是,用于获取有关可用端口的信息的代码片段不起作用。你知道如何在 ryu 中获取可用端口吗?代码片段来自this question.
背景:OVS有两个物理接口,一个接"outside"网络,一个接"inside"网络。我不仅需要知道哪些端口可用,还需要知道哪个端口可用。任何想法如何解决这个问题?提前致谢!
根据我的理解,您可以将事件设置为在不同阶段接收。
set_ev_cls 的第二个参数表示开关的状态。如果你想在 Ryu 和交换机之间的协商完成之前忽略 packet_in 消息,请使用 MAIN_DISPATCHER。换句话说,使用MAIN_DISPATCHER意味着这个函数只有在协商完成后才会被调用。
有 4 个协商阶段:
- HANDSHAKE_DISPATCHER -> 发送并等待问候消息
- CONFIG_DISPATCHER -> 版本协商并发送功能请求消息
- MAIN_DISPATCHER -> Switch-features 消息接收和发送 set-config 消息
- DEAD_DISPATCHER -> 断开与对等方的连接。或由于某些错误而断开连接。
有关详细信息,请参阅 Ryu API。
所以回到你的问题,一个可能的原因是你正在使用CONFIG_DISPATCHER。将其更改为 MAIN_DISPATCHER 并查看是否有效。
此外,请确保向交换机发送 OFPPortDescStatsRequest
。因为我不认为开关会生成 EventOFPPortDescStatsReply
除非被请求。您需要一个生成开关请求的函数。我觉得这会修复你的代码。这是函数:(但是,我建议在我的 github 中查看 this file)。
def send_port_desc_stats_request(self, datapath):
ofp_parser = datapath.ofproto_parser
req = ofp_parser.OFPPortDescStatsRequest(datapath, 0)
datapath.send_msg(req)
事件 EventOFPPortStatsReply
和 EventOFPPortDescStatsReply
可能会有用。我正在使用它们 like this。
我的 github 中有一个教程,我在那里使用了几个事件。上面的函数在那里定义和解释。
我目前正在使用 OpenVSwitch 和 Ryu SDN 控制器框架设置测试平台。 OVS 是 运行 on linux,并且有三个端口(包括内部端口),如以下输出所示:
root@MOF:~# ovs-ofctl -O OpenFlow13 show br0
OFPT_FEATURES_REPLY (OF1.3) (xid=0x2): dpid:aaaaaaaaaaaaaa21
n_tables:254, n_buffers:256
capabilities: FLOW_STATS TABLE_STATS PORT_STATS QUEUE_STATS
OFPST_PORT_DESC reply (OF1.3) (xid=0x3):
6(eth1): addr:00:50:56:82:dc:83
config: 0
state: 0
current: 10GB-FD COPPER
advertised: COPPER
supported: 1GB-FD 10GB-FD COPPER
speed: 10000 Mbps now, 10000 Mbps max
10(eth2): addr:00:50:56:82:29:cb
config: 0
state: 0
current: 10GB-FD COPPER
advertised: COPPER
supported: 1GB-FD 10GB-FD COPPER
speed: 10000 Mbps now, 10000 Mbps max
LOCAL(br0): addr:00:50:56:82:29:cb
config: PORT_DOWN
state: LINK_DOWN
speed: 0 Mbps now, 0 Mbps max
OFPT_GET_CONFIG_REPLY (OF1.3) (xid=0x5): frags=normal miss_send_len=0
使用以下代码片段(最小工作示例),我设法在新交换机连接时收到通知:
class MscApp(app_manager.RyuApp):
OFP_VERSIONS = [ofproto_v1_3.OFP_VERSION]
_CONTEXTS = {
'dpset': dpset.DPSet,
}
def __init__(self, *args, **kwargs):
super(MscApp, self).__init__(*args, **kwargs)
self.dpset = kwargs['dpset']
# Initiate datapath array
self.datapaths = {
0xAAAAAAAAAAAAAA21: {
'name': 'Munic',
}
}
@set_ev_cls(ofp_event.EventOFPDescStatsReply, MAIN_DISPATCHER)
def desc_stats_reply_handler(self,msg):
ofp = msg.datapath.ofproto
body = ev.msg.body
self.logger.info('OFPDescStatsReply received: '
'mfr_desc=%d hw_desc=%s sw_desc=%s '
'serial_num=%s dp_desc=%s ',
body.mfr_desc, body.hw_desc, body.sw_desc,
body.serial_num, body.dp_desc)
@set_ev_cls(ofp_event.EventOFPSwitchFeatures, CONFIG_DISPATCHER)
def switch_features_handler(self, ev):
datapath = ev.msg.datapath
ofproto = datapath.ofproto
parser = datapath.ofproto_parser
print 'Router %s has joined!' % self.datapaths[datapath.id]['name']
# Get available ports
req = parser.OFPPortDescStatsRequest(datapath, 0)
datapath.send_msg(req)
@set_ev_cls(event.EventLinkAdd)
def link_add(self, ev):
print ev.link.src, ev.link.dst
print self._get_hwaddr(ev.link.src.dpid, ev.link.src.port_no)
当显示的开关连接时,控制器正确打印 Router Munic has joined!
。但是,用于获取有关可用端口的信息的代码片段不起作用。你知道如何在 ryu 中获取可用端口吗?代码片段来自this question.
背景:OVS有两个物理接口,一个接"outside"网络,一个接"inside"网络。我不仅需要知道哪些端口可用,还需要知道哪个端口可用。任何想法如何解决这个问题?提前致谢!
根据我的理解,您可以将事件设置为在不同阶段接收。 set_ev_cls 的第二个参数表示开关的状态。如果你想在 Ryu 和交换机之间的协商完成之前忽略 packet_in 消息,请使用 MAIN_DISPATCHER。换句话说,使用MAIN_DISPATCHER意味着这个函数只有在协商完成后才会被调用。
有 4 个协商阶段:
- HANDSHAKE_DISPATCHER -> 发送并等待问候消息
- CONFIG_DISPATCHER -> 版本协商并发送功能请求消息
- MAIN_DISPATCHER -> Switch-features 消息接收和发送 set-config 消息
- DEAD_DISPATCHER -> 断开与对等方的连接。或由于某些错误而断开连接。
有关详细信息,请参阅 Ryu API。
所以回到你的问题,一个可能的原因是你正在使用CONFIG_DISPATCHER。将其更改为 MAIN_DISPATCHER 并查看是否有效。
此外,请确保向交换机发送 OFPPortDescStatsRequest
。因为我不认为开关会生成 EventOFPPortDescStatsReply
除非被请求。您需要一个生成开关请求的函数。我觉得这会修复你的代码。这是函数:(但是,我建议在我的 github 中查看 this file)。
def send_port_desc_stats_request(self, datapath):
ofp_parser = datapath.ofproto_parser
req = ofp_parser.OFPPortDescStatsRequest(datapath, 0)
datapath.send_msg(req)
事件 EventOFPPortStatsReply
和 EventOFPPortDescStatsReply
可能会有用。我正在使用它们 like this。
我的 github 中有一个教程,我在那里使用了几个事件。上面的函数在那里定义和解释。