Stoachastic Switching using Open vSwitch in Mininet
[Description]
OpenFlow 1.3 implements group table feature and select
group type. The default implementation of select
group type in OVS 2.1 randomly selects a bucket from among
the live buckets based on destination MAC. Therefore, I found https://github.com/saeenali/openvswitch/wiki/Stochastic-Switching-using-Open-vSwitch-in-Mininet.
The author uses the select
group type to probabilistically select a group
action bucket. The author generates a random number to represent the
probability for choosing a bucket. This probability and bucket weights are used
to select a bucket. In that webpage, the author described clearly how to
modify the ofproto-dpif-xlate.c. However, it may be
difficult for beginners to do the job. So I do all the things and prepare a VM
(sdnhub_stoachastic_switch.zip).
Everything is included. Just download this file and decompress it. Then use virtualbox to import the ova file.
p.s. The original weight is between 1 and 10. I
have modified the code to make weight between 1 and 100.
[Topology: refer to the original webpage]
[Script]
(topology.py)
#!/usr/bin/python """Topology with 10 switches
and 10 hosts """ from mininet.cli import CLI from mininet.topo
import Topo from mininet.net import Mininet from mininet.link
import TCLink from mininet.log import setLogLevel class CSLRTopo( Topo ):
def __init__( self ):
"Create Topology"
# Initialize topology
Topo.__init__( self )
# Add hosts h0
= self.addHost( 'h0' )
h1 = self.addHost( 'h1' )
h2 = self.addHost( 'h2' )
h3 = self.addHost( 'h3' )
h4 = self.addHost( 'h4' )
h5 = self.addHost( 'h5' )
h6
= self.addHost( 'h6' )
h7 = self.addHost( 'h7' )
h8 = self.addHost( 'h8' )
h9 = self.addHost( 'h9' )
# Add switches
s0 = self.addSwitch( 's0', listenPort=6634 )
s1 = self.addSwitch( 's1', listenPort=6635 )
s2 = self.addSwitch( 's2', listenPort=6636 )
s3 = self.addSwitch( 's3', listenPort=6637 )
s4 = self.addSwitch( 's4', listenPort=6638 )
s5 = self.addSwitch( 's5', listenPort=6639
)
s6 = self.addSwitch( 's6', listenPort=6640 )
s7 = self.addSwitch( 's7', listenPort=6641 )
s8 = self.addSwitch( 's8', listenPort=6642 )
s9 = self.addSwitch( 's9', listenPort=6643 )
# Add links between hosts and switches
self.addLink( h0, s0 ) # h0-eth0 <->
s0-eth1
self.addLink( h1, s1 ) # h1-eth0 <->
s1-eth1
self.addLink( h2, s2 ) # h2-eth0 <->
s2-eth1
self.addLink( h3, s3 ) # h3-eth0 <->
s3-eth1
self.addLink( h4, s4 ) # h4-eth0 <->
s4-eth1
self.addLink( h5, s5 ) # h5-eth0 <->
s5-eth1
self.addLink( h6, s6 ) # h6-eth0 <-> s6-eth1
self.addLink( h7, s7 ) # h7-eth0 <->
s7-eth1
self.addLink( h8, s8 ) # h8-eth0 <->
s8-eth1
self.addLink( h9, s9 ) # h9-eth0 <->
s9-eth1
# Add links between switches, with bandwidth 100Mbps
self.addLink( s0, s1, bw=100
) # s0-eth2 <-> s1-eth2, Bandwidth = 100Mbps
self.addLink( s0, s2, bw=100
) # s0-eth3 <-> s2-eth2, Bandwidth = 100Mbps
self.addLink( s1, s2, bw=100
) # s1-eth3 <-> s2-eth3, Bandwidth = 100Mbps
self.addLink( s2, s3, bw=100
) # s2-eth4 <-> s3-eth2, Bandwidth = 100Mbps
self.addLink( s3, s4, bw=100
) # s3-eth3 <-> s4-eth2, Bandwidth = 100Mbps
self.addLink( s3, s6, bw=100
) # s3-eth4 <-> s6-eth2, Bandwidth = 100Mbps
self.addLink( s4, s5, bw=100
) # s4-eth3 <-> s5-eth2, Bandwidth = 100Mbps
self.addLink( s5, s7, bw=100
) # s5-eth3 <-> s7-eth2, Bandwidth = 100Mbps
self.addLink( s6, s7, bw=100
) # s6-eth3 <-> s7-eth3, Bandwidth = 100Mbps
self.addLink( s7, s8, bw=100
) # s7-eth4 <-> s8-eth2, Bandwidth = 100Mbps
self.addLink( s7, s9, bw=100
) # s7-eth5 <-> s9-eth2, Bandwidth = 100Mbps
self.addLink( s8, s9, bw=100
) # s8-eth3 <-> s9-eth3, Bandwidth = 100Mbps def run():
"Create and configure network" topo = CSLRTopo()
net = Mininet( topo=topo, link=TCLink, controller=None
) #
Set interface IP and MAC addresses for hosts h0
= net.get( 'h0' )
h0.intf( 'h0-eth0' ).setIP( '10.0.0.2', 24 )
h0.intf( 'h0-eth0' ).setMAC(
'0A:00:00:02:00:00' ) h1
= net.get( 'h1' )
h1.intf( 'h1-eth0' ).setIP( '10.0.1.2', 24 )
h1.intf( 'h1-eth0' ).setMAC(
'0A:00:01:02:00:00' ) h2
= net.get( 'h2' )
h2.intf( 'h2-eth0' ).setIP( '10.0.2.2', 24 )
h2.intf( 'h2-eth0' ).setMAC(
'0A:00:02:02:00:00' ) h3
= net.get( 'h3' )
h3.intf( 'h3-eth0' ).setIP( '10.0.3.2', 24 )
h3.intf( 'h3-eth0' ).setMAC(
'0A:00:03:02:00:00' ) h4
= net.get( 'h4' )
h4.intf( 'h4-eth0' ).setIP( '10.0.4.2', 24 )
h4.intf( 'h4-eth0' ).setMAC(
'0A:00:04:02:00:00' ) h5
= net.get( 'h5' )
h5.intf( 'h5-eth0' ).setIP( '10.0.5.2', 24 )
h5.intf( 'h5-eth0' ).setMAC(
'0A:00:05:02:00:00' ) h6
= net.get( 'h6' )
h6.intf( 'h6-eth0' ).setIP( '10.0.6.2', 24 ) h6.intf( 'h6-eth0' ).setMAC( '0A:00:06:02:00:00' ) h7
= net.get( 'h7' )
h7.intf( 'h7-eth0' ).setIP( '10.0.7.2', 24 )
h7.intf( 'h7-eth0' ).setMAC(
'0A:00:07:02:00:00' ) h8
= net.get( 'h8' )
h8.intf( 'h8-eth0' ).setIP( '10.0.8.2', 24 )
h8.intf( 'h8-eth0' ).setMAC(
'0A:00:08:02:00:00' ) h9
= net.get( 'h9' )
h9.intf( 'h9-eth0' ).setIP( '10.0.9.2', 24 )
h9.intf( 'h9-eth0' ).setMAC(
'0A:00:09:02:00:00' ) #
Set interface MAC address for switches (NOTE: IP #
addresses are not assigned to switch interfaces) s0
= net.get( 's0' )
s0.intf( 's0-eth1' ).setMAC(
'0A:00:00:01:00:01' )
s0.intf( 's0-eth2' ).setMAC( '0A:00:0A:01:00:02'
)
s0.intf( 's0-eth3' ).setMAC(
'0A:00:0B:01:00:03' ) s1
= net.get( 's1' )
s1.intf( 's1-eth1' ).setMAC(
'0A:00:01:01:00:01' )
s1.intf( 's1-eth2' ).setMAC(
'0A:00:0A:FE:00:02' )
s1.intf( 's1-eth3' ).setMAC( '0A:00:0C:01:00:03'
) s2
= net.get( 's2' )
s2.intf( 's2-eth1' ).setMAC(
'0A:00:02:01:00:01' )
s2.intf( 's2-eth2' ).setMAC(
'0A:00:0B:FE:00:02' )
s2.intf( 's2-eth3' ).setMAC(
'0A:00:0D:01:00:03' )
s2.intf( 's2-eth4' ).setMAC(
'0A:00:0C:FE:00:04' ) s3
= net.get( 's3' )
s3.intf( 's3-eth1' ).setMAC(
'0A:00:03:01:00:01' )
s3.intf( 's3-eth2' ).setMAC(
'0A:00:0D:FE:00:02' )
s3.intf( 's3-eth3' ).setMAC(
'0A:00:0E:01:00:03' )
s3.intf( 's3-eth4' ).setMAC(
'0A:00:0F:01:00:04' ) s4
= net.get( 's4' )
s4.intf( 's4-eth1' ).setMAC(
'0A:00:04:01:00:01' )
s4.intf( 's4-eth2' ).setMAC(
'0A:00:0E:FE:00:02' )
s4.intf( 's4-eth3' ).setMAC(
'0A:00:10:01:00:03' ) s5
= net.get( 's5' )
s5.intf( 's5-eth1' ).setMAC(
'0A:00:05:01:00:01' )
s5.intf( 's5-eth2' ).setMAC(
'0A:00:10:FE:00:02' )
s5.intf( 's5-eth3' ).setMAC(
'0A:00:11:01:00:03' ) s6
= net.get( 's6' )
s6.intf( 's6-eth1' ).setMAC(
'0A:00:06:01:00:01' )
s6.intf( 's6-eth2' ).setMAC(
'0A:00:0F:FE:00:02' )
s6.intf( 's6-eth3' ).setMAC(
'0A:00:12:01:00:03' ) s7
= net.get( 's7' )
s7.intf( 's7-eth1' ).setMAC(
'0A:00:07:01:00:01' ) s7.intf(
's7-eth2' ).setMAC( '0A:00:11:FE:00:02' )
s7.intf( 's7-eth3' ).setMAC(
'0A:00:12:FE:00:03' )
s7.intf( 's7-eth4' ).setMAC(
'0A:00:13:01:00:04' )
s7.intf( 's7-eth5' ).setMAC(
'0A:00:14:01:00:05' ) s8
= net.get( 's8' )
s8.intf( 's8-eth1' ).setMAC(
'0A:00:08:01:00:01' )
s8.intf( 's8-eth2' ).setMAC(
'0A:00:13:FE:00:02' )
s8.intf( 's8-eth3' ).setMAC(
'0A:00:15:01:00:03' ) s9
= net.get( 's9' )
s9.intf( 's9-eth1' ).setMAC( '0A:00:09:01:00:01'
)
s9.intf( 's9-eth2' ).setMAC(
'0A:00:14:FE:00:02' )
s9.intf( 's9-eth3' ).setMAC(
'0A:00:15:FE:00:03' ) net.start() #
Add routing table entries for hosts (NOTE: The gateway #
IPs 10.0.X.1 are not assigned to switch interfaces)
h0.cmd( 'route add default gw 10.0.0.1 dev
h0-eth0' )
h1.cmd( 'route add default gw 10.0.1.1 dev
h1-eth0' )
h2.cmd( 'route add default gw 10.0.2.1 dev
h2-eth0' )
h3.cmd( 'route add default gw 10.0.3.1 dev
h3-eth0' )
h4.cmd( 'route add default gw 10.0.4.1 dev
h4-eth0' )
h5.cmd( 'route add default gw 10.0.5.1 dev
h5-eth0' )
h6.cmd( 'route add default gw 10.0.6.1 dev
h6-eth0' )
h7.cmd( 'route add default gw 10.0.7.1 dev
h7-eth0' )
h8.cmd( 'route add default gw 10.0.8.1 dev
h8-eth0' )
h9.cmd( 'route add default gw 10.0.9.1 dev
h9-eth0' ) #
Add arp cache entries for hosts
h0.cmd( 'arp -s 10.0.0.1 0A:00:00:01:00:01 -i h0-eth0' )
h1.cmd( 'arp -s 10.0.1.1 0A:00:01:01:00:01 -i h1-eth0' )
h2.cmd( 'arp -s 10.0.2.1 0A:00:02:01:00:01 -i h2-eth0' )
h3.cmd( 'arp -s 10.0.3.1 0A:00:03:01:00:01 -i h3-eth0' )
h4.cmd( 'arp -s 10.0.4.1 0A:00:04:01:00:01 -i h4-eth0' )
h5.cmd( 'arp -s 10.0.5.1 0A:00:05:01:00:01 -i h5-eth0' )
h6.cmd( 'arp -s 10.0.6.1 0A:00:06:01:00:01 -i h6-eth0' )
h7.cmd( 'arp -s 10.0.7.1 0A:00:07:01:00:01 -i h7-eth0' )
h8.cmd( 'arp -s 10.0.8.1 0A:00:08:01:00:01 -i h8-eth0' )
h9.cmd( 'arp -s 10.0.9.1 0A:00:09:01:00:01 -i h9-eth0' ) #
Open Mininet Command Line Interface
CLI(net) #
Teardown and cleanup net.stop() if __name__ == '__main__': setLogLevel('info') run() |
(script_topology)
#
ADD-GROUP at s7 for [0, 9] ovs-ofctl -O OpenFlow13 add-group
tcp:127.0.0.1:6641 group_id=0,type=select,bucket=weight:65,mod_dl_src:0A:00:14:01:00:05,mod_dl_dst:0A:00:14:FE:00:02,output=5,bucket=weight:35,mod_dl_src:0A:00:13:01:00:04,mod_dl_dst:0A:00:13:FE:00:02,output=4 #
ADD-FLOW(s) for [0, 9] at [0, 2, 3, 6, 7, 8, 9] ovs-ofctl -O
OpenFlow13 add-flow tcp:127.0.0.1:6634
in_port=1,ip,nw_src=10.0.0.2,nw_dst=10.0.9.2,actions=mod_dl_src:0A:00:0B:01:00:03,mod_dl_dst:0A:00:0B:FE:00:02,output=3 ovs-ofctl -O
OpenFlow13 add-flow tcp:127.0.0.1:6636
in_port=2,ip,nw_src=10.0.0.2,nw_dst=10.0.9.2,actions=mod_dl_src:0A:00:0D:01:00:04,mod_dl_dst:0A:00:0D:FE:00:02,output=4 ovs-ofctl -O
OpenFlow13 add-flow tcp:127.0.0.1:6637 in_port=2,ip,nw_src=10.0.0.2,nw_dst=10.0.9.2,actions=mod_dl_src:0A:00:0F:01:00:04,mod_dl_dst:0A:00:0F:FE:00:02,output=4 ovs-ofctl -O
OpenFlow13 add-flow tcp:127.0.0.1:6640
in_port=2,ip,nw_src=10.0.0.2,nw_dst=10.0.9.2,actions=mod_dl_src:0A:00:12:01:00:03,mod_dl_dst:0A:00:12:FE:00:03,output=3 ovs-ofctl -O OpenFlow13 add-flow tcp:127.0.0.1:6641 in_port=3,ip,nw_src=10.0.0.2,nw_dst=10.0.9.2,actions=group=0 ovs-ofctl -O
OpenFlow13 add-flow tcp:127.0.0.1:6643
in_port=2,ip,nw_src=10.0.0.2,nw_dst=10.0.9.2,actions=mod_dl_src:0A:00:09:01:00:01,mod_dl_dst:0A:00:09:02:00:00,output=1 ovs-ofctl -O
OpenFlow13 add-flow tcp:127.0.0.1:6642
in_port=2,ip,nw_src=10.0.0.2,nw_dst=10.0.9.2,actions=mod_dl_src:0A:00:15:01:00:03,mod_dl_dst:0A:00:15:FE:00:03,output=3 ovs-ofctl -O
OpenFlow13 add-flow tcp:127.0.0.1:6643
in_port=3,ip,nw_src=10.0.0.2,nw_dst=10.0.9.2,actions=mod_dl_src:0A:00:09:01:00:01,mod_dl_dst:0A:00:09:02:00:00,output=1 |
[Execution]
Open
one terminal to run topology.py
Open
another terminal to run the script_topology. This
will create the rules for those switches.
Check
the rule, group, and port information for switch 7 (s7)
Run
iperf between h0 and h9
check
the port information for s7. We can find that the port 4 has sent out 14774
packets and port 5 has sent out 27591 packets. Port 5: 27591/(14774+27591) *
100% = 65.1% Port 4:14774/(14774+27591)*100%=34.87%
The
results are very close to our setting (Port 5: weight=65, Port 4: weight=35)
Dr. Chih-Heng Ke
Department of Computer Science and Information
Engineering, National Quemoy University, Kinmen,
Taiwan
Email: smallko@gmail.com