2 * Copyright © 2016, 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
8 package org.opendaylight.netvirt.natservice.internal;
10 import static org.opendaylight.netvirt.natservice.internal.NatUtil.buildfloatingIpIdToPortMappingIdentifier;
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;
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.";
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;
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);
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) {
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) {
162 GenerateVpnLabelInput labelInput = new GenerateVpnLabelInputBuilder().setVpnName(vpnName)
163 .setIpPrefix(externalIp).build();
164 Future<RpcResult<GenerateVpnLabelOutput>> labelFuture = vpnService.generateVpnLabel(labelInput);
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);
177 if (elanService.isOpenStackVniSemanticsEnforced()) {
178 l3vni = NatOverVxlanUtil.getInternetVpnVni(idManager, vpnName, l3vni).longValue();
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);
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);
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));
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);
216 return JdkFutureAdapters.listenInPoolThread(future1);
218 String errMsg = String.format("Could not retrieve the label for prefix %s in VPN %s, %s",
219 externalIp, vpnName, result.getErrors());
221 return Futures.immediateFailedFuture(new RuntimeException(errMsg));
225 Futures.addCallback(future, new FutureCallback<RpcResult<Void>>() {
228 public void onFailure(Throwable error) {
229 LOG.error("Error in generate label or fib install process", error);
233 public void onSuccess(RpcResult<Void> result) {
234 if (result.isSuccessful()) {
235 LOG.info("Successfully installed custom FIB routes for prefix {}", externalIp);
237 LOG.error("Error in rpc call to create custom Fib entries for prefix {} in DPN {}, {}",
238 externalIp, dpnId, result.getErrors());
243 // Handle GARP transmission
244 final IpAddress extrenalAddress = IpAddressBuilder.getDefaultInstance(externalIp);
245 sendGarpOnInterface(dpnId, networkId, extrenalAddress, floatingIpPortMacAddress);
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);
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);
276 removeFromFloatingIpPortInfo(floatingIpId);
277 ProviderTypes provType = NatEvpnUtil.getExtNwProvTypeFromRouterName(dataBroker, routerId);
278 if (provType == null) {
281 if (provType == ProviderTypes.VXLAN) {
282 Uuid floatingIpInterface = NatEvpnUtil.getFloatingIpInterfaceIdFromFloatingIpId(dataBroker, floatingIpId);
283 evpnDnatFlowProgrammer.onRemoveFloatingIp(dpnId, vpnName, externalIp, floatingIpInterface.getValue(),
284 floatingIpPortMacAddress, routerId);
287 cleanupFibEntries(dpnId, vpnName, externalIp, label);
291 public void cleanupFibEntries(final BigInteger dpnId, final String vpnName, final String externalIp,
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);
298 //Remove custom FIB routes
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);
306 ListenableFuture<RpcResult<Void>> labelFuture = Futures.transformAsync(
307 JdkFutureAdapters.listenInPoolThread(future),
308 (AsyncFunction<RpcResult<Void>, RpcResult<Void>>) result -> {
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
314 Boolean removeTunnelFlow = Boolean.TRUE;
315 if (elanService.isOpenStackVniSemanticsEnforced()) {
316 if (NatUtil.isFloatingIpPresentForDpn(dataBroker, dpnId, rd, vpnName, externalIp, false)) {
317 removeTunnelFlow = Boolean.FALSE;
320 if (removeTunnelFlow) {
321 removeTunnelTableEntry(dpnId, label);
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);
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());
332 return Futures.immediateFailedFuture(new RuntimeException(errMsg));
336 Futures.addCallback(labelFuture, new FutureCallback<RpcResult<Void>>() {
339 public void onFailure(Throwable error) {
340 LOG.error("Error in removing the label or custom fib entries", error);
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);
348 LOG.error("Error in removing the label for prefix {} from VPN {}, {}",
349 externalIp, vpnName, result.getErrors());
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;
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<>();
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);
373 private void makeTunnelTableEntry(String vpnName, BigInteger dpnId, long serviceId,
374 List<Instruction> customInstructions) {
375 List<MatchInfo> mkMatches = new ArrayList<>();
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)));
386 mkMatches.add(new MatchTunnelId(BigInteger.valueOf(serviceId)));
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);
394 mdsalManager.installFlow(dpnId, terminatingServiceTableFlowEntity);
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));
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));
410 // Install the flow entry in L3_LFIB_TABLE
411 String flowRef = getFlowRef(dpId, NwConstants.L3_LFIB_TABLE, serviceId, "");
413 Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.L3_LFIB_TABLE, flowRef,
415 NwConstants.COOKIE_VM_LFIB_TABLE, matches, instructions);
417 mdsalManager.installFlow(dpId, flowEntity);
419 LOG.debug("LFIB Entry for dpID {} : label : {} modified successfully {}", dpId, serviceId);
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));
427 String flowRef = getFlowRef(dpnId, NwConstants.L3_LFIB_TABLE, serviceId, "");
429 LOG.debug("removing LFib entry with flow ref {}", flowRef);
431 Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.L3_LFIB_TABLE, flowRef,
433 NwConstants.COOKIE_VM_LFIB_TABLE, matches, null);
435 mdsalManager.removeFlow(dpnId, flowEntity);
437 LOG.debug("LFIB Entry for dpID : {} label : {} removed successfully {}", dpnId, serviceId);
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();
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();
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());
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();
476 // TODO Clean up the exception handling
477 @SuppressWarnings("checkstyle:IllegalCatch")
478 private void removeFromFloatingIpPortInfo(Uuid floatingIpId) {
479 InstanceIdentifier id = buildfloatingIpIdToPortMappingIdentifier(floatingIpId);
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);
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);