switching hub解析

from ryu.base import app_manager
from ryu.controller import ofp_event
from ryu.controller.handler import CONFIG_DISPATCHER , MAIN_DISPATCHER
from ryu.controller.handler import set_ev_cls
from ryu.ofproto import ofproto_v1_3
from ryu.lib.packet import packet
from ryu.lib.packet import ethernet

class SimpleSwitch13(app_manager.RyuApp):
OFP_VERSIONS = [ofproto_v1_3.OFP_VERSION]

def __init__(self , *args, **kwargs):
super(SimpleSwitch13 , self).__init__(*args, **kwargs)
self.mac_to_port = {}

@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
# install table -miss flow entry
#
# We specify NO BUFFER to max_len of the output action due to
# OVS bug. At this moment , if we specify a lesser number , e.g.,
# 128, OVS will send Packet -In with invalid buffer_id and
# truncated packet data. In that case , we cannot output packets
# correctly.
match = parser.OFPMatch()
actions = [parser.OFPActionOutput(ofproto.OFPP_CONTROLLER ,
ofproto.OFPCML_NO_BUFFER)]
self.add_flow(datapath , 0, match , actions)
def add_flow(self , datapath , priority , match , actions):
ofproto = datapath.ofproto
parser = datapath.ofproto_parser
inst = [parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS ,
actions)]
mod = parser.OFPFlowMod(datapath=datapath , priority=priority ,
match=match , instructions=inst)
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
parser = datapath.ofproto_parser
in_port = msg.match['in_port']
pkt = packet.Packet(msg.data)
eth = pkt.get_protocols(ethernet.ethernet)[0]
dst = eth.dst
src = eth.src
dpid = datapath.id
self.mac_to_port.setdefault(dpid, {})
self.logger.info("packet in %s %s %s %s", dpid, src, dst, in_port)
# learn a mac address to avoid FLOOD next time.
self.mac_to_port[dpid][src] = in_port
if dst in self.mac_to_port[dpid]:
out_port = self.mac_to_port[dpid][dst]
else:
out_port = ofproto.OFPP_FLOOD
actions = [parser.OFPActionOutput(out_port)]
# install a flow to avoid packet_in next time
if out_port != ofproto.OFPP_FLOOD:
match = parser.OFPMatch(in_port=in_port , eth_dst=dst)
self.add_flow(datapath , 1, match , actions)
data = None
if msg.buffer_id == ofproto.OFP_NO_BUFFER:
data = msg.data
out = parser.OFPPacketOut(datapath=datapath , buffer_id=msg.buffer_id ,
in_port=in_port , actions=actions , data=data)
datapath.send_msg(out)

在ryu中,控制器只要接收到openflow消息(event),就会触发相应的事件管理(event handler)
switching hub流程:
首先,交换机和控制器握手,hello建立连接,然后交换机发送SwitchFeatures到控制器 , 控制器收到switch_features(features_reply)事件后, 注册相应事件,指定交换机状态,触发switch_features_handler方法来为交换机增添table_miss flow entry流表项.于是在此方法在调用add_flow()方法执行后,交换机中多了一个table_miss flow entry,这个表项有两个特点,第一,它的优先级最低,设为0,当进入交换机的packet没有普通表项可匹配时,才会来匹配它.第二,它可以OFPMatch()匹配任意packet,并指定actions为
parser.OFPActionOutput(ofproto.OFPP_CONTROLLER,ofproto.OFPCML_NO_BUFFER) ,表示将包输出向控制器端口,交换机不缓存包,来包全部发向控制器.
那么,在指定好match(匹配来包,并确定包类型)和actions(指定包的行为)后,表项到底是如何建立呢???那就需要我们来分析add_flow()方法. 首先,它有四个输入参数,datapath(相当于当下交换机的抽象逻辑体现),priority,match,actions,然后通过datapath来调用ofproto(s与c商量好的of协议)中的某些指定包动作的参数和调用ofproto.parser来指定包的动作等,如下所示:
通过parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS,actions) , 实例化形成一个指令inst,作为OFPFlowMod()的输入参数. 再然后,通过调用parser.OFPFlowMod()方法生成mod,
再调用datapath.send_msg()方法将mod(openflow消息)发送给交换机,交换机生成对应的表项.至此,从控制器执行add_flow()程序,运行结果----交换机生成相应表项.
当有packet 进入交换机,无普通表项匹配时,触发packet_in 事件, 匹配上面switch_features_handler方法在交换机中生成的table_miss flow entry , 然后根据此表项中的actions, packet_in被发往controller , controller收到packet_in消息事件 , 触发packet_in_handler方法.
这个方法需要做什么呢?
第一,它要对packet_in进行解析,提取出最重要的控制信息,源mac和目的mac地址,源端口等
第二,它要学习发出packet的主机的mac地址.根据packet路经交换机的id,进入交换机端口的id,以及源mac地址信息,学习到mac地址.添加入mac_to_port字典.即mac_to_port[dpid]
[src][in_port]. 如{ “1”:{“01”:”1” , “02”:”2”} , “2”:{“03”:”3” , “04”:”4”} }
第三,需要迭代查找mac_to_port表中是否有需要的目的地址.若有,调用OFPActionOutput()将actions指向输出端口,调用OFPMatch()来match目的地址和输入端口,调用add_flow()向交换机中添加一个从源到目的地的普通表项,避免下次再发时packet_in.若无,actions指向OFPP_FLOOD , 准备泛洪.
第四,调用parser.OFPPacketOut()方法,生成packet_out消息, 参数datapath=datapath ,buffer_id=msg.buffer_id, in_port=in_port, actions=actions, data=data, 最后调用datapath.send_msg()发出packet_out消息到对应地址.

設定封包的 binary data 。主要用在 buffer_id 為 OFP_NO_BUFFER 的情況。如果使用
了 OpenFlow 交換器的緩衝區則可以省略。交換器的實作時,在 Packet-In 訊息中指定 buffer_id。若是 Packet-In 訊息中 buffer_id 被設定為無效時。Packet-In 的封包必須指定 data 以便傳送。
OFPFlowMod()的参数如下:
Datapath类:OpenFlow交换机以及 Flow table 的操作都是透過 Datapath 類別的实体來進行。在一般的情況下,会由事件傳遞給事件管理的openflow消息中取得,例如:Packet-In 訊息。
cookie(0): controller使用它存储特定资料,entry的更新和删除时所需要的资料都会存在这里,当作使用过滤器,但是它并不用作处理packet的参数
cookie_mask(0):若entry更新删除时,若该值非0,则作为指定entry的cookie使用
table_id:指定流表项的table id
command(ofproto_v1_3.):指定某项操作:OFPFC_ADD(新增流表) OFPFC_MODIFY(修改/更新流表) OFPFC_MODIFY_STRICT(严格更新) OFPFC_DELETE(删除流表) OFPFC_DELETE_STRICT(严格删除)
idle_timeout(0):entry的有效时间,。Flow Entry 如果未被參照而且超過了指定的時間之後,該 Flow Entry 將會被刪除。如果 Flow Entry 有被參照,則超過時間之後會重新歸零計算Flow Entry 的有效期限,以秒為單位。在 Flow Entry 被刪除之後就會發出 Flow Removed 訊息通知 Controller 。
hard_timeout(0):Flow Entry 的有效期限,以秒為單位。跟 idle_timeout 不同的地方是,hard_timeout:在超過時限後並不會重新歸零計算。也就是說跟 Flow Entry 與有沒有被參照無關,只要超過指定的時間就會被刪除.
buffer_id(ofproto_v1_3.OFP_NO_BUFFER):指定 OpenFlow 交換器上用來儲存封包的緩衝區 ID。緩衝區 ID 會放在通知 Controller 的 Packet-In 訊息中,並且和接下來的 OFPP_TABLE 所指定的輸出埠和Flow Mod 訊息處理時可以被參照。當發送的命令訊息為 OFPFC_DELETE 或 OFPFC_DELETE_STRICT 時,會忽略本數值
还有out_port(0) out_group(0) flags() match instructions参数等

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值