Merge "QoS Schema - fix type of QoS type"
[ovsdb.git] / southbound / southbound-it / src / test / java / org / opendaylight / ovsdb / southbound / it / SouthboundIT.java
index edfcee9744b1c84d8dc351f201e5da0f6f7f2be6..425ba4c9da7820166853926fd5941225a24d143c 100644 (file)
@@ -12,42 +12,45 @@ import static org.junit.Assert.fail;
 import static org.ops4j.pax.exam.CoreOptions.composite;
 import static org.ops4j.pax.exam.CoreOptions.maven;
 import static org.ops4j.pax.exam.CoreOptions.vmOption;
-import static org.ops4j.pax.exam.CoreOptions.when;
 import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.editConfigurationFilePut;
-import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.karafDistributionConfiguration;
 import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.keepRuntimeFolder;
 
 import com.google.common.collect.ImmutableBiMap;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Sets;
 
-import java.io.File;
-import java.lang.reflect.Array;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
 import java.net.InetAddress;
 import java.net.UnknownHostException;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Properties;
 import java.util.Set;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.TimeUnit;
 
+import javax.annotation.Nullable;
 import javax.inject.Inject;
 
+import org.junit.After;
 import org.junit.Assert;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.mdsal.it.base.AbstractMdsalTestBase;
 import org.opendaylight.ovsdb.southbound.SouthboundConstants;
 import org.opendaylight.ovsdb.southbound.SouthboundMapper;
 import org.opendaylight.ovsdb.southbound.SouthboundProvider;
 import org.opendaylight.ovsdb.southbound.SouthboundUtil;
+import org.opendaylight.ovsdb.utils.mdsal.utils.MdsalUtils;
+import org.opendaylight.ovsdb.utils.southbound.utils.SouthboundUtils;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
@@ -60,7 +63,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.re
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeProtocolBase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbFailModeBase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentation;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentationBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeRef;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbPortInterfaceAttributes.VlanMode;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation;
@@ -77,6 +79,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.re
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ConnectionInfoBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.DatapathTypeEntry;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.InterfaceTypeEntryBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ManagedNodeEntry;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.OpenvswitchOtherConfigs;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceExternalIds;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceExternalIdsBuilder;
@@ -102,11 +105,11 @@ import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointBuilder;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointKey;
 import org.opendaylight.yangtools.concepts.Builder;
+import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.ops4j.pax.exam.Configuration;
 import org.ops4j.pax.exam.Option;
 import org.ops4j.pax.exam.junit.PaxExam;
-import org.ops4j.pax.exam.karaf.options.KarafDistributionOption;
 import org.ops4j.pax.exam.karaf.options.LogLevelOption;
 import org.ops4j.pax.exam.options.MavenUrlReference;
 import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
@@ -126,35 +129,72 @@ public class SouthboundIT extends AbstractMdsalTestBase {
     private static final String NETDEV_DP_TYPE = "netdev";
     private static final Logger LOG = LoggerFactory.getLogger(SouthboundIT.class);
     private static final int OVSDB_UPDATE_TIMEOUT = 1000;
+    private static final int OVSDB_ROUNDTRIP_TIMEOUT = 10000;
     private static final String FORMAT_STR = "%s_%s_%d";
-    public static final int NUM_THREADS = 4;
     private static String addressStr;
-    private static String portStr;
+    private static int portNumber;
     private static String connectionType;
-    private static Boolean setup = false;
+    private static boolean setup = false;
     private static MdsalUtils mdsalUtils = null;
-
-    // TODO Constants copied from AbstractConfigTestBase, need to be removed (see TODO below)
-    private static final String PAX_EXAM_UNPACK_DIRECTORY = "target/exam";
-    private static final String KARAF_DEBUG_PORT = "5005";
-    private static final String KARAF_DEBUG_PROP = "karaf.debug";
-    private static final String KEEP_UNPACK_DIRECTORY_PROP = "karaf.keep.unpack";
+    private static Node ovsdbNode;
+    private static int testMethodsRemaining;
 
     @Inject
     private BundleContext bundleContext;
 
+    private static final NotifyingDataChangeListener CONFIGURATION_LISTENER =
+            new NotifyingDataChangeListener(LogicalDatastoreType.CONFIGURATION);
+    private static final NotifyingDataChangeListener OPERATIONAL_LISTENER =
+            new NotifyingDataChangeListener(LogicalDatastoreType.OPERATIONAL);
+
+    private static class NotifyingDataChangeListener implements DataChangeListener {
+        private final LogicalDatastoreType type;
+        private final Set<InstanceIdentifier<?>> createdIids = new HashSet<>();
+        private final Set<InstanceIdentifier<?>> removedIids = new HashSet<>();
+        private final Set<InstanceIdentifier<?>> updatedIids = new HashSet<>();
+
+        private NotifyingDataChangeListener(LogicalDatastoreType type) {
+            this.type = type;
+        }
+
+        @Override
+        public void onDataChanged(
+                AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> asyncDataChangeEvent) {
+            LOG.info("{} DataChanged: created {}", type, asyncDataChangeEvent.getCreatedData().keySet());
+            LOG.info("{} DataChanged: removed {}", type, asyncDataChangeEvent.getRemovedPaths());
+            LOG.info("{} DataChanged: updated {}", type, asyncDataChangeEvent.getUpdatedData().keySet());
+            createdIids.addAll(asyncDataChangeEvent.getCreatedData().keySet());
+            removedIids.addAll(asyncDataChangeEvent.getRemovedPaths());
+            updatedIids.addAll(asyncDataChangeEvent.getUpdatedData().keySet());
+            // Handled managed iids
+            for (DataObject obj : asyncDataChangeEvent.getCreatedData().values()) {
+                if (obj instanceof ManagedNodeEntry) {
+                    ManagedNodeEntry managedNodeEntry = (ManagedNodeEntry) obj;
+                    LOG.info("{} DataChanged: created managed {}", managedNodeEntry.getBridgeRef().getValue());
+                    createdIids.add(managedNodeEntry.getBridgeRef().getValue());
+                }
+            }
+            synchronized(this) {
+                notifyAll();
+            }
+        }
+
+        public boolean isCreated(InstanceIdentifier<?> iid) {
+            return createdIids.remove(iid);
+        }
+
+        public boolean isRemoved(InstanceIdentifier<?> iid) {
+            return removedIids.remove(iid);
+        }
+
+        public boolean isUpdated(InstanceIdentifier<?> iid) {
+            return updatedIids.remove(iid);
+        }
+    }
+
     @Configuration
     public Option[] config() {
-        // TODO Figure out how to use the parent Karaf setup, then just use super.config()
-        Option[] options = new Option[] {
-                when(Boolean.getBoolean(KARAF_DEBUG_PROP))
-                        .useOptions(KarafDistributionOption.debugConfiguration(KARAF_DEBUG_PORT, true)),
-                karafDistributionConfiguration().frameworkUrl(getKarafDistro())
-                        .unpackDirectory(new File(PAX_EXAM_UNPACK_DIRECTORY))
-                        .useDeployFolder(false),
-                when(Boolean.getBoolean(KEEP_UNPACK_DIRECTORY_PROP)).useOptions(keepRuntimeFolder()),
-                // Works only if we don't specify the feature repo and name
-                getLoggingOption()};
+        Option[] options = super.config();
         Option[] propertyOptions = getPropertiesOptions();
         Option[] otherOptions = getOtherOptions();
         Option[] combinedOptions = new Option[options.length + propertyOptions.length + otherOptions.length];
@@ -204,7 +244,7 @@ public class SouthboundIT extends AbstractMdsalTestBase {
 
     @Override
     public String getFeatureName() {
-        return "odl-ovsdb-southbound-impl-ui";
+        return "odl-ovsdb-southbound-test";
     }
 
     protected String usage() {
@@ -248,7 +288,7 @@ public class SouthboundIT extends AbstractMdsalTestBase {
     @Override
     public void setup() throws InterruptedException {
         if (setup) {
-            LOG.info("Skipping setUp, already initialized");
+            LOG.info("Skipping setup, already initialized");
             return;
         }
 
@@ -263,11 +303,16 @@ public class SouthboundIT extends AbstractMdsalTestBase {
         Assert.assertNotNull("db should not be null", dataBroker);
 
         addressStr = bundleContext.getProperty(SouthboundITConstants.SERVER_IPADDRESS);
-        portStr = bundleContext.getProperty(SouthboundITConstants.SERVER_PORT);
+        String portStr = bundleContext.getProperty(SouthboundITConstants.SERVER_PORT);
+        try {
+            portNumber = Integer.parseInt(portStr);
+        } catch (NumberFormatException e) {
+            fail("Invalid port number " + portStr + System.lineSeparator() + usage());
+        }
         connectionType = bundleContext.getProperty(SouthboundITConstants.CONNECTION_TYPE);
 
         LOG.info("setUp: Using the following properties: mode= {}, ip:port= {}:{}",
-                connectionType, addressStr, portStr);
+                connectionType, addressStr, portNumber);
         if (connectionType.equalsIgnoreCase(SouthboundITConstants.CONNECTION_TYPE_ACTIVE)) {
             if (addressStr == null) {
                 fail(usage());
@@ -275,9 +320,50 @@ public class SouthboundIT extends AbstractMdsalTestBase {
         }
 
         mdsalUtils = new MdsalUtils(dataBroker);
+        final ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
+        final InstanceIdentifier<Node> iid = SouthboundUtils.createInstanceIdentifier(connectionInfo);
+        dataBroker.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
+                iid, CONFIGURATION_LISTENER, AsyncDataBroker.DataChangeScope.SUBTREE);
+        dataBroker.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
+                iid, OPERATIONAL_LISTENER, AsyncDataBroker.DataChangeScope.SUBTREE);
+
+        ovsdbNode = connectOvsdbNode(connectionInfo);
+
+        // Let's count the test methods (we need to use this instead of @AfterClass on teardown() since the latter is
+        // useless with pax-exam)
+        for (Method method : getClass().getMethods()) {
+            boolean testMethod = false;
+            boolean ignoreMethod = false;
+            for (Annotation annotation : method.getAnnotations()) {
+                if (Test.class.equals(annotation.annotationType())) {
+                    testMethod = true;
+                }
+                if (Ignore.class.equals(annotation.annotationType())) {
+                    ignoreMethod = true;
+                }
+            }
+            if (testMethod && !ignoreMethod) {
+                testMethodsRemaining++;
+            }
+        }
+        LOG.info("{} test methods to run", testMethodsRemaining);
+
         setup = true;
     }
 
+    @After
+    public void teardown() {
+        testMethodsRemaining--;
+        LOG.info("{} test methods remaining", testMethodsRemaining);
+        if (testMethodsRemaining == 0) {
+            try {
+                disconnectOvsdbNode(getConnectionInfo(addressStr, portNumber));
+            } catch (InterruptedException e) {
+                LOG.warn("Interrupted while disconnecting", e);
+            }
+        }
+    }
+
     /**
      * Test passive connection mode. The southbound starts in a listening mode waiting for connections on port
      * 6640. This test will wait for incoming connections for {@link SouthboundITConstants#CONNECTION_INIT_TIMEOUT} ms.
@@ -292,29 +378,23 @@ public class SouthboundIT extends AbstractMdsalTestBase {
         }
     }
 
-    private ConnectionInfo getConnectionInfo(final String addressStr, final String portStr) {
+    private static ConnectionInfo getConnectionInfo(final String addressStr, final int portNumber) {
         InetAddress inetAddress = null;
         try {
             inetAddress = InetAddress.getByName(addressStr);
         } catch (UnknownHostException e) {
-            fail("Could not allocate InetAddress: " + e);
+            fail("Could not resolve " + addressStr + ": " + e);
         }
 
         IpAddress address = SouthboundMapper.createIpAddress(inetAddress);
-        PortNumber port = new PortNumber(Integer.parseInt(portStr));
+        PortNumber port = new PortNumber(portNumber);
 
-        LOG.info("connectionInfo: {}", new ConnectionInfoBuilder()
-                .setRemoteIp(address)
-                .setRemotePort(port)
-                .build());
-        return new ConnectionInfoBuilder()
+        final ConnectionInfo connectionInfo = new ConnectionInfoBuilder()
                 .setRemoteIp(address)
                 .setRemotePort(port)
                 .build();
-    }
-
-    private String connectionInfoToString(final ConnectionInfo connectionInfo) {
-        return new String(connectionInfo.getRemoteIp().getValue()) + ":" + connectionInfo.getRemotePort().getValue();
+        LOG.info("connectionInfo: {}", connectionInfo);
+        return connectionInfo;
     }
 
     @Test
@@ -346,66 +426,73 @@ public class SouthboundIT extends AbstractMdsalTestBase {
                 topology);
     }
 
-    private boolean addOvsdbNode(final ConnectionInfo connectionInfo) throws InterruptedException {
-        InstanceIdentifier<Node> iid = createInstanceIdentifier(connectionInfo);
-        // Check that the node doesn't already exist (we don't support connecting twice)
-        Assert.assertNull("The OVSDB node has already been added",
-                mdsalUtils.read(LogicalDatastoreType.CONFIGURATION, iid));
-        boolean result = mdsalUtils.put(LogicalDatastoreType.CONFIGURATION,
-                iid,
-                createNode(connectionInfo));
-        Thread.sleep(OVSDB_UPDATE_TIMEOUT);
-        return result;
-    }
-
-    private InstanceIdentifier<Node> createInstanceIdentifier(
-            ConnectionInfo connectionInfo) {
-        return InstanceIdentifier
-                .create(NetworkTopology.class)
-                .child(Topology.class, new TopologyKey(SouthboundConstants.OVSDB_TOPOLOGY_ID))
-                .child(Node.class,
-                        createNodeKey(connectionInfo.getRemoteIp(), connectionInfo.getRemotePort()));
+    private Node connectOvsdbNode(final ConnectionInfo connectionInfo) throws InterruptedException {
+        final InstanceIdentifier<Node> iid = SouthboundUtils.createInstanceIdentifier(connectionInfo);
+        Assert.assertTrue(
+                mdsalUtils.put(LogicalDatastoreType.CONFIGURATION, iid, SouthboundUtils.createNode(connectionInfo)));
+        waitForOperationalCreation(iid);
+        Node node = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, iid);
+        Assert.assertNotNull(node);
+        LOG.info("Connected to {}", SouthboundUtils.connectionInfoToString(connectionInfo));
+        return node;
     }
 
-    private Node getOvsdbNode(final ConnectionInfo connectionInfo) {
-        return mdsalUtils.read(LogicalDatastoreType.OPERATIONAL,
-                createInstanceIdentifier(connectionInfo));
+    private void waitForOperationalCreation(InstanceIdentifier<Node> iid) throws InterruptedException {
+        synchronized (OPERATIONAL_LISTENER) {
+            long _start = System.currentTimeMillis();
+            LOG.info("Waiting for OPERATIONAL DataChanged creation on {}", iid);
+            while (!OPERATIONAL_LISTENER.isCreated(
+                    iid) && (System.currentTimeMillis() - _start) < OVSDB_ROUNDTRIP_TIMEOUT) {
+                OPERATIONAL_LISTENER.wait(OVSDB_UPDATE_TIMEOUT);
+            }
+            LOG.info("Woke up, waited {} for creation of {}", (System.currentTimeMillis() - _start), iid);
+        }
     }
 
-    private boolean deleteOvsdbNode(final ConnectionInfo connectionInfo) throws InterruptedException {
-        boolean result = mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION,
-                createInstanceIdentifier(connectionInfo));
-        Thread.sleep(OVSDB_UPDATE_TIMEOUT);
-        return result;
+    private static void waitForOperationalDeletion(InstanceIdentifier<Node> iid) throws InterruptedException {
+        synchronized (OPERATIONAL_LISTENER) {
+            long _start = System.currentTimeMillis();
+            LOG.info("Waiting for OPERATIONAL DataChanged deletion on {}", iid);
+            while (!OPERATIONAL_LISTENER.isRemoved(
+                    iid) && (System.currentTimeMillis() - _start) < OVSDB_ROUNDTRIP_TIMEOUT) {
+                OPERATIONAL_LISTENER.wait(OVSDB_UPDATE_TIMEOUT);
+            }
+            LOG.info("Woke up, waited {} for deletion of {}", (System.currentTimeMillis() - _start), iid);
+        }
     }
 
-    private Node connectOvsdbNode(final ConnectionInfo connectionInfo) throws InterruptedException {
-        Assert.assertTrue(addOvsdbNode(connectionInfo));
-        Node node = getOvsdbNode(connectionInfo);
-        Assert.assertNotNull(node);
-        LOG.info("Connected to {}", connectionInfoToString(connectionInfo));
-        return node;
+    private void waitForOperationalUpdate(InstanceIdentifier<Node> iid) throws InterruptedException {
+        synchronized (OPERATIONAL_LISTENER) {
+            long _start = System.currentTimeMillis();
+            LOG.info("Waiting for OPERATIONAL DataChanged update on {}", iid);
+            while (!OPERATIONAL_LISTENER.isUpdated(
+                    iid) && (System.currentTimeMillis() - _start) < OVSDB_ROUNDTRIP_TIMEOUT) {
+                OPERATIONAL_LISTENER.wait(OVSDB_UPDATE_TIMEOUT);
+            }
+            LOG.info("Woke up, waited {} for update of {}", (System.currentTimeMillis() - _start), iid);
+        }
     }
 
-    private boolean disconnectOvsdbNode(final ConnectionInfo connectionInfo) throws InterruptedException {
-        Assert.assertTrue(deleteOvsdbNode(connectionInfo));
-        Node node = getOvsdbNode(connectionInfo);
+    private static void disconnectOvsdbNode(final ConnectionInfo connectionInfo) throws InterruptedException {
+        final InstanceIdentifier<Node> iid = SouthboundUtils.createInstanceIdentifier(connectionInfo);
+        Assert.assertTrue(mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, iid));
+        waitForOperationalDeletion(iid);
+        Node node = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, iid);
         Assert.assertNull(node);
-        LOG.info("Disconnected from {}", connectionInfoToString(connectionInfo));
-        return true;
+        LOG.info("Disconnected from {}", SouthboundUtils.connectionInfoToString(connectionInfo));
     }
 
     @Test
     public void testAddDeleteOvsdbNode() throws InterruptedException {
-        ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr);
+        ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
+        // At this point we're connected, disconnect and reconnect (the connection will be removed at the very end)
+        disconnectOvsdbNode(connectionInfo);
         connectOvsdbNode(connectionInfo);
-        Assert.assertTrue(disconnectOvsdbNode(connectionInfo));
     }
 
     @Test
     public void testDpdkSwitch() throws InterruptedException {
-        ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr);
-        Node ovsdbNode = connectOvsdbNode(connectionInfo);
+        ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
         List<DatapathTypeEntry> datapathTypeEntries = ovsdbNode.getAugmentation(OvsdbNodeAugmentation.class)
                 .getDatapathTypeEntry();
         if (datapathTypeEntries == null) {
@@ -417,64 +504,74 @@ public class SouthboundIT extends AbstractMdsalTestBase {
                 LOG.info("dp type is {}", dpTypeStr);
                 if (dpTypeStr.equals(NETDEV_DP_TYPE)) {
                     LOG.info("Found a DPDK node; adding a corresponding netdev device");
-                    InstanceIdentifier<Node> bridgeIid = createInstanceIdentifier(connectionInfo,
+                    InstanceIdentifier<Node> bridgeIid = SouthboundUtils.createInstanceIdentifier(connectionInfo,
                             new OvsdbBridgeName(SouthboundITConstants.BRIDGE_NAME));
-                    NodeId bridgeNodeId = createManagedNodeId(bridgeIid);
-                    addBridge(connectionInfo, bridgeIid, SouthboundITConstants.BRIDGE_NAME, bridgeNodeId, false, null,
-                            true, dpType, null, null, null);
-
-                    // Verify that the device is netdev
-                    OvsdbBridgeAugmentation bridge = getBridge(connectionInfo);
-                    Assert.assertNotNull(bridge);
-                    Assert.assertEquals(dpType, bridge.getDatapathType());
-
-                    // Add dpdk port
-                    final String TEST_PORT_NAME = "testDPDKPort";
-                    OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder =
-                            createGenericDpdkOvsdbTerminationPointAugmentationBuilder(TEST_PORT_NAME);
-                    Assert.assertTrue(addTerminationPoint(bridgeNodeId, TEST_PORT_NAME, ovsdbTerminationBuilder));
-
-                    // Verify that DPDK port was created
-                    InstanceIdentifier<Node> terminationPointIid = getTpIid(connectionInfo, bridge);
-                    Node terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL,
-                            terminationPointIid);
-                    Assert.assertNotNull(terminationPointNode);
-
-                    // Verify that each termination point has DPDK ifType
-                    Class<? extends InterfaceTypeBase> dpdkIfType = SouthboundConstants.OVSDB_INTERFACE_TYPE_MAP
-                            .get("dpdk");
-                    List<TerminationPoint> terminationPoints = terminationPointNode.getTerminationPoint();
-                    for (TerminationPoint terminationPoint : terminationPoints) {
-                        OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation = terminationPoint
-                                .getAugmentation(OvsdbTerminationPointAugmentation.class);
-                        if (ovsdbTerminationPointAugmentation.getName().equals(TEST_PORT_NAME)) {
-                            Class<? extends InterfaceTypeBase> opPort = ovsdbTerminationPointAugmentation
-                                    .getInterfaceType();
-                            Assert.assertEquals(dpdkIfType, opPort);
+                    NodeId bridgeNodeId = SouthboundUtils.createManagedNodeId(bridgeIid);
+                    try (TestBridge testBridge = new TestBridge(connectionInfo, bridgeIid,
+                            SouthboundITConstants.BRIDGE_NAME, bridgeNodeId, false, null, true, dpType, null, null,
+                            null)) {
+                        // Verify that the device is netdev
+                        OvsdbBridgeAugmentation bridge = getBridge(connectionInfo);
+                        Assert.assertNotNull(bridge);
+                        Assert.assertEquals(dpType, bridge.getDatapathType());
+
+                        // Add port for all dpdk interface types (dpdkvhost not supported in existing dpdk ovs)
+                        List<String> dpdkTypes = new ArrayList<String>();
+                        dpdkTypes.add("dpdk");
+                        dpdkTypes.add("dpdkr");
+                        dpdkTypes.add("dpdkvhostuser");
+                        //dpdkTypes.add("dpdkvhost");
+
+                        for (String dpdkType : dpdkTypes) {
+                            String testPortname = "test"+dpdkType+"port";
+                            LOG.info("DPDK portname and type is {}, {}", testPortname, dpdkType);
+                            Class<? extends InterfaceTypeBase> dpdkIfType = SouthboundConstants.OVSDB_INTERFACE_TYPE_MAP
+                                    .get(dpdkType);
+                            OvsdbTerminationPointAugmentationBuilder ovsdbTerminationpointBuilder =
+                                    createSpecificDpdkOvsdbTerminationPointAugmentationBuilder(testPortname,
+                                            dpdkIfType);
+                            Assert.assertTrue(
+                                    addTerminationPoint(bridgeNodeId, testPortname, ovsdbTerminationpointBuilder));
+                        }
+
+                        // Verify that all DPDK ports are created
+                        InstanceIdentifier<Node> terminationPointIid = getTpIid(connectionInfo, bridge);
+                        Node terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL,
+                                terminationPointIid);
+                        Assert.assertNotNull(terminationPointNode);
+
+                        // Verify that each termination point has the specific DPDK ifType
+                        for (String dpdkType : dpdkTypes) {
+                            String testPortname = "test"+dpdkType+"port";
+                            Class<? extends InterfaceTypeBase> dpdkIfType = SouthboundConstants.OVSDB_INTERFACE_TYPE_MAP
+                                    .get(dpdkType);
+                            List<TerminationPoint> terminationPoints = terminationPointNode.getTerminationPoint();
+                            for (TerminationPoint terminationPoint : terminationPoints) {
+                                OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation = terminationPoint
+                                        .getAugmentation(OvsdbTerminationPointAugmentation.class);
+                                if (ovsdbTerminationPointAugmentation.getName().equals(testPortname)) {
+                                    Class<? extends InterfaceTypeBase> opPort = ovsdbTerminationPointAugmentation
+                                            .getInterfaceType();
+                                    Assert.assertEquals(dpdkIfType, opPort);
+                                }
+                            }
                         }
                     }
-                    Assert.assertTrue(deleteBridge(connectionInfo));
-                    break;
                 }
+                break;
             }
         }
-        Assert.assertTrue(disconnectOvsdbNode(connectionInfo));
     }
 
     @Test
     public void testOvsdbNodeOvsVersion() throws InterruptedException {
-        ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr);
-        Node ovsdbNode = connectOvsdbNode(connectionInfo);
         OvsdbNodeAugmentation ovsdbNodeAugmentation = ovsdbNode.getAugmentation(OvsdbNodeAugmentation.class);
         Assert.assertNotNull(ovsdbNodeAugmentation);
         assertNotNull(ovsdbNodeAugmentation.getOvsVersion());
-        Assert.assertTrue(disconnectOvsdbNode(connectionInfo));
     }
 
     @Test
     public void testOpenVSwitchOtherConfig() throws InterruptedException {
-        ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr);
-        Node ovsdbNode = connectOvsdbNode(connectionInfo);
         OvsdbNodeAugmentation ovsdbNodeAugmentation = ovsdbNode.getAugmentation(OvsdbNodeAugmentation.class);
         Assert.assertNotNull(ovsdbNodeAugmentation);
         List<OpenvswitchOtherConfigs> otherConfigsList = ovsdbNodeAugmentation.getOpenvswitchOtherConfigs();
@@ -490,33 +587,29 @@ public class SouthboundIT extends AbstractMdsalTestBase {
         } else {
             LOG.info("other_config is not present");
         }
-        Assert.assertTrue(disconnectOvsdbNode(connectionInfo));
     }
 
     @Test
     public void testOvsdbBridgeControllerInfo() throws InterruptedException {
-        ConnectionInfo connectionInfo = getConnectionInfo(addressStr,portStr);
-        Node ovsdbNode = connectOvsdbNode(connectionInfo);
+        ConnectionInfo connectionInfo = getConnectionInfo(addressStr,portNumber);
         String controllerTarget = SouthboundUtil.getControllerTarget(ovsdbNode);
         assertNotNull("Failed to get controller target", controllerTarget);
         List<ControllerEntry> setControllerEntry = createControllerEntry(controllerTarget);
         Uri setUri = new Uri(controllerTarget);
-        Assert.assertTrue(addBridge(connectionInfo, null, SouthboundITConstants.BRIDGE_NAME,null, true,
+        try (TestBridge testBridge = new TestBridge(connectionInfo, null, SouthboundITConstants.BRIDGE_NAME,null, true,
                 SouthboundConstants.OVSDB_FAIL_MODE_MAP.inverse().get("secure"), true, null, null,
-                setControllerEntry, null));
-        OvsdbBridgeAugmentation bridge = getBridge(connectionInfo);
-        Assert.assertNotNull("bridge was not found: " + SouthboundITConstants.BRIDGE_NAME,  bridge);
-        Assert.assertNotNull("ControllerEntry was not found: " + setControllerEntry.iterator().next(),
-                bridge.getControllerEntry());
-        List<ControllerEntry> getControllerEntries = bridge.getControllerEntry();
-        for (ControllerEntry entry : getControllerEntries) {
-            if (entry.getTarget() != null) {
-                Assert.assertEquals(setUri.toString(), entry.getTarget().toString());
+                setControllerEntry, null)) {
+            OvsdbBridgeAugmentation bridge = getBridge(connectionInfo);
+            Assert.assertNotNull("bridge was not found: " + SouthboundITConstants.BRIDGE_NAME,  bridge);
+            Assert.assertNotNull("ControllerEntry was not found: " + setControllerEntry.iterator().next(),
+                    bridge.getControllerEntry());
+            List<ControllerEntry> getControllerEntries = bridge.getControllerEntry();
+            for (ControllerEntry entry : getControllerEntries) {
+                if (entry.getTarget() != null) {
+                    Assert.assertEquals(setUri.toString(), entry.getTarget().toString());
+                }
             }
         }
-
-        Assert.assertTrue(deleteBridge(connectionInfo));
-        Assert.assertTrue(disconnectOvsdbNode(connectionInfo));
     }
 
     private List<ControllerEntry> createControllerEntry(String controllerTarget) {
@@ -527,13 +620,13 @@ public class SouthboundIT extends AbstractMdsalTestBase {
         return controllerEntriesList;
     }
 
-    private void setManagedBy(final OvsdbBridgeAugmentationBuilder ovsdbBridgeAugmentationBuilder,
+    private static void setManagedBy(final OvsdbBridgeAugmentationBuilder ovsdbBridgeAugmentationBuilder,
                               final ConnectionInfo connectionInfo) {
-        InstanceIdentifier<Node> connectionNodePath = createInstanceIdentifier(connectionInfo);
+        InstanceIdentifier<Node> connectionNodePath = SouthboundUtils.createInstanceIdentifier(connectionInfo);
         ovsdbBridgeAugmentationBuilder.setManagedBy(new OvsdbNodeRef(connectionNodePath));
     }
 
-    private List<ProtocolEntry> createMdsalProtocols() {
+    private static List<ProtocolEntry> createMdsalProtocols() {
         List<ProtocolEntry> protocolList = new ArrayList<>();
         ImmutableBiMap<String, Class<? extends OvsdbBridgeProtocolBase>> mapper =
                 SouthboundConstants.OVSDB_PROTOCOL_MAP.inverse();
@@ -563,6 +656,15 @@ public class SouthboundIT extends AbstractMdsalTestBase {
         return ovsdbTerminationBuilder;
     }
 
+    private OvsdbTerminationPointAugmentationBuilder createSpecificDpdkOvsdbTerminationPointAugmentationBuilder(
+            String testPortname,Class<? extends InterfaceTypeBase> dpdkIfType) {
+        OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder =
+                createGenericOvsdbTerminationPointAugmentationBuilder();
+        ovsdbTerminationBuilder.setName(testPortname);
+        ovsdbTerminationBuilder.setInterfaceType(dpdkIfType);
+        return ovsdbTerminationBuilder;
+    }
+
     private boolean addTerminationPoint(final NodeId bridgeNodeId, final String portName,
                                         final OvsdbTerminationPointAugmentationBuilder
                                                 ovsdbTerminationPointAugmentationBuilder)
@@ -584,75 +686,81 @@ public class SouthboundIT extends AbstractMdsalTestBase {
         return result;
     }
 
-    /*
-     * base method for adding test bridges.  Other helper methods used to create bridges should utilize this method.
-     *
-     * @param connectionInfo
-     * @param bridgeIid if passed null, one is created
-     * @param bridgeName cannot be null
-     * @param bridgeNodeId if passed null, one is created based on <code>bridgeIid</code>
-     * @param setProtocolEntries toggles whether default protocol entries are set for the bridge
-     * @param failMode toggles whether default fail mode is set for the bridge
-     * @param setManagedBy toggles whether to setManagedBy for the bridge
-     * @param dpType if passed null, this parameter is ignored
-     * @param externalIds if passed null, this parameter is ignored
-     * @param otherConfig if passed null, this parameter is ignored
-     * @return success of bridge addition
-     * @throws InterruptedException
-     */
-    private boolean addBridge(final ConnectionInfo connectionInfo, InstanceIdentifier<Node> bridgeIid,
-                              final String bridgeName, NodeId bridgeNodeId, final boolean setProtocolEntries,
-                              final Class<? extends OvsdbFailModeBase> failMode, final boolean setManagedBy,
-                              final Class<? extends DatapathTypeBase> dpType,
-                              final List<BridgeExternalIds> externalIds,
-                              final List<ControllerEntry> controllerEntries,
-                              final List<BridgeOtherConfigs> otherConfigs) throws InterruptedException {
-
-        NodeBuilder bridgeNodeBuilder = new NodeBuilder();
-        if (bridgeIid == null) {
-            bridgeIid = createInstanceIdentifier(connectionInfo, new OvsdbBridgeName(bridgeName));
-        }
-        if (bridgeNodeId == null) {
-            bridgeNodeId = SouthboundMapper.createManagedNodeId(bridgeIid);
-        }
-        bridgeNodeBuilder.setNodeId(bridgeNodeId);
-        OvsdbBridgeAugmentationBuilder ovsdbBridgeAugmentationBuilder = new OvsdbBridgeAugmentationBuilder();
-        ovsdbBridgeAugmentationBuilder.setBridgeName(new OvsdbBridgeName(bridgeName));
-        if (setProtocolEntries) {
-            ovsdbBridgeAugmentationBuilder.setProtocolEntry(createMdsalProtocols());
-        }
-        if (failMode != null) {
+    private static class TestBridge implements AutoCloseable {
+        private final ConnectionInfo connectionInfo;
+        private final String bridgeName;
+
+        /**
+         * Creates a test bridge which can be automatically removed when no longer necessary.
+         *
+         * @param connectionInfo The connection information.
+         * @param bridgeIid The bridge identifier; if {@code null}, one is created based on {@code bridgeName}.
+         * @param bridgeName The bridge name; must be provided.
+         * @param bridgeNodeId The bridge node identifier; if {@code null}, one is created based on {@code bridgeIid}.
+         * @param setProtocolEntries {@code true} to set default protocol entries for the bridge.
+         * @param failMode The fail mode to set for the bridge.
+         * @param setManagedBy {@code true} to specify {@code setManagedBy} for the bridge.
+         * @param dpType The datapath type.
+         * @param externalIds The external identifiers if any.
+         * @param otherConfigs The other configuration items if any.
+         */
+        public TestBridge(final ConnectionInfo connectionInfo, @Nullable InstanceIdentifier<Node> bridgeIid,
+                                  final String bridgeName, NodeId bridgeNodeId, final boolean setProtocolEntries,
+                                  final Class<? extends OvsdbFailModeBase> failMode, final boolean setManagedBy,
+                                  @Nullable final Class<? extends DatapathTypeBase> dpType,
+                                  @Nullable final List<BridgeExternalIds> externalIds,
+                                  @Nullable final List<ControllerEntry> controllerEntries,
+                                  @Nullable final List<BridgeOtherConfigs> otherConfigs) {
+            this.connectionInfo = connectionInfo;
+            this.bridgeName = bridgeName;
+            NodeBuilder bridgeNodeBuilder = new NodeBuilder();
+            if (bridgeIid == null) {
+                bridgeIid = SouthboundUtils.createInstanceIdentifier(connectionInfo, new OvsdbBridgeName(bridgeName));
+            }
+            if (bridgeNodeId == null) {
+                bridgeNodeId = SouthboundMapper.createManagedNodeId(bridgeIid);
+            }
+            bridgeNodeBuilder.setNodeId(bridgeNodeId);
+            OvsdbBridgeAugmentationBuilder ovsdbBridgeAugmentationBuilder = new OvsdbBridgeAugmentationBuilder();
+            ovsdbBridgeAugmentationBuilder.setBridgeName(new OvsdbBridgeName(bridgeName));
+            if (setProtocolEntries) {
+                ovsdbBridgeAugmentationBuilder.setProtocolEntry(createMdsalProtocols());
+            }
             ovsdbBridgeAugmentationBuilder.setFailMode(failMode);
-        }
-        if (setManagedBy) {
-            setManagedBy(ovsdbBridgeAugmentationBuilder, connectionInfo);
-        }
-        if (dpType != null) {
+            if (setManagedBy) {
+                setManagedBy(ovsdbBridgeAugmentationBuilder, connectionInfo);
+            }
             ovsdbBridgeAugmentationBuilder.setDatapathType(dpType);
-        }
-        if (externalIds != null) {
             ovsdbBridgeAugmentationBuilder.setBridgeExternalIds(externalIds);
-        }
-        if (controllerEntries != null) {
             ovsdbBridgeAugmentationBuilder.setControllerEntry(controllerEntries);
-        }
-        if (otherConfigs != null) {
             ovsdbBridgeAugmentationBuilder.setBridgeOtherConfigs(otherConfigs);
+            bridgeNodeBuilder.addAugmentation(OvsdbBridgeAugmentation.class, ovsdbBridgeAugmentationBuilder.build());
+            LOG.debug("Built with the intent to store bridge data {}", ovsdbBridgeAugmentationBuilder.toString());
+            Assert.assertTrue(
+                    mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, bridgeIid, bridgeNodeBuilder.build()));
+            try {
+                Thread.sleep(OVSDB_UPDATE_TIMEOUT);
+            } catch (InterruptedException e) {
+                LOG.warn("Sleep interrupted while waiting for bridge creation (bridge {})", bridgeName, e);
+            }
         }
-        bridgeNodeBuilder.addAugmentation(OvsdbBridgeAugmentation.class, ovsdbBridgeAugmentationBuilder.build());
-        LOG.debug("Built with the intent to store bridge data {}",
-                ovsdbBridgeAugmentationBuilder.toString());
-        boolean result = mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION,
-                bridgeIid, bridgeNodeBuilder.build());
-        Thread.sleep(OVSDB_UPDATE_TIMEOUT);
-        return result;
-    }
 
-    private boolean addBridge(final ConnectionInfo connectionInfo, final String bridgeName)
-            throws InterruptedException {
+        public TestBridge(final ConnectionInfo connectionInfo, final String bridgeName) {
+            this(connectionInfo, null, bridgeName, null, true,
+                    SouthboundConstants.OVSDB_FAIL_MODE_MAP.inverse().get("secure"), true, null, null, null, null);
+        }
 
-        return addBridge(connectionInfo, null, bridgeName, null, true,
-                SouthboundConstants.OVSDB_FAIL_MODE_MAP.inverse().get("secure"), true, null, null, null, null);
+        @Override
+        public void close() {
+            final InstanceIdentifier<Node> iid =
+                    SouthboundUtils.createInstanceIdentifier(connectionInfo, new OvsdbBridgeName(bridgeName));
+            Assert.assertTrue(mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, iid));
+            try {
+                Thread.sleep(OVSDB_UPDATE_TIMEOUT);
+            } catch (InterruptedException e) {
+                LOG.warn("Sleep interrupted while waiting for bridge deletion (bridge {})", bridgeName, e);
+            }
+        }
     }
 
     private OvsdbBridgeAugmentation getBridge(ConnectionInfo connectionInfo) {
@@ -701,8 +809,7 @@ public class SouthboundIT extends AbstractMdsalTestBase {
      */
     private Node getBridgeNode(ConnectionInfo connectionInfo, String bridgeName, LogicalDatastoreType store) {
         InstanceIdentifier<Node> bridgeIid =
-                createInstanceIdentifier(connectionInfo,
-                        new OvsdbBridgeName(bridgeName));
+                SouthboundUtils.createInstanceIdentifier(connectionInfo, new OvsdbBridgeName(bridgeName));
         return mdsalUtils.read(store, bridgeIid);
     }
 
@@ -718,38 +825,19 @@ public class SouthboundIT extends AbstractMdsalTestBase {
         return getBridgeNode(connectionInfo, bridgeName, LogicalDatastoreType.OPERATIONAL);
     }
 
-    private boolean deleteBridge(ConnectionInfo connectionInfo) throws InterruptedException {
-        return deleteBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME);
-    }
-
-    private boolean deleteBridge(final ConnectionInfo connectionInfo, final String bridgeName)
-            throws InterruptedException {
-
-        boolean result = mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION,
-                createInstanceIdentifier(connectionInfo,
-                        new OvsdbBridgeName(bridgeName)));
-        Thread.sleep(OVSDB_UPDATE_TIMEOUT);
-        return result;
-    }
-
     @Test
     public void testAddDeleteBridge() throws InterruptedException {
-        ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr);
-        connectOvsdbNode(connectionInfo);
-
-        Assert.assertTrue(addBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME));
-        OvsdbBridgeAugmentation bridge = getBridge(connectionInfo);
-        Assert.assertNotNull(bridge);
-        LOG.info("bridge: {}", bridge);
+        ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
 
-        Assert.assertTrue(deleteBridge(connectionInfo));
-
-        Assert.assertTrue(disconnectOvsdbNode(connectionInfo));
+        try (TestBridge testBridge = new TestBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME)) {
+            OvsdbBridgeAugmentation bridge = getBridge(connectionInfo);
+            Assert.assertNotNull(bridge);
+            LOG.info("bridge: {}", bridge);
+        }
     }
 
     private InstanceIdentifier<Node> getTpIid(ConnectionInfo connectionInfo, OvsdbBridgeAugmentation bridge) {
-        return createInstanceIdentifier(connectionInfo,
-                bridge.getBridgeName());
+        return SouthboundUtils.createInstanceIdentifier(connectionInfo, bridge.getBridgeName());
     }
 
     /**
@@ -763,7 +851,7 @@ public class SouthboundIT extends AbstractMdsalTestBase {
      * @return the augmentation (or {@code null} if none)
      */
     private OvsdbTerminationPointAugmentation getOvsdbTerminationPointAugmentation(
-            ConnectionInfo connectionInfo, String bridgeName, LogicalDatastoreType store, int index ) {
+            ConnectionInfo connectionInfo, String bridgeName, LogicalDatastoreType store, int index) {
 
         List<TerminationPoint> tpList = getBridgeNode(connectionInfo, bridgeName, store).getTerminationPoint();
         if (tpList == null) {
@@ -776,47 +864,45 @@ public class SouthboundIT extends AbstractMdsalTestBase {
     public void testCRDTerminationPointOfPort() throws InterruptedException {
         final Long OFPORT_EXPECTED = 45002L;
 
-        ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr);
-        connectOvsdbNode(connectionInfo);
+        ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
 
         // CREATE
-        Assert.assertTrue(addBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME));
-        OvsdbBridgeAugmentation bridge = getBridge(connectionInfo);
-        Assert.assertNotNull(bridge);
-        LOG.info("bridge: {}", bridge);
-        NodeId nodeId = SouthboundMapper.createManagedNodeId(createInstanceIdentifier(
-                connectionInfo, bridge.getBridgeName()));
-        OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder =
-                createGenericOvsdbTerminationPointAugmentationBuilder();
-        String portName = "testOfPort";
-        ovsdbTerminationBuilder.setName(portName);
+        try (TestBridge testBridge = new TestBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME)) {
+            OvsdbBridgeAugmentation bridge = getBridge(connectionInfo);
+            Assert.assertNotNull(bridge);
+            LOG.info("bridge: {}", bridge);
+            NodeId nodeId = SouthboundMapper.createManagedNodeId(SouthboundUtils.createInstanceIdentifier(
+                    connectionInfo, bridge.getBridgeName()));
+            OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder =
+                    createGenericOvsdbTerminationPointAugmentationBuilder();
+            String portName = "testOfPort";
+            ovsdbTerminationBuilder.setName(portName);
+
+            ovsdbTerminationBuilder.setOfport(OFPORT_EXPECTED);
+            Assert.assertTrue(addTerminationPoint(nodeId, portName, ovsdbTerminationBuilder));
+            InstanceIdentifier<Node> terminationPointIid = getTpIid(connectionInfo, bridge);
+            Node terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid);
+            Assert.assertNotNull(terminationPointNode);
 
-        ovsdbTerminationBuilder.setOfport(OFPORT_EXPECTED);
-        Assert.assertTrue(addTerminationPoint(nodeId, portName, ovsdbTerminationBuilder));
-        InstanceIdentifier<Node> terminationPointIid = getTpIid(connectionInfo, bridge);
-        Node terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid);
-        Assert.assertNotNull(terminationPointNode);
-
-        // READ
-        List<TerminationPoint> terminationPoints = terminationPointNode.getTerminationPoint();
-        for (TerminationPoint terminationPoint : terminationPoints) {
-            OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation =
-                    terminationPoint.getAugmentation(OvsdbTerminationPointAugmentation.class);
-            if (ovsdbTerminationPointAugmentation.getName().equals(portName)) {
-                Long ofPort = ovsdbTerminationPointAugmentation.getOfport();
-                // if ephemeral port 45002 is in use, ofPort is set to 1
-                Assert.assertTrue(ofPort.equals(OFPORT_EXPECTED) || ofPort.equals(new Long(1)));
-                LOG.info("ofPort: {}", ofPort);
+            // READ
+            List<TerminationPoint> terminationPoints = terminationPointNode.getTerminationPoint();
+            for (TerminationPoint terminationPoint : terminationPoints) {
+                OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation =
+                        terminationPoint.getAugmentation(OvsdbTerminationPointAugmentation.class);
+                if (ovsdbTerminationPointAugmentation.getName().equals(portName)) {
+                    Long ofPort = ovsdbTerminationPointAugmentation.getOfport();
+                    // if ephemeral port 45002 is in use, ofPort is set to 1
+                    Assert.assertTrue(ofPort.equals(OFPORT_EXPECTED) || ofPort.equals(1L));
+                    LOG.info("ofPort: {}", ofPort);
+                }
             }
-        }
 
-        // UPDATE- Not Applicable.  From the OpenVSwitch Documentation:
-        //   "A client should ideally set this column’s value in the same database transaction that it uses to create
-        //   the interface."
+            // UPDATE- Not Applicable.  From the OpenVSwitch Documentation:
+            //   "A client should ideally set this column’s value in the same database transaction that it uses to create
+            //   the interface."
 
-        // DELETE
-        Assert.assertTrue(deleteBridge(connectionInfo));
-        Assert.assertTrue(disconnectOvsdbNode(connectionInfo));
+            // DELETE handled by TestBridge
+        }
     }
 
     @Test
@@ -824,735 +910,207 @@ public class SouthboundIT extends AbstractMdsalTestBase {
         final Long OFPORT_EXPECTED = 45008L;
         final Long OFPORT_INPUT = 45008L;
 
-        ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr);
-        connectOvsdbNode(connectionInfo);
+        ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
 
         // CREATE
-        Assert.assertTrue(addBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME));
-        OvsdbBridgeAugmentation bridge = getBridge(connectionInfo);
-        Assert.assertNotNull(bridge);
-        NodeId nodeId = createManagedNodeId(createInstanceIdentifier(
-                connectionInfo, bridge.getBridgeName()));
-        OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder =
-                createGenericOvsdbTerminationPointAugmentationBuilder();
-        String portName = "testOfPortRequest";
-        ovsdbTerminationBuilder.setName(portName);
-        Integer ofPortRequestExpected = OFPORT_EXPECTED.intValue();
-        ovsdbTerminationBuilder.setOfport(OFPORT_INPUT);
-        ovsdbTerminationBuilder.setOfportRequest(ofPortRequestExpected);
-        Assert.assertTrue(addTerminationPoint(nodeId, portName, ovsdbTerminationBuilder));
-        InstanceIdentifier<Node> terminationPointIid = getTpIid(connectionInfo, bridge);
-        Node terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid);
-        Assert.assertNotNull(terminationPointNode);
-
-        // READ
-        List<TerminationPoint> terminationPoints = terminationPointNode.getTerminationPoint();
-        for (TerminationPoint terminationPoint : terminationPoints) {
-            OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation =
-                    terminationPoint.getAugmentation(OvsdbTerminationPointAugmentation.class);
-            if (ovsdbTerminationPointAugmentation.getName().equals(portName)) {
-                Long ofPort = ovsdbTerminationPointAugmentation.getOfport();
-                // if ephemeral port 45008 is in use, ofPort is set to 1
-                Assert.assertTrue(ofPort.equals(OFPORT_EXPECTED) || ofPort.equals(new Long(1)));
-                LOG.info("ofPort: {}", ofPort);
-
-                Integer ofPortRequest = ovsdbTerminationPointAugmentation.getOfportRequest();
-                Assert.assertTrue(ofPortRequest.equals(ofPortRequestExpected));
-                LOG.info("ofPortRequest: {}", ofPortRequest);
+        try (TestBridge testBridge = new TestBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME)) {
+            OvsdbBridgeAugmentation bridge = getBridge(connectionInfo);
+            Assert.assertNotNull(bridge);
+            NodeId nodeId = SouthboundUtils.createManagedNodeId(SouthboundUtils.createInstanceIdentifier(
+                    connectionInfo, bridge.getBridgeName()));
+            OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder =
+                    createGenericOvsdbTerminationPointAugmentationBuilder();
+            String portName = "testOfPortRequest";
+            ovsdbTerminationBuilder.setName(portName);
+            Integer ofPortRequestExpected = OFPORT_EXPECTED.intValue();
+            ovsdbTerminationBuilder.setOfport(OFPORT_INPUT);
+            ovsdbTerminationBuilder.setOfportRequest(ofPortRequestExpected);
+            Assert.assertTrue(addTerminationPoint(nodeId, portName, ovsdbTerminationBuilder));
+            InstanceIdentifier<Node> terminationPointIid = getTpIid(connectionInfo, bridge);
+            Node terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid);
+            Assert.assertNotNull(terminationPointNode);
+
+            // READ
+            List<TerminationPoint> terminationPoints = terminationPointNode.getTerminationPoint();
+            for (TerminationPoint terminationPoint : terminationPoints) {
+                OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation =
+                        terminationPoint.getAugmentation(OvsdbTerminationPointAugmentation.class);
+                if (ovsdbTerminationPointAugmentation.getName().equals(portName)) {
+                    Long ofPort = ovsdbTerminationPointAugmentation.getOfport();
+                    // if ephemeral port 45008 is in use, ofPort is set to 1
+                    Assert.assertTrue(ofPort.equals(OFPORT_EXPECTED) || ofPort.equals(1L));
+                    LOG.info("ofPort: {}", ofPort);
+
+                    Integer ofPortRequest = ovsdbTerminationPointAugmentation.getOfportRequest();
+                    Assert.assertTrue(ofPortRequest.equals(ofPortRequestExpected));
+                    LOG.info("ofPortRequest: {}", ofPortRequest);
+                }
             }
-        }
 
-        // UPDATE- Not Applicable.  From the OpenVSwitch documentation:
-        //   "A client should ideally set this column’s value in the same database transaction that it uses to create
-        //   the interface. "
+            // UPDATE- Not Applicable.  From the OpenVSwitch documentation:
+            //   "A client should ideally set this column’s value in the same database transaction that it uses to
+            //   create the interface. "
 
-        // DELETE
-        Assert.assertTrue(deleteBridge(connectionInfo));
-        Assert.assertTrue(disconnectOvsdbNode(connectionInfo));
+            // DELETE handled by TestBridge
+        }
     }
 
-    private interface KeyValueBuilder<T> {
-        T build(String testName, String key, String value);
-        T[] build(String testName, int count, String key, String value);
-        void reset();
+    private <T> void assertExpectedExist(List<T> expected, List<T> test) {
+        if (expected != null && test != null) {
+            for (T exp : expected) {
+                Assert.assertTrue("The retrieved values don't contain " + exp, test.contains(exp));
+            }
+        }
     }
 
-    private abstract static class BaseKeyValueBuilder<T> implements KeyValueBuilder<T> {
-        private static final int COUNTER_START = 0;
-        private int counter = COUNTER_START;
-        private final Class<T> builtClass;
+    private interface SouthboundTerminationPointHelper<T> {
+        void writeValues(OvsdbTerminationPointAugmentationBuilder builder, List<T> values);
+        List<T> readValues(OvsdbTerminationPointAugmentation augmentation);
+    }
 
-        protected abstract Builder<T> builder();
+    /*
+     * Tests the CRUD operations for <code>Port</code> <code>external_ids</code>.
+     *
+     * @see <code>SouthboundIT.generatePortExternalIdsTestCases()</code> for specific test case information
+     */
+    private <T> void testCRUDTerminationPoint(
+            KeyValueBuilder<T> builder, String prefix, SouthboundTerminationPointHelper<T> helper)
+            throws InterruptedException {
+        final int TERMINATION_POINT_TEST_INDEX = 0;
 
-        protected abstract void setKey(Builder<T> builder, String key);
+        ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
 
-        protected abstract void setValue(Builder<T> builder, String value);
+        // updateFromTestCases represent the original test case value.  updateToTestCases represent the new value after
+        // the update has been performed.
+        List<SouthboundTestCase<T>> updateFromTestCases = generateKeyValueTestCases(builder, prefix + "From");
+        List<SouthboundTestCase<T>> updateToTestCases = generateKeyValueTestCases(builder, prefix + "To");
 
-        @SuppressWarnings("unchecked")
-        private BaseKeyValueBuilder() {
-            builtClass = (Class<T>) this.getClass().getSuperclass().getTypeParameters()[0].getClass();
-        }
+        for (SouthboundTestCase<T> updateFromTestCase : updateFromTestCases) {
+            for (SouthboundTestCase<T> updateToTestCase : updateToTestCases) {
+                String testBridgeAndPortName = String.format("%s_%s", prefix, updateToTestCase.name);
 
-        @Override
-        public final T build(final String testName, final String key, final String value) {
-            final Builder<T> builder = builder();
-            this.counter++;
-            if (key != null) {
-                setKey(builder, String.format(FORMAT_STR, testName, key, this.counter));
-            }
-            if (value != null) {
-                setValue(builder, String.format(FORMAT_STR, testName, value, this.counter));
-            }
-            return builder.build();
-        }
+                // CREATE: Create the test bridge
+                try (TestBridge testBridge = new TestBridge(connectionInfo, null, testBridgeAndPortName, null, true,
+                        SouthboundConstants.OVSDB_FAIL_MODE_MAP.inverse().get("secure"), true, null, null, null,
+                        null)) {
+                    NodeId testBridgeNodeId = SouthboundUtils.createManagedNodeId(
+                            SouthboundUtils.createInstanceIdentifier(connectionInfo,
+                                    new OvsdbBridgeName(testBridgeAndPortName)));
+                    OvsdbTerminationPointAugmentationBuilder tpCreateAugmentationBuilder =
+                            createGenericOvsdbTerminationPointAugmentationBuilder();
+                    tpCreateAugmentationBuilder.setName(testBridgeAndPortName);
+                    helper.writeValues(tpCreateAugmentationBuilder, updateFromTestCase.inputValues);
+                    Assert.assertTrue(
+                            addTerminationPoint(testBridgeNodeId, testBridgeAndPortName, tpCreateAugmentationBuilder));
+
+                    // READ: Read the test port and ensure changes are propagated to the CONFIGURATION data store,
+                    // then repeat for OPERATIONAL data store
+                    OvsdbTerminationPointAugmentation updateFromConfigurationTerminationPointAugmentation =
+                            getOvsdbTerminationPointAugmentation(connectionInfo, testBridgeAndPortName,
+                                    LogicalDatastoreType.CONFIGURATION, TERMINATION_POINT_TEST_INDEX);
+                    if (updateFromConfigurationTerminationPointAugmentation != null) {
+                        List<T> updateFromConfigurationValues =
+                                helper.readValues(updateFromConfigurationTerminationPointAugmentation);
+                        assertExpectedExist(updateFromTestCase.expectedValues, updateFromConfigurationValues);
+                    }
+                    OvsdbTerminationPointAugmentation updateFromOperationalTerminationPointAugmentation =
+                            getOvsdbTerminationPointAugmentation(connectionInfo, testBridgeAndPortName,
+                                    LogicalDatastoreType.OPERATIONAL, TERMINATION_POINT_TEST_INDEX);
+                    if (updateFromOperationalTerminationPointAugmentation != null) {
+                        List<T> updateFromOperationalValues =
+                                helper.readValues(updateFromOperationalTerminationPointAugmentation);
+                        assertExpectedExist(updateFromTestCase.expectedValues, updateFromOperationalValues);
+                    }
 
-        @SuppressWarnings("unchecked")
-        @Override
-        public final T[] build(final String testName, final int count, final String key, final String value) {
-            final T[] instances = (T[]) Array.newInstance(builtClass, count);
-            for (int idx = 0; idx < count; idx++) {
-                instances[idx] = build(testName, key, value);
+                    // UPDATE:  update the values
+                    testBridgeNodeId = getBridgeNode(connectionInfo, testBridgeAndPortName).getNodeId();
+                    OvsdbTerminationPointAugmentationBuilder tpUpdateAugmentationBuilder =
+                            new OvsdbTerminationPointAugmentationBuilder();
+                    helper.writeValues(tpUpdateAugmentationBuilder, updateToTestCase.inputValues);
+                    InstanceIdentifier<Node> portIid = SouthboundMapper.createInstanceIdentifier(testBridgeNodeId);
+                    NodeBuilder portUpdateNodeBuilder = new NodeBuilder();
+                    NodeId portUpdateNodeId = SouthboundUtils.createManagedNodeId(portIid);
+                    portUpdateNodeBuilder.setNodeId(portUpdateNodeId);
+                    TerminationPointBuilder tpUpdateBuilder = new TerminationPointBuilder();
+                    tpUpdateBuilder.setKey(new TerminationPointKey(new TpId(testBridgeAndPortName)));
+                    tpUpdateBuilder.addAugmentation(
+                            OvsdbTerminationPointAugmentation.class,
+                            tpUpdateAugmentationBuilder.build());
+                    portUpdateNodeBuilder.setTerminationPoint(Lists.newArrayList(tpUpdateBuilder.build()));
+                    Assert.assertTrue(mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION,
+                            portIid, portUpdateNodeBuilder.build()));
+                    Thread.sleep(OVSDB_UPDATE_TIMEOUT);
+
+                    // READ: the test port and ensure changes are propagated to the CONFIGURATION data store,
+                    // then repeat for OPERATIONAL data store
+                    OvsdbTerminationPointAugmentation updateToConfigurationTerminationPointAugmentation =
+                            getOvsdbTerminationPointAugmentation(connectionInfo, testBridgeAndPortName,
+                                    LogicalDatastoreType.CONFIGURATION, TERMINATION_POINT_TEST_INDEX);
+                    if (updateToConfigurationTerminationPointAugmentation != null) {
+                        List<T> updateToConfigurationValues =
+                                helper.readValues(updateToConfigurationTerminationPointAugmentation);
+                        assertExpectedExist(updateToTestCase.expectedValues, updateToConfigurationValues);
+                        assertExpectedExist(updateFromTestCase.expectedValues, updateToConfigurationValues);
+                    }
+                    OvsdbTerminationPointAugmentation updateToOperationalTerminationPointAugmentation =
+                            getOvsdbTerminationPointAugmentation(connectionInfo, testBridgeAndPortName,
+                                    LogicalDatastoreType.OPERATIONAL, TERMINATION_POINT_TEST_INDEX);
+                    if (updateToOperationalTerminationPointAugmentation != null) {
+                        List<T> updateToOperationalValues =
+                                helper.readValues(updateToOperationalTerminationPointAugmentation);
+                        if (updateFromTestCase.expectedValues != null) {
+                            assertExpectedExist(updateToTestCase.expectedValues, updateToOperationalValues);
+                            assertExpectedExist(updateFromTestCase.expectedValues, updateToOperationalValues);
+                        }
+                    }
+
+                    // DELETE handled by TestBridge
+                }
             }
-            return instances;
         }
+    }
 
-        @Override
-        public final void reset() {
-            this.counter = COUNTER_START;
-        }
+    /*
+     * Tests the CRUD operations for <code>Port</code> <code>external_ids</code>.
+     *
+     * @see <code>SouthboundIT.generatePortExternalIdsTestCases()</code> for specific test case information
+     */
+    @Test
+    public void testCRUDTerminationPointPortExternalIds() throws InterruptedException {
+        testCRUDTerminationPoint(new SouthboundPortExternalIdsBuilder(), "TPPortExternalIds",
+                new PortExternalIdsSouthboundHelper());
     }
 
-    private static final class SouthboundPortExternalIdsBuilder extends BaseKeyValueBuilder<PortExternalIds> {
-        @Override
-        protected Builder<PortExternalIds> builder() {
-            return new PortExternalIdsBuilder();
-        }
+    /*
+     * Tests the CRUD operations for <code>Interface</code> <code>external_ids</code>.
+     *
+     * @see <code>SouthboundIT.generateInterfaceExternalIdsTestCases()</code> for specific test case information
+     */
+    @Test
+    public void testCRUDTerminationPointInterfaceExternalIds() throws InterruptedException {
+        testCRUDTerminationPoint(new SouthboundInterfaceExternalIdsBuilder(), "TPInterfaceExternalIds",
+                new InterfaceExternalIdsSouthboundHelper());
+    }
 
-        @Override
-        protected void setKey(Builder<PortExternalIds> builder, String key) {
-            ((PortExternalIdsBuilder) builder).setExternalIdKey(key);
-        }
+    /*
+     * Tests the CRUD operations for <code>TerminationPoint</code> <code>options</code>.
+     *
+     * @see <code>SouthboundIT.generateTerminationPointOptions()</code> for specific test case information
+     */
+    @Test
+    public void testCRUDTerminationPointOptions() throws InterruptedException {
+        testCRUDTerminationPoint(new SouthboundOptionsBuilder(), "TPOptions", new OptionsSouthboundHelper());
+    }
 
-        @Override
-        protected void setValue(Builder<PortExternalIds> builder, String value) {
-            ((PortExternalIdsBuilder) builder).setExternalIdValue(value);
-        }
-    }
-
-    private static final class SouthboundInterfaceExternalIdsBuilder extends BaseKeyValueBuilder<InterfaceExternalIds> {
-        @Override
-        protected Builder<InterfaceExternalIds> builder() {
-            return new InterfaceExternalIdsBuilder();
-        }
-
-        @Override
-        protected void setKey(Builder<InterfaceExternalIds> builder, String key) {
-            ((InterfaceExternalIdsBuilder) builder).setExternalIdKey(key);
-        }
-
-        @Override
-        protected void setValue(Builder<InterfaceExternalIds> builder, String value) {
-            ((InterfaceExternalIdsBuilder) builder).setExternalIdValue(value);
-        }
-    }
-
-    private static final class SouthboundOptionsBuilder extends BaseKeyValueBuilder<Options> {
-        @Override
-        protected Builder<Options> builder() {
-            return new OptionsBuilder();
-        }
-
-        @Override
-        protected void setKey(Builder<Options> builder, String key) {
-            ((OptionsBuilder) builder).setOption(key);
-        }
-
-        @Override
-        protected void setValue(Builder<Options> builder, String value) {
-            ((OptionsBuilder) builder).setValue(value);
-        }
-    }
-
-    private static final class SouthboundInterfaceOtherConfigsBuilder extends BaseKeyValueBuilder<InterfaceOtherConfigs> {
-        @Override
-        protected Builder<InterfaceOtherConfigs> builder() {
-            return new InterfaceOtherConfigsBuilder();
-        }
-
-        @Override
-        protected void setKey(Builder<InterfaceOtherConfigs> builder, String key) {
-            ((InterfaceOtherConfigsBuilder) builder).setOtherConfigKey(key);
-        }
-
-        @Override
-        protected void setValue(Builder<InterfaceOtherConfigs> builder, String value) {
-            ((InterfaceOtherConfigsBuilder) builder).setOtherConfigValue(value);
-        }
-    }
-
-    private static final class SouthboundPortOtherConfigsBuilder extends BaseKeyValueBuilder<PortOtherConfigs> {
-        @Override
-        protected Builder<PortOtherConfigs> builder() {
-            return new PortOtherConfigsBuilder();
-        }
-
-        @Override
-        protected void setKey(Builder<PortOtherConfigs> builder, String key) {
-            ((PortOtherConfigsBuilder) builder).setOtherConfigKey(key);
-        }
-
-        @Override
-        protected void setValue(Builder<PortOtherConfigs> builder, String value) {
-            ((PortOtherConfigsBuilder) builder).setOtherConfigValue(value);
-        }
-    }
-
-    private static final class SouthboundBridgeOtherConfigsBuilder extends BaseKeyValueBuilder<BridgeOtherConfigs> {
-        @Override
-        protected Builder<BridgeOtherConfigs> builder() {
-            return new BridgeOtherConfigsBuilder();
-        }
-
-        @Override
-        protected void setKey(Builder<BridgeOtherConfigs> builder, String key) {
-            ((BridgeOtherConfigsBuilder) builder).setBridgeOtherConfigKey(key);
-        }
-
-        @Override
-        protected void setValue(Builder<BridgeOtherConfigs> builder, String value) {
-            ((BridgeOtherConfigsBuilder) builder).setBridgeOtherConfigValue(value);
-        }
-    }
-
-    private static final class SouthboundBridgeExternalIdsBuilder extends BaseKeyValueBuilder<BridgeExternalIds> {
-        @Override
-        protected Builder<BridgeExternalIds> builder() {
-            return new BridgeExternalIdsBuilder();
-        }
-
-        @Override
-        protected void setKey(Builder<BridgeExternalIds> builder, String key) {
-            ((BridgeExternalIdsBuilder) builder).setBridgeExternalIdKey(key);
-        }
-
-        @Override
-        protected void setValue(Builder<BridgeExternalIds> builder, String value) {
-            ((BridgeExternalIdsBuilder) builder).setBridgeExternalIdValue(value);
-        }
-    }
-
-    /*
-     * Generates the test cases involved in testing key-value-based data.  See inline comments for descriptions of
-     * the particular cases considered.
-     */
-    private static <T> List<SouthboundTestCase<T>> generateKeyValueTestCases(
-            KeyValueBuilder<T> builder, String idKey, String idValue) {
-        List<SouthboundTestCase<T>> testCases = new ArrayList<>();
-
-        final String GOOD_KEY = "GoodKey";
-        final String GOOD_VALUE = "GoodValue";
-        final String NO_VALUE_FOR_KEY = "NoValueForKey";
-        final String NO_KEY_FOR_VALUE = "NoKeyForValue";
-
-        // Test Case 1:  TestOne
-        // Test Type:    Positive
-        // Description:  Create a termination point with one value
-        // Expected:     A port is created with the single value specified below
-        final String testOneName = "TestOne";
-        testCases.add(new SouthboundTestCaseBuilder<T>()
-                .name(testOneName)
-                .input(builder.build(testOneName, idKey, idValue))
-                .expectInputAsOutput()
-                .build());
-        builder.reset();
-
-        // Test Case 2:  TestFive
-        // Test Type:    Positive
-        // Description:  Create a termination point with multiple (five) values
-        // Expected:     A port is created with the five values specified below
-        final String testFiveName = "TestFive";
-        testCases.add(new SouthboundTestCaseBuilder<T>()
-                .name(testFiveName)
-                .input(builder.build(testFiveName, 5, idKey, idValue))
-                .expectInputAsOutput()
-                .build());
-        builder.reset();
-
-        // Test Case 3:  TestOneGoodOneMalformedValue
-        // Test Type:    Negative
-        // Description:
-        //     One perfectly fine input
-        //        (TestOneGoodOneMalformedValue_GoodKey_1,
-        //        TestOneGoodOneMalformedValue_GoodValue_1)
-        //     and one malformed input which only has key specified
-        //        (TestOneGoodOneMalformedValue_NoValueForKey_2,
-        //        UNSPECIFIED)
-        // Expected:     A port is created without any values
-        final String testOneGoodOneMalformedValueName = "TestOneGoodOneMalformedValue";
-        testCases.add(new SouthboundTestCaseBuilder<T>()
-                .name(testOneGoodOneMalformedValueName)
-                .input(
-                        builder.build(testOneGoodOneMalformedValueName, GOOD_KEY, GOOD_VALUE),
-                        builder.build(testOneGoodOneMalformedValueName, NO_VALUE_FOR_KEY, null)
-                )
-                .expect()
-                .build());
-        builder.reset();
-
-        // Test Case 4:  TestOneGoodOneMalformedKey
-        // Test Type:    Negative
-        // Description:
-        //     One perfectly fine input
-        //        (TestOneGoodOneMalformedKey_GoodKey_1,
-        //        TestOneGoodOneMalformedKey_GoodValue_1)
-        //     and one malformed input which only has value specified
-        //        (UNSPECIFIED,
-        //        TestOneGoodOneMalformedKey_NoKeyForValue_2)
-        // Expected:     A port is created without any values
-        final String testOneGoodOneMalformedKeyName = "TestOneGoodOneMalformedKey";
-        testCases.add(new SouthboundTestCaseBuilder<T>()
-                .name(testOneGoodOneMalformedKeyName)
-                .input(
-                        builder.build(testOneGoodOneMalformedKeyName, GOOD_KEY, GOOD_VALUE),
-                        builder.build(testOneGoodOneMalformedKeyName, null, NO_KEY_FOR_VALUE)
-                )
-                .expect()
-                .build());
-        builder.reset();
-
-        return testCases;
-    }
-
-    /*
-     * Generates the test cases involved in testing PortExternalIds.  See inline comments for descriptions of
-     * the particular cases considered.
-     */
-    private List<SouthboundTestCase<PortExternalIds>> generatePortExternalIdsTestCases() {
-        return generateKeyValueTestCases(new SouthboundPortExternalIdsBuilder(), "PortExternalIdKey",
-                "PortExternalIdValue");
-    }
-
-    /*
-     * Tests the CRUD operations for <code>Port</code>
-     * <code>external_ids</code>.
-     *
-     * @see <code>SouthboundIT.generatePortExternalIdsTestCases()</code> for
-     * specific test case information
-     */
-    @Test
-    public void testCRUDTerminationPointPortExternalIds()
-            throws InterruptedException, ExecutionException {
-
-        final String TEST_PREFIX = "CRUDTPPortExternalIds";
-
-        ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr);
-        connectOvsdbNode(connectionInfo);
-
-        // updateFromTestCases represent the original test case value.
-        // updateToTestCases represent the new value after the update has been
-        // performed.
-        List<SouthboundTestCase<PortExternalIds>> updateFromTestCases = generatePortExternalIdsTestCases();
-        List<SouthboundTestCase<PortExternalIds>> updateToTestCases = generatePortExternalIdsTestCases();
-        String testBridgeName;
-        String testPortName;
-
-        int counter = 1;
-        // multihreads the test using NUM_THREADS
-        ExecutorService executor = Executors.newFixedThreadPool(NUM_THREADS);
-        for (SouthboundTestCase<PortExternalIds> fromTestCase : updateFromTestCases) {
-            for (SouthboundTestCase<PortExternalIds> toTestCase : updateToTestCases) {
-                testPortName = testBridgeName = String.format(FORMAT_STR,
-                        TEST_PREFIX, toTestCase.name, counter);
-                counter += 1;
-                executor.submit(new TestCRUDTerminationPointRunnable<>(
-                        new SouthboundTestHelper<PortExternalIds>() {
-                            @Override
-                            public List<PortExternalIds> readValues(
-                                    OvsdbTerminationPointAugmentation augmentation) {
-                                return augmentation.getPortExternalIds();
-                            }
-
-                            @Override
-                            public void writeValues(
-                                    OvsdbTerminationPointAugmentationBuilder augmentationBuilder,
-                                    List<PortExternalIds> updateFromInput) {
-                                augmentationBuilder.setPortExternalIds(updateFromInput);
-                            }
-                        },
-                        connectionInfo, testBridgeName, testPortName,
-                        fromTestCase.inputValues,
-                        fromTestCase.expectedValues,
-                        toTestCase.inputValues,
-                        toTestCase.expectedValues));
-            }
-        }
-        executor.shutdown();
-        executor.awaitTermination(5, TimeUnit.MINUTES);
-        Assert.assertTrue(disconnectOvsdbNode(connectionInfo));
-    }
-
-    /**
-     * Southbound test helper. Classes implementing this interface are used to provide concrete access to the input and
-     * output of the underlying augmentation for the type being managed.
-     *
-     * @param <T> The type of data used for the test case.
-     */
-    private interface SouthboundTestHelper<T> {
-        /**
-         * Read the values from the augmentation. These would usually be checked against the expected values provided
-         * for the test case.
-         *
-         * @param augmentation The augmentation to read from.
-         * @return The values read.
-         */
-        List<T> readValues(OvsdbTerminationPointAugmentation augmentation);
-
-        /**
-         * Write the values to the augmentation (via its builder). This would usually be used to apply the input values
-         * provided for the test case.
-         *
-         * @param augmentationBuilder The augmentation builder.
-         * @param values The values to write.
-         */
-        void writeValues(OvsdbTerminationPointAugmentationBuilder augmentationBuilder, List<T> values);
-    }
-
-    /**
-     * <p>
-     * Test runner used to apply a suite of create/read/update/delete tests. Each instance of a runner expects:
-     * </p>
-     * <ul>
-     * <li>a helper used to manipulate the appropriate data structures in the termination point augmentation (see
-     * {@link SouthboundTestHelper});</li>
-     * <li>connection information for the southbound;</li>
-     * <li>a name to use for the test bridge (this allows multiple tests to be conducted in parallel against different
-     * bridges);</li>
-     * <li>a name to use for the test port;</li>
-     * <li>the initial input values to use for the termination point augmentation;</li>
-     * <li>the initial expected values to check the augmentation against;</li>
-     * <li>the target input values to update the terminal point to;</li>
-     * <li>the target expected values to check the augmentation point against.</li>
-     * </ul>
-     * <p>The following tests are performed:</p>
-     * <ol>
-     * <li>the bridge is added;</li>
-     * <li>the termination point is added, with the provided initial input values;</li>
-     * <li>the termination point is read from the <em>configuration</em> data store, and checked against the provided
-     * initial expected values;</li>
-     * <li>the termination point is read from the <em>operational</em> data store, and checked against the provided
-     * initial expected values;</li>
-     * <li>the termination point is updated by merging the provided target input values;</li>
-     * <li>the termination point is read from the <em>configuration</em> data store, and checked against the provided
-     * initial <b>and</b> target expected values;</li>
-     * <li>the termination point is read from the <em>operational</em> data store, and checked against the provided
-     * initial <b>and</b> target expected values;</li>
-     * <li>the bridge is deleted.</li>
-     * </ol>
-     *
-     * @param <T> The type of data used for the test case.
-     */
-    private final class TestCRUDTerminationPointRunnable<T> implements Runnable {
-        private final SouthboundTestHelper<T> helper;
-        private final ConnectionInfo connectionInfo;
-        private final String testBridgeName;
-        private final String testPortName;
-        private final List<T> updateFromInput;
-        private final List<T> updateFromExpected;
-        private final List<T> updateToInput;
-        private final List<T> updateToExpected;
-
-        private TestCRUDTerminationPointRunnable(
-                SouthboundTestHelper<T> helper, ConnectionInfo connectionInfo, String testBridgeName,
-                String testPortName, List<T> updateFromInput, List<T> updateFromExpected, List<T> updateToInput,
-                List<T> updateToExpected) {
-            this.helper = helper;
-            this.connectionInfo = connectionInfo;
-            this.testBridgeName = testBridgeName;
-            this.testPortName = testPortName;
-            this.updateFromInput = updateFromInput;
-            this.updateFromExpected = updateFromExpected;
-            this.updateToInput = updateToInput;
-            this.updateToExpected = updateToExpected;
-        }
-
-        @Override
-        public void run() {
-            try {
-                final int TERMINATION_POINT_TEST_INDEX = 0;
-                // CREATE: Create the test bridge
-                Assert.assertTrue(addBridge(connectionInfo, null,
-                        testBridgeName, null, true,
-                        SouthboundConstants.OVSDB_FAIL_MODE_MAP.inverse().get("secure"),
-                        true, null, null, null, null));
-                NodeId testBridgeNodeId = createManagedNodeId(createInstanceIdentifier(
-                        connectionInfo, new OvsdbBridgeName(testBridgeName)));
-                OvsdbTerminationPointAugmentationBuilder tpCreateAugmentationBuilder =
-                        createGenericOvsdbTerminationPointAugmentationBuilder();
-                tpCreateAugmentationBuilder.setName(testPortName);
-                helper.writeValues(tpCreateAugmentationBuilder, updateFromInput);
-                Assert.assertTrue(addTerminationPoint(testBridgeNodeId, testPortName, tpCreateAugmentationBuilder));
-
-                // READ: Read the test port and ensure changes are propagated to the CONFIGURATION data store,
-                // then repeat for OPERATIONAL data store
-                OvsdbTerminationPointAugmentation updateFromConfigurationTerminationPointAugmentation =
-                        getOvsdbTerminationPointAugmentation(connectionInfo, testBridgeName,
-                                LogicalDatastoreType.CONFIGURATION, TERMINATION_POINT_TEST_INDEX);
-                List<T> updateFromConfiguration = null;
-                if (updateFromConfigurationTerminationPointAugmentation != null) {
-                    updateFromConfiguration =
-                        helper.readValues(updateFromConfigurationTerminationPointAugmentation);
-                }
-                if (updateFromConfiguration != null) {
-                    Assert.assertTrue(updateFromConfiguration.containsAll(updateFromExpected));
-                }
-                OvsdbTerminationPointAugmentation updateFromOperationalTerminationPointAugmentation =
-                        getOvsdbTerminationPointAugmentation(connectionInfo, testBridgeName,
-                                LogicalDatastoreType.OPERATIONAL, TERMINATION_POINT_TEST_INDEX);
-                List<T> updateFromOperational = null;
-                if (updateFromOperationalTerminationPointAugmentation != null) {
-                    updateFromOperational = helper.readValues(updateFromOperationalTerminationPointAugmentation);
-                }
-                if (updateFromOperational != null) {
-                    Assert.assertTrue(updateFromOperational.containsAll(updateFromExpected));
-                }
-
-                // UPDATE:  update the external_ids
-                testBridgeNodeId = getBridgeNode(connectionInfo, testBridgeName).getNodeId();
-                OvsdbTerminationPointAugmentationBuilder tpUpdateAugmentationBuilder =
-                        new OvsdbTerminationPointAugmentationBuilder();
-                helper.writeValues(tpUpdateAugmentationBuilder, updateToInput);
-                InstanceIdentifier<Node> portIid = SouthboundMapper.createInstanceIdentifier(testBridgeNodeId);
-                NodeBuilder portUpdateNodeBuilder = new NodeBuilder();
-                NodeId portUpdateNodeId = createManagedNodeId(portIid);
-                portUpdateNodeBuilder.setNodeId(portUpdateNodeId);
-                TerminationPointBuilder tpUpdateBuilder = new TerminationPointBuilder();
-                tpUpdateBuilder.setKey(new TerminationPointKey(new TpId(testPortName)));
-                tpUpdateBuilder.addAugmentation(
-                        OvsdbTerminationPointAugmentation.class,
-                        tpUpdateAugmentationBuilder.build());
-                portUpdateNodeBuilder.setTerminationPoint(Lists.newArrayList(tpUpdateBuilder.build()));
-                boolean result = mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION,
-                        portIid, portUpdateNodeBuilder.build());
-                Thread.sleep(OVSDB_UPDATE_TIMEOUT);
-                Assert.assertTrue(result);
-
-                // READ: the test port and ensure changes are propagated to the CONFIGURATION data store,
-                // then repeat for OPERATIONAL data store
-                OvsdbTerminationPointAugmentation updateToConfigurationTerminationPointAugmentation =
-                        getOvsdbTerminationPointAugmentation(connectionInfo, testBridgeName,
-                                LogicalDatastoreType.CONFIGURATION, TERMINATION_POINT_TEST_INDEX);
-                List<T> updateToConfiguration = helper.readValues(updateToConfigurationTerminationPointAugmentation);
-                Assert.assertTrue(updateToConfiguration.containsAll(updateToExpected));
-                Assert.assertTrue(updateToConfiguration.containsAll(updateFromExpected));
-                OvsdbTerminationPointAugmentation updateToOperationalTerminationPointAugmentation =
-                        getOvsdbTerminationPointAugmentation(connectionInfo, testBridgeName,
-                                LogicalDatastoreType.OPERATIONAL, TERMINATION_POINT_TEST_INDEX);
-                List<T> updateToOperational = helper.readValues(updateToOperationalTerminationPointAugmentation);
-                Assert.assertTrue(updateToOperational.containsAll(updateToExpected));
-                Assert.assertTrue(updateToOperational.containsAll(updateFromExpected));
-
-                // DELETE
-                Assert.assertTrue(deleteBridge(connectionInfo, testBridgeName));
-            } catch (InterruptedException e) {
-                LOG.error("Test interrupted", e);
-            }
-        }
-    }
-
-
-    /*
-     * Generates the test cases involved in testing InterfaceExternalIds.  See inline comments for descriptions of
-     * the particular cases considered.
-     */
-    private static List<SouthboundTestCase<InterfaceExternalIds>> generateInterfaceExternalIdsTestCases() {
-        return generateKeyValueTestCases(new SouthboundInterfaceExternalIdsBuilder(), "IntExternalIdKey",
-                "IntExternalIdValue");
-    }
-
-    /*
-     * Tests the CRUD operations for <code>Interface</code> <code>external_ids</code>.
-     *
-     * @see <code>SouthboundIT.generateInterfaceExternalIdsTestCases()</code> for specific test case information
-     */
-    @Test
-    public void testCRUDTerminationPointInterfaceExternalIds() throws InterruptedException, ExecutionException {
-        final String TEST_PREFIX = "CRUDTPInterfaceExternalIds";
-
-        ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr);
-        connectOvsdbNode(connectionInfo);
-
-        // updateFromTestCases represent the original test case value.  updateToTestCases represent the new value after
-        // the update has been performed.
-        List<SouthboundTestCase<InterfaceExternalIds>> updateFromTestCases = generateInterfaceExternalIdsTestCases();
-        List<SouthboundTestCase<InterfaceExternalIds>> updateToTestCases = generateInterfaceExternalIdsTestCases();
-        String testBridgeName;
-        String testPortName;
-
-        int counter = 1;
-        // multithreads the test using NUM_THREADS
-        ExecutorService executor = Executors.newFixedThreadPool(NUM_THREADS);
-        for (SouthboundTestCase<InterfaceExternalIds> fromTestCase : updateFromTestCases) {
-            for (SouthboundTestCase<InterfaceExternalIds> toTestCase : updateToTestCases) {
-                testPortName = testBridgeName = String.format(FORMAT_STR,
-                        TEST_PREFIX, toTestCase.name, counter);
-                counter += 1;
-                executor.submit(new TestCRUDTerminationPointRunnable<>(
-                        new SouthboundTestHelper<InterfaceExternalIds>() {
-                            @Override
-                            public List<InterfaceExternalIds> readValues(
-                                    OvsdbTerminationPointAugmentation augmentation) {
-                                return augmentation.getInterfaceExternalIds();
-                            }
-
-                            @Override
-                            public void writeValues(
-                                    OvsdbTerminationPointAugmentationBuilder augmentationBuilder,
-                                    List<InterfaceExternalIds> values) {
-                                augmentationBuilder.setInterfaceExternalIds(values);
-                            }
-                        },
-                        connectionInfo, testBridgeName, testPortName,
-                        fromTestCase.inputValues,
-                        fromTestCase.expectedValues,
-                        toTestCase.inputValues,
-                        toTestCase.expectedValues));
-            }
-        }
-        executor.shutdown();
-        executor.awaitTermination(5, TimeUnit.MINUTES);
-        Assert.assertTrue(disconnectOvsdbNode(connectionInfo));
-    }
-
-    /*
-     * Generates the test cases involved in testing TP Options.  See inline comments for descriptions of
-     * the particular cases considered.
-     */
-    private List<SouthboundTestCase<Options>> generateTerminationPointOptionsTestCases() {
-        return generateKeyValueTestCases(new SouthboundOptionsBuilder(), "TOPOptionsKey", "TPOptionsValue");
-    }
-
-    /*
-     * Tests the CRUD operations for <code>TerminationPoint</code> <code>options</code>.
-     *
-     * @see <code>SouthboundIT.generateTerminationPointOptions()</code> for specific test case information
-     */
-    @Test
-    public void testCRUDTerminationPointOptions() throws InterruptedException {
-        final String TEST_PREFIX = "CRUDTPOptions";
-
-        ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr);
-        connectOvsdbNode(connectionInfo);
-
-        // updateFromTestCases represent the original test case value.  updateToTestCases represent the new value after
-        // the update has been performed.
-        List<SouthboundTestCase<Options>> updateFromTestCases = generateTerminationPointOptionsTestCases();
-        List<SouthboundTestCase<Options>> updateToTestCases = generateTerminationPointOptionsTestCases();
-        String testBridgeName;
-        String testPortName;
-
-        int counter = 1;
-        ExecutorService executor = Executors.newFixedThreadPool(NUM_THREADS);
-        for (SouthboundTestCase<Options> fromTestCase : updateFromTestCases) {
-            for (SouthboundTestCase<Options> toTestCase : updateToTestCases) {
-                testPortName = testBridgeName = String.format(FORMAT_STR,
-                        TEST_PREFIX, toTestCase.name, counter);
-                counter += 1;
-                executor.submit(new TestCRUDTerminationPointRunnable<>(
-                        new SouthboundTestHelper<Options>() {
-                            @Override
-                            public List<Options> readValues(
-                                    OvsdbTerminationPointAugmentation augmentation) {
-                                return augmentation.getOptions();
-                            }
-
-                            @Override
-                            public void writeValues(
-                                    OvsdbTerminationPointAugmentationBuilder augmentationBuilder,
-                                    List<Options> values) {
-                                augmentationBuilder.setOptions(values);
-                            }
-                        },
-                        connectionInfo, testBridgeName, testPortName,
-                        fromTestCase.inputValues,
-                        fromTestCase.expectedValues,
-                        toTestCase.inputValues,
-                        toTestCase.expectedValues));
-            }
-        }
-        executor.shutdown();
-        executor.awaitTermination(5, TimeUnit.MINUTES);
-        Assert.assertTrue(disconnectOvsdbNode(connectionInfo));
-    }
-
-    /*
-     * Generates the test cases involved in testing Interface other_configs.  See inline comments for descriptions of
-     * the particular cases considered.
-     */
-    private List<SouthboundTestCase<InterfaceOtherConfigs>> generateInterfaceOtherConfigsTestCases() {
-        return generateKeyValueTestCases(new SouthboundInterfaceOtherConfigsBuilder(), "IntOtherConfigsKey",
-                "IntOtherConfigsValue");
-    }
-
-    /*
-     * Tests the CRUD operations for <code>Interface</code> <code>other_configs</code>.
-     *
-     * @see <code>SouthboundIT.generateInterfaceExternalIdsTestCases()</code> for specific test case information
-     */
-    @Test
-    public void testCRUDTerminationPointInterfaceOtherConfigs() throws InterruptedException {
-        final String TEST_PREFIX = "CRUDTPInterfaceOtherConfigs";
-
-        ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr);
-        connectOvsdbNode(connectionInfo);
-
-        // updateFromTestCases represent the original test case value.  updateToTestCases represent the new value after
-        // the update has been performed.
-        List<SouthboundTestCase<InterfaceOtherConfigs>> updateFromTestCases = generateInterfaceOtherConfigsTestCases();
-        List<SouthboundTestCase<InterfaceOtherConfigs>> updateToTestCases = generateInterfaceOtherConfigsTestCases();
-        String testBridgeName;
-        String testPortName;
-
-        int counter = 1;
-        ExecutorService executor = Executors.newFixedThreadPool(NUM_THREADS);
-        for (SouthboundTestCase<InterfaceOtherConfigs> fromTestCase : updateFromTestCases) {
-            for (SouthboundTestCase<InterfaceOtherConfigs> toTestCase : updateToTestCases) {
-                testPortName = testBridgeName = String.format(FORMAT_STR,
-                        TEST_PREFIX, toTestCase.name, counter);
-                counter += 1;
-                executor.submit(new TestCRUDTerminationPointRunnable<>(
-                        new SouthboundTestHelper<InterfaceOtherConfigs>() {
-                            @Override
-                            public List<InterfaceOtherConfigs> readValues(
-                                    OvsdbTerminationPointAugmentation augmentation) {
-                                return augmentation.getInterfaceOtherConfigs();
-                            }
-
-                            @Override
-                            public void writeValues(
-                                    OvsdbTerminationPointAugmentationBuilder augmentationBuilder,
-                                    List<InterfaceOtherConfigs> values) {
-                                augmentationBuilder.setInterfaceOtherConfigs(values);
-                            }
-                        },
-                        connectionInfo, testBridgeName, testPortName,
-                        fromTestCase.inputValues,
-                        fromTestCase.expectedValues,
-                        toTestCase.inputValues,
-                        toTestCase.expectedValues));
-            }
-        }
-        executor.shutdown();
-        executor.awaitTermination(5, TimeUnit.MINUTES);
-        Assert.assertTrue(disconnectOvsdbNode(connectionInfo));
-    }
-
-    /*
-     * Generates the test cases involved in testing Port other_configs.  See inline comments for descriptions of
-     * the particular cases considered.
-     */
-    private List<SouthboundTestCase<PortOtherConfigs>> generatePortOtherConfigsTestCases() {
-        return generateKeyValueTestCases(new SouthboundPortOtherConfigsBuilder(), "PortOtherConfigsKey",
-                "PortOtherConfigsValue");
+    /*
+     * Tests the CRUD operations for <code>Interface</code> <code>other_configs</code>.
+     *
+     * @see <code>SouthboundIT.generateInterfaceExternalIdsTestCases()</code> for specific test case information
+     */
+    @Test
+    public void testCRUDTerminationPointInterfaceOtherConfigs() throws InterruptedException {
+        testCRUDTerminationPoint(new SouthboundInterfaceOtherConfigsBuilder(), "TPInterfaceOtherConfigs",
+                new InterfaceOtherConfigsSouthboundHelper());
     }
 
     /*
@@ -1562,50 +1120,8 @@ public class SouthboundIT extends AbstractMdsalTestBase {
      */
     @Test
     public void testCRUDTerminationPointPortOtherConfigs() throws InterruptedException {
-        final String TEST_PREFIX = "CRUDTPPortOtherConfigs";
-
-        ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr);
-        connectOvsdbNode(connectionInfo);
-
-        // updateFromTestCases represent the original test case value.  updateToTestCases represent the new value after
-        // the update has been performed.
-        List<SouthboundTestCase<PortOtherConfigs>> updateFromTestCases = generatePortOtherConfigsTestCases();
-        List<SouthboundTestCase<PortOtherConfigs>> updateToTestCases = generatePortOtherConfigsTestCases();
-        String testBridgeName;
-        String testPortName;
-
-        int counter = 1;
-        ExecutorService executor = Executors.newFixedThreadPool(NUM_THREADS);
-        for (SouthboundTestCase<PortOtherConfigs> fromTestCase : updateFromTestCases) {
-            for (SouthboundTestCase<PortOtherConfigs> toTestCase : updateToTestCases) {
-                testPortName = testBridgeName = String.format(FORMAT_STR,
-                        TEST_PREFIX, toTestCase.name, counter);
-                counter += 1;
-                executor.submit(new TestCRUDTerminationPointRunnable<>(
-                        new SouthboundTestHelper<PortOtherConfigs>() {
-                            @Override
-                            public List<PortOtherConfigs> readValues(
-                                    OvsdbTerminationPointAugmentation augmentation) {
-                                return augmentation.getPortOtherConfigs();
-                            }
-
-                            @Override
-                            public void writeValues(
-                                    OvsdbTerminationPointAugmentationBuilder augmentationBuilder,
-                                    List<PortOtherConfigs> values) {
-                                augmentationBuilder.setPortOtherConfigs(values);
-                            }
-                        },
-                        connectionInfo, testBridgeName, testPortName,
-                        fromTestCase.inputValues,
-                        fromTestCase.expectedValues,
-                        toTestCase.inputValues,
-                        toTestCase.expectedValues));
-            }
-        }
-        executor.shutdown();
-        executor.awaitTermination(5, TimeUnit.MINUTES);
-        Assert.assertTrue(disconnectOvsdbNode(connectionInfo));
+        testCRUDTerminationPoint(new SouthboundPortOtherConfigsBuilder(), "TPPortOtherConfigs",
+                new PortOtherConfigsSouthboundHelper());
     }
 
     @Test
@@ -1613,96 +1129,19 @@ public class SouthboundIT extends AbstractMdsalTestBase {
         final Integer CREATED_VLAN_ID = 4000;
         final Integer UPDATED_VLAN_ID = 4001;
 
-        ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr);
-        connectOvsdbNode(connectionInfo);
+        ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
 
         // CREATE
-        Assert.assertTrue(addBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME));
-        OvsdbBridgeAugmentation bridge = getBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME);
-        Assert.assertNotNull(bridge);
-        NodeId nodeId = createManagedNodeId(createInstanceIdentifier(
-                connectionInfo, bridge.getBridgeName()));
-        OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder =
-                createGenericOvsdbTerminationPointAugmentationBuilder();
-        String portName = "testTerminationPointVlanId";
-        ovsdbTerminationBuilder.setName(portName);
-        ovsdbTerminationBuilder.setVlanTag(new VlanId(CREATED_VLAN_ID));
-        Assert.assertTrue(addTerminationPoint(nodeId, portName, ovsdbTerminationBuilder));
-        InstanceIdentifier<Node> terminationPointIid = getTpIid(connectionInfo, bridge);
-        Node terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid);
-        Assert.assertNotNull(terminationPointNode);
-
-        // READ
-        List<TerminationPoint> terminationPoints = terminationPointNode.getTerminationPoint();
-        OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation;
-        for (TerminationPoint terminationPoint : terminationPoints) {
-            ovsdbTerminationPointAugmentation = terminationPoint.getAugmentation(
-                    OvsdbTerminationPointAugmentation.class);
-            if (ovsdbTerminationPointAugmentation.getName().equals(portName)) {
-                VlanId actualVlanId = ovsdbTerminationPointAugmentation.getVlanTag();
-                Assert.assertNotNull(actualVlanId);
-                Integer actualVlanIdInt = actualVlanId.getValue();
-                Assert.assertEquals(CREATED_VLAN_ID, actualVlanIdInt);
-            }
-        }
-
-        // UPDATE
-        NodeId testBridgeNodeId = getBridgeNode(connectionInfo, SouthboundITConstants.BRIDGE_NAME).getNodeId();
-        OvsdbTerminationPointAugmentationBuilder tpUpdateAugmentationBuilder =
-                new OvsdbTerminationPointAugmentationBuilder();
-        tpUpdateAugmentationBuilder.setVlanTag(new VlanId(UPDATED_VLAN_ID));
-        InstanceIdentifier<Node> portIid = SouthboundMapper.createInstanceIdentifier(testBridgeNodeId);
-        NodeBuilder portUpdateNodeBuilder = new NodeBuilder();
-        NodeId portUpdateNodeId = createManagedNodeId(portIid);
-        portUpdateNodeBuilder.setNodeId(portUpdateNodeId);
-        TerminationPointBuilder tpUpdateBuilder = new TerminationPointBuilder();
-        tpUpdateBuilder.setKey(new TerminationPointKey(new TpId(portName)));
-        tpUpdateBuilder.addAugmentation(
-                OvsdbTerminationPointAugmentation.class,
-                tpUpdateAugmentationBuilder.build());
-        tpUpdateBuilder.setTpId(new TpId(portName));
-        portUpdateNodeBuilder.setTerminationPoint(Lists.newArrayList(tpUpdateBuilder.build()));
-        boolean result = mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION,
-                portIid, portUpdateNodeBuilder.build());
-        Assert.assertTrue(result);
-        Thread.sleep(OVSDB_UPDATE_TIMEOUT);
-
-        terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid);
-        terminationPoints = terminationPointNode.getTerminationPoint();
-        for (TerminationPoint terminationPoint : terminationPoints) {
-            ovsdbTerminationPointAugmentation = terminationPoint.getAugmentation(
-                    OvsdbTerminationPointAugmentation.class);
-            if (ovsdbTerminationPointAugmentation.getName().equals(portName)) {
-                VlanId actualVlanId = ovsdbTerminationPointAugmentation.getVlanTag();
-                Assert.assertNotNull(actualVlanId);
-                Integer actualVlanIdInt = actualVlanId.getValue();
-                Assert.assertEquals(UPDATED_VLAN_ID, actualVlanIdInt);
-            }
-        }
-
-        // DELETE
-        Assert.assertTrue(deleteBridge(connectionInfo));
-        Assert.assertTrue(disconnectOvsdbNode(connectionInfo));
-    }
-
-    @Test
-    public void testCRUDTerminationPointVlanModes() throws InterruptedException {
-        final VlanMode UPDATED_VLAN_MODE = VlanMode.Access;
-        ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr);
-        connectOvsdbNode(connectionInfo);
-        VlanMode []vlanModes = VlanMode.values();
-        for (VlanMode vlanMode : vlanModes) {
-            // CREATE
-            Assert.assertTrue(addBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME));
-            OvsdbBridgeAugmentation bridge = getBridge(connectionInfo);
+        try (TestBridge testBridge = new TestBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME)) {
+            OvsdbBridgeAugmentation bridge = getBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME);
             Assert.assertNotNull(bridge);
-            NodeId nodeId = createManagedNodeId(createInstanceIdentifier(
+            NodeId nodeId = SouthboundUtils.createManagedNodeId(SouthboundUtils.createInstanceIdentifier(
                     connectionInfo, bridge.getBridgeName()));
             OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder =
                     createGenericOvsdbTerminationPointAugmentationBuilder();
-            String portName = "testTerminationPointVlanMode" + vlanMode.toString();
+            String portName = "testTerminationPointVlanId";
             ovsdbTerminationBuilder.setName(portName);
-            ovsdbTerminationBuilder.setVlanMode(vlanMode);
+            ovsdbTerminationBuilder.setVlanTag(new VlanId(CREATED_VLAN_ID));
             Assert.assertTrue(addTerminationPoint(nodeId, portName, ovsdbTerminationBuilder));
             InstanceIdentifier<Node> terminationPointIid = getTpIid(connectionInfo, bridge);
             Node terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid);
@@ -1710,12 +1149,15 @@ public class SouthboundIT extends AbstractMdsalTestBase {
 
             // READ
             List<TerminationPoint> terminationPoints = terminationPointNode.getTerminationPoint();
+            OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation;
             for (TerminationPoint terminationPoint : terminationPoints) {
-                OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation =
-                        terminationPoint.getAugmentation(OvsdbTerminationPointAugmentation.class);
+                ovsdbTerminationPointAugmentation = terminationPoint.getAugmentation(
+                        OvsdbTerminationPointAugmentation.class);
                 if (ovsdbTerminationPointAugmentation.getName().equals(portName)) {
-                    //test
-                    Assert.assertTrue(ovsdbTerminationPointAugmentation.getVlanMode().equals(vlanMode));
+                    VlanId actualVlanId = ovsdbTerminationPointAugmentation.getVlanTag();
+                    Assert.assertNotNull(actualVlanId);
+                    Integer actualVlanIdInt = actualVlanId.getValue();
+                    Assert.assertEquals(CREATED_VLAN_ID, actualVlanIdInt);
                 }
             }
 
@@ -1723,10 +1165,10 @@ public class SouthboundIT extends AbstractMdsalTestBase {
             NodeId testBridgeNodeId = getBridgeNode(connectionInfo, SouthboundITConstants.BRIDGE_NAME).getNodeId();
             OvsdbTerminationPointAugmentationBuilder tpUpdateAugmentationBuilder =
                     new OvsdbTerminationPointAugmentationBuilder();
-            tpUpdateAugmentationBuilder.setVlanMode(UPDATED_VLAN_MODE);
+            tpUpdateAugmentationBuilder.setVlanTag(new VlanId(UPDATED_VLAN_ID));
             InstanceIdentifier<Node> portIid = SouthboundMapper.createInstanceIdentifier(testBridgeNodeId);
             NodeBuilder portUpdateNodeBuilder = new NodeBuilder();
-            NodeId portUpdateNodeId = createManagedNodeId(portIid);
+            NodeId portUpdateNodeId = SouthboundUtils.createManagedNodeId(portIid);
             portUpdateNodeBuilder.setNodeId(portUpdateNodeId);
             TerminationPointBuilder tpUpdateBuilder = new TerminationPointBuilder();
             tpUpdateBuilder.setKey(new TerminationPointKey(new TpId(portName)));
@@ -1735,53 +1177,104 @@ public class SouthboundIT extends AbstractMdsalTestBase {
                     tpUpdateAugmentationBuilder.build());
             tpUpdateBuilder.setTpId(new TpId(portName));
             portUpdateNodeBuilder.setTerminationPoint(Lists.newArrayList(tpUpdateBuilder.build()));
-            boolean result = mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION,
-                    portIid, portUpdateNodeBuilder.build());
-            Assert.assertTrue(result);
+            Assert.assertTrue(
+                    mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, portIid, portUpdateNodeBuilder.build()));
             Thread.sleep(OVSDB_UPDATE_TIMEOUT);
 
             terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid);
             terminationPoints = terminationPointNode.getTerminationPoint();
             for (TerminationPoint terminationPoint : terminationPoints) {
-                OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation =
-                        terminationPoint.getAugmentation(OvsdbTerminationPointAugmentation.class);
+                ovsdbTerminationPointAugmentation = terminationPoint.getAugmentation(
+                        OvsdbTerminationPointAugmentation.class);
                 if (ovsdbTerminationPointAugmentation.getName().equals(portName)) {
-                    //test
-                    Assert.assertEquals(UPDATED_VLAN_MODE, ovsdbTerminationPointAugmentation.getVlanMode());
+                    VlanId actualVlanId = ovsdbTerminationPointAugmentation.getVlanTag();
+                    Assert.assertNotNull(actualVlanId);
+                    Integer actualVlanIdInt = actualVlanId.getValue();
+                    Assert.assertEquals(UPDATED_VLAN_ID, actualVlanIdInt);
                 }
             }
 
-            // DELETE
-            Assert.assertTrue(deleteBridge(connectionInfo));
+            // DELETE handled by TestBridge
         }
-        Assert.assertTrue(disconnectOvsdbNode(connectionInfo));
     }
 
-    private ArrayList<Set<Integer>> generateVlanSets() {
-        ArrayList<Set<Integer>> vlanSets = new ArrayList<>();
+    @Test
+    public void testCRUDTerminationPointVlanModes() throws InterruptedException {
+        final VlanMode UPDATED_VLAN_MODE = VlanMode.Access;
+        ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
+        VlanMode []vlanModes = VlanMode.values();
+        for (VlanMode vlanMode : vlanModes) {
+            // CREATE
+            try (TestBridge testBridge = new TestBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME)) {
+                OvsdbBridgeAugmentation bridge = getBridge(connectionInfo);
+                Assert.assertNotNull(bridge);
+                NodeId nodeId = SouthboundUtils.createManagedNodeId(SouthboundUtils.createInstanceIdentifier(
+                        connectionInfo, bridge.getBridgeName()));
+                OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder =
+                        createGenericOvsdbTerminationPointAugmentationBuilder();
+                String portName = "testTerminationPointVlanMode" + vlanMode.toString();
+                ovsdbTerminationBuilder.setName(portName);
+                ovsdbTerminationBuilder.setVlanMode(vlanMode);
+                Assert.assertTrue(addTerminationPoint(nodeId, portName, ovsdbTerminationBuilder));
+                InstanceIdentifier<Node> terminationPointIid = getTpIid(connectionInfo, bridge);
+                Node terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid);
+                Assert.assertNotNull(terminationPointNode);
+
+                // READ
+                List<TerminationPoint> terminationPoints = terminationPointNode.getTerminationPoint();
+                for (TerminationPoint terminationPoint : terminationPoints) {
+                    OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation =
+                            terminationPoint.getAugmentation(OvsdbTerminationPointAugmentation.class);
+                    if (ovsdbTerminationPointAugmentation.getName().equals(portName)) {
+                        //test
+                        Assert.assertTrue(ovsdbTerminationPointAugmentation.getVlanMode().equals(vlanMode));
+                    }
+                }
 
-        Set<Integer> emptySet = new HashSet<>();
-        vlanSets.add(emptySet);
+                // UPDATE
+                NodeId testBridgeNodeId = getBridgeNode(connectionInfo, SouthboundITConstants.BRIDGE_NAME).getNodeId();
+                OvsdbTerminationPointAugmentationBuilder tpUpdateAugmentationBuilder =
+                        new OvsdbTerminationPointAugmentationBuilder();
+                tpUpdateAugmentationBuilder.setVlanMode(UPDATED_VLAN_MODE);
+                InstanceIdentifier<Node> portIid = SouthboundMapper.createInstanceIdentifier(testBridgeNodeId);
+                NodeBuilder portUpdateNodeBuilder = new NodeBuilder();
+                NodeId portUpdateNodeId = SouthboundUtils.createManagedNodeId(portIid);
+                portUpdateNodeBuilder.setNodeId(portUpdateNodeId);
+                TerminationPointBuilder tpUpdateBuilder = new TerminationPointBuilder();
+                tpUpdateBuilder.setKey(new TerminationPointKey(new TpId(portName)));
+                tpUpdateBuilder.addAugmentation(
+                        OvsdbTerminationPointAugmentation.class,
+                        tpUpdateAugmentationBuilder.build());
+                tpUpdateBuilder.setTpId(new TpId(portName));
+                portUpdateNodeBuilder.setTerminationPoint(Lists.newArrayList(tpUpdateBuilder.build()));
+                Assert.assertTrue(
+                        mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, portIid, portUpdateNodeBuilder.build()));
+                Thread.sleep(OVSDB_UPDATE_TIMEOUT);
 
-        Set<Integer> singleSet = new HashSet<>();
-        Integer single = 2222;
-        singleSet.add(single);
-        vlanSets.add(singleSet);
+                terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid);
+                terminationPoints = terminationPointNode.getTerminationPoint();
+                for (TerminationPoint terminationPoint : terminationPoints) {
+                    OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation =
+                            terminationPoint.getAugmentation(OvsdbTerminationPointAugmentation.class);
+                    if (ovsdbTerminationPointAugmentation.getName().equals(portName)) {
+                        //test
+                        Assert.assertEquals(UPDATED_VLAN_MODE, ovsdbTerminationPointAugmentation.getVlanMode());
+                    }
+                }
 
-        Set<Integer> minMaxMiddleSet = new HashSet<>();
-        Integer min = 0;
-        minMaxMiddleSet.add(min);
-        Integer max = 4095;
-        minMaxMiddleSet.add(max);
-        Integer minPlusOne = min + 1;
-        minMaxMiddleSet.add(minPlusOne);
-        Integer maxMinusOne = max - 1;
-        minMaxMiddleSet.add(maxMinusOne);
-        Integer middle = (max - min) / 2;
-        minMaxMiddleSet.add(middle);
-        vlanSets.add(minMaxMiddleSet);
+                // DELETE handled by TestBridge
+            }
+        }
+    }
 
-        return vlanSets;
+    @SuppressWarnings("unchecked")
+    private List<Set<Integer>> generateVlanSets() {
+        int min = 0;
+        int max = 4095;
+        return Lists.newArrayList(
+                Collections.<Integer>emptySet(),
+                Sets.newHashSet(2222),
+                Sets.newHashSet(min, max, min + 1, max - 1, (max - min) / 2));
     }
 
     private List<Trunks> buildTrunkList(Set<Integer> trunkSet) {
@@ -1797,91 +1290,86 @@ public class SouthboundIT extends AbstractMdsalTestBase {
     @Test
     public void testCRUDTerminationPointVlanTrunks() throws InterruptedException {
         final List<Trunks> UPDATED_TRUNKS = buildTrunkList(Sets.newHashSet(2011));
-        ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr);
-        connectOvsdbNode(connectionInfo);
+        ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
         Iterable<Set<Integer>> vlanSets = generateVlanSets();
         int testCase = 0;
         for (Set<Integer> vlanSet : vlanSets) {
             ++testCase;
             // CREATE
-            Assert.assertTrue(addBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME));
-            OvsdbBridgeAugmentation bridge = getBridge(connectionInfo);
-            Assert.assertNotNull(bridge);
-            NodeId nodeId = createManagedNodeId(createInstanceIdentifier(
-                    connectionInfo, bridge.getBridgeName()));
-            OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder =
-                    createGenericOvsdbTerminationPointAugmentationBuilder();
-            String portName = "testTerminationPointVlanTrunks" + testCase;
-            ovsdbTerminationBuilder.setName(portName);
-            List<Trunks> trunks = buildTrunkList(vlanSet);
-            ovsdbTerminationBuilder.setTrunks(trunks);
-            Assert.assertTrue(addTerminationPoint(nodeId, portName, ovsdbTerminationBuilder));
-            InstanceIdentifier<Node> terminationPointIid = getTpIid(connectionInfo, bridge);
-            Node terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid);
-            Assert.assertNotNull(terminationPointNode);
-
-            // READ
-            List<TerminationPoint> terminationPoints = terminationPointNode.getTerminationPoint();
-            for (TerminationPoint terminationPoint : terminationPoints) {
-                OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation =
-                        terminationPoint.getAugmentation(OvsdbTerminationPointAugmentation.class);
-                if (ovsdbTerminationPointAugmentation.getName().equals(portName)) {
-                    List<Trunks> actualTrunks = ovsdbTerminationPointAugmentation.getTrunks();
-                    for (Trunks trunk : trunks) {
-                        Assert.assertTrue(actualTrunks.contains(trunk));
+            try (TestBridge testBridge = new TestBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME)) {
+                OvsdbBridgeAugmentation bridge = getBridge(connectionInfo);
+                Assert.assertNotNull(bridge);
+                NodeId nodeId = SouthboundUtils.createManagedNodeId(connectionInfo, bridge.getBridgeName());
+                OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder =
+                        createGenericOvsdbTerminationPointAugmentationBuilder();
+                String portName = "testTerminationPointVlanTrunks" + testCase;
+                ovsdbTerminationBuilder.setName(portName);
+                List<Trunks> trunks = buildTrunkList(vlanSet);
+                ovsdbTerminationBuilder.setTrunks(trunks);
+                Assert.assertTrue(addTerminationPoint(nodeId, portName, ovsdbTerminationBuilder));
+                InstanceIdentifier<Node> terminationPointIid = getTpIid(connectionInfo, bridge);
+                Node terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid);
+                Assert.assertNotNull(terminationPointNode);
+
+                // READ
+                List<TerminationPoint> terminationPoints = terminationPointNode.getTerminationPoint();
+                for (TerminationPoint terminationPoint : terminationPoints) {
+                    OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation =
+                            terminationPoint.getAugmentation(OvsdbTerminationPointAugmentation.class);
+                    if (ovsdbTerminationPointAugmentation.getName().equals(portName)) {
+                        List<Trunks> actualTrunks = ovsdbTerminationPointAugmentation.getTrunks();
+                        for (Trunks trunk : trunks) {
+                            Assert.assertTrue(actualTrunks.contains(trunk));
+                        }
                     }
                 }
-            }
 
 
-            // UPDATE
-            NodeId testBridgeNodeId = getBridgeNode(connectionInfo, SouthboundITConstants.BRIDGE_NAME).getNodeId();
-            OvsdbTerminationPointAugmentationBuilder tpUpdateAugmentationBuilder =
-                    new OvsdbTerminationPointAugmentationBuilder();
-            tpUpdateAugmentationBuilder.setTrunks(UPDATED_TRUNKS);
-            InstanceIdentifier<Node> portIid = SouthboundMapper.createInstanceIdentifier(testBridgeNodeId);
-            NodeBuilder portUpdateNodeBuilder = new NodeBuilder();
-            NodeId portUpdateNodeId = createManagedNodeId(portIid);
-            portUpdateNodeBuilder.setNodeId(portUpdateNodeId);
-            TerminationPointBuilder tpUpdateBuilder = new TerminationPointBuilder();
-            tpUpdateBuilder.setKey(new TerminationPointKey(new TpId(portName)));
-            tpUpdateBuilder.addAugmentation(
-                    OvsdbTerminationPointAugmentation.class,
-                    tpUpdateAugmentationBuilder.build());
-            tpUpdateBuilder.setTpId(new TpId(portName));
-            portUpdateNodeBuilder.setTerminationPoint(Lists.newArrayList(tpUpdateBuilder.build()));
-            boolean result = mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION,
-                    portIid, portUpdateNodeBuilder.build());
-            Assert.assertTrue(result);
-            Thread.sleep(OVSDB_UPDATE_TIMEOUT);
+                // UPDATE
+                NodeId testBridgeNodeId = getBridgeNode(connectionInfo, SouthboundITConstants.BRIDGE_NAME).getNodeId();
+                OvsdbTerminationPointAugmentationBuilder tpUpdateAugmentationBuilder =
+                        new OvsdbTerminationPointAugmentationBuilder();
+                tpUpdateAugmentationBuilder.setTrunks(UPDATED_TRUNKS);
+                InstanceIdentifier<Node> portIid = SouthboundMapper.createInstanceIdentifier(testBridgeNodeId);
+                NodeBuilder portUpdateNodeBuilder = new NodeBuilder();
+                NodeId portUpdateNodeId = SouthboundUtils.createManagedNodeId(portIid);
+                portUpdateNodeBuilder.setNodeId(portUpdateNodeId);
+                TerminationPointBuilder tpUpdateBuilder = new TerminationPointBuilder();
+                tpUpdateBuilder.setKey(new TerminationPointKey(new TpId(portName)));
+                tpUpdateBuilder.addAugmentation(
+                        OvsdbTerminationPointAugmentation.class,
+                        tpUpdateAugmentationBuilder.build());
+                tpUpdateBuilder.setTpId(new TpId(portName));
+                portUpdateNodeBuilder.setTerminationPoint(Lists.newArrayList(tpUpdateBuilder.build()));
+                Assert.assertTrue(
+                        mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, portIid, portUpdateNodeBuilder.build()));
+                Thread.sleep(OVSDB_UPDATE_TIMEOUT);
 
-            terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid);
-            terminationPoints = terminationPointNode.getTerminationPoint();
-            for (TerminationPoint terminationPoint : terminationPoints) {
-                OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation =
-                        terminationPoint.getAugmentation(OvsdbTerminationPointAugmentation.class);
-                if (ovsdbTerminationPointAugmentation.getName().equals(portName)) {
-                    //test
-                    Assert.assertEquals(UPDATED_TRUNKS, ovsdbTerminationPointAugmentation.getTrunks());
+                terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid);
+                terminationPoints = terminationPointNode.getTerminationPoint();
+                for (TerminationPoint terminationPoint : terminationPoints) {
+                    OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation =
+                            terminationPoint.getAugmentation(OvsdbTerminationPointAugmentation.class);
+                    if (ovsdbTerminationPointAugmentation.getName().equals(portName)) {
+                        //test
+                        Assert.assertEquals(UPDATED_TRUNKS, ovsdbTerminationPointAugmentation.getTrunks());
+                    }
                 }
-            }
 
-            // DELETE
-            Assert.assertTrue(deleteBridge(connectionInfo));
+                // DELETE handled by TestBridge
+            }
         }
-        Assert.assertTrue(disconnectOvsdbNode(connectionInfo));
     }
 
     @Test
     public void testGetOvsdbNodes() throws InterruptedException {
-        ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr);
-        connectOvsdbNode(connectionInfo);
+        ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
         InstanceIdentifier<Topology> topologyPath = InstanceIdentifier
                 .create(NetworkTopology.class)
                 .child(Topology.class, new TopologyKey(SouthboundConstants.OVSDB_TOPOLOGY_ID));
 
         Topology topology = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, topologyPath);
-        InstanceIdentifier<Node> expectedNodeIid = createInstanceIdentifier(connectionInfo);
+        InstanceIdentifier<Node> expectedNodeIid = SouthboundUtils.createInstanceIdentifier(connectionInfo);
         NodeId expectedNodeId = expectedNodeIid.firstKeyOf(Node.class, NodeKey.class).getNodeId();
         Node foundNode = null;
         Assert.assertNotNull("Expected to find topology: " + topologyPath, topology);
@@ -1894,30 +1382,6 @@ public class SouthboundIT extends AbstractMdsalTestBase {
             }
         }
         Assert.assertNotNull("Expected to find Node: " + expectedNodeId, foundNode);
-        Assert.assertTrue(disconnectOvsdbNode(connectionInfo));
-    }
-
-    /*
-     * Generates the test cases involved in testing BridgeOtherConfigs.  See inline comments for descriptions of
-     * the particular cases considered.
-     */
-    private List<SouthboundTestCase<BridgeOtherConfigs>> generateBridgeOtherConfigsTestCases() {
-        return generateKeyValueTestCases(new SouthboundBridgeOtherConfigsBuilder(), "BridgeOtherConfigsKey",
-                "BridgeOtherConfigsValue");
-    }
-
-    /*
-     * @see <code>SouthboundIT.testCRUDBridgeOtherConfigs()</code>
-     * This is helper test method to compare a test "set" of BridgeExternalIds against an expected "set"
-     */
-    private void assertExpectedBridgeOtherConfigsExist( List<BridgeOtherConfigs> expected,
-                                                        List<BridgeOtherConfigs> test ) {
-
-        if (expected != null) {
-            for (BridgeOtherConfigs expectedOtherConfig : expected) {
-                Assert.assertTrue(test.contains(expectedOtherConfig));
-            }
-        }
     }
 
     /*
@@ -1925,306 +1389,95 @@ public class SouthboundIT extends AbstractMdsalTestBase {
      */
     @Test
     public void testCRUDBridgeOtherConfigs() throws InterruptedException {
-        final String TEST_BRIDGE_PREFIX = "CRUDBridgeOtherConfigs";
-        ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr);
-        connectOvsdbNode(connectionInfo);
-        // updateFromTestCases represent the original test case value.  updateToTestCases represent the new value after
-        // the update has been performed.
-        List<SouthboundTestCase<BridgeOtherConfigs>> updateFromTestCases = generateBridgeOtherConfigsTestCases();
-        List<SouthboundTestCase<BridgeOtherConfigs>> updateToTestCases = generateBridgeOtherConfigsTestCases();
-        String testBridgeName;
-
-        int counter = 1;
-        ExecutorService executor = Executors.newFixedThreadPool(NUM_THREADS);
-        for (SouthboundTestCase<BridgeOtherConfigs> fromTestCase : updateFromTestCases) {
-            for (SouthboundTestCase<BridgeOtherConfigs> toTestCase : updateToTestCases) {
-                testBridgeName = String.format(FORMAT_STR, TEST_BRIDGE_PREFIX, toTestCase.name, counter);
-                counter += 1;
-                TestCRUDBridgeOtherConfigsRunnable testRunnable =
-                        new TestCRUDBridgeOtherConfigsRunnable(
-                                connectionInfo, testBridgeName,
-                                fromTestCase.inputValues,
-                                fromTestCase.expectedValues,
-                                toTestCase.inputValues,
-                                toTestCase.expectedValues);
-                executor.submit(testRunnable);
-            }
-        }
-        executor.shutdown();
-        executor.awaitTermination(5, TimeUnit.MINUTES);
-
-        Assert.assertTrue(disconnectOvsdbNode(connectionInfo));
-    }
-
-    class TestCRUDBridgeOtherConfigsRunnable implements Runnable {
-
-        ConnectionInfo connectionInfo;
-        String testBridgeName;
-        List<BridgeOtherConfigs> updateFromInputOtherConfigs;
-        List<BridgeOtherConfigs> updateFromExpectedOtherConfigs;
-        List<BridgeOtherConfigs> updateToInputOtherConfigs;
-        List<BridgeOtherConfigs> updateToExpectedOtherConfigs;
-
-        TestCRUDBridgeOtherConfigsRunnable(
-                ConnectionInfo connectionInfo, String testBridgeName,
-                List<BridgeOtherConfigs> updateFromInputOtherConfigs,
-                List<BridgeOtherConfigs> updateFromExpectedOtherConfigs,
-                List<BridgeOtherConfigs> updateToInputOtherConfigs,
-                List<BridgeOtherConfigs> updateToExpectedOtherConfigs) {
-
-            this.connectionInfo = connectionInfo;
-            this.testBridgeName = testBridgeName;
-            this.updateFromInputOtherConfigs = updateFromInputOtherConfigs;
-            this.updateFromExpectedOtherConfigs = updateFromExpectedOtherConfigs;
-            this.updateToInputOtherConfigs = updateToInputOtherConfigs;
-            this.updateToExpectedOtherConfigs = updateToExpectedOtherConfigs;
-        }
-
-        @Override
-        public void run() {
-            try {
-                test();
-            } catch (InterruptedException e) {
-                e.printStackTrace();
-            }
-        }
-
-        public void test() throws InterruptedException {
-            // CREATE: Create the test bridge
-            boolean bridgeAdded = addBridge(connectionInfo, null,
-                    testBridgeName, null, true, SouthboundConstants.OVSDB_FAIL_MODE_MAP.inverse().get("secure"),
-                    true, null, null, null, updateFromInputOtherConfigs);
-            Assert.assertTrue(bridgeAdded);
-
-            // READ: Read the test bridge and ensure changes are propagated to the CONFIGURATION data store,
-            // then repeat for OPERATIONAL data store
-            List<BridgeOtherConfigs> updateFromConfigurationOtherConfigs = getBridge(connectionInfo, testBridgeName,
-                    LogicalDatastoreType.CONFIGURATION).getBridgeOtherConfigs();
-            assertExpectedBridgeOtherConfigsExist(updateFromExpectedOtherConfigs,
-                    updateFromConfigurationOtherConfigs);
-            List<BridgeOtherConfigs> updateFromOperationalOtherConfigs = getBridge(connectionInfo, testBridgeName)
-                    .getBridgeOtherConfigs();
-            assertExpectedBridgeOtherConfigsExist(updateFromExpectedOtherConfigs,
-                    updateFromOperationalOtherConfigs);
-
-            // UPDATE:  update the external_ids
-            OvsdbBridgeAugmentationBuilder bridgeAugmentationBuilder = new OvsdbBridgeAugmentationBuilder();
-            bridgeAugmentationBuilder.setBridgeOtherConfigs(updateToInputOtherConfigs);
-            InstanceIdentifier<Node> bridgeIid =
-                    createInstanceIdentifier(connectionInfo,
-                            new OvsdbBridgeName(testBridgeName));
-            NodeBuilder bridgeNodeBuilder = new NodeBuilder();
-            Node bridgeNode = getBridgeNode(connectionInfo, testBridgeName);
-            bridgeNodeBuilder.setNodeId(bridgeNode.getNodeId());
-            bridgeNodeBuilder.setKey(bridgeNode.getKey());
-            bridgeNodeBuilder.addAugmentation(OvsdbBridgeAugmentation.class, bridgeAugmentationBuilder.build());
-            boolean result = mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, bridgeIid,
-                    bridgeNodeBuilder.build());
-            Thread.sleep(OVSDB_UPDATE_TIMEOUT);
-            Assert.assertTrue(result);
-
-            // READ: the test bridge and ensure changes are propagated to the CONFIGURATION data store,
-            // then repeat for OPERATIONAL data store
-            List<BridgeOtherConfigs> updateToConfigurationOtherConfigs = getBridge(connectionInfo, testBridgeName,
-                    LogicalDatastoreType.CONFIGURATION).getBridgeOtherConfigs();
-            assertExpectedBridgeOtherConfigsExist(updateToExpectedOtherConfigs, updateToConfigurationOtherConfigs);
-            assertExpectedBridgeOtherConfigsExist(updateFromExpectedOtherConfigs,
-                    updateToConfigurationOtherConfigs);
-            List<BridgeOtherConfigs> updateToOperationalOtherConfigs = getBridge(connectionInfo, testBridgeName)
-                    .getBridgeOtherConfigs();
-            if (updateFromExpectedOtherConfigs != null) {
-                assertExpectedBridgeOtherConfigsExist(updateToExpectedOtherConfigs,
-                        updateToOperationalOtherConfigs);
-                assertExpectedBridgeOtherConfigsExist(updateFromExpectedOtherConfigs,
-                        updateToOperationalOtherConfigs);
-            }
-
-            // DELETE
-            Assert.assertTrue(deleteBridge(connectionInfo, testBridgeName));
-        }
-    }
-
-    /*
-     * Generates the test cases involved in testing BridgeExternalIds.  See inline comments for descriptions of
-     * the particular cases considered.
-     */
-    private List<SouthboundTestCase<BridgeExternalIds>> generateBridgeExternalIdsTestCases() {
-        return generateKeyValueTestCases(new SouthboundBridgeExternalIdsBuilder(), "BridgeExternalIdsKey",
-                "BridgeExternalIdsValue");
+        testCRUDBridge("BridgeOtherConfigs", new SouthboundBridgeOtherConfigsBuilder(),
+                new BridgeOtherConfigsSouthboundHelper());
     }
 
-    /*
-     * @see <code>SouthboundIT.testCRUDBridgeExternalIds()</code>
-     * This is helper test method to compare a test "set" of BridgeExternalIds against an expected "set"
-     */
-    private void assertExpectedBridgeExternalIdsExist( List<BridgeExternalIds> expected,
-                                                       List<BridgeExternalIds> test ) {
-
-        if (expected != null) {
-            for (BridgeExternalIds expectedExternalId : expected) {
-                Assert.assertTrue(test.contains(expectedExternalId));
-            }
-        }
+    private interface SouthboundBridgeHelper<T> {
+        void writeValues(OvsdbBridgeAugmentationBuilder builder, List<T> values);
+        List<T> readValues(OvsdbBridgeAugmentation augmentation);
     }
 
-    /*
-     * @see <code>SouthboundIT.generateBridgeExternalIdsTestCases()</code> for specific test case information
-     */
-    @Test
-    public void testCRUDBridgeExternalIds() throws InterruptedException {
-        final String TEST_BRIDGE_PREFIX = "CRUDBridgeExternalIds";
-        ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr);
-        connectOvsdbNode(connectionInfo);
+    private <T> void testCRUDBridge(String prefix, KeyValueBuilder<T> builder, SouthboundBridgeHelper<T> helper)
+            throws InterruptedException {
+        ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
         // updateFromTestCases represent the original test case value.  updateToTestCases represent the new value after
         // the update has been performed.
-        List<SouthboundTestCase<BridgeExternalIds>> updateFromTestCases = generateBridgeExternalIdsTestCases();
-        List<SouthboundTestCase<BridgeExternalIds>> updateToTestCases = generateBridgeExternalIdsTestCases();
-        String testBridgeName;
-
-        int counter = 1;
-        ExecutorService executor = Executors.newFixedThreadPool(NUM_THREADS);
-        for (SouthboundTestCase<BridgeExternalIds> fromTestCase : updateFromTestCases) {
-            for (SouthboundTestCase<BridgeExternalIds> toTestCase : updateToTestCases) {
-                testBridgeName = String.format(FORMAT_STR, TEST_BRIDGE_PREFIX, toTestCase.name, counter);
-                counter += 1;
-                TestCRUDBridgeExternalIdsRunnable testRunnable =
-                        new TestCRUDBridgeExternalIdsRunnable(
-                                connectionInfo, testBridgeName,
-                                fromTestCase.inputValues,
-                                fromTestCase.expectedValues,
-                                toTestCase.inputValues,
-                                toTestCase.expectedValues);
-                executor.submit(testRunnable);
-            }
-        }
-        executor.shutdown();
-        executor.awaitTermination(5, TimeUnit.MINUTES);
-
-        Assert.assertTrue(disconnectOvsdbNode(connectionInfo));
-    }
-
-    class TestCRUDBridgeExternalIdsRunnable implements Runnable {
-        ConnectionInfo connectionInfo;
-        String testBridgeName;
-        List<BridgeExternalIds> updateFromInputExternalIds;
-        List<BridgeExternalIds> updateFromExpectedExternalIds;
-        List<BridgeExternalIds> updateToInputExternalIds;
-        List<BridgeExternalIds> updateToExpectedExternalIds;
+        List<SouthboundTestCase<T>> updateFromTestCases = generateKeyValueTestCases(builder, prefix + "From");
+        List<SouthboundTestCase<T>> updateToTestCases = generateKeyValueTestCases(builder, prefix + "To");
+        for (SouthboundTestCase<T> updateFromTestCase : updateFromTestCases) {
+            for (SouthboundTestCase<T> updateToTestCase : updateToTestCases) {
+                String testBridgeName = String.format("%s_%s", prefix, updateToTestCase.name);
 
-        TestCRUDBridgeExternalIdsRunnable(
-                ConnectionInfo connectionInfo, String testBridgeName,
-                List<BridgeExternalIds> updateFromInputExternalIds,
-                List<BridgeExternalIds> updateFromExpectedExternalIds,
-                List<BridgeExternalIds> updateToInputExternalIds,
-                List<BridgeExternalIds> updateToExpectedExternalIds) {
+                // CREATE: Create the test bridge
+                final OvsdbBridgeName ovsdbBridgeName = new OvsdbBridgeName(testBridgeName);
+                final InstanceIdentifier<Node> bridgeIid =
+                        SouthboundUtils.createInstanceIdentifier(connectionInfo, ovsdbBridgeName);
+                final NodeId bridgeNodeId = SouthboundMapper.createManagedNodeId(bridgeIid);
+                final NodeBuilder bridgeCreateNodeBuilder = new NodeBuilder();
+                bridgeCreateNodeBuilder.setNodeId(bridgeNodeId);
+                OvsdbBridgeAugmentationBuilder bridgeCreateAugmentationBuilder = new OvsdbBridgeAugmentationBuilder();
+                bridgeCreateAugmentationBuilder.setBridgeName(ovsdbBridgeName);
+                bridgeCreateAugmentationBuilder.setProtocolEntry(createMdsalProtocols());
+                bridgeCreateAugmentationBuilder.setFailMode(
+                        SouthboundConstants.OVSDB_FAIL_MODE_MAP.inverse().get("secure"));
+                setManagedBy(bridgeCreateAugmentationBuilder, connectionInfo);
+                helper.writeValues(bridgeCreateAugmentationBuilder, updateFromTestCase.inputValues);
+                bridgeCreateNodeBuilder.addAugmentation(OvsdbBridgeAugmentation.class,
+                        bridgeCreateAugmentationBuilder.build());
+                LOG.debug("Built with the intent to store bridge data {}", bridgeCreateAugmentationBuilder.toString());
+                Assert.assertTrue(mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, bridgeIid,
+                        bridgeCreateNodeBuilder.build()));
+                Thread.sleep(OVSDB_UPDATE_TIMEOUT);
 
-            this.connectionInfo = connectionInfo;
-            this.testBridgeName = testBridgeName;
-            this.updateFromInputExternalIds = updateFromInputExternalIds;
-            this.updateFromExpectedExternalIds = updateFromExpectedExternalIds;
-            this.updateToInputExternalIds = updateToInputExternalIds;
-            this.updateToExpectedExternalIds = updateToExpectedExternalIds;
-        }
+                // READ: Read the test bridge and ensure changes are propagated to the CONFIGURATION data store,
+                // then repeat for OPERATIONAL data store
+                List<T> updateFromConfigurationExternalIds = helper.readValues(getBridge(connectionInfo, testBridgeName,
+                        LogicalDatastoreType.CONFIGURATION));
+                assertExpectedExist(updateFromTestCase.expectedValues, updateFromConfigurationExternalIds);
+                List<T> updateFromOperationalExternalIds = helper.readValues(getBridge(connectionInfo, testBridgeName));
+                assertExpectedExist(updateFromTestCase.expectedValues, updateFromOperationalExternalIds);
+
+                // UPDATE:  update the values
+                final OvsdbBridgeAugmentationBuilder bridgeUpdateAugmentationBuilder =
+                        new OvsdbBridgeAugmentationBuilder();
+                helper.writeValues(bridgeUpdateAugmentationBuilder, updateToTestCase.inputValues);
+                final NodeBuilder bridgeUpdateNodeBuilder = new NodeBuilder();
+                final Node bridgeNode = getBridgeNode(connectionInfo, testBridgeName);
+                bridgeUpdateNodeBuilder.setNodeId(bridgeNode.getNodeId());
+                bridgeUpdateNodeBuilder.setKey(bridgeNode.getKey());
+                bridgeUpdateNodeBuilder.addAugmentation(OvsdbBridgeAugmentation.class,
+                        bridgeUpdateAugmentationBuilder.build());
+                Assert.assertTrue(mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, bridgeIid,
+                        bridgeUpdateNodeBuilder.build()));
+                Thread.sleep(OVSDB_UPDATE_TIMEOUT);
 
-        @Override
-        public void run() {
-            try {
-                test();
-            } catch (InterruptedException e) {
-                e.printStackTrace();
-            }
-        }
+                // READ: the test bridge and ensure changes are propagated to the CONFIGURATION data store,
+                // then repeat for OPERATIONAL data store
+                List<T> updateToConfigurationExternalIds = helper.readValues(getBridge(connectionInfo, testBridgeName,
+                        LogicalDatastoreType.CONFIGURATION));
+                assertExpectedExist(updateToTestCase.expectedValues, updateToConfigurationExternalIds);
+                assertExpectedExist(updateFromTestCase.expectedValues, updateToConfigurationExternalIds);
+                List<T> updateToOperationalExternalIds = helper.readValues(getBridge(connectionInfo, testBridgeName));
+                if (updateFromTestCase.expectedValues != null) {
+                    assertExpectedExist(updateToTestCase.expectedValues, updateToOperationalExternalIds);
+                    assertExpectedExist(updateFromTestCase.expectedValues, updateToOperationalExternalIds);
+                }
 
-        public void test() throws InterruptedException {
-            // CREATE: Create the test bridge
-            boolean bridgeAdded = addBridge(connectionInfo, null,
-                    testBridgeName, null, true, SouthboundConstants.OVSDB_FAIL_MODE_MAP.inverse().get("secure"),
-                    true, null, updateFromInputExternalIds, null, null);
-            Assert.assertTrue(bridgeAdded);
-
-            // READ: Read the test bridge and ensure changes are propagated to the CONFIGURATION data store,
-            // then repeat for OPERATIONAL data store
-            List<BridgeExternalIds> updateFromConfigurationExternalIds = getBridge(connectionInfo, testBridgeName,
-                    LogicalDatastoreType.CONFIGURATION).getBridgeExternalIds();
-            assertExpectedBridgeExternalIdsExist(updateFromExpectedExternalIds, updateFromConfigurationExternalIds);
-            List<BridgeExternalIds> updateFromOperationalExternalIds = getBridge(connectionInfo, testBridgeName)
-                    .getBridgeExternalIds();
-            assertExpectedBridgeExternalIdsExist(updateFromExpectedExternalIds, updateFromOperationalExternalIds);
-
-            // UPDATE:  update the external_ids
-            OvsdbBridgeAugmentationBuilder bridgeAugmentationBuilder = new OvsdbBridgeAugmentationBuilder();
-            bridgeAugmentationBuilder.setBridgeExternalIds(updateToInputExternalIds);
-            InstanceIdentifier<Node> bridgeIid =
-                    createInstanceIdentifier(connectionInfo,
-                            new OvsdbBridgeName(testBridgeName));
-            NodeBuilder bridgeNodeBuilder = new NodeBuilder();
-            Node bridgeNode = getBridgeNode(connectionInfo, testBridgeName);
-            bridgeNodeBuilder.setNodeId(bridgeNode.getNodeId());
-            bridgeNodeBuilder.setKey(bridgeNode.getKey());
-            bridgeNodeBuilder.addAugmentation(OvsdbBridgeAugmentation.class, bridgeAugmentationBuilder.build());
-            boolean result = mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, bridgeIid,
-                    bridgeNodeBuilder.build());
-            Thread.sleep(OVSDB_UPDATE_TIMEOUT);
-            Assert.assertTrue(result);
-
-            // READ: the test bridge and ensure changes are propagated to the CONFIGURATION data store,
-            // then repeat for OPERATIONAL data store
-            List<BridgeExternalIds> updateToConfigurationExternalIds = getBridge(connectionInfo, testBridgeName,
-                    LogicalDatastoreType.CONFIGURATION).getBridgeExternalIds();
-            assertExpectedBridgeExternalIdsExist(updateToExpectedExternalIds, updateToConfigurationExternalIds);
-            assertExpectedBridgeExternalIdsExist(updateFromExpectedExternalIds, updateToConfigurationExternalIds);
-            List<BridgeExternalIds> updateToOperationalExternalIds = getBridge(connectionInfo, testBridgeName)
-                    .getBridgeExternalIds();
-            if (updateFromExpectedExternalIds != null) {
-                assertExpectedBridgeExternalIdsExist(updateToExpectedExternalIds, updateToOperationalExternalIds);
-                assertExpectedBridgeExternalIdsExist(updateFromExpectedExternalIds, updateToOperationalExternalIds);
+                // DELETE
+                Assert.assertTrue(mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, bridgeIid));
+                Thread.sleep(OVSDB_UPDATE_TIMEOUT);
             }
-
-            // DELETE
-            Assert.assertTrue(deleteBridge(connectionInfo, testBridgeName));
         }
     }
 
-    public static InstanceIdentifier<Node> createInstanceIdentifier(ConnectionInfo key,OvsdbBridgeName bridgeName) {
-        return SouthboundMapper.createInstanceIdentifier(createManagedNodeId(key, bridgeName));
-    }
-
-    public static NodeId createManagedNodeId(ConnectionInfo key, OvsdbBridgeName bridgeName) {
-        return createManagedNodeId(key.getRemoteIp(), key.getRemotePort(), bridgeName);
-    }
-
-    public static NodeId createManagedNodeId(IpAddress ip, PortNumber port, OvsdbBridgeName bridgeName) {
-        return new NodeId(createNodeId(ip,port).getValue()
-                + "/" + SouthboundConstants.BRIDGE_URI_PREFIX + "/" + bridgeName.getValue());
-    }
-
-    public static NodeId createNodeId(IpAddress ip, PortNumber port) {
-        String uriString = SouthboundConstants.OVSDB_URI_PREFIX + "://"
-                + new String(ip.getValue()) + ":" + port.getValue();
-        Uri uri = new Uri(uriString);
-        return new NodeId(uri);
-    }
-
-    public static NodeKey createNodeKey(IpAddress ip, PortNumber port) {
-        return new NodeKey(createNodeId(ip,port));
-    }
-
-    public static Node createNode(ConnectionInfo key) {
-        NodeBuilder nodeBuilder = new NodeBuilder();
-        nodeBuilder.setNodeId(createNodeId(key.getRemoteIp(),key.getRemotePort()));
-        nodeBuilder.addAugmentation(OvsdbNodeAugmentation.class, createOvsdbAugmentation(key));
-        return nodeBuilder.build();
-    }
-
-    public static OvsdbNodeAugmentation createOvsdbAugmentation(ConnectionInfo key) {
-        OvsdbNodeAugmentationBuilder ovsdbNodeBuilder = new OvsdbNodeAugmentationBuilder();
-        ovsdbNodeBuilder.setConnectionInfo(key);
-        return ovsdbNodeBuilder.build();
-    }
-
-    public static NodeId createManagedNodeId(InstanceIdentifier<Node> iid) {
-        NodeKey nodeKey = iid.firstKeyOf(Node.class, NodeKey.class);
-        return nodeKey.getNodeId();
+    /*
+     * @see <code>SouthboundIT.generateBridgeExternalIdsTestCases()</code> for specific test case information
+     */
+    @Test
+    public void testCRUDBridgeExternalIds() throws InterruptedException {
+        testCRUDBridge("BridgeExternalIds", new SouthboundBridgeExternalIdsBuilder(),
+                new BridgeExternalIdsSouthboundHelper());
     }
 
     /**
@@ -2301,24 +1554,22 @@ public class SouthboundIT extends AbstractMdsalTestBase {
         }
 
         /**
-         * Sets the expected output values.
+         * Indicates that the provided input values should be expected as output values.
          *
-         * @param expectedValues The expected output values.
          * @return The builder.
          */
-        @SafeVarargs
-        public final SouthboundTestCaseBuilder<T> expect(final T... expectedValues) {
-            this.expectedValues = Lists.newArrayList(expectedValues);
+        public SouthboundTestCaseBuilder<T> expectInputAsOutput() {
+            this.expectedValues = this.inputValues;
             return this;
         }
 
         /**
-         * Indicates that the provided input values should be expected as output values.
+         * Indicates that no output should be expected.
          *
          * @return The builder.
          */
-        public SouthboundTestCaseBuilder<T> expectInputAsOutput() {
-            this.expectedValues = this.inputValues;
+        public SouthboundTestCaseBuilder<T> expectNoOutput() {
+            this.expectedValues = null;
             return this;
         }
 
@@ -2332,4 +1583,319 @@ public class SouthboundIT extends AbstractMdsalTestBase {
             return new SouthboundTestCase<>(name, inputValues, expectedValues);
         }
     }
+
+    private abstract static class KeyValueBuilder<T> {
+        private static final int COUNTER_START = 0;
+        private int counter = COUNTER_START;
+
+        protected abstract Builder<T> builder();
+
+        protected abstract void setKey(Builder<T> builder, String key);
+
+        protected abstract void setValue(Builder<T> builder, String value);
+
+        public final T build(final String testName, final String key, final String value) {
+            final Builder<T> builder = builder();
+            this.counter++;
+            if (key != null) {
+                setKey(builder, String.format(FORMAT_STR, testName, key, this.counter));
+            }
+            if (value != null) {
+                setValue(builder, String.format(FORMAT_STR, testName, value, this.counter));
+            }
+            return builder.build();
+        }
+
+        public final void reset() {
+            this.counter = COUNTER_START;
+        }
+    }
+
+    private static final class SouthboundPortExternalIdsBuilder extends KeyValueBuilder<PortExternalIds> {
+        @Override
+        protected Builder<PortExternalIds> builder() {
+            return new PortExternalIdsBuilder();
+        }
+
+        @Override
+        protected void setKey(Builder<PortExternalIds> builder, String key) {
+            ((PortExternalIdsBuilder) builder).setExternalIdKey(key);
+        }
+
+        @Override
+        protected void setValue(Builder<PortExternalIds> builder, String value) {
+            ((PortExternalIdsBuilder) builder).setExternalIdValue(value);
+        }
+    }
+
+    private static final class SouthboundInterfaceExternalIdsBuilder extends KeyValueBuilder<InterfaceExternalIds> {
+        @Override
+        protected Builder<InterfaceExternalIds> builder() {
+            return new InterfaceExternalIdsBuilder();
+        }
+
+        @Override
+        protected void setKey(Builder<InterfaceExternalIds> builder, String key) {
+            ((InterfaceExternalIdsBuilder) builder).setExternalIdKey(key);
+        }
+
+        @Override
+        protected void setValue(Builder<InterfaceExternalIds> builder, String value) {
+            ((InterfaceExternalIdsBuilder) builder).setExternalIdValue(value);
+        }
+    }
+
+    private static final class SouthboundOptionsBuilder extends KeyValueBuilder<Options> {
+        @Override
+        protected Builder<Options> builder() {
+            return new OptionsBuilder();
+        }
+
+        @Override
+        protected void setKey(Builder<Options> builder, String key) {
+            ((OptionsBuilder) builder).setOption(key);
+        }
+
+        @Override
+        protected void setValue(Builder<Options> builder, String value) {
+            ((OptionsBuilder) builder).setValue(value);
+        }
+    }
+
+    private static final class SouthboundInterfaceOtherConfigsBuilder extends KeyValueBuilder<InterfaceOtherConfigs> {
+        @Override
+        protected Builder<InterfaceOtherConfigs> builder() {
+            return new InterfaceOtherConfigsBuilder();
+        }
+
+        @Override
+        protected void setKey(Builder<InterfaceOtherConfigs> builder, String key) {
+            ((InterfaceOtherConfigsBuilder) builder).setOtherConfigKey(key);
+        }
+
+        @Override
+        protected void setValue(Builder<InterfaceOtherConfigs> builder, String value) {
+            ((InterfaceOtherConfigsBuilder) builder).setOtherConfigValue(value);
+        }
+    }
+
+    private static final class SouthboundPortOtherConfigsBuilder extends KeyValueBuilder<PortOtherConfigs> {
+        @Override
+        protected Builder<PortOtherConfigs> builder() {
+            return new PortOtherConfigsBuilder();
+        }
+
+        @Override
+        protected void setKey(Builder<PortOtherConfigs> builder, String key) {
+            ((PortOtherConfigsBuilder) builder).setOtherConfigKey(key);
+        }
+
+        @Override
+        protected void setValue(Builder<PortOtherConfigs> builder, String value) {
+            ((PortOtherConfigsBuilder) builder).setOtherConfigValue(value);
+        }
+    }
+
+    private static final class SouthboundBridgeOtherConfigsBuilder extends KeyValueBuilder<BridgeOtherConfigs> {
+        @Override
+        protected Builder<BridgeOtherConfigs> builder() {
+            return new BridgeOtherConfigsBuilder();
+        }
+
+        @Override
+        protected void setKey(Builder<BridgeOtherConfigs> builder, String key) {
+            ((BridgeOtherConfigsBuilder) builder).setBridgeOtherConfigKey(key);
+        }
+
+        @Override
+        protected void setValue(Builder<BridgeOtherConfigs> builder, String value) {
+            ((BridgeOtherConfigsBuilder) builder).setBridgeOtherConfigValue(value);
+        }
+    }
+
+    private static final class SouthboundBridgeExternalIdsBuilder extends KeyValueBuilder<BridgeExternalIds> {
+        @Override
+        protected Builder<BridgeExternalIds> builder() {
+            return new BridgeExternalIdsBuilder();
+        }
+
+        @Override
+        protected void setKey(Builder<BridgeExternalIds> builder, String key) {
+            ((BridgeExternalIdsBuilder) builder).setBridgeExternalIdKey(key);
+        }
+
+        @Override
+        protected void setValue(Builder<BridgeExternalIds> builder, String value) {
+            ((BridgeExternalIdsBuilder) builder).setBridgeExternalIdValue(value);
+        }
+    }
+
+    /*
+     * Generates the test cases involved in testing key-value-based data.  See inline comments for descriptions of
+     * the particular cases considered.
+     */
+    private static <T> List<SouthboundTestCase<T>> generateKeyValueTestCases(
+            KeyValueBuilder<T> builder, String testName) {
+        List<SouthboundTestCase<T>> testCases = new ArrayList<>();
+
+        final String GOOD_KEY = "GoodKey";
+        final String GOOD_VALUE = "GoodValue";
+        final String NO_VALUE_FOR_KEY = "NoValueForKey";
+
+        final String idKey = testName + "Key";
+        final String idValue = testName + "Value";
+
+        // Test Case 1:  TestOne
+        // Test Type:    Positive
+        // Description:  Create a termination point with one value
+        // Expected:     A port is created with the single value specified below
+        final String testOneName = "TestOne" + testName;
+        testCases.add(new SouthboundTestCaseBuilder<T>()
+                .name(testOneName)
+                .input(builder.build(testOneName, idKey, idValue))
+                .expectInputAsOutput()
+                .build());
+
+        // Test Case 2:  TestFive
+        // Test Type:    Positive
+        // Description:  Create a termination point with multiple (five) values
+        // Expected:     A port is created with the five values specified below
+        final String testFiveName = "TestFive" + testName;
+        builder.reset();
+        testCases.add(new SouthboundTestCaseBuilder<T>()
+                .name(testFiveName)
+                .input(
+                        builder.build(testFiveName, idKey, idValue),
+                        builder.build(testFiveName, idKey, idValue),
+                        builder.build(testFiveName, idKey, idValue),
+                        builder.build(testFiveName, idKey, idValue),
+                        builder.build(testFiveName, idKey, idValue))
+                .expectInputAsOutput()
+                .build());
+
+        if ((builder instanceof SouthboundBridgeExternalIdsBuilder) ||
+                (builder instanceof SouthboundInterfaceExternalIdsBuilder) ||
+                (builder instanceof SouthboundPortExternalIdsBuilder)) {
+            LOG.info("generateKeyValueTestCases: instance skipping test case 3 TestOneGoodOneMalformedValue");
+            builder.reset();
+
+            return testCases;
+        }
+
+        // Test Case 3:  TestOneGoodOneMalformedValue
+        // Test Type:    Negative
+        // Description:
+        //     One perfectly fine input
+        //        (TestOneGoodOneMalformedValue_GoodKey_1,
+        //        TestOneGoodOneMalformedValue_GoodValue_1)
+        //     and one malformed input which only has key specified
+        //        (TestOneGoodOneMalformedValue_NoValueForKey_2,
+        //        UNSPECIFIED)
+        // Expected:     A port is created without any values
+        final String testOneGoodOneMalformedValueName = "TestOneGoodOneMalformedValue" + testName;
+        builder.reset();
+        testCases.add(new SouthboundTestCaseBuilder<T>()
+                .name(testOneGoodOneMalformedValueName)
+                .input(
+                        builder.build(testOneGoodOneMalformedValueName, GOOD_KEY, GOOD_VALUE),
+                        builder.build(testOneGoodOneMalformedValueName, NO_VALUE_FOR_KEY, null))
+                .expectNoOutput()
+                .build());
+        builder.reset();
+
+        return testCases;
+    }
+
+    private static class PortExternalIdsSouthboundHelper implements SouthboundTerminationPointHelper<PortExternalIds> {
+        @Override
+        public void writeValues(OvsdbTerminationPointAugmentationBuilder builder, List<PortExternalIds> values) {
+            builder.setPortExternalIds(values);
+        }
+
+        @Override
+        public List<PortExternalIds> readValues(OvsdbTerminationPointAugmentation augmentation) {
+            return augmentation.getPortExternalIds();
+        }
+    }
+
+    private static class InterfaceExternalIdsSouthboundHelper implements
+            SouthboundTerminationPointHelper<InterfaceExternalIds> {
+        @Override
+        public void writeValues(
+                OvsdbTerminationPointAugmentationBuilder builder, List<InterfaceExternalIds> values) {
+            builder.setInterfaceExternalIds(values);
+        }
+
+        @Override
+        public List<InterfaceExternalIds> readValues(OvsdbTerminationPointAugmentation augmentation) {
+            return augmentation.getInterfaceExternalIds();
+        }
+    }
+
+    private static class OptionsSouthboundHelper implements SouthboundTerminationPointHelper<Options> {
+        @Override
+        public void writeValues(
+                OvsdbTerminationPointAugmentationBuilder builder, List<Options> values) {
+            builder.setOptions(values);
+        }
+
+        @Override
+        public List<Options> readValues(OvsdbTerminationPointAugmentation augmentation) {
+            return augmentation.getOptions();
+        }
+    }
+
+    private static class InterfaceOtherConfigsSouthboundHelper implements
+            SouthboundTerminationPointHelper<InterfaceOtherConfigs> {
+        @Override
+        public void writeValues(
+                OvsdbTerminationPointAugmentationBuilder builder, List<InterfaceOtherConfigs> values) {
+            builder.setInterfaceOtherConfigs(values);
+        }
+
+        @Override
+        public List<InterfaceOtherConfigs> readValues(OvsdbTerminationPointAugmentation augmentation) {
+            return augmentation.getInterfaceOtherConfigs();
+        }
+    }
+
+    private static class PortOtherConfigsSouthboundHelper implements
+            SouthboundTerminationPointHelper<PortOtherConfigs> {
+        @Override
+        public void writeValues(
+                OvsdbTerminationPointAugmentationBuilder builder, List<PortOtherConfigs> values) {
+            builder.setPortOtherConfigs(values);
+        }
+
+        @Override
+        public List<PortOtherConfigs> readValues(OvsdbTerminationPointAugmentation augmentation) {
+            return augmentation.getPortOtherConfigs();
+        }
+    }
+
+    private static class BridgeExternalIdsSouthboundHelper implements SouthboundBridgeHelper<BridgeExternalIds> {
+        @Override
+        public void writeValues(
+                OvsdbBridgeAugmentationBuilder builder, List<BridgeExternalIds> values) {
+            builder.setBridgeExternalIds(values);
+        }
+
+        @Override
+        public List<BridgeExternalIds> readValues(OvsdbBridgeAugmentation augmentation) {
+            return augmentation.getBridgeExternalIds();
+        }
+    }
+
+    private static class BridgeOtherConfigsSouthboundHelper implements SouthboundBridgeHelper<BridgeOtherConfigs> {
+        @Override
+        public void writeValues(
+                OvsdbBridgeAugmentationBuilder builder, List<BridgeOtherConfigs> values) {
+            builder.setBridgeOtherConfigs(values);
+        }
+
+        @Override
+        public List<BridgeOtherConfigs> readValues(OvsdbBridgeAugmentation augmentation) {
+            return augmentation.getBridgeOtherConfigs();
+        }
+    }
 }