REST Linkage
This summary describes how to add a rest Link function
The Ryu itself provides a Web server function similar to WSGI. With this feature, we can create a rest API.
Based on the rest API created, the Ryu system can be quickly connected to other systems or browsers, which is a very useful feature.
Program parsing
In the case, two classes were implemented
- SimpleSwitchRest13
- Inherits the functionality of the SimpleSwitch13, which is the basic functionality of a three-layer switch with a parent class.
- Register WSGI Service
- Configure Mac_to_port
- Simpleswitchcontroller
- The principal class for the REST API feature implementation
- Returns the mac_table of the specified switch
- Update the specified Mac_table entry
SimpleSwitchRest13 class implementation
_CONTEXTS = {'wsgi': WSGIApplication}
This member variable is used to indicate the Ryu compatible WSGI Web service object.
wsgi = kwargs['wsgi']wsgi.register(SimpleSwitchController, {simple_switch_instance_name: self})
The member variables that are set in the previous step _CONTEXTS
can be kwargs
instantiated by a wsgiapplication. Use register
the same method to register the service to
Controller class.
@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, {})
Overriding a function of the parent class switch_features_handler
- Storage DataPath to
switches
- Initializing the MAC Address table
def set_mac_to_port (self, Dpid, entry): # get mac Table mac_table = Self.mac_to_port.setdefault (Dpid, {}) # get D Atapath, if none, proves that there is no switch datapath = Self.switches.get (dpid) entry_port = entry[' Port '] Entry_mac = entry[' mac '] If DataPath is not none:parser = datapath.ofproto_parser # if Entry_port isn't in mac_table if Entry_port Not in Mac_table.values (): # issued stream table for Mac, Port in Mac_table.items (): # from Known de Vice 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) # Add Entry_m AC, entry_port to mac_table mac_tablE.update ({entry_mac:entry_port}) return mac_table
This method registers the MAC address and port with the specified switch. This method is primarily called by the put method of the rest API.
Simpleswitchcontroller class implementation
@route('simpleswitch', url, methods=['GET'], requirements={'dpid': dpid_lib.DPID_PATTERN})
route
associate methods and URLs with adorners. The parameters are as follows:
- First parameter: Any custom name
- Second parameter: Indicates the URL
- Third parameter: Specify the HTTP method
- Fourth parameter: Indicates the format of the specified location, the URL (/simpleswitch/mactable/{dpid} matches
DPID_PATTERN
the description
Call the List_mac_table function when you access the rest API interface by using GET mode
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)
Run analysis
Start mininet Create a network topology diagram
sudo mn --topo single,3 --mac --switch ovsk,protocols=OpenFlow13 --controller remote -x
Start the controller program and print the log information as follows:
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
Here we can see that the WSGI service has been started with a port number of 8080
Query the default Mac table for S1
curl -X GET http://127.0.0.1:8080/simpleswitch/mactable/0000000000000001
Return to{}
Execute in Mininet
mininet> h1 ping -c 1 h2
The log information prints the following information:
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
Three Packagein messages returned (ARP procedure)
- Host1 initiates an ARP request and broadcasts
- Host2 initiated ARP request, MAC address is host1
- ICMP Echo Reply request takes place from Host1 to Host2
Now by design, two entries have been added to Mac table, and the query is verified again.
curl -X GET http://127.0.0.1:8080/simpleswitch/mactable/0000000000000001
Return as follows to demonstrate compliance with experimental expectations:
{"00:00:00:00:00:02": 2, "00:00:00:00:00:01": 1}
Test Post API interface, add H3 to Mac Table
curl -X PUT -d '{"mac" : "00:00:00:00:00:03", "port" : 3}' http://127.0.0.1:8080/simpleswitch/mactable/0000000000000001
Return:
{"00:00:00:00:00:03": 3, "00:00:00:00:00:02": 2, "00:00:00:00:00:01": 1}
Prove that the H3 Mac has been added to Mac table. Because H3 has been added to Mac table, it is theoretically not possible to find H3 through ARP when H1 ping H3.
Testing: Executing commands in 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
The controller log information is as follows:
EVENT ofp_event->SimpleSwitchRest13 EventOFPPacketInpacket in 1 00:00:00:00:00:01 ff:ff:ff:ff:ff:ff 1
We can see that only H1, without knowing the H3 address, initiates an ARP broadcast that sends Packagein messages to the controller without any subsequent series of messages. This proves that the entries added to the
MAC table are successful, as expected.