NETVIRT-1630 migrate to md-sal APIs
[netvirt.git] / fibmanager / impl / src / main / java / org / opendaylight / netvirt / fibmanager / BgpRouteVrfEntryHandler.java
index 4e786feaf3f34ec1f1624640cbd34414c5bd8eb1..758915fc89938601ea09cc6188b6f562945fbdd4 100644 (file)
@@ -9,22 +9,20 @@ package org.opendaylight.netvirt.fibmanager;
 
 import static java.util.stream.Collectors.toList;
 
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import java.math.BigInteger;
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.Collections;
 import java.util.List;
+import java.util.Optional;
 import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.LinkedBlockingQueue;
 import java.util.function.Consumer;
 import javax.annotation.PostConstruct;
 import javax.inject.Inject;
 import javax.inject.Singleton;
-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.eclipse.jdt.annotation.Nullable;
+import org.opendaylight.genius.datastoreutils.listeners.DataTreeEventCallbackRegistrar;
+import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
+import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
 import org.opendaylight.genius.mdsalutil.ActionInfo;
 import org.opendaylight.genius.mdsalutil.InstructionInfo;
 import org.opendaylight.genius.mdsalutil.NwConstants;
@@ -41,7 +39,12 @@ import org.opendaylight.genius.utils.batching.ActionableResourceImpl;
 import org.opendaylight.genius.utils.batching.ResourceBatchingManager;
 import org.opendaylight.genius.utils.batching.ResourceHandler;
 import org.opendaylight.genius.utils.batching.SubTransaction;
+import org.opendaylight.infrautils.utils.concurrent.ListenableFutures;
+import org.opendaylight.mdsal.binding.api.DataBroker;
+import org.opendaylight.mdsal.binding.api.WriteTransaction;
+import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
 import org.opendaylight.netvirt.vpnmanager.api.VpnExtraRouteHelper;
+import org.opendaylight.serviceutils.upgrade.UpgradeState;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeBase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeMplsOverGre;
@@ -55,19 +58,21 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.to.extraroutes.vpn.extra.routes.Routes;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.Uint32;
+import org.opendaylight.yangtools.yang.common.Uint64;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 
 @Singleton
-public class BgpRouteVrfEntryHandler extends BaseVrfEntryHandler
-        implements ResourceHandler, IVrfEntryHandler {
+public class BgpRouteVrfEntryHandler extends BaseVrfEntryHandler implements ResourceHandler {
 
     private static final Logger LOG = LoggerFactory.getLogger(BgpRouteVrfEntryHandler.class);
     private static final int BATCH_INTERVAL = 500;
     private static final int BATCH_SIZE = 1000;
 
     private final DataBroker dataBroker;
+    private final ManagedNewTransactionRunner txRunner;
     private final BlockingQueue<ActionableResource> vrfEntryBufferQ = new LinkedBlockingQueue<>();
     private final ResourceBatchingManager resourceBatchingManager;
     private final NexthopManager nexthopManager;
@@ -75,9 +80,12 @@ public class BgpRouteVrfEntryHandler extends BaseVrfEntryHandler
     @Inject
     public BgpRouteVrfEntryHandler(final DataBroker dataBroker,
                                    final NexthopManager nexthopManager,
-                                   final FibUtil fibUtil) {
-        super(dataBroker, nexthopManager, null, fibUtil);
+                                   final FibUtil fibUtil,
+                                   final UpgradeState upgradeState,
+                                   final DataTreeEventCallbackRegistrar eventCallbacks) {
+        super(dataBroker, nexthopManager, null, fibUtil, upgradeState, eventCallbacks);
         this.dataBroker = dataBroker;
+        this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
         this.nexthopManager = nexthopManager;
 
         resourceBatchingManager = ResourceBatchingManager.getInstance();
@@ -122,6 +130,11 @@ public class BgpRouteVrfEntryHandler extends BaseVrfEntryHandler
         }
     }
 
+    @Override
+    public void updateContainer(WriteTransaction tx, LogicalDatastoreType datastoreType, InstanceIdentifier identifier,
+                                Object original, Object update, List<SubTransaction> transactionObjects) {
+    }
+
     @Override
     public void create(WriteTransaction tx, LogicalDatastoreType datastoreType, InstanceIdentifier identifier,
                        Object vrfEntry, List<SubTransaction> subTxns) {
@@ -138,27 +151,24 @@ public class BgpRouteVrfEntryHandler extends BaseVrfEntryHandler
         }
     }
 
-    @Override
-    public void createFlows(InstanceIdentifier<VrfEntry> identifier, VrfEntry vrfEntry, String rd) {
-        ActionableResource actResource = new ActionableResourceImpl(rd + vrfEntry.getDestPrefix());
+    void createFlows(InstanceIdentifier<VrfEntry> identifier, VrfEntry vrfEntry, String rd) {
+        ActionableResourceImpl actResource = new ActionableResourceImpl(rd + vrfEntry.getDestPrefix());
         actResource.setAction(ActionableResource.CREATE);
         actResource.setInstanceIdentifier(identifier);
         actResource.setInstance(vrfEntry);
         vrfEntryBufferQ.add(actResource);
     }
 
-    @Override
-    public void removeFlows(InstanceIdentifier<VrfEntry> identifier, VrfEntry vrfEntry, String rd) {
-        ActionableResource actResource = new ActionableResourceImpl(rd + vrfEntry.getDestPrefix());
+    void removeFlows(InstanceIdentifier<VrfEntry> identifier, VrfEntry vrfEntry, String rd) {
+        ActionableResourceImpl actResource = new ActionableResourceImpl(rd + vrfEntry.getDestPrefix());
         actResource.setAction(ActionableResource.DELETE);
         actResource.setInstanceIdentifier(identifier);
         actResource.setInstance(vrfEntry);
         vrfEntryBufferQ.add(actResource);
     }
 
-    @Override
-    public void updateFlows(InstanceIdentifier<VrfEntry> identifier, VrfEntry original, VrfEntry update, String rd) {
-        ActionableResource actResource = new ActionableResourceImpl(rd + update.getDestPrefix());
+    void updateFlows(InstanceIdentifier<VrfEntry> identifier, VrfEntry original, VrfEntry update, String rd) {
+        ActionableResourceImpl actResource = new ActionableResourceImpl(rd + update.getDestPrefix());
         actResource.setAction(ActionableResource.UPDATE);
         actResource.setInstanceIdentifier(identifier);
         actResource.setInstance(update);
@@ -174,22 +184,27 @@ public class BgpRouteVrfEntryHandler extends BaseVrfEntryHandler
     private void createFibEntries(WriteTransaction writeTx, final InstanceIdentifier<VrfEntry> vrfEntryIid,
                                   final VrfEntry vrfEntry, List<SubTransaction> subTxns) {
         final VrfTablesKey vrfTableKey = vrfEntryIid.firstKeyOf(VrfTables.class);
-
+        LOG.trace("Creating fib entry for vrfEntry with destPrefix{}, rd {}",
+            vrfEntry.getDestPrefix(), vrfTableKey.getRouteDistinguisher());
         final VpnInstanceOpDataEntry vpnInstance =
                 getFibUtil().getVpnInstance(vrfTableKey.getRouteDistinguisher());
-        Preconditions.checkNotNull(vpnInstance, "Vpn Instance not available " + vrfTableKey.getRouteDistinguisher());
-        Preconditions.checkNotNull(vpnInstance.getVpnId(), "Vpn Instance with rd " + vpnInstance.getVrfId()
-                + " has null vpnId!");
-
+        if (vpnInstance == null || vpnInstance.getVpnId() == null) {
+            LOG.error("Vpn Instance not availabe {}", vrfTableKey.getRouteDistinguisher());
+            return;
+        }
         final Collection<VpnToDpnList> vpnToDpnList = vpnInstance.getVpnToDpnList();
         if (vpnToDpnList != null) {
             for (VpnToDpnList vpnDpn : vpnToDpnList) {
+                LOG.trace("Dpnstate is {} for dpn {} in vpn {}", vpnDpn.getDpnState(), vpnDpn.getDpnId(),
+                    vpnInstance.getVpnId());
                 if (vpnDpn.getDpnState() == VpnToDpnList.DpnState.Active) {
-                    createRemoteFibEntry(vpnDpn.getDpnId(), vpnInstance.getVpnId(), vrfTableKey.getRouteDistinguisher(),
-                            vrfEntry, writeTx, subTxns);
+                    createRemoteFibEntry(vpnDpn.getDpnId(), vpnInstance.getVpnId(),
+                            vrfTableKey.getRouteDistinguisher(), vrfEntry, writeTx, subTxns);
                 }
             }
         }
+        LOG.trace("Created fib entry for vrfEntry with destPrefix{}, rd {}",
+            vrfEntry.getDestPrefix(), vrfTableKey.getRouteDistinguisher());
     }
 
     /*
@@ -223,26 +238,30 @@ public class BgpRouteVrfEntryHandler extends BaseVrfEntryHandler
                             usedRds.get(0), vrfEntry.getDestPrefix());
                 }
             } else {
-                extraRouteOptional = Optional.absent();
+                extraRouteOptional = Optional.empty();
             }
             for (VpnToDpnList curDpn : vpnToDpnList) {
                 if (curDpn.getDpnState() == VpnToDpnList.DpnState.Active) {
-                    deleteRemoteRoute(BigInteger.ZERO, curDpn.getDpnId(), vpnInstance.getVpnId(),
+                    deleteRemoteRoute(Uint64.ZERO, curDpn.getDpnId(), vpnInstance.getVpnId(),
                             vrfTableKey, vrfEntry, extraRouteOptional, writeTx, subTxns);
                 }
             }
         }
     }
 
-    public void programRemoteFibForBgpRoutes(final BigInteger remoteDpnId,
-                                             final long vpnId,
+    public void programRemoteFibForBgpRoutes(final Uint64 remoteDpnId,
+                                             final Uint32 vpnId,
                                              final VrfEntry vrfEntry,
                                              WriteTransaction tx,
                                              String rd,
                                              List<NexthopManager.AdjacencyResult> adjacencyResults,
                                              List<SubTransaction> subTxns) {
-        Preconditions.checkArgument(vrfEntry.getRoutePaths().size() <= 2);
-
+        if (vrfEntry.nonnullRoutePaths().size() > 2) {
+            LOG.error("DC-GW can advertise only 2 bestPaths for prefix {}", vrfEntry.getDestPrefix());
+            return;
+        }
+        LOG.trace("Start programming remote fib for destPrefix {}, vpnId {}, dpnId {}",
+            vrfEntry.getDestPrefix(), vpnId, remoteDpnId);
         if (adjacencyResults.size() == 1) {
             programRemoteFib(remoteDpnId, vpnId, vrfEntry, tx, rd, adjacencyResults, subTxns);
             return;
@@ -250,7 +269,7 @@ public class BgpRouteVrfEntryHandler extends BaseVrfEntryHandler
         // ECMP Use case, point to LB group. Move the mpls label accordingly.
         List<String> tunnelList =
                 adjacencyResults.stream()
-                        .map(adjacencyResult -> adjacencyResult.getNextHopIp())
+                        .map(NexthopManager.AdjacencyResult::getNextHopIp)
                         .sorted().collect(toList());
         String lbGroupKey = FibUtil.getGreLbGroupKey(tunnelList);
         long groupId = nexthopManager.createNextHopPointer(lbGroupKey);
@@ -258,12 +277,12 @@ public class BgpRouteVrfEntryHandler extends BaseVrfEntryHandler
         List<ActionInfo> actionInfos = new ArrayList<>();
         for (NexthopManager.AdjacencyResult adjResult : adjacencyResults) {
             String nextHopIp = adjResult.getNextHopIp();
-            java.util.Optional<Long> optionalLabel = FibUtil.getLabelForNextHop(vrfEntry, nextHopIp);
+            java.util.Optional<Uint32> optionalLabel = FibUtil.getLabelForNextHop(vrfEntry, nextHopIp);
             if (!optionalLabel.isPresent()) {
                 LOG.warn("NextHopIp {} not found in vrfEntry {}", nextHopIp, vrfEntry);
                 continue;
             }
-            long label = optionalLabel.get();
+            long label = optionalLabel.get().toJava();
 
             actionInfos.add(new ActionRegLoad(index, FibConstants.NXM_REG_MAPPING.get(index++), 0,
                     31, label));
@@ -272,18 +291,23 @@ public class BgpRouteVrfEntryHandler extends BaseVrfEntryHandler
         actionInfos.add(new ActionGroup(index, groupId));
         instructions.add(new InstructionApplyActions(actionInfos));
         makeConnectedRoute(remoteDpnId, vpnId, vrfEntry, rd, instructions, NwConstants.ADD_FLOW, tx, subTxns);
+        LOG.trace("End programming remote fib for destPrefix {}, vpnId {}, dpnId {}",
+                vrfEntry.getDestPrefix(), vpnId, remoteDpnId);
     }
 
-    public void createRemoteFibEntry(final BigInteger remoteDpnId,
-                                     final long vpnId,
+    // Allow deprecated TransactionRunner calls for now
+    @SuppressWarnings("ForbidCertainMethod")
+    public void createRemoteFibEntry(final Uint64 remoteDpnId,
+                                     final Uint32 vpnId,
                                      final String rd,
                                      final VrfEntry vrfEntry,
                                      WriteTransaction tx,
                                      List<SubTransaction> subTxns) {
-        Boolean wrTxPresent = true;
         if (tx == null) {
-            wrTxPresent = false;
-            tx = dataBroker.newWriteOnlyTransaction();
+            ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(
+                newTx -> createRemoteFibEntry(remoteDpnId, vpnId, rd, vrfEntry, newTx, subTxns)), LOG,
+                "Error creating remote FIB entry");
+            return;
         }
 
         LOG.debug("createRemoteFibEntry: adding route {} for rd {} on remoteDpnId {}",
@@ -299,13 +323,10 @@ public class BgpRouteVrfEntryHandler extends BaseVrfEntryHandler
 
         programRemoteFibForBgpRoutes(remoteDpnId, vpnId, vrfEntry, tx, rd, adjacencyResults, subTxns);
 
-        if (!wrTxPresent) {
-            tx.submit();
-        }
         LOG.debug("Successfully added FIB entry for prefix {} in vpnId {}", vrfEntry.getDestPrefix(), vpnId);
     }
 
-    private void deleteFibEntryForBgpRoutes(BigInteger remoteDpnId, long vpnId, VrfEntry vrfEntry,
+    private void deleteFibEntryForBgpRoutes(Uint64 remoteDpnId, Uint32 vpnId, VrfEntry vrfEntry,
                                              String rd, WriteTransaction tx, List<SubTransaction> subTxns) {
         // When the tunnel is removed the fib entries should be reprogrammed/deleted depending on
         // the adjacencyResults.
@@ -315,26 +336,27 @@ public class BgpRouteVrfEntryHandler extends BaseVrfEntryHandler
         }
     }
 
-    public void deleteRemoteRoute(final BigInteger localDpnId, final BigInteger remoteDpnId,
-                                  final long vpnId, final VrfTablesKey vrfTableKey,
+    // Allow deprecated TransactionRunner calls for now
+    @SuppressWarnings("ForbidCertainMethod")
+    public void deleteRemoteRoute(@Nullable final Uint64 localDpnId, final Uint64 remoteDpnId,
+                                  final Uint32 vpnId, final VrfTablesKey vrfTableKey,
                                   final VrfEntry vrfEntry, Optional<Routes> extraRouteOptional,
-                                  WriteTransaction tx, List<SubTransaction> subTxns) {
-
-        Boolean wrTxPresent = true;
+                                  @Nullable WriteTransaction tx, List<SubTransaction> subTxns) {
         if (tx == null) {
-            wrTxPresent = false;
-            tx = dataBroker.newWriteOnlyTransaction();
+            ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(
+                newTx -> deleteRemoteRoute(localDpnId, remoteDpnId, vpnId, vrfTableKey, vrfEntry,
+                        extraRouteOptional, newTx)), LOG, "Error deleting remote route");
+            return;
         }
 
         LOG.debug("deleting remote route: prefix={}, vpnId={} localDpnId {} remoteDpnId {}",
                 vrfEntry.getDestPrefix(), vpnId, localDpnId, remoteDpnId);
         String rd = vrfTableKey.getRouteDistinguisher();
 
-        if (localDpnId != null && localDpnId != BigInteger.ZERO) {
+        if (localDpnId != null && !Uint64.ZERO.equals(localDpnId)) {
             // localDpnId is not known when clean up happens for last vm for a vpn on a dpn
             if (extraRouteOptional.isPresent()) {
-                nexthopManager.setupLoadBalancingNextHop(vpnId, remoteDpnId, vrfEntry.getDestPrefix(),
-                        Collections.emptyList() /*listBucketInfo*/ , false);
+                nexthopManager.deleteLoadBalancingNextHop(vpnId, remoteDpnId, vrfEntry.getDestPrefix());
             }
             deleteFibEntryForBgpRoutes(remoteDpnId, vpnId, vrfEntry, rd, tx, subTxns);
             return;
@@ -343,21 +365,17 @@ public class BgpRouteVrfEntryHandler extends BaseVrfEntryHandler
         // below two reads are kept as is, until best way is found to identify dpnID
         VpnNexthop localNextHopInfo = nexthopManager.getVpnNexthop(vpnId, vrfEntry.getDestPrefix());
         if (extraRouteOptional.isPresent()) {
-            nexthopManager.setupLoadBalancingNextHop(vpnId, remoteDpnId, vrfEntry.getDestPrefix(),
-                    Collections.emptyList()  /*listBucketInfo*/ , false);
+            nexthopManager.deleteLoadBalancingNextHop(vpnId, remoteDpnId, vrfEntry.getDestPrefix());
         } else {
             checkDpnDeleteFibEntry(localNextHopInfo, remoteDpnId, vpnId, vrfEntry, rd, tx, subTxns);
         }
-        if (!wrTxPresent) {
-            tx.submit();
-        }
     }
 
     public Consumer<? super VrfEntry> getConsumerForCreatingRemoteFib(
-            final BigInteger dpnId, final long vpnId, final String rd,
+            final Uint64 dpnId, final Uint32 vpnId, final String rd,
             final String remoteNextHopIp, final Optional<VrfTables> vrfTable,
             WriteTransaction writeCfgTxn, List<SubTransaction> subTxns) {
-        return vrfEntry -> vrfEntry.getRoutePaths().stream()
+        return vrfEntry -> vrfEntry.nonnullRoutePaths().stream()
                 .filter(routes -> !routes.getNexthopAddress().isEmpty()
                         && remoteNextHopIp.trim().equals(routes.getNexthopAddress().trim()))
                 .findFirst()
@@ -370,45 +388,44 @@ public class BgpRouteVrfEntryHandler extends BaseVrfEntryHandler
     }
 
     public Consumer<? super VrfEntry> getConsumerForDeletingRemoteFib(
-            final BigInteger dpnId, final long vpnId,
+            final Uint64 dpnId, final Uint32 vpnId,
             final String remoteNextHopIp, final Optional<VrfTables> vrfTable,
             WriteTransaction writeCfgTxn, List<SubTransaction> subTxns) {
-        return vrfEntry -> vrfEntry.getRoutePaths().stream()
+        return vrfEntry -> vrfEntry.nonnullRoutePaths().stream()
                 .filter(routes -> !routes.getNexthopAddress().isEmpty()
                         && remoteNextHopIp.trim().equals(routes.getNexthopAddress().trim()))
                 .findFirst()
                 .ifPresent(routes -> {
                     LOG.trace(" deleting remote FIB entry {}", vrfEntry);
-                    deleteRemoteRoute(null, dpnId, vpnId, vrfTable.get().getKey(), vrfEntry,
-                            Optional.absent(), writeCfgTxn, subTxns);
+                    deleteRemoteRoute(null, dpnId, vpnId, vrfTable.get().key(), vrfEntry,
+                            Optional.empty(), writeCfgTxn, subTxns);
                 });
     }
 
     @Override
-    protected void addTunnelInterfaceActions(NexthopManager.AdjacencyResult adjacencyResult, long vpnId,
+    protected void addTunnelInterfaceActions(NexthopManager.AdjacencyResult adjacencyResult, Uint32 vpnId,
             VrfEntry vrfEntry, List<ActionInfo> actionInfos, String rd) {
-        Class<? extends TunnelTypeBase> tunnelType =
-                VpnExtraRouteHelper.getTunnelType(getNextHopManager().getInterfaceManager(),
-                        adjacencyResult.getInterfaceName());
+        Class<? extends TunnelTypeBase> tunnelType = VpnExtraRouteHelper
+                .getTunnelType(getNextHopManager().getItmManager(), adjacencyResult.getInterfaceName());
         if (tunnelType == null) {
             LOG.debug("Tunnel type not found for vrfEntry {}", vrfEntry);
             return;
         }
         String nextHopIp = adjacencyResult.getNextHopIp();
         if (tunnelType.equals(TunnelTypeMplsOverGre.class)) {
-            java.util.Optional<Long> optionalLabel = FibUtil.getLabelForNextHop(vrfEntry, nextHopIp);
+            java.util.Optional<Uint32> optionalLabel = FibUtil.getLabelForNextHop(vrfEntry, nextHopIp);
             if (!optionalLabel.isPresent()) {
                 LOG.warn("NextHopIp {} not found in vrfEntry {}", nextHopIp, vrfEntry);
                 return;
             }
-            long label = optionalLabel.get();
+            long label = optionalLabel.get().toJava();
             LOG.debug("addTunnelInterfaceActions: Push label action for prefix {} rd {} l3vni {} nextHop {}",
                     vrfEntry.getDestPrefix(), rd, vrfEntry.getL3vni(), nextHopIp);
             actionInfos.add(new ActionPushMpls());
             actionInfos.add(new ActionSetFieldMplsLabel(label));
-            actionInfos.add(new ActionNxLoadInPort(BigInteger.ZERO));
+            actionInfos.add(new ActionNxLoadInPort(Uint64.ZERO));
         } else if (tunnelType.equals(TunnelTypeVxlan.class)) {
-            actionInfos.add(new ActionSetFieldTunnelId(BigInteger.valueOf(vrfEntry.getL3vni())));
+            actionInfos.add(new ActionSetFieldTunnelId(Uint64.valueOf(vrfEntry.getL3vni().longValue())));
             LOG.debug("addTunnelInterfaceActions: adding set tunnel id action for prefix {} rd {} l3vni {}"
                     + " nextHop {} ", vrfEntry.getDestPrefix(), rd, vrfEntry.getL3vni(), nextHopIp);
             addRewriteDstMacAction(vpnId, vrfEntry, null /*prefixInfo*/, actionInfos);
@@ -416,8 +433,8 @@ public class BgpRouteVrfEntryHandler extends BaseVrfEntryHandler
     }
 
     @Override
-    protected void addRewriteDstMacAction(long vpnId, VrfEntry vrfEntry, Prefixes prefixInfo,
-                                        List<ActionInfo> actionInfos) {
+    protected void addRewriteDstMacAction(Uint32 vpnId, VrfEntry vrfEntry, @Nullable Prefixes prefixInfo,
+                                          List<ActionInfo> actionInfos) {
         if (vrfEntry.getGatewayMacAddress() != null) {
             actionInfos.add(new ActionSetFieldEthernetDestination(actionInfos.size(),
                     new MacAddress(vrfEntry.getGatewayMacAddress())));