2 * Copyright (c) 2016 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.vpnmanager;
10 import java.math.BigInteger;
11 import java.util.Arrays;
12 import java.util.List;
13 import java.util.concurrent.Future;
14 import java.util.concurrent.TimeUnit;
16 import org.apache.commons.lang3.tuple.ImmutablePair;
17 import org.apache.commons.lang3.tuple.Pair;
18 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
19 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
20 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
21 import org.opendaylight.genius.mdsalutil.MDSALUtil;
22 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
23 import org.opendaylight.netvirt.elanmanager.api.IElanService;
24 import org.opendaylight.netvirt.vpnmanager.utilities.InterfaceUtils;
25 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnAfConfig;
26 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
27 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
28 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceBuilder;
29 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey;
30 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
31 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
32 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
33 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.ArpRequestReceived;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.ArpResponseReceived;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.MacChanged;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.OdlArputilListener;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.OdlArputilService;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.SendArpResponseInput;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.SendArpResponseInputBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.Adjacencies;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyKey;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance.VpnIds;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPort;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.floatingips.attributes.Floatingips;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.floatingips.attributes.floatingips.Floatingip;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.PortKey;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.Subnets;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.SubnetKey;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.config.rev161130.VpnConfig;
59 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
60 import org.opendaylight.yangtools.yang.common.RpcResult;
61 import org.slf4j.Logger;
62 import org.slf4j.LoggerFactory;
64 import com.google.common.base.Optional;
65 import com.google.common.cache.Cache;
66 import com.google.common.cache.CacheBuilder;
67 import com.google.common.collect.Maps;
68 import com.google.common.util.concurrent.FutureCallback;
69 import com.google.common.util.concurrent.Futures;
70 import com.google.common.util.concurrent.JdkFutureAdapters;
73 public class ArpNotificationHandler implements OdlArputilListener {
74 private static final Logger LOG = LoggerFactory.getLogger(ArpNotificationHandler.class);
75 // temp where Key is VPNInstance+IP and value is timestamp
76 private final Cache<Pair<String, String>, BigInteger> migrateArpReqCache;
78 DataBroker dataBroker;
79 VpnInterfaceManager vpnIfManager;
80 IdManagerService idManager;
81 OdlArputilService arpManager;
82 final IElanService elanService;
83 ArpMonitoringHandler arpScheduler;
84 OdlInterfaceRpcService ifaceMgrRpcService;
85 IInterfaceManager interfaceManager;
86 private final VpnConfig config;
89 public ArpNotificationHandler(DataBroker dataBroker, VpnInterfaceManager vpnIfMgr,
90 final IElanService elanService, IdManagerService idManager, OdlArputilService arpManager,
91 ArpMonitoringHandler arpScheduler, OdlInterfaceRpcService ifaceMgrRpcService,
92 IInterfaceManager interfaceManager, VpnConfig vpnConfig) {
93 this.dataBroker = dataBroker;
94 vpnIfManager = vpnIfMgr;
95 this.elanService = elanService;
96 this.idManager = idManager;
97 this.arpManager = arpManager;
98 this.arpScheduler = arpScheduler;
99 this.ifaceMgrRpcService = ifaceMgrRpcService;
100 this.interfaceManager = interfaceManager;
101 this.config = vpnConfig;
103 long duration = config.getArpLearnTimeout() * 10;
104 long cacheSize = config.getArpCacheSize().longValue();
106 CacheBuilder.newBuilder().maximumSize(cacheSize).expireAfterWrite(duration, TimeUnit.MILLISECONDS).build();
110 public void onMacChanged(MacChanged notification){
115 public void onArpRequestReceived(ArpRequestReceived notification){
116 LOG.trace("ArpNotification Request Received from interface {} and IP {} having MAC {} target destination {}",
117 notification.getInterface(), notification.getSrcIpaddress().getIpv4Address().getValue(),
118 notification.getSrcMac().getValue(),notification.getDstIpaddress().getIpv4Address().getValue());
119 String srcInterface = notification.getInterface();
120 IpAddress srcIP = notification.getSrcIpaddress();
121 PhysAddress srcMac = notification.getSrcMac();
122 IpAddress targetIP = notification.getDstIpaddress();
123 BigInteger metadata = notification.getMetadata();
124 if (metadata != null && metadata != BigInteger.ZERO) {
125 long vpnId = MetaDataUtil.getVpnIdFromMetadata(metadata);
126 // Respond to ARP request only if vpnservice is configured on the interface
127 InstanceIdentifier<VpnIds> vpnIdsInstanceIdentifier = VpnUtil.getVpnIdToVpnInstanceIdentifier(vpnId);
128 Optional<VpnIds> vpnIdsOptional
129 = VpnUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdsInstanceIdentifier);
130 if (!vpnIdsOptional.isPresent()) {
131 // Donot respond to ARP requests on unknown VPNs
132 LOG.trace("ARP NO_RESOLVE: VPN {} not configured. Ignoring responding to ARP requests on this VPN", vpnId);
135 VpnIds vpnIds = vpnIdsOptional.get();
136 String vpnName = vpnIds.getVpnInstanceName();
137 if (VpnUtil.isInterfaceAssociatedWithVpn(dataBroker, vpnName, srcInterface)) {
138 LOG.debug("Received ARP request for target IP {}, sender MAC {} and sender IP {} via interface {}",
139 targetIP.getIpv4Address().getValue(), srcMac.getValue(), srcIP.getIpv4Address().getValue(), srcInterface);
140 String ipToQuery = notification.getSrcIpaddress().getIpv4Address().getValue();
141 LOG.trace("ArpRequest being processed for Source IP {}", ipToQuery);
142 VpnPortipToPort vpnPortipToPort = VpnUtil.getNeutronPortFromVpnPortFixedIp(dataBroker, vpnName, ipToQuery);
143 boolean isGarp = srcIP.equals(targetIP);
144 if (isGarp && vpnPortipToPort != null) {
145 String oldPortName = vpnPortipToPort.getPortName();
146 String oldMac = vpnPortipToPort.getMacAddress();
147 if (!oldMac.equalsIgnoreCase(srcMac.getValue())) {
148 //MAC has changed for requested IP
149 LOG.trace("ARP request Source IP/MAC data modified for IP {} with MAC {} and Port {}",
150 ipToQuery, srcMac, srcInterface);
151 if (!vpnPortipToPort.isConfig()) {
152 synchronized ((vpnName + ipToQuery).intern()) {
153 removeMipAdjacency(vpnName, oldPortName, srcIP);
154 VpnUtil.removeVpnPortFixedIpToPort(dataBroker, vpnName, ipToQuery);
156 putVpnIpToMigrateArpCache(vpnName, ipToQuery, srcMac);
159 //MAC mismatch for a Neutron learned IP
160 LOG.warn("MAC Address mismatch for Interface {} having a Mac {}, IP {} and ARP learnt Mac {}",
161 oldPortName, oldMac, ipToQuery, srcMac.getValue());
165 } else if (isGarp && shouldLearnMacFromArpPackets(vpnName, ipToQuery)) {
166 learnMacFromArpPackets(vpnName, srcInterface, srcIP, srcMac);
168 if (elanService.isExternalInterface(srcInterface)) {
169 handleArpRequestFromExternalInterface(srcInterface, srcIP, srcMac, targetIP);
176 private void handleArpRequestForSubnetIp(String srcInterface, IpAddress srcIP, PhysAddress srcMac,
177 IpAddress targetIP, VpnPortipToPort vpnTargetIpToPort) {
178 String macAddress = vpnTargetIpToPort.getMacAddress();
179 PhysAddress targetMac = new PhysAddress(macAddress);
180 processArpRequest(srcIP, srcMac, targetIP, targetMac, srcInterface);
184 private void handleArpRequestForExternalVpn(String srcInterface, IpAddress srcIP, PhysAddress srcMac,
185 IpAddress targetIP, String targetIpToQuery, VpnPortipToPort vpnTargetIpToPort) {
186 if (vpnTargetIpToPort != null) {
187 if (vpnTargetIpToPort.isSubnetIp()) {
188 handleArpRequestForSubnetIp(srcInterface, srcIP, srcMac, targetIP, vpnTargetIpToPort);
192 // Respond for gateway Ips ARP requests if L3vpn configured without a router
195 Uuid portUuid = new Uuid(srcInterface);
196 InstanceIdentifier<Port> inst = InstanceIdentifier.create(Neutron.class).child(Ports.class)
197 .child(Port.class, new PortKey(portUuid));
198 Optional<Port> port = VpnUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, inst);
199 if (port.isPresent()) {
201 //TODO(Gobinath): Need to fix this as assuming port will belong to only one Subnet would be incorrect"
202 Uuid subnetUUID = prt.getFixedIps().get(0).getSubnetId();
203 LOG.trace("Subnet UUID for this VPN Interface is {}", subnetUUID);
204 SubnetKey subnetkey = new SubnetKey(subnetUUID);
205 InstanceIdentifier<Subnet> subnetidentifier = InstanceIdentifier.create(Neutron.class)
206 .child(Subnets.class).child(Subnet.class, subnetkey);
207 Optional<Subnet> subnet = VpnUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
209 if (subnet.isPresent()) {
210 gw = subnet.get().getGatewayIp().getIpv4Address().getValue();
211 if (targetIpToQuery.equalsIgnoreCase(gw)) {
212 LOG.trace("Target Destination matches the Gateway IP {} so respond for ARP", gw);
213 processArpRequest(srcIP, srcMac, targetIP, null, srcInterface);
220 public void onArpResponseReceived(ArpResponseReceived notification){
221 LOG.trace("ArpNotification Response Received from interface {} and IP {} having MAC {}",notification.getInterface(),
222 notification.getIpaddress().getIpv4Address().getValue(), notification.getMacaddress().getValue());
223 String srcInterface = notification.getInterface();
224 IpAddress srcIP = notification.getIpaddress();
225 PhysAddress srcMac = notification.getMacaddress();
226 BigInteger metadata = notification.getMetadata();
227 if (metadata != null && metadata != BigInteger.ZERO) {
228 long vpnId = MetaDataUtil.getVpnIdFromMetadata(metadata);
229 InstanceIdentifier<VpnIds>
230 vpnIdsInstanceIdentifier = VpnUtil.getVpnIdToVpnInstanceIdentifier(vpnId);
231 Optional<VpnIds> vpnIdsOptional
232 = VpnUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdsInstanceIdentifier);
233 if (!vpnIdsOptional.isPresent()) {
234 // Donot respond to ARP requests on unknown VPNs
235 LOG.trace("ARP NO_RESOLVE: VPN {} not configured. Ignoring responding to ARP requests on this VPN", vpnId);
238 String vpnName = vpnIdsOptional.get().getVpnInstanceName();
239 if (VpnUtil.isInterfaceAssociatedWithVpn(dataBroker, vpnName, srcInterface)) {
240 String ipToQuery = notification.getIpaddress().getIpv4Address().getValue();
241 VpnPortipToPort vpnPortipToPort = VpnUtil.getNeutronPortFromVpnPortFixedIp(dataBroker, vpnName, ipToQuery);
242 if (vpnPortipToPort != null) {
243 String oldMac = vpnPortipToPort.getMacAddress();
244 String oldPortName = vpnPortipToPort.getPortName();
245 if (!oldMac.equalsIgnoreCase(srcMac.getValue())) {
246 //MAC has changed for requested IP
247 LOG.trace("ARP response Source IP/MAC data modified for IP {} with MAC {} and Port {}",
248 ipToQuery, srcMac, srcInterface);
249 if (!vpnPortipToPort.isConfig()) {
250 synchronized ((vpnName + ipToQuery).intern()) {
251 removeMipAdjacency(vpnName, oldPortName, srcIP);
252 VpnUtil.removeVpnPortFixedIpToPort(dataBroker, vpnName, ipToQuery);
254 putVpnIpToMigrateArpCache(vpnName, ipToQuery, srcMac);
257 //MAC mismatch for a Neutron learned IP set learnt back to false
258 LOG.warn("MAC Address mismatch for Interface {} having a Mac {} , IP {} and Arp learnt Mac {}",
259 srcInterface, oldMac, ipToQuery, srcMac.getValue());
262 } else if (shouldLearnMacFromArpPackets(vpnName, ipToQuery)) {
263 learnMacFromArpPackets(vpnName, srcInterface, srcIP, srcMac);
269 private void learnMacFromArpPackets(String vpnName, String srcInterface,
270 IpAddress srcIP, PhysAddress srcMac) {
271 String ipToQuery = srcIP.getIpv4Address().getValue();
272 /* Traffic coming from external interfaces should always be learnt */
273 if (interfaceManager.isExternalInterface(srcInterface) ||
274 !VpnUtil.isNeutronPortConfigured(dataBroker, srcInterface, srcIP)) {
275 synchronized ((vpnName + ipToQuery).intern()) {
276 VpnUtil.createVpnPortFixedIpToPort(dataBroker, vpnName, ipToQuery, srcInterface,
277 srcMac.getValue(), false, false, true);
278 addMipAdjacency(vpnName, srcInterface, srcIP, srcMac.getValue());
283 private void handleArpRequestFromExternalInterface(String srcInterface, IpAddress srcIP, PhysAddress srcMac,
284 IpAddress targetIP) {
285 Port port = VpnUtil.getNeutronPortForFloatingIp(dataBroker, targetIP);
286 String floatingIp = targetIP.getIpv4Address().getValue();
288 LOG.trace("No neutron port found for with floating ip {}", floatingIp);
292 MacAddress targetMac = port.getMacAddress();
293 if (targetMac == null) {
294 LOG.trace("No mac address found for floating ip {}", floatingIp);
298 // don't allow ARP responses if it arrives from different dpn
299 String localPortInterface = getFloatingInternalInterface(floatingIp);
300 if (localPortInterface != null && !localPortInterface.isEmpty()) {
301 BigInteger dpnIdSrc = InterfaceUtils.getDpnForInterface(ifaceMgrRpcService, srcInterface);
302 BigInteger dpnIdLocal = InterfaceUtils.getDpnForInterface(ifaceMgrRpcService, localPortInterface);
303 if (!dpnIdSrc.equals(dpnIdLocal)) {
304 LOG.trace("Not same dpnId, so don't respond for ARP - dpnIdSrc:{} dpnIdLocal:{}", dpnIdSrc, dpnIdLocal);
308 LOG.trace("Target destination matches floating IP {} so respond for ARP", floatingIp);
309 vpnIfManager.processArpRequest(srcIP, srcMac, targetIP, new PhysAddress(targetMac.getValue()), srcInterface);
312 public void processArpRequest(IpAddress srcIP, PhysAddress srcMac, IpAddress targetIP, PhysAddress targetMac,
313 String srcInterface){
314 //Build ARP response with ARP requests TargetIp TargetMac as the Arp Response SrcIp and SrcMac
315 SendArpResponseInput input = new SendArpResponseInputBuilder().setInterface(srcInterface)
316 .setDstIpaddress(srcIP).setDstMacaddress(srcMac).setSrcIpaddress(targetIP).setSrcMacaddress(targetMac).build();
317 final String msgFormat = String.format("Send ARP Response on interface %s to destination %s", srcInterface, srcIP);
318 Future<RpcResult<Void>> future = arpManager.sendArpResponse(input);
319 Futures.addCallback(JdkFutureAdapters.listenInPoolThread(future), new FutureCallback<RpcResult<Void>>() {
321 public void onFailure(Throwable error) {
322 LOG.error("Error - {}", msgFormat, error);
326 public void onSuccess(RpcResult<Void> result) {
327 if(!result.isSuccessful()) {
328 LOG.warn("Rpc call to {} failed", msgFormat);
330 LOG.debug("Successful RPC Result - {}", msgFormat);
336 private void addMipAdjacency(String vpnName, String vpnInterface, IpAddress prefix, String mipMacAddress){
338 LOG.trace("Adding {} adjacency to VPN Interface {} ",prefix,vpnInterface);
339 InstanceIdentifier<VpnInterface> vpnIfId = VpnUtil.getVpnInterfaceIdentifier(vpnInterface);
340 InstanceIdentifier<Adjacencies> path = vpnIfId.augmentation(Adjacencies.class);
341 synchronized (vpnInterface.intern()) {
342 Optional<Adjacencies> adjacencies = VpnUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, path);
343 String nextHopIpAddr = null;
344 String nextHopMacAddress = null;
345 String ip = prefix.getIpv4Address().getValue();
346 if (adjacencies.isPresent()) {
347 List<Adjacency> adjacencyList = adjacencies.get().getAdjacency();
348 ip = VpnUtil.getIpPrefix(ip);
349 for (Adjacency adjacs : adjacencyList) {
350 if (adjacs.isPrimaryAdjacency()) {
351 nextHopIpAddr = adjacs.getIpAddress();
352 nextHopMacAddress = adjacs.getMacAddress();
356 if (nextHopIpAddr != null) {
357 String rd = VpnUtil.getVpnRd(dataBroker, vpnName);
359 VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME,
360 VpnUtil.getNextHopLabelKey((rd != null) ? rd : vpnName, ip));
362 LOG.error("Unable to fetch label from Id Manager. Bailing out of adding MIP adjacency {} "
363 + "to vpn interface {} for vpn {}", ip, vpnInterface, vpnName);
366 String nextHopIp = nextHopIpAddr.split("/")[0];
367 AdjacencyBuilder newAdjBuilder = new AdjacencyBuilder().setIpAddress(ip).setKey
368 (new AdjacencyKey(ip)).setNextHopIpList(Arrays.asList(nextHopIp));
369 if (mipMacAddress != null && !mipMacAddress.equals(nextHopMacAddress)) {
370 newAdjBuilder.setMacAddress(mipMacAddress);
372 adjacencyList.add(newAdjBuilder.build());
373 Adjacencies aug = VpnUtil.getVpnInterfaceAugmentation(adjacencyList);
374 VpnInterface newVpnIntf = new VpnInterfaceBuilder().setKey(new VpnInterfaceKey(vpnInterface)).
375 setName(vpnInterface).setVpnInstanceName(vpnName).addAugmentation(Adjacencies.class, aug)
377 VpnUtil.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIfId, newVpnIntf);
378 LOG.debug(" Successfully stored subnetroute Adjacency into VpnInterface {}", vpnInterface);
385 private void removeMipAdjacency(String vpnName, String vpnInterface, IpAddress prefix) {
386 String ip = VpnUtil.getIpPrefix(prefix.getIpv4Address().getValue());
387 LOG.trace("Removing {} adjacency from Old VPN Interface {} ", ip,vpnInterface);
388 InstanceIdentifier<VpnInterface> vpnIfId = VpnUtil.getVpnInterfaceIdentifier(vpnInterface);
389 InstanceIdentifier<Adjacencies> path = vpnIfId.augmentation(Adjacencies.class);
390 synchronized (vpnInterface.intern()) {
391 Optional<Adjacencies> adjacencies = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, path);
392 if (adjacencies.isPresent()) {
393 InstanceIdentifier<Adjacency> adjacencyIdentifier = InstanceIdentifier.builder(VpnInterfaces.class).
394 child(VpnInterface.class, new VpnInterfaceKey(vpnInterface)).augmentation(Adjacencies.class)
395 .child(Adjacency.class, new AdjacencyKey(ip)).build();
396 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, adjacencyIdentifier);
397 LOG.trace("Successfully Deleted Adjacency into VpnInterface {}", vpnInterface);
402 public String getFloatingInternalInterface(String targetIpValue) {
403 if (targetIpValue == null || targetIpValue.isEmpty()) {
406 InstanceIdentifier<Floatingips> identifier = InstanceIdentifier.create(Neutron.class).child(Floatingips.class);
407 Optional<Floatingips> optInterface = VpnUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, identifier);
408 if (optInterface.isPresent()) {
409 Floatingips fips = optInterface.get();
411 for (Floatingip fip : fips.getFloatingip()) {
412 String ipv4Addr = fip.getFloatingIpAddress().getIpv4Address().getValue();
413 if (targetIpValue.equals(ipv4Addr)) {
414 return fip.getPortId().getValue();
422 private void putVpnIpToMigrateArpCache(String vpnName, String ipToQuery, PhysAddress srcMac) {
423 long cacheSize = config.getArpCacheSize().longValue();
424 if (migrateArpReqCache.size() >= cacheSize) {
425 LOG.debug("ARP_MIGRATE_CACHE: max size {} reached, assuming cache eviction we still put IP {}"
426 + " vpnName {} with MAC {}", cacheSize, ipToQuery, vpnName, srcMac);
428 LOG.debug("ARP_MIGRATE_CACHE: add to dirty cache IP {} vpnName {} with MAC {}", ipToQuery, vpnName, srcMac);
429 migrateArpReqCache.put(new ImmutablePair<>(vpnName, ipToQuery),
430 new BigInteger(String.valueOf(System.currentTimeMillis())));
433 private boolean shouldLearnMacFromArpPackets(String vpnName, String ipToQuery) {
434 if (migrateArpReqCache == null || migrateArpReqCache.size() == 0) {
437 Pair<String, String> keyPair = new ImmutablePair<>(vpnName, ipToQuery);
438 BigInteger prevTimeStampCached = migrateArpReqCache.getIfPresent(keyPair);
439 if (prevTimeStampCached == null) {
440 LOG.debug("ARP_MIGRATE_CACHE: there is no IP {} vpnName {} in dirty cache, so learn it",
444 if (System.currentTimeMillis() > prevTimeStampCached.longValue() + config.getArpLearnTimeout()) {
445 LOG.debug("ARP_MIGRATE_CACHE: older than timeout value - remove from dirty cache IP {} vpnName {}",
447 migrateArpReqCache.invalidate(keyPair);
450 LOG.debug("ARP_MIGRATE_CACHE: younger than timeout value - ignore learning IP {} vpnName {}",