Switch to JDT annotations for Nullable and NonNull
[netvirt.git] / elanmanager / impl / src / main / java / org / opendaylight / netvirt / elan / internal / ElanServiceProvider.java
index c15aa5ac3552b24bd6abcfece7afeee3316096dc..cbde09c7ea563112b931928125a0d4e2405fe9f9 100644 (file)
@@ -8,6 +8,8 @@
 
 package org.opendaylight.netvirt.elan.internal;
 
+import static java.util.Collections.emptyList;
+
 import com.google.common.base.Optional;
 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 import java.math.BigInteger;
@@ -17,26 +19,29 @@ import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Set;
 import java.util.concurrent.Future;
 import java.util.function.BiFunction;
-import javax.annotation.Nonnull;
 import javax.inject.Inject;
 import javax.inject.Singleton;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.genius.infra.Datastore;
+import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
+import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
 import org.opendaylight.genius.interfacemanager.exceptions.InterfaceAlreadyExistsException;
 import org.opendaylight.genius.interfacemanager.globals.IfmConstants;
 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
 import org.opendaylight.genius.mdsalutil.MDSALUtil;
-import org.opendaylight.genius.mdsalutil.MatchInfoBase;
-import org.opendaylight.genius.mdsalutil.MetaDataUtil;
 import org.opendaylight.genius.mdsalutil.NwConstants;
 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
-import org.opendaylight.genius.mdsalutil.nxmatches.NxMatchRegister;
 import org.opendaylight.genius.utils.ServiceIndex;
 import org.opendaylight.genius.utils.hwvtep.HwvtepSouthboundConstants;
 import org.opendaylight.infrautils.inject.AbstractLifecycle;
+import org.opendaylight.infrautils.utils.concurrent.ListenableFutures;
 import org.opendaylight.mdsal.eos.binding.api.Entity;
 import org.opendaylight.mdsal.eos.binding.api.EntityOwnershipCandidateRegistration;
 import org.opendaylight.mdsal.eos.binding.api.EntityOwnershipService;
@@ -49,14 +54,15 @@ import org.opendaylight.netvirt.elan.utils.ElanConstants;
 import org.opendaylight.netvirt.elan.utils.ElanUtils;
 import org.opendaylight.netvirt.elanmanager.api.ElanHelper;
 import org.opendaylight.netvirt.elanmanager.api.IElanService;
-import org.opendaylight.netvirt.elanmanager.exceptions.MacNotFoundException;
 import org.opendaylight.ovsdb.utils.southbound.utils.SouthboundUtils;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
 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.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolOutput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfL2vlan;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.etree.rev160614.EtreeInstance;
@@ -93,6 +99,7 @@ public class ElanServiceProvider extends AbstractLifecycle implements IElanServi
     private final IInterfaceManager interfaceManager;
     private final ElanBridgeManager bridgeMgr;
     private final DataBroker broker;
+    private final ManagedNewTransactionRunner txRunner;
     private final ElanUtils elanUtils;
     private final SouthboundUtils southboundUtils;
     private final IMdsalApiManager mdsalManager;
@@ -106,7 +113,6 @@ public class ElanServiceProvider extends AbstractLifecycle implements IElanServi
     public ElanServiceProvider(IdManagerService idManager, IInterfaceManager interfaceManager,
                                ElanBridgeManager bridgeMgr,
                                DataBroker dataBroker,
-                               ElanInterfaceManager elanInterfaceManager,
                                ElanUtils elanUtils,
                                EntityOwnershipService entityOwnershipService,
                                SouthboundUtils southboundUtils, ElanInstanceCache elanInstanceCache,
@@ -115,6 +121,7 @@ public class ElanServiceProvider extends AbstractLifecycle implements IElanServi
         this.interfaceManager = interfaceManager;
         this.bridgeMgr = bridgeMgr;
         this.broker = dataBroker;
+        this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
         this.elanUtils = elanUtils;
         this.southboundUtils = southboundUtils;
         this.elanInstanceCache = elanInstanceCache;
@@ -124,6 +131,7 @@ public class ElanServiceProvider extends AbstractLifecycle implements IElanServi
         candidateRegistration = registerCandidate(entityOwnershipService);
     }
 
+    @Nullable
     private static EntityOwnershipCandidateRegistration registerCandidate(
             EntityOwnershipService entityOwnershipService) {
         try {
@@ -162,7 +170,7 @@ public class ElanServiceProvider extends AbstractLifecycle implements IElanServi
     private void createIdPool() throws Exception {
         CreateIdPoolInput createPool = new CreateIdPoolInputBuilder().setPoolName(ElanConstants.ELAN_ID_POOL_NAME)
                 .setLow(ElanConstants.ELAN_ID_LOW_VALUE).setHigh(ElanConstants.ELAN_ID_HIGH_VALUE).build();
-        Future<RpcResult<Void>> result = idManager.createIdPool(createPool);
+        Future<RpcResult<CreateIdPoolOutput>> result = idManager.createIdPool(createPool);
         if (result != null && result.get().isSuccessful()) {
             LOG.debug("ELAN Id Pool is created successfully");
         }
@@ -179,16 +187,16 @@ public class ElanServiceProvider extends AbstractLifecycle implements IElanServi
             } else {
                 ElanInstance updateElanInstance = new ElanInstanceBuilder().setElanInstanceName(elanInstanceName)
                         .setDescription(description).setMacTimeout(macTimeout)
-                        .setKey(new ElanInstanceKey(elanInstanceName)).build();
+                        .withKey(new ElanInstanceKey(elanInstanceName)).build();
                 MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION,
                         ElanHelper.getElanInstanceConfigurationDataPath(elanInstanceName), updateElanInstance);
-                LOG.debug("Updating the Elan Instance {} with MAC TIME-OUT %l and Description %s ",
+                LOG.debug("Updating the Elan Instance {} with MAC TIME-OUT {} and Description {}",
                         updateElanInstance, macTimeout, description);
             }
         } else {
             ElanInstance elanInstance = new ElanInstanceBuilder().setElanInstanceName(elanInstanceName)
-                    .setMacTimeout(macTimeout).setDescription(description).setKey(new ElanInstanceKey(elanInstanceName))
-                    .build();
+                    .setMacTimeout(macTimeout).setDescription(description)
+                    .withKey(new ElanInstanceKey(elanInstanceName)).build();
             MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION,
                     ElanHelper.getElanInstanceConfigurationDataPath(elanInstanceName), elanInstance);
             LOG.debug("Creating the new Elan Instance {}", elanInstance);
@@ -208,17 +216,18 @@ public class ElanServiceProvider extends AbstractLifecycle implements IElanServi
                 EtreeInstance etreeInstance = new EtreeInstanceBuilder().build();
                 ElanInstance updateElanInstance = new ElanInstanceBuilder().setElanInstanceName(elanInstanceName)
                         .setDescription(description).setMacTimeout(macTimeout)
-                        .setKey(new ElanInstanceKey(elanInstanceName))
+                        .withKey(new ElanInstanceKey(elanInstanceName))
                         .addAugmentation(EtreeInstance.class, etreeInstance).build();
                 MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION,
                         ElanHelper.getElanInstanceConfigurationDataPath(elanInstanceName), updateElanInstance);
-                LOG.debug("Updating the Etree Instance {} with MAC TIME-OUT %l and Description %s ",
+                LOG.debug("Updating the Etree Instance {} with MAC TIME-OUT {} and Description {} ",
                         updateElanInstance, macTimeout, description);
             }
         } else {
             EtreeInstance etreeInstance = new EtreeInstanceBuilder().build();
             ElanInstance elanInstance = new ElanInstanceBuilder().setElanInstanceName(elanInstanceName)
-                    .setMacTimeout(macTimeout).setDescription(description).setKey(new ElanInstanceKey(elanInstanceName))
+                    .setMacTimeout(macTimeout).setDescription(description)
+                    .withKey(new ElanInstanceKey(elanInstanceName))
                     .addAugmentation(EtreeInstance.class, etreeInstance).build();
             MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION,
                     ElanHelper.getElanInstanceConfigurationDataPath(elanInstanceName), elanInstance);
@@ -228,6 +237,7 @@ public class ElanServiceProvider extends AbstractLifecycle implements IElanServi
     }
 
     @Override
+    @Nullable
     public EtreeInterface getEtreeInterfaceByElanInterfaceName(String elanInterface) {
         return elanInterfaceCache.getEtreeInterface(elanInterface).orNull();
     }
@@ -236,7 +246,7 @@ public class ElanServiceProvider extends AbstractLifecycle implements IElanServi
             String description) {
         boolean isEqual = false;
         if (existingElanInstance.getMacTimeout() == macTimeOut
-                && existingElanInstance.getDescription().equals(description)) {
+                && Objects.equals(existingElanInstance.getDescription(), description)) {
             isEqual = true;
         }
         return isEqual;
@@ -254,17 +264,15 @@ public class ElanServiceProvider extends AbstractLifecycle implements IElanServi
 
     @Override
     public boolean deleteElanInstance(String elanInstanceName) {
-        boolean isSuccess = false;
         Optional<ElanInstance> existingElanInstance = elanInstanceCache.get(elanInstanceName);
         if (!existingElanInstance.isPresent()) {
             LOG.debug("Elan Instance is not present for {}", elanInstanceName);
-            return isSuccess;
+            return false;
         }
         LOG.debug("Deletion of the existing Elan Instance {}", existingElanInstance);
         ElanUtils.delete(broker, LogicalDatastoreType.CONFIGURATION,
                 ElanHelper.getElanInstanceConfigurationDataPath(elanInstanceName));
-        isSuccess = true;
-        return isSuccess;
+        return true;
     }
 
     @Override
@@ -272,19 +280,19 @@ public class ElanServiceProvider extends AbstractLifecycle implements IElanServi
             List<String> staticMacAddresses, String description) {
         Optional<ElanInstance> existingElanInstance = elanInstanceCache.get(etreeInstanceName);
         if (existingElanInstance.isPresent()
-                && existingElanInstance.get().getAugmentation(EtreeInstance.class) != null) {
+                && existingElanInstance.get().augmentation(EtreeInstance.class) != null) {
             EtreeInterface etreeInterface = new EtreeInterfaceBuilder().setEtreeInterfaceType(interfaceType).build();
             ElanInterface elanInterface;
             if (staticMacAddresses == null) {
                 elanInterface = new ElanInterfaceBuilder().setElanInstanceName(etreeInstanceName)
-                        .setDescription(description).setName(interfaceName).setKey(new ElanInterfaceKey(interfaceName))
+                        .setDescription(description).setName(interfaceName).withKey(new ElanInterfaceKey(interfaceName))
                         .addAugmentation(EtreeInterface.class, etreeInterface).build();
             } else {
                 List<StaticMacEntries> staticMacEntries = ElanUtils.getStaticMacEntries(staticMacAddresses);
                 elanInterface = new ElanInterfaceBuilder().setElanInstanceName(etreeInstanceName)
                         .setDescription(description).setName(interfaceName)
                         .setStaticMacEntries(staticMacEntries)
-                        .setKey(new ElanInterfaceKey(interfaceName))
+                        .withKey(new ElanInterfaceKey(interfaceName))
                         .addAugmentation(EtreeInterface.class, etreeInterface).build();
             }
             MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION,
@@ -294,14 +302,14 @@ public class ElanServiceProvider extends AbstractLifecycle implements IElanServi
     }
 
     @Override
-    public void addElanInterface(String elanInstanceName, String interfaceName, List<String> staticMacAddresses,
-            String description) {
+    public void addElanInterface(String elanInstanceName, String interfaceName,
+            @Nullable List<String> staticMacAddresses, @Nullable String description) {
         Optional<ElanInstance> existingElanInstance = elanInstanceCache.get(elanInstanceName);
         if (existingElanInstance.isPresent()) {
             ElanInterfaceBuilder elanInterfaceBuilder = new ElanInterfaceBuilder()
                     .setElanInstanceName(elanInstanceName)
                     .setDescription(description).setName(interfaceName)
-                    .setKey(new ElanInterfaceKey(interfaceName));
+                    .withKey(new ElanInterfaceKey(interfaceName));
             if (staticMacAddresses != null) {
                 List<StaticMacEntries> staticMacEntries = ElanUtils.getStaticMacEntries(staticMacAddresses);
                 elanInterfaceBuilder.setStaticMacEntries(staticMacEntries);
@@ -325,19 +333,19 @@ public class ElanServiceProvider extends AbstractLifecycle implements IElanServi
         LOG.debug("updating the ElanInterface with new Mac Entries {}", updatedStaticMacAddresses);
         ElanInterface elanInterface = new ElanInterfaceBuilder().setElanInstanceName(elanInstanceName)
                 .setName(interfaceName).setDescription(newDescription).setStaticMacEntries(updatedStaticMacEntries)
-                .setKey(new ElanInterfaceKey(interfaceName)).build();
+                .withKey(new ElanInterfaceKey(interfaceName)).build();
         MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION,
                 ElanUtils.getElanInterfaceConfigurationDataPathId(interfaceName), elanInterface);
     }
 
     @Override
-    public void deleteEtreeInterface(String elanInstanceName, String interfaceName) {
-        deleteElanInterface(elanInstanceName, interfaceName);
+    public void deleteEtreeInterface(String interfaceName) {
+        deleteElanInterface(interfaceName);
         LOG.debug("deleting the Etree Interface {}", interfaceName);
     }
 
     @Override
-    public void deleteElanInterface(String elanInstanceName, String interfaceName) {
+    public void deleteElanInterface(String interfaceName) {
         Optional<ElanInterface> existingElanInterface = elanInterfaceCache.get(interfaceName);
         if (existingElanInterface.isPresent()) {
             ElanUtils.delete(broker, LogicalDatastoreType.CONFIGURATION,
@@ -347,7 +355,7 @@ public class ElanServiceProvider extends AbstractLifecycle implements IElanServi
     }
 
     @Override
-    public void addStaticMacAddress(String elanInstanceName, String interfaceName, String macAddress) {
+    public void addStaticMacAddress(String interfaceName, String macAddress) {
         Optional<ElanInterface> existingElanInterface = elanInterfaceCache.get(interfaceName);
         if (existingElanInterface.isPresent()) {
             StaticMacEntriesBuilder staticMacEntriesBuilder = new StaticMacEntriesBuilder();
@@ -360,8 +368,7 @@ public class ElanServiceProvider extends AbstractLifecycle implements IElanServi
     }
 
     @Override
-    public void deleteStaticMacAddress(String elanInstanceName, String interfaceName, String macAddress)
-            throws MacNotFoundException {
+    public void deleteStaticMacAddress(String interfaceName, String macAddress) {
         Optional<ElanInterface> existingElanInterface = elanInterfaceCache.get(interfaceName);
         if (existingElanInterface.isPresent()) {
             InstanceIdentifier<StaticMacEntries> staticMacEntriesIdentifier =
@@ -406,11 +413,7 @@ public class ElanServiceProvider extends AbstractLifecycle implements IElanServi
             if (elanInterfaceMac.getMacEntry() != null && elanInterfaceMac.getMacEntry().size() > 0) {
                 List<MacEntry> macEntries = elanInterfaceMac.getMacEntry();
                 for (MacEntry macEntry : macEntries) {
-                    try {
-                        deleteStaticMacAddress(elanInstanceName, elanInterface, macEntry.getMacAddress().getValue());
-                    } catch (MacNotFoundException e) {
-                        LOG.error("Mac Not Found Exception {}", e);
-                    }
+                    deleteStaticMacAddress(elanInterface, macEntry.getMacAddress().getValue());
                 }
             }
         }
@@ -418,6 +421,7 @@ public class ElanServiceProvider extends AbstractLifecycle implements IElanServi
     }
 
     @Override
+    @Nullable
     public ElanInstance getElanInstance(String elanName) {
         return elanInstanceCache.get(elanName).orNull();
     }
@@ -427,11 +431,11 @@ public class ElanServiceProvider extends AbstractLifecycle implements IElanServi
         InstanceIdentifier<ElanInstances> elanInstancesIdentifier = InstanceIdentifier.builder(ElanInstances.class)
                 .build();
         return ElanUtils.read(broker, LogicalDatastoreType.CONFIGURATION, elanInstancesIdentifier).toJavaUtil().map(
-                ElanInstances::getElanInstance).orElse(Collections.emptyList());
+                ElanInstances::getElanInstance).orElse(emptyList());
     }
 
     @Override
-    @Nonnull
+    @NonNull
     public List<String> getElanInterfaces(String elanInstanceName) {
         List<String> elanInterfaces = new ArrayList<>();
         InstanceIdentifier<ElanInterfaces> elanInterfacesIdentifier = InstanceIdentifier.builder(ElanInterfaces.class)
@@ -441,9 +445,9 @@ public class ElanServiceProvider extends AbstractLifecycle implements IElanServi
         if (!elanInterfacesOptional.isPresent()) {
             return elanInterfaces;
         }
-        List<ElanInterface> elanInterfaceList = elanInterfacesOptional.get().getElanInterface();
+        List<ElanInterface> elanInterfaceList = elanInterfacesOptional.get().nonnullElanInterface();
         for (ElanInterface elanInterface : elanInterfaceList) {
-            if (elanInterface.getElanInstanceName().equals(elanInstanceName)) {
+            if (Objects.equals(elanInterface.getElanInstanceName(), elanInstanceName)) {
                 elanInterfaces.add(elanInterface.getName());
             }
         }
@@ -516,7 +520,7 @@ public class ElanServiceProvider extends AbstractLifecycle implements IElanServi
         String intfName = providerIntfName + IfmConstants.OF_URI_SEPARATOR + elanInstance.getSegmentationId();
         Interface memberIntf = interfaceManager.getInterfaceInfoFromConfigDataStore(intfName);
         if (memberIntf != null) {
-            deleteElanInterface(elanInstance.getElanInstanceName(), intfName);
+            deleteElanInterface(intfName);
             deleteIetfInterface(intfName);
             LOG.debug("delete vlan prv intf {} in elan {}, dpID {}", intfName,
                     elanInstance.getElanInstanceName(), dpnId);
@@ -541,7 +545,7 @@ public class ElanServiceProvider extends AbstractLifecycle implements IElanServi
                 if (shouldDeleteTrunk(trunkInterfaceName, elanInterface)) {
                     deleteIetfInterface(trunkInterfaceName);
                 }
-                deleteElanInterface(elanInstanceName, elanInterface);
+                deleteElanInterface(elanInterface);
             }
         }
     }
@@ -659,6 +663,7 @@ public class ElanServiceProvider extends AbstractLifecycle implements IElanServi
     }
 
     @Override
+    @Nullable
     public ElanInterface getElanInterfaceByElanInterfaceName(String interfaceName) {
         return elanInterfaceCache.get(interfaceName).orNull();
     }
@@ -715,23 +720,6 @@ public class ElanServiceProvider extends AbstractLifecycle implements IElanServi
         elanUtils.removeDmacRedirectToDispatcherFlows(elanInstance.getElanTag(), macAddress, dpnsIdsForElanInstance);
     }
 
-    @Override
-    public List<MatchInfoBase> getEgressMatchesForElanInstance(String elanInstanceName) {
-        ElanInstance elanInstance = getElanInstance(elanInstanceName);
-        if (elanInstance == null) {
-            LOG.debug("No ELAN instance found for {}", elanInstanceName);
-            return Collections.emptyList();
-        }
-
-        Long elanTag = elanInstance.getElanTag();
-        if (elanTag == null) {
-            LOG.debug("No ELAN tag found for {}", elanInstanceName);
-            return Collections.emptyList();
-        }
-        return Collections.singletonList(
-                new NxMatchRegister(ElanConstants.ELAN_REG_ID, elanTag, MetaDataUtil.getElanMaskForReg()));
-    }
-
     /**
      * Create ietf-interfaces based on the ELAN segment type.<br>
      * For segment type flat - create transparent interface pointing to the
@@ -867,16 +855,19 @@ public class ElanServiceProvider extends AbstractLifecycle implements IElanServi
         ElanInstance elanInstance = elanIface.isPresent()
                 ? elanInstanceCache.get(elanIface.get().getElanInstanceName()).orNull() : null;
         if (elanInstance == null) {
-            LOG.debug("addArpResponderFlow: elanInstance is null, Failed to install arp responder flow for Interface {}"
-                      + " with MAC {} & IP {}", dpnId,
-                ingressInterfaceName, macAddress, ipAddress);
+            LOG.debug("addArpResponderFlow: elanInstance is null, Failed to install arp responder flow for dpnId {}"
+                    + "for Interface {} with MAC {} & IP {}", dpnId, ingressInterfaceName, macAddress, ipAddress);
             return;
         }
         String flowId = ArpResponderUtil.getFlowId(lportTag, ipAddress);
-        ArpResponderUtil.installFlow(mdsalManager, dpnId, flowId, flowId, NwConstants.DEFAULT_ARP_FLOW_PRIORITY,
+        Flow flowEntity =
+            MDSALUtil.buildFlowNew(NwConstants.ARP_RESPONDER_TABLE, flowId, NwConstants.DEFAULT_ARP_FLOW_PRIORITY,
+                flowId, 0, 0,
                 ArpResponderUtil.generateCookie(lportTag, ipAddress),
                 ArpResponderUtil.getMatchCriteria(lportTag, elanInstance, ipAddress),
                 arpResponderInput.getInstructions());
+        ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(Datastore.CONFIGURATION,
+            tx -> mdsalManager.addFlow(tx, dpnId, flowEntity)), LOG, "Error adding flow {}", flowEntity);
         LOG.info("Installed the ARP Responder flow for Interface {}", ingressInterfaceName);
     }
 
@@ -897,9 +888,14 @@ public class ElanServiceProvider extends AbstractLifecycle implements IElanServi
 
         int lportTag = arpResponderInput.getLportTag();
         String flowId = ArpResponderUtil.getFlowId(lportTag, ipAddress);
-        ArpResponderUtil.installFlow(mdsalManager, dpnId, flowId, flowId, NwConstants.DEFAULT_ARP_FLOW_PRIORITY,
-                ArpResponderUtil.generateCookie(lportTag, ipAddress), ArpResponderUtil.getMatchCriteria(lportTag,
-                        elanInstance, ipAddress), arpResponderInput.getInstructions());
+        Flow flowEntity =
+            MDSALUtil.buildFlowNew(NwConstants.ARP_RESPONDER_TABLE, flowId, NwConstants.DEFAULT_ARP_FLOW_PRIORITY,
+                flowId, 0, 0,
+                ArpResponderUtil.generateCookie(lportTag, ipAddress),
+                ArpResponderUtil.getMatchCriteria(lportTag, elanInstance, ipAddress),
+                arpResponderInput.getInstructions());
+        ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(Datastore.CONFIGURATION,
+            tx -> mdsalManager.addFlow(tx, dpnId, flowEntity)), LOG, "Error adding flow {}", flowEntity);
         LOG.trace("Installed the ExternalTunnel ARP Responder flow for ElanInstance {}", elanInstanceName);
     }