962665d234d20dd7890da2a364041b65bae1d949
[netvirt.git] / vpnservice / natservice / natservice-impl / src / main / java / org / opendaylight / netvirt / natservice / internal / VpnFloatingIpHandler.java
1 /*
2  * Copyright © 2016, 2017 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.netvirt.natservice.internal;
9
10 import static org.opendaylight.netvirt.natservice.internal.NatUtil.buildfloatingIpIdToPortMappingIdentifier;
11
12 import com.google.common.base.Optional;
13 import com.google.common.util.concurrent.AsyncFunction;
14 import com.google.common.util.concurrent.FutureCallback;
15 import com.google.common.util.concurrent.Futures;
16 import com.google.common.util.concurrent.JdkFutureAdapters;
17 import com.google.common.util.concurrent.ListenableFuture;
18 import java.math.BigInteger;
19 import java.util.ArrayList;
20 import java.util.Collections;
21 import java.util.List;
22 import java.util.concurrent.Future;
23 import javax.inject.Inject;
24 import javax.inject.Singleton;
25 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
26 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
27 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
28 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
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.ActionPopMpls;
35 import org.opendaylight.genius.mdsalutil.actions.ActionSetFieldEthernetDestination;
36 import org.opendaylight.genius.mdsalutil.instructions.InstructionApplyActions;
37 import org.opendaylight.genius.mdsalutil.instructions.InstructionGotoTable;
38 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
39 import org.opendaylight.genius.mdsalutil.matches.MatchEthernetType;
40 import org.opendaylight.genius.mdsalutil.matches.MatchMplsLabel;
41 import org.opendaylight.genius.mdsalutil.matches.MatchTunnelId;
42 import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
43 import org.opendaylight.netvirt.elanmanager.api.IElanService;
44 import org.opendaylight.netvirt.fibmanager.api.IFibManager;
45 import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
46 import org.opendaylight.netvirt.neutronvpn.interfaces.INeutronVpnManager;
47 import org.opendaylight.netvirt.vpnmanager.api.IVpnManager;
48 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
49 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddressBuilder;
50 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
51 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
52 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.OdlArputilService;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.SendArpRequestInput;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.SendArpRequestInputBuilder;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.interfaces.InterfaceAddress;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.interfaces.InterfaceAddressBuilder;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.CreateFibEntryInput;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.CreateFibEntryInputBuilder;
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.natservice.rev160111.ProviderTypes;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.subnets.Subnets;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.ports.InternalToExternalPortMap;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.port.info.FloatingIpIdToPortMapping;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.GenerateVpnLabelInput;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.GenerateVpnLabelInputBuilder;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.GenerateVpnLabelOutput;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.RemoveVpnLabelInput;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.RemoveVpnLabelInputBuilder;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.VpnRpcService;
76 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
77 import org.opendaylight.yangtools.yang.common.RpcResult;
78 import org.slf4j.Logger;
79 import org.slf4j.LoggerFactory;
80
81 @Singleton
82 public class VpnFloatingIpHandler implements FloatingIPHandler {
83     private static final Logger LOG = LoggerFactory.getLogger(VpnFloatingIpHandler.class);
84     private final DataBroker dataBroker;
85     private final IMdsalApiManager mdsalManager;
86     private final VpnRpcService vpnService;
87     private final IBgpManager bgpManager;
88     private final FibRpcService fibService;
89     private final IVpnManager vpnManager;
90     private final IFibManager fibManager;
91     private final OdlArputilService arpUtilService;
92     private final IElanService elanService;
93     private final EvpnDnatFlowProgrammer evpnDnatFlowProgrammer;
94     private final INeutronVpnManager nvpnManager;
95     private final IdManagerService idManager;
96     private static final BigInteger COOKIE_TUNNEL = new BigInteger("9000000", 16);
97     private static final String FLOWID_PREFIX = "NAT.";
98
99     @Inject
100     public VpnFloatingIpHandler(final DataBroker dataBroker, final IMdsalApiManager mdsalManager,
101                                 final VpnRpcService vpnService,
102                                 final IBgpManager bgpManager,
103                                 final FibRpcService fibService,
104                                 final IFibManager fibManager,
105                                 final OdlArputilService arputilService,
106                                 final IVpnManager vpnManager,
107                                 final IElanService elanService,
108                                 final EvpnDnatFlowProgrammer evpnDnatFlowProgrammer,
109                                 final INeutronVpnManager nvpnManager,
110                                 final IdManagerService idManager) {
111         this.dataBroker = dataBroker;
112         this.mdsalManager = mdsalManager;
113         this.vpnService = vpnService;
114         this.bgpManager = bgpManager;
115         this.fibService = fibService;
116         this.fibManager = fibManager;
117         this.arpUtilService = arputilService;
118         this.vpnManager = vpnManager;
119         this.elanService = elanService;
120         this.evpnDnatFlowProgrammer = evpnDnatFlowProgrammer;
121         this.nvpnManager = nvpnManager;
122         this.idManager = idManager;
123     }
124
125     @Override
126     public void onAddFloatingIp(final BigInteger dpnId, final String routerId,
127                                 final Uuid networkId, final String interfaceName,
128                                 final InternalToExternalPortMap mapping) {
129         String externalIp = mapping.getExternalIp();
130         String internalIp = mapping.getInternalIp();
131         Uuid floatingIpId = mapping.getExternalId();
132         Uuid subnetId = NatUtil.getFloatingIpPortSubnetIdFromFloatingIpId(dataBroker, floatingIpId);
133         String floatingIpPortMacAddress = NatUtil.getFloatingIpPortMacFromFloatingIpId(dataBroker, floatingIpId);
134         Optional<Subnets> externalSubnet = NatUtil.getOptionalExternalSubnets(dataBroker, subnetId);
135         final String vpnName = externalSubnet.isPresent() ? subnetId.getValue() :
136             NatUtil.getAssociatedVPN(dataBroker, networkId, LOG);
137         final String subnetVpnName = externalSubnet.isPresent() ? subnetId.getValue() : null;
138         if (vpnName == null) {
139             LOG.info("No VPN associated with ext nw {} to handle add floating ip configuration {} in router {}",
140                 networkId, externalIp, routerId);
141             return;
142         }
143         String rd = NatUtil.getVpnRd(dataBroker, vpnName);
144         String nextHopIp = NatUtil.getEndpointIpAddressForDPN(dataBroker, dpnId);
145         LOG.debug("Nexthop ip for prefix {} is {}", externalIp, nextHopIp);
146         WriteTransaction writeTx = dataBroker.newWriteOnlyTransaction();
147         ProviderTypes provType = NatEvpnUtil.getExtNwProvTypeFromRouterName(dataBroker, routerId);
148         if (provType == null) {
149             return;
150         }
151         NatOverVxlanUtil.validateAndCreateVxlanVniPool(dataBroker, nvpnManager, idManager,
152                 NatConstants.ODL_VNI_POOL_NAME);
153         if (provType == ProviderTypes.VXLAN) {
154             Uuid floatingIpInterface = NatEvpnUtil.getFloatingIpInterfaceIdFromFloatingIpId(dataBroker, floatingIpId);
155             evpnDnatFlowProgrammer.onAddFloatingIp(dpnId, routerId, vpnName, internalIp, externalIp, networkId,
156                     interfaceName, floatingIpInterface.getValue(), floatingIpPortMacAddress, rd, nextHopIp, writeTx);
157             if (writeTx != null) {
158                 writeTx.submit();
159             }
160             return;
161         }
162         GenerateVpnLabelInput labelInput = new GenerateVpnLabelInputBuilder().setVpnName(vpnName)
163             .setIpPrefix(externalIp).build();
164         Future<RpcResult<GenerateVpnLabelOutput>> labelFuture = vpnService.generateVpnLabel(labelInput);
165
166         ListenableFuture<RpcResult<Void>> future = Futures.transformAsync(
167                 JdkFutureAdapters.listenInPoolThread(labelFuture),
168                 (AsyncFunction<RpcResult<GenerateVpnLabelOutput>, RpcResult<Void>>) result -> {
169                 if (result.isSuccessful()) {
170                     GenerateVpnLabelOutput output = result.getResult();
171                     long label = output.getLabel();
172                     LOG.debug("Generated label {} for prefix {}", label, externalIp);
173                     FloatingIPListener.updateOperationalDS(dataBroker, routerId, interfaceName, label,
174                         internalIp, externalIp);
175                     //Inform BGP
176                     long l3vni = 0;
177                     if (elanService.isOpenStackVniSemanticsEnforced()) {
178                         l3vni = NatOverVxlanUtil.getInternetVpnVni(idManager, vpnName, l3vni).longValue();
179                     }
180                     String fibExternalIp = NatUtil.validateAndAddNetworkMask(externalIp);
181                     NatUtil.addPrefixToBGP(dataBroker, bgpManager, fibManager, vpnName, rd, subnetId,
182                             fibExternalIp, nextHopIp, networkId.getValue(), floatingIpPortMacAddress,
183                             label, l3vni, LOG, RouteOrigin.STATIC, dpnId);
184
185                     List<Instruction> instructions = new ArrayList<>();
186                     List<ActionInfo> actionsInfos = new ArrayList<>();
187                     actionsInfos.add(new ActionNxResubmit(NwConstants.PDNAT_TABLE));
188                     instructions.add(new InstructionApplyActions(actionsInfos).buildInstruction(0));
189                     makeTunnelTableEntry(vpnName, dpnId, label, instructions);
190
191                     //Install custom FIB routes
192                     List<ActionInfo> actionInfoFib = new ArrayList<>();
193                     List<Instruction> customInstructions = new ArrayList<>();
194                     actionInfoFib.add(new ActionSetFieldEthernetDestination(new MacAddress(floatingIpPortMacAddress)));
195                     customInstructions.add(new InstructionApplyActions(actionInfoFib).buildInstruction(0));
196                     customInstructions.add(new InstructionGotoTable(NwConstants.PDNAT_TABLE).buildInstruction(1));
197
198                     makeLFibTableEntry(dpnId, label, floatingIpPortMacAddress, NwConstants.PDNAT_TABLE);
199                     CreateFibEntryInput input = new CreateFibEntryInputBuilder().setVpnName(vpnName)
200                         .setSourceDpid(dpnId).setInstruction(customInstructions)
201                         .setIpAddress(fibExternalIp).setServiceId(label)
202                         .setIpAddressSource(CreateFibEntryInput.IpAddressSource.FloatingIP)
203                         .setInstruction(customInstructions).build();
204                     //Future<RpcResult<java.lang.Void>> createFibEntry(CreateFibEntryInput input);
205                     Future<RpcResult<Void>> future1 = fibService.createFibEntry(input);
206                     LOG.debug("Add Floating Ip {} , found associated to fixed port {}", externalIp, interfaceName);
207                     if (floatingIpPortMacAddress != null) {
208                         String networkVpnName =  NatUtil.getAssociatedVPN(dataBroker, networkId, LOG);
209                         vpnManager.setupSubnetMacIntoVpnInstance(networkVpnName, subnetVpnName,
210                                 floatingIpPortMacAddress, dpnId, writeTx, NwConstants.ADD_FLOW);
211                         vpnManager.setupArpResponderFlowsToExternalNetworkIps(routerId,
212                                 Collections.singleton(externalIp),
213                             floatingIpPortMacAddress, dpnId, networkId, writeTx, NwConstants.ADD_FLOW);
214                         writeTx.submit();
215                     }
216                     return JdkFutureAdapters.listenInPoolThread(future1);
217                 } else {
218                     String errMsg = String.format("Could not retrieve the label for prefix %s in VPN %s, %s",
219                         externalIp, vpnName, result.getErrors());
220                     LOG.error(errMsg);
221                     return Futures.immediateFailedFuture(new RuntimeException(errMsg));
222                 }
223             });
224
225         Futures.addCallback(future, new FutureCallback<RpcResult<Void>>() {
226
227             @Override
228             public void onFailure(Throwable error) {
229                 LOG.error("Error in generate label or fib install process", error);
230             }
231
232             @Override
233             public void onSuccess(RpcResult<Void> result) {
234                 if (result.isSuccessful()) {
235                     LOG.info("Successfully installed custom FIB routes for prefix {}", externalIp);
236                 } else {
237                     LOG.error("Error in rpc call to create custom Fib entries for prefix {} in DPN {}, {}",
238                         externalIp, dpnId, result.getErrors());
239                 }
240             }
241         });
242
243         // Handle GARP transmission
244         final IpAddress extrenalAddress = IpAddressBuilder.getDefaultInstance(externalIp);
245         sendGarpOnInterface(dpnId, networkId, extrenalAddress, floatingIpPortMacAddress);
246
247     }
248
249     @Override
250     public void onRemoveFloatingIp(final BigInteger dpnId, String routerId, final Uuid networkId,
251                                    InternalToExternalPortMap mapping, final long label) {
252         String externalIp = mapping.getExternalIp();
253         Uuid floatingIpId = mapping.getExternalId();
254         Uuid subnetId = NatUtil.getFloatingIpPortSubnetIdFromFloatingIpId(dataBroker, floatingIpId);
255         Optional<Subnets> externalSubnet = NatUtil.getOptionalExternalSubnets(dataBroker, subnetId);
256         final String vpnName = externalSubnet.isPresent() ? subnetId.getValue() :
257             NatUtil.getAssociatedVPN(dataBroker, networkId, LOG);
258         if (vpnName == null) {
259             LOG.info("No VPN associated with ext nw {} to handle remove floating ip configuration {} in router {}",
260                 networkId, externalIp, routerId);
261             return;
262         }
263
264         //Remove floating mac from mymac table
265         LOG.debug("Removing FloatingIp {}", externalIp);
266         String floatingIpPortMacAddress = NatUtil.getFloatingIpPortMacFromFloatingIpId(dataBroker, floatingIpId);
267         if (floatingIpPortMacAddress != null) {
268             WriteTransaction writeTx = dataBroker.newWriteOnlyTransaction();
269             String networkVpnName =  NatUtil.getAssociatedVPN(dataBroker, networkId, LOG);
270             vpnManager.setupSubnetMacIntoVpnInstance(networkVpnName, subnetId.getValue(), floatingIpPortMacAddress,
271                     dpnId, writeTx, NwConstants.DEL_FLOW);
272             vpnManager.setupArpResponderFlowsToExternalNetworkIps(routerId, Collections.singletonList(externalIp),
273                 floatingIpPortMacAddress, dpnId, networkId, writeTx, NwConstants.DEL_FLOW);
274             writeTx.submit();
275         }
276         removeFromFloatingIpPortInfo(floatingIpId);
277         ProviderTypes provType = NatEvpnUtil.getExtNwProvTypeFromRouterName(dataBroker, routerId);
278         if (provType == null) {
279             return;
280         }
281         if (provType == ProviderTypes.VXLAN) {
282             Uuid floatingIpInterface = NatEvpnUtil.getFloatingIpInterfaceIdFromFloatingIpId(dataBroker, floatingIpId);
283             evpnDnatFlowProgrammer.onRemoveFloatingIp(dpnId, vpnName, externalIp, floatingIpInterface.getValue(),
284                     floatingIpPortMacAddress, routerId);
285             return;
286         }
287         cleanupFibEntries(dpnId, vpnName, externalIp, label);
288     }
289
290     @Override
291     public void cleanupFibEntries(final BigInteger dpnId, final String vpnName, final String externalIp,
292                                   final long label) {
293         //Remove Prefix from BGP
294         String rd = NatUtil.getVpnRd(dataBroker, vpnName);
295         String fibExternalIp = NatUtil.validateAndAddNetworkMask(externalIp);
296         NatUtil.removePrefixFromBGP(dataBroker, bgpManager, fibManager, rd, fibExternalIp, vpnName, LOG);
297
298         //Remove custom FIB routes
299
300         //Future<RpcResult<java.lang.Void>> removeFibEntry(RemoveFibEntryInput input);
301         RemoveFibEntryInput input = new RemoveFibEntryInputBuilder().setVpnName(vpnName)
302             .setSourceDpid(dpnId).setIpAddress(fibExternalIp).setServiceId(label)
303             .setIpAddressSource(RemoveFibEntryInput.IpAddressSource.FloatingIP).build();
304         Future<RpcResult<Void>> future = fibService.removeFibEntry(input);
305
306         ListenableFuture<RpcResult<Void>> labelFuture = Futures.transformAsync(
307                 JdkFutureAdapters.listenInPoolThread(future),
308                 (AsyncFunction<RpcResult<Void>, RpcResult<Void>>) result -> {
309                 //Release label
310                 if (result.isSuccessful()) {
311                 /*  check if any floating IP information is available in vpn-to-dpn-list for given dpn id. If exist any
312                  *  floating IP then do not remove INTERNAL_TUNNEL_TABLE (table=36) -> PDNAT_TABLE (table=25) flow entry
313                  */
314                     Boolean removeTunnelFlow = Boolean.TRUE;
315                     if (elanService.isOpenStackVniSemanticsEnforced()) {
316                         if (NatUtil.isFloatingIpPresentForDpn(dataBroker, dpnId, rd, vpnName, externalIp, false)) {
317                             removeTunnelFlow = Boolean.FALSE;
318                         }
319                     }
320                     if (removeTunnelFlow) {
321                         removeTunnelTableEntry(dpnId, label);
322                     }
323                     removeLFibTableEntry(dpnId, label);
324                     RemoveVpnLabelInput labelInput = new RemoveVpnLabelInputBuilder()
325                         .setVpnName(vpnName).setIpPrefix(externalIp).build();
326                     Future<RpcResult<Void>> labelFuture1 = vpnService.removeVpnLabel(labelInput);
327                     return JdkFutureAdapters.listenInPoolThread(labelFuture1);
328                 } else {
329                     String errMsg = String.format("RPC call to remove custom FIB entries on dpn %s for "
330                         + "prefix %s Failed - %s", dpnId, externalIp, result.getErrors());
331                     LOG.error(errMsg);
332                     return Futures.immediateFailedFuture(new RuntimeException(errMsg));
333                 }
334             });
335
336         Futures.addCallback(labelFuture, new FutureCallback<RpcResult<Void>>() {
337
338             @Override
339             public void onFailure(Throwable error) {
340                 LOG.error("Error in removing the label or custom fib entries", error);
341             }
342
343             @Override
344             public void onSuccess(RpcResult<Void> result) {
345                 if (result.isSuccessful()) {
346                     LOG.debug("Successfully removed the label for the prefix {} from VPN {}", externalIp, vpnName);
347                 } else {
348                     LOG.error("Error in removing the label for prefix {} from VPN {}, {}",
349                         externalIp, vpnName, result.getErrors());
350                 }
351             }
352         });
353     }
354
355     private String getFlowRef(BigInteger dpnId, short tableId, long id, String ipAddress) {
356         return FLOWID_PREFIX + dpnId + NwConstants.FLOWID_SEPARATOR + tableId + NwConstants.FLOWID_SEPARATOR + id
357                 + NwConstants.FLOWID_SEPARATOR + ipAddress;
358     }
359
360     private void removeTunnelTableEntry(BigInteger dpnId, long serviceId) {
361         LOG.info("remove terminatingServiceActions called with DpnId = {} and label = {}", dpnId, serviceId);
362         List<MatchInfo> mkMatches = new ArrayList<>();
363         // Matching metadata
364         mkMatches.add(new MatchTunnelId(BigInteger.valueOf(serviceId)));
365         Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE,
366             getFlowRef(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, serviceId, ""),
367             5, String.format("%s:%d", "TST Flow Entry ", serviceId), 0, 0,
368             COOKIE_TUNNEL.add(BigInteger.valueOf(serviceId)), mkMatches, null);
369         mdsalManager.removeFlow(dpnId, flowEntity);
370         LOG.debug("Terminating service Entry for dpID {} : label : {} removed successfully {}", dpnId, serviceId);
371     }
372
373     private void makeTunnelTableEntry(String vpnName, BigInteger dpnId, long serviceId,
374             List<Instruction> customInstructions) {
375         List<MatchInfo> mkMatches = new ArrayList<>();
376
377         LOG.info("create terminatingServiceAction on DpnId = {} and serviceId = {} and actions = {}", dpnId, serviceId);
378         int flowPriority = 5;
379         // Increased the 36->25 flow priority. If SNAT is also configured on the same
380         // DPN, then the traffic will be hijacked to DNAT and if there are no DNAT match,
381         // then handled back to using using flow 25->44(which will be installed as part of SNAT)
382         if (elanService.isOpenStackVniSemanticsEnforced()) {
383             mkMatches.add(new MatchTunnelId(NatOverVxlanUtil.getInternetVpnVni(idManager, vpnName, serviceId)));
384             flowPriority = 6;
385         } else {
386             mkMatches.add(new MatchTunnelId(BigInteger.valueOf(serviceId)));
387         }
388
389         Flow terminatingServiceTableFlowEntity = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE,
390             getFlowRef(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, serviceId, ""), flowPriority,
391             String.format("%s:%d", "TST Flow Entry ", serviceId),
392             0, 0, COOKIE_TUNNEL.add(BigInteger.valueOf(serviceId)), mkMatches, customInstructions);
393
394         mdsalManager.installFlow(dpnId, terminatingServiceTableFlowEntity);
395     }
396
397     private void makeLFibTableEntry(BigInteger dpId, long serviceId, String floatingIpPortMacAddress, short tableId) {
398         List<MatchInfo> matches = new ArrayList<>();
399         matches.add(MatchEthernetType.MPLS_UNICAST);
400         matches.add(new MatchMplsLabel(serviceId));
401
402         List<Instruction> instructions = new ArrayList<>();
403         List<ActionInfo> actionsInfos = new ArrayList<>();
404         actionsInfos.add(new ActionPopMpls());
405         actionsInfos.add(new ActionSetFieldEthernetDestination(new MacAddress(floatingIpPortMacAddress)));
406         Instruction writeInstruction = new InstructionApplyActions(actionsInfos).buildInstruction(0);
407         instructions.add(writeInstruction);
408         instructions.add(new InstructionGotoTable(tableId).buildInstruction(1));
409
410         // Install the flow entry in L3_LFIB_TABLE
411         String flowRef = getFlowRef(dpId, NwConstants.L3_LFIB_TABLE, serviceId, "");
412
413         Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.L3_LFIB_TABLE, flowRef,
414             10, flowRef, 0, 0,
415             NwConstants.COOKIE_VM_LFIB_TABLE, matches, instructions);
416
417         mdsalManager.installFlow(dpId, flowEntity);
418
419         LOG.debug("LFIB Entry for dpID {} : label : {} modified successfully {}", dpId, serviceId);
420     }
421
422     private void removeLFibTableEntry(BigInteger dpnId, long serviceId) {
423         List<MatchInfo> matches = new ArrayList<>();
424         matches.add(MatchEthernetType.MPLS_UNICAST);
425         matches.add(new MatchMplsLabel(serviceId));
426
427         String flowRef = getFlowRef(dpnId, NwConstants.L3_LFIB_TABLE, serviceId, "");
428
429         LOG.debug("removing LFib entry with flow ref {}", flowRef);
430
431         Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.L3_LFIB_TABLE, flowRef,
432             10, flowRef, 0, 0,
433             NwConstants.COOKIE_VM_LFIB_TABLE, matches, null);
434
435         mdsalManager.removeFlow(dpnId, flowEntity);
436
437         LOG.debug("LFIB Entry for dpID : {} label : {} removed successfully {}", dpnId, serviceId);
438     }
439
440     // TODO Clean up the exception handling
441     @SuppressWarnings("checkstyle:IllegalCatch")
442     private void sendGarpOnInterface(final BigInteger dpnId, Uuid networkId, final IpAddress floatingIpAddress,
443                                      String floatingIpPortMacAddress) {
444         if (floatingIpAddress.getIpv4Address() == null) {
445             LOG.info("Failed to send GARP for IP. recieved IPv6.");
446             NatServiceCounters.garp_failed_ipv6.inc();
447             return;
448         }
449
450         String interfaceName = elanService.getExternalElanInterface(networkId.getValue(), dpnId);
451         if (interfaceName == null) {
452             LOG.warn("Failed to send GARP for IP. Failed to retrieve interface name from network {} and dpn id {}.",
453                 networkId.getValue(), dpnId);
454             NatServiceCounters.garp_failed_missing_interface.inc();
455         }
456
457         try {
458             // find the external network interface name for dpn
459             List<InterfaceAddress> interfaceAddresses = new ArrayList<>();
460             interfaceAddresses.add(new InterfaceAddressBuilder()
461                 .setInterface(interfaceName)
462                 .setIpAddress(floatingIpAddress)
463                 .setMacaddress(new PhysAddress(floatingIpPortMacAddress)).build());
464
465             SendArpRequestInput sendArpRequestInput = new SendArpRequestInputBuilder().setIpaddress(floatingIpAddress)
466                 .setInterfaceAddress(interfaceAddresses).build();
467             arpUtilService.sendArpRequest(sendArpRequestInput);
468             NatServiceCounters.garp_sent.inc();
469         } catch (Exception e) {
470             LOG.error("Failed to send GARP request for floating ip {} from interface {}",
471                 floatingIpAddress.getIpv4Address().getValue(), interfaceName, e);
472             NatServiceCounters.garp_failed_send.inc();
473         }
474     }
475
476     // TODO Clean up the exception handling
477     @SuppressWarnings("checkstyle:IllegalCatch")
478     private void removeFromFloatingIpPortInfo(Uuid floatingIpId) {
479         InstanceIdentifier id = buildfloatingIpIdToPortMappingIdentifier(floatingIpId);
480         try {
481             Optional<FloatingIpIdToPortMapping> optFloatingIpIdToPortMapping =
482                     SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
483                             LogicalDatastoreType.CONFIGURATION, id);
484             if (optFloatingIpIdToPortMapping.isPresent() && optFloatingIpIdToPortMapping.get().isFloatingIpDeleted()) {
485                 LOG.debug("Deleting floating IP UUID {} to Floating IP neutron port mapping from Floating "
486                     + "IP Port Info Config DS", floatingIpId.getValue());
487                 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
488             }
489         } catch (Exception e) {
490             LOG.error("Deleting floating IP UUID {} to Floating IP neutron port mapping from Floating "
491                 + "IP Port Info Config DS failed with exception {}", floatingIpId.getValue(), e);
492         }
493     }
494
495 }