REST Linkage
该小结主要介绍如何添加一个REST Link 函数
RYU本身提供了一个类似WSGI的web服务器功能。借助这个功能,我们可以创建一个REST API。基于创建的REST API,可以快速的将RYU系统与其他系统或者是浏览器相连接,非常实用的一个功能。
程序解析
在案例中,实现了两个类
SimpleSwitchRest13继承SimpleSwitch13的功能,即具备父类的三层交换机的基本功能。注册WSGI服务配置mac_to_portSimpleSwitchControllerREST API功能实现的主体类返回指定交换机的mac_table更新指定的mac_table条目SimpleSwitchRest13类实现
_CONTEXTS = {"wsgi": WSGIApplication}
该成员变量用于指明Ryu的兼容WSGI的web服务对象。
wsgi = kwargs["wsgi"]wsgi.register(SimpleSwitchController {simple_switch_instance_name: self})
通过上一步设置的_CONTEXTS
成员变量,可以通过kwargs
进行实例化一个WSGIApplication。同时使用register
方法注册该服务到controller类上。
@set_ev_cls(ofp_event.EventOFPSwitchFeatures CONFIG_DISPATCHER)def switch_features_handler(self ev): super(SimpleSwitchRest13 self).switch_features_handler(ev) datapath = ev.msg.datapath self.switches[datapath.id] = datapath self.mac_to_port.setdefault(datapath.id {})
重写父类的switch_features_handler
函数
switches
初始化MAC 地址表def set_mac_to_port(self dpid entry): # 获取MAC table mac_table = self.mac_to_port.setdefault(dpid {}) # 获取datapath如果为None,证明没有该交换机 datapath = self.switches.get(dpid) entry_port = entry["port"] entry_mac = entry["mac"] if datapath is not None: parser = datapath.ofproto_parser # 如果entry_port不在mac_table中 if entry_port not in mac_table.values(): # 下发流表 for mac port in mac_table.items(): # from known device to new device actions = [parser.OFPActionOutput(entry_port)] match = parser.OFPMatch(in_port=port eth_dst=entry_mac) self.add_flow(datapath 1 match actions) # from new device to known device actions = [parser.OFPActionOutput(port)] match = parser.OFPMatch(in_port=entry_port eth_dst=mac) self.add_flow(datapath 1 match actions) # 添加entry_mac entry_port到mac_table mac_table.update({entry_mac: entry_port}) return mac_table
该方法将MAC地址和端口注册到指定的交换机。该方法主要被REST API的PUT方法所调用。
SimpleSwitchController类实现
@route("simpleswitch" url methods=["GET"] requirements={"dpid": dpid_lib.DPID_PATTERN})
借助route
装饰器关联方法和URL。参数如下:
DPID_PATTERN
的描述当使用GET方式访问到该REST API接口时,调用list_mac_table函数
def list_mac_table(self req **kwargs): simple_switch = self.simple_switch_app # 获取{dpid} dpid = dpid_lib.str_to_dpid(kwargs["dpid"]) # 如果没有dpid返回404 if dpid not in simple_switch.mac_to_port: return Response(status=404) # 获取mac_table mac_table = simple_switch.mac_to_port.get(dpid {}) body = json.dumps(mac_table) return Response(content_type="application/json" body=body)
# 使用PUT方式设置mac_table@route("simpleswitch" url methods=["PUT"] requirements={"dpid": dpid_lib.DPID_PATTERN}) def put_mac_table(self req **kwargs): simple_switch = self.simple_switch_app dpid = dpid_lib.str_to_dpid(kwargs["dpid"]) try: new_entry = req.json if req.body else {} except ValueError: raise Response(status=400) if dpid not in simple_switch.mac_to_port: return Response(status=404) try: mac_table = simple_switch.set_mac_to_port(dpid new_entry) body = json.dumps(mac_table) return Response(content_type="application/json" body=body) except Exception as e: return Response(status=500)
运行分析
启动mininet创建网络拓扑图
sudo mn --topo single3 --mac --switch ovskprotocols=OpenFlow13 --controller remote -x
启动控制器程序,打印log信息如下:
debugging is available (--enable-debugger option is turned on)loading app SimpleSwitchRest13loading app ryu.controller.ofp_handlercreating context wsgiinstantiating app SimpleSwitchRest13 of SimpleSwitchRest13instantiating app ryu.controller.ofp_handler of OFPHandlerBRICK SimpleSwitchRest13 CONSUMES EventOFPPacketIn CONSUMES EventOFPSwitchFeaturesBRICK ofp_event PROVIDES EventOFPPacketIn TO {"SimpleSwitchRest13": set(["main"])} PROVIDES EventOFPSwitchFeatures TO {"SimpleSwitchRest13": set(["config"])} CONSUMES EventOFPEchoReply CONSUMES EventOFPSwitchFeatures CONSUMES EventOFPPortDescStatsReply CONSUMES EventOFPHello CONSUMES EventOFPErrorMsg CONSUMES EventOFPEchoRequest CONSUMES EventOFPPortStatus(22238) wsgi starting up on http://0.0.0.0:8080
这里我们可以看到,wsgi服务已经启动,端口号为8080
查询s1的默认MAC table
curl -X GET http://127.0.0.1:8080/simpleswitch/mactable/0000000000000001
返回为{}
在mininet中执行
mininet> h1 ping -c 1 h2
log信息打印如下信息:
EVENT ofp_event->SimpleSwitchRest13 EventOFPPacketInpacket in 1 00:00:00:00:00:01 ff:ff:ff:ff:ff:ff 1EVENT ofp_event->SimpleSwitchRest13 EventOFPPacketInpacket in 1 00:00:00:00:00:02 00:00:00:00:00:01 2EVENT ofp_event->SimpleSwitchRest13 EventOFPPacketInpacket in 1 00:00:00:00:00:01 00:00:00:00:00:02 1
返回了三条PackageIn消息(ARP过程)
此刻按照设计,已经添加了两条条目到MAC table再次查询进行验证。
curl -X GET http://127.0.0.1:8080/simpleswitch/mactable/0000000000000001
返回如下证明符合实验预期:
{"00:00:00:00:00:02": 2 "00:00:00:00:00:01": 1}
测试POST API接口添加h3到MAC Table
curl -X PUT -d "{"mac" : "00:00:00:00:00:03" "port" : 3}" http://127.0.0.1:8080/simpleswitch/mactable/0000000000000001
返回:
{"00:00:00:00:00:03": 3 "00:00:00:00:00:02": 2 "00:00:00:00:00:01": 1}
证明h3 mac已经被添加到MAC table。因为h3已经被添加到MAC Table中,所以理论上当h1 ping h3时将不再通过ARP查找到h3.
测试:在mininet中执行命令
mininet> h1 ping c1 h3PING 10.0.0.3 (10.0.0.3) 56(84) bytes of data.64 bytes from 10.0.0.3: icmp_seq=1 ttl=64 time=2.48 ms--- 10.0.0.3 ping statistics ---1 packets transmitted 1 received 0% packet loss time 0msrtt min/avg/max/mdev = 2.480/2.480/2.480/0.000 ms
控制器log信息如下:
EVENT ofp_event->SimpleSwitchRest13 EventOFPPacketInpacket in 1 00:00:00:00:00:01 ff:ff:ff:ff:ff:ff 1
我们可以看到,只有h1在不知道h3地址的情况下,发起ARP广播,将PackageIn消息发送到控制器,而不再出现以后的一系列消息。这证明MAC Table中添加的条目成功生效,符合预期情况。
Copyright © 2004-2019 Aier EYE Hospital Group.
海口市新港渡海路宝岛花园1A07铺面
版权所有