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;
15 import com.google.common.base.Optional;
16 import com.google.common.util.concurrent.FutureCallback;
17 import com.google.common.util.concurrent.Futures;
18 import com.google.common.util.concurrent.ListenableFuture;
19 import com.google.common.util.concurrent.MoreExecutors;
20 import java.math.BigInteger;
21 import java.util.ArrayList;
22 import java.util.Collections;
23 import java.util.List;
24 import java.util.concurrent.ExecutionException;
25 import javax.inject.Inject;
26 import javax.inject.Singleton;
27 import org.eclipse.jdt.annotation.NonNull;
28 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
29 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
30 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
31 import org.opendaylight.genius.infra.Datastore.Configuration;
32 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
33 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
34 import org.opendaylight.genius.infra.TypedReadWriteTransaction;
35 import org.opendaylight.genius.infra.TypedWriteTransaction;
36 import org.opendaylight.genius.mdsalutil.ActionInfo;
37 import org.opendaylight.genius.mdsalutil.MDSALUtil;
38 import org.opendaylight.genius.mdsalutil.MatchInfo;
39 import org.opendaylight.genius.mdsalutil.NwConstants;
40 import org.opendaylight.genius.mdsalutil.actions.ActionNxResubmit;
41 import org.opendaylight.genius.mdsalutil.actions.ActionSetFieldEthernetDestination;
42 import org.opendaylight.genius.mdsalutil.instructions.InstructionApplyActions;
43 import org.opendaylight.genius.mdsalutil.instructions.InstructionGotoTable;
44 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
45 import org.opendaylight.genius.mdsalutil.matches.MatchTunnelId;
46 import org.opendaylight.infrautils.utils.concurrent.ListenableFutures;
47 import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
48 import org.opendaylight.netvirt.fibmanager.api.IFibManager;
49 import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
50 import org.opendaylight.netvirt.vpnmanager.api.IVpnManager;
51 import org.opendaylight.netvirt.vpnmanager.api.VpnHelper;
52 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
53 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceBuilder;
54 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.vpn._interface.VpnInstanceNames;
55 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
56 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.CreateFibEntryInput;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.CreateFibEntryInputBuilder;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.CreateFibEntryOutput;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.FibRpcService;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.RemoveFibEntryInput;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.RemoveFibEntryInputBuilder;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.RemoveFibEntryOutput;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.Adjacencies;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AdjacenciesOp;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AdjacenciesOpBuilder;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn._interface.op.data.VpnInterfaceOpDataEntry;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn._interface.op.data.VpnInterfaceOpDataEntryBuilder;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn._interface.op.data.VpnInterfaceOpDataEntryKey;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap;
74 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
75 import org.opendaylight.yangtools.yang.common.RpcResult;
76 import org.slf4j.Logger;
77 import org.slf4j.LoggerFactory;
80 public class EvpnDnatFlowProgrammer {
81 private static final Logger LOG = LoggerFactory.getLogger(EvpnDnatFlowProgrammer.class);
83 private static final BigInteger COOKIE_TUNNEL = new BigInteger("9000000", 16);
85 private final DataBroker dataBroker;
86 private final ManagedNewTransactionRunner txRunner;
87 private final IMdsalApiManager mdsalManager;
88 private final IBgpManager bgpManager;
89 private final IFibManager fibManager;
90 private final FibRpcService fibService;
91 private final IVpnManager vpnManager;
92 private final NatOverVxlanUtil natOverVxlanUtil;
95 public EvpnDnatFlowProgrammer(final DataBroker dataBroker, final IMdsalApiManager mdsalManager,
96 final IBgpManager bgpManager,
97 final IFibManager fibManager,
98 final FibRpcService fibService,
99 final IVpnManager vpnManager,
100 final NatOverVxlanUtil natOverVxlanUtil) {
101 this.dataBroker = dataBroker;
102 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
103 this.mdsalManager = mdsalManager;
104 this.bgpManager = bgpManager;
105 this.fibManager = fibManager;
106 this.fibService = fibService;
107 this.vpnManager = vpnManager;
108 this.natOverVxlanUtil = natOverVxlanUtil;
111 public void onAddFloatingIp(final BigInteger dpnId, final String routerName, final long routerId,
112 final String vpnName,
113 final String internalIp, final String externalIp, final Uuid networkId,
114 final String interfaceName,
115 final String floatingIpInterface,
116 final String floatingIpPortMacAddress,
118 final String nextHopIp, final TypedReadWriteTransaction<Configuration> confTx) {
120 * 1) Install the flow INTERNAL_TUNNEL_TABLE (table=36)-> PDNAT_TABLE (table=25) (SNAT VM on DPN1 is
121 * responding back to FIP VM on DPN2) {SNAT to DNAT traffic on different Hypervisor}
123 * 2) Install the flow L3_FIB_TABLE (table=21)-> PDNAT_TABLE (table=25) (FIP VM1 to FIP VM2
124 * Traffic on Same Hypervisor) {DNAT to DNAT on Same Hypervisor}
126 * 3) Install the flow L3_GW_MAC_TABLE (table=19)-> PDNAT_TABLE (table=25)
127 * (DC-GW is responding back to FIP VM) {DNAT Reverse traffic})
130 long vpnId = NatUtil.getVpnId(dataBroker, vpnName);
131 if (vpnId == NatConstants.INVALID_ID) {
132 LOG.error("onAddFloatingIp : Invalid Vpn Id is found for Vpn Name {}", vpnName);
135 long l3Vni = NatEvpnUtil.getL3Vni(dataBroker, rd);
136 if (l3Vni == NatConstants.DEFAULT_L3VNI_VALUE) {
137 LOG.debug("onAddFloatingIp : L3VNI value is not configured in Internet VPN {} and RD {} "
138 + "Carve-out L3VNI value from OpenDaylight VXLAN VNI Pool and continue with installing "
139 + "DNAT flows for FloatingIp {}", vpnName, rd, externalIp);
140 l3Vni = natOverVxlanUtil.getInternetVpnVni(vpnName, routerId).longValue();
142 FloatingIPListener.updateOperationalDS(dataBroker, routerName, interfaceName, NatConstants.DEFAULT_LABEL_VALUE,
143 internalIp, externalIp);
144 String fibExternalIp = NatUtil.validateAndAddNetworkMask(externalIp);
145 //Inform to FIB and BGP
146 NatEvpnUtil.addRoutesForVxLanProvType(dataBroker, bgpManager, fibManager, vpnName, rd, fibExternalIp,
147 nextHopIp, l3Vni, floatingIpInterface, floatingIpPortMacAddress,
148 confTx, RouteOrigin.STATIC, dpnId, networkId);
150 /* Install the flow table L3_FIB_TABLE (table=21)-> PDNAT_TABLE (table=25)
151 * (SNAT to DNAT reverse traffic: If the DPN has both SNAT and DNAT configured )
153 List<ActionInfo> actionInfoFib = new ArrayList<>();
154 actionInfoFib.add(new ActionSetFieldEthernetDestination(new MacAddress(floatingIpPortMacAddress)));
155 List<Instruction> instructionsFib = new ArrayList<>();
156 instructionsFib.add(new InstructionApplyActions(actionInfoFib).buildInstruction(0));
157 instructionsFib.add(new InstructionGotoTable(NwConstants.PDNAT_TABLE).buildInstruction(1));
159 CreateFibEntryInput input = new CreateFibEntryInputBuilder().setVpnName(vpnName)
160 .setSourceDpid(dpnId).setIpAddress(fibExternalIp)
161 .setServiceId(l3Vni).setIpAddressSource(CreateFibEntryInput.IpAddressSource.FloatingIP)
162 .setInstruction(instructionsFib).build();
164 ListenableFuture<RpcResult<CreateFibEntryOutput>> futureVxlan = fibService.createFibEntry(input);
165 LOG.debug("onAddFloatingIp : Add Floating Ip {} , found associated to fixed port {}",
166 externalIp, interfaceName);
167 if (floatingIpPortMacAddress != null) {
168 ListenableFutures.addErrorLogging(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, tx -> {
169 vpnManager.addSubnetMacIntoVpnInstance(vpnName, null, floatingIpPortMacAddress, dpnId, tx);
170 vpnManager.addArpResponderFlowsToExternalNetworkIps(routerName,
171 Collections.singleton(externalIp),
172 floatingIpPortMacAddress, dpnId, networkId);
173 }), LOG, "Error processing floating IP port with MAC address {}", floatingIpPortMacAddress);
175 final long finalL3Vni = l3Vni;
176 Futures.addCallback(futureVxlan, new FutureCallback<RpcResult<CreateFibEntryOutput>>() {
179 public void onFailure(@NonNull Throwable error) {
180 LOG.error("onAddFloatingIp : Error {} in custom fib routes install process for Floating "
181 + "IP Prefix {} on DPN {}", error, externalIp, dpnId);
185 public void onSuccess(@NonNull RpcResult<CreateFibEntryOutput> result) {
186 if (result.isSuccessful()) {
187 ListenableFutures.addErrorLogging(
188 txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, innerConfTx -> {
189 LOG.info("onAddFloatingIp : Successfully installed custom FIB routes for Floating "
190 + "IP Prefix {} on DPN {}", externalIp, dpnId);
191 List<Instruction> instructions = new ArrayList<>();
192 List<ActionInfo> actionsInfos = new ArrayList<>();
193 List<Instruction> customInstructions = new ArrayList<>();
194 customInstructions.add(
195 new InstructionGotoTable(NwConstants.PDNAT_TABLE).buildInstruction(0));
196 actionsInfos.add(new ActionNxResubmit(NwConstants.PDNAT_TABLE));
197 instructions.add(new InstructionApplyActions(actionsInfos).buildInstruction(0));
198 /* If more than one floatingIp is available in vpn-to-dpn-list for given dpn id, do not
200 * installing INTERNAL_TUNNEL_TABLE (table=36) -> PDNAT_TABLE (table=25) flow entry with
204 if (!NatUtil.isFloatingIpPresentForDpn(dataBroker, dpnId, rd, vpnName, externalIp, true)) {
205 makeTunnelTableEntry(dpnId, finalL3Vni, instructions, innerConfTx);
207 /* Install the flow L3_GW_MAC_TABLE (table=19)-> PDNAT_TABLE (table=25)
208 * (DNAT reverse traffic: If the traffic is Initiated from DC-GW to FIP VM (DNAT forward
211 NatEvpnUtil.makeL3GwMacTableEntry(dpnId, vpnId, floatingIpPortMacAddress,
213 mdsalManager, innerConfTx);
214 }), LOG, "Error installing DNAT flows");
216 LOG.error("onAddFloatingIp : Error {} in rpc call to create custom Fib entries for Floating "
217 + "IP Prefix {} on DPN {}", result.getErrors(), externalIp, dpnId);
220 }, MoreExecutors.directExecutor());
222 //Read the FIP vpn-interface details from Configuration l3vpn:vpn-interfaces model and write into Operational DS
223 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NatUtil.getVpnInterfaceIdentifier(floatingIpInterface);
224 Optional<VpnInterface> optionalVpnInterface =
225 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
226 LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier);
227 if (optionalVpnInterface.isPresent()) {
228 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL, tx -> {
229 for (VpnInstanceNames vpnInstance : optionalVpnInterface.get().nonnullVpnInstanceNames()) {
230 if (!vpnName.equals(vpnInstance.getVpnName())) {
233 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get());
234 Adjacencies adjs = vpnIfBuilder.augmentation(Adjacencies.class);
235 VpnInterfaceOpDataEntryBuilder vpnIfOpDataEntryBuilder = new VpnInterfaceOpDataEntryBuilder();
236 vpnIfOpDataEntryBuilder.withKey(new VpnInterfaceOpDataEntryKey(interfaceName, vpnName));
238 List<Adjacency> adjacencyList =
239 adjs != null && adjs.getAdjacency() != null ? adjs.getAdjacency() : new ArrayList<>();
240 List<Adjacency> adjacencyListToImport = new ArrayList<>();
241 for (Adjacency adj : adjacencyList) {
242 Subnetmap sn = VpnHelper.getSubnetmapFromItsUuid(dataBroker, adj.getSubnetId());
243 if (!VpnHelper.isSubnetPartOfVpn(sn, vpnName)) {
246 adjacencyListToImport.add(adj);
248 AdjacenciesOp adjacenciesOp = new AdjacenciesOpBuilder()
249 .setAdjacency(adjacencyListToImport).build();
250 vpnIfOpDataEntryBuilder.addAugmentation(AdjacenciesOp.class, adjacenciesOp);
252 LOG.debug("onAddFloatingIp : Add vpnInterface {} to Operational l3vpn:vpn-interfaces-op-data ",
253 floatingIpInterface);
254 InstanceIdentifier<VpnInterfaceOpDataEntry> vpnIfIdentifierOpDataEntry =
255 NatUtil.getVpnInterfaceOpDataEntryIdentifier(interfaceName, vpnName);
256 tx.put(vpnIfIdentifierOpDataEntry, vpnIfOpDataEntryBuilder.build(), CREATE_MISSING_PARENTS);
259 }), LOG, "onAddFloatingIp : Could not write Interface {}, vpnName {}", interfaceName, vpnName);
261 LOG.debug("onAddFloatingIp : No vpnInterface {} found in Configuration l3vpn:vpn-interfaces ",
262 floatingIpInterface);
266 public void onRemoveFloatingIp(final BigInteger dpnId, final String vpnName, final String externalIp,
267 final String floatingIpInterface, final String floatingIpPortMacAddress,
268 final long routerId, TypedReadWriteTransaction<Configuration> confTx) {
270 * 1) Remove the flow INTERNAL_TUNNEL_TABLE (table=36)-> PDNAT_TABLE (table=25) (SNAT VM on DPN1 is
271 * responding back to FIP VM on DPN2) {SNAT to DNAT traffic on different Hypervisor}
273 * 2) Remove the flow L3_FIB_TABLE (table=21)-> PDNAT_TABLE (table=25) (FIP VM1 to FIP VM2
274 * Traffic on Same Hypervisor) {DNAT to DNAT on Same Hypervisor}
276 * 3) Remove the flow L3_GW_MAC_TABLE (table=19)-> PDNAT_TABLE (table=25)
277 * (DC-GW is responding back to FIP VM) {DNAT Reverse traffic})
280 String rd = NatUtil.getVpnRd(dataBroker, vpnName);
282 LOG.error("onRemoveFloatingIp : Could not retrieve RD value from VPN Name {} ", vpnName);
285 long vpnId = NatUtil.getVpnId(dataBroker, vpnName);
286 if (vpnId == NatConstants.INVALID_ID) {
287 LOG.error("onRemoveFloatingIp : Invalid Vpn Id is found for Vpn Name {}", vpnName);
290 long l3Vni = NatEvpnUtil.getL3Vni(dataBroker, rd);
291 if (l3Vni == NatConstants.DEFAULT_L3VNI_VALUE) {
292 LOG.debug("onRemoveFloatingIp : L3VNI value is not configured in Internet VPN {} and RD {} "
293 + "Carve-out L3VNI value from OpenDaylight VXLAN VNI Pool and continue with installing "
294 + "DNAT flows for FloatingIp {}", vpnName, rd, externalIp);
295 l3Vni = natOverVxlanUtil.getInternetVpnVni(vpnName, routerId).longValue();
297 String fibExternalIp = NatUtil.validateAndAddNetworkMask(externalIp);
299 //Remove Prefix from BGP
300 NatUtil.removePrefixFromBGP(bgpManager, fibManager, rd, fibExternalIp, vpnName, LOG);
302 //Remove custom FIB routes flow for L3_FIB_TABLE (table=21)-> PDNAT_TABLE (table=25)
303 RemoveFibEntryInput input = new RemoveFibEntryInputBuilder().setVpnName(vpnName)
304 .setSourceDpid(dpnId).setIpAddress(fibExternalIp).setServiceId(l3Vni)
305 .setIpAddressSource(RemoveFibEntryInput.IpAddressSource.FloatingIP).build();
306 ListenableFuture<RpcResult<RemoveFibEntryOutput>> futureVxlan = fibService.removeFibEntry(input);
307 final long finalL3Vni = l3Vni;
308 Futures.addCallback(futureVxlan, new FutureCallback<RpcResult<RemoveFibEntryOutput>>() {
311 public void onFailure(@NonNull Throwable error) {
312 LOG.error("onRemoveFloatingIp : Error {} in custom fib routes remove process for Floating "
313 + "IP Prefix {} on DPN {}", error, externalIp, dpnId);
317 public void onSuccess(@NonNull RpcResult<RemoveFibEntryOutput> result) {
318 if (result.isSuccessful()) {
319 ListenableFutures.addErrorLogging(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION,
321 LOG.info("onRemoveFloatingIp : Successfully removed custom FIB routes for Floating "
322 + "IP Prefix {} on DPN {}", externalIp, dpnId);
323 /* check if any floating IP information is available in vpn-to-dpn-list for given dpn id.
324 * If exist any floating IP then do not remove
325 * INTERNAL_TUNNEL_TABLE (table=36) -> PDNAT_TABLE (table=25) flow entry.
327 if (!NatUtil.isFloatingIpPresentForDpn(dataBroker, dpnId, rd, vpnName, externalIp, false)) {
328 //Remove the flow for INTERNAL_TUNNEL_TABLE (table=36)-> PDNAT_TABLE (table=25)
329 removeTunnelTableEntry(dpnId, finalL3Vni, innerConfTx);
331 //Remove the flow for L3_GW_MAC_TABLE (table=19)-> PDNAT_TABLE (table=25)
332 NatEvpnUtil.removeL3GwMacTableEntry(dpnId, vpnId, floatingIpPortMacAddress, mdsalManager,
334 }), LOG, "Error removing flows");
336 LOG.error("onRemoveFloatingIp : Error {} in rpc call to remove custom Fib entries for Floating "
337 + "IP Prefix {} on DPN {}", result.getErrors(), externalIp, dpnId);
340 }, MoreExecutors.directExecutor());
341 //Read the FIP vpn-interface details from Operational l3vpn:vpn-interfaces model and delete from Operational DS
342 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NatUtil.getVpnInterfaceIdentifier(floatingIpInterface);
343 Optional<VpnInterface> optionalVpnInterface =
344 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
345 LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier);
346 if (optionalVpnInterface.isPresent()) {
347 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL, tx -> {
348 for (VpnInstanceNames vpnInstance : optionalVpnInterface.get().nonnullVpnInstanceNames()) {
349 if (!vpnName.equals(vpnInstance.getVpnName())) {
352 InstanceIdentifier<VpnInterfaceOpDataEntry> vpnOpIfIdentifier = NatUtil
353 .getVpnInterfaceOpDataEntryIdentifier(floatingIpInterface, vpnName);
354 tx.delete(vpnOpIfIdentifier);
357 }), LOG, "onRemoveFloatingIp : Could not remove vpnInterface {}, vpnName {} from Operational "
358 + "odl-l3vpn:vpn-interface-op-data", floatingIpInterface, vpnName);
360 LOG.debug("onRemoveFloatingIp : Remove vpnInterface {} vpnName {} "
361 + "to Operational odl-l3vpn:vpn-interface-op-data", floatingIpInterface, vpnName);
363 LOG.debug("onRemoveFloatingIp : No vpnInterface {} found "
364 + "in Operational odl-l3vpn:vpn-interface-op-data", floatingIpInterface);
368 private void makeTunnelTableEntry(BigInteger dpnId, long l3Vni, List<Instruction> customInstructions,
369 TypedWriteTransaction<Configuration> confTx) {
370 LOG.debug("makeTunnelTableEntry : Create 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 terminatingServiceTableFlowEntity = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE,
376 NatEvpnUtil.getFlowRef(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, l3Vni, NatConstants.DNAT_FLOW_NAME), 6,
377 String.format("%s:%d", "TST Flow Entry ", l3Vni),
378 0, 0, COOKIE_TUNNEL.add(BigInteger.valueOf(l3Vni)), mkMatches, customInstructions);
379 mdsalManager.addFlow(confTx, dpnId, terminatingServiceTableFlowEntity);
380 LOG.debug("makeTunnelTableEntry : Successfully installed terminating service table flow {} on DpnId {}",
381 terminatingServiceTableFlowEntity, dpnId);
384 private void removeTunnelTableEntry(BigInteger dpnId, long l3Vni, TypedReadWriteTransaction<Configuration> confTx)
385 throws ExecutionException, InterruptedException {
386 LOG.debug("removeTunnelTableEntry : Remove terminating service table {} --> table {} flow on DpnId {} "
387 + "with l3Vni {} as matching parameter", NwConstants.INTERNAL_TUNNEL_TABLE, NwConstants.PDNAT_TABLE,
389 List<MatchInfo> mkMatches = new ArrayList<>();
390 mkMatches.add(new MatchTunnelId(BigInteger.valueOf(l3Vni)));
391 Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE,
392 NatEvpnUtil.getFlowRef(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, l3Vni, NatConstants.DNAT_FLOW_NAME),
393 6, String.format("%s:%d", "TST Flow Entry ", l3Vni), 0, 0,
394 COOKIE_TUNNEL.add(BigInteger.valueOf(l3Vni)), mkMatches, null);
395 mdsalManager.removeFlow(confTx, dpnId, flowEntity);
396 LOG.debug("removeTunnelTableEntry : Successfully removed terminating service table flow {} on DpnId {}",