2 * Copyright (c) 2017 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
9 package org.opendaylight.netvirt.natservice.internal;
11 import static org.opendaylight.controller.md.sal.binding.api.WriteTransaction.CREATE_MISSING_PARENTS;
12 import static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
13 import static org.opendaylight.genius.infra.Datastore.OPERATIONAL;
14 import static org.opendaylight.netvirt.natservice.internal.NatUtil.requireNonNullElse;
16 import com.google.common.base.Optional;
17 import com.google.common.util.concurrent.FutureCallback;
18 import com.google.common.util.concurrent.Futures;
19 import com.google.common.util.concurrent.ListenableFuture;
20 import com.google.common.util.concurrent.MoreExecutors;
21 import java.math.BigInteger;
22 import java.util.ArrayList;
23 import java.util.Collections;
24 import java.util.List;
25 import java.util.concurrent.ExecutionException;
26 import javax.annotation.Nonnull;
27 import javax.inject.Inject;
28 import javax.inject.Singleton;
29 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
30 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
31 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
32 import org.opendaylight.genius.infra.Datastore.Configuration;
33 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
34 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
35 import org.opendaylight.genius.infra.TypedReadWriteTransaction;
36 import org.opendaylight.genius.infra.TypedWriteTransaction;
37 import org.opendaylight.genius.mdsalutil.ActionInfo;
38 import org.opendaylight.genius.mdsalutil.MDSALUtil;
39 import org.opendaylight.genius.mdsalutil.MatchInfo;
40 import org.opendaylight.genius.mdsalutil.NwConstants;
41 import org.opendaylight.genius.mdsalutil.actions.ActionNxResubmit;
42 import org.opendaylight.genius.mdsalutil.actions.ActionSetFieldEthernetDestination;
43 import org.opendaylight.genius.mdsalutil.instructions.InstructionApplyActions;
44 import org.opendaylight.genius.mdsalutil.instructions.InstructionGotoTable;
45 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
46 import org.opendaylight.genius.mdsalutil.matches.MatchTunnelId;
47 import org.opendaylight.infrautils.utils.concurrent.ListenableFutures;
48 import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
49 import org.opendaylight.netvirt.fibmanager.api.IFibManager;
50 import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
51 import org.opendaylight.netvirt.vpnmanager.api.IVpnManager;
52 import org.opendaylight.netvirt.vpnmanager.api.VpnHelper;
53 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
54 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceBuilder;
55 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.vpn._interface.VpnInstanceNames;
56 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
57 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.CreateFibEntryInput;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.CreateFibEntryInputBuilder;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.CreateFibEntryOutput;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.FibRpcService;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.RemoveFibEntryInput;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.RemoveFibEntryInputBuilder;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.RemoveFibEntryOutput;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.Adjacencies;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AdjacenciesOp;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AdjacenciesOpBuilder;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn._interface.op.data.VpnInterfaceOpDataEntry;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn._interface.op.data.VpnInterfaceOpDataEntryBuilder;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn._interface.op.data.VpnInterfaceOpDataEntryKey;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap;
75 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
76 import org.opendaylight.yangtools.yang.common.RpcResult;
77 import org.slf4j.Logger;
78 import org.slf4j.LoggerFactory;
81 public class EvpnDnatFlowProgrammer {
82 private static final Logger LOG = LoggerFactory.getLogger(EvpnDnatFlowProgrammer.class);
84 private static final BigInteger COOKIE_TUNNEL = new BigInteger("9000000", 16);
86 private final DataBroker dataBroker;
87 private final ManagedNewTransactionRunner txRunner;
88 private final IMdsalApiManager mdsalManager;
89 private final IBgpManager bgpManager;
90 private final IFibManager fibManager;
91 private final FibRpcService fibService;
92 private final IVpnManager vpnManager;
93 private final NatOverVxlanUtil natOverVxlanUtil;
96 public EvpnDnatFlowProgrammer(final DataBroker dataBroker, final IMdsalApiManager mdsalManager,
97 final IBgpManager bgpManager,
98 final IFibManager fibManager,
99 final FibRpcService fibService,
100 final IVpnManager vpnManager,
101 final NatOverVxlanUtil natOverVxlanUtil) {
102 this.dataBroker = dataBroker;
103 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
104 this.mdsalManager = mdsalManager;
105 this.bgpManager = bgpManager;
106 this.fibManager = fibManager;
107 this.fibService = fibService;
108 this.vpnManager = vpnManager;
109 this.natOverVxlanUtil = natOverVxlanUtil;
112 public void onAddFloatingIp(final BigInteger dpnId, final String routerName, final long routerId,
113 final String vpnName,
114 final String internalIp, final String externalIp, final Uuid networkId,
115 final String interfaceName,
116 final String floatingIpInterface,
117 final String floatingIpPortMacAddress,
119 final String nextHopIp, final TypedReadWriteTransaction<Configuration> confTx) {
121 * 1) Install the flow INTERNAL_TUNNEL_TABLE (table=36)-> PDNAT_TABLE (table=25) (SNAT VM on DPN1 is
122 * responding back to FIP VM on DPN2) {SNAT to DNAT traffic on different Hypervisor}
124 * 2) Install the flow L3_FIB_TABLE (table=21)-> PDNAT_TABLE (table=25) (FIP VM1 to FIP VM2
125 * Traffic on Same Hypervisor) {DNAT to DNAT on Same Hypervisor}
127 * 3) Install the flow L3_GW_MAC_TABLE (table=19)-> PDNAT_TABLE (table=25)
128 * (DC-GW is responding back to FIP VM) {DNAT Reverse traffic})
131 long vpnId = NatUtil.getVpnId(dataBroker, vpnName);
132 if (vpnId == NatConstants.INVALID_ID) {
133 LOG.error("onAddFloatingIp : Invalid Vpn Id is found for Vpn Name {}", vpnName);
136 long l3Vni = NatEvpnUtil.getL3Vni(dataBroker, rd);
137 if (l3Vni == NatConstants.DEFAULT_L3VNI_VALUE) {
138 LOG.debug("onAddFloatingIp : L3VNI value is not configured in Internet VPN {} and RD {} "
139 + "Carve-out L3VNI value from OpenDaylight VXLAN VNI Pool and continue with installing "
140 + "DNAT flows for FloatingIp {}", vpnName, rd, externalIp);
141 l3Vni = natOverVxlanUtil.getInternetVpnVni(vpnName, routerId).longValue();
143 FloatingIPListener.updateOperationalDS(dataBroker, routerName, interfaceName, NatConstants.DEFAULT_LABEL_VALUE,
144 internalIp, externalIp);
145 String fibExternalIp = NatUtil.validateAndAddNetworkMask(externalIp);
146 //Inform to FIB and BGP
147 NatEvpnUtil.addRoutesForVxLanProvType(dataBroker, bgpManager, fibManager, vpnName, rd, fibExternalIp,
148 nextHopIp, l3Vni, floatingIpInterface, floatingIpPortMacAddress,
149 confTx, RouteOrigin.STATIC, dpnId, networkId);
151 /* Install the flow table L3_FIB_TABLE (table=21)-> PDNAT_TABLE (table=25)
152 * (SNAT to DNAT reverse traffic: If the DPN has both SNAT and DNAT configured )
154 List<ActionInfo> actionInfoFib = new ArrayList<>();
155 actionInfoFib.add(new ActionSetFieldEthernetDestination(new MacAddress(floatingIpPortMacAddress)));
156 List<Instruction> instructionsFib = new ArrayList<>();
157 instructionsFib.add(new InstructionApplyActions(actionInfoFib).buildInstruction(0));
158 instructionsFib.add(new InstructionGotoTable(NwConstants.PDNAT_TABLE).buildInstruction(1));
160 CreateFibEntryInput input = new CreateFibEntryInputBuilder().setVpnName(vpnName)
161 .setSourceDpid(dpnId).setIpAddress(fibExternalIp)
162 .setServiceId(l3Vni).setIpAddressSource(CreateFibEntryInput.IpAddressSource.FloatingIP)
163 .setInstruction(instructionsFib).build();
165 ListenableFuture<RpcResult<CreateFibEntryOutput>> futureVxlan = fibService.createFibEntry(input);
166 LOG.debug("onAddFloatingIp : Add Floating Ip {} , found associated to fixed port {}",
167 externalIp, interfaceName);
168 if (floatingIpPortMacAddress != null) {
169 ListenableFutures.addErrorLogging(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, tx -> {
170 vpnManager.addSubnetMacIntoVpnInstance(vpnName, null, floatingIpPortMacAddress, dpnId, tx);
171 vpnManager.addArpResponderFlowsToExternalNetworkIps(routerName,
172 Collections.singleton(externalIp),
173 floatingIpPortMacAddress, dpnId, networkId);
174 }), LOG, "Error processing floating IP port with MAC address {}", floatingIpPortMacAddress);
176 final long finalL3Vni = l3Vni;
177 Futures.addCallback(futureVxlan, new FutureCallback<RpcResult<CreateFibEntryOutput>>() {
180 public void onFailure(@Nonnull Throwable error) {
181 LOG.error("onAddFloatingIp : Error {} in custom fib routes install process for Floating "
182 + "IP Prefix {} on DPN {}", error, externalIp, dpnId);
186 public void onSuccess(@Nonnull RpcResult<CreateFibEntryOutput> result) {
187 if (result.isSuccessful()) {
188 ListenableFutures.addErrorLogging(
189 txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, innerConfTx -> {
190 LOG.info("onAddFloatingIp : Successfully installed custom FIB routes for Floating "
191 + "IP Prefix {} on DPN {}", externalIp, dpnId);
192 List<Instruction> instructions = new ArrayList<>();
193 List<ActionInfo> actionsInfos = new ArrayList<>();
194 List<Instruction> customInstructions = new ArrayList<>();
195 customInstructions.add(
196 new InstructionGotoTable(NwConstants.PDNAT_TABLE).buildInstruction(0));
197 actionsInfos.add(new ActionNxResubmit(NwConstants.PDNAT_TABLE));
198 instructions.add(new InstructionApplyActions(actionsInfos).buildInstruction(0));
199 /* If more than one floatingIp is available in vpn-to-dpn-list for given dpn id, do not
201 * installing INTERNAL_TUNNEL_TABLE (table=36) -> PDNAT_TABLE (table=25) flow entry with
205 if (!NatUtil.isFloatingIpPresentForDpn(dataBroker, dpnId, rd, vpnName, externalIp, true)) {
206 makeTunnelTableEntry(dpnId, finalL3Vni, instructions, innerConfTx);
208 /* Install the flow L3_GW_MAC_TABLE (table=19)-> PDNAT_TABLE (table=25)
209 * (DNAT reverse traffic: If the traffic is Initiated from DC-GW to FIP VM (DNAT forward
212 NatEvpnUtil.makeL3GwMacTableEntry(dpnId, vpnId, floatingIpPortMacAddress,
214 mdsalManager, innerConfTx);
215 }), LOG, "Error installing DNAT flows");
217 LOG.error("onAddFloatingIp : Error {} in rpc call to create custom Fib entries for Floating "
218 + "IP Prefix {} on DPN {}", result.getErrors(), externalIp, dpnId);
221 }, MoreExecutors.directExecutor());
223 //Read the FIP vpn-interface details from Configuration l3vpn:vpn-interfaces model and write into Operational DS
224 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NatUtil.getVpnInterfaceIdentifier(floatingIpInterface);
225 Optional<VpnInterface> optionalVpnInterface =
226 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
227 LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier);
228 if (optionalVpnInterface.isPresent()) {
229 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL, tx -> {
230 for (VpnInstanceNames vpnInstance : requireNonNullElse(optionalVpnInterface.get().getVpnInstanceNames(),
231 Collections.<VpnInstanceNames>emptyList())) {
232 if (!vpnName.equals(vpnInstance.getVpnName())) {
235 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get());
236 Adjacencies adjs = vpnIfBuilder.augmentation(Adjacencies.class);
237 VpnInterfaceOpDataEntryBuilder vpnIfOpDataEntryBuilder = new VpnInterfaceOpDataEntryBuilder();
238 vpnIfOpDataEntryBuilder.withKey(new VpnInterfaceOpDataEntryKey(interfaceName, vpnName));
240 List<Adjacency> adjacencyList =
241 adjs != null && adjs.getAdjacency() != null ? adjs.getAdjacency() : new ArrayList<>();
242 List<Adjacency> adjacencyListToImport = new ArrayList<>();
243 for (Adjacency adj : adjacencyList) {
244 Subnetmap sn = VpnHelper.getSubnetmapFromItsUuid(dataBroker, adj.getSubnetId());
245 if (!VpnHelper.isSubnetPartOfVpn(sn, vpnName)) {
248 adjacencyListToImport.add(adj);
250 AdjacenciesOp adjacenciesOp = new AdjacenciesOpBuilder()
251 .setAdjacency(adjacencyListToImport).build();
252 vpnIfOpDataEntryBuilder.addAugmentation(AdjacenciesOp.class, adjacenciesOp);
254 LOG.debug("onAddFloatingIp : Add vpnInterface {} to Operational l3vpn:vpn-interfaces-op-data ",
255 floatingIpInterface);
256 InstanceIdentifier<VpnInterfaceOpDataEntry> vpnIfIdentifierOpDataEntry =
257 NatUtil.getVpnInterfaceOpDataEntryIdentifier(interfaceName, vpnName);
258 tx.put(vpnIfIdentifierOpDataEntry, vpnIfOpDataEntryBuilder.build(), CREATE_MISSING_PARENTS);
261 }), LOG, "onAddFloatingIp : Could not write Interface {}, vpnName {}", interfaceName, vpnName);
263 LOG.debug("onAddFloatingIp : No vpnInterface {} found in Configuration l3vpn:vpn-interfaces ",
264 floatingIpInterface);
268 public void onRemoveFloatingIp(final BigInteger dpnId, final String vpnName, final String externalIp,
269 final String floatingIpInterface, final String floatingIpPortMacAddress,
270 final long routerId, TypedReadWriteTransaction<Configuration> confTx) {
272 * 1) Remove the flow INTERNAL_TUNNEL_TABLE (table=36)-> PDNAT_TABLE (table=25) (SNAT VM on DPN1 is
273 * responding back to FIP VM on DPN2) {SNAT to DNAT traffic on different Hypervisor}
275 * 2) Remove the flow L3_FIB_TABLE (table=21)-> PDNAT_TABLE (table=25) (FIP VM1 to FIP VM2
276 * Traffic on Same Hypervisor) {DNAT to DNAT on Same Hypervisor}
278 * 3) Remove the flow L3_GW_MAC_TABLE (table=19)-> PDNAT_TABLE (table=25)
279 * (DC-GW is responding back to FIP VM) {DNAT Reverse traffic})
282 String rd = NatUtil.getVpnRd(dataBroker, vpnName);
284 LOG.error("onRemoveFloatingIp : Could not retrieve RD value from VPN Name {} ", vpnName);
287 long vpnId = NatUtil.getVpnId(dataBroker, vpnName);
288 if (vpnId == NatConstants.INVALID_ID) {
289 LOG.error("onRemoveFloatingIp : Invalid Vpn Id is found for Vpn Name {}", vpnName);
292 long l3Vni = NatEvpnUtil.getL3Vni(dataBroker, rd);
293 if (l3Vni == NatConstants.DEFAULT_L3VNI_VALUE) {
294 LOG.debug("onRemoveFloatingIp : L3VNI value is not configured in Internet VPN {} and RD {} "
295 + "Carve-out L3VNI value from OpenDaylight VXLAN VNI Pool and continue with installing "
296 + "DNAT flows for FloatingIp {}", vpnName, rd, externalIp);
297 l3Vni = natOverVxlanUtil.getInternetVpnVni(vpnName, routerId).longValue();
299 String fibExternalIp = NatUtil.validateAndAddNetworkMask(externalIp);
301 //Remove Prefix from BGP
302 NatUtil.removePrefixFromBGP(bgpManager, fibManager, rd, fibExternalIp, vpnName, LOG);
304 //Remove custom FIB routes flow for L3_FIB_TABLE (table=21)-> PDNAT_TABLE (table=25)
305 RemoveFibEntryInput input = new RemoveFibEntryInputBuilder().setVpnName(vpnName)
306 .setSourceDpid(dpnId).setIpAddress(fibExternalIp).setServiceId(l3Vni)
307 .setIpAddressSource(RemoveFibEntryInput.IpAddressSource.FloatingIP).build();
308 ListenableFuture<RpcResult<RemoveFibEntryOutput>> futureVxlan = fibService.removeFibEntry(input);
309 final long finalL3Vni = l3Vni;
310 Futures.addCallback(futureVxlan, new FutureCallback<RpcResult<RemoveFibEntryOutput>>() {
313 public void onFailure(@Nonnull Throwable error) {
314 LOG.error("onRemoveFloatingIp : Error {} in custom fib routes remove process for Floating "
315 + "IP Prefix {} on DPN {}", error, externalIp, dpnId);
319 public void onSuccess(@Nonnull RpcResult<RemoveFibEntryOutput> result) {
320 if (result.isSuccessful()) {
321 ListenableFutures.addErrorLogging(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION,
323 LOG.info("onRemoveFloatingIp : Successfully removed custom FIB routes for Floating "
324 + "IP Prefix {} on DPN {}", externalIp, dpnId);
325 /* check if any floating IP information is available in vpn-to-dpn-list for given dpn id.
326 * If exist any floating IP then do not remove
327 * INTERNAL_TUNNEL_TABLE (table=36) -> PDNAT_TABLE (table=25) flow entry.
329 if (!NatUtil.isFloatingIpPresentForDpn(dataBroker, dpnId, rd, vpnName, externalIp, false)) {
330 //Remove the flow for INTERNAL_TUNNEL_TABLE (table=36)-> PDNAT_TABLE (table=25)
331 removeTunnelTableEntry(dpnId, finalL3Vni, innerConfTx);
333 //Remove the flow for L3_GW_MAC_TABLE (table=19)-> PDNAT_TABLE (table=25)
334 NatEvpnUtil.removeL3GwMacTableEntry(dpnId, vpnId, floatingIpPortMacAddress, mdsalManager,
336 }), LOG, "Error removing flows");
338 LOG.error("onRemoveFloatingIp : Error {} in rpc call to remove custom Fib entries for Floating "
339 + "IP Prefix {} on DPN {}", result.getErrors(), externalIp, dpnId);
342 }, MoreExecutors.directExecutor());
343 //Read the FIP vpn-interface details from Operational l3vpn:vpn-interfaces model and delete from Operational DS
344 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NatUtil.getVpnInterfaceIdentifier(floatingIpInterface);
345 Optional<VpnInterface> optionalVpnInterface =
346 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
347 LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier);
348 if (optionalVpnInterface.isPresent()) {
349 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL, tx -> {
350 for (VpnInstanceNames vpnInstance : requireNonNullElse(optionalVpnInterface.get().getVpnInstanceNames(),
351 Collections.<VpnInstanceNames>emptyList())) {
352 if (!vpnName.equals(vpnInstance.getVpnName())) {
355 InstanceIdentifier<VpnInterfaceOpDataEntry> vpnOpIfIdentifier = NatUtil
356 .getVpnInterfaceOpDataEntryIdentifier(floatingIpInterface, vpnName);
357 tx.delete(vpnOpIfIdentifier);
360 }), LOG, "onRemoveFloatingIp : Could not remove vpnInterface {}, vpnName {} from Operational "
361 + "odl-l3vpn:vpn-interface-op-data", floatingIpInterface, vpnName);
363 LOG.debug("onRemoveFloatingIp : Remove vpnInterface {} vpnName {} "
364 + "to Operational odl-l3vpn:vpn-interface-op-data", floatingIpInterface, vpnName);
366 LOG.debug("onRemoveFloatingIp : No vpnInterface {} found "
367 + "in Operational odl-l3vpn:vpn-interface-op-data", floatingIpInterface);
371 private void makeTunnelTableEntry(BigInteger dpnId, long l3Vni, List<Instruction> customInstructions,
372 TypedWriteTransaction<Configuration> confTx) {
373 LOG.debug("makeTunnelTableEntry : Create terminating service table {} --> table {} flow on DpnId {} "
374 + "with l3Vni {} as matching parameter", NwConstants.INTERNAL_TUNNEL_TABLE, NwConstants.PDNAT_TABLE,
376 List<MatchInfo> mkMatches = new ArrayList<>();
377 mkMatches.add(new MatchTunnelId(BigInteger.valueOf(l3Vni)));
378 Flow terminatingServiceTableFlowEntity = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE,
379 NatEvpnUtil.getFlowRef(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, l3Vni, NatConstants.DNAT_FLOW_NAME), 6,
380 String.format("%s:%d", "TST Flow Entry ", l3Vni),
381 0, 0, COOKIE_TUNNEL.add(BigInteger.valueOf(l3Vni)), mkMatches, customInstructions);
382 mdsalManager.addFlow(confTx, dpnId, terminatingServiceTableFlowEntity);
383 LOG.debug("makeTunnelTableEntry : Successfully installed terminating service table flow {} on DpnId {}",
384 terminatingServiceTableFlowEntity, dpnId);
387 private void removeTunnelTableEntry(BigInteger dpnId, long l3Vni, TypedReadWriteTransaction<Configuration> confTx)
388 throws ExecutionException, InterruptedException {
389 LOG.debug("removeTunnelTableEntry : Remove terminating service table {} --> table {} flow on DpnId {} "
390 + "with l3Vni {} as matching parameter", NwConstants.INTERNAL_TUNNEL_TABLE, NwConstants.PDNAT_TABLE,
392 List<MatchInfo> mkMatches = new ArrayList<>();
393 mkMatches.add(new MatchTunnelId(BigInteger.valueOf(l3Vni)));
394 Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE,
395 NatEvpnUtil.getFlowRef(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, l3Vni, NatConstants.DNAT_FLOW_NAME),
396 6, String.format("%s:%d", "TST Flow Entry ", l3Vni), 0, 0,
397 COOKIE_TUNNEL.add(BigInteger.valueOf(l3Vni)), mkMatches, null);
398 mdsalManager.removeFlow(confTx, dpnId, flowEntity);
399 LOG.debug("removeTunnelTableEntry : Successfully removed terminating service table flow {} on DpnId {}",