add eth platform and --interfaces command line option

When using the eth platform you can give oft multiple "-i ofport@interface"
options to specify which ethernet interfaces to use for the dataplane, instead
of needing to write your own platform file.
diff --git a/oft b/oft
index b0e51ba..993e58d 100755
--- a/oft
+++ b/oft
@@ -23,6 +23,7 @@
 import random
 import signal
 import fnmatch
+import copy
 
 root_dir = os.path.dirname(os.path.realpath(__file__))
 
@@ -77,6 +78,7 @@
     "platform"           : "local",
     "platform_args"      : None,
     "platform_dir"       : os.path.join(root_dir, "platforms"),
+    "interfaces"         : [],
 
     # Logging options
     "log_file"           : "oft.log",
@@ -121,10 +123,25 @@
 prefixing them with the '^' character.
 """
 
+    # Parse --interface
+    def check_interface(option, opt, value):
+        try:
+            ofport, interface = value.split('@', 1)
+            ofport = int(ofport)
+        except ValueError:
+            raise optparse.OptionValueError("incorrect interface syntax (got %s, expected 'ofport@interface')" % repr(value))
+        return (ofport, interface)
+
+    class Option(optparse.Option):
+        TYPES = optparse.Option.TYPES + ("interface",)
+        TYPE_CHECKER = copy.copy(optparse.Option.TYPE_CHECKER)
+        TYPE_CHECKER["interface"] = check_interface
+
     parser = optparse.OptionParser(version="%prog 0.1",
                                    usage=usage,
                                    description=description,
-                                   formatter=oftest.help_formatter.HelpFormatter())
+                                   formatter=oftest.help_formatter.HelpFormatter(),
+                                   option_class=Option)
 
     # Set up default values
     parser.set_defaults(**config_default)
@@ -152,6 +169,8 @@
     group.add_option("-P", "--platform", help="Platform module name (default %default)")
     group.add_option("-a", "--platform-args", help="Custom arguments for the platform")
     group.add_option("--platform-dir", type="string", help="Directory containing platform modules")
+    group.add_option("--interface", "-i", type="interface", dest="interfaces", metavar="INTERFACE", action="append",
+                     help="Specify a OpenFlow port number and the dataplane interface to use. May be given multiple times. Example: 1@eth1")
     parser.add_option_group(group)
 
     group = optparse.OptionGroup(parser, "Logging options")
diff --git a/platforms/eth.py b/platforms/eth.py
new file mode 100644
index 0000000..5628092
--- /dev/null
+++ b/platforms/eth.py
@@ -0,0 +1,28 @@
+"""
+Eth platform
+
+This platform uses the --interface command line option to choose the ethernet interfaces.
+"""
+
+def platform_config_update(config):
+    """
+    Update configuration for the local platform
+
+    @param config The configuration dictionary to use/update
+    """
+
+    port_map = {}
+
+    for (ofport, interface) in config["interfaces"]:
+        port_map[ofport] = interface
+
+    # Default to a veth configuration compatible with the reference switch
+    if not port_map:
+        port_map = {
+            1: 'veth1',
+            2: 'veth3',
+            3: 'veth5',
+            4: 'veth7',
+        }
+
+    config['port_map'] = port_map