org.opendaylight.netvirt.natservice.internal.NatArpNotificationHandler Maven / Gradle / Ivy
/*
* Copyright (c) 2018 Red Hat, Inc. and others. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
package org.opendaylight.netvirt.natservice.internal;
import java.util.List;
import java.util.Objects;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
import org.opendaylight.netvirt.elanmanager.api.IElanService;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.ArpRequestReceived;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.ArpResponseReceived;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.MacChanged;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.OdlArputilListener;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterface;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.elan._interface.StaticMacEntries;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.router.interfaces.RouterInterface;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.neutron.vip.states.VipState;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Singleton
public class NatArpNotificationHandler implements OdlArputilListener {
private static final Logger LOG = LoggerFactory.getLogger(NatArpNotificationHandler.class);
private final DataBroker dataBroker;
private final IElanService elanService;
private final NatSouthboundEventHandlers southboundEventHandlers;
private final VipStateTracker vipStateTracker;
@Inject
public NatArpNotificationHandler(final DataBroker dataBroker,
final IElanService elanService,
final NatSouthboundEventHandlers southboundEventHandlers,
final VipStateTracker vipStateTracker) {
this.dataBroker = dataBroker;
this.elanService = elanService;
this.southboundEventHandlers = southboundEventHandlers;
this.vipStateTracker = vipStateTracker;
}
@Override
public void onArpResponseReceived(ArpResponseReceived notification) {
}
@Override
public void onMacChanged(MacChanged notification) {
}
@Override
public void onArpRequestReceived(ArpRequestReceived notification) {
LOG.debug("NatArpNotificationHandler received {}", notification);
IpAddress srcIp = notification.getSrcIpaddress();
if (srcIp == null || !Objects.equals(srcIp, notification.getDstIpaddress())) {
LOG.debug("NatArpNotificationHandler: ignoring ARP packet, not gratuitous {}", notification);
return;
}
//Since the point of all this is to learn VIPs those are by definition
//not the IP addresses assigned to a port by neutron configuration.
ElanInterface arpSenderIfc = elanService.getElanInterfaceByElanInterfaceName(notification.getInterface());
if (ipBelongsToElanInterface(arpSenderIfc, srcIp)) {
LOG.debug("NatArpNotificationHandler: ignoring GARP packet. No need to NAT a port's static IP. {}",
notification);
return;
}
ElanInterface targetIfc = null;
for (String ifcName : elanService.getElanInterfaces(arpSenderIfc.getElanInstanceName())) {
ElanInterface elanInterface = elanService.getElanInterfaceByElanInterfaceName(ifcName);
if (ipBelongsToElanInterface(elanInterface, srcIp)) {
targetIfc = elanInterface;
break;
}
}
if (null == targetIfc) {
LOG.warn("NatArpNotificationHandler: GARP does not correspond to an interface in this elan {}",
notification);
return;
}
RouterInterface routerInterface = NatUtil.getConfiguredRouterInterface(dataBroker, targetIfc.getName());
if (null == routerInterface) {
LOG.warn("NatArpNotificationHandler: Could not retrieve router ifc for {}", targetIfc);
return;
}
VipState newVipState = this.vipStateTracker.buildVipState(srcIp.getIpv4Address().getValue(),
notification.getDpnId(), targetIfc.getName());
VipState cachedState = null;
try {
cachedState = this.vipStateTracker.get(newVipState.getIp()).orNull();
} catch (ReadFailedException e) {
LOG.warn("NatArpNotificationHandler failed to read vip state {}", notification, e);
}
if (null == cachedState) {
this.southboundEventHandlers.handleAdd(
targetIfc.getName(), notification.getDpnId(), routerInterface, newVipState);
} else if (!cachedState.getDpnId().equals(newVipState.getDpnId())) {
this.southboundEventHandlers.handleRemove(cachedState.getIfcName(),
cachedState.getDpnId(), routerInterface);
this.southboundEventHandlers.handleAdd(
targetIfc.getName(), notification.getDpnId(), routerInterface, newVipState);
}
}
private boolean ipBelongsToElanInterface(ElanInterface elanInterface, IpAddress ip) {
if (elanInterface == null) {
return false;
}
List staticMacEntries = elanInterface.getStaticMacEntries();
if (null == staticMacEntries) {
return false;
}
for (StaticMacEntries staticMacEntry : staticMacEntries) {
if (Objects.equals(staticMacEntry.getIpPrefix(), ip)) {
return true;
}
}
return false;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy