Hi guys..so now that you know what our project is about and thus, this blog is about, I think it’s time we start making progress towards our aim of having multiple controllers. You would have gotten some idea as to how to control flows in Mininet from the previous post. Well then, we don't have to worry for writing code to enable multiple-controller in OpenVSwitch's source since we know that it supports a switch talking to multiple controllers. We hopefully won't be leaving Mininet at all during the development.
We intend to create a dictionary of lists in order to store the Switch:Controller associations. The keys of the dictionary will be the switch names as in s1, s2, etc. Each key will map to a list of remote controller ip-addresses and probably their port numbers too for establishing a connection between the switches and their assigned controllers.
So, in python our variable would look like:
mulitpleController = {
's1':['127.0.0.1','128.0.0.1','129.0.0.1'],
's2':['127.0.0.1','130.0.0.1']
's3':['130.0.0.1','129.0.0.1']
}
This dictionary will be passed to the function where the controller-switch connection is established.So, we thought of how to attack the problem, and we needed to add an option to allow the users to specify the connectivity of switch to controllers via command-line or through a config file. Command-line seemed to be a good way to start as it is convenient to specify. For this, we have added a new command-line argument, --multictrl, which stands for multiple-controllers. Now if someone wants to specify which controller should talk to which switch, the command will look something like this:
sudo mn --mutictrl=s1:c1,s2:c2,s3:c3
Now lets get into more interesting topic of all the trouble we faced in order to make this happen and how we resolved it :P
- Getting the input through command line and storing it in a variable called ‘multictrl’ in the file mn was not all that difficult. We added an option in parseArgs()[...]
opts.add_option( '--multictrl', '-m', type='string', default=False,
help='use switches with multiple controllers' )
[...]
This will enable parsing with multictrl command line argument during execution. Later we can access the string using self.options.multictrl.
- Once we got that, we had to pass it to the constructor of the class to which ‘Net’ object belonged to (i.e., either Mininet or MininetWithControlNet). We passed it like this in mn file:
[...]
mn = Net(
topo=topo,
switch=switch, host=host, controller=controller,
link=link,
ipBase=ipBase,
inNamespace=inNamespace,
xterms=xterms, autoSetMacs=mac,
autoStaticArp=arp, autoPinCpus=pin,
listenPort=listenPort,
multictrl=multictrl
)
[...]
In the net.py file, there is a contructor __init__() inside Mininet class which accepts the passed keyword arguments. So we added another keyword parameter multictrl and gave it a default value of None. And we wrote a method which would parse the given input, make and return a dictionary object which would hold the associations of Controllers and Switches. The returned dictionary would be stored in a data member called self.multiCtrl.
Now when we ran the program, the program caught an exception :
TypeError: __init__() got an unexpected keyword argument 'multictrl'
So the __init__() method would not accept the newly added parameter! In order to solve this, quite obviously, the first thing we did was we Google-d the error and shockingly we did not get any clear result which would tell us what exactly this error was or how to resolve it. So we read quite a bit about keyword arguments, what is it, how is it done, what are the different methods we can pass the keyword arguments in and things like that. Later we tried to pass our ‘multictrl’ from ‘begin()’ method to ‘__init__()’ method by using *args and **kwargs method i.e.,
[...]
def __init__( self,topo=None, switch=OVSKernelSwitch, host=Host,
controller=Controller, link=Link, intf=Intf,
build=True, xterms=False, cleanup=False, ipBase='10.0.0.0/8',
inNamespace=False,
autoSetMacs=False, autoStaticArp=False, autoPinCpus=False,
listenPort=None, *args, **kwargs):
[...]
In this, the *kwargs argument hold all the unmatched key:value pairs of keyword arguments. So we were hoping that our input would be stored in this at least. But once we ran, we ended up getting the same error!!
Actually, the main cause of all the problems which we were facing was the self.multiCtrl data member. We noticed how other keyword arguments are getting stored while multictrl is failing. It came to our notice that the other keyword arguments and their respective data members to which they were assigned were just the same. Each character’s case matched exactly with that of the data member.
[...]
def __init__( self, topo=None, switch=OVSKernelSwitch, host=Host,
controller=Controller, link=Link, intf=Intf,
build=True, xterms=False, cleanup=False, ipBase='10.0.0.0/8',
multictrl=False, inNamespace=False,
autoSetMacs=False, autoStaticArp=False, autoPinCpus=False,
listenPort=None):
self.topo = topo
self.switoch = switch
self.host = host
self.controller = controller
self.link = link
self.intf = intf
self.ipBase = ipBase
self.ipBaseNum, self.prefixLen = netParse( self.ipBase )
self.nextIP = 1 # start for address allocation
self.inNamespace = inNamespace
self.xterms = xterms
self.cleanup = cleanup
self.autoSetMacs = autoSetMacs
self.autoStaticArp = autoStaticArp
self.autoPinCpus = autoPinCpus
self.numCores = numCores()
self.nextCore = 0 # next core for pinning hosts to CPUs
self.listenPort = listenPort
self.multiCtrl = switchControlPair(multictrl) if multictrl else False
#^the line causing error
#^the line causing error
[...]
On changing the keyword argument such that it exactly matched with the data member, the program did not encounter any errors and we could neatly run with whatever changes we had made in the code.
Using the address 127.0.0.1 is really a bad example as it implies localhost and somehow implies that controller is internal.
ReplyDeleteYou need to be precisely clear how a switch will bifurcate among multiple controllers. Will it be based on IPs, VLAN Ids, MAC addresses, or flows (e.g. HTTP, Mail etc). Also, if multiple controllers tries to make the flow entries for a single flow packet, how you plan to resolve it. Unless this is conceptually clear, the implementation will face issues in development and testing.