+++ /dev/null
-/*
- * Copyright (c) 2016 - 2017 Ericsson India Global Services Pvt Ltd. 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 com.google.common.base.Optional;
-import com.google.common.util.concurrent.ListenableFuture;
-import java.math.BigInteger;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Future;
-import javax.annotation.PostConstruct;
-import javax.inject.Inject;
-import javax.inject.Singleton;
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
-import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
-import org.opendaylight.genius.mdsalutil.FlowEntity;
-import org.opendaylight.genius.mdsalutil.NwConstants;
-import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
-import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
-import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
-import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.vpn._interface.VpnInstanceNames;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.L2vlan;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn._interface.op.data.VpnInterfaceOpDataEntry;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.NaptSwitches;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ProtocolTypes;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.RouterPorts;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.Ports;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.ports.InternalToExternalPortMap;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.intext.ip.protocol.type.ip.port.map.IpPortExternal;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.napt.switches.RouterToNaptSwitch;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.napt.switches.RouterToNaptSwitchKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.snatint.ip.port.map.intip.port.map.IpPort;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.snatint.ip.port.map.intip.port.map.ip.port.IntIpProtoType;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortInputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortOutput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NeutronvpnService;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-@Singleton
-public class InterfaceStateEventListener
- extends AsyncDataTreeChangeListenerBase<Interface, InterfaceStateEventListener> {
-
- private static final Logger LOG = LoggerFactory.getLogger(InterfaceStateEventListener.class);
-
- private static final String NAT_FLOW = "NATFLOW";
-
- private final DataBroker dataBroker;
- private final IMdsalApiManager mdsalManager;
- private final FloatingIPListener floatingIPListener;
- private final NaptManager naptManager;
- private final NeutronvpnService neutronVpnService;
- private final JobCoordinator coordinator;
-
- @Inject
- public InterfaceStateEventListener(final DataBroker dataBroker, final IMdsalApiManager mdsalManager,
- final FloatingIPListener floatingIPListener,
- final NaptManager naptManager,
- final NeutronvpnService neutronvpnService,
- final JobCoordinator coordinator) {
- super(Interface.class, InterfaceStateEventListener.class);
- this.dataBroker = dataBroker;
- this.mdsalManager = mdsalManager;
- this.floatingIPListener = floatingIPListener;
- this.naptManager = naptManager;
- this.neutronVpnService = neutronvpnService;
- this.coordinator = coordinator;
- }
-
- @Override
- @PostConstruct
- public void init() {
- LOG.info("{} init", getClass().getSimpleName());
- registerListener(LogicalDatastoreType.OPERATIONAL, dataBroker);
- }
-
- @Override
- protected InstanceIdentifier<Interface> getWildCardPath() {
- return InstanceIdentifier.create(InterfacesState.class).child(Interface.class);
- }
-
- @Override
- protected InterfaceStateEventListener getDataTreeChangeListener() {
- return InterfaceStateEventListener.this;
- }
-
- @Override
- // TODO Clean up the exception handling
- @SuppressWarnings("checkstyle:IllegalCatch")
- protected void remove(InstanceIdentifier<Interface> identifier, Interface delintrf) {
- LOG.trace("remove : Interface {} removed event received", delintrf);
- if (!L2vlan.class.equals(delintrf.getType())) {
- LOG.debug("remove : Interface {} is a not type Vlan.Ignoring", delintrf.getName());
- return;
- }
-
- NatFlowRemoveWorker natFlowRemoveWorker =
- new NatFlowRemoveWorker(delintrf);
- coordinator.enqueueJob(NAT_FLOW + "-" + delintrf.getName(), natFlowRemoveWorker,
- NatConstants.NAT_DJC_MAX_RETRIES);
- }
-
- @Override
- // TODO Clean up the exception handling
- @SuppressWarnings("checkstyle:IllegalCatch")
- protected void update(InstanceIdentifier<Interface> identifier, Interface original, Interface update) {
- LOG.trace("update : Operation Interface update event - Old: {}, New: {}", original, update);
- if (!L2vlan.class.equals(update.getType())) {
- LOG.debug("update : Interface {} is not type Vlan.Ignoring", update.getName());
- return;
- }
-
- NatFlowUpdateWorker natFlowUpdateWorker =
- new NatFlowUpdateWorker(update);
- coordinator.enqueueJob(NAT_FLOW + "-" + update.getName(), natFlowUpdateWorker,
- NatConstants.NAT_DJC_MAX_RETRIES);
-
- }
-
- @Override
- // TODO Clean up the exception handling
- @SuppressWarnings("checkstyle:IllegalCatch")
- protected void add(InstanceIdentifier<Interface> identifier, Interface intrf) {
- LOG.trace("add : Interface {} up event received", intrf);
- if (!L2vlan.class.equals(intrf.getType())) {
- LOG.debug("add : Interface {} is not type vlan.Ignoring", intrf.getName());
- return;
- }
-
- NatFlowAddWorker natFlowAddWorker =
- new NatFlowAddWorker(intrf);
- coordinator.enqueueJob(NAT_FLOW + "-" + intrf.getName(), natFlowAddWorker,
- NatConstants.NAT_DJC_MAX_RETRIES);
- }
-
- // TODO Clean up the exception handling
- @SuppressWarnings("checkstyle:IllegalCatch")
- private void removeSnatEntriesForPort(String interfaceName, String routerName) {
- Long routerId = NatUtil.getVpnId(dataBroker, routerName);
- if (routerId == NatConstants.INVALID_ID) {
- LOG.error("removeSnatEntriesForPort : routerId not found for routername {}", routerName);
- return;
- }
- BigInteger naptSwitch = getNaptSwitchforRouter(dataBroker, routerName);
- if (naptSwitch == null || naptSwitch.equals(BigInteger.ZERO)) {
- LOG.error("removeSnatEntriesForPort : NaptSwitch is not elected for router {} with Id {}",
- routerName, routerId);
- return;
- }
- //getInternalIp for port
- List<String> fixedIps = getFixedIpsForPort(interfaceName);
- if (fixedIps == null) {
- LOG.warn("removeSnatEntriesForPort : Internal Ips not found for InterfaceName {} in router {} with id {}",
- interfaceName, routerName, routerId);
- return;
- }
-
- for (String internalIp : fixedIps) {
- LOG.debug("removeSnatEntriesForPort : Internal Ip retrieved for interface {} is {} in router with Id {}",
- interfaceName, internalIp, routerId);
- IpPort ipPort = NatUtil.getInternalIpPortInfo(dataBroker, routerId, internalIp);
- if (ipPort == null) {
- LOG.debug("removeSnatEntriesForPort : no snatint-ip-port-map found for ip:{}", internalIp);
- continue;
- }
-
- for (IntIpProtoType protoType: ipPort.getIntIpProtoType()) {
- ProtocolTypes protocol = protoType.getProtocol();
- for (Integer portnum : protoType.getPorts()) {
- //build and remove the flow in outbound table
- try {
- removeNatFlow(naptSwitch, NwConstants.OUTBOUND_NAPT_TABLE, routerId, internalIp, portnum);
- } catch (Exception ex) {
- LOG.error("removeSnatEntriesForPort : Failed to remove snat flow for internalIP {} with "
- + "Port {} protocol {} for routerId {} in OUTBOUNDTABLE of NaptSwitch {}",
- internalIp, portnum, protocol, routerId, naptSwitch, ex);
- }
- //Get the external IP address and the port from the model
- NAPTEntryEvent.Protocol proto = protocol.toString().equals(ProtocolTypes.TCP.toString())
- ? NAPTEntryEvent.Protocol.TCP : NAPTEntryEvent.Protocol.UDP;
- IpPortExternal ipPortExternal = NatUtil.getExternalIpPortMap(dataBroker, routerId,
- internalIp, String.valueOf(portnum), proto);
- if (ipPortExternal == null) {
- LOG.error("removeSnatEntriesForPort : Mapping for internalIp {} with port {} is not found in "
- + "router with Id {}", internalIp, portnum, routerId);
- return;
- }
- String externalIpAddress = ipPortExternal.getIpAddress();
- Integer portNumber = ipPortExternal.getPortNum();
-
- //build and remove the flow in inboundtable
- try {
- removeNatFlow(naptSwitch, NwConstants.INBOUND_NAPT_TABLE, routerId,
- externalIpAddress, portNumber);
- } catch (Exception ex) {
- LOG.error("removeSnatEntriesForPort : Failed to remove snat flow internalIP {} with "
- + "Port {} protocol {} for routerId {} in INBOUNDTABLE of naptSwitch {}",
- externalIpAddress, portNumber, protocol, routerId, naptSwitch, ex);
- }
-
- String internalIpPort = internalIp + ":" + portnum;
- // delete the entry from IntExtIpPortMap DS
- try {
- naptManager.removeFromIpPortMapDS(routerId, internalIpPort, proto);
- naptManager.removePortFromPool(internalIpPort, externalIpAddress);
- } catch (Exception ex) {
- LOG.error("removeSnatEntriesForPort : releaseIpExtPortMapping failed, Removal of "
- + "ipportmap {} for router {} failed", internalIpPort, routerId, ex);
- }
- }
- }
- // delete the entry from SnatIntIpPortMap DS
- LOG.debug("removeSnatEntriesForPort : Removing InternalIp:{} on router {}", internalIp, routerId);
- naptManager.removeFromSnatIpPortDS(routerId, internalIp);
- }
- }
-
- // TODO Clean up the exception handling
- @SuppressWarnings("checkstyle:IllegalCatch")
- private String getRouterIdForPort(String interfaceName) {
- String routerName = null;
- VpnInterface vpnInterface = null;
- try {
- vpnInterface = NatUtil.getConfiguredVpnInterface(dataBroker, interfaceName);
- } catch (Exception ex) {
- LOG.error("getRouterIdForPort : Unable to process for interface {} as it is not configured",
- interfaceName, ex);
- }
- if (vpnInterface != null) {
- //getVpnName
- if (vpnInterface.getVpnInstanceNames() == null) {
- LOG.debug("getRouterIdForPort : vpnName not found for vpnInterface {} of port {}",
- vpnInterface, interfaceName);
- } else {
- for (VpnInstanceNames vpnInstance : vpnInterface.getVpnInstanceNames()) {
- String vpnName = vpnInstance.getVpnName();
- try {
- routerName = NatUtil.getRouterIdfromVpnInstance(dataBroker, vpnName);
- } catch (Exception e) {
- LOG.error("getRouterIdForPort : Unable to get routerId for vpnName {}", vpnName, e);
- }
- if (routerName != null) {
- //check router is associated to external network
- if (NatUtil.isSnatEnabledForRouterId(dataBroker, routerName)) {
- LOG.debug("getRouterIdForPort : Retreived Router Id {} for vpnname {} "
- + "associated to interface {}", routerName, vpnName, interfaceName);
- return routerName;
- } else {
- LOG.warn("getRouterIdForPort : Interface {} associated to routerId {} is not "
- + "associated to external network", interfaceName, routerName);
- }
- } else {
- LOG.warn("getRouterIdForPort : Router is not associated to vpnname {} for interface {}",
- vpnName, interfaceName);
- }
- }
- }
- } else {
- LOG.debug("getRouterIdForPort : Interface {} is not a vpninterface", interfaceName);
- }
- return null;
- }
-
- private BigInteger getNaptSwitchforRouter(DataBroker broker, String routerName) {
- InstanceIdentifier<RouterToNaptSwitch> rtrNaptSw = InstanceIdentifier.builder(NaptSwitches.class)
- .child(RouterToNaptSwitch.class, new RouterToNaptSwitchKey(routerName)).build();
- Optional<RouterToNaptSwitch> routerToNaptSwitchData =
- SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
- LogicalDatastoreType.CONFIGURATION, rtrNaptSw);
- if (routerToNaptSwitchData.isPresent()) {
- RouterToNaptSwitch routerToNaptSwitchInstance = routerToNaptSwitchData.get();
- return routerToNaptSwitchInstance.getPrimarySwitchId();
- }
- return null;
- }
-
- private void removeNatFlow(BigInteger dpnId, short tableId, Long routerId, String ipAddress, int ipPort) {
-
- String switchFlowRef = NatUtil.getNaptFlowRef(dpnId, tableId, String.valueOf(routerId), ipAddress, ipPort);
- FlowEntity snatFlowEntity = NatUtil.buildFlowEntity(dpnId, tableId, switchFlowRef);
-
- mdsalManager.removeFlow(snatFlowEntity);
- LOG.debug("removeNatFlow : Removed the flow in table {} for the switch with the DPN ID {} for "
- + "router {} ip {} port {}", tableId, dpnId, routerId, ipAddress, ipPort);
- }
-
- private void processInterfaceAdded(String portName, String routerId, List<ListenableFuture<Void>> futures) {
- LOG.trace("processInterfaceAdded : Processing Interface Add Event for interface {}", portName);
- List<InternalToExternalPortMap> intExtPortMapList = getIntExtPortMapListForPortName(portName, routerId);
- if (intExtPortMapList == null || intExtPortMapList.isEmpty()) {
- LOG.debug("processInterfaceAdded : Ip Mapping list is empty/null for portname {}", portName);
- return;
- }
- InstanceIdentifier<RouterPorts> portIid = NatUtil.buildRouterPortsIdentifier(routerId);
- WriteTransaction installFlowInvTx = dataBroker.newWriteOnlyTransaction();
- for (InternalToExternalPortMap intExtPortMap : intExtPortMapList) {
- floatingIPListener.createNATFlowEntries(portName, intExtPortMap, portIid, routerId, installFlowInvTx);
- }
- //final submit call for installFlowInvTx
- futures.add(NatUtil.waitForTransactionToComplete(installFlowInvTx));
- }
-
- private void processInterfaceRemoved(String portName, BigInteger dpnId, String routerId,
- List<ListenableFuture<Void>> futures) {
- LOG.trace("processInterfaceRemoved : Processing Interface Removed Event for interface {} on DPN ID {}",
- portName, dpnId);
- List<InternalToExternalPortMap> intExtPortMapList = getIntExtPortMapListForPortName(portName, routerId);
- if (intExtPortMapList == null || intExtPortMapList.isEmpty()) {
- LOG.debug("processInterfaceRemoved : Ip Mapping list is empty/null for portName {}", portName);
- return;
- }
- InstanceIdentifier<RouterPorts> portIid = NatUtil.buildRouterPortsIdentifier(routerId);
- WriteTransaction removeFlowInvTx = dataBroker.newWriteOnlyTransaction();
- for (InternalToExternalPortMap intExtPortMap : intExtPortMapList) {
- LOG.trace("processInterfaceRemoved : Removing DNAT Flow entries for dpnId {} ", dpnId);
- floatingIPListener.removeNATFlowEntries(portName, intExtPortMap, portIid, routerId, dpnId, removeFlowInvTx);
- }
- //final submit call for removeFlowInvTx
- futures.add(NatUtil.waitForTransactionToComplete(removeFlowInvTx));
- }
-
- private List<InternalToExternalPortMap> getIntExtPortMapListForPortName(String portName, String routerId) {
- InstanceIdentifier<Ports> portToIpMapIdentifier = NatUtil.buildPortToIpMapIdentifier(routerId, portName);
- Optional<Ports> port =
- SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
- LogicalDatastoreType.CONFIGURATION, portToIpMapIdentifier);
- if (!port.isPresent()) {
- LOG.info("getIntExtPortMapListForPortName : Unable to read router port entry for router ID {} "
- + "and port name {}", routerId, portName);
- return null;
- }
- return port.get().getInternalToExternalPortMap();
- }
-
- private List<String> getFixedIpsForPort(String interfname) {
- LOG.debug("getFixedIpsForPort : getFixedIpsForPort method is called for interface {}", interfname);
- try {
- Future<RpcResult<GetFixedIPsForNeutronPortOutput>> result =
- neutronVpnService.getFixedIPsForNeutronPort(new GetFixedIPsForNeutronPortInputBuilder()
- .setPortId(new Uuid(interfname)).build());
-
- RpcResult<GetFixedIPsForNeutronPortOutput> rpcResult = result.get();
- if (!rpcResult.isSuccessful()) {
- LOG.error("getFixedIpsForPort : RPC Call to GetFixedIPsForNeutronPortOutput returned with Errors {}",
- rpcResult.getErrors());
- } else {
- return rpcResult.getResult().getFixedIPs();
- }
- } catch (InterruptedException | ExecutionException | NullPointerException ex) {
- LOG.error("getFixedIpsForPort : Exception while receiving fixedIps for port {}", interfname, ex);
- }
- return null;
- }
-
- private class NatFlowAddWorker implements Callable<List<ListenableFuture<Void>>> {
- Interface iface;
-
- NatFlowAddWorker(Interface iface) {
- this.iface = iface;
- }
-
- @Override
- @SuppressWarnings("checkstyle:IllegalCatch")
- public List<ListenableFuture<Void>> call() {
- final List<ListenableFuture<Void>> futures = new ArrayList<>();
- LOG.trace("call : Interface {} up event received", iface);
- String interfaceName = iface.getName();
- try {
- LOG.trace("call : Port added event received for interface {} ", interfaceName);
- String routerId = getRouterIdForPort(interfaceName);
- if (routerId != null) {
- processInterfaceAdded(interfaceName, routerId, futures);
- }
- } catch (Exception ex) {
- LOG.error("call : Exception caught in Interface {} Operational State Up event",
- interfaceName, ex);
- }
- return futures;
- }
- }
-
- private class NatFlowRemoveWorker implements Callable<List<ListenableFuture<Void>>> {
- Interface delintrf;
-
- NatFlowRemoveWorker(Interface delintrf) {
- this.delintrf = delintrf;
- }
-
- @Override
- @SuppressWarnings("checkstyle:IllegalCatch")
- public List<ListenableFuture<Void>> call() {
- final List<ListenableFuture<Void>> futures = new ArrayList<>();
- final String interfaceName = delintrf.getName();
- LOG.trace("call : Interface {} removed event received", delintrf);
- try {
- String routerName = getRouterIdForPort(interfaceName);
- if (routerName != null) {
- LOG.trace("call : Port removed event received for interface {} ", interfaceName);
-
- BigInteger dpId = null;
- try {
- dpId = NatUtil.getDpIdFromInterface(delintrf);
- } catch (Exception e) {
- LOG.warn(
- "call: Unable to retrieve DPNID from Interface operational data store for"
- + " Interface {}. Fetching from VPN Interface op data store. ",
- interfaceName, e);
- InstanceIdentifier<VpnInterface> id = NatUtil.getVpnInterfaceIdentifier(interfaceName);
- Optional<VpnInterface> cfgVpnInterface =
- SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(
- dataBroker, LogicalDatastoreType.CONFIGURATION, id);
- if (!cfgVpnInterface.isPresent()) {
- LOG.debug("call : Interface {} is not a VPN Interface, ignoring.", interfaceName);
- return futures;
- }
- for (VpnInstanceNames vpnInstance : cfgVpnInterface.get().getVpnInstanceNames()) {
- String vpnName = vpnInstance.getVpnName();
- InstanceIdentifier<VpnInterfaceOpDataEntry> idOper = NatUtil
- .getVpnInterfaceOpDataEntryIdentifier(interfaceName, vpnName);
- Optional<VpnInterfaceOpDataEntry> optVpnInterface =
- SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(
- dataBroker, LogicalDatastoreType.OPERATIONAL, idOper);
- if (optVpnInterface.isPresent()) {
- dpId = optVpnInterface.get().getDpnId();
- break;
- }
- }
- }
- if (dpId == null || dpId.equals(BigInteger.ZERO)) {
- LOG.error("call : Unable to get DPN ID for the Interface {}", interfaceName);
- return futures;
- }
- processInterfaceRemoved(interfaceName, dpId, routerName, futures);
- removeSnatEntriesForPort(interfaceName, routerName);
- } else {
- LOG.debug("call : PORT_REMOVE: Router Id is null either Interface {} is not associated "
- + "to router or failed to retrieve routerId due to exception", interfaceName);
- }
- } catch (Exception e) {
- LOG.error("call : Exception caught in Interface {} OperationalStateRemove", interfaceName, e);
- }
- return futures;
- }
- }
-
- private class NatFlowUpdateWorker implements Callable<List<ListenableFuture<Void>>> {
- Interface update;
-
- NatFlowUpdateWorker(Interface update) {
- this.update = update;
- }
-
- @Override
- @SuppressWarnings("checkstyle:IllegalCatch")
- public List<ListenableFuture<Void>> call() {
- final List<ListenableFuture<Void>> futures = new ArrayList<>();
- String interfaceName = update.getName();
- if (update.getOperStatus().equals(Interface.OperStatus.Up)) {
- LOG.debug("call : Port UP event received for interface {} ", interfaceName);
- } else if (update.getOperStatus().equals(Interface.OperStatus.Down)) {
- LOG.debug("call : Port DOWN event received for interface {} ", interfaceName);
- try {
- String routerName = getRouterIdForPort(interfaceName);
- if (routerName != null) {
- removeSnatEntriesForPort(interfaceName, routerName);
- } else {
- LOG.debug(
- "call : PORT_DOWN: Router Id is null, either Interface {} is not associated "
- + "to a router or failed to retrieve routerId due to exception", interfaceName);
- }
- } catch (Exception ex) {
- LOG.error("call : Exception caught in Interface {} OperationalStateDown", interfaceName, ex);
- }
- }
- return futures;
- }
- }
-}
package org.opendaylight.netvirt.natservice.internal;
import com.google.common.base.Optional;
+import com.google.common.collect.HashBasedTable;
+import com.google.common.collect.Table;
import com.google.common.util.concurrent.ListenableFuture;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
import javax.annotation.PostConstruct;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
+import org.opendaylight.genius.mdsalutil.FlowEntity;
+import org.opendaylight.genius.mdsalutil.NwConstants;
+import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.vpn._interface.VpnInstanceNames;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.L2vlan;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.router.interfaces.RouterInterface;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn._interface.op.data.VpnInterfaceOpDataEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.NaptSwitches;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ProtocolTypes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.RouterPorts;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.Ports;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.ports.InternalToExternalPortMap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.intext.ip.protocol.type.ip.port.map.IpPortExternal;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.napt.switches.RouterToNaptSwitch;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.napt.switches.RouterToNaptSwitchKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.snatint.ip.port.map.intip.port.map.IpPort;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.snatint.ip.port.map.intip.port.map.ip.port.IntIpProtoType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NeutronvpnService;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private final DataBroker dataBroker;
private final OdlInterfaceRpcService odlInterfaceRpcService;
private final JobCoordinator coordinator;
+ private final FloatingIPListener floatingIPListener;
+ private final NeutronvpnService neutronVpnService;
+ private final IMdsalApiManager mdsalManager;
+ private final NaptManager naptManager;
+ Table<Interface.OperStatus, Interface.OperStatus, IntfTransitionState> stateTable = HashBasedTable.create();
+
+ enum IntfTransitionState {
+ STATE_UP,
+ STATE_DOWN,
+ STATE_IGNORE
+ }
+
+ private void initialize() {
+ // Interface State Transition Table
+ // Up Down Unknown
+ // ---------------------------------------------------------------
+ /* Up { STATE_IGNORE, STATE_DOWN, STATE_DOWN }, */
+ /* Down { STATE_UP, STATE_IGNORE, STATE_IGNORE }, */
+ /* Unknown { STATE_UP, STATE_DOWN, STATE_IGNORE }, */
+ stateTable.put(Interface.OperStatus.Up, Interface.OperStatus.Down, IntfTransitionState.STATE_DOWN);
+ stateTable.put(Interface.OperStatus.Down, Interface.OperStatus.Up, IntfTransitionState.STATE_UP);
+ stateTable.put(Interface.OperStatus.Unknown, Interface.OperStatus.Up, IntfTransitionState.STATE_UP);
+ stateTable.put(Interface.OperStatus.Unknown, Interface.OperStatus.Down, IntfTransitionState.STATE_DOWN);
+ stateTable.put(Interface.OperStatus.Up, Interface.OperStatus.Unknown, IntfTransitionState.STATE_DOWN);
+ }
@Inject
public NatInterfaceStateChangeListener(final DataBroker dataBroker,
- final OdlInterfaceRpcService odlInterfaceRpcService, final JobCoordinator coordinator) {
+ final OdlInterfaceRpcService odlInterfaceRpcService, final JobCoordinator coordinator,
+ final FloatingIPListener floatingIPListener,final NeutronvpnService neutronvpnService,
+ final IMdsalApiManager mdsalManager, final NaptManager naptManager) {
super(Interface.class, NatInterfaceStateChangeListener.class);
this.dataBroker = dataBroker;
this.odlInterfaceRpcService = odlInterfaceRpcService;
this.coordinator = coordinator;
+ this.floatingIPListener = floatingIPListener;
+ this.neutronVpnService = neutronvpnService;
+ this.mdsalManager = mdsalManager;
+ this.naptManager = naptManager;
+ initialize();
}
@Override
LOG.debug("add : Interface {} is not Vlan Interface.Ignoring", intrf.getName());
return;
}
+ String interfaceName = intrf.getName();
+ BigInteger intfDpnId;
+ try {
+ intfDpnId = NatUtil.getDpIdFromInterface(intrf);
+ } catch (Exception e) {
+ LOG.error("add : Exception occured while retriving dpnid for interface {}", intrf.getName(), e);
+ return;
+ }
+ if (BigInteger.ZERO.equals(intfDpnId)) {
+ LOG.warn("add : Could not retrieve dp id for interface {} ", interfaceName);
+ return;
+ }
+ // We service only VM interfaces. We do not service Tunnel Interfaces here.
+ // Tunnel events are directly serviced by TunnelInterfacesStateListener present as part of
+ // VpnInterfaceManager
+ RouterInterface routerInterface = NatUtil.getConfiguredRouterInterface(dataBroker, interfaceName);
+ if (routerInterface != null) {
+ String routerName = routerInterface.getRouterName();
+ NatInterfaceStateAddWorker natIfaceStateAddWorker = new NatInterfaceStateAddWorker(interfaceName,
+ intfDpnId, routerName);
+ coordinator.enqueueJob(NAT_DS + "-" + intrf.getName(), natIfaceStateAddWorker);
- NatInterfaceStateAddWorker natIfaceStateAddWorker = new NatInterfaceStateAddWorker(intrf);
- coordinator.enqueueJob(NAT_DS + "-" + intrf.getName(), natIfaceStateAddWorker);
+ NatFlowAddWorker natFlowAddWorker = new NatFlowAddWorker(interfaceName, routerName);
+ coordinator.enqueueJob(NAT_DS + "-" + interfaceName, natFlowAddWorker, NatConstants.NAT_DJC_MAX_RETRIES);
+ } else {
+ LOG.info("add : Router-Interface Mapping not found for Interface : {}", interfaceName);
+ }
}
@Override
LOG.debug("remove : Interface {} is not Vlan Interface.Ignoring", intrf.getName());
return;
}
+ String interfaceName = intrf.getName();
+ BigInteger intfDpnId = BigInteger.ZERO;
+ try {
+ intfDpnId = NatUtil.getDpIdFromInterface(intrf);
+ } catch (Exception e) {
+ LOG.error("remove : Exception occured while retriving dpnid for interface {}", intrf.getName(), e);
+ InstanceIdentifier<VpnInterface> id = NatUtil.getVpnInterfaceIdentifier(interfaceName);
+ Optional<VpnInterface> cfgVpnInterface =
+ SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(
+ dataBroker, LogicalDatastoreType.CONFIGURATION, id);
+ if (!cfgVpnInterface.isPresent()) {
+ LOG.warn("remove : Interface {} is not a VPN Interface, ignoring.", interfaceName);
+ return;
+ }
+ for (VpnInstanceNames vpnInterfaceVpnInstance : cfgVpnInterface.get().getVpnInstanceNames()) {
+ String vpnName = vpnInterfaceVpnInstance.getVpnName();
+ InstanceIdentifier<VpnInterfaceOpDataEntry> idOper = NatUtil
+ .getVpnInterfaceOpDataEntryIdentifier(interfaceName, vpnName);
+ Optional<VpnInterfaceOpDataEntry> optVpnInterface =
+ SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(
+ dataBroker, LogicalDatastoreType.OPERATIONAL, idOper);
+ if (optVpnInterface.isPresent()) {
+ intfDpnId = optVpnInterface.get().getDpnId();
+ break;
+ }
+ }
+ }
+ if (intfDpnId.equals(BigInteger.ZERO)) {
+ LOG.warn("remove : Could not retrieve dpnid for interface {} ", interfaceName);
+ return;
+ }
+ RouterInterface routerInterface = NatUtil.getConfiguredRouterInterface(dataBroker, interfaceName);
+ if (routerInterface != null) {
+ String routerName = routerInterface.getRouterName();
+ NatInterfaceStateRemoveWorker natIfaceStateRemoveWorker = new NatInterfaceStateRemoveWorker(interfaceName,
+ intfDpnId, routerName);
+ coordinator.enqueueJob(NAT_DS + "-" + interfaceName, natIfaceStateRemoveWorker);
- NatInterfaceStateRemoveWorker natIfaceStateRemoveWorker = new NatInterfaceStateRemoveWorker(intrf);
- coordinator.enqueueJob(NAT_DS + "-" + intrf.getName(), natIfaceStateRemoveWorker);
+ NatFlowRemoveWorker natFlowRemoveWorker = new NatFlowRemoveWorker(intrf, intfDpnId, routerName);
+ coordinator.enqueueJob(NAT_DS + "-" + interfaceName, natFlowRemoveWorker,
+ NatConstants.NAT_DJC_MAX_RETRIES);
+ } else {
+ LOG.info("remove : Router-Interface Mapping not found for Interface : {}", interfaceName);
+ }
}
@Override
LOG.debug("update : Interface {} is not Vlan Interface.Ignoring", update.getName());
return;
}
-
- NatInterfaceStateUpdateWorker natIfaceStateupdateWorker = new NatInterfaceStateUpdateWorker(original,update);
- coordinator.enqueueJob(NAT_DS + "-" + update.getName(), natIfaceStateupdateWorker);
- }
-
- void handleRouterInterfacesUpEvent(String routerName, String interfaceName, WriteTransaction writeOperTxn) {
- LOG.debug("handleRouterInterfacesUpEvent : Handling UP event for router interface {} in Router {}",
- interfaceName, routerName);
- BigInteger dpId = NatUtil.getDpnForInterface(odlInterfaceRpcService, interfaceName);
- if (dpId.equals(BigInteger.ZERO)) {
- LOG.warn("handleRouterInterfacesUpEvent : Could not retrieve dp id for interface {} to handle router {} "
- + "association model", interfaceName, routerName);
+ BigInteger intfDpnId = BigInteger.ZERO;
+ String interfaceName = update.getName();
+ try {
+ intfDpnId = NatUtil.getDpIdFromInterface(update);
+ } catch (Exception e) {
+ LOG.error("update : Exception occured while retriving dpnid for interface {}", update.getName(), e);
+ InstanceIdentifier<VpnInterface> id = NatUtil.getVpnInterfaceIdentifier(interfaceName);
+ Optional<VpnInterface> cfgVpnInterface =
+ SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(
+ dataBroker, LogicalDatastoreType.CONFIGURATION, id);
+ if (!cfgVpnInterface.isPresent()) {
+ LOG.warn("update : Interface {} is not a VPN Interface, ignoring.", interfaceName);
+ return;
+ }
+ for (VpnInstanceNames vpnInterfaceVpnInstance : cfgVpnInterface.get().getVpnInstanceNames()) {
+ String vpnName = vpnInterfaceVpnInstance.getVpnName();
+ InstanceIdentifier<VpnInterfaceOpDataEntry> idOper = NatUtil
+ .getVpnInterfaceOpDataEntryIdentifier(interfaceName, vpnName);
+ Optional<VpnInterfaceOpDataEntry> optVpnInterface =
+ SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(
+ dataBroker, LogicalDatastoreType.OPERATIONAL, idOper);
+ if (optVpnInterface.isPresent()) {
+ intfDpnId = optVpnInterface.get().getDpnId();
+ break;
+ }
+ }
+ }
+ if (intfDpnId.equals(BigInteger.ZERO)) {
+ LOG.warn("remove : Could not retrieve dpnid for interface {} ", interfaceName);
return;
}
+ RouterInterface routerInterface = NatUtil.getConfiguredRouterInterface(dataBroker, interfaceName);
+ if (routerInterface != null) {
+ String routerName = routerInterface.getRouterName();
+ NatInterfaceStateUpdateWorker natIfaceStateupdateWorker = new NatInterfaceStateUpdateWorker(original,
+ update, intfDpnId, routerName);
+ coordinator.enqueueJob(NAT_DS + "-" + update.getName(), natIfaceStateupdateWorker);
+ NatFlowUpdateWorker natFlowUpdateWorker = new NatFlowUpdateWorker(original, update, routerName);
+ coordinator.enqueueJob(NAT_DS + "-" + update.getName(), natFlowUpdateWorker,
+ NatConstants.NAT_DJC_MAX_RETRIES);
+ } else {
+ LOG.info("update : Router-Interface Mapping not found for Interface : {}", interfaceName);
+ }
+ }
+
+ void handleRouterInterfacesUpEvent(String routerName, String interfaceName, BigInteger dpId,
+ WriteTransaction writeOperTxn) {
+ LOG.debug("handleRouterInterfacesUpEvent : Handling UP event for router interface {} in Router {} on Dpn {}",
+ interfaceName, routerName, dpId);
NatUtil.addToNeutronRouterDpnsMap(dataBroker, routerName, interfaceName, dpId, writeOperTxn);
NatUtil.addToDpnRoutersMap(dataBroker, routerName, interfaceName, dpId, writeOperTxn);
}
writeOperTxn);
}
+ private IntfTransitionState getTransitionState(Interface.OperStatus original , Interface.OperStatus updated) {
+ IntfTransitionState transitionState = stateTable.get(original, updated);
+
+ if (transitionState == null) {
+ return IntfTransitionState.STATE_IGNORE;
+ }
+ return transitionState;
+ }
+
private class NatInterfaceStateAddWorker implements Callable<List<ListenableFuture<Void>>> {
- Interface iface;
+ private String interfaceName;
+ private String routerName;
+ private BigInteger intfDpnId;
- NatInterfaceStateAddWorker(Interface iface) {
- this.iface = iface;
+ NatInterfaceStateAddWorker(String interfaceName, BigInteger intfDpnId, String routerName) {
+ this.interfaceName = interfaceName;
+ this.routerName = routerName;
+ this.intfDpnId = intfDpnId;
}
@Override
@SuppressWarnings("checkstyle:IllegalCatch")
public List<ListenableFuture<Void>> call() {
List<ListenableFuture<Void>> futures = new ArrayList<>();
- final String interfaceName = iface.getName();
try {
LOG.trace("call : Received interface {} PORT UP OR ADD event ", interfaceName);
- // We service only VM interfaces and Router interfaces here. We do not service Tunnel Interfaces here.
- // Tunnel events are directly serviced by TunnelInterfacesStateListener present as part of
- // VpnInterfaceManager
- RouterInterface routerInterface = NatUtil.getConfiguredRouterInterface(dataBroker, interfaceName);
- if (routerInterface != null) {
- String routerName = routerInterface.getRouterName();
- LOG.debug("call : Router Name {} ", routerInterface.getRouterName());
- WriteTransaction writeOperTxn = dataBroker.newWriteOnlyTransaction();
- handleRouterInterfacesUpEvent(routerName, interfaceName, writeOperTxn);
- futures.add(writeOperTxn.submit());
- } else {
- LOG.info("call : Unable to process add for interface {}", interfaceName);
- }
+ WriteTransaction writeOperTxn = dataBroker.newWriteOnlyTransaction();
+ handleRouterInterfacesUpEvent(routerName, interfaceName, intfDpnId, writeOperTxn);
+ futures.add(writeOperTxn.submit());
} catch (Exception e) {
LOG.error("call : Exception caught in Interface {} Operational State Up event",
interfaceName, e);
}
private class NatInterfaceStateRemoveWorker implements Callable<List<ListenableFuture<Void>>> {
- Interface iface;
+ private String interfaceName;
+ private String routerName;
+ private BigInteger intfDpnId;
- NatInterfaceStateRemoveWorker(Interface iface) {
- this.iface = iface;
+ NatInterfaceStateRemoveWorker(String interfaceName, BigInteger intfDpnId, String routerName) {
+ this.interfaceName = interfaceName;
+ this.routerName = routerName;
+ this.intfDpnId = intfDpnId;
}
@Override
@SuppressWarnings("checkstyle:IllegalCatch")
public List<ListenableFuture<Void>> call() {
- final String interfaceName = iface.getName();
List<ListenableFuture<Void>> futures = new ArrayList<>();
try {
LOG.trace("call : Received interface {} PORT DOWN or REMOVE event", interfaceName);
- BigInteger dpId = null;
- try {
- dpId = NatUtil.getDpIdFromInterface(iface);
- } catch (Exception e) {
- LOG.error("call : Unable to retrieve DPNID from Interface operational data store for "
- + "Interface {}.", interfaceName, e);
- InstanceIdentifier<VpnInterface> id = NatUtil.getVpnInterfaceIdentifier(interfaceName);
- Optional<VpnInterface> cfgVpnInterface =
- SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(
- dataBroker, LogicalDatastoreType.CONFIGURATION, id);
- if (!cfgVpnInterface.isPresent()) {
- LOG.warn("call : Interface {} is not a VPN Interface, ignoring.", interfaceName);
- return futures;
- }
- for (VpnInstanceNames vpnInterfaceVpnInstance : cfgVpnInterface.get().getVpnInstanceNames()) {
- String vpnName = vpnInterfaceVpnInstance.getVpnName();
- InstanceIdentifier<VpnInterfaceOpDataEntry> idOper = NatUtil
- .getVpnInterfaceOpDataEntryIdentifier(interfaceName, vpnName);
- Optional<VpnInterfaceOpDataEntry> optVpnInterface =
- SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(
- dataBroker, LogicalDatastoreType.CONFIGURATION, idOper);
- if (optVpnInterface.isPresent()) {
- dpId = optVpnInterface.get().getDpnId();
- break;
- }
- }
- }
- if (dpId == null || dpId.equals(BigInteger.ZERO)) {
- LOG.error("call : Unable to get DPN ID for the Interface {}", interfaceName);
- return futures;
- }
WriteTransaction writeOperTxn = dataBroker.newWriteOnlyTransaction();
- RouterInterface routerInterface = NatUtil.getConfiguredRouterInterface(dataBroker, interfaceName);
- if (routerInterface != null) {
- handleRouterInterfacesDownEvent(routerInterface.getRouterName(), interfaceName, dpId, writeOperTxn);
- }
+ handleRouterInterfacesDownEvent(routerName, interfaceName, intfDpnId, writeOperTxn);
futures.add(writeOperTxn.submit());
} catch (Exception e) {
LOG.error("call : Exception observed in handling deletion of VPN Interface {}.", interfaceName, e);
}
private class NatInterfaceStateUpdateWorker implements Callable<List<ListenableFuture<Void>>> {
- Interface original;
- Interface update;
+ private Interface original;
+ private Interface update;
+ private BigInteger intfDpnId;
+ private String routerName;
- NatInterfaceStateUpdateWorker(Interface original, Interface update) {
+ NatInterfaceStateUpdateWorker(Interface original, Interface update, BigInteger intfDpnId, String routerName) {
this.original = original;
this.update = update;
+ this.intfDpnId = intfDpnId;
+ this.routerName = routerName;
}
@Override
try {
final String interfaceName = update.getName();
LOG.trace("call : Received interface {} state change event", interfaceName);
- BigInteger dpId = null;
- try {
- dpId = NatUtil.getDpIdFromInterface(update);
- } catch (Exception e) {
- LOG.error("call : Unable to retrieve DPN ID from Interface operational data "
- + "store for Interface {}", update.getName(), e);
- InstanceIdentifier<VpnInterface> id = NatUtil.getVpnInterfaceIdentifier(interfaceName);
- Optional<VpnInterface> cfgVpnInterface =
- SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(
- dataBroker, LogicalDatastoreType.CONFIGURATION, id);
- if (!cfgVpnInterface.isPresent()) {
- LOG.warn("call : Interface {} is not a VPN Interface, ignoring.", interfaceName);
- return futures;
- }
- for (VpnInstanceNames vpnInterfaceVpnInstance : cfgVpnInterface.get().getVpnInstanceNames()) {
- String vpnName = vpnInterfaceVpnInstance.getVpnName();
- InstanceIdentifier<VpnInterfaceOpDataEntry> idOper = NatUtil
- .getVpnInterfaceOpDataEntryIdentifier(interfaceName, vpnName);
- Optional<VpnInterfaceOpDataEntry> optVpnInterface =
- SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(
- dataBroker, LogicalDatastoreType.OPERATIONAL, idOper);
- if (optVpnInterface.isPresent()) {
- dpId = optVpnInterface.get().getDpnId();
- break;
- }
- }
- }
- if (dpId == null || dpId.equals(BigInteger.ZERO)) {
- LOG.error("call : Unable to get DPN ID for the Interface {}", interfaceName);
+ LOG.debug("call : DPN ID {} for the interface {} ", intfDpnId, interfaceName);
+ WriteTransaction writeOperTxn = dataBroker.newWriteOnlyTransaction();
+ IntfTransitionState state = getTransitionState(original.getOperStatus(), update.getOperStatus());
+ if (state.equals(IntfTransitionState.STATE_IGNORE)) {
+ LOG.info("NAT Service: Interface {} state original {} updated {} not handled",
+ interfaceName, original.getOperStatus(), update.getOperStatus());
return futures;
}
- LOG.debug("call : DPN ID {} for the interface {} ", dpId, interfaceName);
- WriteTransaction writeOperTxn = dataBroker.newWriteOnlyTransaction();
- RouterInterface routerInterface = NatUtil.getConfiguredRouterInterface(dataBroker, interfaceName);
- if (routerInterface != null) {
- Interface.OperStatus originalOperStatus = original.getOperStatus();
- Interface.OperStatus updateOperStatus = update.getOperStatus();
- if (originalOperStatus != updateOperStatus) {
- String routerName = routerInterface.getRouterName();
- if (updateOperStatus == Interface.OperStatus.Unknown) {
- LOG.debug("call : DPN {} connnected to the interface {} has gone down."
- + "Hence clearing the dpn-vpninterfaces-list entry from the"
- + " neutron-router-dpns model in the ODL:L3VPN", dpId, interfaceName);
- // If the interface state is unknown, it means that the corresponding DPN has gone down.
- // So remove the dpn-vpninterfaces-list from the neutron-router-dpns model.
- NatUtil.removeFromNeutronRouterDpnsMap(dataBroker, routerName, dpId, writeOperTxn);
- } else if (updateOperStatus == Interface.OperStatus.Up) {
- LOG.debug("call : DPN {} connnected to the interface {} has come up. Hence adding"
- + " the dpn-vpninterfaces-list entry from the neutron-router-dpns model"
- + " in the ODL:L3VPN", dpId, interfaceName);
- handleRouterInterfacesUpEvent(routerName, interfaceName, writeOperTxn);
- }
- }
+ if (state.equals(IntfTransitionState.STATE_DOWN)) {
+ LOG.debug("call : DPN {} connnected to the interface {} has gone down."
+ + "Hence clearing the dpn-vpninterfaces-list entry from the"
+ + " neutron-router-dpns model in the ODL:L3VPN", intfDpnId, interfaceName);
+ // If the interface state is unknown, it means that the corresponding DPN has gone down.
+ // So remove the dpn-vpninterfaces-list from the neutron-router-dpns model.
+ NatUtil.removeFromNeutronRouterDpnsMap(dataBroker, routerName, intfDpnId, writeOperTxn);
+ } else if (state.equals(IntfTransitionState.STATE_UP)) {
+ LOG.debug("call : DPN {} connnected to the interface {} has come up. Hence adding"
+ + " the dpn-vpninterfaces-list entry from the neutron-router-dpns model"
+ + " in the ODL:L3VPN", intfDpnId, interfaceName);
+ handleRouterInterfacesUpEvent(routerName, interfaceName, intfDpnId, writeOperTxn);
}
futures.add(writeOperTxn.submit());
} catch (Exception e) {
return futures;
}
}
-}
+
+ private void processInterfaceAdded(String portName, String routerId, List<ListenableFuture<Void>> futures) {
+ LOG.trace("processInterfaceAdded : Processing Interface Add Event for interface {}", portName);
+ List<InternalToExternalPortMap> intExtPortMapList = getIntExtPortMapListForPortName(portName, routerId);
+ if (intExtPortMapList == null || intExtPortMapList.isEmpty()) {
+ LOG.debug("processInterfaceAdded : Ip Mapping list is empty/null for portname {}", portName);
+ return;
+ }
+ InstanceIdentifier<RouterPorts> portIid = NatUtil.buildRouterPortsIdentifier(routerId);
+ WriteTransaction installFlowInvTx = dataBroker.newWriteOnlyTransaction();
+ for (InternalToExternalPortMap intExtPortMap : intExtPortMapList) {
+ floatingIPListener.createNATFlowEntries(portName, intExtPortMap, portIid, routerId, installFlowInvTx);
+ }
+ //final submit call for installFlowInvTx
+ futures.add(NatUtil.waitForTransactionToComplete(installFlowInvTx));
+ }
+
+ private List<InternalToExternalPortMap> getIntExtPortMapListForPortName(String portName, String routerId) {
+ InstanceIdentifier<Ports> portToIpMapIdentifier = NatUtil.buildPortToIpMapIdentifier(routerId, portName);
+ Optional<Ports> port =
+ SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
+ LogicalDatastoreType.CONFIGURATION, portToIpMapIdentifier);
+ if (!port.isPresent()) {
+ LOG.info("getIntExtPortMapListForPortName : Unable to read router port entry for router ID {} "
+ + "and port name {}", routerId, portName);
+ return null;
+ }
+ return port.get().getInternalToExternalPortMap();
+ }
+
+ private BigInteger getNaptSwitchforRouter(DataBroker broker, String routerName) {
+ InstanceIdentifier<RouterToNaptSwitch> rtrNaptSw = InstanceIdentifier.builder(NaptSwitches.class)
+ .child(RouterToNaptSwitch.class, new RouterToNaptSwitchKey(routerName)).build();
+ Optional<RouterToNaptSwitch> routerToNaptSwitchData =
+ SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
+ LogicalDatastoreType.CONFIGURATION, rtrNaptSw);
+ if (routerToNaptSwitchData.isPresent()) {
+ RouterToNaptSwitch routerToNaptSwitchInstance = routerToNaptSwitchData.get();
+ return routerToNaptSwitchInstance.getPrimarySwitchId();
+ }
+ return null;
+ }
+
+ private void removeNatFlow(BigInteger dpnId, short tableId, Long routerId, String ipAddress, int ipPort) {
+
+ String switchFlowRef = NatUtil.getNaptFlowRef(dpnId, tableId, String.valueOf(routerId), ipAddress, ipPort);
+ FlowEntity snatFlowEntity = NatUtil.buildFlowEntity(dpnId, tableId, switchFlowRef);
+
+ mdsalManager.removeFlow(snatFlowEntity);
+ LOG.debug("removeNatFlow : Removed the flow in table {} for the switch with the DPN ID {} for "
+ + "router {} ip {} port {}", tableId, dpnId, routerId, ipAddress, ipPort);
+ }
+
+ private List<String> getFixedIpsForPort(String interfname) {
+ LOG.debug("getFixedIpsForPort : getFixedIpsForPort method is called for interface {}", interfname);
+ try {
+ Future<RpcResult<GetFixedIPsForNeutronPortOutput>> result =
+ neutronVpnService.getFixedIPsForNeutronPort(new GetFixedIPsForNeutronPortInputBuilder()
+ .setPortId(new Uuid(interfname)).build());
+
+ RpcResult<GetFixedIPsForNeutronPortOutput> rpcResult = result.get();
+ if (!rpcResult.isSuccessful()) {
+ LOG.error("getFixedIpsForPort : RPC Call to GetFixedIPsForNeutronPortOutput returned with Errors {}",
+ rpcResult.getErrors());
+ } else {
+ return rpcResult.getResult().getFixedIPs();
+ }
+ } catch (InterruptedException | ExecutionException | NullPointerException ex) {
+ LOG.error("getFixedIpsForPort : Exception while receiving fixedIps for port {}", interfname, ex);
+ }
+ return null;
+ }
+
+ private void processInterfaceRemoved(String portName, BigInteger dpnId, String routerId,
+ List<ListenableFuture<Void>> futures) {
+ LOG.trace("processInterfaceRemoved : Processing Interface Removed Event for interface {} on DPN ID {}",
+ portName, dpnId);
+ List<InternalToExternalPortMap> intExtPortMapList = getIntExtPortMapListForPortName(portName, routerId);
+ if (intExtPortMapList == null || intExtPortMapList.isEmpty()) {
+ LOG.debug("processInterfaceRemoved : Ip Mapping list is empty/null for portName {}", portName);
+ return;
+ }
+ InstanceIdentifier<RouterPorts> portIid = NatUtil.buildRouterPortsIdentifier(routerId);
+ WriteTransaction removeFlowInvTx = dataBroker.newWriteOnlyTransaction();
+ for (InternalToExternalPortMap intExtPortMap : intExtPortMapList) {
+ LOG.trace("processInterfaceRemoved : Removing DNAT Flow entries for dpnId {} ", dpnId);
+ floatingIPListener.removeNATFlowEntries(portName, intExtPortMap, portIid, routerId, dpnId, removeFlowInvTx);
+ }
+ // final submit call for removeFlowInvTx
+ futures.add(NatUtil.waitForTransactionToComplete(removeFlowInvTx));
+ }
+
+ // TODO Clean up the exception handling
+ @SuppressWarnings("checkstyle:IllegalCatch")
+ private void removeSnatEntriesForPort(String interfaceName, String routerName) {
+ Long routerId = NatUtil.getVpnId(dataBroker, routerName);
+ if (routerId == NatConstants.INVALID_ID) {
+ LOG.error("removeSnatEntriesForPort : routerId not found for routername {}", routerName);
+ return;
+ }
+ BigInteger naptSwitch = getNaptSwitchforRouter(dataBroker, routerName);
+ if (naptSwitch == null || naptSwitch.equals(BigInteger.ZERO)) {
+ LOG.error("removeSnatEntriesForPort : NaptSwitch is not elected for router {} with Id {}",
+ routerName, routerId);
+ return;
+ }
+ //getInternalIp for port
+ List<String> fixedIps = getFixedIpsForPort(interfaceName);
+ if (fixedIps == null) {
+ LOG.warn("removeSnatEntriesForPort : Internal Ips not found for InterfaceName {} in router {} with id {}",
+ interfaceName, routerName, routerId);
+ return;
+ }
+
+ for (String internalIp : fixedIps) {
+ LOG.debug("removeSnatEntriesForPort : Internal Ip retrieved for interface {} is {} in router with Id {}",
+ interfaceName, internalIp, routerId);
+ IpPort ipPort = NatUtil.getInternalIpPortInfo(dataBroker, routerId, internalIp);
+ if (ipPort == null) {
+ LOG.debug("removeSnatEntriesForPort : no snatint-ip-port-map found for ip:{}", internalIp);
+ continue;
+ }
+
+ for (IntIpProtoType protoType: ipPort.getIntIpProtoType()) {
+ ProtocolTypes protocol = protoType.getProtocol();
+ for (Integer portnum : protoType.getPorts()) {
+ //build and remove the flow in outbound table
+ try {
+ removeNatFlow(naptSwitch, NwConstants.OUTBOUND_NAPT_TABLE, routerId, internalIp, portnum);
+ } catch (Exception ex) {
+ LOG.error("removeSnatEntriesForPort : Failed to remove snat flow for internalIP {} with "
+ + "Port {} protocol {} for routerId {} in OUTBOUNDTABLE of NaptSwitch {}",
+ internalIp, portnum, protocol, routerId, naptSwitch, ex);
+ }
+ //Get the external IP address and the port from the model
+ NAPTEntryEvent.Protocol proto = protocol.toString().equals(ProtocolTypes.TCP.toString())
+ ? NAPTEntryEvent.Protocol.TCP : NAPTEntryEvent.Protocol.UDP;
+ IpPortExternal ipPortExternal = NatUtil.getExternalIpPortMap(dataBroker, routerId,
+ internalIp, String.valueOf(portnum), proto);
+ if (ipPortExternal == null) {
+ LOG.error("removeSnatEntriesForPort : Mapping for internalIp {} with port {} is not found in "
+ + "router with Id {}", internalIp, portnum, routerId);
+ return;
+ }
+ String externalIpAddress = ipPortExternal.getIpAddress();
+ Integer portNumber = ipPortExternal.getPortNum();
+
+ //build and remove the flow in inboundtable
+ try {
+ removeNatFlow(naptSwitch, NwConstants.INBOUND_NAPT_TABLE, routerId,
+ externalIpAddress, portNumber);
+ } catch (Exception ex) {
+ LOG.error("removeSnatEntriesForPort : Failed to remove snat flow internalIP {} with "
+ + "Port {} protocol {} for routerId {} in INBOUNDTABLE of naptSwitch {}",
+ externalIpAddress, portNumber, protocol, routerId, naptSwitch, ex);
+ }
+
+ String internalIpPort = internalIp + ":" + portnum;
+ // delete the entry from IntExtIpPortMap DS
+ try {
+ naptManager.removeFromIpPortMapDS(routerId, internalIpPort, proto);
+ naptManager.removePortFromPool(internalIpPort, externalIpAddress);
+ } catch (Exception ex) {
+ LOG.error("removeSnatEntriesForPort : releaseIpExtPortMapping failed, Removal of "
+ + "ipportmap {} for router {} failed", internalIpPort, routerId, ex);
+ }
+ }
+ }
+ // delete the entry from SnatIntIpPortMap DS
+ LOG.debug("removeSnatEntriesForPort : Removing InternalIp:{} on router {}", internalIp, routerId);
+ naptManager.removeFromSnatIpPortDS(routerId, internalIp);
+ }
+ }
+
+ private class NatFlowAddWorker implements Callable<List<ListenableFuture<Void>>> {
+ private String interfaceName;
+ private String routerName;
+
+ NatFlowAddWorker(String interfaceName,String routerName) {
+ this.interfaceName = interfaceName;
+ this.routerName = routerName;
+ }
+
+ @Override
+ @SuppressWarnings("checkstyle:IllegalCatch")
+ public List<ListenableFuture<Void>> call() {
+ final List<ListenableFuture<Void>> futures = new ArrayList<>();
+ LOG.trace("call : Interface {} up event received", interfaceName);
+ try {
+ LOG.trace("call : Port added event received for interface {} ", interfaceName);
+ processInterfaceAdded(interfaceName, routerName, futures);
+ } catch (Exception ex) {
+ LOG.error("call : Exception caught in Interface {} Operational State Up event",
+ interfaceName, ex);
+ }
+ return futures;
+ }
+ }
+
+ private class NatFlowUpdateWorker implements Callable<List<ListenableFuture<Void>>> {
+ private Interface original;
+ private Interface update;
+ private String routerName;
+
+ NatFlowUpdateWorker(Interface original, Interface update, String routerName) {
+ this.original = original;
+ this.update = update;
+ this.routerName = routerName;
+ }
+
+ @Override
+ @SuppressWarnings("checkstyle:IllegalCatch")
+ public List<ListenableFuture<Void>> call() {
+ final List<ListenableFuture<Void>> futures = new ArrayList<>();
+ String interfaceName = update.getName();
+ IntfTransitionState state = getTransitionState(original.getOperStatus(), update.getOperStatus());
+ if (state.equals(IntfTransitionState.STATE_IGNORE)) {
+ LOG.info("NAT Service: Interface {} state original {} updated {} not handled",
+ interfaceName, original.getOperStatus(), update.getOperStatus());
+ return futures;
+ }
+ if (state.equals(IntfTransitionState.STATE_UP)) {
+ LOG.debug("call : Port UP event received for interface {} ", interfaceName);
+ } else if (state.equals(IntfTransitionState.STATE_DOWN)) {
+ LOG.debug("call : Port DOWN event received for interface {} ", interfaceName);
+ try {
+ removeSnatEntriesForPort(interfaceName, routerName);
+ } catch (Exception ex) {
+ LOG.error("call : Exception caught in Interface {} OperationalStateDown", interfaceName, ex);
+ }
+ }
+ return futures;
+ }
+ }
+
+ private class NatFlowRemoveWorker implements Callable<List<ListenableFuture<Void>>> {
+ private Interface delintrf;
+ private String routerName;
+ private BigInteger intfDpnId;
+
+ NatFlowRemoveWorker(Interface delintrf, BigInteger intfDpnId, String routerName) {
+ this.delintrf = delintrf;
+ this.routerName = routerName;
+ this.intfDpnId = intfDpnId;
+ }
+
+ @Override
+ @SuppressWarnings("checkstyle:IllegalCatch")
+ public List<ListenableFuture<Void>> call() {
+ final List<ListenableFuture<Void>> futures = new ArrayList<>();
+ final String interfaceName = delintrf.getName();
+ LOG.trace("call : Interface {} removed event received", delintrf);
+ try {
+ LOG.trace("call : Port removed event received for interface {} ", interfaceName);
+ processInterfaceRemoved(interfaceName, intfDpnId, routerName, futures);
+ removeSnatEntriesForPort(interfaceName, routerName);
+ } catch (Exception e) {
+ LOG.error("call : Exception caught in Interface {} OperationalStateRemove", interfaceName, e);
+ }
+ return futures;
+ }
+ }
+}
\ No newline at end of file