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 425ba4c9da7820166853926fd5941225a24d143c..6817bfa1850b8b5a615816fdd105922c7f495e98 100644 (file)
@@ -11,14 +11,11 @@ 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.keepRuntimeFolder;
 
-import com.google.common.collect.ImmutableBiMap;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
-
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Method;
 import java.net.InetAddress;
@@ -35,9 +32,11 @@ 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;
@@ -45,15 +44,19 @@ 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.ovsdb.southbound.SouthboundUtil;
 import org.opendaylight.ovsdb.utils.mdsal.utils.MdsalUtils;
 import org.opendaylight.ovsdb.utils.southbound.utils.SouthboundUtils;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
+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;
@@ -67,6 +70,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.re
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.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;
@@ -75,14 +79,40 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.re
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.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;
@@ -107,6 +137,7 @@ import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.
 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;
@@ -118,6 +149,11 @@ 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
  *
@@ -131,6 +167,8 @@ public class SouthboundIT extends AbstractMdsalTestBase {
     private static final int OVSDB_UPDATE_TIMEOUT = 1000;
     private static final int OVSDB_ROUNDTRIP_TIMEOUT = 10000;
     private static final String FORMAT_STR = "%s_%s_%d";
+    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 int portNumber;
     private static String connectionType;
@@ -138,6 +176,10 @@ public class SouthboundIT extends AbstractMdsalTestBase {
     private static MdsalUtils mdsalUtils = null;
     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;
@@ -152,9 +194,17 @@ public class SouthboundIT extends AbstractMdsalTestBase {
         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
@@ -190,6 +240,50 @@ public class SouthboundIT extends AbstractMdsalTestBase {
         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
@@ -222,16 +316,6 @@ public class SouthboundIT extends AbstractMdsalTestBase {
                 .getURL();
     }
 
-    @Override
-    public String getModuleName() {
-        return "southbound-impl";
-    }
-
-    @Override
-    public String getInstanceName() {
-        return "southbound-default";
-    }
-
     @Override
     public MavenUrlReference getFeatureRepo() {
         return maven()
@@ -275,6 +359,10 @@ public class SouthboundIT extends AbstractMdsalTestBase {
                 connectionType, addressStr, portStr);
 
         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,
@@ -295,11 +383,11 @@ public class SouthboundIT extends AbstractMdsalTestBase {
         try {
             super.setup();
         } catch (Exception e) {
-            e.printStackTrace();
+            LOG.warn("Failed to setup test", e);
         }
         //dataBroker = getSession().getSALService(DataBroker.class);
         Thread.sleep(3000);
-        DataBroker dataBroker = SouthboundProvider.getDb();
+        dataBroker = SouthboundProvider.getDb();
         Assert.assertNotNull("db should not be null", dataBroker);
 
         addressStr = bundleContext.getProperty(SouthboundITConstants.SERVER_IPADDRESS);
@@ -328,6 +416,17 @@ public class SouthboundIT extends AbstractMdsalTestBase {
                 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)
@@ -763,6 +862,314 @@ public class SouthboundIT extends AbstractMdsalTestBase {
         }
     }
 
+    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 testCRUDAutoAttach() throws InterruptedException {
+        final boolean isOldSchema = schemaVersion.compareTo(AUTOATTACH_FROM_VERSION) < 0;
+
+        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");
+
+        try (TestBridge testBridge = new TestBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME)) {
+            OvsdbBridgeAugmentation bridge = getBridge(connectionInfo);
+            Assert.assertNotNull(bridge);
+
+            // 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());
+                }
+
+                // 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);
+            }
+        }
+    }
+
+    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;
+                }
+            }
+        }
+        return null;
+    }
+
+    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);
+            }
+
+        }
+
+        @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);
+            }
+        }
+    }
+
+    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);
+            }
+        }
+
+        @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);
+            }
+        }
+    }
+
+    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;
+    }
+
     private OvsdbBridgeAugmentation getBridge(ConnectionInfo connectionInfo) {
         return getBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME);
     }
@@ -860,6 +1267,45 @@ public class SouthboundIT extends AbstractMdsalTestBase {
         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)) {
+                    Long ifIndex = ovsdbTerminationPointAugmentation.getIfindex();
+                    Assert.assertNotNull(ifIndex);
+                    LOG.info("ifIndex: {} for the port:{}", ifIndex, portName);
+                }
+            }
+        }
+    }
+
     @Test
     public void testCRDTerminationPointOfPort() throws InterruptedException {
         final Long OFPORT_EXPECTED = 45002L;
@@ -1092,6 +1538,17 @@ public class SouthboundIT extends AbstractMdsalTestBase {
                 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>.
      *
@@ -1124,6 +1581,89 @@ public class SouthboundIT extends AbstractMdsalTestBase {
                 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;
@@ -1361,6 +1901,69 @@ public class SouthboundIT extends AbstractMdsalTestBase {
         }
     }
 
+    /*
+     * 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, portNumber);
@@ -1480,6 +2083,464 @@ public class SouthboundIT extends AbstractMdsalTestBase {
                 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
@@ -1594,6 +2655,8 @@ public class SouthboundIT extends AbstractMdsalTestBase {
 
         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++;
@@ -1611,6 +2674,94 @@ public class SouthboundIT extends AbstractMdsalTestBase {
         }
     }
 
+    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() {
@@ -1626,6 +2777,11 @@ public class SouthboundIT extends AbstractMdsalTestBase {
         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> {
@@ -1643,6 +2799,33 @@ public class SouthboundIT extends AbstractMdsalTestBase {
         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> {
@@ -1660,6 +2843,11 @@ public class SouthboundIT extends AbstractMdsalTestBase {
         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> {
@@ -1677,6 +2865,11 @@ public class SouthboundIT extends AbstractMdsalTestBase {
         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> {
@@ -1694,6 +2887,11 @@ public class SouthboundIT extends AbstractMdsalTestBase {
         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> {
@@ -1711,6 +2909,11 @@ public class SouthboundIT extends AbstractMdsalTestBase {
         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> {
@@ -1728,6 +2931,11 @@ public class SouthboundIT extends AbstractMdsalTestBase {
         protected void setValue(Builder<BridgeExternalIds> builder, String value) {
             ((BridgeExternalIdsBuilder) builder).setBridgeExternalIdValue(value);
         }
+
+        @Override
+        protected boolean isValueMandatory() {
+            return true;
+        }
     }
 
     /*
@@ -1755,13 +2963,13 @@ public class SouthboundIT extends AbstractMdsalTestBase {
                 .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;
-        builder.reset();
         testCases.add(new SouthboundTestCaseBuilder<T>()
                 .name(testFiveName)
                 .input(
@@ -1772,37 +2980,32 @@ public class SouthboundIT extends AbstractMdsalTestBase {
                         builder.build(testFiveName, idKey, idValue))
                 .expectInputAsOutput()
                 .build());
+        builder.reset();
 
-        if ((builder instanceof SouthboundBridgeExternalIdsBuilder) ||
-                (builder instanceof SouthboundInterfaceExternalIdsBuilder) ||
-                (builder instanceof SouthboundPortExternalIdsBuilder)) {
-            LOG.info("generateKeyValueTestCases: instance skipping test case 3 TestOneGoodOneMalformedValue");
+        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();
-
-            return testCases;
+        } else {
+            LOG.info("generateKeyValueTestCases: skipping test case 3 for {}", builder.getClass().getSimpleName());
         }
 
-        // Test Case 3:  TestOneGoodOneMalformedValue
-        // Test Type:    Negative
-        // Description:
-        //     One perfectly fine input
-        //        (TestOneGoodOneMalformedValue_GoodKey_1,
-        //        TestOneGoodOneMalformedValue_GoodValue_1)
-        //     and one malformed input which only has key specified
-        //        (TestOneGoodOneMalformedValue_NoValueForKey_2,
-        //        UNSPECIFIED)
-        // Expected:     A port is created without any values
-        final String testOneGoodOneMalformedValueName = "TestOneGoodOneMalformedValue" + testName;
-        builder.reset();
-        testCases.add(new SouthboundTestCaseBuilder<T>()
-                .name(testOneGoodOneMalformedValueName)
-                .input(
-                        builder.build(testOneGoodOneMalformedValueName, GOOD_KEY, GOOD_VALUE),
-                        builder.build(testOneGoodOneMalformedValueName, NO_VALUE_FOR_KEY, null))
-                .expectNoOutput()
-                .build());
-        builder.reset();
-
         return testCases;
     }
 
@@ -1832,6 +3035,20 @@ public class SouthboundIT extends AbstractMdsalTestBase {
         }
     }
 
+    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(