Implement changes to cord-tester framework for vrouter configuration.
And add vrouter tests to verify routes.
diff --git a/src/test/cli/clidriver.py b/src/test/cli/clidriver.py
index ce10a2c..ccb27a0 100644
--- a/src/test/cli/clidriver.py
+++ b/src/test/cli/clidriver.py
@@ -52,7 +52,7 @@
         if self.port:
             ssh_hosts_file = os.path.join(os.getenv('HOME'), '.ssh', 'known_hosts')
             cmd_host_remove = 'ssh-keygen -f "%s" -R [%s]:8101' %(ssh_hosts_file, self.ip_address)
-            #os.system(cmd_host_remove)
+            os.system(cmd_host_remove)
             #main.log.info('SSH host remove cmd: %s' %cmd_host_remove)
             main.log.info('Spawning pexpect for ip %s' %self.ip_address)
             self.handle = pexpect.spawn(
diff --git a/src/test/cli/onosclidriver.py b/src/test/cli/onosclidriver.py
index 15753a6..b2e0526 100644
--- a/src/test/cli/onosclidriver.py
+++ b/src/test/cli/onosclidriver.py
@@ -41,6 +41,7 @@
 
     def connect_cli(self):
         options = { 'name' : 'onoscli', 'onosIp': '{0}'.format(self.controller) }
+        main.log.info('Connecting to controller at %s' %self.controller)
         self.connect(name = options['name'], user_name = 'onos', pwd = 'rocks',
                      ip_address = self.controller, port = '8101', options = options)
 
@@ -4575,7 +4576,7 @@
             main.exit()
 
 if __name__ == '__main__':
-  onos_cli = OnosCliDriver()
+  onos_cli = OnosCliDriver(connect = False)
   name = 'onos_cli'
   user = 'onos'
   passwd = 'rocks'
diff --git a/src/test/flows/flowsTest.py b/src/test/flows/flowsTest.py
index 3e73559..88a7d0b 100644
--- a/src/test/flows/flowsTest.py
+++ b/src/test/flows/flowsTest.py
@@ -6,17 +6,11 @@
 import time
 import json
 import threading
-import fcntl, socket, struct
 from OnosCtrl import OnosCtrl
-from OnosFlowCtrl import OnosFlowCtrl
+from OnosFlowCtrl import OnosFlowCtrl, get_mac
 from OltConfig import OltConfig
 log.setLevel('INFO')
 
-def get_mac(iface = 'ovsbr0', pad = 4):
-    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
-    info = fcntl.ioctl(s.fileno(), 0x8927, struct.pack('256s', iface[:15]))
-    return '0'*pad + ''.join(['%02x' %ord(char) for char in info[18:24]])
-
 class flows_exchange(unittest.TestCase):
 
     #Use the first available device id as our device id to program flows
@@ -94,7 +88,7 @@
                 log.info('Pkt seen with ingress ip %s, egress ip %s' %(pkt[IP].src, pkt[IP].dst))
                 self.success = True
             sniff(count=2, timeout=5, 
-                  lfilter = lambda p: p[IP].dst == egress_map['ip'] and p[IP].src == ingress_map['ip'],
+                  lfilter = lambda p: IP in p and p[IP].dst == egress_map['ip'] and p[IP].src == ingress_map['ip'],
                   prn = recv_cb, iface = self.port_map[egress])
 
         t = threading.Thread(target = mac_recv_task)
diff --git a/src/test/setup/cord-test.py b/src/test/setup/cord-test.py
index 09c04db..8ac86fc 100755
--- a/src/test/setup/cord-test.py
+++ b/src/test/setup/cord-test.py
@@ -1,222 +1,16 @@
 #!/usr/bin/env python
 from argparse import ArgumentParser
 import os,sys,time
-import io
-import yaml
-from pyroute2 import IPRoute
-from itertools import chain
-from nsenter import Namespace
-from docker import Client
-from shutil import copy
 utils_dir = os.path.join( os.path.dirname(os.path.realpath(sys.argv[0])), '../utils')
 sys.path.append(utils_dir)
 from OnosCtrl import OnosCtrl
 from OltConfig import OltConfig
+from CordContainer import *
+from CordTestServer import cord_test_server_start, cord_test_server_stop
 
-class docker_netns(object):
-
-    dckr = Client()
-    def __init__(self, name):
-        pid = int(self.dckr.inspect_container(name)['State']['Pid'])
-        if pid == 0:
-            raise Exception('no container named {0}'.format(name))
-        self.pid = pid
-
-    def __enter__(self):
-        pid = self.pid
-        if not os.path.exists('/var/run/netns'):
-            os.mkdir('/var/run/netns')
-        os.symlink('/proc/{0}/ns/net'.format(pid), '/var/run/netns/{0}'.format(pid))
-        return str(pid)
-
-    def __exit__(self, type, value, traceback):
-        pid = self.pid
-        os.unlink('/var/run/netns/{0}'.format(pid))
-
-flatten = lambda l: chain.from_iterable(l)
-
-class Container(object):
-    dckr = Client()
-    def __init__(self, name, image, tag = 'latest', command = 'bash', quagga_config = None):
-        self.name = name
-        self.image = image
-        self.tag = tag
-        self.image_name = image + ':' + tag
-        self.id = None
-        self.command = command
-        if quagga_config is not None:
-            self.bridge = quagga_config['bridge']
-            self.ipaddress = quagga_config['ip']
-            self.mask = quagga_config['mask']
-        else:
-            self.bridge = None
-            self.ipaddress = None
-            self.mask = None
-
-    @classmethod
-    def build_image(cls, dockerfile, tag, force=True, nocache=False):
-        f = io.BytesIO(dockerfile.encode('utf-8'))
-        if force or not cls.image_exists(tag):
-            print('Build {0}...'.format(tag))
-            for line in cls.dckr.build(fileobj=f, rm=True, tag=tag, decode=True, nocache=nocache):
-                if 'stream' in line:
-                    print(line['stream'].strip())
-
-    @classmethod
-    def image_exists(cls, name):
-        return name in [ctn['RepoTags'][0] for ctn in cls.dckr.images()]
-
-    @classmethod
-    def create_host_config(cls, port_list = None, host_guest_map = None, privileged = False):
-        port_bindings = None
-        binds = None
-        if port_list:
-            port_bindings = {}
-            for p in port_list:
-                port_bindings[str(p)] = str(p)
-
-        if host_guest_map:
-            binds = []
-            for h, g in host_guest_map:
-                binds.append('{0}:{1}'.format(h, g))
-
-        return cls.dckr.create_host_config(binds = binds, port_bindings = port_bindings, privileged = privileged)
-
-    @classmethod
-    def cleanup(cls, image):
-        cnt_list = filter(lambda c: c['Image'] == image, cls.dckr.containers())
-        for cnt in cnt_list:
-            print('Cleaning container %s' %cnt['Id'])
-            cls.dckr.kill(cnt['Id'])
-            cls.dckr.remove_container(cnt['Id'], force=True)
-
-    @classmethod
-    def remove_container(cls, name, force=True):
-        try:
-            cls.dckr.remove_container(name, force = force)
-        except: pass
-
-    def exists(self):
-        return '/{0}'.format(self.name) in list(flatten(n['Names'] for n in self.dckr.containers()))
-
-    def img_exists(self):
-        return self.image_name in [ctn['RepoTags'][0] for ctn in self.dckr.images()]
-
-    def ip(self):
-        cnt_list = filter(lambda c: c['Image'] == self.image_name, self.dckr.containers())
-        cnt_settings = cnt_list.pop()
-        return cnt_settings['NetworkSettings']['Networks']['bridge']['IPAddress']
-
-    def kill(self, remove = True):
-        self.dckr.kill(self.name)
-        self.dckr.remove_container(self.name, force=True)
-
-    def start(self, rm = True, ports = None, volumes = None, host_config = None, 
-              environment = None, tty = False, stdin_open = True):
-
-        if rm and self.exists():
-            print('Removing container:', self.name)
-            self.dckr.remove_container(self.name, force=True)
-
-        ctn = self.dckr.create_container(image=self.image_name, ports = ports, command=self.command, 
-                                         detach=True, name=self.name,
-                                         environment = environment, 
-                                         volumes = volumes, 
-                                         host_config = host_config, stdin_open=stdin_open, tty = tty)
-        self.dckr.start(container=self.name)
-        if self.bridge:
-            self.connect_to_br()
-        self.id = ctn['Id']
-        return ctn
-
-    def connect_to_br(self):
-        with docker_netns(self.name) as pid:
-            ip = IPRoute()
-            br = ip.link_lookup(ifname=self.bridge)
-            if len(br) == 0:
-                ip.link_create(ifname=self.bridge, kind='bridge')
-                br = ip.link_lookup(ifname=self.bridge)
-            br = br[0]
-            ip.link('set', index=br, state='up')
-
-            ifs = ip.link_lookup(ifname=self.name)
-            if len(ifs) > 0:
-               ip.link_remove(ifs[0])
-
-            ip.link_create(ifname=self.name, kind='veth', peer=pid)
-            host = ip.link_lookup(ifname=self.name)[0]
-            ip.link('set', index=host, master=br)
-            ip.link('set', index=host, state='up')
-            guest = ip.link_lookup(ifname=pid)[0]
-            ip.link('set', index=guest, net_ns_fd=pid)
-            with Namespace(pid, 'net'):
-                ip = IPRoute()
-                ip.link('set', index=guest, ifname='eth1')
-                ip.addr('add', index=guest, address=self.ipaddress, mask=self.mask)
-                ip.link('set', index=guest, state='up')
-
-    def execute(self, cmd, tty = True, stream = False, shell = False):
-        res = 0
-        if type(cmd) == str:
-            cmds = (cmd,)
-        else:
-            cmds = cmd
-        if shell:
-            for c in cmds:
-                res += os.system('docker exec {0} {1}'.format(self.name, c))
-            return res
-        for c in cmds:
-            i = self.dckr.exec_create(container=self.name, cmd=c, tty = tty, privileged = True)
-            self.dckr.exec_start(i['Id'], stream = stream, detach=True)
-            result = self.dckr.exec_inspect(i['Id'])
-            res += 0 if result['ExitCode'] == None else result['ExitCode']
-        return res
-
-class Onos(Container):
-
-    quagga_config = { 'bridge' : 'quagga-br', 'ip': '10.10.0.4', 'mask' : 16 }
-    env = { 'ONOS_APPS' : 'drivers,openflow,proxyarp,aaa,igmp,vrouter' }
-    ports = [ 8181, 8101, 9876, 6653, 6633, 2000, 2620 ]
-
-    def __init__(self, name = 'cord-onos', image = 'onosproject/onos', tag = 'latest', boot_delay = 60):
-        super(Onos, self).__init__(name, image, tag = tag, quagga_config = self.quagga_config)
-        if not self.exists():
-            self.remove_container(name, force=True)
-            host_config = self.create_host_config(port_list = self.ports)
-            print('Starting ONOS container %s' %self.name)
-            self.start(ports = self.ports, environment = self.env, 
-                       host_config = host_config, tty = True)
-            print('Waiting %d seconds for ONOS to boot' %(boot_delay))
-            time.sleep(boot_delay)
-
-class Radius(Container):
-    ports = [ 1812, 1813 ]
-    env = {'TIMEZONE':'America/Los_Angeles', 
-           'DEBUG': 'true', 'cert_password':'whatever', 'primary_shared_secret':'radius_password'
-           }
-    host_db_dir = os.path.join(os.getenv('HOME'), 'services', 'radius', 'data', 'db')
-    guest_db_dir = os.path.join(os.path.sep, 'opt', 'db')
-    host_config_dir = os.path.join(os.getenv('HOME'), 'services', 'radius', 'freeradius')
-    guest_config_dir = os.path.join(os.path.sep, 'etc', 'freeradius')
-    start_command = '/root/start-radius.py'
-    host_guest_map = ( (host_db_dir, guest_db_dir),
-                       (host_config_dir, guest_config_dir)
-                       )
-    def __init__(self, name = 'cord-radius', image = 'freeradius', tag = 'podd'):
-        super(Radius, self).__init__(name, image, tag = tag, command = self.start_command)
-        if not self.exists():
-            self.remove_container(name, force=True)
-            host_config = self.create_host_config(port_list = self.ports,
-                                                  host_guest_map = self.host_guest_map)
-            volumes = []
-            for _,g in self.host_guest_map:
-                volumes.append(g)
-            self.start(ports = self.ports, environment = self.env, 
-                       volumes = volumes, 
-                       host_config = host_config, tty = True)
+test_server = cord_test_server_start()
 
 class CordTester(Container):
-
     sandbox = '/root/test'
     sandbox_setup = '/root/test/src/test/setup'
     tester_base = os.path.dirname(os.path.realpath(sys.argv[0]))
@@ -356,6 +150,7 @@
 RUN pip install -U nsenter
 RUN pip install -U pyroute2
 RUN pip install -U netaddr
+RUN apt-get -y install arping
 RUN mv /usr/sbin/tcpdump /sbin/
 RUN ln -sf /sbin/tcpdump /usr/sbin/tcpdump
 CMD ["/bin/bash"]
@@ -385,7 +180,6 @@
             self.kill(remove=True)
 
 class Quagga(Container):
-
     quagga_config = { 'bridge' : 'quagga-br', 'ip': '10.10.0.3', 'mask' : 16 }
     ports = [ 179, 2601, 2602, 2603, 2604, 2605, 2606 ]
     host_quagga_config = os.path.join(CordTester.tester_base, 'quagga-config')
@@ -439,6 +233,7 @@
 onos_app_file = os.path.abspath('{0}/../apps/ciena-cordigmp-'.format(cord_tester_base) + onos_app_version + '.oar')
 
 def runTest(args):
+    global test_server
     onos_cnt = {'tag':'latest'}
     radius_cnt = {'tag':'latest'}
     nose_cnt = {'image': 'cord-test/nose','tag': 'latest'}
@@ -507,6 +302,7 @@
     test_cnt.setup_intfs()
     tests = args.test_type.split('-')
     test_cnt.run_tests(tests)
+    cord_test_server_stop(test_server)
 
 if __name__ == '__main__':
     parser = ArgumentParser(description='Cord Tester for ONOS')
diff --git a/src/test/setup/quagga-config/start.sh b/src/test/setup/quagga-config/start.sh
index 5b140ca..77e342b 100755
--- a/src/test/setup/quagga-config/start.sh
+++ b/src/test/setup/quagga-config/start.sh
@@ -2,4 +2,5 @@
 ulimit -n 65536
 ip a add 10.10.0.3/16 dev eth1
 #bgpd -u root -f /root/config/bgpd.conf &
-/usr/local/sbin/zebra -u root -f /root/config/testrib.conf
+conf_file=${1:-/root/config/testrib.conf}
+/usr/local/sbin/zebra -u root -f $conf_file
diff --git a/src/test/setup/quagga-config/testrib.conf b/src/test/setup/quagga-config/testrib.conf
index 2a02337..af2f213 100644
--- a/src/test/setup/quagga-config/testrib.conf
+++ b/src/test/setup/quagga-config/testrib.conf
@@ -15,37 +15,6 @@
 
 ! statics that should be subsumed by connected routes, according to interface
 ! state
-ip route 50.10.0.0/24 172.17.0.4
-ip route 50.10.0.0/24 172.17.0.3
-ip route 50.10.0.0/24 172.17.0.2
-ip route 60.10.0.0/24 172.17.0.4
-ip route 60.10.0.0/24 172.17.0.3
-ip route 70.10.0.0/24 172.17.0.4
-ip route 70.10.0.0/24 172.17.0.3
-ip route 80.10.0.0/24 172.17.0.4
-ip route 80.10.0.0/24 172.17.0.3
-ip route 90.10.0.0/24 172.17.0.4
-ip route 90.10.0.0/24 172.17.0.3
-ip route 100.10.0.0/24 172.17.0.4
-ip route 100.10.0.0/24 172.17.0.3
-ip route 120.10.0.0/24 172.17.0.4
-ip route 120.10.0.0/24 172.17.0.3
-ip route 50.10.0.0/24 172.17.0.6
-ip route 50.10.0.0/24 172.17.0.3
-ip route 50.10.0.0/24 172.17.0.2
-ip route 50.10.0.0/24 172.17.0.4
-ip route 60.10.0.0/24 172.17.0.7
-ip route 60.10.0.0/24 172.17.0.3
-ip route 60.10.0.0/24 172.17.0.4
-ip route 70.10.0.0/24 172.17.0.1
-ip route 70.10.0.0/24 172.17.0.3
-ip route 70.10.0.0/24 172.17.0.2
-ip route 80.10.0.0/24 172.17.0.2
-ip route 80.10.0.0/24 172.17.0.3
-ip route 80.10.0.0/24 172.17.0.4
-ip route 90.10.0.0/24 172.17.0.3
-ip route 90.10.0.0/24 172.17.0.2
-ip route 90.10.0.0/24 172.17.0.4
 line vty
  exec-timeout 0 0
 !
diff --git a/src/test/utils/CordContainer.py b/src/test/utils/CordContainer.py
new file mode 100644
index 0000000..4d713d7
--- /dev/null
+++ b/src/test/utils/CordContainer.py
@@ -0,0 +1,235 @@
+import os,time
+import io
+import json
+from pyroute2 import IPRoute
+from itertools import chain
+from nsenter import Namespace
+from docker import Client
+from shutil import copy
+
+class docker_netns(object):
+
+    dckr = Client()
+    def __init__(self, name):
+        pid = int(self.dckr.inspect_container(name)['State']['Pid'])
+        if pid == 0:
+            raise Exception('no container named {0}'.format(name))
+        self.pid = pid
+
+    def __enter__(self):
+        pid = self.pid
+        if not os.path.exists('/var/run/netns'):
+            os.mkdir('/var/run/netns')
+        os.symlink('/proc/{0}/ns/net'.format(pid), '/var/run/netns/{0}'.format(pid))
+        return str(pid)
+
+    def __exit__(self, type, value, traceback):
+        pid = self.pid
+        os.unlink('/var/run/netns/{0}'.format(pid))
+
+flatten = lambda l: chain.from_iterable(l)
+
+class Container(object):
+    dckr = Client()
+    def __init__(self, name, image, tag = 'latest', command = 'bash', quagga_config = None):
+        self.name = name
+        self.image = image
+        self.tag = tag
+        self.image_name = image + ':' + tag
+        self.id = None
+        self.command = command
+        if quagga_config is not None:
+            self.bridge = quagga_config['bridge']
+            self.ipaddress = quagga_config['ip']
+            self.mask = quagga_config['mask']
+        else:
+            self.bridge = None
+            self.ipaddress = None
+            self.mask = None
+
+    @classmethod
+    def build_image(cls, dockerfile, tag, force=True, nocache=False):
+        f = io.BytesIO(dockerfile.encode('utf-8'))
+        if force or not cls.image_exists(tag):
+            print('Build {0}...'.format(tag))
+            for line in cls.dckr.build(fileobj=f, rm=True, tag=tag, decode=True, nocache=nocache):
+                if 'stream' in line:
+                    print(line['stream'].strip())
+
+    @classmethod
+    def image_exists(cls, name):
+        return name in [ctn['RepoTags'][0] for ctn in cls.dckr.images()]
+
+    @classmethod
+    def create_host_config(cls, port_list = None, host_guest_map = None, privileged = False):
+        port_bindings = None
+        binds = None
+        if port_list:
+            port_bindings = {}
+            for p in port_list:
+                port_bindings[str(p)] = str(p)
+
+        if host_guest_map:
+            binds = []
+            for h, g in host_guest_map:
+                binds.append('{0}:{1}'.format(h, g))
+
+        return cls.dckr.create_host_config(binds = binds, port_bindings = port_bindings, privileged = privileged)
+
+    @classmethod
+    def cleanup(cls, image):
+        cnt_list = filter(lambda c: c['Image'] == image, cls.dckr.containers())
+        for cnt in cnt_list:
+            print('Cleaning container %s' %cnt['Id'])
+            cls.dckr.kill(cnt['Id'])
+            cls.dckr.remove_container(cnt['Id'], force=True)
+
+    @classmethod
+    def remove_container(cls, name, force=True):
+        try:
+            cls.dckr.remove_container(name, force = force)
+        except: pass
+
+    def exists(self):
+        return '/{0}'.format(self.name) in list(flatten(n['Names'] for n in self.dckr.containers()))
+
+    def img_exists(self):
+        return self.image_name in [ctn['RepoTags'][0] for ctn in self.dckr.images()]
+
+    def ip(self):
+        cnt_list = filter(lambda c: c['Image'] == self.image_name, self.dckr.containers())
+        cnt_settings = cnt_list.pop()
+        return cnt_settings['NetworkSettings']['Networks']['bridge']['IPAddress']
+
+    def kill(self, remove = True):
+        self.dckr.kill(self.name)
+        self.dckr.remove_container(self.name, force=True)
+
+    def start(self, rm = True, ports = None, volumes = None, host_config = None, 
+              environment = None, tty = False, stdin_open = True):
+
+        if rm and self.exists():
+            print('Removing container:', self.name)
+            self.dckr.remove_container(self.name, force=True)
+
+        ctn = self.dckr.create_container(image=self.image_name, ports = ports, command=self.command, 
+                                         detach=True, name=self.name,
+                                         environment = environment, 
+                                         volumes = volumes, 
+                                         host_config = host_config, stdin_open=stdin_open, tty = tty)
+        self.dckr.start(container=self.name)
+        if self.bridge:
+            self.connect_to_br()
+        self.id = ctn['Id']
+        return ctn
+
+    def connect_to_br(self):
+        with docker_netns(self.name) as pid:
+            ip = IPRoute()
+            br = ip.link_lookup(ifname=self.bridge)
+            if len(br) == 0:
+                ip.link_create(ifname=self.bridge, kind='bridge')
+                br = ip.link_lookup(ifname=self.bridge)
+            br = br[0]
+            ip.link('set', index=br, state='up')
+
+            ifs = ip.link_lookup(ifname=self.name)
+            if len(ifs) > 0:
+               ip.link_remove(ifs[0])
+
+            ip.link_create(ifname=self.name, kind='veth', peer=pid)
+            host = ip.link_lookup(ifname=self.name)[0]
+            ip.link('set', index=host, master=br)
+            ip.link('set', index=host, state='up')
+            guest = ip.link_lookup(ifname=pid)[0]
+            ip.link('set', index=guest, net_ns_fd=pid)
+            with Namespace(pid, 'net'):
+                ip = IPRoute()
+                ip.link('set', index=guest, ifname='eth1')
+                ip.addr('add', index=guest, address=self.ipaddress, mask=self.mask)
+                ip.link('set', index=guest, state='up')
+
+    def execute(self, cmd, tty = True, stream = False, shell = False):
+        res = 0
+        if type(cmd) == str:
+            cmds = (cmd,)
+        else:
+            cmds = cmd
+        if shell:
+            for c in cmds:
+                res += os.system('docker exec {0} {1}'.format(self.name, c))
+            return res
+        for c in cmds:
+            i = self.dckr.exec_create(container=self.name, cmd=c, tty = tty, privileged = True)
+            self.dckr.exec_start(i['Id'], stream = stream, detach=True)
+            result = self.dckr.exec_inspect(i['Id'])
+            res += 0 if result['ExitCode'] == None else result['ExitCode']
+        return res
+
+class Onos(Container):
+
+    quagga_config = { 'bridge' : 'quagga-br', 'ip': '10.10.0.4', 'mask' : 16 }
+    env = { 'ONOS_APPS' : 'drivers,openflow,proxyarp,aaa,igmp,vrouter,fwd' }
+    ports = [ 8181, 8101, 9876, 6653, 6633, 2000, 2620 ]
+    host_config_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), '..', 'setup/onos-config')
+    guest_config_dir = '/root/onos/config'
+    host_guest_map = ( (host_config_dir, guest_config_dir), )
+
+    def __init__(self, name = 'cord-onos', image = 'onosproject/onos', tag = 'latest', 
+                 boot_delay = 60, restart = False, network_cfg = None):
+        if restart is True:
+            ##Find the right image to restart
+            running_image = filter(lambda c: c['Names'][0] == '/{}'.format(name), self.dckr.containers())
+            if running_image:
+                image_name = running_image[0]['Image']
+                try:
+                    image = image_name.split(':')[0]
+                    tag = image_name.split(':')[1]
+                except: pass
+
+        super(Onos, self).__init__(name, image, tag = tag, quagga_config = self.quagga_config)
+        if restart is True and self.exists():
+            self.kill()
+        if not self.exists():
+            self.remove_container(name, force=True)
+            host_config = self.create_host_config(port_list = self.ports,
+                                                  host_guest_map = self.host_guest_map)
+            volumes = []
+            for _,g in self.host_guest_map:
+                volumes.append(g)
+            if network_cfg is not None:
+                json_data = json.dumps(network_cfg)
+                with open('{}/network-cfg.json'.format(self.host_config_dir), 'w') as f:
+                    f.write(json_data)
+            print('Starting ONOS container %s' %self.name)
+            self.start(ports = self.ports, environment = self.env, 
+                       host_config = host_config, volumes = volumes, tty = True)
+            print('Waiting %d seconds for ONOS to boot' %(boot_delay))
+            time.sleep(boot_delay)
+
+class Radius(Container):
+    ports = [ 1812, 1813 ]
+    env = {'TIMEZONE':'America/Los_Angeles', 
+           'DEBUG': 'true', 'cert_password':'whatever', 'primary_shared_secret':'radius_password'
+           }
+    host_db_dir = os.path.join(os.getenv('HOME'), 'services', 'radius', 'data', 'db')
+    guest_db_dir = os.path.join(os.path.sep, 'opt', 'db')
+    host_config_dir = os.path.join(os.getenv('HOME'), 'services', 'radius', 'freeradius')
+    guest_config_dir = os.path.join(os.path.sep, 'etc', 'freeradius')
+    start_command = '/root/start-radius.py'
+    host_guest_map = ( (host_db_dir, guest_db_dir),
+                       (host_config_dir, guest_config_dir)
+                       )
+    def __init__(self, name = 'cord-radius', image = 'freeradius', tag = 'podd'):
+        super(Radius, self).__init__(name, image, tag = tag, command = self.start_command)
+        if not self.exists():
+            self.remove_container(name, force=True)
+            host_config = self.create_host_config(port_list = self.ports,
+                                                  host_guest_map = self.host_guest_map)
+            volumes = []
+            for _,g in self.host_guest_map:
+                volumes.append(g)
+            self.start(ports = self.ports, environment = self.env, 
+                       volumes = volumes, 
+                       host_config = host_config, tty = True)
+
diff --git a/src/test/utils/CordTestServer.py b/src/test/utils/CordTestServer.py
new file mode 100644
index 0000000..75acf3d
--- /dev/null
+++ b/src/test/utils/CordTestServer.py
@@ -0,0 +1,48 @@
+import SocketServer as socketserver
+import threading
+import socket
+from CordContainer import Onos
+from nose.tools import nottest
+
+##Server to handle container restart requests from test container.
+##Used now to restart ONOS from vrouter test container
+
+CORD_TEST_HOST = '172.17.0.1'
+CORD_TEST_PORT = 25000
+
+class CordTestServer(socketserver.BaseRequestHandler):
+
+    def handle(self):
+        data = self.request.recv(1024).strip()
+        if data == 'RESTART_ONOS':
+            print('Restarting ONOS')
+            onos = Onos(restart = True)
+            self.request.sendall('DONE')
+
+class ThreadedTestServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
+    pass
+
+@nottest
+def cord_test_server_start():
+    server = ThreadedTestServer( (CORD_TEST_HOST, CORD_TEST_PORT), CordTestServer)
+    task = threading.Thread(target = server.serve_forever)
+    ##terminate when main thread exits
+    task.daemon = True
+    task.start()
+    return server
+
+@nottest
+def cord_test_server_stop(server):
+    server.shutdown()
+    server.server_close()
+
+@nottest
+def cord_test_onos_restart():
+    '''Send ONOS restart to server'''
+    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+    s.connect( (CORD_TEST_HOST, CORD_TEST_PORT) )
+    s.sendall('RESTART_ONOS\n')
+    data = s.recv(1024).strip()
+    if data == 'DONE':
+        return True
+    return False
diff --git a/src/test/utils/OnosFlowCtrl.py b/src/test/utils/OnosFlowCtrl.py
index 1956392..323a720 100644
--- a/src/test/utils/OnosFlowCtrl.py
+++ b/src/test/utils/OnosFlowCtrl.py
@@ -4,6 +4,12 @@
 from nose.tools import *
 from scapy.all import *
 from OnosCtrl import OnosCtrl
+import fcntl, socket, struct
+
+def get_mac(iface = 'ovsbr0', pad = 4):
+    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+    info = fcntl.ioctl(s.fileno(), 0x8927, struct.pack('256s', iface[:15]))
+    return '0'*pad + ''.join(['%02x' %ord(char) for char in info[18:24]])
 
 class OnosFlowCtrl:
 
diff --git a/src/test/vrouter/__init__.py b/src/test/vrouter/__init__.py
new file mode 100644
index 0000000..a42b024
--- /dev/null
+++ b/src/test/vrouter/__init__.py
@@ -0,0 +1,11 @@
+import os,sys
+##add the python path to lookup the utils
+working_dir = os.path.dirname(os.path.realpath(sys.argv[-1]))
+utils_dir = os.path.join(working_dir, '../utils')
+fsm_dir = os.path.join(working_dir, '../fsm')
+cli_dir = os.path.join(working_dir, '../cli')
+subscriber_dir = os.path.join(working_dir, '../subscriber')
+__path__.append(utils_dir)
+__path__.append(fsm_dir)
+__path__.append(cli_dir)
+__path__.append(subscriber_dir)
diff --git a/src/test/vrouter/vrouterTest.py b/src/test/vrouter/vrouterTest.py
new file mode 100644
index 0000000..945539f
--- /dev/null
+++ b/src/test/vrouter/vrouterTest.py
@@ -0,0 +1,285 @@
+import unittest
+from nose.tools import *
+from scapy.all import *
+from OnosCtrl import OnosCtrl
+from OltConfig import OltConfig
+from OnosFlowCtrl import OnosFlowCtrl, get_mac
+from onosclidriver import OnosCliDriver
+from CordContainer import Container, Onos
+from CordTestServer import cord_test_onos_restart
+from portmaps import g_subscriber_port_map
+import threading
+import time
+import os
+import json
+log.setLevel('INFO')
+
+class Quagga(Container):
+    quagga_config = '/root/config'
+    def __init__(self, name = 'cord-quagga', image = 'cord-test/quagga', tag = 'latest'):
+        super(Quagga, self).__init__(name, image, tag = tag)
+        if not self.exists():
+            raise Exception('Quagga container was not started by cord-test')
+        
+class vrouter_exchange(unittest.TestCase):
+
+    apps = ('org.onosproject.vrouter', 'org.onosproject.fwd')
+    device_id = 'of:' + get_mac('ovsbr0')
+    vrouter_device_dict = { "devices" : {
+                "{}".format(device_id) : {
+                    "basic" : {
+                        "driver" : "softrouter"
+                    }
+                }
+             },
+          }
+    zebra_conf = '''
+password zebra
+log stdout
+service advanced-vty
+!
+debug zebra rib
+debug zebra kernel
+debug zebra fpm
+!
+!interface eth1
+! ip address 10.10.0.3/16
+line vty
+ exec-timeout 0 0
+'''
+    test_path = os.path.dirname(os.path.realpath(__file__))
+    quagga_config_path = os.path.join(test_path, '..', 'setup/quagga-config')
+    onos_config_path = os.path.join(test_path, '..', 'setup/onos-config')
+    GATEWAY = '172.17.0.50'
+    MAX_PORTS = 100
+
+    @classmethod
+    def setUpClass(cls):
+        ''' Activate the vrouter apps'''
+        cls.olt = OltConfig()
+        cls.port_map = cls.olt.olt_port_map()
+        if not cls.port_map:
+            cls.port_map = g_subscriber_port_map
+        cls.vrouter_host_load(host = cls.GATEWAY)
+        time.sleep(3)
+        
+    @classmethod
+    def tearDownClass(cls):
+        '''Deactivate the vrouter apps'''
+        cls.vrouter_host_unload()
+
+    def cliEnter(self):
+        retries = 0
+        while retries < 3:
+            self.cli = OnosCliDriver(connect = True)
+            if self.cli.handle:
+                break
+            else:
+                retries += 1
+                time.sleep(2)
+
+    def cliExit(self):
+        self.cli.disconnect()
+
+    @classmethod
+    def onos_load_config(cls, config):
+        status, code = OnosCtrl.config(config)
+        if status is False:
+            log.info('JSON request returned status %d' %code)
+            assert_equal(status, True)
+
+    @classmethod
+    def vrouter_config_get(cls, networks = 4):
+        vrouter_configs = cls.generate_vrouter_conf(networks = networks)
+        return vrouter_configs
+        ##ONOS router does not support dynamic reconfigurations
+        #for config in vrouter_configs:
+        #    cls.onos_load_config(config)
+        #    time.sleep(5)
+
+    @classmethod
+    def vrouter_host_load(cls, host=GATEWAY, iface = 'veth0'):
+        config_cmds = ( 'ifconfig {0} {1}'.format(iface, host),
+                        'arping -I {0} {1} -c 2'.format(iface, host),
+                        )
+        for cmd in config_cmds:
+            os.system(cmd)
+
+    @classmethod
+    def vrouter_host_unload(cls, iface='veth0'):
+        config_cmds = ('ifconfig {} 0'.format(iface), )
+        for cmd in config_cmds:
+            os.system(cmd)
+
+    @classmethod
+    def start_onos(cls, network_cfg = None):
+        if type(network_cfg) is tuple:
+            res = []
+            for v in network_cfg:
+                res += v.items()
+            config = dict(res)
+        else:
+            config = network_cfg
+        log.info('Restarting ONOS with new network configuration')
+        cfg = json.dumps(config)
+        with open('{}/network-cfg.json'.format(cls.onos_config_path), 'w') as f:
+            f.write(cfg)
+
+        return cord_test_onos_restart()
+
+    @classmethod
+    def start_quagga(cls, stop = True, networks = 4, gateway = GATEWAY):
+        quagga = Quagga()
+        log.info('Starting Quagga on container %s with %d networks' %(quagga.name, networks))
+        if stop is True:
+            quagga.execute('{}/stop.sh'.format(Quagga.quagga_config))
+        config = cls.generate_conf(networks = networks, gateway = gateway)
+        with open('{}/testrib_gen.conf'.format(cls.quagga_config_path), 'w') as f:
+            f.write(config)
+        quagga.execute('{0}/start.sh {1}/testrib_gen.conf'.format(Quagga.quagga_config, Quagga.quagga_config))
+        time.sleep(10)
+
+    @classmethod
+    def generate_vrouter_conf(cls, networks = 4):
+        num = 0
+        start_network = ( 11 << 24) | ( 0 << 16) | ( 0 << 8) | 0
+        end_network =   ( 200 << 24 ) | ( 0 << 16)  | (0 << 8) | 0
+        ports_dict = { 'ports' : {} }
+        interface_list = []
+        for n in xrange(start_network, end_network):
+            if n & 255 == 0:
+                port_map = ports_dict['ports']
+                port = num + 1 if num < cls.MAX_PORTS - 1 else cls.MAX_PORTS - 1
+                device_port_key = '{0}/{1}'.format(cls.device_id, port)
+                try:
+                    interfaces = port_map[device_port_key]['interfaces']
+                except:
+                    port_map[device_port_key] = { 'interfaces' : [] }
+                    interfaces = port_map[device_port_key]['interfaces']
+                    
+                ips = '%d.%d.%d.2/24'%( (n >> 24) & 0xff, ( ( n >> 16) & 0xff ), ( (n >> 8 ) & 0xff ) )
+                if num < cls.MAX_PORTS - 1:
+                    interface_dict = { 'name' : 'b1-{}'.format(port), 'ips': [ips], 'mac' : '00:00:00:00:00:01' }
+                    interfaces.append(interface_dict)
+                    interface_list.append(interface_dict['name'])
+                else:
+                    interfaces[0]['ips'].append(ips)
+                num += 1
+                if num == networks:
+                    break
+        quagga_dict = { 'apps': { 'org.onosproject.router' : { 'router' : {} } } }
+        quagga_router_dict = quagga_dict['apps']['org.onosproject.router']['router']
+        quagga_router_dict['ospfEnabled'] = True
+        quagga_router_dict['interfaces'] = interface_list
+        quagga_router_dict['controlPlaneConnectPoint'] = '{0}/{1}'.format(cls.device_id, 
+                                                                          networks + 1 if networks < cls.MAX_PORTS else cls.MAX_PORTS )
+        return (cls.vrouter_device_dict, ports_dict, quagga_dict)
+
+    @classmethod
+    def generate_conf(cls, networks = 4, gateway = GATEWAY):
+        num = 0
+        start_network = ( 11 << 24) | ( 0 << 16) | ( 0 << 8) | 0
+        end_network =   ( 200 << 24 ) | ( 0 << 16)  | (0 << 8) | 0
+        net_list = []
+        for n in xrange(start_network, end_network):
+            if n & 255 == 0:
+                net = '%d.%d.%d.0'%( (n >> 24) & 0xff, ( ( n >> 16) & 0xff ), ( (n >> 8 ) & 0xff ) )
+                net_route = 'ip route {0}/24 {1}'.format(net, gateway)
+                net_list.append(net_route)
+                num += 1
+            if num == networks:
+                break
+        zebra_routes = '\n'.join(net_list)
+        log.info('Zebra routes: \n:%s\n' %cls.zebra_conf + zebra_routes)
+        return cls.zebra_conf + zebra_routes
+    
+    @classmethod
+    def vrouter_activate(cls, deactivate = False):
+        app = 'org.onosproject.vrouter'
+        onos_ctrl = OnosCtrl(app)
+        if deactivate is True:
+            onos_ctrl.deactivate()
+        else:
+            onos_ctrl.activate()
+        time.sleep(3)
+
+    @classmethod
+    def vrouter_configure(cls, networks = 4):
+        ##Deactivate vrouter
+        vrouter_configs = cls.vrouter_config_get(networks = networks)
+        #cls.start_onos(network_cfg = vrouter_configs)
+        ##Start quagga with 4 networks
+        #cls.start_quagga(networks = networks, stop = True, gateway = cls.GATEWAY)
+        return vrouter_configs
+    
+    def vrouter_port_send_recv(self, ingress, egress, dst_mac, dst_ip):
+        src_mac = '00:00:00:00:00:02'
+        src_ip = '172.17.0.100'
+        self.success = False
+        def recv_task():
+            def recv_cb(pkt):
+                log.info('Pkt seen with ingress ip %s, egress ip %s' %(pkt[IP].src, pkt[IP].dst))
+                self.success = True
+            sniff(count=2, timeout=5, 
+                  lfilter = lambda p: IP in p and p[IP].dst == dst_ip and p[IP].src == src_ip,
+                  prn = recv_cb, iface = self.port_map[egress])
+
+        t = threading.Thread(target = recv_task)
+        t.start()
+        L2 = Ether(src = src_mac, dst = dst_mac)
+        L3 = IP(src = src_ip, dst = dst_ip)
+        pkt = L2/L3
+        log.info('Sending a packet with dst ip %s, dst mac %s on port %s to verify if flows are correct' %
+                 (dst_ip, dst_mac, self.port_map[ingress]))
+        sendp(pkt, count=50, iface = self.port_map[ingress])
+        t.join()
+        assert_equal(self.success, True)
+
+    def vrouter_traffic_verify(self, ports_dict, egress_dict):
+        egress = int(egress_dict['apps']['org.onosproject.router']['router']['controlPlaneConnectPoint'].split('/')[1])
+        for dev in ports_dict['ports'].keys():
+            for intf in ports_dict['ports'][dev]['interfaces']:
+                for ip in intf['ips']:
+                    dst_ip = ip.split('/')[0]
+                    dst_mac = intf['mac']
+                    port = intf['name']
+                    ingress = int(port.split('-')[1])
+                    ##Verify if flows are setup by sending traffic across
+                    self.vrouter_port_send_recv(ingress, egress, dst_mac, dst_ip)
+
+    def __vrouter_network_verify(self, networks):
+        _, ports_map, egress_map = self.vrouter_configure(networks = networks)
+        self.cliEnter()
+        ##Now verify
+        hosts = json.loads(self.cli.hosts(jsonFormat = True))
+        log.info('Discovered hosts: %s' %hosts)
+        routes = json.loads(self.cli.routes(jsonFormat = True))
+        log.info('Routes: %s' %routes)
+        #assert_equal(len(routes['routes4']), networks)
+        flows = json.loads(self.cli.flows(jsonFormat = True))
+        flows = filter(lambda f: f['flows'], flows)
+        #log.info('Flows: %s' %flows)
+        assert_not_equal(len(flows), 0)
+        self.vrouter_traffic_verify(ports_map, egress_map)
+        self.cliExit()
+        return True
+
+    def test_vrouter_1(self):
+        '''Test vrouter with 5 routes'''
+        res = self.__vrouter_network_verify(5)
+        assert_equal(res, True)
+
+    def test_vrouter_2(self):
+        '''Test vrouter with 20 routes'''
+        res = self.__vrouter_network_verify(50)
+        assert_equal(res, True)
+
+    def test_vrouter_3(self):
+        '''Test vrouter with 100 routes'''
+        res = self.__vrouter_network_verify(100)
+        assert_equal(res, True)
+
+    def test_vrouter_4(self):
+        '''Test vrouter with 200 routes'''
+        res = self.__vrouter_network_verify(300)
+        assert_equal(res, True)