Merge into master from pull request #401:
Add 512-bit variation of OFPortBigMap (https://github.com/floodlight/loxigen/pull/401)
diff --git a/java_gen/java_type.py b/java_gen/java_type.py
index 64794cf..ac6a3e0 100644
--- a/java_gen/java_type.py
+++ b/java_gen/java_type.py
@@ -705,6 +705,15 @@
         'of_oxm_bsn_l2_cache_hit' : { 'value' : boolean_value },
         'of_oxm_bsn_l2_cache_hit_masked' : { 'value' : boolean_value, 'value_mask' : boolean_value },
 
+        'of_oxm_bsn_vxlan_network_id' : { 'value' : u32obj },
+        'of_oxm_bsn_vxlan_network_id_masked' : { 'value' : u32obj, 'value_mask' : u32obj },
+
+        'of_oxm_bsn_inner_eth_dst' : { 'value' : mac_addr },
+        'of_oxm_bsn_inner_eth_dst_masked' : { 'value' : mac_addr, 'value_mask' : mac_addr },
+
+        'of_oxm_bsn_inner_eth_src' : { 'value' : mac_addr },
+        'of_oxm_bsn_inner_eth_src_masked' : { 'value' : mac_addr, 'value_mask' : mac_addr },
+
         'of_table_stats_entry': { 'wildcards': table_stats_wildcards },
         'of_match_v1': { 'vlan_vid' : vlan_vid_match, 'vlan_pcp': vlan_pcp,
                 'eth_type': eth_type, 'ip_dscp': ip_dscp, 'ip_proto': ip_proto,
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/match/MatchField.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/match/MatchField.java
index faae773..e36cb59 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/match/MatchField.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/match/MatchField.java
@@ -263,6 +263,15 @@
     public final static MatchField<OFBooleanValue> BSN_L2_CACHE_HIT =
             new MatchField<OFBooleanValue>("bsn_l2_cache_hit", MatchFields.BSN_L2_CACHE_HIT);
 
+    public final static MatchField<U32> BSN_VXLAN_NETWORK_ID =
+            new MatchField<U32>("bsn_vxlan_network_id", MatchFields.BSN_VXLAN_NETWORK_ID);
+
+    public final static MatchField<MacAddress> BSN_INNER_ETH_DST =
+            new MatchField<MacAddress>("bsn_inner_eth_dst", MatchFields.BSN_INNER_ETH_DST);
+
+    public final static MatchField<MacAddress> BSN_INNER_ETH_SRC =
+            new MatchField<MacAddress>("bsn_inner_eth_src", MatchFields.BSN_INNER_ETH_SRC);
+
     public String getName() {
         return name;
     }
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/match/MatchFields.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/match/MatchFields.java
index 2cefa53..76671bd 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/match/MatchFields.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/match/MatchFields.java
@@ -65,4 +65,7 @@
     BSN_VLAN_XLATE_PORT_GROUP_ID,
     BSN_L2_CACHE_HIT,
     BSN_INGRESS_PORT_GROUP_ID,
+    BSN_VXLAN_NETWORK_ID,
+    BSN_INNER_ETH_DST,
+    BSN_INNER_ETH_SRC,
 }
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IPAddress.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IPAddress.java
index e1f739d..ad21e06 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IPAddress.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IPAddress.java
@@ -40,6 +40,13 @@
      */
     public abstract boolean isBroadcast();
 
+
+    /**
+     * Checks if the IPAddress is the multicast address
+     * @return boolean true or false
+     */
+    public abstract boolean isMulticast();
+
     /**
      * Perform a low level AND operation on the bits of two IPAddress objects
      * @param   other IPAddress
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IPv4Address.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IPv4Address.java
index 1530629..53e8071 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IPv4Address.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IPv4Address.java
@@ -90,6 +90,14 @@
         return this.equals(NO_MASK);
     }
 
+    /**
+     * IPv4 multicast addresses are defined by the leading address bits of 1110 
+     */
+    @Override
+    public boolean isMulticast() {
+        return ((rawValue >>> 24) & 0xF0) == 0xE0;
+    }
+    
     @Override
     public IPv4Address and(IPv4Address other) {
         Preconditions.checkNotNull(other, "other must not be null");
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IPv6Address.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IPv6Address.java
index 4660fc5..fee04ac 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IPv6Address.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IPv6Address.java
@@ -115,6 +115,14 @@
         return this.equals(NO_MASK);
     }
 
+    /**
+     * IPv6 multicast addresses are defined by the prefix ff00::/8 
+     */
+    @Override
+    public boolean isMulticast() {
+        return (raw1 >>> 56) == 0xFFL;
+    }
+    
     @Override
     public IPv6Address and(IPv6Address other) {
         Preconditions.checkNotNull(other, "other must not be null");
@@ -166,13 +174,13 @@
                 (address[0] & 0xFFL) << 56 | (address[1] & 0xFFL) << 48
                         | (address[2] & 0xFFL) << 40 | (address[3] & 0xFFL) << 32
                         | (address[4] & 0xFFL) << 24 | (address[5] & 0xFFL) << 16
-                        | (address[6] & 0xFFL) << 8 | (address[7]);
+                        | (address[6] & 0xFFL) << 8 | (address[7] & 0xFFL);
 
         long raw2 =
                 (address[8] & 0xFFL) << 56 | (address[9] & 0xFFL) << 48
                         | (address[10] & 0xFFL) << 40 | (address[11] & 0xFFL) << 32
                         | (address[12] & 0xFFL) << 24 | (address[13] & 0xFFL) << 16
-                        | (address[14] & 0xFFL) << 8 | (address[15]);
+                        | (address[14] & 0xFFL) << 8 | (address[15] & 0xFFL);
 
         return IPv6Address.of(raw1, raw2);
     }
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFGroup.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFGroup.java
index 32e9bcc..9c571ea 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFGroup.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFGroup.java
@@ -38,7 +38,7 @@
     public final static OFGroup ANY = new NamedGroup(ANY_VAL, "any");
 
     /** group 0 in case we need it */
-    public static final OFGroup ZERO = OFGroup.of(ZERO_VAL);
+    public static final OFGroup ZERO = new OFGroup(ZERO_VAL);
 
     public static final OFGroup NO_MASK = ANY;
     public static final OFGroup FULL_MASK = ZERO;
@@ -62,7 +62,7 @@
     public static OFGroup of(final int groupNumber) {
         switch(groupNumber) {
             case ZERO_VAL:
-                return MAX;
+                return ZERO;
             case MAX_VAL:
                 return MAX;
             case ALL_VAL:
diff --git a/java_gen/pre-written/src/test/java/org/projectfloodlight/openflow/types/IPAddressTest.java b/java_gen/pre-written/src/test/java/org/projectfloodlight/openflow/types/IPAddressTest.java
index 2ba4528..6e9d047 100644
--- a/java_gen/pre-written/src/test/java/org/projectfloodlight/openflow/types/IPAddressTest.java
+++ b/java_gen/pre-written/src/test/java/org/projectfloodlight/openflow/types/IPAddressTest.java
@@ -130,4 +130,17 @@
         }
     }
 
+    @Test
+    public void testMulticastIp() {
+        IPAddress<?> ip0 = IPAddress.of("240.2.3.4");
+        IPAddress<?> ip1 = IPAddress.of("224.0.1.1");
+        IPAddress<?> ip2 = IPAddress.of("239.0.0.0");
+        IPAddress<?> ip3 = IPAddress.of("feff::1");
+        IPAddress<?> ip4 = IPAddress.of("ff00::1");
+        assertTrue(!ip0.isMulticast());
+        assertTrue(ip1.isMulticast());
+        assertTrue(ip2.isMulticast());
+        assertTrue(!ip3.isMulticast());
+        assertTrue(ip4.isMulticast());
+    }
 }
diff --git a/java_gen/pre-written/src/test/java/org/projectfloodlight/openflow/types/IPv6AddressTest.java b/java_gen/pre-written/src/test/java/org/projectfloodlight/openflow/types/IPv6AddressTest.java
index 52f2487..a94f443 100644
--- a/java_gen/pre-written/src/test/java/org/projectfloodlight/openflow/types/IPv6AddressTest.java
+++ b/java_gen/pre-written/src/test/java/org/projectfloodlight/openflow/types/IPv6AddressTest.java
@@ -20,7 +20,8 @@
             "::",
             "::1",
             "ffe0::",
-            "1:2:3:4:5:6:7:8"
+            "1:2:3:4:5:6:7:8",
+            "8091:a2b3:c4d5:e6f7:8495:a6b7:c1d2:e3d4",
     };
 
 
diff --git a/openflow_input/bsn_inner_eth_dst b/openflow_input/bsn_inner_eth_dst
new file mode 100644
index 0000000..d3e9fa9
--- /dev/null
+++ b/openflow_input/bsn_inner_eth_dst
@@ -0,0 +1,47 @@
+// Copyright 2015, Big Switch Networks, Inc.
+//
+// LoxiGen is licensed under the Eclipse Public License,
+// version 1.0 (EPL), with the following special exception:
+//
+// LOXI Exception
+//
+// As a special exception to the terms of the EPL, you may
+// distribute libraries generated by LoxiGen (LoxiGen Libraries)
+// under the terms of your choice, provided that copyright and
+// licensing notices generated by LoxiGen are not altered or removed
+// from the LoxiGen Libraries and the notice provided below is (i)
+// included in the LoxiGen Libraries, if distributed in source code
+// form and (ii) included in any documentation for the LoxiGen
+// Libraries, if distributed in binary form.
+//
+// Notice: "Copyright 2013, Big Switch Networks, Inc.
+// This library was generated by the LoxiGen Compiler."
+//
+// You may not use this file except in compliance with the EPL or
+// LOXI Exception. You may obtain a copy of the EPL at:
+//
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// 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 EPL for the specific language
+// governing permissions and limitations under the EPL.
+
+#version 4
+#version 5
+
+/*
+ * Inner ethernet destination MAC
+ */
+
+struct of_oxm_bsn_inner_eth_dst : of_oxm {
+    uint32_t type_len == 0x00032c06;
+    of_mac_addr_t value;
+};
+
+struct of_oxm_bsn_inner_eth_dst_masked : of_oxm {
+    uint32_t type_len == 0x00032d0c;
+    of_mac_addr_t value;
+    of_mac_addr_t value_mask;
+};
diff --git a/openflow_input/bsn_inner_eth_src b/openflow_input/bsn_inner_eth_src
new file mode 100644
index 0000000..36e0e35
--- /dev/null
+++ b/openflow_input/bsn_inner_eth_src
@@ -0,0 +1,47 @@
+// Copyright 2015, Big Switch Networks, Inc.
+//
+// LoxiGen is licensed under the Eclipse Public License,
+// version 1.0 (EPL), with the following special exception:
+//
+// LOXI Exception
+//
+// As a special exception to the terms of the EPL, you may
+// distribute libraries generated by LoxiGen (LoxiGen Libraries)
+// under the terms of your choice, provided that copyright and
+// licensing notices generated by LoxiGen are not altered or removed
+// from the LoxiGen Libraries and the notice provided below is (i)
+// included in the LoxiGen Libraries, if distributed in source code
+// form and (ii) included in any documentation for the LoxiGen
+// Libraries, if distributed in binary form.
+//
+// Notice: "Copyright 2013, Big Switch Networks, Inc.
+// This library was generated by the LoxiGen Compiler."
+//
+// You may not use this file except in compliance with the EPL or
+// LOXI Exception. You may obtain a copy of the EPL at:
+//
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// 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 EPL for the specific language
+// governing permissions and limitations under the EPL.
+
+#version 4
+#version 5
+
+/*
+ * Inner ethernet source MAC
+ */
+
+struct of_oxm_bsn_inner_eth_src : of_oxm {
+    uint32_t type_len == 0x00032e06;
+    of_mac_addr_t value;
+};
+
+struct of_oxm_bsn_inner_eth_src_masked : of_oxm {
+    uint32_t type_len == 0x00032f0c;
+    of_mac_addr_t value;
+    of_mac_addr_t value_mask;
+};
diff --git a/openflow_input/bsn_vxlan b/openflow_input/bsn_vxlan
new file mode 100644
index 0000000..4171a51
--- /dev/null
+++ b/openflow_input/bsn_vxlan
@@ -0,0 +1,47 @@
+// Copyright 2015, Big Switch Networks, Inc.
+//
+// LoxiGen is licensed under the Eclipse Public License,
+// version 1.0 (EPL), with the following special exception:
+//
+// LOXI Exception
+//
+// As a special exception to the terms of the EPL, you may
+// distribute libraries generated by LoxiGen (LoxiGen Libraries)
+// under the terms of your choice, provided that copyright and
+// licensing notices generated by LoxiGen are not altered or removed
+// from the LoxiGen Libraries and the notice provided below is (i)
+// included in the LoxiGen Libraries, if distributed in source code
+// form and (ii) included in any documentation for the LoxiGen
+// Libraries, if distributed in binary form.
+//
+// Notice: "Copyright 2013, Big Switch Networks, Inc.
+// This library was generated by the LoxiGen Compiler."
+//
+// You may not use this file except in compliance with the EPL or
+// LOXI Exception. You may obtain a copy of the EPL at:
+//
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// 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 EPL for the specific language
+// governing permissions and limitations under the EPL.
+
+#version 4
+#version 5
+
+/*
+ * VXLAN Virtual Network Identifier
+ */
+
+struct of_oxm_bsn_vxlan_network_id : of_oxm {
+    uint32_t type_len == 0x00032a04;
+    uint32_t value;
+};
+
+struct of_oxm_bsn_vxlan_network_id_masked : of_oxm {
+    uint32_t type_len == 0x00032b08;
+    uint32_t value;
+    uint32_t value_mask;
+};
diff --git a/py_gen/codegen.py b/py_gen/codegen.py
index 9c741d2..aa7141a 100644
--- a/py_gen/codegen.py
+++ b/py_gen/codegen.py
@@ -88,6 +88,7 @@
     render('__init__.py', template_name='toplevel_init.py')
     render('pp.py')
     render('generic_util.py')
+    render('connection.py')
 
     for version in loxi_globals.OFVersions.all_supported:
         subdir = 'of' + version.version.replace('.', '')
diff --git a/py_gen/templates/connection.py b/py_gen/templates/connection.py
new file mode 100644
index 0000000..f0648be
--- /dev/null
+++ b/py_gen/templates/connection.py
@@ -0,0 +1,264 @@
+:: # Copyright 2015, Big Switch Networks, Inc.
+:: #
+:: # LoxiGen is licensed under the Eclipse Public License, version 1.0 (EPL), with
+:: # the following special exception:
+:: #
+:: # LOXI Exception
+:: #
+:: # As a special exception to the terms of the EPL, you may distribute libraries
+:: # generated by LoxiGen (LoxiGen Libraries) under the terms of your choice, provided
+:: # that copyright and licensing notices generated by LoxiGen are not altered or removed
+:: # from the LoxiGen Libraries and the notice provided below is (i) included in
+:: # the LoxiGen Libraries, if distributed in source code form and (ii) included in any
+:: # documentation for the LoxiGen Libraries, if distributed in binary form.
+:: #
+:: # Notice: "Copyright 2013, Big Switch Networks, Inc. This library was generated by the LoxiGen Compiler."
+:: #
+:: # You may not use this file except in compliance with the EPL or LOXI Exception. You may obtain
+:: # a copy of the EPL at:
+:: #
+:: # http://www.eclipse.org/legal/epl-v10.html
+:: #
+:: # 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
+:: # EPL for the specific language governing permissions and limitations
+:: # under the EPL.
+::
+# Copyright 2015, Big Switch Networks, Inc.
+
+"""
+OpenFlow connection class
+
+This class creates a thread which continually parses OpenFlow messages off the
+supplied socket and places them in a queue. The class has methods for reading messages
+from the RX queue, sending messages, and higher level operations like request-response
+and multipart transactions.
+"""
+
+import loxi
+import loxi.of14
+import logging
+import time
+import socket
+import errno
+import os
+import select
+from threading import Condition, Lock, Thread
+
+DEFAULT_TIMEOUT = 1
+
+class TransactionError(Exception):
+    def __str__(self):
+        return self.args[0]
+
+    @property
+    def msg(self):
+        return self.args[1]
+
+class Connection(Thread):
+    def __init__(self, sock):
+        Thread.__init__(self)
+        self.sock = sock
+        self.logger = logging.getLogger("connection")
+        self.rx = []
+        self.rx_cv = Condition()
+        self.tx_lock = Lock()
+        self.next_xid = 1
+        self.wakeup_rd, self.wakeup_wr = os.pipe()
+        self.finished = False
+        self.read_buffer = None
+
+    def run(self):
+        while not self.finished:
+            rd, wr, err = select.select([self.sock, self.wakeup_rd], [], [])
+            if self.sock in rd:
+                self.process_read()
+            if self.wakeup_rd in rd:
+                os.read(self.wakeup_rd, 1)
+        self.logger.debug("Exited event loop")
+
+    def process_read(self):
+        recvd = self.sock.recv(4096)
+
+        self.logger.debug("Received %d bytes", len(recvd))
+
+        buf = self.read_buffer
+        if buf:
+            buf += recvd
+        else:
+            buf = recvd
+
+        offset = 0
+        while offset < len(buf):
+            if offset + 8 > len(buf):
+                # Not enough data for the OpenFlow header
+                break
+
+            # Parse the header to get type
+            hdr_version, hdr_type, hdr_msglen, hdr_xid = loxi.of14.message.parse_header(buf[offset:])
+
+            # Use loxi to resolve ofp of matching version
+            ofp = loxi.protocol(hdr_version)
+
+            # Extract the raw message bytes
+            if (offset + hdr_msglen) > len(buf):
+                # Not enough data for the body
+                break
+            rawmsg = buf[offset : offset + hdr_msglen]
+            offset += hdr_msglen
+
+            msg = ofp.message.parse_message(rawmsg)
+            if not msg:
+                self.logger.warn("Could not parse message")
+                continue
+
+            self.logger.debug("Received message %s.%s xid %d length %d",
+                              type(msg).__module__, type(msg).__name__, hdr_xid, hdr_msglen)
+
+            with self.rx_cv:
+                self.rx.append(msg)
+                self.rx_cv.notify_all()
+
+        if offset == len(buf):
+            self.read_buffer = None
+        else:
+            self.read_buffer = buf[offset:]
+            self.logger.debug("%d bytes remaining", len(self.read_buffer))
+
+    def recv(self, predicate, timeout=DEFAULT_TIMEOUT):
+        """
+        Remove and return the first message in the RX queue for
+        which 'predicate' returns true
+        """
+        assert self.is_alive()
+
+        deadline = time.time() + timeout
+        while True:
+            with self.rx_cv:
+                for i, msg in enumerate(self.rx):
+                    if predicate(msg):
+                        return self.rx.pop(i)
+
+                now = time.time()
+                if now > deadline:
+                    return None
+                else:
+                    self.rx_cv.wait(deadline - now)
+
+    def recv_any(self, timeout=DEFAULT_TIMEOUT):
+        """
+        Return the first message in the RX queue
+        """
+        return self.recv(lambda msg: True, timeout)
+
+    def recv_xid(self, xid, timeout=DEFAULT_TIMEOUT):
+        """
+        Return the first message in the RX queue with XID 'xid'
+        """
+        return self.recv(lambda msg: msg.xid == xid, timeout)
+
+    def recv_class(self, klass, timeout=DEFAULT_TIMEOUT):
+        """
+        Return the first message in the RX queue which is an instance of 'klass'
+        """
+        return self.recv(lambda msg: isinstance(msg, klass), timeout)
+
+    def send_raw(self, buf):
+        """
+        Send raw bytes on the socket
+        """
+        assert self.is_alive()
+        self.logger.debug("Sending raw message length %d", len(buf))
+        with self.tx_lock:
+            if self.sock.sendall(buf) is not None:
+                raise RuntimeError("failed to send message to switch")
+
+    def send(self, msg):
+        """
+        Send a message
+        """
+        assert self.is_alive()
+
+        if msg.xid is None:
+            msg.xid = self._gen_xid()
+        buf = msg.pack()
+        self.logger.debug("Sending message %s.%s xid %d length %d",
+                          type(msg).__module__, type(msg).__name__, msg.xid, len(buf))
+        with self.tx_lock:
+            if self.sock.sendall(buf) is not None:
+                raise RuntimeError("failed to send message to switch")
+
+    def transact(self, msg, timeout=DEFAULT_TIMEOUT):
+        """
+        Send a message and return the reply
+        """
+        self.send(msg)
+        reply = self.recv_xid(msg.xid, timeout)
+        if reply is None:
+            raise TransactionError("no reply for %s" % type(msg).__name__, None)
+        elif isinstance(reply, loxi.protocol(reply.version).message.error_msg):
+            raise TransactionError("received %s in response to %s" % (type(reply).__name__, type(msg).__name__), reply)
+        return reply
+
+    def transact_multipart_generator(self, msg, timeout=DEFAULT_TIMEOUT):
+        """
+        Send a multipart request and yield each entry from the replies
+        """
+        self.send(msg)
+        finished = False
+        while not finished:
+            reply = self.recv_xid(msg.xid, timeout)
+            if reply is None:
+                raise TransactionError("no reply for %s" % type(msg).__name__, None)
+            elif not isinstance(reply, loxi.protocol(reply.version).message.stats_reply):
+                raise TransactionError("received %s in response to %s" % (type(reply).__name__, type(msg).__name__), reply)
+            for entry in reply.entries:
+                yield entry
+            finished = reply.flags & loxi.protocol(reply.version).OFPSF_REPLY_MORE == 0
+
+    def transact_multipart(self, msg, timeout=DEFAULT_TIMEOUT):
+        """
+        Send a multipart request and return all entries from the replies
+        """
+        entries = []
+        for entry in self.transact_multipart_generator(msg, timeout):
+            entries.append(entry)
+        return entries
+
+    def stop(self):
+        """
+        Signal the thread to exit and wait for it
+        """
+        assert not self.finished
+        self.logger.debug("Stopping connection")
+        self.finished = True
+        os.write(self.wakeup_wr, "x")
+        self.join()
+        self.sock.close()
+        os.close(self.wakeup_rd)
+        os.close(self.wakeup_wr)
+        self.logger.debug("Stopped connection")
+
+    def _gen_xid(self):
+        xid = self.next_xid
+        self.next_xid += 1
+        return xid
+
+def connect(ip, port=6653, daemon=True, ofp=loxi.of14):
+    """
+    Actively connect to a switch
+    """
+    soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+    soc.connect((ip, port))
+    soc.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, True)
+    cxn = Connection(soc)
+    cxn.daemon = daemon
+    cxn.logger.debug("Connected to %s:%d", ip, port)
+    cxn.start()
+
+    cxn.send(ofp.message.hello())
+    if not cxn.recv(lambda msg: msg.type == ofp.OFPT_HELLO):
+        raise Exception("Did not receive HELLO")
+
+    return cxn