genius/interfacemanager annotation based bp
[genius.git] / interfacemanager / interfacemanager-impl / src / main / java / org / opendaylight / genius / interfacemanager / renderer / ovs / utilities / SouthboundUtils.java
index faed3650392a6a9a9267d3efa56e07c2c98a8a25..3f48b7ce4130351c921a3ca439777d87c1a1d5ae 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
+ * Copyright (c) 2016, 2017 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
@@ -7,21 +7,36 @@
  */
 package org.opendaylight.genius.interfacemanager.renderer.ovs.utilities;
 
+import static org.opendaylight.controller.md.sal.binding.api.WriteTransaction.CREATE_MISSING_PARENTS;
+
 import com.google.common.collect.Maps;
-import com.google.common.util.concurrent.ListenableFuture;
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 import java.math.BigInteger;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
+import java.util.Locale;
 import java.util.Map;
 import java.util.UUID;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.apache.aries.blueprint.annotation.service.Reference;
 import org.apache.commons.lang3.BooleanUtils;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
+import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
+import org.opendaylight.genius.infra.Datastore.Configuration;
+import org.opendaylight.genius.infra.TypedWriteTransaction;
+import org.opendaylight.genius.interfacemanager.InterfacemgrProvider;
 import org.opendaylight.genius.interfacemanager.commons.InterfaceManagerCommonUtils;
+import org.opendaylight.genius.interfacemanager.globals.IfmConstants;
+import org.opendaylight.infrautils.caches.Cache;
+import org.opendaylight.infrautils.caches.CacheConfigBuilder;
+import org.opendaylight.infrautils.caches.CachePolicyBuilder;
+import org.opendaylight.infrautils.caches.CacheProvider;
 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.Uri;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.bridge._interface.info.BridgeEntry;
@@ -40,6 +55,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.InterfaceTypeGre;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeVxlan;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentation;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbPortInterfaceAttributes;
 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;
@@ -50,7 +66,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.re
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.OptionsBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.OptionsKey;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TpId;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
@@ -63,26 +79,21 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+@Singleton
 public class SouthboundUtils {
     private static final Logger LOG = LoggerFactory.getLogger(SouthboundUtils.class);
 
-    public static final String BFD_PARAM_ENABLE = "enable";
-    static final String BFD_PARAM_MIN_TX = "min_tx";
-    static final String BFD_PARAM_MIN_RX = "min_rx";
-    static final String BFD_PARAM_DECAY_MIN_RX = "decay_min_rx";
-    static final String BFD_PARAM_FORWARDING_IF_RX = "forwarding_if_rx";
-    static final String BFD_PARAM_CPATH_DOWN = "cpath_down";
-    static final String BFD_PARAM_CHECK_TNL_KEY = "check_tnl_key";
+    private static final String BFD_PARAM_ENABLE = "enable";
+    private static final String BFD_PARAM_MIN_TX = "min_tx";
+    private static final String BFD_PARAM_FORWARDING_IF_RX = "forwarding_if_rx";
 
     // BFD parameters
+    public static final String BFD_ENABLE_KEY = "enable";
+    public static final String BFD_ENABLE_VALUE = "true";
     public static final String BFD_OP_STATE = "state";
     public static final String BFD_STATE_UP = "up";
-    private static final String BFD_MIN_RX_VAL = "1000";
     private static final String BFD_MIN_TX_VAL = "100";
-    private static final String BFD_DECAY_MIN_RX_VAL = "200";
     private static final String BFD_FORWARDING_IF_RX_VAL = "true";
-    private static final String BFD_CPATH_DOWN_VAL = "false";
-    private static final String BFD_CHECK_TNL_KEY_VAL = "false";
 
     // Tunnel options
     private static final String TUNNEL_OPTIONS_KEY = "key";
@@ -99,39 +110,70 @@ public class SouthboundUtils {
     private static final String TUNNEL_OPTIONS_NSHC3 = "nshc3";
     private static final String TUNNEL_OPTIONS_NSHC4 = "nshc4";
 
+    // Tunnel options for MPLS-GRE tunnels [requires OVS 2.8+)
+    private static final String TUNNEL_OPTIONS_PKT_TYPE = "packet_type";
+
     // Option values for VxLAN-GPE + NSH tunnels
     private static final String TUNNEL_OPTIONS_VALUE_FLOW = "flow";
     private static final String TUNNEL_OPTIONS_VALUE_GPE = "gpe";
-     // UDP port for VxLAN-GPE Tunnels
+    // UDP port for VxLAN-GPE Tunnels
     private static final String TUNNEL_OPTIONS_VALUE_GPE_DESTINATION_PORT = "4880";
 
-    //
-    public static final TopologyId OVSDB_TOPOLOGY_ID = new TopologyId(new Uri("ovsdb:1"));
+    // Tunnel option values for MPLS-GRE tunnels [requires OVS 2.8+)
+    private static final String TUNNEL_OPTIONS_VALUE_LEGACY_L3 = "legacy_l3";
 
     // To keep the mapping between Tunnel Types and Tunnel Interfaces
-    private static final Map<Class<? extends TunnelTypeBase>, Class<? extends InterfaceTypeBase>> TUNNEL_TYPE_MAP = new HashMap<Class<? extends TunnelTypeBase>, Class<? extends InterfaceTypeBase>>() {
-        {
-            put(TunnelTypeGre.class, InterfaceTypeGre.class);
-            put(TunnelTypeVxlan.class, InterfaceTypeVxlan.class);
-            put(TunnelTypeVxlanGpe.class, InterfaceTypeVxlan.class);
-        }
-    };
+    private static final Map<Class<? extends TunnelTypeBase>, Class<? extends InterfaceTypeBase>>
+        TUNNEL_TYPE_MAP = new HashMap<Class<? extends TunnelTypeBase>, Class<? extends InterfaceTypeBase>>() {
+            {
+                put(TunnelTypeGre.class, InterfaceTypeGre.class);
+                put(TunnelTypeMplsOverGre.class, InterfaceTypeGre.class);
+                put(TunnelTypeVxlan.class, InterfaceTypeVxlan.class);
+                put(TunnelTypeVxlanGpe.class, InterfaceTypeVxlan.class);
+            }
+        };
+
+    // OVS Detection statics
+    private static final String DEFAULT_OVS_VERSION = "2.8.0";
+    private static final String MIN_GRE_VERSION = "2.8.0";
+    private static final long MAX_CACHE_SIZE = 1024;
+
+    private final SingleTransactionDataBroker singleTxDB;
+
+    private final BatchingUtils batchingUtils;
+    private final InterfacemgrProvider interfacemgrProvider;
+    private final Cache<String, String> ovsVersionCache;
+
+    @Inject
+    public SouthboundUtils(@Reference final DataBroker dataBroker,
+                           final BatchingUtils batchingUtils, InterfacemgrProvider interfacemgrProvider,
+                           @Reference final CacheProvider cacheProvider) {
+        this.batchingUtils = batchingUtils;
+        this.interfacemgrProvider = interfacemgrProvider;
+        this.singleTxDB = new SingleTransactionDataBroker(dataBroker);
+        ovsVersionCache = cacheProvider.newCache(
+                new CacheConfigBuilder<String, String>()
+                        .anchor(this)
+                        .id("ovsVersionCache")
+                        .cacheFunction(key -> getVersionForBridgeNodeId(key))
+                        .description("BridgeNodeId to OVS Version cache")
+                        .build(),
+                new CachePolicyBuilder().maxEntries(MAX_CACHE_SIZE).build());
+    }
 
-    public static void addPortToBridge(InstanceIdentifier<?> bridgeIid, Interface iface, String portName, DataBroker dataBroker,
-            List<ListenableFuture<Void>> futures) {
-        IfTunnel ifTunnel = iface.getAugmentation(IfTunnel.class);
+    public void addPortToBridge(InstanceIdentifier<?> bridgeIid, Interface iface, String portName) {
+        IfTunnel ifTunnel = iface.augmentation(IfTunnel.class);
         if (ifTunnel != null) {
-            addTunnelPortToBridge(ifTunnel, bridgeIid, iface, portName, dataBroker);
+            addTunnelPortToBridge(ifTunnel, bridgeIid, iface, portName);
         }
     }
 
     /*
-     * Add all tunnels ports corresponding to the bridge to the topology config
-     * DS
+     * Add all tunnels ports corresponding to the bridge to the topology config DS.
      */
-    public static void addAllPortsToBridge(BridgeEntry bridgeEntry, DataBroker dataBroker,
-            InstanceIdentifier<OvsdbBridgeAugmentation> bridgeIid, OvsdbBridgeAugmentation bridgeNew,
-            List<ListenableFuture<Void>> futures) {
+    public void addAllPortsToBridge(BridgeEntry bridgeEntry, InterfaceManagerCommonUtils interfaceManagerCommonUtils,
+                                    InstanceIdentifier<OvsdbBridgeAugmentation> bridgeIid,
+                                    OvsdbBridgeAugmentation bridgeNew) {
         String bridgeName = bridgeNew.getBridgeName().getValue();
         LOG.debug("adding all ports to bridge: {}", bridgeName);
         List<BridgeInterfaceEntry> bridgeInterfaceEntries = bridgeEntry.getBridgeInterfaceEntry();
@@ -139,15 +181,17 @@ public class SouthboundUtils {
             for (BridgeInterfaceEntry bridgeInterfaceEntry : bridgeInterfaceEntries) {
                 String portName = bridgeInterfaceEntry.getInterfaceName();
                 InterfaceKey interfaceKey = new InterfaceKey(portName);
-                Interface iface = InterfaceManagerCommonUtils.getInterfaceFromConfigDS(interfaceKey, dataBroker);
+                Interface iface = interfaceManagerCommonUtils.getInterfaceFromConfigDS(interfaceKey);
                 if (iface != null) {
-                    IfTunnel ifTunnel = iface.getAugmentation(IfTunnel.class);
+                    IfTunnel ifTunnel = iface.augmentation(IfTunnel.class);
                     if (ifTunnel != null) {
-                        addTunnelPortToBridge(ifTunnel, bridgeIid, iface, portName, dataBroker);
-                    }
-                    if(SouthboundUtils.isOfTunnel(ifTunnel)) {
-                        LOG.debug("Using OFTunnel. Only one tunnel port will be added");
-                        return;
+                        if (!(interfacemgrProvider.isItmDirectTunnelsEnabled() && ifTunnel.isInternal())) {
+                            addTunnelPortToBridge(ifTunnel, bridgeIid, iface, portName);
+                        }
+                        if (isOfTunnel(ifTunnel)) {
+                            LOG.debug("Using OFTunnel. Only one tunnel port will be added");
+                            return;
+                        }
                     }
                 } else {
                     LOG.debug("Interface {} not found in config DS", portName);
@@ -156,50 +200,8 @@ public class SouthboundUtils {
         }
     }
 
-    /*
-     * delete all tunnels ports corresponding to the bridge to the topology config
-     * DS
-     */
-    public static void removeAllPortsFromBridge(BridgeEntry bridgeEntry, DataBroker dataBroker,
-            InstanceIdentifier<OvsdbBridgeAugmentation> bridgeIid, OvsdbBridgeAugmentation bridgeNew,
-            List<ListenableFuture<Void>> futures) {
-        WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction();
-        String bridgeName = bridgeNew.getBridgeName().getValue();
-        LOG.debug("removing all ports from bridge: {}", bridgeName);
-        List<BridgeInterfaceEntry> bridgeInterfaceEntries = bridgeEntry.getBridgeInterfaceEntry();
-        if (bridgeInterfaceEntries != null) {
-            for (BridgeInterfaceEntry bridgeInterfaceEntry : bridgeInterfaceEntries) {
-                String portName = bridgeInterfaceEntry.getInterfaceName();
-                InterfaceKey interfaceKey = new InterfaceKey(portName);
-                Interface iface = InterfaceManagerCommonUtils.getInterfaceFromConfigDS(interfaceKey, dataBroker);
-                if (iface != null) {
-                    IfTunnel ifTunnel = iface.getAugmentation(IfTunnel.class);
-                    if (ifTunnel != null) {
-                        removeTerminationEndPoint(futures, dataBroker, bridgeIid, iface.getName());
-                    }
-                    if(SouthboundUtils.isOfTunnel(ifTunnel)) {
-                        LOG.debug("Using OFTunnel. Only one tunnel port to be removed");
-                        return;
-                    }
-                } else {
-                    LOG.debug("Interface {} not found in config DS", portName);
-                }
-            }
-        }
-        futures.add(writeTransaction.submit());
-    }
-
-    private static void addVlanPortToBridge(InstanceIdentifier<?> bridgeIid, IfL2vlan ifL2vlan, IfTunnel ifTunnel,
-            OvsdbBridgeAugmentation bridgeAugmentation, String bridgeName, String portName, DataBroker dataBroker,
-            WriteTransaction t) {
-        if (ifL2vlan.getVlanId() != null) {
-            addTerminationPoint(bridgeIid, portName, ifL2vlan.getVlanId().getValue(),
-                    null, null, ifTunnel);
-        }
-    }
-
-    private static void addTunnelPortToBridge(IfTunnel ifTunnel, InstanceIdentifier<?> bridgeIid, Interface iface,
-            String portName, DataBroker dataBroker) {
+    private void addTunnelPortToBridge(IfTunnel ifTunnel, InstanceIdentifier<?> bridgeIid, Interface iface,
+            String portName) {
         LOG.debug("adding tunnel port {} to bridge {}", portName, bridgeIid);
 
         Class<? extends InterfaceTypeBase> type = TUNNEL_TYPE_MAP.get(ifTunnel.getTunnelInterfaceType());
@@ -210,7 +212,7 @@ public class SouthboundUtils {
         }
 
         int vlanId = 0;
-        IfL2vlan ifL2vlan = iface.getAugmentation(IfL2vlan.class);
+        IfL2vlan ifL2vlan = iface.augmentation(IfL2vlan.class);
         if (ifL2vlan != null && ifL2vlan.getVlanId() != null) {
             vlanId = ifL2vlan.getVlanId().getValue();
         }
@@ -218,21 +220,32 @@ public class SouthboundUtils {
         Map<String, String> options = Maps.newHashMap();
 
         // Options common to any kind of tunnel
-        if(BooleanUtils.isTrue(ifTunnel.isTunnelSourceIpFlow())) {
+        if (BooleanUtils.isTrue(ifTunnel.isTunnelSourceIpFlow())) {
             options.put(TUNNEL_OPTIONS_LOCAL_IP, TUNNEL_OPTIONS_VALUE_FLOW);
         } else {
             IpAddress localIp = ifTunnel.getTunnelSource();
-            options.put(TUNNEL_OPTIONS_LOCAL_IP, localIp.getIpv4Address().getValue());
+            options.put(TUNNEL_OPTIONS_LOCAL_IP, localIp.stringValue());
         }
-        if(BooleanUtils.isTrue(ifTunnel.isTunnelRemoteIpFlow())) {
+        if (BooleanUtils.isTrue(ifTunnel.isTunnelRemoteIpFlow())) {
             options.put(TUNNEL_OPTIONS_REMOTE_IP, TUNNEL_OPTIONS_VALUE_FLOW);
         } else {
             IpAddress remoteIp = ifTunnel.getTunnelDestination();
-            options.put(TUNNEL_OPTIONS_REMOTE_IP, remoteIp.getIpv4Address().getValue());
+            options.put(TUNNEL_OPTIONS_REMOTE_IP, remoteIp.stringValue());
         }
-
         // Specific options for each type of tunnel
-        if (!ifTunnel.getTunnelInterfaceType().equals(TunnelTypeMplsOverGre.class)) {
+        if (TunnelTypeMplsOverGre.class.equals(ifTunnel.getTunnelInterfaceType())) {
+            String switchVersion = getSwitchVersion((InstanceIdentifier<Node>) bridgeIid);
+            LOG.debug("Switch OVS Version: {}", switchVersion);
+            if (org.opendaylight.ovsdb.utils.southbound.utils.SouthboundUtils.compareDbVersionToMinVersion(
+                    switchVersion, MIN_GRE_VERSION)) {
+                options.put(TUNNEL_OPTIONS_PKT_TYPE, TUNNEL_OPTIONS_VALUE_LEGACY_L3);
+            } else {
+                LOG.warn("{} OVS version {} less than {} required for MplsOverGre",
+                        bridgeIid.firstKeyOf(Node.class).getNodeId().getValue(),
+                        switchVersion, MIN_GRE_VERSION);
+                return;
+            }
+        } else {
             options.put(TUNNEL_OPTIONS_KEY, TUNNEL_OPTIONS_VALUE_FLOW);
         }
         if (ifTunnel.getTunnelInterfaceType().equals(TunnelTypeVxlanGpe.class)) {
@@ -243,12 +256,13 @@ public class SouthboundUtils {
             options.put(TUNNEL_OPTIONS_NSHC2, TUNNEL_OPTIONS_VALUE_FLOW);
             options.put(TUNNEL_OPTIONS_NSHC3, TUNNEL_OPTIONS_VALUE_FLOW);
             options.put(TUNNEL_OPTIONS_NSHC4, TUNNEL_OPTIONS_VALUE_FLOW);
-            // VxLAN-GPE interfaces will not use the default UDP port to avoid problems with other meshes
+            // VxLAN-GPE interfaces will not use the default UDP port to avoid
+            // problems with other meshes
             options.put(TUNNEL_OPTIONS_DESTINATION_PORT, TUNNEL_OPTIONS_VALUE_GPE_DESTINATION_PORT);
         }
 
-        if(ifTunnel.getTunnelOptions() != null) {
-            for(TunnelOptions tunOpt : ifTunnel.getTunnelOptions()) {
+        if (ifTunnel.getTunnelOptions() != null) {
+            for (TunnelOptions tunOpt : ifTunnel.getTunnelOptions()) {
                 options.putIfAbsent(tunOpt.getTunnelOption(), tunOpt.getValue());
             }
         }
@@ -258,10 +272,10 @@ public class SouthboundUtils {
 
     // Update is allowed only for tunnel monitoring attributes
     public static void updateBfdParamtersForTerminationPoint(InstanceIdentifier<?> bridgeIid, IfTunnel ifTunnel,
-            String portName, WriteTransaction transaction) {
+            String portName, TypedWriteTransaction<Configuration> transaction) {
         InstanceIdentifier<TerminationPoint> tpIid = createTerminationPointInstanceIdentifier(
                 InstanceIdentifier.keyOf(bridgeIid.firstIdentifierOf(Node.class)), portName);
-        if(isOfTunnel(ifTunnel)) {
+        if (isOfTunnel(ifTunnel)) {
             LOG.warn("BFD monitoring not supported for OFTunnels. Skipping BFD parameters for {}", portName);
             return;
         }
@@ -271,16 +285,14 @@ public class SouthboundUtils {
         tpAugmentationBuilder.setInterfaceBfd(bfdParams);
 
         TerminationPointBuilder tpBuilder = new TerminationPointBuilder();
-        tpBuilder.setKey(InstanceIdentifier.keyOf(tpIid));
+        tpBuilder.withKey(InstanceIdentifier.keyOf(tpIid));
         tpBuilder.addAugmentation(OvsdbTerminationPointAugmentation.class, tpAugmentationBuilder.build());
 
-        transaction.merge(LogicalDatastoreType.CONFIGURATION, tpIid, tpBuilder.build(), true);
+        transaction.merge(tpIid, tpBuilder.build(), CREATE_MISSING_PARENTS);
     }
 
-    private static void addTerminationPoint(InstanceIdentifier<?> bridgeIid, String portName, int vlanId,
-                                            Class<? extends InterfaceTypeBase> type, Map<String, String> options, IfTunnel ifTunnel) {
-        InstanceIdentifier<TerminationPoint> tpIid = createTerminationPointInstanceIdentifier(
-                InstanceIdentifier.keyOf(bridgeIid.firstIdentifierOf(Node.class)), portName);
+    private void addTerminationPoint(InstanceIdentifier<?> bridgeIid, String portName, int vlanId,
+            Class<? extends InterfaceTypeBase> type, Map<String, String> options, IfTunnel ifTunnel) {
         OvsdbTerminationPointAugmentationBuilder tpAugmentationBuilder = new OvsdbTerminationPointAugmentationBuilder();
 
         tpAugmentationBuilder.setName(portName);
@@ -293,7 +305,7 @@ public class SouthboundUtils {
             List<Options> optionsList = new ArrayList<>();
             for (Map.Entry<String, String> entry : options.entrySet()) {
                 OptionsBuilder optionsBuilder = new OptionsBuilder();
-                optionsBuilder.setKey(new OptionsKey(entry.getKey()));
+                optionsBuilder.withKey(new OptionsKey(entry.getKey()));
                 optionsBuilder.setOption(entry.getKey());
                 optionsBuilder.setValue(entry.getValue());
                 optionsList.add(optionsBuilder.build());
@@ -307,54 +319,91 @@ public class SouthboundUtils {
         }
 
         if (bfdMonitoringEnabled(ifTunnel)) {
-            if(isOfTunnel(ifTunnel)) {
+            if (isOfTunnel(ifTunnel)) {
                 LOG.warn("BFD Monitoring not supported for OFTunnels");
             } else {
                 List<InterfaceBfd> bfdParams = getBfdParams(ifTunnel);
                 tpAugmentationBuilder.setInterfaceBfd(bfdParams);
             }
         }
-
         TerminationPointBuilder tpBuilder = new TerminationPointBuilder();
-        tpBuilder.setKey(InstanceIdentifier.keyOf(tpIid));
+        InstanceIdentifier<TerminationPoint> tpIid = createTerminationPointInstanceIdentifier(
+                InstanceIdentifier.keyOf(bridgeIid.firstIdentifierOf(Node.class)), portName);
+        tpBuilder.withKey(InstanceIdentifier.keyOf(tpIid));
         tpBuilder.addAugmentation(OvsdbTerminationPointAugmentation.class, tpAugmentationBuilder.build());
 
-        BatchingUtils.write(tpIid, tpBuilder.build(), BatchingUtils.EntityType.TOPOLOGY_CONFIG);
-
+        batchingUtils.write(tpIid, tpBuilder.build(), BatchingUtils.EntityType.TOPOLOGY_CONFIG);
     }
 
     private static List<InterfaceBfd> getBfdParams(IfTunnel ifTunnel) {
         List<InterfaceBfd> bfdParams = new ArrayList<>();
-        bfdParams.add(getIfBfdObj(BFD_PARAM_ENABLE,ifTunnel != null ? ifTunnel.isMonitorEnabled().toString() :"false"));
-        bfdParams.add(getIfBfdObj(BFD_PARAM_MIN_TX, ifTunnel != null &&  ifTunnel.getMonitorInterval() != null ?
-                ifTunnel.getMonitorInterval().toString() : BFD_MIN_TX_VAL));
+        bfdParams.add(
+                getIfBfdObj(BFD_PARAM_ENABLE, ifTunnel != null ? ifTunnel.isMonitorEnabled().toString() : "false"));
+        bfdParams.add(getIfBfdObj(BFD_PARAM_MIN_TX,
+                ifTunnel != null && ifTunnel.getMonitorInterval() != null ? ifTunnel.getMonitorInterval().toString()
+                        : BFD_MIN_TX_VAL));
+        bfdParams.add(getIfBfdObj(BFD_PARAM_FORWARDING_IF_RX, BFD_FORWARDING_IF_RX_VAL));
         return bfdParams;
     }
 
     private static InterfaceBfd getIfBfdObj(String key, String value) {
         InterfaceBfdBuilder bfdBuilder = new InterfaceBfdBuilder();
-        bfdBuilder.setBfdKey(key).setKey(new InterfaceBfdKey(key)).setBfdValue(value);
+        bfdBuilder.setBfdKey(key).withKey(new InterfaceBfdKey(key)).setBfdValue(value);
         return bfdBuilder.build();
     }
 
+    private String getSwitchVersion(InstanceIdentifier<Node> bridgeIid) {
+        String ovsNodeId = bridgeIid.firstKeyOf(Node.class).getNodeId().getValue().split("/bridge")[0];
+        return ovsVersionCache.get(ovsNodeId);
+    }
+
+    private String getVersionForBridgeNodeId(String ovsNodeId) {
+        InstanceIdentifier<Node> ovsNodeIid = InstanceIdentifier.create(NetworkTopology.class)
+                .child(Topology.class, new TopologyKey(IfmConstants.OVSDB_TOPOLOGY_ID))
+                .child(Node.class, new NodeKey(new NodeId(ovsNodeId)));
+        String ovsVersion = DEFAULT_OVS_VERSION;
+        try {
+            Node ovsNode = singleTxDB.syncRead(LogicalDatastoreType.OPERATIONAL, ovsNodeIid);
+            ovsVersion = ovsNode.augmentation(OvsdbNodeAugmentation.class).getOvsVersion()
+                    .toLowerCase(Locale.ROOT);
+        } catch (ReadFailedException e) {
+            LOG.error("OVS Node {} not present", ovsNodeId);
+        }
+        return ovsVersion;
+    }
+
     public static InstanceIdentifier<TerminationPoint> createTerminationPointInstanceIdentifier(NodeKey nodekey,
             String portName) {
         InstanceIdentifier<TerminationPoint> terminationPointPath = InstanceIdentifier.create(NetworkTopology.class)
-                .child(Topology.class, new TopologyKey(OVSDB_TOPOLOGY_ID)).child(Node.class, nodekey)
+                .child(Topology.class, new TopologyKey(IfmConstants.OVSDB_TOPOLOGY_ID)).child(Node.class, nodekey)
                 .child(TerminationPoint.class, new TerminationPointKey(new TpId(portName)));
 
         LOG.debug("Termination point InstanceIdentifier generated : {}", terminationPointPath);
         return terminationPointPath;
     }
 
-    public static void removeTerminationEndPoint(List<ListenableFuture<Void>> futures, DataBroker dataBroker,
-            InstanceIdentifier<?> bridgeIid, String interfaceName) {
+    public void removeTerminationEndPoint(InstanceIdentifier<?> bridgeIid, String interfaceName) {
         LOG.debug("removing termination point for {}", interfaceName);
-        WriteTransaction transaction = dataBroker.newWriteOnlyTransaction();
         InstanceIdentifier<TerminationPoint> tpIid = SouthboundUtils.createTerminationPointInstanceIdentifier(
                 InstanceIdentifier.keyOf(bridgeIid.firstIdentifierOf(Node.class)), interfaceName);
-        transaction.delete(LogicalDatastoreType.CONFIGURATION, tpIid);
-        futures.add(transaction.submit());
+        batchingUtils.delete(tpIid, BatchingUtils.EntityType.TOPOLOGY_CONFIG);
+    }
+
+    public static boolean ifBfdStatusNotEqual(OvsdbTerminationPointAugmentation tpOld,
+                                           OvsdbTerminationPointAugmentation tpNew) {
+        return (tpNew.getInterfaceBfdStatus() != null
+                && (tpOld == null || !tpNew.getInterfaceBfdStatus().equals(tpOld.getInterfaceBfdStatus())));
+    }
+
+    public static boolean changeInBfdMonitoringDetected(OvsdbTerminationPointAugmentation tpOld,
+                                                        OvsdbTerminationPointAugmentation tpNew) {
+        if (tpOld != null) {
+            return org.opendaylight.genius.interfacemanager.renderer.ovs.utilities.SouthboundUtils
+                    .bfdMonitoringEnabled(tpNew.getInterfaceBfd())
+                    != org.opendaylight.genius.interfacemanager.renderer.ovs.utilities.SouthboundUtils
+                    .bfdMonitoringEnabled(tpOld.getInterfaceBfd());
+        }
+        return false;
     }
 
     public static boolean bfdMonitoringEnabled(IfTunnel ifTunnel) {
@@ -362,30 +411,44 @@ public class SouthboundUtils {
                 && TunnelMonitoringTypeBfd.class.isAssignableFrom(ifTunnel.getMonitorProtocol());
     }
 
+    public static boolean bfdMonitoringEnabled(List<InterfaceBfd> interfaceBfds) {
+        if (interfaceBfds == null) {
+            return false;
+        }
+        for (InterfaceBfd interfaceBfd : interfaceBfds) {
+            if (SouthboundUtils.BFD_ENABLE_KEY.equalsIgnoreCase(interfaceBfd.getBfdKey())) {
+                return SouthboundUtils.BFD_ENABLE_VALUE.equalsIgnoreCase(interfaceBfd.getBfdValue());//checkBfdEnabled
+            }
+        }
+        return false;
+    }
+
     public static boolean isMonitorProtocolBfd(IfTunnel ifTunnel) {
         return TunnelMonitoringTypeBfd.class.isAssignableFrom(ifTunnel.getMonitorProtocol());
     }
 
+    @SuppressFBWarnings("DM_DEFAULT_ENCODING")
     public static String generateOfTunnelName(BigInteger dpId, IfTunnel ifTunnel) {
-        String sourceKey = ifTunnel.getTunnelSource().getIpv4Address().getValue();
-        String remoteKey = ifTunnel.getTunnelDestination().getIpv4Address().getValue();
-        ififTunnel.isTunnelSourceIpFlow() != null) {
+        String sourceKey = ifTunnel.getTunnelSource().stringValue();
+        String remoteKey = ifTunnel.getTunnelDestination().stringValue();
+        if (ifTunnel.isTunnelSourceIpFlow() != null) {
             sourceKey = "flow";
         }
-        ififTunnel.isTunnelRemoteIpFlow() != null) {
+        if (ifTunnel.isTunnelRemoteIpFlow() != null) {
             remoteKey = "flow";
         }
-        String tunnelNameKey = dpId.toString()+sourceKey+remoteKey;
+        String tunnelNameKey = dpId.toString() + sourceKey + remoteKey;
         String uuidStr = UUID.nameUUIDFromBytes(tunnelNameKey.getBytes()).toString().substring(0, 12).replace("-", "");
         return String.format("%s%s", "tun", uuidStr);
     }
 
     public static boolean isOfTunnel(IfTunnel ifTunnel) {
-        if( BooleanUtils.isTrue(ifTunnel.isTunnelRemoteIpFlow()) ||
-                BooleanUtils.isTrue(ifTunnel.isTunnelSourceIpFlow()) ) {
-            return true;
-        }
-        return false;
+        return Boolean.TRUE.equals(ifTunnel.isTunnelRemoteIpFlow())
+                || Boolean.TRUE.equals(ifTunnel.isTunnelSourceIpFlow());
+    }
+
+    public static boolean isInterfaceTypeTunnel(Class<? extends InterfaceTypeBase> interfaceType) {
+        return InterfaceTypeGre.class.equals(interfaceType) || InterfaceTypeVxlan.class.equals(interfaceType);
     }
 
 }