Upgrade ietf-{inet,yang}-types to 2013-07-15
[ovsdb.git] / southbound / southbound-it / src / test / java / org / opendaylight / ovsdb / southbound / it / SouthboundIT.java
index 410c19cd15890346113df6e9c6a1a62dc0ebb404..6817bfa1850b8b5a615816fdd105922c7f495e98 100644 (file)
@@ -9,35 +9,54 @@ package org.opendaylight.ovsdb.southbound.it;
 
 import static org.junit.Assert.assertNotNull;
 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.propagateSystemProperties;
+import static org.ops4j.pax.exam.CoreOptions.vmOption;
 import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.editConfigurationFilePut;
-import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.features;
-
-import com.google.common.collect.ImmutableBiMap;
-import com.google.common.collect.Lists;
-import com.google.common.collect.ObjectArrays;
+import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.keepRuntimeFolder;
 
+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 javax.annotation.Nullable;
 import javax.inject.Inject;
 
+import org.junit.After;
 import org.junit.Assert;
+import org.junit.Assume;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
+import org.junit.internal.AssumptionViolatedException;
 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.lib.OvsdbClient;
+import org.opendaylight.ovsdb.lib.notation.Version;
+import org.opendaylight.ovsdb.lib.schema.DatabaseSchema;
 import org.opendaylight.ovsdb.southbound.SouthboundConstants;
 import org.opendaylight.ovsdb.southbound.SouthboundMapper;
 import org.opendaylight.ovsdb.southbound.SouthboundProvider;
-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.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.rev130715.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.DatapathTypeBase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeBase;
@@ -51,15 +70,49 @@ 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.OvsdbPortInterfaceAttributes.VlanMode;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.QosTypeBase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeExternalIds;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeExternalIdsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeOtherConfigs;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeOtherConfigsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ControllerEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ControllerEntryBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ProtocolEntry;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ProtocolEntryBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.Autoattach;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.AutoattachBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.AutoattachKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ConnectionInfo;
 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.node.attributes.QosEntries;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.QosEntriesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.QosEntriesKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.Queues;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.QueuesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.QueuesKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.autoattach.AutoattachExternalIds;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.autoattach.AutoattachExternalIdsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.autoattach.Mappings;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.autoattach.MappingsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.qos.entries.QosExternalIds;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.qos.entries.QosExternalIdsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.qos.entries.QosOtherConfig;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.qos.entries.QosOtherConfigBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.qos.entries.QueueList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.qos.entries.QueueListBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.qos.entries.QueueListKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.queues.QueuesExternalIds;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.queues.QueuesExternalIdsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.queues.QueuesOtherConfig;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.queues.QueuesOtherConfigBuilder;
 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;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceLldp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceLldpBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceOtherConfigs;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceOtherConfigsBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.Options;
@@ -81,7 +134,10 @@ 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.TerminationPoint;
 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.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
 import org.ops4j.pax.exam.Configuration;
 import org.ops4j.pax.exam.Option;
 import org.ops4j.pax.exam.junit.PaxExam;
@@ -89,11 +145,15 @@ import org.ops4j.pax.exam.karaf.options.LogLevelOption;
 import org.ops4j.pax.exam.options.MavenUrlReference;
 import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
 import org.ops4j.pax.exam.spi.reactors.PerClass;
-import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.google.common.collect.ImmutableBiMap;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+
 /**
  * Integration tests for southbound-impl
  *
@@ -105,33 +165,155 @@ 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 DataBroker dataBroker = null;
+    private static final int OVSDB_ROUNDTRIP_TIMEOUT = 10000;
+    private static final String FORMAT_STR = "%s_%s_%d";
+    private static final Version AUTOATTACH_FROM_VERSION = Version.fromString("7.11.2");
+    private static final Version IF_INDEX_FROM_VERSION = Version.fromString("7.2.1");
     private static String addressStr;
-    private static String portStr;
+    private static int portNumber;
     private static String connectionType;
-    private static String extrasStr;
-    private static Boolean setup = false;
+    private static boolean setup = false;
     private static MdsalUtils mdsalUtils = null;
-    //private static String extras = "false";
-    private static final String NETVIRT = "org.opendaylight.ovsdb.openstack.net-virt";
-    private static final String NETVIRTPROVIDERS = "org.opendaylight.ovsdb.openstack.net-virt-providers";
+    private static Node ovsdbNode;
+    private static int testMethodsRemaining;
+    private static DataBroker dataBroker;
+    private static Version schemaVersion;
+    private static OvsdbClient ovsdbClient;
+    private static DatabaseSchema dbSchema;
 
     @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 final InstanceIdentifier<?> iid;
+        private final int RETRY_WAIT = 100;
+
+        private NotifyingDataChangeListener(LogicalDatastoreType type) {
+            this.type = type;
+            this.iid = null;
+        }
+
+        private NotifyingDataChangeListener(LogicalDatastoreType type, InstanceIdentifier<?> iid) {
+            this.type = type;
+            this.iid = iid;
+        }
+
+        @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);
+        }
+
+        public void clear() {
+            createdIids.clear();
+            removedIids.clear();
+            updatedIids.clear();
+        }
+
+        public void registerDataChangeListener() {
+            dataBroker.registerDataChangeListener(type, iid, this, AsyncDataBroker.DataChangeScope.SUBTREE);
+        }
+
+        public void waitForCreation(long timeout) throws InterruptedException {
+            synchronized (this) {
+                long _start = System.currentTimeMillis();
+                LOG.info("Waiting for {} DataChanged creation on {}", type, iid);
+                while (!isCreated(iid) && (System.currentTimeMillis() - _start) < timeout) {
+                    wait(RETRY_WAIT);
+                }
+                LOG.info("Woke up, waited {}ms for creation of {}", (System.currentTimeMillis() - _start), iid);
+            }
+        }
+
+        public void waitForDeletion(long timeout) throws InterruptedException {
+            synchronized (this) {
+                long _start = System.currentTimeMillis();
+                LOG.info("Waiting for {} DataChanged deletion on {}", type, iid);
+                while (!isRemoved(iid) && (System.currentTimeMillis() - _start) < timeout) {
+                    wait(RETRY_WAIT);
+                }
+                LOG.info("Woke up, waited {}ms for deletion of {}", (System.currentTimeMillis() - _start), iid);
+            }
+        }
+
+        public void waitForUpdate(long timeout) throws InterruptedException {
+            synchronized (this) {
+                long _start = System.currentTimeMillis();
+                LOG.info("Waiting for {} DataChanged update on {}", type, iid);
+                while (!isUpdated(iid) && (System.currentTimeMillis() - _start) < timeout) {
+                    wait(RETRY_WAIT);
+                }
+                LOG.info("Woke up, waited {}ms for update of {}", (System.currentTimeMillis() - _start), iid);
+            }
+        }
+
+    }
+
     @Configuration
     public Option[] config() {
-        return super.config();
+        Option[] options = super.config();
+        Option[] propertyOptions = getPropertiesOptions();
+        Option[] otherOptions = getOtherOptions();
+        Option[] combinedOptions = new Option[options.length + propertyOptions.length + otherOptions.length];
+        System.arraycopy(options, 0, combinedOptions, 0, options.length);
+        System.arraycopy(propertyOptions, 0, combinedOptions, options.length, propertyOptions.length);
+        System.arraycopy(otherOptions, 0, combinedOptions, options.length + propertyOptions.length,
+                otherOptions.length);
+        return combinedOptions;
     }
 
-    @Override
-    public String getModuleName() {
-        return "southbound-impl";
+    private Option[] getOtherOptions() {
+        return new Option[] {
+                vmOption("-javaagent:../jars/org.jacoco.agent.jar=destfile=../../jacoco-it.exec"),
+                keepRuntimeFolder()
+        };
     }
 
     @Override
-    public String getInstanceName() {
-        return "southbound-default";
+    public String getKarafDistro() {
+        return maven()
+                .groupId("org.opendaylight.ovsdb")
+                .artifactId("southbound-karaf")
+                .versionAsInProject()
+                .type("zip")
+                .getURL();
     }
 
     @Override
@@ -146,8 +328,7 @@ public class SouthboundIT extends AbstractMdsalTestBase {
 
     @Override
     public String getFeatureName() {
-        //setExtras();
-        return "odl-ovsdb-southbound-impl-ui";
+        return "odl-ovsdb-southbound-test";
     }
 
     protected String usage() {
@@ -157,46 +338,15 @@ public class SouthboundIT extends AbstractMdsalTestBase {
     }
 
     @Override
-    public Option[] getFeaturesOptions(final boolean extras) {
-        if (extras == true) {
-            Option[] options = new Option[] {
-                    features("mvn:org.opendaylight.ovsdb/features-ovsdb/1.1.0-SNAPSHOT/xml/features",
-                            "odl-ovsdb-openstack-sb")};
-            return options;
-        } else {
-            return new Option[]{};
-        }
-    }
-
-    @Override
-    public Option[] getLoggingOptions(final boolean extras) {
-        Option[] options = new Option[] {
-                /*editConfigurationFilePut(SouthboundITConstants.ORG_OPS4J_PAX_LOGGING_CFG,
-                        "log4j.logger.org.opendaylight.ovsdb",
-                        LogLevelOption.LogLevel.DEBUG.name()),*/
-                editConfigurationFilePut(SouthboundITConstants.ORG_OPS4J_PAX_LOGGING_CFG,
-                        "log4j.logger.org.opendaylight.ovsdb.southbound-impl",
-                        LogLevelOption.LogLevel.DEBUG.name())
-        };
-
-        if (extras == true) {
-            Option[] extraOptions = new Option[] {
+    public Option getLoggingOption() {
+        return composite(
                 editConfigurationFilePut(SouthboundITConstants.ORG_OPS4J_PAX_LOGGING_CFG,
                         "log4j.logger.org.opendaylight.ovsdb",
-                        LogLevelOption.LogLevel.DEBUG.name()),
-                editConfigurationFilePut(SouthboundITConstants.ORG_OPS4J_PAX_LOGGING_CFG,
-                        "log4j.logger.org.opendaylight.ovsdb.openstack.net-virt",
-                        LogLevelOption.LogLevel.DEBUG.name())
-            };
-            options = ObjectArrays.concat(options, extraOptions, Option.class);
-        }
-
-        options = ObjectArrays.concat(options, super.getLoggingOptions(extras), Option.class);
-        return options;
+                        LogLevelOption.LogLevel.TRACE.name()),
+                super.getLoggingOption());
     }
 
-    @Override
-    public Option[] getPropertiesOptions(final boolean extras) {
+    private Option[] getPropertiesOptions() {
         Properties props = new Properties(System.getProperties());
         String addressStr = props.getProperty(SouthboundITConstants.SERVER_IPADDRESS,
                 SouthboundITConstants.DEFAULT_SERVER_IPADDRESS);
@@ -204,45 +354,36 @@ public class SouthboundIT extends AbstractMdsalTestBase {
                 SouthboundITConstants.DEFAULT_SERVER_PORT);
         String connectionType = props.getProperty(SouthboundITConstants.CONNECTION_TYPE,
                 SouthboundITConstants.CONNECTION_TYPE_ACTIVE);
-        String extrasStr = props.getProperty(SouthboundITConstants.SERVER_EXTRAS,
-                SouthboundITConstants.DEFAULT_SERVER_EXTRAS);
 
-        LOG.info("getPropertiesOptions: Using the following properties: mode= {}, ip:port= {}:{}, extras= {}",
-                connectionType, addressStr, portStr, extrasStr);
+        LOG.info("getPropertiesOptions: Using the following properties: mode= {}, ip:port= {}:{}",
+                connectionType, addressStr, portStr);
 
-        Option[] options = new Option[] {
+        return new Option[] {
+                propagateSystemProperties(
+                        SouthboundITConstants.SERVER_IPADDRESS,
+                        SouthboundITConstants.SERVER_PORT,
+                        SouthboundITConstants.CONNECTION_TYPE),
                 editConfigurationFilePut(SouthboundITConstants.CUSTOM_PROPERTIES,
                         SouthboundITConstants.SERVER_IPADDRESS, addressStr),
                 editConfigurationFilePut(SouthboundITConstants.CUSTOM_PROPERTIES,
                         SouthboundITConstants.SERVER_PORT, portStr),
                 editConfigurationFilePut(SouthboundITConstants.CUSTOM_PROPERTIES,
                         SouthboundITConstants.CONNECTION_TYPE, connectionType),
-                editConfigurationFilePut(SouthboundITConstants.CUSTOM_PROPERTIES,
-                        SouthboundITConstants.SERVER_EXTRAS, extrasStr)
         };
-        return options;
-    }
-
-
-    public boolean setExtras() {
-        Properties props = new Properties(System.getProperties());
-        boolean extras = props.getProperty(SouthboundITConstants.SERVER_EXTRAS,
-                SouthboundITConstants.DEFAULT_SERVER_EXTRAS).equals("true");
-        LOG.info("setExtras: {}", extras);
-        return extras;
     }
 
     @Before
-    public void setUp() throws InterruptedException {
-        if (setup == true) {
-            LOG.info("Skipping setUp, already initialized");
+    @Override
+    public void setup() throws InterruptedException {
+        if (setup) {
+            LOG.info("Skipping setup, already initialized");
             return;
         }
 
         try {
             super.setup();
         } catch (Exception e) {
-            e.printStackTrace();
+            LOG.warn("Failed to setup test", e);
         }
         //dataBroker = getSession().getSALService(DataBroker.class);
         Thread.sleep(3000);
@@ -250,12 +391,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);
-        extrasStr = bundleContext.getProperty(SouthboundITConstants.SERVER_EXTRAS);
 
-        LOG.info("setUp: Using the following properties: mode= {}, ip:port= {}:{}, extras= {}",
-                connectionType, addressStr, portStr, extrasStr);
+        LOG.info("setUp: Using the following properties: mode= {}, ip:port= {}:{}",
+                connectionType, addressStr, portNumber);
         if (connectionType.equalsIgnoreCase(SouthboundITConstants.CONNECTION_TYPE_ACTIVE)) {
             if (addressStr == null) {
                 fail(usage());
@@ -263,17 +408,64 @@ 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);
+        try {
+            ovsdbClient = SouthboundIntegrationTestUtils.getTestConnection(this);
+            assertNotNull("Invalid Client. Check connection params", ovsdbClient);
+
+            dbSchema = ovsdbClient.getSchema(SouthboundIntegrationTestUtils.OPEN_VSWITCH_SCHEMA).get();
+            assertNotNull("Invalid dbSchema.", dbSchema);
+            schemaVersion = dbSchema.getVersion();
+            LOG.info("{} schema version = {}", SouthboundIntegrationTestUtils.OPEN_VSWITCH_SCHEMA, schemaVersion);
+        } catch (Exception e) {
+            fail("Error accessing schemaVersion in SouthboundIT setUp()." + usage());
+        }
+
+        // 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;
+    }
 
-        if (extrasStr.equals("true")) {
-            isBundleReady(bundleContext, NETVIRT);
-            isBundleReady(bundleContext, NETVIRTPROVIDERS);
+    @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.
+     * 6640. This test will wait for incoming connections for {@link SouthboundITConstants#CONNECTION_INIT_TIMEOUT} ms.
      *
      * @throws InterruptedException
      */
@@ -285,29 +477,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()
+        final ConnectionInfo connectionInfo = new ConnectionInfoBuilder()
                 .setRemoteIp(address)
                 .setRemotePort(port)
-                .build());
-        return new ConnectionInfoBuilder()
-                       .setRemoteIp(address)
-                       .setRemotePort(port)
-                       .build();
-    }
-
-    private String connectionInfoToString(final ConnectionInfo connectionInfo) {
-        return new String(connectionInfo.getRemoteIp().getValue()) + ":" + connectionInfo.getRemotePort().getValue();
+                .build();
+        LOG.info("connectionInfo: {}", connectionInfo);
+        return connectionInfo;
     }
 
     @Test
@@ -339,129 +525,152 @@ public class SouthboundIT extends AbstractMdsalTestBase {
                 topology);
     }
 
-    private boolean addOvsdbNode(final ConnectionInfo connectionInfo) throws InterruptedException {
-        boolean result = mdsalUtils.put(LogicalDatastoreType.CONFIGURATION,
-                SouthboundMapper.createInstanceIdentifier(connectionInfo),
-                SouthboundMapper.createNode(connectionInfo));
-        Thread.sleep(OVSDB_UPDATE_TIMEOUT);
-        return result;
+    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) {
-        Node node = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL,
-                SouthboundMapper.createInstanceIdentifier(connectionInfo));
-        return node;
+    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,
-                SouthboundMapper.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);
-        //Assume.assumeNotNull(node); // Using assumeNotNull because there is no assumeNull
-        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);
-        Node ovsdbNode = connectOvsdbNode(connectionInfo);
-        Assert.assertTrue(disconnectOvsdbNode(connectionInfo));
-        //Assume.assumeTrue(disconnectOvsdbNode(connectionInfo));
+        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);
     }
 
     @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) {
             LOG.info("DPDK not supported on this node.");
         } else {
-            Class<? extends DatapathTypeBase> dpType = null;
-            String dpTypeStr = null;
             for (DatapathTypeEntry dpTypeEntry : datapathTypeEntries) {
-                dpType = dpTypeEntry.getDatapathType();
-                dpTypeStr = SouthboundConstants.DATAPATH_TYPE_MAP.get(dpType);
+                Class<? extends DatapathTypeBase> dpType = dpTypeEntry.getDatapathType();
+                String dpTypeStr = SouthboundConstants.DATAPATH_TYPE_MAP.get(dpType);
                 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 = SouthboundMapper.createInstanceIdentifier(connectionInfo,
+                    InstanceIdentifier<Node> bridgeIid = SouthboundUtils.createInstanceIdentifier(connectionInfo,
                             new OvsdbBridgeName(SouthboundITConstants.BRIDGE_NAME));
-                    NodeId bridgeNodeId = SouthboundMapper.createManagedNodeId(bridgeIid);
-                    addBridge(connectionInfo, bridgeIid, SouthboundITConstants.BRIDGE_NAME, bridgeNodeId, false, null,
-                            true, dpType);
-
-                    // 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");
-                    Class<? extends InterfaceTypeBase> opPort = null;
-                    List<TerminationPoint> terminationPoints = terminationPointNode.getTerminationPoint();
-                    for (TerminationPoint terminationPoint : terminationPoints) {
-                        OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation = terminationPoint
-                                .getAugmentation(OvsdbTerminationPointAugmentation.class);
-                        if (ovsdbTerminationPointAugmentation.getName().equals(TEST_PORT_NAME)) {
-                            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));
-        //Assume.assumeTrue(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();
@@ -477,22 +686,50 @@ public class SouthboundIT extends AbstractMdsalTestBase {
         } else {
             LOG.info("other_config is not present");
         }
-        Assert.assertTrue(disconnectOvsdbNode(connectionInfo));
-        //Assume.assumeTrue(disconnectOvsdbNode(connectionInfo));
     }
 
-    private void setManagedBy(final OvsdbBridgeAugmentationBuilder ovsdbBridgeAugmentationBuilder,
+    @Test
+    public void testOvsdbBridgeControllerInfo() throws InterruptedException {
+        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);
+        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());
+                }
+            }
+        }
+    }
+
+    private List<ControllerEntry> createControllerEntry(String controllerTarget) {
+        List<ControllerEntry> controllerEntriesList = new ArrayList<>();
+        controllerEntriesList.add(new ControllerEntryBuilder()
+                .setTarget(new Uri(controllerTarget))
+                .build());
+        return controllerEntriesList;
+    }
+
+    private static void setManagedBy(final OvsdbBridgeAugmentationBuilder ovsdbBridgeAugmentationBuilder,
                               final ConnectionInfo connectionInfo) {
-        InstanceIdentifier<Node> connectionNodePath = SouthboundMapper.createInstanceIdentifier(connectionInfo);
+        InstanceIdentifier<Node> connectionNodePath = SouthboundUtils.createInstanceIdentifier(connectionInfo);
         ovsdbBridgeAugmentationBuilder.setManagedBy(new OvsdbNodeRef(connectionNodePath));
     }
 
-    private List<ProtocolEntry> createMdsalProtocols() {
-        List<ProtocolEntry> protocolList = new ArrayList<ProtocolEntry>();
+    private static List<ProtocolEntry> createMdsalProtocols() {
+        List<ProtocolEntry> protocolList = new ArrayList<>();
         ImmutableBiMap<String, Class<? extends OvsdbBridgeProtocolBase>> mapper =
                 SouthboundConstants.OVSDB_PROTOCOL_MAP.inverse();
-        protocolList.add(new ProtocolEntryBuilder().
-                setProtocol((Class<? extends OvsdbBridgeProtocolBase>) mapper.get("OpenFlow13")).build());
+        protocolList.add(new ProtocolEntryBuilder().setProtocol(mapper.get("OpenFlow13")).build());
         return protocolList;
     }
 
@@ -518,9 +755,19 @@ 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)
-        throws InterruptedException {
+                                        final OvsdbTerminationPointAugmentationBuilder
+                                                ovsdbTerminationPointAugmentationBuilder)
+            throws InterruptedException {
 
         InstanceIdentifier<Node> portIid = SouthboundMapper.createInstanceIdentifier(bridgeNodeId);
         NodeBuilder portNodeBuilder = new NodeBuilder();
@@ -538,595 +785,2334 @@ 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
-     * @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) throws InterruptedException {
-
-        NodeBuilder bridgeNodeBuilder = new NodeBuilder();
-        if (bridgeIid == null) {
-            bridgeIid = SouthboundMapper.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);
+            ovsdbBridgeAugmentationBuilder.setBridgeExternalIds(externalIds);
+            ovsdbBridgeAugmentationBuilder.setControllerEntry(controllerEntries);
+            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 {
 
-        return addBridge(connectionInfo, null, bridgeName, null, true,
-                SouthboundConstants.OVSDB_FAIL_MODE_MAP.inverse().get("secure"), true, null);
-    }
+        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);
+        }
 
-    private OvsdbBridgeAugmentation getBridge(ConnectionInfo connectionInfo) {
-        InstanceIdentifier<Node> bridgeIid =
-                SouthboundMapper.createInstanceIdentifier(connectionInfo,
-                        new OvsdbBridgeName(SouthboundITConstants.BRIDGE_NAME));
-        Node bridgeNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, bridgeIid);
-        Assert.assertNotNull(bridgeNode);
-        OvsdbBridgeAugmentation ovsdbBridgeAugmentation = bridgeNode.getAugmentation(OvsdbBridgeAugmentation.class);
-        Assert.assertNotNull(ovsdbBridgeAugmentation);
-        return ovsdbBridgeAugmentation;
+        @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 boolean deleteBridge(ConnectionInfo connectionInfo) throws InterruptedException {
-        boolean result = mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION,
-                SouthboundMapper.createInstanceIdentifier(connectionInfo,
-                        new OvsdbBridgeName(SouthboundITConstants.BRIDGE_NAME)));
-        Thread.sleep(OVSDB_UPDATE_TIMEOUT);
-        return result;
+    private static class TestAutoAttach implements AutoCloseable {
+        private final ConnectionInfo connectionInfo;
+        private final Uri autoattachId;
+        private final Uri bridgeId;
+
+        public TestAutoAttach (final ConnectionInfo connectionInfo,
+                final Uri autoattachId,
+                final Uri bridgeId,
+                @Nullable final String systemName,
+                @Nullable final String systemDescription,
+                @Nullable final List<Mappings> mappings,
+                @Nullable final List<AutoattachExternalIds> externalIds) {
+            this.connectionInfo = connectionInfo;
+            this.autoattachId = autoattachId;
+            this.bridgeId = bridgeId;
+
+            Autoattach aaEntry = new AutoattachBuilder()
+                    .setAutoattachId(autoattachId)
+                    .setBridgeId(bridgeId)
+                    .setSystemName(systemName)
+                    .setSystemDescription(systemDescription)
+                    .setMappings(mappings)
+                    .setAutoattachExternalIds(externalIds)
+                    .build();
+            InstanceIdentifier<Autoattach> iid = SouthboundUtils.createInstanceIdentifier(connectionInfo)
+                    .augmentation(OvsdbNodeAugmentation.class)
+                    .child(Autoattach.class, aaEntry.getKey());
+            final NotifyingDataChangeListener aaOperationalListener =
+                    new NotifyingDataChangeListener(LogicalDatastoreType.OPERATIONAL, iid);
+            aaOperationalListener.registerDataChangeListener();
+
+            Assert.assertTrue(mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, iid, aaEntry));
+            try {
+                aaOperationalListener.waitForCreation(OVSDB_ROUNDTRIP_TIMEOUT);
+            } catch (InterruptedException e) {
+                LOG.warn("Sleep interrupted while waiting for queue {}", iid, e);
+            }
+        }
+        @Override
+        public void close() {
+            final InstanceIdentifier<Autoattach> iid = SouthboundUtils.createInstanceIdentifier(connectionInfo)
+                    .augmentation(OvsdbNodeAugmentation.class)
+                    .child(Autoattach.class, new AutoattachKey(this.autoattachId));
+            final NotifyingDataChangeListener aaOperationalListener =
+                    new NotifyingDataChangeListener(LogicalDatastoreType.OPERATIONAL, iid);
+            aaOperationalListener.registerDataChangeListener();
+
+            Assert.assertTrue(mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, iid));
+            try {
+                aaOperationalListener.waitForDeletion(OVSDB_ROUNDTRIP_TIMEOUT);
+            } catch (InterruptedException e) {
+                LOG.warn("Sleep interrupted while waiting for qos deletion (qos {})", iid, e);
+            }
+        }
     }
 
     @Test
-    public void testAddDeleteBridge() throws InterruptedException {
-        ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr);
-        Node ovsdbNode = connectOvsdbNode(connectionInfo);
-
-        Assert.assertTrue(addBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME));
-        OvsdbBridgeAugmentation bridge = getBridge(connectionInfo);
-        Assert.assertNotNull(bridge);
-        LOG.info("bridge: {}", bridge);
+    public void testCRUDAutoAttach() throws InterruptedException {
+        final boolean isOldSchema = schemaVersion.compareTo(AUTOATTACH_FROM_VERSION) < 0;
 
-        Assert.assertTrue(deleteBridge(connectionInfo));
-
-        Assert.assertTrue(disconnectOvsdbNode(connectionInfo));
-        //Assume.assumeTrue(disconnectOvsdbNode(connectionInfo));
-    }
+        ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
+        String testAutoattachId = new String("testAutoattachEntry");
+        String testSystemName = new String("testSystemName");
+        String testSystemDescription = new String("testSystemDescription");
+        String testAutoattachExternalKey = new String("testAutoattachExternalKey");
+        String testAutoattachExternalValue = new String("testAutoattachExternalValue");
 
-    private InstanceIdentifier<Node> getTpIid(ConnectionInfo connectionInfo, OvsdbBridgeAugmentation bridge) {
-        return SouthboundMapper.createInstanceIdentifier(connectionInfo,
-            bridge.getBridgeName());
-    }
+        try (TestBridge testBridge = new TestBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME)) {
+            OvsdbBridgeAugmentation bridge = getBridge(connectionInfo);
+            Assert.assertNotNull(bridge);
 
-    @Test
-    public void testTerminationPointOfPort() throws InterruptedException {
-        ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr);
-        connectOvsdbNode(connectionInfo);
+            // CREATE: Create Autoattach table
+            NodeId nodeId = SouthboundUtils.createManagedNodeId(SouthboundUtils.createInstanceIdentifier(
+                    connectionInfo, bridge.getBridgeName()));
+            String bridgeId = nodeId.getValue();
+            try(TestAutoAttach testAutoattach = new TestAutoAttach(connectionInfo, new Uri(testAutoattachId),
+                    new Uri(bridgeId), testSystemName, testSystemDescription, null, null)) {
+                // READ: Read md-sal operational datastore to see if the AutoAttach table was created
+                // and if Bridge table was updated with AutoAttach Uuid
+                OvsdbNodeAugmentation ovsdbNodeAugmentation = getOvsdbNode(connectionInfo,
+                        LogicalDatastoreType.OPERATIONAL);
+                Autoattach operAa = getAutoAttach(ovsdbNodeAugmentation, new Uri(testAutoattachId));
+
+                // skip tests after verifying that Autoattach doesn't break with unsupported schema
+                Assume.assumeFalse(isOldSchema);
+
+                // FIXME: Remove once CRUD is supported
+                Assume.assumeFalse(operAa == null);
+
+                Assert.assertNotNull(operAa);
+                Assert.assertEquals(testSystemName, operAa.getSystemName());
+                bridge = getBridge(connectionInfo);
+                Uuid aaUuid = new Uuid(operAa.getAutoattachUuid().getValue());
+                Assert.assertEquals(aaUuid, bridge.getAutoAttach());
+
+                // UPDATE: Update mappings column of AutoAttach table that was created
+                List<Mappings> mappings = ImmutableList.of(new MappingsBuilder().setMappingsKey(100L).setMappingsValue(200).build());
+                Autoattach updatedAa = new AutoattachBuilder()
+                        .setAutoattachId(new Uri(testAutoattachId))
+                        .setMappings(mappings)
+                        .build();
+                InstanceIdentifier<Autoattach> iid = SouthboundUtils.createInstanceIdentifier(connectionInfo)
+                        .augmentation(OvsdbNodeAugmentation.class)
+                        .child(Autoattach.class, updatedAa.getKey());
+                final NotifyingDataChangeListener aaOperationalListener =
+                        new NotifyingDataChangeListener(LogicalDatastoreType.OPERATIONAL, iid);
+                aaOperationalListener.registerDataChangeListener();
+                Assert.assertTrue(mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, iid, updatedAa));
+                aaOperationalListener.waitForUpdate(OVSDB_UPDATE_TIMEOUT);
+
+                // UPDATE: Update external_ids column of AutoAttach table that was created
+                List<AutoattachExternalIds> externalIds = new ArrayList<>();
+                externalIds.add(new AutoattachExternalIdsBuilder()
+                        .setAutoattachExternalIdKey(testAutoattachExternalKey)
+                        .setAutoattachExternalIdValue(testAutoattachExternalValue)
+                        .build());
+                updatedAa = new AutoattachBuilder()
+                        .setAutoattachId(new Uri(testAutoattachId))
+                        .setAutoattachExternalIds(externalIds)
+                        .build();
+                Assert.assertTrue(mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, iid, updatedAa));
+                aaOperationalListener.waitForUpdate(OVSDB_UPDATE_TIMEOUT);
+
+                // READ: Read the updated AutoAttach table for latest mappings and external_ids column value
+                ovsdbNodeAugmentation = getOvsdbNode(connectionInfo,
+                        LogicalDatastoreType.OPERATIONAL);
+                operAa = getAutoAttach(ovsdbNodeAugmentation, new Uri(testAutoattachId));
+                Assert.assertNotNull(operAa);
+                List<Mappings> operMappingsList = operAa.getMappings();
+                for (Mappings operMappings: operMappingsList) {
+                    Assert.assertEquals(mappings.get(operMappingsList.indexOf(operMappings)).getMappingsKey(), operMappings.getMappingsKey());
+                    Assert.assertEquals(mappings.get(operMappingsList.indexOf(operMappings)).getMappingsValue(), operMappings.getMappingsValue());
+                }
+                List<AutoattachExternalIds> operExternalIds = operAa.getAutoattachExternalIds();
+                externalIds.add(new AutoattachExternalIdsBuilder()
+                        .setAutoattachExternalIdKey(SouthboundConstants.AUTOATTACH_ID_EXTERNAL_ID_KEY)
+                        .setAutoattachExternalIdValue(operAa.getAutoattachId().getValue())
+                        .build());
+                for (AutoattachExternalIds operExternalId : operExternalIds) {
+                    Assert.assertEquals(externalIds.get(operExternalIds.indexOf(operExternalId)).getAutoattachExternalIdKey(),
+                            operExternalId.getAutoattachExternalIdKey());
+                    Assert.assertEquals(externalIds.get(operExternalIds.indexOf(operExternalId)).getAutoattachExternalIdValue(),
+                            operExternalId.getAutoattachExternalIdValue());
+                }
 
-        Assert.assertTrue(addBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME));
-        OvsdbBridgeAugmentation bridge = getBridge(connectionInfo);
-        Assert.assertNotNull(bridge);
-        LOG.info("bridge: {}", bridge);
-        NodeId nodeId = SouthboundMapper.createManagedNodeId(SouthboundMapper.createInstanceIdentifier(
-                connectionInfo, bridge.getBridgeName()));
-        OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder =
-                createGenericOvsdbTerminationPointAugmentationBuilder();
-        String portName = "testOfPort";
-        ovsdbTerminationBuilder.setName(portName);
-        Long ofPortExpected = new Long(45002);
-        ovsdbTerminationBuilder.setOfport(ofPortExpected);
-        Assert.assertTrue(addTerminationPoint(nodeId, portName, ovsdbTerminationBuilder));
-        InstanceIdentifier<Node> terminationPointIid = getTpIid(connectionInfo, bridge);
-        Node terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid);
-        Assert.assertNotNull(terminationPointNode);
-
-        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(ofPortExpected) || ofPort.equals(new Long(1)));
-                LOG.info("ofPort: {}", ofPort);
+                // DELETE: Delete AutoAttach table
+                Assert.assertTrue(mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, iid));
+                aaOperationalListener.waitForUpdate(OVSDB_UPDATE_TIMEOUT);
+                ovsdbNodeAugmentation = getOvsdbNode(connectionInfo,
+                        LogicalDatastoreType.OPERATIONAL);
+                operAa = getAutoAttach(ovsdbNodeAugmentation, new Uri(testAutoattachId));
+                Assert.assertNull(operAa);
+            } catch (AssumptionViolatedException e) {
+                LOG.warn("Skipped test for Autoattach due to unsupported schema", e);
+            } catch (Exception e) {
+                fail("Unexpected exception in CRUD test for Autoattach table for schema:" + schemaVersion.toString() +". " + e);
             }
         }
-        Assert.assertTrue(deleteBridge(connectionInfo));
     }
 
-    @Test
-    public void testTerminationPointOfPortRequest() throws InterruptedException {
-        ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr);
-        connectOvsdbNode(connectionInfo);
-        Assert.assertTrue(addBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME));
-        OvsdbBridgeAugmentation bridge = getBridge(connectionInfo);
-        Assert.assertNotNull(bridge);
-        NodeId nodeId = SouthboundMapper.createManagedNodeId(SouthboundMapper.createInstanceIdentifier(
-                connectionInfo, bridge.getBridgeName()));
-        OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder =
-                createGenericOvsdbTerminationPointAugmentationBuilder();
-        String portName = "testOfPortRequest";
-        ovsdbTerminationBuilder.setName(portName);
-        Long ofPortExpected = new Long(45008);
-        Integer ofPortRequestExpected = ofPortExpected.intValue();
-        Long ofPortInput = new Long(45008);
-        ovsdbTerminationBuilder.setOfport(ofPortInput);
-        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);
-
-        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(ofPortExpected) || ofPort.equals(new Long(1)));
-                LOG.info("ofPort: {}", ofPort);
-
-                Integer ofPortRequest = ovsdbTerminationPointAugmentation.getOfportRequest();
-                Assert.assertTrue(ofPortRequest.equals(ofPortRequestExpected));
-                LOG.info("ofPortRequest: {}", ofPortRequest);
+    private Autoattach getAutoAttach(OvsdbNodeAugmentation ovsdbNodeAugmentation, Uri uri) {
+        if (ovsdbNodeAugmentation.getAutoattach() != null
+                && !ovsdbNodeAugmentation.getAutoattach().isEmpty()) {
+            for (Autoattach aa : ovsdbNodeAugmentation.getAutoattach()) {
+                if (aa.getKey().getAutoattachId().equals(uri)) {
+                    return aa;
+                }
             }
         }
-        Assert.assertTrue(deleteBridge(connectionInfo));
+        return null;
     }
 
-    @Test
-    public void testTerminationPointPortExternalIds() throws InterruptedException {
-        ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr);
-        connectOvsdbNode(connectionInfo);
-        Assert.assertTrue(addBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME));
-        OvsdbBridgeAugmentation bridge = getBridge(connectionInfo);
-        Assert.assertNotNull(bridge);
-        NodeId nodeId = SouthboundMapper.createManagedNodeId(SouthboundMapper.createInstanceIdentifier(
-                connectionInfo, bridge.getBridgeName()));
-        OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder =
-                createGenericOvsdbTerminationPointAugmentationBuilder();
-        String portName = "testPortExternalIds";
-        ovsdbTerminationBuilder.setName(portName);
-        //setup
-        PortExternalIdsBuilder externalIdsBuilder1 = new PortExternalIdsBuilder();
-        externalIdsBuilder1.setExternalIdKey("portExternalIdKey1");
-        externalIdsBuilder1.setExternalIdValue("portExternalIdValue1");
-        PortExternalIdsBuilder externalIdsBuilder2 = new PortExternalIdsBuilder();
-        externalIdsBuilder2.setExternalIdKey("portExternalIdKey2");
-        externalIdsBuilder2.setExternalIdValue("portExternalIdValue2");
-        List<PortExternalIds> portExternalIds = Lists.newArrayList(externalIdsBuilder1.build(),
-                externalIdsBuilder2.build());
-        ovsdbTerminationBuilder.setPortExternalIds(portExternalIds);
-
-        Assert.assertTrue(addTerminationPoint(nodeId, portName, ovsdbTerminationBuilder));
-        InstanceIdentifier<Node> terminationPointIid = getTpIid(connectionInfo, bridge);
-        Node terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid);
-        Assert.assertNotNull(terminationPointNode);
-
-        List<TerminationPoint> terminationPoints = terminationPointNode.getTerminationPoint();
-        for (TerminationPoint terminationPoint : terminationPoints) {
-            OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation =
-                    terminationPoint.getAugmentation(OvsdbTerminationPointAugmentation.class);
-            if (ovsdbTerminationPointAugmentation.getName().equals(portName)) {
-                List<PortExternalIds> actualPortExternalIds = ovsdbTerminationPointAugmentation.getPortExternalIds();
-                Assert.assertTrue((portExternalIds.size() == actualPortExternalIds.size()));
-                for (PortExternalIds portExternalId : portExternalIds) {
-                    Assert.assertTrue(actualPortExternalIds.contains(portExternalId));
-                }
+    private static class TestQos implements AutoCloseable {
+        private final ConnectionInfo connectionInfo;
+        private final Uri qosId;
+
+        /**
+         * Creates a test qos entry which can be automatically removed when no longer necessary.
+         *
+         * @param connectionInfo The connection information.
+         * @param qosId The Qos identifier.
+         * @param qosType The qos type.
+         * @param externalIds The external identifiers if any.
+         * @param otherConfigs The other configuration items if any.
+         */
+        public TestQos(final ConnectionInfo connectionInfo,
+                                  final Uri qosId,
+                                  final Class<? extends QosTypeBase> qosType,
+                                  @Nullable final List<QosExternalIds> externalIds,
+                                  @Nullable final List<QosOtherConfig> otherConfigs) {
+            this.connectionInfo = connectionInfo;
+            this.qosId = qosId;
+
+            QosEntries qosEntry = new QosEntriesBuilder()
+                .setQosId(qosId)
+                .setQosType(qosType)
+                .setQosExternalIds(externalIds)
+                .setQosOtherConfig(otherConfigs)
+                .build();
+            InstanceIdentifier<QosEntries> qeIid = SouthboundUtils.createInstanceIdentifier(connectionInfo)
+                    .augmentation(OvsdbNodeAugmentation.class)
+                    .child(QosEntries.class, qosEntry.getKey());
+            final NotifyingDataChangeListener qosOperationalListener =
+                    new NotifyingDataChangeListener(LogicalDatastoreType.OPERATIONAL, qeIid);
+            qosOperationalListener.registerDataChangeListener();
+
+            Assert.assertTrue(
+                    mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION,
+                    qeIid, qosEntry));
+
+            try {
+                qosOperationalListener.waitForCreation(OVSDB_ROUNDTRIP_TIMEOUT);
+            } catch (InterruptedException e) {
+                LOG.warn("Sleep interrupted while waiting for queue {}", qeIid, e);
             }
+
         }
-        Assert.assertTrue(deleteBridge(connectionInfo));
-    }
 
-    @Test
-    public void testTerminationPointInterfaceExternalIds() throws InterruptedException {
-        ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr);
-        connectOvsdbNode(connectionInfo);
-        Assert.assertTrue(addBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME));
-        OvsdbBridgeAugmentation bridge = getBridge(connectionInfo);
-        Assert.assertNotNull(bridge);
-        NodeId nodeId = SouthboundMapper.createManagedNodeId(SouthboundMapper.createInstanceIdentifier(
-                connectionInfo, bridge.getBridgeName()));
-        OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder =
-                createGenericOvsdbTerminationPointAugmentationBuilder();
-        String portName = "testInterfaceExternalIds";
-        ovsdbTerminationBuilder.setName(portName);
-        //setup
-        InterfaceExternalIdsBuilder externalIdsBuilder1 = new InterfaceExternalIdsBuilder();
-        externalIdsBuilder1.setExternalIdKey("interfaceExternalIdKey1");
-        externalIdsBuilder1.setExternalIdValue("interfaceExternalIdValue1");
-        InterfaceExternalIdsBuilder externalIdsBuilder2 = new InterfaceExternalIdsBuilder();
-        externalIdsBuilder2.setExternalIdKey("interfaceExternalIdKey2");
-        externalIdsBuilder2.setExternalIdValue("interfaceExternalIdValue2");
-        List<InterfaceExternalIds> interfaceExternalIds = Lists.newArrayList(externalIdsBuilder1.build(),
-                externalIdsBuilder2.build());
-        ovsdbTerminationBuilder.setInterfaceExternalIds(interfaceExternalIds);
-
-        Assert.assertTrue(addTerminationPoint(nodeId, portName, ovsdbTerminationBuilder));
-        InstanceIdentifier<Node> terminationPointIid = getTpIid(connectionInfo, bridge);
-        Node terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid);
-        Assert.assertNotNull(terminationPointNode);
-
-        List<TerminationPoint> terminationPoints = terminationPointNode.getTerminationPoint();
-        for (TerminationPoint terminationPoint : terminationPoints) {
-            OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation =
-                    terminationPoint.getAugmentation(OvsdbTerminationPointAugmentation.class);
-            if (ovsdbTerminationPointAugmentation.getName().equals(portName)) {
-                List<InterfaceExternalIds> actualInterfaceExternalIds = ovsdbTerminationPointAugmentation.
-                        getInterfaceExternalIds();
-                Assert.assertTrue((interfaceExternalIds.size() == actualInterfaceExternalIds.size()));
-                for (InterfaceExternalIds interfaceExternalId : interfaceExternalIds) {
-                    Assert.assertTrue(actualInterfaceExternalIds.contains(interfaceExternalId));
-                }
+        @Override
+        public void close() {
+            final InstanceIdentifier<QosEntries> qeIid = SouthboundUtils.createInstanceIdentifier(connectionInfo)
+                    .augmentation(OvsdbNodeAugmentation.class)
+                    .child(QosEntries.class, new QosEntriesKey(this.qosId));
+            final NotifyingDataChangeListener qosOperationalListener =
+                    new NotifyingDataChangeListener(LogicalDatastoreType.OPERATIONAL, qeIid);
+            qosOperationalListener.registerDataChangeListener();
+
+            Assert.assertTrue(mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, qeIid));
+            try {
+                qosOperationalListener.waitForDeletion(OVSDB_ROUNDTRIP_TIMEOUT);
+            } catch (InterruptedException e) {
+                LOG.warn("Sleep interrupted while waiting for qos deletion (qos {})", qeIid, e);
             }
         }
-        Assert.assertTrue(deleteBridge(connectionInfo));
     }
 
-    @Test
-    public void testTerminationPointOptions() throws InterruptedException {
-        ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr);
-        connectOvsdbNode(connectionInfo);
-        Assert.assertTrue(addBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME));
-        OvsdbBridgeAugmentation bridge = getBridge(connectionInfo);
-        Assert.assertNotNull(bridge);
-        NodeId nodeId = SouthboundMapper.createManagedNodeId(SouthboundMapper.createInstanceIdentifier(
-                connectionInfo, bridge.getBridgeName()));
-        OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder =
-                createGenericOvsdbTerminationPointAugmentationBuilder();
-        String portName = "testInterfaceOptions";
-        ovsdbTerminationBuilder.setName(portName);
-        //setup
-        OptionsBuilder optionsBuilder1 = new OptionsBuilder();
-        optionsBuilder1.setOption("option1");
-        optionsBuilder1.setValue("optionValue1");
-        OptionsBuilder optionsBuilder2 = new OptionsBuilder();
-        optionsBuilder2.setOption("option2");
-        optionsBuilder2.setValue("optionValue2");
-        List<Options> options = Lists.newArrayList(optionsBuilder1.build(),
-                optionsBuilder2.build());
-        ovsdbTerminationBuilder.setOptions(options);
-
-        Assert.assertTrue(addTerminationPoint(nodeId, portName, ovsdbTerminationBuilder));
-        InstanceIdentifier<Node> terminationPointIid = getTpIid(connectionInfo, bridge);
-        Node terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid);
-        Assert.assertNotNull(terminationPointNode);
-
-        List<TerminationPoint> terminationPoints = terminationPointNode.getTerminationPoint();
-        for (TerminationPoint terminationPoint : terminationPoints) {
-            OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation =
-                    terminationPoint.getAugmentation(OvsdbTerminationPointAugmentation.class);
-            if (ovsdbTerminationPointAugmentation.getName().equals(portName)) {
-                List<Options> actualOptions = ovsdbTerminationPointAugmentation.
-                        getOptions();
-                Assert.assertTrue((options.size() == actualOptions.size()));
-                for (Options option : options) {
-                    Assert.assertTrue(actualOptions.contains(option));
-                }
+    private static class TestQueue implements AutoCloseable {
+        private final ConnectionInfo connectionInfo;
+        private final Uri queueId;
+
+        /**
+         * Creates a test queue entry which can be automatically removed when no longer necessary.
+         *
+         * @param connectionInfo The connection information.
+         * @param queueId The Queue identifier.
+         * @param queueDscp The queue dscp value.
+         * @param externalIds The external identifiers if any.
+         * @param otherConfigs The other configuration items if any.
+         */
+        public TestQueue(final ConnectionInfo connectionInfo,
+                                  final Uri queueId,
+                                  final Short queueDscp,
+                                  @Nullable final List<QueuesExternalIds> externalIds,
+                                  @Nullable final List<QueuesOtherConfig> otherConfigs) {
+            this.connectionInfo = connectionInfo;
+            this.queueId = queueId;
+
+            Queues queue = new QueuesBuilder()
+                .setQueueId(queueId)
+                .setDscp(queueDscp)
+                .setQueuesExternalIds(externalIds)
+                .setQueuesOtherConfig(otherConfigs)
+                .build();
+            InstanceIdentifier<Queues> qIid = SouthboundUtils.createInstanceIdentifier(connectionInfo)
+                    .augmentation(OvsdbNodeAugmentation.class)
+                    .child(Queues.class, queue.getKey());
+            final NotifyingDataChangeListener queueOperationalListener =
+                    new NotifyingDataChangeListener(LogicalDatastoreType.OPERATIONAL, qIid);
+            queueOperationalListener.registerDataChangeListener();
+
+            Assert.assertTrue(
+                    mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION,
+                    qIid, queue));
+
+            try {
+                queueOperationalListener.waitForCreation(OVSDB_ROUNDTRIP_TIMEOUT);
+            } catch (InterruptedException e) {
+                LOG.warn("Sleep interrupted while waiting for queue {}", queueId, e);
             }
         }
-        Assert.assertTrue(deleteBridge(connectionInfo));
-    }
 
-    @Test
-    public void testTerminationPointInterfaceOtherConfigs() throws InterruptedException {
-        ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr);
-        connectOvsdbNode(connectionInfo);
-        Assert.assertTrue(addBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME));
-        OvsdbBridgeAugmentation bridge = getBridge(connectionInfo);
-        Assert.assertNotNull(bridge);
-        NodeId nodeId = SouthboundMapper.createManagedNodeId(SouthboundMapper.createInstanceIdentifier(
-                connectionInfo, bridge.getBridgeName()));
-        OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder =
-                createGenericOvsdbTerminationPointAugmentationBuilder();
-        String portName = "testInterfaceOtherConfigs";
-        ovsdbTerminationBuilder.setName(portName);
-        //setup
-        InterfaceOtherConfigsBuilder interfaceBuilder1 = new InterfaceOtherConfigsBuilder();
-        interfaceBuilder1.setOtherConfigKey("interfaceOtherConfigsKey1");
-        interfaceBuilder1.setOtherConfigValue("interfaceOtherConfigsValue1");
-        InterfaceOtherConfigsBuilder interfaceBuilder2 = new InterfaceOtherConfigsBuilder();
-        interfaceBuilder2.setOtherConfigKey("interfaceOtherConfigsKey2");
-        interfaceBuilder2.setOtherConfigValue("interfaceOtherConfigsValue2");
-        List<InterfaceOtherConfigs> interfaceOtherConfigs = Lists.newArrayList(interfaceBuilder1.build(),
-                interfaceBuilder2.build());
-        ovsdbTerminationBuilder.setInterfaceOtherConfigs(interfaceOtherConfigs);
-
-        Assert.assertTrue(addTerminationPoint(nodeId, portName, ovsdbTerminationBuilder));
-        Thread.sleep(1000);
-        InstanceIdentifier<Node> terminationPointIid = getTpIid(connectionInfo, bridge);
-        Node terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid);
-        Assert.assertNotNull(terminationPointNode);
-
-        List<TerminationPoint> terminationPoints = terminationPointNode.getTerminationPoint();
-        for (TerminationPoint terminationPoint : terminationPoints) {
-            OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation =
-                    terminationPoint.getAugmentation(OvsdbTerminationPointAugmentation.class);
-            if (ovsdbTerminationPointAugmentation.getName().equals(portName)) {
-                List<InterfaceOtherConfigs> actualInterfaceOtherConfigs = ovsdbTerminationPointAugmentation.
-                        getInterfaceOtherConfigs();
-                Assert.assertNotNull(actualInterfaceOtherConfigs);
-                Assert.assertNotNull(interfaceOtherConfigs);
-                Assert.assertTrue(interfaceOtherConfigs.size() == actualInterfaceOtherConfigs.size());
-                for (InterfaceOtherConfigs interfaceOtherConfig : interfaceOtherConfigs) {
-                    Assert.assertTrue(actualInterfaceOtherConfigs.contains(interfaceOtherConfig));
-                }
+        @Override
+        public void close() {
+            InstanceIdentifier<Queues> qIid = SouthboundUtils.createInstanceIdentifier(connectionInfo)
+                    .augmentation(OvsdbNodeAugmentation.class)
+                    .child(Queues.class, new QueuesKey(this.queueId));
+            final NotifyingDataChangeListener queueOperationalListener =
+                    new NotifyingDataChangeListener(LogicalDatastoreType.OPERATIONAL, qIid);
+            queueOperationalListener.registerDataChangeListener();
+
+            Assert.assertTrue(mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, qIid));
+            try {
+                queueOperationalListener.waitForDeletion(OVSDB_ROUNDTRIP_TIMEOUT);
+            } catch (InterruptedException e) {
+                LOG.warn("Sleep interrupted while waiting for queue deletion (queue {})", queueId, e);
             }
         }
-        Assert.assertTrue(deleteBridge(connectionInfo));
     }
 
-    @Test
-    public void testTerminationPointPortOtherConfigs() throws InterruptedException {
-        ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr);
-        connectOvsdbNode(connectionInfo);
-        Assert.assertTrue(addBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME));
-        OvsdbBridgeAugmentation bridge = getBridge(connectionInfo);
-        Assert.assertNotNull(bridge);
-        NodeId nodeId = SouthboundMapper.createManagedNodeId(SouthboundMapper.createInstanceIdentifier(
-                connectionInfo, bridge.getBridgeName()));
-        OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder =
-                createGenericOvsdbTerminationPointAugmentationBuilder();
-        String portName = "testPortOtherConfigs";
-        ovsdbTerminationBuilder.setName(portName);
-        //setup
-        PortOtherConfigsBuilder portBuilder1 = new PortOtherConfigsBuilder();
-        portBuilder1.setOtherConfigKey("portOtherConfigsKey1");
-        portBuilder1.setOtherConfigValue("portOtherConfigsValue1");
-        PortOtherConfigsBuilder portBuilder2 = new PortOtherConfigsBuilder();
-        portBuilder2.setOtherConfigKey("portOtherConfigsKey2");
-        portBuilder2.setOtherConfigValue("portOtherConfigsValue2");
-        List<PortOtherConfigs> portOtherConfigs = Lists.newArrayList(portBuilder1.build(),
-                portBuilder2.build());
-        ovsdbTerminationBuilder.setPortOtherConfigs(portOtherConfigs);
-
-        Assert.assertTrue(addTerminationPoint(nodeId, portName, ovsdbTerminationBuilder));
-        InstanceIdentifier<Node> terminationPointIid = getTpIid(connectionInfo, bridge);
-        Node terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid);
-        Assert.assertNotNull(terminationPointNode);
-
-        List<TerminationPoint> terminationPoints = terminationPointNode.getTerminationPoint();
-        for (TerminationPoint terminationPoint : terminationPoints) {
-            OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation =
-                    terminationPoint.getAugmentation(OvsdbTerminationPointAugmentation.class);
-            if (ovsdbTerminationPointAugmentation.getName().equals(portName)) {
-                List<PortOtherConfigs> actualPortOtherConfigs = ovsdbTerminationPointAugmentation.
-                        getPortOtherConfigs();
-                Assert.assertTrue((portOtherConfigs.size() == actualPortOtherConfigs.size()));
-                for (PortOtherConfigs portOtherConfig : portOtherConfigs) {
-                    Assert.assertTrue(actualPortOtherConfigs.contains(portOtherConfig));
-                }
-            }
-        }
-        Assert.assertTrue(deleteBridge(connectionInfo));
+    private OvsdbNodeAugmentation getOvsdbNode(ConnectionInfo connectionInfo, LogicalDatastoreType store) {
+        InstanceIdentifier<Node> nodeIid = SouthboundUtils.createInstanceIdentifier(connectionInfo);
+        Node node = mdsalUtils.read(store, nodeIid);
+        Assert.assertNotNull(node);
+        OvsdbNodeAugmentation ovsdbNodeAugmentation = node.getAugmentation(OvsdbNodeAugmentation.class);
+        Assert.assertNotNull(ovsdbNodeAugmentation);
+        return ovsdbNodeAugmentation;
     }
 
-    @Test
-    public void testTerminationPointVlan() throws InterruptedException {
-        ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr);
-        connectOvsdbNode(connectionInfo);
-        Assert.assertTrue(addBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME));
-        OvsdbBridgeAugmentation bridge = getBridge(connectionInfo);
-        Assert.assertNotNull(bridge);
-        NodeId nodeId = SouthboundMapper.createManagedNodeId(SouthboundMapper.createInstanceIdentifier(
-                connectionInfo, bridge.getBridgeName()));
-        OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder =
-                createGenericOvsdbTerminationPointAugmentationBuilder();
-        String portName = "testTerminationPointVlanId";
-        ovsdbTerminationBuilder.setName(portName);
-        //setup
-        Integer vlanId = new Integer(4000);
-        ovsdbTerminationBuilder.setVlanTag(new VlanId(vlanId));
+    private OvsdbBridgeAugmentation getBridge(ConnectionInfo connectionInfo) {
+        return getBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME);
+    }
 
-        Assert.assertTrue(addTerminationPoint(nodeId, portName, ovsdbTerminationBuilder));
-        InstanceIdentifier<Node> terminationPointIid = getTpIid(connectionInfo, bridge);
-        Node terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid);
-        Assert.assertNotNull(terminationPointNode);
+    /**
+     * Extract the <code>store</code> type data store contents for the particular bridge identified by
+     * <code>bridgeName</code>.
+     *
+     * @param connectionInfo the connection information
+     * @param bridgeName the bridge name
+     * @param store defined by the <code>LogicalDatastoreType</code> enumeration
+     * @return <code>store</code> type data store contents
+     */
+    private OvsdbBridgeAugmentation getBridge(ConnectionInfo connectionInfo, String bridgeName,
+                                              LogicalDatastoreType store) {
+        Node bridgeNode = getBridgeNode(connectionInfo, bridgeName, store);
+        Assert.assertNotNull(bridgeNode);
+        OvsdbBridgeAugmentation ovsdbBridgeAugmentation = bridgeNode.getAugmentation(OvsdbBridgeAugmentation.class);
+        Assert.assertNotNull(ovsdbBridgeAugmentation);
+        return ovsdbBridgeAugmentation;
+    }
 
-        List<TerminationPoint> terminationPoints = terminationPointNode.getTerminationPoint();
-        for (TerminationPoint terminationPoint : terminationPoints) {
-            OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation =
-                    terminationPoint.getAugmentation(OvsdbTerminationPointAugmentation.class);
-            if (ovsdbTerminationPointAugmentation.getName().equals(portName)) {
-                //test
-                VlanId actualVlanId = ovsdbTerminationPointAugmentation.getVlanTag();
-                Assert.assertNotNull(actualVlanId);
-                Integer actualVlanIdInt = actualVlanId.getValue();
-                Assert.assertTrue(actualVlanIdInt.equals(vlanId));
-            }
-        }
-        Assert.assertTrue(deleteBridge(connectionInfo));
+    /**
+     * extract the <code>LogicalDataStoreType.OPERATIONAL</code> type data store contents for the particular bridge
+     * identified by <code>bridgeName</code>
+     *
+     * @param connectionInfo the connection information
+     * @param bridgeName the bridge name
+     * @see <code>SouthboundIT.getBridge(ConnectionInfo, String, LogicalDatastoreType)</code>
+     * @return <code>LogicalDatastoreType.OPERATIONAL</code> type data store contents
+     */
+    private OvsdbBridgeAugmentation getBridge(ConnectionInfo connectionInfo, String bridgeName) {
+        return getBridge(connectionInfo, bridgeName, LogicalDatastoreType.OPERATIONAL);
     }
 
-    @Test
-    public void testTerminationPointVlanModes() throws InterruptedException {
-        VlanMode []vlanModes = VlanMode.values();
-        for (VlanMode vlanMode : vlanModes) {
-            ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr);
-            connectOvsdbNode(connectionInfo);
-            Assert.assertTrue(addBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME));
-            OvsdbBridgeAugmentation bridge = getBridge(connectionInfo);
-            Assert.assertNotNull(bridge);
-            NodeId nodeId = SouthboundMapper.createManagedNodeId(SouthboundMapper.createInstanceIdentifier(
-                    connectionInfo, bridge.getBridgeName()));
-            OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder =
-                    createGenericOvsdbTerminationPointAugmentationBuilder();
-            String portName = "testTerminationPointVlanMode" + vlanMode.toString();
-            ovsdbTerminationBuilder.setName(portName);
-            //setup
-            ovsdbTerminationBuilder.setVlanMode(vlanMode);
+    /**
+     * Extract the node contents from <code>store</code> type data store for the
+     * bridge identified by <code>bridgeName</code>
+     *
+     * @param connectionInfo the connection information
+     * @param bridgeName the bridge name
+     * @param store defined by the <code>LogicalDatastoreType</code> enumeration
+     * @return <code>store</code> type data store contents
+     */
+    private Node getBridgeNode(ConnectionInfo connectionInfo, String bridgeName, LogicalDatastoreType store) {
+        InstanceIdentifier<Node> bridgeIid =
+                SouthboundUtils.createInstanceIdentifier(connectionInfo, new OvsdbBridgeName(bridgeName));
+        return mdsalUtils.read(store, bridgeIid);
+    }
+
+    /**
+     * Extract the node contents from <code>LogicalDataStoreType.OPERATIONAL</code> data store for the
+     * bridge identified by <code>bridgeName</code>
+     *
+     * @param connectionInfo the connection information
+     * @param bridgeName the bridge name
+     * @return <code>LogicalDatastoreType.OPERATIONAL</code> type data store contents
+     */
+    private Node getBridgeNode(ConnectionInfo connectionInfo, String bridgeName) {
+        return getBridgeNode(connectionInfo, bridgeName, LogicalDatastoreType.OPERATIONAL);
+    }
+
+    @Test
+    public void testAddDeleteBridge() throws InterruptedException {
+        ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
+
+        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 SouthboundUtils.createInstanceIdentifier(connectionInfo, bridge.getBridgeName());
+    }
+
+    /**
+     * Extracts the <code>TerminationPointAugmentation</code> for the <code>index</code> <code>TerminationPoint</code>
+     * on <code>bridgeName</code>
+     *
+     * @param connectionInfo the connection information
+     * @param bridgeName the bridge name
+     * @param store defined by the <code>LogicalDatastoreType</code> enumeration
+     * @param index the index we're interested in
+     * @return the augmentation (or {@code null} if none)
+     */
+    private OvsdbTerminationPointAugmentation getOvsdbTerminationPointAugmentation(
+            ConnectionInfo connectionInfo, String bridgeName, LogicalDatastoreType store, int index) {
+
+        List<TerminationPoint> tpList = getBridgeNode(connectionInfo, bridgeName, store).getTerminationPoint();
+        if (tpList == null) {
+            return null;
+        }
+        return tpList.get(index).getAugmentation(OvsdbTerminationPointAugmentation.class);
+    }
+
+    @Test
+    public void testCRUDTerminationPointIfIndex() throws InterruptedException {
+        final boolean isOldSchema = schemaVersion.compareTo(IF_INDEX_FROM_VERSION) < 0;
+        Assume.assumeFalse(isOldSchema);
+        ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
+
+        // Test create ifIndex
+        try (TestBridge testBridge = new TestBridge(connectionInfo, null, SouthboundITConstants.BRIDGE_NAME, null, true,
+                SouthboundConstants.OVSDB_FAIL_MODE_MAP.inverse().get("secure"),
+                true, SouthboundMapper.createDatapathType("netdev"), null, null, null)) {
+            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 = "testIfIndex";
+            ovsdbTerminationBuilder.setName(portName);
+
             Assert.assertTrue(addTerminationPoint(nodeId, portName, ovsdbTerminationBuilder));
             InstanceIdentifier<Node> terminationPointIid = getTpIid(connectionInfo, bridge);
             Node terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid);
             Assert.assertNotNull(terminationPointNode);
 
+            // Test read ifIndex
             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));
+                    Long ifIndex = ovsdbTerminationPointAugmentation.getIfindex();
+                    Assert.assertNotNull(ifIndex);
+                    LOG.info("ifIndex: {} for the port:{}", ifIndex, portName);
                 }
             }
-            Assert.assertTrue(deleteBridge(connectionInfo));
         }
     }
 
-    private ArrayList<Set<Integer>> generateVlanSets() {
-        ArrayList<Set<Integer>> vlanSets = new ArrayList<Set<Integer>>();
+    @Test
+    public void testCRDTerminationPointOfPort() throws InterruptedException {
+        final Long OFPORT_EXPECTED = 45002L;
+
+        ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
 
-        Set<Integer> emptySet = new HashSet<Integer>();
-        vlanSets.add(emptySet);
+        // CREATE
+        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);
 
-        Set<Integer> singleSet = new HashSet<Integer>();
-        Integer single = new Integer(2222);
-        singleSet.add(single);
-        vlanSets.add(singleSet);
+            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);
 
-        Set<Integer> minMaxMiddleSet = new HashSet<Integer>();
-        Integer min = new Integer(0);
-        minMaxMiddleSet.add(min);
-        Integer max = new Integer(4095);
-        minMaxMiddleSet.add(max);
-        Integer minPlusOne = new Integer(min + 1);
-        minMaxMiddleSet.add(minPlusOne);
-        Integer maxMinusOne = new Integer(max - 1);
-        minMaxMiddleSet.add(maxMinusOne);
-        Integer middle = new Integer((max - min) / 2);
-        minMaxMiddleSet.add(middle);
-        vlanSets.add(minMaxMiddleSet);
+            // 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);
+                }
+            }
 
-        return vlanSets;
-    }
+            // 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."
 
-    private List<Trunks> buildTrunkList(Set<Integer> trunkSet) {
-        List<Trunks> trunkList = Lists.newArrayList();
-        for (Integer trunk : trunkSet) {
-            TrunksBuilder trunkBuilder = new TrunksBuilder();
-            trunkBuilder.setTrunk(new VlanId(trunk));
-            trunkList.add(trunkBuilder.build());
+            // DELETE handled by TestBridge
         }
-        return trunkList;
     }
 
     @Test
-    public void testTerminationPointVlanTrunks() throws InterruptedException {
-        ArrayList<Set<Integer>> vlanSets = generateVlanSets();
-        int testCase = 0;
-        for (Set<Integer> vlanSet : vlanSets) {
-            ++testCase;
-            ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr);
-            connectOvsdbNode(connectionInfo);
-            Assert.assertTrue(addBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME));
+    public void testCRDTerminationPointOfPortRequest() throws InterruptedException {
+        final Long OFPORT_EXPECTED = 45008L;
+        final Long OFPORT_INPUT = 45008L;
+
+        ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
+
+        // CREATE
+        try (TestBridge testBridge = new TestBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME)) {
             OvsdbBridgeAugmentation bridge = getBridge(connectionInfo);
             Assert.assertNotNull(bridge);
-            NodeId nodeId = SouthboundMapper.createManagedNodeId(SouthboundMapper.createInstanceIdentifier(
+            NodeId nodeId = SouthboundUtils.createManagedNodeId(SouthboundUtils.createInstanceIdentifier(
                     connectionInfo, bridge.getBridgeName()));
             OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder =
                     createGenericOvsdbTerminationPointAugmentationBuilder();
-            String portName = "testTerminationPointVlanTrunks" + testCase;
+            String portName = "testOfPortRequest";
             ovsdbTerminationBuilder.setName(portName);
-            //setup
-            List<Trunks> trunks = buildTrunkList(vlanSet);
-            ovsdbTerminationBuilder.setTrunks(trunks);
+            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)) {
-                    List<Trunks> actualTrunks = ovsdbTerminationPointAugmentation.getTrunks();
-                    for (Trunks trunk : trunks) {
-                        Assert.assertTrue(actualTrunks.contains(trunk));
+                    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. "
+
+            // DELETE handled by TestBridge
+        }
+    }
+
+    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 interface SouthboundTerminationPointHelper<T> {
+        void writeValues(OvsdbTerminationPointAugmentationBuilder builder, List<T> values);
+        List<T> readValues(OvsdbTerminationPointAugmentation augmentation);
+    }
+
+    /*
+     * 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;
+
+        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<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 testBridgeAndPortName = String.format("%s_%s", prefix, updateToTestCase.name);
+
+                // 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);
+                    }
+
+                    // 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
+                }
+            }
+        }
+    }
+
+    /*
+     * 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());
+    }
+
+    /*
+     * 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());
+    }
+
+    /*
+     * Tests the CRUD operations for <code>Interface</code> <code>lldp</code>.
+     *
+     * @see <code>SouthboundIT.generateInterfaceLldpTestCases()</code> for specific test case information
+     */
+    @Test
+    public void testCRUDTerminationPointInterfaceLldp() throws InterruptedException {
+        testCRUDTerminationPoint(new SouthboundInterfaceLldpBuilder(), "TPInterfaceLldp",
+                new InterfaceLldpSouthboundHelper());
+    }
+
+    /*
+     * 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());
+    }
+
+    /*
+     * 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());
+    }
+
+    /*
+     * Tests the CRUD operations for <code>Port</code> <code>other_configs</code>.
+     *
+     * @see <code>SouthboundIT.generatePortExternalIdsTestCases()</code> for specific test case information
+     */
+    @Test
+    public void testCRUDTerminationPointPortOtherConfigs() throws InterruptedException {
+        testCRUDTerminationPoint(new SouthboundPortOtherConfigsBuilder(), "TPPortOtherConfigs",
+                new PortOtherConfigsSouthboundHelper());
+    }
+
+    @Test
+    public void testCRUDTerminationPoints() throws InterruptedException {
+        String port1 = "vx1";
+        String port2 = "vxlanport";
+        ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
+
+        try (TestBridge testBridge = new TestBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME)) {
+            OvsdbBridgeAugmentation bridge = getBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME);
+            Assert.assertNotNull(bridge);
+            NodeId nodeId = SouthboundUtils.createManagedNodeId(SouthboundUtils.createInstanceIdentifier(
+                    connectionInfo, bridge.getBridgeName()));
+            OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder =
+                    createGenericOvsdbTerminationPointAugmentationBuilder();
+
+            // add and delete a single port
+            String portName = port1;
+            ovsdbTerminationBuilder.setName(portName);
+            Assert.assertTrue(addTerminationPoint(nodeId, portName, ovsdbTerminationBuilder));
+            InstanceIdentifier<Node> terminationPointIid = getTpIid(connectionInfo, bridge);
+            Node terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid);
+            Assert.assertNotNull(terminationPointNode);
+
+            SouthboundUtils.createInstanceIdentifier(connectionInfo,
+                    new OvsdbBridgeName(SouthboundITConstants.BRIDGE_NAME));
+            portName = port1;
+            InstanceIdentifier<TerminationPoint> nodePath =
+                    SouthboundUtils.createInstanceIdentifier(connectionInfo,
+                            new OvsdbBridgeName(SouthboundITConstants.BRIDGE_NAME))
+                            .child(TerminationPoint.class, new TerminationPointKey(new TpId(portName)));
+
+            Assert.assertTrue("failed to delete port " + portName,
+                    mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, nodePath));
+            LOG.info("shague: waiting for delete {}", portName);
+            Thread.sleep(1000);
+            TerminationPoint terminationPoint = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, nodePath);
+            Assert.assertNull(terminationPoint);
+
+            // add two ports, then delete them
+            portName = port1;
+            ovsdbTerminationBuilder.setName(portName);
+            Assert.assertTrue(addTerminationPoint(nodeId, portName, ovsdbTerminationBuilder));
+            terminationPointIid = getTpIid(connectionInfo, bridge);
+            terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid);
+            Assert.assertNotNull(terminationPointNode);
+
+            portName = port2;
+            ovsdbTerminationBuilder.setName(portName);
+            Assert.assertTrue(addTerminationPoint(nodeId, portName, ovsdbTerminationBuilder));
+            terminationPointIid = getTpIid(connectionInfo, bridge);
+            terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid);
+            Assert.assertNotNull(terminationPointNode);
+
+            SouthboundUtils.createInstanceIdentifier(connectionInfo,
+                    new OvsdbBridgeName(SouthboundITConstants.BRIDGE_NAME));
+            portName = port1;
+            nodePath =
+                    SouthboundUtils.createInstanceIdentifier(connectionInfo,
+                            new OvsdbBridgeName(SouthboundITConstants.BRIDGE_NAME))
+                            .child(TerminationPoint.class, new TerminationPointKey(new TpId(portName)));
+
+            Assert.assertTrue("failed to delete port " + portName,
+                    mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, nodePath));
+            LOG.info("shague: waiting for delete {}", portName);
+            Thread.sleep(1000);
+            terminationPoint = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, nodePath);
+            Assert.assertNull(terminationPoint);
+
+            portName = port2;
+            nodePath = SouthboundUtils.createInstanceIdentifier(connectionInfo,
+                    new OvsdbBridgeName(SouthboundITConstants.BRIDGE_NAME))
+                    .child(TerminationPoint.class, new TerminationPointKey(new TpId(portName)));
+
+            Assert.assertTrue("failed to delete port " + portName,
+                    mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, nodePath));
+            LOG.info("shague: waiting for delete {}", portName);
+            Thread.sleep(1000);
+            terminationPoint = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, nodePath);
+            Assert.assertNull(terminationPoint);
+
+            // DELETE handled by TestBridge
+        }
+    }
+
+    @Test
+    public void testCRUDTerminationPointVlan() throws InterruptedException {
+        final Integer CREATED_VLAN_ID = 4000;
+        final Integer UPDATED_VLAN_ID = 4001;
+
+        ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
+
+        // CREATE
+        try (TestBridge testBridge = new TestBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME)) {
+            OvsdbBridgeAugmentation bridge = getBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME);
+            Assert.assertNotNull(bridge);
+            NodeId nodeId = SouthboundUtils.createManagedNodeId(SouthboundUtils.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 = 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 = 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 handled by TestBridge
+        }
+    }
+
+    @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));
+                    }
+                }
+
+                // 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);
+
+                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());
+                    }
+                }
+
+                // DELETE handled by TestBridge
+            }
+        }
+    }
+
+    @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) {
+        List<Trunks> trunkList = Lists.newArrayList();
+        for (Integer trunk : trunkSet) {
+            TrunksBuilder trunkBuilder = new TrunksBuilder();
+            trunkBuilder.setTrunk(new VlanId(trunk));
+            trunkList.add(trunkBuilder.build());
+        }
+        return trunkList;
+    }
+
+    @Test
+    public void testCRUDTerminationPointVlanTrunks() throws InterruptedException {
+        final List<Trunks> UPDATED_TRUNKS = buildTrunkList(Sets.newHashSet(2011));
+        ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
+        Iterable<Set<Integer>> vlanSets = generateVlanSets();
+        int testCase = 0;
+        for (Set<Integer> vlanSet : vlanSets) {
+            ++testCase;
+            // CREATE
+            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 = 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());
                     }
                 }
+
+                // DELETE handled by TestBridge
             }
-            Assert.assertTrue(deleteBridge(connectionInfo));
+        }
+    }
+
+    /*
+     * Tests setting and deleting <code>qos</code> field in a <code>port</code>.
+     */
+    @Test
+    public void testCRUDTerminationPointQos() throws InterruptedException {
+        ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
+        String testQosId = new String("testQosEntry");
+
+        // CREATE
+        try (TestBridge testBridge = new TestBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME);
+                TestQos testQos = new TestQos(connectionInfo, new Uri(testQosId),
+                        SouthboundMapper.createQosType(SouthboundConstants.QOS_LINUX_HFSC), null, null)) {
+            OvsdbNodeAugmentation ovsdbNodeAugmentation = getOvsdbNode(connectionInfo,
+                    LogicalDatastoreType.OPERATIONAL);
+            QosEntries operQos = getQos(new Uri(testQosId), ovsdbNodeAugmentation);
+            Assert.assertNotNull(operQos);
+            Uuid qosUuid = new Uuid(operQos.getQosUuid().getValue());
+
+            OvsdbBridgeAugmentation bridge = getBridge(connectionInfo);
+            Assert.assertNotNull(bridge);
+            NodeId nodeId = SouthboundUtils.createManagedNodeId(connectionInfo, bridge.getBridgeName());
+            OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder =
+                    createGenericOvsdbTerminationPointAugmentationBuilder();
+            String portName = "testTerminationPointQos";
+            ovsdbTerminationBuilder.setName(portName);
+            ovsdbTerminationBuilder.setQos(qosUuid);
+            Assert.assertTrue(addTerminationPoint(nodeId, portName, ovsdbTerminationBuilder));
+
+            // READ and check that qos uuid has been added to the port
+            InstanceIdentifier<TerminationPoint> tpEntryIid = getTpIid(connectionInfo, bridge)
+                    .child(TerminationPoint.class, new TerminationPointKey(new TpId(portName)));
+            TerminationPoint terminationPoint = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, tpEntryIid);
+            Assert.assertNotNull(terminationPoint);
+            OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation =
+                    terminationPoint.getAugmentation(OvsdbTerminationPointAugmentation.class);
+            Assert.assertEquals(ovsdbTerminationPointAugmentation.getQos(), qosUuid);
+
+            // UPDATE - remove the qos entry from the port
+            OvsdbTerminationPointAugmentationBuilder tpUpdateAugmentationBuilder =
+                    new OvsdbTerminationPointAugmentationBuilder();
+            tpUpdateAugmentationBuilder.setName(portName);
+            TerminationPointBuilder tpUpdateBuilder = new TerminationPointBuilder();
+            tpUpdateBuilder.setKey(new TerminationPointKey(new TpId(portName)));
+            tpUpdateBuilder.addAugmentation(
+                    OvsdbTerminationPointAugmentation.class,
+                    tpUpdateAugmentationBuilder.build());
+            tpUpdateBuilder.setTpId(new TpId(portName));
+
+            Assert.assertTrue(
+                    mdsalUtils.put(LogicalDatastoreType.CONFIGURATION, tpEntryIid, tpUpdateBuilder.build()));
+            Thread.sleep(OVSDB_UPDATE_TIMEOUT);
+
+            // READ and verify that qos uuid has been removed from port
+            TerminationPoint terminationPointUpdate = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, tpEntryIid);
+            Assert.assertNotNull(terminationPointUpdate);
+            OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentationUpdate =
+                    terminationPointUpdate.getAugmentation(OvsdbTerminationPointAugmentation.class);
+            Assert.assertNull(ovsdbTerminationPointAugmentationUpdate.getQos());
+
+            // DELETE handled by TestBridge
         }
     }
 
     @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);
-        Assert.assertEquals("There should only be one node in the topology", 1, topology.getNode().size());
-        InstanceIdentifier<Node> expectedNodeIid = SouthboundMapper.createInstanceIdentifier(connectionInfo);
-        Node node = topology.getNode().iterator().next();
+        InstanceIdentifier<Node> expectedNodeIid = SouthboundUtils.createInstanceIdentifier(connectionInfo);
         NodeId expectedNodeId = expectedNodeIid.firstKeyOf(Node.class, NodeKey.class).getNodeId();
-        Assert.assertEquals(expectedNodeId, node.getNodeId());
-        Assert.assertTrue(disconnectOvsdbNode(connectionInfo));
+        Node foundNode = null;
+        Assert.assertNotNull("Expected to find topology: " + topologyPath, topology);
+        Assert.assertNotNull("Expected to find some nodes" + topology.getNode());
+        LOG.info("expectedNodeId: {}, getNode: {}", expectedNodeId, topology.getNode());
+        for (Node node : topology.getNode()) {
+            if (node.getNodeId().getValue().equals(expectedNodeId.getValue())) {
+                foundNode = node;
+                break;
+            }
+        }
+        Assert.assertNotNull("Expected to find Node: " + expectedNodeId, foundNode);
     }
 
-    /**
-     * isBundleReady is used to check if the requested bundle is Active
+    /*
+     * @see <code>SouthboundIT.generateBridgeOtherConfigsTestCases()</code> for specific test case information.
      */
-    public void isBundleReady(BundleContext bundleContext, String bundleName) throws InterruptedException {
-        boolean ready = false;
-
-        while (!ready) {
-            int state = Bundle.UNINSTALLED;
-            Bundle[] bundles = bundleContext.getBundles();
-            for (Bundle element : bundles) {
-                if (element.getSymbolicName().equals(bundleName)) {
-                    state = element.getState();
-                    LOG.info(">>>>> bundle is ready {}", bundleName);
-                    break;
+    @Test
+    public void testCRUDBridgeOtherConfigs() throws InterruptedException {
+        testCRUDBridge("BridgeOtherConfigs", new SouthboundBridgeOtherConfigsBuilder(),
+                new BridgeOtherConfigsSouthboundHelper());
+    }
+
+    private interface SouthboundBridgeHelper<T> {
+        void writeValues(OvsdbBridgeAugmentationBuilder builder, List<T> values);
+        List<T> readValues(OvsdbBridgeAugmentation augmentation);
+    }
+
+    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<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);
+
+                // 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);
+
+                // 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);
+
+                // 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);
                 }
+
+                // DELETE
+                Assert.assertTrue(mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, bridgeIid));
+                Thread.sleep(OVSDB_UPDATE_TIMEOUT);
             }
-            if (state != Bundle.ACTIVE) {
-                LOG.info(">>>>> bundle not ready {}", bundleName);
-                Thread.sleep(5000);
-            } else {
-                ready = true;
+        }
+    }
+
+    /*
+     * @see <code>SouthboundIT.generateBridgeExternalIdsTestCases()</code> for specific test case information
+     */
+    @Test
+    public void testCRUDBridgeExternalIds() throws InterruptedException {
+        testCRUDBridge("BridgeExternalIds", new SouthboundBridgeExternalIdsBuilder(),
+                new BridgeExternalIdsSouthboundHelper());
+    }
+
+    @Test
+    public void testAddDeleteQos() throws InterruptedException {
+        ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
+        OvsdbNodeAugmentation ovsdbNodeAugmentation;
+        Uri qosUri = new Uri("QOS-ROW");
+        List<String> typeList = new ArrayList<String>();
+        typeList.add(SouthboundConstants.QOS_LINUX_HTB);
+        typeList.add(SouthboundConstants.QOS_LINUX_HFSC);
+
+        for (String qosType : typeList) {
+            try (TestQos testQos = new TestQos(connectionInfo, qosUri, SouthboundMapper.createQosType(qosType), null, null)) {
+                ovsdbNodeAugmentation = getOvsdbNode(connectionInfo,
+                        LogicalDatastoreType.OPERATIONAL);
+                QosEntries operQosHtb = getQos(qosUri, ovsdbNodeAugmentation);
+                Assert.assertNotNull(operQosHtb);
             }
+            ovsdbNodeAugmentation = getOvsdbNode(connectionInfo,
+                    LogicalDatastoreType.OPERATIONAL);
+            QosEntries operQosHtb = getQos(qosUri, ovsdbNodeAugmentation);
+            Assert.assertNull(operQosHtb);
+        }
+    }
+
+    @Test
+    public void testAddDeleteQueue() throws InterruptedException {
+        ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
+        Uri queueUri = new Uri("QUEUE-A1");
+
+        try (TestQueue testQueue = new TestQueue(connectionInfo, queueUri, new Short("25"), null, null)) {
+            OvsdbNodeAugmentation ovsdbNodeAugmentation = getOvsdbNode(connectionInfo,
+                    LogicalDatastoreType.OPERATIONAL);
+            Queues operQueue = getQueue(queueUri, ovsdbNodeAugmentation);
+            Assert.assertNotNull(operQueue);
+        }
+        OvsdbNodeAugmentation ovsdbNodeAugmentation = getOvsdbNode(connectionInfo,
+                LogicalDatastoreType.OPERATIONAL);
+        Queues operQueue = getQueue(queueUri, ovsdbNodeAugmentation);
+        Assert.assertNull(operQueue);
+    }
+
+    private static class SouthboundQueuesExternalIdsHelper implements SouthboundQueueHelper<QueuesExternalIds> {
+        @Override
+        public void writeValues(QueuesBuilder builder, List<QueuesExternalIds> values) {
+            builder.setQueuesExternalIds(values);
+        }
+
+        @Override
+        public List<QueuesExternalIds> readValues(Queues queue) {
+            return queue.getQueuesExternalIds();
+        }
+    }
+
+    private static class SouthboundQueuesOtherConfigHelper implements SouthboundQueueHelper<QueuesOtherConfig> {
+        @Override
+        public void writeValues(QueuesBuilder builder, List<QueuesOtherConfig> values) {
+            builder.setQueuesOtherConfig(values);
+        }
+
+        @Override
+        public List<QueuesOtherConfig> readValues(Queues queue) {
+            return queue.getQueuesOtherConfig();
+        }
+    }
+
+    private interface SouthboundQueueHelper<T> {
+        void writeValues(QueuesBuilder builder, List<T> values);
+        List<T> readValues(Queues queue);
+    }
+
+    private Queues getQueue(Uri queueId, OvsdbNodeAugmentation node) {
+        for (Queues queue : node.getQueues()) {
+            if (queue.getKey().getQueueId().getValue().equals(queueId.getValue()))
+                return queue;
+        }
+        return null;
+    }
+
+    private static class SouthboundQosExternalIdsHelper implements SouthboundQosHelper<QosExternalIds> {
+        @Override
+        public void writeValues(QosEntriesBuilder builder, List<QosExternalIds> values) {
+            builder.setQosExternalIds(values);
+        }
+
+        @Override
+        public List<QosExternalIds> readValues(QosEntries qos) {
+            return qos.getQosExternalIds();
+        }
+    }
+
+    private static class SouthboundQosOtherConfigHelper implements SouthboundQosHelper<QosOtherConfig> {
+        @Override
+        public void writeValues(QosEntriesBuilder builder, List<QosOtherConfig> values) {
+            builder.setQosOtherConfig(values);
+        }
+
+        @Override
+        public List<QosOtherConfig> readValues(QosEntries qos) {
+            return qos.getQosOtherConfig();
+        }
+    }
+
+    private interface SouthboundQosHelper<T> {
+        void writeValues(QosEntriesBuilder builder, List<T> values);
+        List<T> readValues(QosEntries qos);
+    }
+
+    private QosEntries getQos(Uri qosId, OvsdbNodeAugmentation node) {
+        for (QosEntries qos : node.getQosEntries()) {
+            if (qos.getKey().getQosId().equals(qosId))
+                return qos;
+        }
+        return null;
+    }
+
+    private <T> void testCRUDQueue(
+            KeyValueBuilder<T> builder, String prefix, SouthboundQueueHelper<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<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 testQueueId = String.format("%s_%s", prefix, updateToTestCase.name);
+
+                // CREATE: and update the test queue with starting values.
+                try (TestQueue testQueue = new TestQueue(connectionInfo, new Uri(testQueueId), new Short("45"), null, null)) {
+                    QueuesBuilder queuesBuilder = new QueuesBuilder();
+                    queuesBuilder.setQueueId(new Uri(testQueueId));
+                    InstanceIdentifier<Queues> queueIid = SouthboundUtils.createInstanceIdentifier(connectionInfo)
+                            .augmentation(OvsdbNodeAugmentation.class)
+                            .child(Queues.class, queuesBuilder.build().getKey());
+                    final NotifyingDataChangeListener queueConfigurationListener =
+                            new NotifyingDataChangeListener(LogicalDatastoreType.CONFIGURATION, queueIid);
+                    queueConfigurationListener.registerDataChangeListener();
+                    final NotifyingDataChangeListener queueOperationalListener =
+                            new NotifyingDataChangeListener(LogicalDatastoreType.OPERATIONAL, queueIid);
+                    queueOperationalListener.registerDataChangeListener();
+
+                    helper.writeValues(queuesBuilder, updateFromTestCase.inputValues);
+                    Assert.assertTrue(mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION,
+                            queueIid, queuesBuilder.build()));
+                    queueConfigurationListener.waitForUpdate(OVSDB_UPDATE_TIMEOUT);
+
+                    // READ: Read the test queue and ensure changes are propagated to the CONFIGURATION data store,
+                    // then repeat for OPERATIONAL data store
+                    OvsdbNodeAugmentation updateFromConfigurationOvsdbNodeAugmentation = getOvsdbNode(connectionInfo,
+                            LogicalDatastoreType.CONFIGURATION);
+                    Queues queueFromConfig = getQueue(new Uri(testQueueId), updateFromConfigurationOvsdbNodeAugmentation);
+                    if (queueFromConfig != null) {
+                        List<T> updateFromConfigurationValues =
+                                helper.readValues(queueFromConfig);
+                        assertExpectedExist(updateFromTestCase.expectedValues, updateFromConfigurationValues);
+                    }
+
+                    queueOperationalListener.waitForUpdate(OVSDB_UPDATE_TIMEOUT);
+                    OvsdbNodeAugmentation updateFromOperationalOvsdbNodeAugmentation = getOvsdbNode(connectionInfo,
+                            LogicalDatastoreType.OPERATIONAL);
+                    Queues queueFromOper = getQueue(new Uri(testQueueId), updateFromOperationalOvsdbNodeAugmentation);
+                    if (queueFromOper != null) {
+                        List<T> updateFromOperationalValues =
+                                helper.readValues(queueFromOper);
+                        assertExpectedExist(updateFromTestCase.expectedValues, updateFromOperationalValues);
+                    }
+
+                    // UPDATE:  update the values
+                    QueuesBuilder queuesUpdateBuilder = new QueuesBuilder();
+                    queuesUpdateBuilder.setQueueId(new Uri(testQueueId));
+                    helper.writeValues(queuesUpdateBuilder, updateToTestCase.inputValues);
+                    Assert.assertTrue(mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION,
+                            queueIid, queuesUpdateBuilder.build()));
+                    queueConfigurationListener.waitForUpdate(OVSDB_UPDATE_TIMEOUT);
+
+                    // READ: the test queue and ensure changes are propagated to the CONFIGURATION data store,
+                    // then repeat for OPERATIONAL data store
+                    OvsdbNodeAugmentation updateToConfigurationOvsdbNodeAugmentation = getOvsdbNode(connectionInfo,
+                            LogicalDatastoreType.CONFIGURATION);
+                    Queues queueToConfig = getQueue(new Uri(testQueueId), updateToConfigurationOvsdbNodeAugmentation);
+                    if (queueToConfig != null) {
+                        List<T> updateToConfigurationValues =
+                                helper.readValues(queueToConfig);
+                        assertExpectedExist(updateToTestCase.expectedValues, updateToConfigurationValues);
+                    }
+
+                    queueOperationalListener.waitForUpdate(OVSDB_UPDATE_TIMEOUT);
+                    OvsdbNodeAugmentation updateToOperationalOvsdbNodeAugmentation = getOvsdbNode(connectionInfo,
+                            LogicalDatastoreType.OPERATIONAL);
+                    Queues queueToOper = getQueue(new Uri(testQueueId), updateToOperationalOvsdbNodeAugmentation);
+                    if (queueToOper != null) {
+                        List<T> updateToOperationalValues =
+                                helper.readValues(queueToOper);
+                        assertExpectedExist(updateToTestCase.expectedValues, updateToOperationalValues);
+                    }
+
+                    // DELETE handled by TestQueue
+                }
+            }
+        }
+    }
+
+    @Test
+    public void testCRUDQueueExternalIds() throws InterruptedException {
+        testCRUDQueue(new SouthboundQueuesExternalIdsBuilder(), "QueueExternalIds",
+                new SouthboundQueuesExternalIdsHelper());
+    }
+
+    @Test
+    public void testCRUDQueueOtherConfig() throws InterruptedException {
+        testCRUDQueue(new SouthboundQueuesOtherConfigBuilder(), "QueueOtherConfig",
+                new SouthboundQueuesOtherConfigHelper());
+    }
+
+    @Test
+    public void testCRUDQueueDscp() throws InterruptedException {
+        ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
+        String testQueueId = "testQueueDscp";
+
+        // CREATE: and update the test queue with starting values.
+        try (TestQueue testQueue = new TestQueue(connectionInfo, new Uri(testQueueId), new Short("0"), null, null)) {
+            for (Short dscp = 1; dscp < 64; dscp++) {
+                QueuesBuilder queuesBuilder = new QueuesBuilder();
+                queuesBuilder.setQueueId(new Uri(testQueueId));
+                InstanceIdentifier<Queues> queueIid = SouthboundUtils.createInstanceIdentifier(connectionInfo)
+                        .augmentation(OvsdbNodeAugmentation.class)
+                        .child(Queues.class, queuesBuilder.build().getKey());
+                final NotifyingDataChangeListener queueOperationalListener =
+                        new NotifyingDataChangeListener(LogicalDatastoreType.OPERATIONAL, queueIid);
+                queueOperationalListener.registerDataChangeListener();
+
+                queuesBuilder.setDscp(dscp);
+                Assert.assertTrue(mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION,
+                        queueIid, queuesBuilder.build()));
+                queueOperationalListener.waitForUpdate(OVSDB_ROUNDTRIP_TIMEOUT);
+
+                // READ: Read the test queue and ensure changes are propagated to the OPERATIONAL data store
+                // assumption is that CONFIGURATION was updated if OPERATIONAL is correct
+                OvsdbNodeAugmentation ovsdbNodeAugmentation = getOvsdbNode(connectionInfo,
+                        LogicalDatastoreType.OPERATIONAL);
+                Queues operQueue = getQueue(new Uri(testQueueId), ovsdbNodeAugmentation);
+                Assert.assertNotNull(operQueue);
+                Short operDscp = operQueue.getDscp();
+                Assert.assertNotNull(operDscp);
+                Assert.assertEquals(dscp, operDscp);
+            }
+
+            // DELETE handled by TestQueue
+        }
+
+    }
+
+    private <T> void testCRUDQos(
+            KeyValueBuilder<T> builder, String prefix, SouthboundQosHelper<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<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 testQosId = String.format("%s_%s", prefix, updateToTestCase.name);
+
+                // CREATE: and update the test qos with starting values.
+                try (TestQos testQos = new TestQos(connectionInfo, new Uri(testQosId), SouthboundMapper.createQosType(SouthboundConstants.QOS_LINUX_HTB), null, null)) {
+                    QosEntriesBuilder qosBuilder = new QosEntriesBuilder();
+                    qosBuilder.setQosId(new Uri(testQosId));
+                    InstanceIdentifier<QosEntries> qosIid = SouthboundUtils.createInstanceIdentifier(connectionInfo)
+                            .augmentation(OvsdbNodeAugmentation.class)
+                            .child(QosEntries.class, qosBuilder.build().getKey());
+                    final NotifyingDataChangeListener qosConfigurationListener =
+                            new NotifyingDataChangeListener(LogicalDatastoreType.CONFIGURATION, qosIid);
+                    qosConfigurationListener.registerDataChangeListener();
+                    final NotifyingDataChangeListener qosOperationalListener =
+                            new NotifyingDataChangeListener(LogicalDatastoreType.OPERATIONAL, qosIid);
+                    qosOperationalListener.registerDataChangeListener();
+
+                    helper.writeValues(qosBuilder, updateFromTestCase.inputValues);
+                    Assert.assertTrue(mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION,
+                            qosIid, qosBuilder.build()));
+                    qosConfigurationListener.waitForUpdate(OVSDB_UPDATE_TIMEOUT);
+
+                    // READ: Read the test queue and ensure changes are propagated to the CONFIGURATION data store,
+                    // then repeat for OPERATIONAL data store
+                    OvsdbNodeAugmentation updateFromConfigurationOvsdbNodeAugmentation = getOvsdbNode(connectionInfo,
+                            LogicalDatastoreType.CONFIGURATION);
+                    QosEntries qosFromConfig = getQos(new Uri(testQosId), updateFromConfigurationOvsdbNodeAugmentation);
+                    if (qosFromConfig != null) {
+                        List<T> updateFromConfigurationValues =
+                                helper.readValues(qosFromConfig);
+                        assertExpectedExist(updateFromTestCase.expectedValues, updateFromConfigurationValues);
+                    }
+
+                    qosOperationalListener.waitForUpdate(OVSDB_UPDATE_TIMEOUT);
+                    OvsdbNodeAugmentation updateFromOperationalOvsdbNodeAugmentation = getOvsdbNode(connectionInfo,
+                            LogicalDatastoreType.OPERATIONAL);
+                    QosEntries qosFromOper = getQos(new Uri(testQosId), updateFromOperationalOvsdbNodeAugmentation);
+                    if (qosFromOper != null) {
+                        List<T> updateFromOperationalValues =
+                                helper.readValues(qosFromOper);
+                        assertExpectedExist(updateFromTestCase.expectedValues, updateFromOperationalValues);
+                    }
+
+                    // UPDATE:  update the values
+                    QosEntriesBuilder qosUpdateBuilder = new QosEntriesBuilder();
+                    qosUpdateBuilder.setQosId(new Uri(testQosId));
+                    helper.writeValues(qosUpdateBuilder, updateToTestCase.inputValues);
+                    Assert.assertTrue(mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION,
+                            qosIid, qosUpdateBuilder.build()));
+                    qosConfigurationListener.waitForUpdate(OVSDB_UPDATE_TIMEOUT);
+
+                    // READ: the test queue and ensure changes are propagated to the CONFIGURATION data store,
+                    // then repeat for OPERATIONAL data store
+                    OvsdbNodeAugmentation updateToConfigurationOvsdbNodeAugmentation = getOvsdbNode(connectionInfo,
+                            LogicalDatastoreType.CONFIGURATION);
+                    QosEntries qosToConfig = getQos(new Uri(testQosId), updateToConfigurationOvsdbNodeAugmentation);
+                    if (qosToConfig != null) {
+                        List<T> updateToConfigurationValues =
+                                helper.readValues(qosToConfig);
+                        assertExpectedExist(updateToTestCase.expectedValues, updateToConfigurationValues);
+                    }
+
+                    qosOperationalListener.waitForUpdate(OVSDB_UPDATE_TIMEOUT);
+                    OvsdbNodeAugmentation updateToOperationalOvsdbNodeAugmentation = getOvsdbNode(connectionInfo,
+                            LogicalDatastoreType.OPERATIONAL);
+                    QosEntries qosToOper = getQos(new Uri(testQosId), updateToOperationalOvsdbNodeAugmentation);
+                    if (qosToOper != null) {
+                        List<T> updateToOperationalValues =
+                                helper.readValues(qosToOper);
+                        assertExpectedExist(updateToTestCase.expectedValues, updateToOperationalValues);
+                    }
+
+                    // DELETE handled by TestQueue
+                }
+            }
+        }
+    }
+
+    @Test
+    public void testCRUDQosExternalIds() throws InterruptedException {
+        testCRUDQos(new SouthboundQosExternalIdsBuilder(), "QosExternalIds",
+                new SouthboundQosExternalIdsHelper());
+    }
+
+    @Test
+    public void testCRUDQosOtherConfig() throws InterruptedException {
+        testCRUDQos(new SouthboundQosOtherConfigBuilder(), "QosOtherConfig",
+                new SouthboundQosOtherConfigHelper());
+    }
+    @Test
+    public void testCRUDQosQueues() throws InterruptedException {
+        ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
+        String testQosId = "testQosQueues";
+
+        // CREATE: and update the test queue with starting values.
+        try (TestQos testQos = new TestQos(connectionInfo, new Uri(testQosId),
+                SouthboundMapper.createQosType(SouthboundConstants.QOS_LINUX_HTB), null, null);
+                TestQueue testQueue1 = new TestQueue(connectionInfo, new Uri("queue1"), new Short("12"), null, null);
+                TestQueue testQueue2 = new TestQueue(connectionInfo, new Uri("queue2"), new Short("35"), null, null)) {
+            QosEntriesBuilder qosBuilder = new QosEntriesBuilder();
+            qosBuilder.setQosId(new Uri(testQosId));
+            InstanceIdentifier<QosEntries> qosIid = SouthboundUtils.createInstanceIdentifier(connectionInfo)
+                    .augmentation(OvsdbNodeAugmentation.class)
+                    .child(QosEntries.class, qosBuilder.build().getKey());
+            final NotifyingDataChangeListener qosOperationalListener =
+                    new NotifyingDataChangeListener(LogicalDatastoreType.OPERATIONAL, qosIid);
+            qosOperationalListener.registerDataChangeListener();
+
+            // READ, UPDATE:  Read the UUIDs of the Queue rows and add them to the
+            // configuration of the Qos row.
+            OvsdbNodeAugmentation ovsdbNodeAugmentation = getOvsdbNode(connectionInfo,
+                    LogicalDatastoreType.OPERATIONAL);
+            Queues operQueue1 = getQueue(new Uri("queue1"), ovsdbNodeAugmentation);
+            Assert.assertNotNull(operQueue1);
+            Uuid queue1Uuid = new Uuid(operQueue1.getQueueUuid().getValue());
+            Queues operQueue2 = getQueue(new Uri("queue2"), ovsdbNodeAugmentation);
+            Assert.assertNotNull(operQueue2);
+            Uuid queue2Uuid = new Uuid(operQueue2.getQueueUuid().getValue());
+
+            List<QueueList> queueList = new ArrayList<>();
+            queueList.add(new QueueListBuilder().setQueueNumber(new Long("0"))
+                    .setQueueUuid(queue1Uuid).build());
+            queueList.add(new QueueListBuilder().setQueueNumber(new Long("1"))
+                    .setQueueUuid(queue2Uuid).build());
+            qosBuilder.setQueueList(queueList);
+
+            Assert.assertTrue(mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION,
+                    qosIid, qosBuilder.build()));
+            qosOperationalListener.waitForUpdate(OVSDB_UPDATE_TIMEOUT);
+
+            // READ: Read the test qos and ensure changes are propagated to the OPERATIONAL data store
+            // assumption is that CONFIGURATION was updated if OPERATIONAL is correct
+            ovsdbNodeAugmentation = getOvsdbNode(connectionInfo,
+                    LogicalDatastoreType.OPERATIONAL);
+            QosEntries operQos = getQos(new Uri(testQosId), ovsdbNodeAugmentation);
+            Assert.assertNotNull(operQos);
+            List<QueueList> operQueueList = operQos.getQueueList();
+            Assert.assertNotNull(operQueueList);
+            for (QueueList queueEntry : queueList) {
+                Assert.assertTrue(isQueueInList(operQueueList, queueEntry));
+            }
+
+            // DELETE one queue from queue list and check that one remains
+            KeyedInstanceIdentifier<QueueList, QueueListKey> qosQueueIid = qosIid
+                        .child(QueueList.class, new QueueListKey(new Long("0")));
+            Assert.assertTrue(mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, qosQueueIid));
+            qosOperationalListener.waitForUpdate(OVSDB_UPDATE_TIMEOUT);
+
+            // READ: Read the test qos and ensure changes are propagated to the OPERATIONAL data store
+            // assumption is that CONFIGURATION was updated if OPERATIONAL is correct
+            ovsdbNodeAugmentation = getOvsdbNode(connectionInfo,
+                    LogicalDatastoreType.OPERATIONAL);
+            operQos = getQos(new Uri(testQosId), ovsdbNodeAugmentation);
+            Assert.assertNotNull(operQos);
+            operQueueList = operQos.getQueueList();
+            Assert.assertNotNull(operQueueList);
+            for (QueueList queueEntry : queueList) {
+                if (queueEntry.getQueueUuid().equals(queue2Uuid)) {
+                    Assert.assertTrue(isQueueInList(operQueueList, queueEntry));
+                } else if (queueEntry.getQueueUuid().equals(queue1Uuid)) {
+                    Assert.assertFalse(isQueueInList(operQueueList, queueEntry));
+                } else {
+                    Assert.assertTrue("Unknown queue entry in qos queue list", false);
+                }
+            }
+
+            // DELETE  queue list and check that list is empty
+            qosQueueIid = qosIid
+                    .child(QueueList.class, new QueueListKey(new Long("1")));
+            Assert.assertTrue(mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, qosQueueIid));
+            qosOperationalListener.waitForUpdate(OVSDB_UPDATE_TIMEOUT);
+
+            ovsdbNodeAugmentation = getOvsdbNode(connectionInfo,
+                    LogicalDatastoreType.OPERATIONAL);
+            operQos = getQos(new Uri(testQosId), ovsdbNodeAugmentation);
+            Assert.assertNotNull(operQos);
+            operQueueList = operQos.getQueueList();
+            Assert.assertNotNull(operQueueList);
+            Assert.assertTrue(operQueueList.isEmpty());
+        }
+    }
+
+    private Boolean isQueueInList(List<QueueList> queueList, QueueList queue) {
+        for (QueueList queueEntry : queueList) {
+            if (queueEntry.getQueueNumber().equals(queue.getQueueNumber())
+                && queueEntry.getQueueUuid().equals(queue.getQueueUuid())) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * <p>
+     * Representation of a southbound test case. Each test case has a name, a list of input values and a list of
+     * expected values. The input values are provided to the augmentation builder, and the expected values are checked
+     * against the output of the resulting augmentation.
+     * </p>
+     * <p>
+     * Instances of this class are immutable.
+     * </p>
+     *
+     * @param <T> The type of data used for the test case.
+     */
+    private static final class SouthboundTestCase<T> {
+        private final String name;
+        private final List<T> inputValues;
+        private final List<T> expectedValues;
+
+        /**
+         * Creates an instance of a southbound test case.
+         *
+         * @param name The test case's name.
+         * @param inputValues The input values (provided as input to the underlying augmentation builder).
+         * @param expectedValues The expected values (checked against the output of the underlying augmentation).
+         */
+        public SouthboundTestCase(
+                final String name, final List<T> inputValues, final List<T> expectedValues) {
+            this.name = name;
+            this.inputValues = inputValues;
+            this.expectedValues = expectedValues;
+        }
+    }
+
+    /**
+     * Southbound test case builder.
+     *
+     * @param <T> The type of data used for the test case.
+     */
+    private static final class SouthboundTestCaseBuilder<T> {
+        private String name;
+        private List<T> inputValues;
+        private List<T> expectedValues;
+
+        /**
+         * Creates a builder. Builders may be reused, the generated immutable instances are independent of the
+         * builders. There are no default values.
+         */
+        public SouthboundTestCaseBuilder() {
+            // Nothing to do
+        }
+
+        /**
+         * Sets the test case's name.
+         *
+         * @param name The test case's name.
+         * @return The builder.
+         */
+        public SouthboundTestCaseBuilder<T> name(final String name) {
+            this.name = name;
+            return this;
+        }
+
+        /**
+         * Sets the input values.
+         *
+         * @param inputValues The input values.
+         * @return The builder.
+         */
+        @SafeVarargs
+        public final SouthboundTestCaseBuilder<T> input(final T... inputValues) {
+            this.inputValues = Lists.newArrayList(inputValues);
+            return this;
+        }
+
+        /**
+         * Indicates that the provided input values should be expected as output values.
+         *
+         * @return The builder.
+         */
+        public SouthboundTestCaseBuilder<T> expectInputAsOutput() {
+            this.expectedValues = this.inputValues;
+            return this;
+        }
+
+        /**
+         * Indicates that no output should be expected.
+         *
+         * @return The builder.
+         */
+        public SouthboundTestCaseBuilder<T> expectNoOutput() {
+            this.expectedValues = null;
+            return this;
+        }
+
+        /**
+         * Builds an immutable instance representing the test case.
+         *
+         * @return The test case.
+         */
+        @SuppressWarnings("unchecked")
+        public SouthboundTestCase<T> build() {
+            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);
+
+        protected abstract boolean isValueMandatory();
+
+        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 SouthboundQueuesExternalIdsBuilder extends KeyValueBuilder<QueuesExternalIds> {
+        @Override
+        protected Builder<QueuesExternalIds> builder() {
+            return new QueuesExternalIdsBuilder();
+        }
+
+        @Override
+        protected void setKey(Builder<QueuesExternalIds> builder, String key) {
+            ((QueuesExternalIdsBuilder) builder).setQueuesExternalIdKey(key);
+        }
+
+        @Override
+        protected void setValue(Builder<QueuesExternalIds> builder, String value) {
+            ((QueuesExternalIdsBuilder) builder).setQueuesExternalIdValue(value);
+        }
+
+        @Override
+        protected boolean isValueMandatory() {
+            return true;
+        }
+    }
+
+    private static final class SouthboundQueuesOtherConfigBuilder extends KeyValueBuilder<QueuesOtherConfig> {
+        @Override
+        protected Builder<QueuesOtherConfig> builder() {
+            return new QueuesOtherConfigBuilder();
+        }
+
+        @Override
+        protected void setKey(Builder<QueuesOtherConfig> builder, String key) {
+            ((QueuesOtherConfigBuilder) builder).setQueueOtherConfigKey(key);
+        }
+
+        @Override
+        protected void setValue(Builder<QueuesOtherConfig> builder, String value) {
+            ((QueuesOtherConfigBuilder) builder).setQueueOtherConfigValue(value);
+        }
+
+        @Override
+        protected boolean isValueMandatory() {
+            return false;
+        }
+    }
+
+    private static final class SouthboundQosExternalIdsBuilder extends KeyValueBuilder<QosExternalIds> {
+        @Override
+        protected Builder<QosExternalIds> builder() {
+            return new QosExternalIdsBuilder();
+        }
+
+        @Override
+        protected void setKey(Builder<QosExternalIds> builder, String key) {
+            ((QosExternalIdsBuilder) builder).setQosExternalIdKey(key);
+        }
+
+        @Override
+        protected void setValue(Builder<QosExternalIds> builder, String value) {
+            ((QosExternalIdsBuilder) builder).setQosExternalIdValue(value);
+        }
+
+        @Override
+        protected boolean isValueMandatory() {
+            return true;
+        }
+    }
+
+    private static final class SouthboundQosOtherConfigBuilder extends KeyValueBuilder<QosOtherConfig> {
+        @Override
+        protected Builder<QosOtherConfig> builder() {
+            return new QosOtherConfigBuilder();
+        }
+
+        @Override
+        protected void setKey(Builder<QosOtherConfig> builder, String key) {
+            ((QosOtherConfigBuilder) builder).setOtherConfigKey(key);
+        }
+
+        @Override
+        protected void setValue(Builder<QosOtherConfig> builder, String value) {
+            ((QosOtherConfigBuilder) builder).setOtherConfigValue(value);
+        }
+
+        @Override
+        protected boolean isValueMandatory() {
+            return false;
+        }
+    }
+
+    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);
+        }
+
+        @Override
+        protected boolean isValueMandatory() {
+            return true;
+        }
+    }
+
+    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);
+        }
+
+        @Override
+        protected boolean isValueMandatory() {
+            return true;
+        }
+    }
+
+    private static final class SouthboundInterfaceLldpBuilder extends KeyValueBuilder<InterfaceLldp> {
+        @Override
+        protected Builder<InterfaceLldp> builder() {
+            return new InterfaceLldpBuilder();
+        }
+
+        @Override
+        protected void setKey(Builder<InterfaceLldp> builder, String key) {
+            ((InterfaceLldpBuilder) builder).setLldpKey((key));
+        }
+
+        @Override
+        protected void setValue(Builder<InterfaceLldp> builder, String value) {
+            ((InterfaceLldpBuilder) builder).setLldpValue(value);
+        }
+
+        @Override
+        protected boolean isValueMandatory() {
+            return true;
+        }
+    }
+
+    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);
+        }
+
+        @Override
+        protected boolean isValueMandatory() {
+            return false;
+        }
+    }
+
+    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);
+        }
+
+        @Override
+        protected boolean isValueMandatory() {
+            return false;
+        }
+    }
+
+    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);
+        }
+
+        @Override
+        protected boolean isValueMandatory() {
+            return false;
+        }
+    }
+
+    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);
+        }
+
+        @Override
+        protected boolean isValueMandatory() {
+            return false;
+        }
+    }
+
+    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);
+        }
+
+        @Override
+        protected boolean isValueMandatory() {
+            return true;
+        }
+    }
+
+    /*
+     * 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());
+        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" + testName;
+        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());
+        builder.reset();
+
+        if (!builder.isValueMandatory()) {
+            // 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;
+            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();
+        } else {
+            LOG.info("generateKeyValueTestCases: skipping test case 3 for {}", builder.getClass().getSimpleName());
+        }
+
+        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 InterfaceLldpSouthboundHelper implements
+    SouthboundTerminationPointHelper<InterfaceLldp> {
+        @Override
+        public void writeValues(
+                OvsdbTerminationPointAugmentationBuilder builder, List<InterfaceLldp> values) {
+            builder.setInterfaceLldp(values);
+        }
+
+        @Override
+        public List<InterfaceLldp> readValues(OvsdbTerminationPointAugmentation augmentation) {
+            return augmentation.getInterfaceLldp();
+        }
+    }
+
+    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();
         }
     }
-}
\ No newline at end of file
+}