Initial set of Fabric switch test cases

Change-Id: I86fd2b67d3b773aa496f5ef61f1e1fdf51fd9925
diff --git a/Fabric/Utilities/tools/ovs-ctl/README b/Fabric/Utilities/tools/ovs-ctl/README
new file mode 100644
index 0000000..b2378f7
--- /dev/null
+++ b/Fabric/Utilities/tools/ovs-ctl/README
@@ -0,0 +1,212 @@
+###############################################################################
+#
+# ovs-ctl.py
+#
+###############################################################################
+
+ovs-ctl manages the initialization and execution of OVS instances as targets
+for OFTest execution. 
+
+
+-------------------------------------------------------------------------------
+INSTALLATION
+-------------------------------------------------------------------------------
+
+ovs-ctl requires OVS be built and installed on your local machine. 
+If you are new to OVS, the preferred method is:
+
+1. Download openvswitch-X.Y.Z from http://openvswitch.org/releases
+2. Untar, configure, build, and install openvswitch into a useful location:
+
+   # All OVS installations will go in to /opt/ovs:
+   > mkdir -p /opt/ovs
+   
+   # All OVS Source distributions will live in /opt/ovs/src:
+   > mkdir -p /opt/ovs/src
+
+   # Download and untar source for openvswitch 1.4.0:
+   > curl http://openvswitch.org/releases/openvswitch-1.4.0.tar.gz | tar -xzC /opt/ovs/src
+
+   # build and install:
+   > cd /opt/ovs/openvswitch-1.4.0
+   > ./configure --prefix=/opt/ovs/1.4.0 --with-linux=/lib/modules/`uname -r`/build
+   > make
+   > sudo make install
+
+   # Copy the OVS kernel module out of the build tree into the install tree:
+   > sudo cp /opt/ovs/src/openvswitch-1.4.0/datapath/linux/openvswitch_mod.ko /opt/ovs/1.4.0/sbin
+
+
+3. READ the comments and instructions in ovs-ctl-default.example.conf
+
+4. Copy ovs-ctl-default.example.conf from the local directory to /opt/ovs:
+   
+   > sudo cp ovs-ctl-default.example.conf /opt/ovs/ovs-ctl-default.conf
+
+5. Modify /opt/ovs/ovs-ctl-default.conf to match your existing installation(s). 
+   If you followed the directions and used the paths suggested in Step 2, then the default 
+   configuration file should work without modification. 
+   Otherwise, edit to point to your installation directorie(s). 
+
+
+
+-------------------------------------------------------------------------------
+EXAMPLE USAGE
+-------------------------------------------------------------------------------
+
+You can initialize and run your default configuration (as specified in the config files) as follows:
+
+> ./ovs-ctl
+
+You can stop a running configuration as follows:
+
+> ./ovs-ctl --kill
+
+You can initialize and run any configuration (as specified in the config files) as follows:
+
+> ./ovs-ctl --config 1.3.0
+> ./ovs-ctl --config 1.4.0
+> ./ovs-ctl --config MySomeOtherConfiguration
+
+You can output logging and verbose information with the --log and --verbose options. 
+
+By default, OVS is initialized with 4 veth ports. You can change this with the --port-count option. 
+
+
+
+CONFIG FILES
+------------
+
+The configuration file options are just convenient methods of storing values for the command line
+arguments. Every command line argument can be specified as a key in your configuration file. 
+
+You do not need a configuration file at all -- you can specify all required paths and values
+from the command line -- but this is not recommended for regular usage. 
+
+The precedence for these settings is in the following order:
+
+1. Command Line option, if specified, THEN
+2. The [ConfigName] section of all config files, both default, user, or command-line specified, THEN
+3. The [Defaults] section of all config files
+
+
+Note that you may have a section defined in the ovs-ctl-default.conf file, AND in your ~/.ovs-ctl file. 
+The settings will be merged together, with the values in ~/.ovs-ctl taking precedence:
+
+So, for example, you can have the local installation information for 1.4.0 specified in /opt/ovs/ovs-ctl-default.conf as follows:
+
+    [1.4.0]
+    # ovs-1.4.0, configured and built into /opt/ovs/1.4.0
+    # Can be selected with 'ovs-ctl.py --config 1.4.0'
+    ovs_src_dir:/opt/ovs/src/openvswitch-1.4.0
+    ovs_base_dir:/opt/ovs/1.4.0
+    ovs_runtime_dir:/var/run/ovs/1.4.0
+
+This can be used by everyone. 
+
+You can also have user-specific settings in ~/.ovs-ctl for your own execution:
+
+    [1.4.0]
+    # Put logfiles for my personal runs in my ~/ovs-logfiles directory:
+    ovs_vswitchd_log=~/.ovs-logfiles/vswitchd.log
+
+
+
+-------------------------------------------------------------------------------
+OPTIONS AND HELP
+-------------------------------------------------------------------------------
+
+This documentation is minimal.
+
+Please see ./ovs-ctl --help for a full list of options:
+
+usage: ovs-ctl.py [-h] [-cf FILE [FILE ...]] [-c CONFIG] [-d FILE] [-nd]
+                  [--dump-config] [--ovs-vswitchd-schema OVS_VSWITCHD_SCHEMA]
+                  [--ovs-vswitchd-log OVS_VSWITCHD_LOG]
+                  [--ovs-vswitchd OVS_VSWITCHD] [--ovs-vsctl OVS_VSCTL]
+                  [--ovs-ofctl OVS_OFCTL] [--ovsdb-tool OVSDB_TOOL]
+                  [--ovsdb-server OVSDB_SERVER] [--ovs-kmod OVS_KMOD]
+                  [--ovs-src-dir OVS_SRC_DIR] [--ovs-log-dir OVS_LOG_DIR]
+                  [--ovs-version OVS_VERSION] [--ovs-base-dir OVS_BASE_DIR]
+                  [--ovs-runtime-dir OVS_RUNTIME_DIR]
+                  [--ovs-db-sock OVS_DB_SOCK] [--ovs-db-file OVS_DB_FILE]
+                  [--dry] [--log] [--verbose] [--kill] [--keep-veths]
+                  [--no-kmod] [--vlog] [-p PORT_COUNT] [--bridge BRIDGE]
+                  [--cip CIP] [--cport CPORT] [--max_backoff MAX_BACKOFF]
+                  [--keep-db]
+
+optional arguments:
+  -h, --help            show this help message and exit
+  -cf FILE [FILE ...], --config-file FILE [FILE ...]
+                        Load settings from the given config file
+  -c CONFIG, --config CONFIG
+                        Use the specified configuration section
+  -d FILE, --default-config-file FILE
+                        Location of the local default config file
+  -nd, --no-default     Do not load the default config file
+  --dump-config         Dump the loaded configuration settings
+  --ovs-vswitchd-schema OVS_VSWITCHD_SCHEMA
+                        Path to the vswitchd.ovsschema file
+  --ovs-vswitchd-log OVS_VSWITCHD_LOG
+                        Path to the vswitchd log file
+  --ovs-vswitchd OVS_VSWITCHD
+                        Path to the target ovs-vswitchd binary
+  --ovs-vsctl OVS_VSCTL
+                        Path to the target ovs-vsctl binary
+  --ovs-ofctl OVS_OFCTL
+                        Path to the target ovs-ofctl binary
+  --ovsdb-tool OVSDB_TOOL
+                        Path to the target ovsdb-tool binary
+  --ovsdb-server OVSDB_SERVER
+                        Path to the target ovsdb-server binary
+  --ovs-kmod OVS_KMOD   Path to the OVS kernel module
+  --ovs-src-dir OVS_SRC_DIR
+                        Directory for the OVS Source Files
+  --ovs-log-dir OVS_LOG_DIR
+                        Directory for the OVS Runtime Log Files
+  --ovs-version OVS_VERSION
+  --ovs-base-dir OVS_BASE_DIR
+                        OVS Base Installation Directory
+  --ovs-runtime-dir OVS_RUNTIME_DIR
+                        OVS Runtime Directory
+  --ovs-db-sock OVS_DB_SOCK
+                        Domain Socket Location
+  --ovs-db-file OVS_DB_FILE
+                        Location for the OVS database file
+  --dry                 Dry run only. Don't actually do anything
+  --log                 Enable logging
+  --verbose             Enable verbose output information
+  --kill                Kill running OVS
+  --keep-veths          By default, all existing veths will be destroyed and
+                        the veth module removed before initializing. If you
+                        don't want the veth module removed, specify this
+                        argument. Your mileage may vary if you use this.
+  --no-kmod             Do not attempt to insert or remove the OVS kernel
+                        module. Your mileage may vary.
+  --vlog                Tail the running vswitch.log file in a new xterm
+  -p PORT_COUNT, --port-count PORT_COUNT
+                        Number of veth ports to connect.
+  --bridge BRIDGE       Name of OF OVS Bridge
+  --cip CIP             Controller Connection
+  --cport CPORT         Controller Port
+  --max_backoff MAX_BACKOFF
+                        VSwitchD max backoff value
+  --keep-db             By default, a new database is initialized at each
+                        execution. If you want to keep and use the old
+                        database (if it exists), use this option
+
+
+
+
+-------------------------------------------------------------------------------
+TODO
+-------------------------------------------------------------------------------
+
+1. Better documentation. 
+2. Option for automatic downloading, configuration, and installation of OVS. 
+3. Symlinks or alias generation for selecting the correct ovs-* tools for
+   debugging the running configuration. 
+
+
+
+
diff --git a/Fabric/Utilities/tools/ovs-ctl/ovs-ctl-default.example.conf b/Fabric/Utilities/tools/ovs-ctl/ovs-ctl-default.example.conf
new file mode 100644
index 0000000..2996dce
--- /dev/null
+++ b/Fabric/Utilities/tools/ovs-ctl/ovs-ctl-default.example.conf
@@ -0,0 +1,96 @@
+###############################################################################
+#
+# This is the example/default ovs-ctl config file. 
+#
+# ovs-ctl config files will be searched and read, by default, int he following
+# order:
+#
+# /opt/ovs/ovs-ctl-default.conf
+# ~/.ovs-ctl
+#
+# This behavior can be modified and change specifically on the command line:
+#
+# Change the location of the default config file:
+# > ovs-ctl --default-config-file=/path/to/file
+#
+# Disable the default config file:
+# > ovs-ctl --no-default 
+#
+# Read these specific config files:
+# > ovs-ctl --config-file file1 file2 file3
+#
+# Note: The default config file reading behavior is equivalent to:
+#
+# > ovs-ctl --default /opt/ovs/ovs-ctl-default.conf --config-file ~/.ovs-ctl
+# 
+# This is also equivalent to:
+# > ovs-ctl --no-default --config-file /opt/ovs/ovs-ctl-default.conf ~/.ovs-ctl
+#
+#
+###############################################################################
+
+#
+# Default options can be specified here
+#
+[Defaults]
+# Default all configurations to 1.4.0
+config:1.4.0
+
+#
+# Specific OVS configurations go here
+#
+[1.4.0]
+# ovs-1.4.0, configured and built into /opt/ovs/1.4.0
+# Can be selected with 'ovs-ctl.py --config 1.4.0'
+ovs_src_dir:/opt/ovs/src/openvswitch-1.4.0
+ovs_base_dir:/opt/ovs/1.4.0
+ovs_runtime_dir:/var/run/ovs/1.4.0
+
+
+[1.3.0]
+# ovs-1.3.0, configured and built into /opt/ovs/1.3.0
+# Can be selected with 'ovsctl.py --config 1.3.0'
+ovs_src_dir:/opt/ovs/src/openvswitch-1.3.0
+ovs_base_dir:/opt/ovs/1.3.0
+ovs_runtime_dir:/var/run/ovs/1.3.0
+
+[1.2.2]
+# ovs-1.2.2, configured and built into /opt/ovs/1.2.2
+# Can be selected with 'ovsctl.py --config 1.2.2'
+ovs_src_dir:/opt/ovs/src/openvswitch-1.2.2
+ovs_base_dir:/opt/ovs/1.2.2
+ovs_runtime_dir:/var/run/ovs/1.2.2
+
+#
+# In the above configurations, the locations of the tools
+# are derived by ovs-ctl relative to 'ovs_src_dir' and 'ovs_base_dir'
+#
+# Individual tools and locations can be specified directly in 
+# the configuration (as well as the command line):
+#
+# Try:
+# 'ovs-ctl.py --no-default --config-file ovs-ctl-default.example.conf --config MyExample'
+#
+# In general, every command line option can be specified in a config file section. 
+#
+# The precedence of options is:
+#     1. Command Line Options
+#     2. [The Config You Specified]
+#     3. [The Defaults sections]
+#
+
+[MyExampleConfig]
+ovs_vswitchd_schema:/path/to/vswitch/schema/file
+ovs_vswitchdL:/path/to/vswitchd
+ovs_vsctl:/path/to/vsctl
+ovs_ofctl:/path/to/ofctl
+ovsdb_tool:/path/to/ovsdb_tool
+ovsd_db_file:/path/to/ovs_db_file
+ovs_db_sock:/path/to/ovs_db_sock
+ovs_kmod:/path/to/ovs_kmod
+
+
+
+
+
+
diff --git a/Fabric/Utilities/tools/ovs-ctl/ovs-ctl.py b/Fabric/Utilities/tools/ovs-ctl/ovs-ctl.py
new file mode 100755
index 0000000..13e287e
--- /dev/null
+++ b/Fabric/Utilities/tools/ovs-ctl/ovs-ctl.py
@@ -0,0 +1,542 @@
+
+# Copyright 2017-present Open Networking Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+#!/usr/bin/python
+
+import os
+import subprocess
+import argparse
+import sys
+import signal
+import time
+import ConfigParser
+import pprint
+
+###############################################################################
+#
+# Arguments
+#
+# Arguments can be specified directly, or via config file. 
+# TODO -- Make this a separate reusable class
+#
+################################################################################
+gBasename = "ovs-ctl"
+
+gConfigParser = argparse.ArgumentParser(description=gBasename, add_help=False)
+
+gConfigParser.add_argument('-cf', '--config-file', 
+                     help="Load settings from the given config file", 
+                     nargs='+', metavar="FILE", 
+                     default=os.path.expanduser("~/."+gBasename))
+
+gConfigParser.add_argument('-c', '--config', 
+                     help="Use the specified configuration section", 
+                     default=None)
+
+gConfigParser.add_argument('-d', '--default-config-file', 
+                     help="Location of the local default config file", 
+                     metavar="FILE", 
+                     default="/opt/ovs/%s-default.conf" % (gBasename))
+
+gConfigParser.add_argument('-nd', '--no-default', 
+                     help="Do not load the default config file", 
+                     action='store_true', default=False)
+gConfigParser.add_argument('--dump-config',
+                     help="Dump the loaded configuration settings", 
+                     action='store_true', default=False)
+
+#
+# Parse the config files first, then parse remaining command line arguments
+#
+gConfig = ConfigParser.SafeConfigParser()
+configArgs, remainingArgs = gConfigParser.parse_known_args()
+
+if not configArgs.no_default:
+    gConfig.read([configArgs.default_config_file])
+
+if isinstance(configArgs.config_file, str):
+    configFiles = [ configArgs.config_file]
+else:
+    configFiles = configArgs.config_file
+
+configFiles = [ os.path.expanduser(x) if x.startswith('~') else x 
+                for x in configFiles ]
+
+gConfig.read(configFiles)
+
+# Dump loaded config if requested
+if configArgs.dump_config:
+    for section in gConfig.sections():
+        print section
+        for option in gConfig.options(section):
+            print " ", option, "=", gConfig.get(section, option)
+    sys.exit()
+
+
+
+#
+# Functional arguments go here
+#
+
+#
+# OVS target binaries -- these can all be specified individually. 
+# If not specified, they are determined by the base directory settings
+#
+gParser = argparse.ArgumentParser(parents=[gConfigParser])
+
+gParser.add_argument('--ovs-vswitchd-schema', 
+                     help="""Path to the vswitchd.ovsschema file""")
+gParser.add_argument('--ovs-vswitchd-log', 
+                     help="""Path to the vswitchd log file""")
+gParser.add_argument('--ovs-vswitchd-verbosity', 
+                     help="""Set vswitchd logging level (off/emer/err/warn/info/dbg)""",
+                     default="dbg")
+gParser.add_argument('--ovs-vswitchd', 
+                     help="""Path to the target ovs-vswitchd binary""")
+gParser.add_argument('--ovs-vsctl', 
+                     help="""Path to the target ovs-vsctl binary""")
+gParser.add_argument('--ovs-ofctl', 
+                     help="""Path to the target ovs-ofctl binary""")
+gParser.add_argument('--ovsdb-tool', 
+                     help="""Path to the target ovsdb-tool binary""")
+gParser.add_argument('--ovsdb-server', 
+                     help="""Path to the target ovsdb-server binary""")
+gParser.add_argument('--ovs-kmod', 
+                     help="""Path to the OVS kernel module""")
+gParser.add_argument('--ovs-src-dir',
+                     help="""Directory for the OVS Source Files""")
+
+gParser.add_argument('--ovs-log-dir',
+                     help="""Directory for the OVS Runtime Log Files""")
+
+gParser.add_argument('--ovs-version')
+
+gParser.add_argument("--ovs-base-dir", help="OVS Base Installation Directory")
+
+gParser.add_argument("--ovs-runtime-dir", 
+                     help="OVS Runtime Directory", 
+                     default="/var/run/ovs")
+
+gParser.add_argument('--ovs-db-sock', 
+                     help="Domain Socket Location")
+                     
+gParser.add_argument('--ovs-db-file', 
+                     help="Location for the OVS database file")
+
+
+#
+# Logging/Debugging/Testing options
+#
+gParser.add_argument('--dry', 
+                     help="""Dry run only. Don't actually do anything""", 
+                     action='store_true',  default=False)
+
+gParser.add_argument('--log', 
+                     help='Enable logging', 
+                     action='store_true', default=False)
+
+gParser.add_argument('--verbose', 
+                     help='Enable verbose output information', 
+                     action='store_true', default=False)
+
+gParser.add_argument("--kill", help="Kill running OVS", 
+                     default=False, action='store_true')
+
+gParser.add_argument("--keep-veths", 
+                     help="""By default, all existing veths will be destroyed and
+the veth module removed before initializing. If you don't want the veth module
+removed, specify this argument. Your mileage may vary if you use this.""", 
+                     default=False, action='store_true')
+
+gParser.add_argument("--no-kmod", 
+                     help="""Do not attempt to insert or remove the OVS kernel module. 
+Your mileage may vary.""", 
+                     default=False, action='store_true')
+
+gParser.add_argument("--vlog", 
+                     help="""Tail the running vswitch.log file in a new xterm""", 
+                     default=False, action='store_true')
+
+#
+# Runtime and setup arguments
+#
+gParser.add_argument('-p', '--port-count', type=int, 
+                     help="Number of veth ports to connect.", 
+                     default='4')
+
+
+gParser.add_argument("--bridge", help="Name of OF OVS Bridge", 
+                     default="ofbr0")
+
+gParser.add_argument("--cip", help="Controller Connection", 
+                     default="127.0.0.1")
+
+gParser.add_argument("--cport", type=int, help="Controller Port", 
+                     default=6653)
+gParser.add_argument("--dpid", help="DPID")
+
+gParser.add_argument("--max_backoff", help="VSwitchD max backoff value", 
+                     default=1000, type=int)
+
+
+gParser.add_argument("--keep-db", 
+                     help="""By default, a new database is initialized at each
+execution. If you want to keep and use the old database (if it exists), 
+use this option""", 
+                     action='store_true', default=False)
+
+gParser.add_argument('-lb', '--loopback',
+                     help="Create a loopback pair.  The port numbers are port_count+1 and port_count+2.", 
+                     default=False, action='store_true')
+
+
+gParser.add_argument("--cli", 
+                     help="Run the ovs-ctl cli after initialization", 
+                     action='store_true', default=False)
+
+gParser.add_argument("--teardown", 
+                     help="Kill OVS instance after CLI exits", 
+                     action='store_true', default=False)
+
+#
+# Reset defaults based on config files and override
+#
+# Anything in the "Defaults" section gets slurped first:
+defaults = {}
+if gConfig.has_section('Defaults'):
+    defaults = dict(gConfig.items('Defaults'))
+    gParser.set_defaults(**defaults)
+
+#
+# The configuration to execute might be specified in on the command line, or in the Defaults section(s)
+# of the config files. 
+#
+# If its specified on the command line, it will be present in configArgs.config
+# If its specified in the section, it will only be present in the defaults dict. 
+# Need to check both. Command line takes precedence. 
+#
+gConfigSection = None
+if configArgs.config != None:
+    gConfigSection = configArgs.config
+elif defaults.has_key('config'):
+    gConfigSection = defaults['config']
+
+
+if gConfigSection != None:
+    if gConfig.has_section(gConfigSection):
+        section = dict(gConfig.items(gConfigSection))
+        gParser.set_defaults(**section)
+    else:
+        print >>sys.stderr, "Requestion configuration '%s' does not exist" % (configArgs.config)
+        sys.exit()
+
+
+###############################################################################
+# 
+# Done with argument setup. Parser remaining arguments
+#
+###############################################################################
+gArgs = gParser.parse_args(remainingArgs)
+
+
+#
+# At the end of all of this, we need the following things to be defined
+# or derived:
+#
+gRequiredOptions = [
+    [ 'ovs_vswitchd_schema', 'ovs_src_dir',     '/vswitchd/vswitch.ovsschema', True,  True  ], 
+    [ 'ovs_vswitchd',        'ovs_base_dir',    '/sbin/ovs-vswitchd',          True,  True  ], 
+    [ 'ovs_vsctl',           'ovs_base_dir',    '/bin/ovs-vsctl',              True,  True  ], 
+    [ 'ovs_ofctl',           'ovs_base_dir',    '/bin/ovs-ofctl',              True,  True  ], 
+    [ 'ovsdb_tool',          'ovs_base_dir',    '/bin/ovsdb-tool',             True,  True, ], 
+    [ 'ovsdb_server',        'ovs_base_dir',    '/sbin/ovsdb-server',          True,  True, ], 
+    [ 'ovs_db_file',          'ovs_base_dir',    '/ovs.db',                    False, True, ], 
+    [ 'ovs_db_sock',         'ovs_runtime_dir', '/db.sock',                    False, True, ], 
+    [ 'ovs_kmod',            'ovs_base_dir',    '/sbin/openvswitch_mod.ko',    True,  not gArgs.no_kmod ], 
+]
+
+def __require_option(key, basedir, path, exists=True):
+    value = getattr(gArgs, key)
+    if value is None:
+        # Unspecified -- try to default based on given path
+        value = getattr(gArgs, basedir)
+
+        if value is None:
+            return False
+
+        value += path
+
+    if exists and not os.path.exists(value):
+        return False
+
+    if gArgs.verbose:
+        print '--v-- option: %s @ %s' % (key, value)
+
+    setattr(gArgs, key, value)
+
+
+Validated = True
+# Try to validate as many things as we can
+for option in gRequiredOptions:
+    if option[4]:
+        if __require_option(option[0], option[1], option[2], option[3]) == False:
+            Validated = False
+
+# If any of them failed, try to be as helpful as possible
+if Validated == False:
+    print >>sys.stdout, "\nConfiguration problem. One or more required settings are missing or could not be derived:\n"
+    for option in gRequiredOptions:
+        if option[4] is False:
+            continue
+
+        value = getattr(gArgs, option[0])
+        if value:
+            print >>sys.stdout, " %s: %s" % (option[0], value), 
+            if option[3] and not os.path.exists(value):
+                print >>sys.stdout, "-- does not exist"
+            else:
+                print "(OK)"
+        else:
+            print >>sys.stdout, " %s: Unknown. " % (option[0]), 
+            base = getattr(gArgs, option[1])
+            if base:
+                print >>sys.stdout, "Search path was '%s'." % (base + option[2])
+            else:
+                print >>sys.stdout, "Could not derive path because '%s' was also unspecified." % (option[1])
+    print >>sys.stdout
+    sys.exit()
+
+
+
+
+#
+# If we aren't in a dry run, you must execute as root to accompish anything
+#
+if not os.geteuid() == 0 and gArgs.dry == False:
+    print >>sys.stderr, "Must run as root to accomplish any of this."
+    sys.exit()
+
+
+###############################################################################
+#
+# Helpers 
+#
+###############################################################################
+
+def createVeths(count):
+    for idx in range(0, count):
+        lcall(["/sbin/ip", "link", "add", "type", "veth"])
+
+def vethsUp(count):
+    for idx in range(0, count*2):
+        lcall(["/sbin/ifconfig", 'veth%s' % (idx), "up"])
+
+def lcall(cmd, log=gArgs.log, dry=gArgs.dry, popen=False, 
+          pidFile=None):
+    
+    if log or gArgs.verbose:
+        print "%s: %s" % ('popen' if popen else 'call', cmd)
+    
+    if not dry:
+        if not popen:
+            subprocess.call(cmd)
+        else:
+            p = subprocess.Popen(cmd)
+            if pidFile != None:
+                pidf = open(pidFile, "w"); 
+                print >>pidf, p.pid
+                pidf.close()
+
+    
+
+def vsctl(argsList):
+    argsList.insert(0, "--db=unix:%s" % (gArgs.ovs_db_sock))
+    argsList.insert(0, gArgs.ovs_vsctl)
+    lcall(argsList)
+
+def ofctl(argsList):
+    argsList.insert(0, gArgs.ovs_ofctl)
+    lcall(argsList)
+
+def killpid(pid):
+    try:
+        os.kill(pid, signal.SIGTERM)
+        return False
+    except OSError, e:
+        return True
+
+
+def killp(pidfile):
+    if os.path.exists(pidfile):
+        pid=int(open(pidfile).read())
+        print "Killing %s, pid=%s..." % (pidfile, pid),
+        if not gArgs.dry:
+            while not killpid(pid):
+                time.sleep(1)
+                pass
+        print "dead"
+
+
+###############################################################################
+#
+# main
+#
+###############################################################################
+
+gServerPid = gArgs.ovs_runtime_dir + "/ovsdb-server.pid"
+gSwitchPid = gArgs.ovs_runtime_dir + "/ovs-vswitchd.pid"
+gLogPid=     gArgs.ovs_runtime_dir + "/ovs-vswitchd-tail.pid"
+
+# Kill previous execution based on contents of the runtime dir
+if os.path.exists(gServerPid):
+    print gServerPid
+    vsctl(["del-br", gArgs.bridge])
+
+
+def killall():
+    # Kill existing DB/vswitchd
+    killp(gSwitchPid)
+    killp(gServerPid)
+    killp(gLogPid)
+
+    # Remove old logpid file, since this does not happen automagically
+    if os.path.exists(gLogPid):
+        os.remove(gLogPid)
+
+    if gArgs.keep_veths == False:
+        lcall(['/sbin/rmmod', 'veth'])
+        lcall(['/sbin/modprobe', 'veth'])
+
+    # Remove kmod
+    lcall(['/sbin/rmmod', gArgs.ovs_kmod])
+
+
+killall()
+if gArgs.kill == True:
+    # Don't do anything else
+    sys.exit()
+
+
+# Remove bridge module
+lcall(['/sbin/rmmod', 'bridge'])
+# Insert openvswitch module
+lcall(['/sbin/insmod', gArgs.ovs_kmod])
+
+port_count = gArgs.port_count
+if gArgs.loopback:
+    port_count += 1
+createVeths(port_count)
+vethsUp(port_count)
+
+if not os.path.exists(gArgs.ovs_db_file) or gArgs.keep_db == False:
+    print "Initializing DB @ %s" % (gArgs.ovs_db_file)
+    if os.path.exists(gArgs.ovs_db_file) and not gArgs.dry:
+        os.remove(gArgs.ovs_db_file)
+
+    lcall([gArgs.ovsdb_tool, "create", gArgs.ovs_db_file, 
+           gArgs.ovs_vswitchd_schema])
+else:
+    print "Keeping existing DB @ %s" % (gArgs.ovs_db_file)
+
+
+if not os.path.exists(gArgs.ovs_runtime_dir):
+    os.makedirs(gArgs.ovs_runtime_dir)
+
+# Start dbserver
+lcall([gArgs.ovsdb_server, gArgs.ovs_db_file, 
+       "--remote=punix:%s" % (gArgs.ovs_db_sock), 
+       "--detach", "--pidfile=%s" % (gServerPid)])
+
+# Init db
+vsctl(["--no-wait", "init"])
+
+# Start vswitchd
+startV = [ gArgs.ovs_vswitchd, 
+          "unix:%s" % (gArgs.ovs_db_sock), 
+          "--verbose=%s" % gArgs.ovs_vswitchd_verbosity,
+          "--detach",
+          "--pidfile=%s" % (gSwitchPid) ]
+
+if gArgs.ovs_vswitchd_log:
+    startV.append("--log-file=%s" % (gArgs.ovs_vswitchd_log))
+
+lcall(startV)
+
+if gArgs.vlog:
+    lcall(["xterm", "-T", "vswitchd-log", "-e", "tail", "-f", 
+           gArgs.ovs_vswitchd_log], 
+          popen=True, pidFile=gLogPid)
+
+
+# Add a bridge
+vsctl(["add-br", gArgs.bridge])
+ofctl(["show", gArgs.bridge])
+
+# Add Veths to bridge
+for idx in range(0, gArgs.port_count):
+    vsctl(["add-port", gArgs.bridge, "veth%s" % (idx*2)])
+
+# Check if loopback port added
+if gArgs.loopback:
+    lb_idx = gArgs.port_count * 2
+    vsctl(["add-port", gArgs.bridge, "veth%d" % (lb_idx)])
+    vsctl(["add-port", gArgs.bridge, "veth%d" % (lb_idx+1)])
+
+if gArgs.dpid:
+    vsctl(["set", "bridge", gArgs.bridge, "other-config:datapath-id=%s" % (
+                gArgs.dpid)])
+
+# Set controller
+vsctl(["set-controller", gArgs.bridge, "tcp:%s:%s" % (
+        gArgs.cip, gArgs.cport)])
+
+# Minimize default backoff for controller connections
+vsctl(["set", "Controller", gArgs.bridge, 
+       "max_backoff=%s" % (gArgs.max_backoff)])
+
+
+ofctl(["show", gArgs.bridge])
+
+
+if gArgs.cli:
+    while True:
+        cmd = raw_input("[%s] ovs-ctl> " % gConfigSection)
+        if cmd and cmd != "":
+            args = cmd.split(" ")
+            if args[0] == "vsctl" or args[0] == "ovs-vsctl":
+                vsctl(args[1:])
+            elif args[0] == "ofctl" or args[0] == "ovs-ofctl":
+                ofctl(args[1:])
+            elif args[0] == "dumpflows" or args[0] == "flowtable":
+                ofctl(["dump-flows", "%s" % gArgs.bridge])
+            elif args[0] == "exit" or args[0] == "quit":
+                break; 
+            elif args[0] == "kill":
+                gArgs.teardown = True
+                break
+            else:
+                print "unknown command '%s'" % args[0]
+            
+
+if gArgs.teardown:
+    print "Killing OVS"
+    killall()
+
+
+
+
+                        
+