o. Construct a network as below and restrict capacity of each link to 1Gbps.
o. If there are flows start from the left nodes(host 5, 6) to right node(host 7, 8), arrange them by round-robin strategy. (Also implement the same strategy to flows from right nodes to left nodes)
o. Use iperf to check whether the strategy is implemented successfully.
o. Set a link down, e.g., s1-s3, and rearrange new flows to go through s2 to keep the whole network unimpeded.
o. Set the former link up, and implement round-robin strategy to new flows as usual.
-----------------------------------------------------------------------------------------------------------
- Construct the topology
o. Construct a topology like that is easy.
o. Add "bw" parameter in Add_link() function to restrict the bandwidth of a link.
o. Add "link=TCLink" parameter when creating a mininet object. Remember to import TCLink from mininet.link.
o. For ease of debugging, I set the mac address of "host x" as "00:00:10:00:00:0x" and ip address as "10.0.0.x".
-----------------------------------------------------------------------------------------------------------
- Prerequisites before implementing Round-Robin strategy
o. To identify whether a flow starts from left/right to right/left or not, we need to know the information for every host about which switch it connects to -- that is, a host tracker function, which is not provided by RYU/Mininet/OpenFlow.
o. This is a network with a loop, therefore we need to handle broadcast stream problem causing by ARP packets if we don't hard-code the hosts information in the controller. (Hard-coding is OK, but inelegant for me...)
o. Need to write another event handler to catch link down event and do proper things to make the network remain WORKING!
o. Need to identify the packet type to install different flow rules to switches.
-----------------------------------------------------------------------------------------------------------
o. Handle broadcast stream problem
- Idea: A switch should refuse to broadcast a packet if it has done it before (or within a certain time).
if dst == "ff:ff:ff:ff:ff:ff": if dpid not in self.flood_history: self.flood_history.setdefault(dpid, []) if (src_ip, dst_ip) in self.flood_history[dpid]: print "Not flood" return else: self.flood_history[dpid].append((src_ip, dst_ip))
- "self.flood_history" is used to record the arp packets that a switch has broadcasted. When the same arp packet is forwarded to the same switch, the packet will be dropped directly.
- Note that ideally the content of "self.flood_history" should be flushed periodically, otherwise a host can only just broadcast once (in case that if an application really needs to broadcast lots of packets from a host).
-----------------------------------------------------------------------------------------------------------
o. Host tracker
- A host tracker implementation is here: https://bitbucket.org/sdnhub/ryu-starter-kit/src/7a162d81f97d080c10beb15d8653a8e0eff8a469/host_tracker.py, but I cannot embedded it into my controller and still don't know why >"<
- Idea: Use get_link() function provided by topology API and "self.mac_to_port" dictionary in the simple learning switch sample code.
* get_link() function provided by topology API could just return switch-switch links but not switch-host links. I think it is also the reason that REST GUI webpage could not show hosts in the topology view. Use get_link() function to get the links of switch s1:
Link: Port<dpid=1, port_no=4, LIVE> to Port<dpid=3, port_no=1, LIVE> Link: Port<dpid=1, port_no=3, LIVE> to Port<dpid=2, port_no=1, LIVE>Both of these two links are switch-switch links.
* "mac_to_port" is used to record that "which port a packet should be sent to" according to its destination mac address. It is a data structure presented in sample code Simple_switch.py. For any switch, it will include all hosts if the whole network is learned by the controller. For example:
{ 1: { '00:00:10:00:00:06': 2, '00:00:10:00:00:07': 4, '00:00:10:00:00:05': 1, '00:00:10:00:00:08': 3}, 4: { '00:00:10:00:00:06': 4, '00:00:10:00:00:07': 1, '00:00:10:00:00:05': 3, '00:00:10:00:00:08': 2} }
- The idea is: consider self.mac_to_port as host information first, and then delete the entries that the port is connected to a switch(obtained by get_link function), e.g, for switch 1, '00:00:10:00:00:07': 4 and '00:00:10:00:00:08': 3 will be deleted.
- (links in self.mac_to_port) – (links got by get_link) = switch-host links
- This information will be updated when a new packet is sent to controller.
--------------------------------------------------------------------------------------------------------------
o. Identify the packet type
msg = ev.msg pkt = packet.Packet(msg.data) eth = pkt.get_protocols(ethernet.ethernet)[0] eth_typr = eth.ethertype- "eth_typr" could be used to identify LLDP packet(ETH_TYPE_LLDP), ARP packet(ETH_TYPE_ARP) or commom IP packet (ETH_TYPE_IP).
- If the packet is a IP packet, use "protocol = pkt.get_protocols(ipv4.ipv4)[0].proto" could obtain the layer 4 protocol type.
* ICMP packet, protocol=1
* TCP packet, protocol=6
* UDP packet, protocol=17
* ICMPv6 packet, protocol=58
* SCTP packet, protocol=132
See also OpenFlow spec for more information.
-------------------------------------------------------------------------------------------------------------------
o. Handle link down event
- According to API, port_add, port_del, port_mod, link_add, link_del events all could be caught by “EventOFPPortStatus”
- When a link is down/up, ofp_event.EventOFPPortStatus will be triggered.
- Catch the event and the "msg.reason" is "ofproto.OFPPR_MODIFY"
- When a link is down, there are three port modified events triggered(should be two!) <-- have no idea at all!
- For example: link s1 s3 down, three events are triggered:
OFPPort(port_no=4,hw_addr='5e:b1:28:ff:85:93',name='s1-eth4',config=1,state=1,curr=2112,advertised=0,supported=0,peer=0,curr_speed=10000000,max_speed=0) OFPPort(port_no=1,hw_addr='ca:89:57:2e:43:75',name='s3-eth1',config=0,state=1,curr=2112,advertised=0,supported=0,peer=0,curr_speed=10000000,max_speed=0) OFPPort(port_no=1,hw_addr='ca:89:57:2e:43:75',name='s3-eth1',config=1,state=1,curr=2112,advertised=0,supported=0,peer=0,curr_speed=10000000,max_speed=0)
- Apparently one of them is unnecessary. My implementation here is ignore the event whith "config!=state" intuitively, if anyone has a good reason for this or other more sensible implementation, please let me know! m( _ _ )m
--------------------------------------------------------------------------------------------------------------------
o. Round Robin strategy
- This part is relatively easier than the above ... just use a parameter to record the last flow is going up/down path, and add the new flow to the other path.
- Also record the path status, if one of these two paths is down, just add new flows to the alive path. If both of them are down, call the police.
- Open xterm of two hosts(lets say h5 and h8) and use iperf to test the round robin strategy, the result will be like:
----------------------------------------------------------------------------------------------------------------------
o. Most of problems of this work were discovered when I tried to run the program practically. It's really interesting to debug ....................................... - . - |||
沒有留言:
張貼留言