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 javax.annotation.Nonnull;
25 import javax.inject.Inject;
26 import javax.inject.Singleton;
27 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
28 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
29 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
30 import org.opendaylight.genius.infra.Datastore.Configuration;
31 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
32 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
33 import org.opendaylight.genius.infra.TypedReadWriteTransaction;
34 import org.opendaylight.genius.infra.TypedWriteTransaction;
35 import org.opendaylight.genius.mdsalutil.ActionInfo;
36 import org.opendaylight.genius.mdsalutil.MDSALUtil;
37 import org.opendaylight.genius.mdsalutil.MatchInfo;
38 import org.opendaylight.genius.mdsalutil.NwConstants;
39 import org.opendaylight.genius.mdsalutil.actions.ActionNxResubmit;
40 import org.opendaylight.genius.mdsalutil.actions.ActionSetFieldEthernetDestination;
41 import org.opendaylight.genius.mdsalutil.instructions.InstructionApplyActions;
42 import org.opendaylight.genius.mdsalutil.instructions.InstructionGotoTable;
43 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
44 import org.opendaylight.genius.mdsalutil.matches.MatchTunnelId;
45 import org.opendaylight.infrautils.utils.concurrent.ListenableFutures;
46 import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
47 import org.opendaylight.netvirt.fibmanager.api.IFibManager;
48 import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
49 import org.opendaylight.netvirt.vpnmanager.api.IVpnManager;
50 import org.opendaylight.netvirt.vpnmanager.api.VpnHelper;
51 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
52 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceBuilder;
53 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.vpn._interface.VpnInstanceNames;
54 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
55 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
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 IdManagerService idManager;
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 IdManagerService idManager) {
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.idManager = idManager;
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(idManager, 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, confTx, RouteOrigin.STATIC, dpnId);
149 /* Install the flow table L3_FIB_TABLE (table=21)-> PDNAT_TABLE (table=25)
150 * (SNAT to DNAT reverse traffic: If the DPN has both SNAT and DNAT configured )
152 List<ActionInfo> actionInfoFib = new ArrayList<>();
153 actionInfoFib.add(new ActionSetFieldEthernetDestination(new MacAddress(floatingIpPortMacAddress)));
154 List<Instruction> instructionsFib = new ArrayList<>();
155 instructionsFib.add(new InstructionApplyActions(actionInfoFib).buildInstruction(0));
156 instructionsFib.add(new InstructionGotoTable(NwConstants.PDNAT_TABLE).buildInstruction(1));
158 CreateFibEntryInput input = new CreateFibEntryInputBuilder().setVpnName(vpnName)
159 .setSourceDpid(dpnId).setIpAddress(fibExternalIp)
160 .setServiceId(l3Vni).setIpAddressSource(CreateFibEntryInput.IpAddressSource.FloatingIP)
161 .setInstruction(instructionsFib).build();
163 ListenableFuture<RpcResult<CreateFibEntryOutput>> futureVxlan = fibService.createFibEntry(input);
164 LOG.debug("onAddFloatingIp : Add Floating Ip {} , found associated to fixed port {}",
165 externalIp, interfaceName);
166 if (floatingIpPortMacAddress != null) {
167 ListenableFutures.addErrorLogging(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, tx -> {
168 vpnManager.addSubnetMacIntoVpnInstance(vpnName, null, floatingIpPortMacAddress, dpnId, tx);
169 vpnManager.addArpResponderFlowsToExternalNetworkIps(routerName,
170 Collections.singleton(externalIp),
171 floatingIpPortMacAddress, dpnId, networkId);
172 }), LOG, "Error processing floating IP port with MAC address {}", floatingIpPortMacAddress);
174 final long finalL3Vni = l3Vni;
175 Futures.addCallback(futureVxlan, new FutureCallback<RpcResult<CreateFibEntryOutput>>() {
178 public void onFailure(@Nonnull Throwable error) {
179 LOG.error("onAddFloatingIp : Error {} in custom fib routes install process for Floating "
180 + "IP Prefix {} on DPN {}", error, externalIp, dpnId);
184 public void onSuccess(@Nonnull RpcResult<CreateFibEntryOutput> result) {
185 if (result.isSuccessful()) {
186 ListenableFutures.addErrorLogging(
187 txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, innerConfTx -> {
188 LOG.info("onAddFloatingIp : Successfully installed custom FIB routes for Floating "
189 + "IP Prefix {} on DPN {}", externalIp, dpnId);
190 List<Instruction> instructions = new ArrayList<>();
191 List<ActionInfo> actionsInfos = new ArrayList<>();
192 List<Instruction> customInstructions = new ArrayList<>();
193 customInstructions.add(
194 new InstructionGotoTable(NwConstants.PDNAT_TABLE).buildInstruction(0));
195 actionsInfos.add(new ActionNxResubmit(NwConstants.PDNAT_TABLE));
196 instructions.add(new InstructionApplyActions(actionsInfos).buildInstruction(0));
197 /* If more than one floatingIp is available in vpn-to-dpn-list for given dpn id, do not
199 * installing INTERNAL_TUNNEL_TABLE (table=36) -> PDNAT_TABLE (table=25) flow entry with
203 if (!NatUtil.isFloatingIpPresentForDpn(dataBroker, dpnId, rd, vpnName, externalIp, true)) {
204 makeTunnelTableEntry(dpnId, finalL3Vni, instructions, innerConfTx);
206 /* Install the flow L3_GW_MAC_TABLE (table=19)-> PDNAT_TABLE (table=25)
207 * (DNAT reverse traffic: If the traffic is Initiated from DC-GW to FIP VM (DNAT forward
210 NatEvpnUtil.makeL3GwMacTableEntry(dpnId, vpnId, floatingIpPortMacAddress,
212 mdsalManager, innerConfTx);
213 }), LOG, "Error installing DNAT flows");
215 LOG.error("onAddFloatingIp : Error {} in rpc call to create custom Fib entries for Floating "
216 + "IP Prefix {} on DPN {}", result.getErrors(), externalIp, dpnId);
219 }, MoreExecutors.directExecutor());
221 //Read the FIP vpn-interface details from Configuration l3vpn:vpn-interfaces model and write into Operational DS
222 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NatUtil.getVpnInterfaceIdentifier(floatingIpInterface);
223 Optional<VpnInterface> optionalVpnInterface =
224 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
225 LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier);
226 if (optionalVpnInterface.isPresent()) {
227 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL, tx -> {
228 for (VpnInstanceNames vpnInstance : optionalVpnInterface.get().getVpnInstanceNames()) {
229 if (!vpnName.equals(vpnInstance.getVpnName())) {
232 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get());
233 Adjacencies adjs = vpnIfBuilder.augmentation(Adjacencies.class);
234 VpnInterfaceOpDataEntryBuilder vpnIfOpDataEntryBuilder = new VpnInterfaceOpDataEntryBuilder();
235 vpnIfOpDataEntryBuilder.withKey(new VpnInterfaceOpDataEntryKey(interfaceName, vpnName));
237 List<Adjacency> adjacencyList = adjs != null ? adjs.getAdjacency() : new ArrayList<>();
238 List<Adjacency> adjacencyListToImport = new ArrayList<>();
239 for (Adjacency adj : adjacencyList) {
240 Subnetmap sn = VpnHelper.getSubnetmapFromItsUuid(dataBroker, adj.getSubnetId());
241 if (!VpnHelper.isSubnetPartOfVpn(sn, vpnName)) {
244 adjacencyListToImport.add(adj);
246 AdjacenciesOp adjacenciesOp = new AdjacenciesOpBuilder()
247 .setAdjacency(adjacencyListToImport).build();
248 vpnIfOpDataEntryBuilder.addAugmentation(AdjacenciesOp.class, adjacenciesOp);
250 LOG.debug("onAddFloatingIp : Add vpnInterface {} to Operational l3vpn:vpn-interfaces-op-data ",
251 floatingIpInterface);
252 InstanceIdentifier<VpnInterfaceOpDataEntry> vpnIfIdentifierOpDataEntry =
253 NatUtil.getVpnInterfaceOpDataEntryIdentifier(interfaceName, vpnName);
254 tx.put(vpnIfIdentifierOpDataEntry, vpnIfOpDataEntryBuilder.build(), CREATE_MISSING_PARENTS);
257 }), LOG, "onAddFloatingIp : Could not write Interface {}, vpnName {}", interfaceName, vpnName);
259 LOG.debug("onAddFloatingIp : No vpnInterface {} found in Configuration l3vpn:vpn-interfaces ",
260 floatingIpInterface);
264 public void onRemoveFloatingIp(final BigInteger dpnId, final String vpnName, final String externalIp,
265 final String floatingIpInterface, final String floatingIpPortMacAddress,
266 final long routerId, TypedReadWriteTransaction<Configuration> confTx) {
268 * 1) Remove the flow INTERNAL_TUNNEL_TABLE (table=36)-> PDNAT_TABLE (table=25) (SNAT VM on DPN1 is
269 * responding back to FIP VM on DPN2) {SNAT to DNAT traffic on different Hypervisor}
271 * 2) Remove the flow L3_FIB_TABLE (table=21)-> PDNAT_TABLE (table=25) (FIP VM1 to FIP VM2
272 * Traffic on Same Hypervisor) {DNAT to DNAT on Same Hypervisor}
274 * 3) Remove the flow L3_GW_MAC_TABLE (table=19)-> PDNAT_TABLE (table=25)
275 * (DC-GW is responding back to FIP VM) {DNAT Reverse traffic})
278 String rd = NatUtil.getVpnRd(dataBroker, vpnName);
280 LOG.error("onRemoveFloatingIp : Could not retrieve RD value from VPN Name {} ", vpnName);
283 long vpnId = NatUtil.getVpnId(dataBroker, vpnName);
284 if (vpnId == NatConstants.INVALID_ID) {
285 LOG.error("onRemoveFloatingIp : Invalid Vpn Id is found for Vpn Name {}", vpnName);
288 long l3Vni = NatEvpnUtil.getL3Vni(dataBroker, rd);
289 if (l3Vni == NatConstants.DEFAULT_L3VNI_VALUE) {
290 LOG.debug("onRemoveFloatingIp : L3VNI value is not configured in Internet VPN {} and RD {} "
291 + "Carve-out L3VNI value from OpenDaylight VXLAN VNI Pool and continue with installing "
292 + "DNAT flows for FloatingIp {}", vpnName, rd, externalIp);
293 l3Vni = NatOverVxlanUtil.getInternetVpnVni(idManager, vpnName, routerId).longValue();
295 String fibExternalIp = NatUtil.validateAndAddNetworkMask(externalIp);
297 //Remove Prefix from BGP
298 NatUtil.removePrefixFromBGP(bgpManager, fibManager, rd, fibExternalIp, vpnName, LOG);
300 //Remove custom FIB routes flow for L3_FIB_TABLE (table=21)-> PDNAT_TABLE (table=25)
301 RemoveFibEntryInput input = new RemoveFibEntryInputBuilder().setVpnName(vpnName)
302 .setSourceDpid(dpnId).setIpAddress(fibExternalIp).setServiceId(l3Vni)
303 .setIpAddressSource(RemoveFibEntryInput.IpAddressSource.FloatingIP).build();
304 ListenableFuture<RpcResult<RemoveFibEntryOutput>> futureVxlan = fibService.removeFibEntry(input);
305 final long finalL3Vni = l3Vni;
306 Futures.addCallback(futureVxlan, new FutureCallback<RpcResult<RemoveFibEntryOutput>>() {
309 public void onFailure(@Nonnull Throwable error) {
310 LOG.error("onRemoveFloatingIp : Error {} in custom fib routes remove process for Floating "
311 + "IP Prefix {} on DPN {}", error, externalIp, dpnId);
315 public void onSuccess(@Nonnull RpcResult<RemoveFibEntryOutput> result) {
316 if (result.isSuccessful()) {
317 ListenableFutures.addErrorLogging(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION,
319 LOG.info("onRemoveFloatingIp : Successfully removed custom FIB routes for Floating "
320 + "IP Prefix {} on DPN {}", externalIp, dpnId);
321 /* check if any floating IP information is available in vpn-to-dpn-list for given dpn id.
322 * If exist any floating IP then do not remove
323 * INTERNAL_TUNNEL_TABLE (table=36) -> PDNAT_TABLE (table=25) flow entry.
325 if (!NatUtil.isFloatingIpPresentForDpn(dataBroker, dpnId, rd, vpnName, externalIp, false)) {
326 //Remove the flow for INTERNAL_TUNNEL_TABLE (table=36)-> PDNAT_TABLE (table=25)
327 removeTunnelTableEntry(dpnId, finalL3Vni, innerConfTx);
329 //Remove the flow for L3_GW_MAC_TABLE (table=19)-> PDNAT_TABLE (table=25)
330 NatEvpnUtil.removeL3GwMacTableEntry(dpnId, vpnId, floatingIpPortMacAddress, mdsalManager,
332 }), LOG, "Error removing flows");
334 LOG.error("onRemoveFloatingIp : Error {} in rpc call to remove custom Fib entries for Floating "
335 + "IP Prefix {} on DPN {}", result.getErrors(), externalIp, dpnId);
338 }, MoreExecutors.directExecutor());
339 //Read the FIP vpn-interface details from Operational l3vpn:vpn-interfaces model and delete from Operational DS
340 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NatUtil.getVpnInterfaceIdentifier(floatingIpInterface);
341 Optional<VpnInterface> optionalVpnInterface =
342 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
343 LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier);
344 if (optionalVpnInterface.isPresent()) {
345 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL, tx -> {
346 for (VpnInstanceNames vpnInstance : optionalVpnInterface.get().getVpnInstanceNames()) {
347 if (!vpnName.equals(vpnInstance.getVpnName())) {
350 InstanceIdentifier<VpnInterfaceOpDataEntry> vpnOpIfIdentifier = NatUtil
351 .getVpnInterfaceOpDataEntryIdentifier(floatingIpInterface, vpnName);
352 tx.delete(vpnOpIfIdentifier);
355 }), LOG, "onRemoveFloatingIp : Could not remove vpnInterface {}, vpnName {} from Operational "
356 + "odl-l3vpn:vpn-interface-op-data", floatingIpInterface, vpnName);
358 LOG.debug("onRemoveFloatingIp : Remove vpnInterface {} vpnName {} "
359 + "to Operational odl-l3vpn:vpn-interface-op-data", floatingIpInterface, vpnName);
361 LOG.debug("onRemoveFloatingIp : No vpnInterface {} found "
362 + "in Operational odl-l3vpn:vpn-interface-op-data", floatingIpInterface);
366 private void makeTunnelTableEntry(BigInteger dpnId, long l3Vni, List<Instruction> customInstructions,
367 TypedWriteTransaction<Configuration> confTx) {
368 LOG.debug("makeTunnelTableEntry : Create terminating service table {} --> table {} flow on DpnId {} "
369 + "with l3Vni {} as matching parameter", NwConstants.INTERNAL_TUNNEL_TABLE, NwConstants.PDNAT_TABLE,
371 List<MatchInfo> mkMatches = new ArrayList<>();
372 mkMatches.add(new MatchTunnelId(BigInteger.valueOf(l3Vni)));
373 Flow terminatingServiceTableFlowEntity = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE,
374 NatEvpnUtil.getFlowRef(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, l3Vni, NatConstants.DNAT_FLOW_NAME), 6,
375 String.format("%s:%d", "TST Flow Entry ", l3Vni),
376 0, 0, COOKIE_TUNNEL.add(BigInteger.valueOf(l3Vni)), mkMatches, customInstructions);
377 mdsalManager.addFlow(confTx, dpnId, terminatingServiceTableFlowEntity);
378 LOG.debug("makeTunnelTableEntry : Successfully installed terminating service table flow {} on DpnId {}",
379 terminatingServiceTableFlowEntity, dpnId);
382 private void removeTunnelTableEntry(BigInteger dpnId, long l3Vni, TypedReadWriteTransaction<Configuration> confTx) {
383 LOG.debug("removeTunnelTableEntry : Remove terminating service table {} --> table {} flow on DpnId {} "
384 + "with l3Vni {} as matching parameter", NwConstants.INTERNAL_TUNNEL_TABLE, NwConstants.PDNAT_TABLE,
386 List<MatchInfo> mkMatches = new ArrayList<>();
387 mkMatches.add(new MatchTunnelId(BigInteger.valueOf(l3Vni)));
388 Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE,
389 NatEvpnUtil.getFlowRef(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, l3Vni, NatConstants.DNAT_FLOW_NAME),
390 6, String.format("%s:%d", "TST Flow Entry ", l3Vni), 0, 0,
391 COOKIE_TUNNEL.add(BigInteger.valueOf(l3Vni)), mkMatches, null);
392 mdsalManager.removeFlow(confTx, dpnId, flowEntity);
393 LOG.debug("removeTunnelTableEntry : Successfully removed terminating service table flow {} on DpnId {}",