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 com.google.common.base.Optional;
12 import com.google.common.util.concurrent.FutureCallback;
13 import com.google.common.util.concurrent.Futures;
14 import com.google.common.util.concurrent.ListenableFuture;
15 import com.google.common.util.concurrent.MoreExecutors;
16 import java.math.BigInteger;
17 import java.util.ArrayList;
18 import java.util.Collections;
19 import java.util.List;
20 import javax.annotation.Nonnull;
21 import javax.inject.Inject;
22 import javax.inject.Singleton;
23 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
24 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
25 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
26 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
27 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
28 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
29 import org.opendaylight.genius.mdsalutil.ActionInfo;
30 import org.opendaylight.genius.mdsalutil.MDSALUtil;
31 import org.opendaylight.genius.mdsalutil.MatchInfo;
32 import org.opendaylight.genius.mdsalutil.NwConstants;
33 import org.opendaylight.genius.mdsalutil.actions.ActionNxResubmit;
34 import org.opendaylight.genius.mdsalutil.actions.ActionSetFieldEthernetDestination;
35 import org.opendaylight.genius.mdsalutil.instructions.InstructionApplyActions;
36 import org.opendaylight.genius.mdsalutil.instructions.InstructionGotoTable;
37 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
38 import org.opendaylight.genius.mdsalutil.matches.MatchTunnelId;
39 import org.opendaylight.infrautils.utils.concurrent.ListenableFutures;
40 import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
41 import org.opendaylight.netvirt.fibmanager.api.IFibManager;
42 import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
43 import org.opendaylight.netvirt.vpnmanager.api.IVpnManager;
44 import org.opendaylight.netvirt.vpnmanager.api.VpnHelper;
45 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
46 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceBuilder;
47 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.vpn._interface.VpnInstanceNames;
48 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
49 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.CreateFibEntryInput;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.CreateFibEntryInputBuilder;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.CreateFibEntryOutput;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.FibRpcService;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.RemoveFibEntryInput;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.RemoveFibEntryInputBuilder;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.RemoveFibEntryOutput;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.Adjacencies;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AdjacenciesOp;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AdjacenciesOpBuilder;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn._interface.op.data.VpnInterfaceOpDataEntry;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn._interface.op.data.VpnInterfaceOpDataEntryBuilder;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn._interface.op.data.VpnInterfaceOpDataEntryKey;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap;
68 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
69 import org.opendaylight.yangtools.yang.common.RpcResult;
70 import org.slf4j.Logger;
71 import org.slf4j.LoggerFactory;
74 public class EvpnDnatFlowProgrammer {
75 private static final Logger LOG = LoggerFactory.getLogger(EvpnDnatFlowProgrammer.class);
77 private static final BigInteger COOKIE_TUNNEL = new BigInteger("9000000", 16);
79 private final DataBroker dataBroker;
80 private final ManagedNewTransactionRunner txRunner;
81 private final IMdsalApiManager mdsalManager;
82 private final IBgpManager bgpManager;
83 private final IFibManager fibManager;
84 private final FibRpcService fibService;
85 private final IVpnManager vpnManager;
86 private final IdManagerService idManager;
89 public EvpnDnatFlowProgrammer(final DataBroker dataBroker, final IMdsalApiManager mdsalManager,
90 final IBgpManager bgpManager,
91 final IFibManager fibManager,
92 final FibRpcService fibService,
93 final IVpnManager vpnManager,
94 final IdManagerService idManager) {
95 this.dataBroker = dataBroker;
96 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
97 this.mdsalManager = mdsalManager;
98 this.bgpManager = bgpManager;
99 this.fibManager = fibManager;
100 this.fibService = fibService;
101 this.vpnManager = vpnManager;
102 this.idManager = idManager;
105 public void onAddFloatingIp(final BigInteger dpnId, final String routerName, final long routerId,
106 final String vpnName,
107 final String internalIp, final String externalIp, final Uuid networkId,
108 final String interfaceName,
109 final String floatingIpInterface,
110 final String floatingIpPortMacAddress,
112 final String nextHopIp, final WriteTransaction writeFlowInvTx) {
114 * 1) Install the flow INTERNAL_TUNNEL_TABLE (table=36)-> PDNAT_TABLE (table=25) (SNAT VM on DPN1 is
115 * responding back to FIP VM on DPN2) {SNAT to DNAT traffic on different Hypervisor}
117 * 2) Install the flow L3_FIB_TABLE (table=21)-> PDNAT_TABLE (table=25) (FIP VM1 to FIP VM2
118 * Traffic on Same Hypervisor) {DNAT to DNAT on Same Hypervisor}
120 * 3) Install the flow L3_GW_MAC_TABLE (table=19)-> PDNAT_TABLE (table=25)
121 * (DC-GW is responding back to FIP VM) {DNAT Reverse traffic})
124 long vpnId = NatUtil.getVpnId(dataBroker, vpnName);
125 if (vpnId == NatConstants.INVALID_ID) {
126 LOG.error("onAddFloatingIp : Invalid Vpn Id is found for Vpn Name {}", vpnName);
129 long l3Vni = NatEvpnUtil.getL3Vni(dataBroker, rd);
130 if (l3Vni == NatConstants.DEFAULT_L3VNI_VALUE) {
131 LOG.debug("onAddFloatingIp : L3VNI value is not configured in Internet VPN {} and RD {} "
132 + "Carve-out L3VNI value from OpenDaylight VXLAN VNI Pool and continue with installing "
133 + "DNAT flows for FloatingIp {}", vpnName, rd, externalIp);
134 l3Vni = NatOverVxlanUtil.getInternetVpnVni(idManager, vpnName, routerId).longValue();
136 FloatingIPListener.updateOperationalDS(dataBroker, routerName, interfaceName, NatConstants.DEFAULT_LABEL_VALUE,
137 internalIp, externalIp);
138 String fibExternalIp = NatUtil.validateAndAddNetworkMask(externalIp);
139 //Inform to FIB and BGP
140 NatEvpnUtil.addRoutesForVxLanProvType(dataBroker, bgpManager, fibManager, vpnName, rd, fibExternalIp,
141 nextHopIp, l3Vni, floatingIpInterface, floatingIpPortMacAddress,
142 writeFlowInvTx, RouteOrigin.STATIC, dpnId);
144 /* Install the flow table L3_FIB_TABLE (table=21)-> PDNAT_TABLE (table=25)
145 * (SNAT to DNAT reverse traffic: If the DPN has both SNAT and DNAT configured )
147 List<ActionInfo> actionInfoFib = new ArrayList<>();
148 actionInfoFib.add(new ActionSetFieldEthernetDestination(new MacAddress(floatingIpPortMacAddress)));
149 List<Instruction> instructionsFib = new ArrayList<>();
150 instructionsFib.add(new InstructionApplyActions(actionInfoFib).buildInstruction(0));
151 instructionsFib.add(new InstructionGotoTable(NwConstants.PDNAT_TABLE).buildInstruction(1));
153 CreateFibEntryInput input = new CreateFibEntryInputBuilder().setVpnName(vpnName)
154 .setSourceDpid(dpnId).setIpAddress(fibExternalIp)
155 .setServiceId(l3Vni).setIpAddressSource(CreateFibEntryInput.IpAddressSource.FloatingIP)
156 .setInstruction(instructionsFib).build();
158 ListenableFuture<RpcResult<CreateFibEntryOutput>> futureVxlan = fibService.createFibEntry(input);
159 LOG.debug("onAddFloatingIp : Add Floating Ip {} , found associated to fixed port {}",
160 externalIp, interfaceName);
161 if (floatingIpPortMacAddress != null) {
162 ListenableFutures.addErrorLogging(txRunner.callWithNewReadWriteTransactionAndSubmit(tx -> {
163 vpnManager.addSubnetMacIntoVpnInstance(vpnName, null, floatingIpPortMacAddress, dpnId, tx);
164 vpnManager.addArpResponderFlowsToExternalNetworkIps(routerName,
165 Collections.singleton(externalIp),
166 floatingIpPortMacAddress, dpnId, networkId, tx);
167 }), LOG, "Error processing floating IP port with MAC address {}", floatingIpPortMacAddress);
169 final long finalL3Vni = l3Vni;
170 Futures.addCallback(futureVxlan, new FutureCallback<RpcResult<CreateFibEntryOutput>>() {
173 public void onFailure(@Nonnull Throwable error) {
174 LOG.error("onAddFloatingIp : Error {} in custom fib routes install process for Floating "
175 + "IP Prefix {} on DPN {}", error, externalIp, dpnId);
179 public void onSuccess(@Nonnull RpcResult<CreateFibEntryOutput> result) {
180 if (result.isSuccessful()) {
181 LOG.info("onAddFloatingIp : Successfully installed custom FIB routes for Floating "
182 + "IP Prefix {} on DPN {}", externalIp, dpnId);
183 List<Instruction> instructions = new ArrayList<>();
184 List<ActionInfo> actionsInfos = new ArrayList<>();
185 List<Instruction> customInstructions = new ArrayList<>();
186 customInstructions.add(new InstructionGotoTable(NwConstants.PDNAT_TABLE).buildInstruction(0));
187 actionsInfos.add(new ActionNxResubmit(NwConstants.PDNAT_TABLE));
188 instructions.add(new InstructionApplyActions(actionsInfos).buildInstruction(0));
189 /* If more than one floatingIp is available in vpn-to-dpn-list for given dpn id, do not call for
190 * installing INTERNAL_TUNNEL_TABLE (table=36) -> PDNAT_TABLE (table=25) flow entry with same tunnel_id
193 if (!NatUtil.isFloatingIpPresentForDpn(dataBroker, dpnId, rd, vpnName, externalIp, true)) {
194 makeTunnelTableEntry(dpnId, finalL3Vni, instructions, writeFlowInvTx);
196 /* Install the flow L3_GW_MAC_TABLE (table=19)-> PDNAT_TABLE (table=25)
197 * (DNAT reverse traffic: If the traffic is Initiated from DC-GW to FIP VM (DNAT forward traffic))
199 NatEvpnUtil.makeL3GwMacTableEntry(dpnId, vpnId, floatingIpPortMacAddress, customInstructions,
200 mdsalManager, writeFlowInvTx);
201 NatUtil.waitForTransactionToComplete(writeFlowInvTx);
203 LOG.error("onAddFloatingIp : Error {} in rpc call to create custom Fib entries for Floating "
204 + "IP Prefix {} on DPN {}", result.getErrors(), externalIp, dpnId);
207 }, MoreExecutors.directExecutor());
209 //Read the FIP vpn-interface details from Configuration l3vpn:vpn-interfaces model and write into Operational DS
210 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NatUtil.getVpnInterfaceIdentifier(floatingIpInterface);
211 Optional<VpnInterface> optionalVpnInterface =
212 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
213 LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier);
214 if (optionalVpnInterface.isPresent()) {
215 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
216 for (VpnInstanceNames vpnInstance : optionalVpnInterface.get().getVpnInstanceNames()) {
217 if (!vpnName.equals(vpnInstance.getVpnName())) {
220 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get());
221 Adjacencies adjs = vpnIfBuilder.getAugmentation(Adjacencies.class);
222 VpnInterfaceOpDataEntryBuilder vpnIfOpDataEntryBuilder = new VpnInterfaceOpDataEntryBuilder();
223 vpnIfOpDataEntryBuilder.setKey(new VpnInterfaceOpDataEntryKey(interfaceName, vpnName));
225 List<Adjacency> adjacencyList = adjs != null ? adjs.getAdjacency() : new ArrayList<>();
226 List<Adjacency> adjacencyListToImport = new ArrayList<>();
227 for (Adjacency adj : adjacencyList) {
228 Subnetmap sn = VpnHelper.getSubnetmapFromItsUuid(dataBroker, adj.getSubnetId());
229 if (!VpnHelper.isSubnetPartOfVpn(sn, vpnName)) {
232 adjacencyListToImport.add(adj);
234 AdjacenciesOp adjacenciesOp = new AdjacenciesOpBuilder()
235 .setAdjacency(adjacencyListToImport).build();
236 vpnIfOpDataEntryBuilder.addAugmentation(AdjacenciesOp.class, adjacenciesOp);
238 LOG.debug("onAddFloatingIp : Add vpnInterface {} to Operational l3vpn:vpn-interfaces-op-data ",
239 floatingIpInterface);
240 InstanceIdentifier<VpnInterfaceOpDataEntry> vpnIfIdentifierOpDataEntry =
241 NatUtil.getVpnInterfaceOpDataEntryIdentifier(interfaceName, vpnName);
242 tx.put(LogicalDatastoreType.OPERATIONAL, vpnIfIdentifierOpDataEntry,
243 vpnIfOpDataEntryBuilder.build(), WriteTransaction.CREATE_MISSING_PARENTS);
246 }), LOG, "onAddFloatingIp : Could not write Interface {}, vpnName {}", interfaceName, vpnName);
248 LOG.debug("onAddFloatingIp : No vpnInterface {} found in Configuration l3vpn:vpn-interfaces ",
249 floatingIpInterface);
253 public void onRemoveFloatingIp(final BigInteger dpnId, final String vpnName, final String externalIp,
254 final String floatingIpInterface, final String floatingIpPortMacAddress,
255 final long routerId, WriteTransaction removeFlowInvTx) {
257 * 1) Remove the flow INTERNAL_TUNNEL_TABLE (table=36)-> PDNAT_TABLE (table=25) (SNAT VM on DPN1 is
258 * responding back to FIP VM on DPN2) {SNAT to DNAT traffic on different Hypervisor}
260 * 2) Remove the flow L3_FIB_TABLE (table=21)-> PDNAT_TABLE (table=25) (FIP VM1 to FIP VM2
261 * Traffic on Same Hypervisor) {DNAT to DNAT on Same Hypervisor}
263 * 3) Remove the flow L3_GW_MAC_TABLE (table=19)-> PDNAT_TABLE (table=25)
264 * (DC-GW is responding back to FIP VM) {DNAT Reverse traffic})
267 String rd = NatUtil.getVpnRd(dataBroker, vpnName);
269 LOG.error("onRemoveFloatingIp : Could not retrieve RD value from VPN Name {} ", vpnName);
272 long vpnId = NatUtil.getVpnId(dataBroker, vpnName);
273 if (vpnId == NatConstants.INVALID_ID) {
274 LOG.error("onRemoveFloatingIp : Invalid Vpn Id is found for Vpn Name {}", vpnName);
277 long l3Vni = NatEvpnUtil.getL3Vni(dataBroker, rd);
278 if (l3Vni == NatConstants.DEFAULT_L3VNI_VALUE) {
279 LOG.debug("onRemoveFloatingIp : L3VNI value is not configured in Internet VPN {} and RD {} "
280 + "Carve-out L3VNI value from OpenDaylight VXLAN VNI Pool and continue with installing "
281 + "DNAT flows for FloatingIp {}", vpnName, rd, externalIp);
282 l3Vni = NatOverVxlanUtil.getInternetVpnVni(idManager, vpnName, routerId).longValue();
284 String fibExternalIp = NatUtil.validateAndAddNetworkMask(externalIp);
286 //Remove Prefix from BGP
287 NatUtil.removePrefixFromBGP(bgpManager, fibManager, rd, fibExternalIp, vpnName, LOG);
289 //Remove custom FIB routes flow for L3_FIB_TABLE (table=21)-> PDNAT_TABLE (table=25)
290 RemoveFibEntryInput input = new RemoveFibEntryInputBuilder().setVpnName(vpnName)
291 .setSourceDpid(dpnId).setIpAddress(fibExternalIp).setServiceId(l3Vni)
292 .setIpAddressSource(RemoveFibEntryInput.IpAddressSource.FloatingIP).build();
293 ListenableFuture<RpcResult<RemoveFibEntryOutput>> futureVxlan = fibService.removeFibEntry(input);
294 final long finalL3Vni = l3Vni;
295 Futures.addCallback(futureVxlan, new FutureCallback<RpcResult<RemoveFibEntryOutput>>() {
298 public void onFailure(@Nonnull Throwable error) {
299 LOG.error("onRemoveFloatingIp : Error {} in custom fib routes remove process for Floating "
300 + "IP Prefix {} on DPN {}", error, externalIp, dpnId);
304 public void onSuccess(@Nonnull RpcResult<RemoveFibEntryOutput> result) {
305 if (result.isSuccessful()) {
306 LOG.info("onRemoveFloatingIp : Successfully removed custom FIB routes for Floating "
307 + "IP Prefix {} on DPN {}", externalIp, dpnId);
308 /* check if any floating IP information is available in vpn-to-dpn-list for given dpn id.
309 * If exist any floating IP then do not remove
310 * INTERNAL_TUNNEL_TABLE (table=36) -> PDNAT_TABLE (table=25) flow entry.
312 if (!NatUtil.isFloatingIpPresentForDpn(dataBroker, dpnId, rd, vpnName, externalIp, false)) {
313 //Remove the flow for INTERNAL_TUNNEL_TABLE (table=36)-> PDNAT_TABLE (table=25)
314 removeTunnelTableEntry(dpnId, finalL3Vni, removeFlowInvTx);
316 //Remove the flow for L3_GW_MAC_TABLE (table=19)-> PDNAT_TABLE (table=25)
317 NatEvpnUtil.removeL3GwMacTableEntry(dpnId, vpnId, floatingIpPortMacAddress, mdsalManager,
319 NatUtil.waitForTransactionToComplete(removeFlowInvTx);
321 LOG.error("onRemoveFloatingIp : Error {} in rpc call to remove custom Fib entries for Floating "
322 + "IP Prefix {} on DPN {}", result.getErrors(), externalIp, dpnId);
325 }, MoreExecutors.directExecutor());
326 //Read the FIP vpn-interface details from Operational l3vpn:vpn-interfaces model and delete from Operational DS
327 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NatUtil.getVpnInterfaceIdentifier(floatingIpInterface);
328 Optional<VpnInterface> optionalVpnInterface =
329 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
330 LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier);
331 if (optionalVpnInterface.isPresent()) {
332 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
333 for (VpnInstanceNames vpnInstance : optionalVpnInterface.get().getVpnInstanceNames()) {
334 if (!vpnName.equals(vpnInstance.getVpnName())) {
337 InstanceIdentifier<VpnInterfaceOpDataEntry> vpnOpIfIdentifier = NatUtil
338 .getVpnInterfaceOpDataEntryIdentifier(floatingIpInterface, vpnName);
339 tx.delete(LogicalDatastoreType.OPERATIONAL, vpnOpIfIdentifier);
342 }), LOG, "onRemoveFloatingIp : Could not remove vpnInterface {}, vpnName {} from Operational "
343 + "odl-l3vpn:vpn-interface-op-data", floatingIpInterface, vpnName);
345 LOG.debug("onRemoveFloatingIp : Remove vpnInterface {} vpnName {} "
346 + "to Operational odl-l3vpn:vpn-interface-op-data", floatingIpInterface, vpnName);
348 LOG.debug("onRemoveFloatingIp : No vpnInterface {} found "
349 + "in Operational odl-l3vpn:vpn-interface-op-data", floatingIpInterface);
353 private void makeTunnelTableEntry(BigInteger dpnId, long l3Vni, List<Instruction> customInstructions,
354 WriteTransaction writeFlowInvTx) {
355 LOG.debug("makeTunnelTableEntry : Create terminating service table {} --> table {} flow on DpnId {} "
356 + "with l3Vni {} as matching parameter", NwConstants.INTERNAL_TUNNEL_TABLE, NwConstants.PDNAT_TABLE,
358 List<MatchInfo> mkMatches = new ArrayList<>();
359 mkMatches.add(new MatchTunnelId(BigInteger.valueOf(l3Vni)));
360 Flow terminatingServiceTableFlowEntity = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE,
361 NatEvpnUtil.getFlowRef(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, l3Vni, NatConstants.DNAT_FLOW_NAME), 6,
362 String.format("%s:%d", "TST Flow Entry ", l3Vni),
363 0, 0, COOKIE_TUNNEL.add(BigInteger.valueOf(l3Vni)), mkMatches, customInstructions);
364 mdsalManager.addFlowToTx(dpnId, terminatingServiceTableFlowEntity, writeFlowInvTx);
365 LOG.debug("makeTunnelTableEntry : Successfully installed terminating service table flow {} on DpnId {}",
366 terminatingServiceTableFlowEntity, dpnId);
369 private void removeTunnelTableEntry(BigInteger dpnId, long l3Vni, WriteTransaction removeFlowInvTx) {
370 LOG.debug("removeTunnelTableEntry : Remove terminating service table {} --> table {} flow on DpnId {} "
371 + "with l3Vni {} as matching parameter", NwConstants.INTERNAL_TUNNEL_TABLE, NwConstants.PDNAT_TABLE,
373 List<MatchInfo> mkMatches = new ArrayList<>();
374 mkMatches.add(new MatchTunnelId(BigInteger.valueOf(l3Vni)));
375 Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE,
376 NatEvpnUtil.getFlowRef(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, l3Vni, NatConstants.DNAT_FLOW_NAME),
377 6, String.format("%s:%d", "TST Flow Entry ", l3Vni), 0, 0,
378 COOKIE_TUNNEL.add(BigInteger.valueOf(l3Vni)), mkMatches, null);
379 mdsalManager.removeFlowToTx(dpnId, flowEntity, removeFlowInvTx);
380 LOG.debug("removeTunnelTableEntry : Successfully removed terminating service table flow {} on DpnId {}",