From: Achuth Maniyedath Date: Sat, 23 Sep 2017 12:50:14 +0000 (+0530) Subject: NETVIRT-1033: Adding ArpResponder flows for SR-IOV VMs X-Git-Tag: release/oxygen~64 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=commitdiff_plain;h=deabf2a77df0584b2ef7712d1676975e7ba879a3;p=netvirt.git NETVIRT-1033: Adding ArpResponder flows for SR-IOV VMs DHCP Neutron Port ARP handling for SR-IOV VMs. Handled removal of stale flows entry from ArpResponderTable. New pipeline for processing Neutron port DHCP ARPs Table 0 -> Table 18 -> Table 38 -> Table 81 Change-Id: Id5ee3160240cfcb6caec5790734d9f003c16640e Signed-off-by: Achuth Maniyedath Signed-off-by: Vijayalakshmi Chickkamenahalli Nagaraju --- diff --git a/vpnservice/dhcpservice/dhcpservice-api/src/main/java/org/opendaylight/netvirt/dhcpservice/api/DhcpMConstants.java b/vpnservice/dhcpservice/dhcpservice-api/src/main/java/org/opendaylight/netvirt/dhcpservice/api/DhcpMConstants.java index 52300ea568..99f7f746ec 100644 --- a/vpnservice/dhcpservice/dhcpservice-api/src/main/java/org/opendaylight/netvirt/dhcpservice/api/DhcpMConstants.java +++ b/vpnservice/dhcpservice/dhcpservice-api/src/main/java/org/opendaylight/netvirt/dhcpservice/api/DhcpMConstants.java @@ -16,6 +16,7 @@ public interface DhcpMConstants { int DEFAULT_DHCP_FLOW_PRIORITY = 50; int DEFAULT_DHCP_ALLOCATION_POOL_FLOW_PRIORITY = DEFAULT_DHCP_FLOW_PRIORITY - 1; + int DEFAULT_DHCP_ARP_FLOW_PRIORITY = 10; int ARP_FLOW_PRIORITY = 50; short DEFAULT_FLOW_PRIORITY = 100; diff --git a/vpnservice/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/netvirt/dhcpservice/DhcpDesignatedDpnListener.java b/vpnservice/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/netvirt/dhcpservice/DhcpDesignatedDpnListener.java index af89ba41d0..3397b749b2 100644 --- a/vpnservice/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/netvirt/dhcpservice/DhcpDesignatedDpnListener.java +++ b/vpnservice/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/netvirt/dhcpservice/DhcpDesignatedDpnListener.java @@ -18,6 +18,7 @@ import org.opendaylight.genius.datastoreutils.AsyncClusteredDataTreeChangeListen 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.netvirt.dhcp.rev160428.DesignatedSwitchesForExternalTunnels; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.dhcp.rev160428.designated.switches._for.external.tunnels.DesignatedSwitchForTunnel; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.dhcpservice.api.rev150710.subnet.dhcp.port.data.SubnetToDhcpPort; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.dhcpservice.config.rev150710.DhcpserviceConfig; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.slf4j.Logger; @@ -63,19 +64,41 @@ public class DhcpDesignatedDpnListener del.getTunnelRemoteIpAddress(), del.getElanInstanceName()); dhcpExternalTunnelManager.unInstallDhcpFlowsForVms(del.getElanInstanceName(), del.getTunnelRemoteIpAddress(), DhcpServiceUtils.getListOfDpns(broker)); + LOG.trace("Removing designated DPN {} DHCP Arp Flows for Elan {}.", del.getDpId(), del.getElanInstanceName()); + java.util.Optional subnetDhcpData = dhcpExternalTunnelManager + .getSubnetDhcpPortData(del.getElanInstanceName()); + if (subnetDhcpData.isPresent()) { + dhcpExternalTunnelManager.configureDhcpArpRequestResponseFlow(BigInteger.valueOf(del.getDpId()), + del.getElanInstanceName(), false, del.getTunnelRemoteIpAddress(), + subnetDhcpData.get().getPortFixedip(), subnetDhcpData.get().getPortMacaddress()); + } + } @Override protected void update(InstanceIdentifier identifier, DesignatedSwitchForTunnel original, DesignatedSwitchForTunnel update) { LOG.debug("Update for DesignatedSwitchForTunnel original {}, update {}", original, update); + dhcpExternalTunnelManager.removeFromLocalCache(BigInteger.valueOf(original.getDpId()), + original.getTunnelRemoteIpAddress(), original.getElanInstanceName()); BigInteger designatedDpnId = BigInteger.valueOf(update.getDpId()); IpAddress tunnelRemoteIpAddress = update.getTunnelRemoteIpAddress(); String elanInstanceName = update.getElanInstanceName(); - dhcpExternalTunnelManager.removeFromLocalCache(BigInteger.valueOf(original.getDpId()), - original.getTunnelRemoteIpAddress(), original.getElanInstanceName()); dhcpExternalTunnelManager.updateLocalCache(designatedDpnId, tunnelRemoteIpAddress, elanInstanceName); dhcpExternalTunnelManager.installRemoteMcastMac(designatedDpnId, tunnelRemoteIpAddress, elanInstanceName); + java.util.Optional subnetDhcpData = dhcpExternalTunnelManager + .getSubnetDhcpPortData(elanInstanceName); + if (subnetDhcpData.isPresent()) { + LOG.trace("Removing Designated DPN {} DHCP Arp Flows for Elan {}.", original.getDpId(), + original.getElanInstanceName()); + dhcpExternalTunnelManager.configureDhcpArpRequestResponseFlow(BigInteger.valueOf(original.getDpId()), + original.getElanInstanceName(), false, original.getTunnelRemoteIpAddress(), + subnetDhcpData.get().getPortFixedip(), subnetDhcpData.get().getPortMacaddress()); + LOG.trace("Configuring DHCP Arp Flows for Designated dpn {} Elan {}", designatedDpnId, elanInstanceName); + dhcpExternalTunnelManager.configureDhcpArpRequestResponseFlow(designatedDpnId, elanInstanceName, + true, tunnelRemoteIpAddress, subnetDhcpData.get().getPortFixedip(), + subnetDhcpData.get().getPortMacaddress()); + } } @Override @@ -86,6 +109,14 @@ public class DhcpDesignatedDpnListener String elanInstanceName = add.getElanInstanceName(); dhcpExternalTunnelManager.updateLocalCache(designatedDpnId, tunnelRemoteIpAddress, elanInstanceName); dhcpExternalTunnelManager.installRemoteMcastMac(designatedDpnId, tunnelRemoteIpAddress, elanInstanceName); + LOG.trace("Configuring DHCP Arp Flows for Designated dpn {} Elan {}", designatedDpnId, elanInstanceName); + java.util.Optional subnetDhcpData = dhcpExternalTunnelManager + .getSubnetDhcpPortData(elanInstanceName); + if (subnetDhcpData.isPresent()) { + dhcpExternalTunnelManager.configureDhcpArpRequestResponseFlow(designatedDpnId, elanInstanceName, + true, tunnelRemoteIpAddress, subnetDhcpData.get().getPortFixedip(), + subnetDhcpData.get().getPortMacaddress()); + } } @Override diff --git a/vpnservice/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/netvirt/dhcpservice/DhcpExternalTunnelManager.java b/vpnservice/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/netvirt/dhcpservice/DhcpExternalTunnelManager.java index 4d547c0b8f..134529fda1 100644 --- a/vpnservice/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/netvirt/dhcpservice/DhcpExternalTunnelManager.java +++ b/vpnservice/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/netvirt/dhcpservice/DhcpExternalTunnelManager.java @@ -26,6 +26,7 @@ import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import javax.annotation.PostConstruct; import javax.inject.Inject; +import javax.inject.Named; import javax.inject.Singleton; import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.commons.lang3.tuple.Pair; @@ -48,6 +49,9 @@ import org.opendaylight.infrautils.jobcoordinator.JobCoordinator; import org.opendaylight.infrautils.utils.concurrent.ListenableFutures; import org.opendaylight.mdsal.eos.binding.api.EntityOwnershipService; import org.opendaylight.netvirt.dhcpservice.api.DhcpMConstants; +import org.opendaylight.netvirt.elan.arp.responder.ArpResponderInput; +import org.opendaylight.netvirt.elan.arp.responder.ArpResponderUtil; +import org.opendaylight.netvirt.elanmanager.api.IElanService; import org.opendaylight.netvirt.elanmanager.utils.ElanL2GwCacheUtils; import org.opendaylight.netvirt.neutronvpn.api.l2gw.L2GatewayCache; import org.opendaylight.netvirt.neutronvpn.api.l2gw.L2GatewayDevice; @@ -67,9 +71,13 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.dhcp.rev160428.Desi import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.dhcp.rev160428.designated.switches._for.external.tunnels.DesignatedSwitchForTunnel; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.dhcp.rev160428.designated.switches._for.external.tunnels.DesignatedSwitchForTunnelBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.dhcp.rev160428.designated.switches._for.external.tunnels.DesignatedSwitchForTunnelKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInstances; +import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstance; +import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstanceKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports; import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port; import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.dhcpservice.api.rev150710.subnet.dhcp.port.data.SubnetToDhcpPort; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepLogicalSwitchRef; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepNodeName; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalLocatorRef; @@ -100,6 +108,7 @@ public class DhcpExternalTunnelManager { private final IInterfaceManager interfaceManager; private final JobCoordinator jobCoordinator; private final L2GatewayCache l2GatewayCache; + private IElanService elanService; private final ConcurrentMap>> designatedDpnsToTunnelIpElanNameCache = new ConcurrentHashMap<>(); @@ -112,7 +121,8 @@ public class DhcpExternalTunnelManager { public DhcpExternalTunnelManager(final DataBroker broker, final IMdsalApiManager mdsalUtil, final ItmRpcService itmRpcService, final EntityOwnershipService entityOwnershipService, final IInterfaceManager interfaceManager, - final JobCoordinator jobCoordinator, final L2GatewayCache l2GatewayCache) { + final JobCoordinator jobCoordinator, final L2GatewayCache l2GatewayCache, + @Named("elanService") IElanService ielanService) { this.broker = broker; this.txRunner = new ManagedNewTransactionRunnerImpl(broker); this.mdsalUtil = mdsalUtil; @@ -121,6 +131,7 @@ public class DhcpExternalTunnelManager { this.interfaceManager = interfaceManager; this.jobCoordinator = jobCoordinator; this.l2GatewayCache = l2GatewayCache; + this.elanService = ielanService; } @PostConstruct @@ -398,6 +409,11 @@ public class DhcpExternalTunnelManager { LOG.trace("Updating DHCP flows for VMs {} with new designated DPN {}", setOfVmMacs, newDesignatedDpn); installDhcpFlowsForVms(newDesignatedDpn, setOfVmMacs, tx); } + java.util.Optional subnetDhcpData = getSubnetDhcpPortData(pair.getRight()); + if (subnetDhcpData.isPresent()) { + configureDhcpArpRequestResponseFlow(newDesignatedDpn, pair.getRight(), true, + pair.getLeft(), subnetDhcpData.get().getPortFixedip(), subnetDhcpData.get().getPortMacaddress()); + } } private void changeExistingFlowToDrop(Pair tunnelIpElanNamePair, BigInteger dpnId, @@ -476,6 +492,122 @@ public class DhcpExternalTunnelManager { vmMacAddress, NwConstants.ADD_FLOW, mdsalUtil, tx); } + public void addOrRemoveDhcpArpFlowforElan(String elanInstanceName, boolean addFlow, String dhcpIpAddress, + String dhcpMacAddress) { + LOG.trace("Configure DHCP SR-IOV Arp flows for Elan {} dpns .", elanInstanceName); + for (Entry>> entry : designatedDpnsToTunnelIpElanNameCache.entrySet()) { + BigInteger dpn = entry.getKey(); + Set> tunnelIpElanNameSet = entry.getValue(); + for (Pair pair : tunnelIpElanNameSet) { + if (pair.getRight().equalsIgnoreCase(elanInstanceName)) { + if (addFlow) { + LOG.trace("Adding SR-IOV DHCP Arp Flows for Elan {} and tunnelIp {}", + elanInstanceName, pair.getLeft()); + configureDhcpArpRequestResponseFlow(dpn, elanInstanceName, true, + pair.getLeft(), dhcpIpAddress, dhcpMacAddress); + } else { + LOG.trace("Deleting SR-IOV DHCP Arp Flows for Elan {} and tunnelIp {}", + elanInstanceName, pair.getLeft()); + configureDhcpArpRequestResponseFlow(dpn, elanInstanceName, false, + pair.getLeft(), dhcpIpAddress, dhcpMacAddress); + } + } + } + } + } + + + public void configureDhcpArpRequestResponseFlow(BigInteger dpnId, String elanInstanceName, boolean addFlow, + IpAddress tunnelIp, String dhcpIpAddress, String dhcpMacAddress) { + L2GatewayDevice device = getDeviceFromTunnelIp(elanInstanceName, tunnelIp); + if (device == null) { + LOG.error("Unable to get L2Device for tunnelIp {} and elanInstanceName {}", tunnelIp, + elanInstanceName); + } + jobCoordinator.enqueueJob(getJobKey(elanInstanceName), () -> { + if (entityOwnershipUtils.isEntityOwner(HwvtepSouthboundConstants.ELAN_ENTITY_TYPE, + HwvtepSouthboundConstants.ELAN_ENTITY_NAME)) { + String tunnelInterfaceName = getExternalTunnelInterfaceName(String.valueOf(dpnId), + device.getHwvtepNodeId()); + int lportTag = interfaceManager.getInterfaceInfo(tunnelInterfaceName).getInterfaceTag(); + InstanceIdentifier elanIdentifier = InstanceIdentifier.builder(ElanInstances.class) + .child(ElanInstance.class, new ElanInstanceKey(elanInstanceName)).build(); + Optional optElan = MDSALUtil.read(broker, + LogicalDatastoreType.CONFIGURATION, elanIdentifier); + if (optElan.isPresent()) { + LOG.trace("Configuring the SR-IOV Arp request/response flows for LPort {} ElanTag {}.", + lportTag, optElan.get().getElanTag()); + Uuid nwUuid = new Uuid(elanInstanceName); + String strVni = DhcpServiceUtils.getSegmentationId(nwUuid, broker); + BigInteger vni = strVni != null ? new BigInteger(strVni) : BigInteger.ZERO; + if (!vni.equals(BigInteger.ZERO)) { + if (addFlow) { + LOG.trace("Installing the SR-IOV DHCP Arp flow for DPN {} Port Ip {}, Lport {}.", + dpnId, dhcpIpAddress, lportTag); + installDhcpArpRequestFlows(dpnId, vni, dhcpIpAddress, lportTag, + optElan.get().getElanTag()); + installDhcpArpResponderFlows(dpnId, tunnelInterfaceName, lportTag, elanInstanceName, + dhcpIpAddress, dhcpMacAddress); + } else { + LOG.trace("Uninstalling the SR-IOV DHCP Arp flows for DPN {} Port Ip {}, Lport {}.", + dpnId, dhcpIpAddress, lportTag); + uninstallDhcpArpRequestFlows(dpnId, vni, dhcpIpAddress, lportTag); + uninstallDhcpArpResponderFlows(dpnId, tunnelInterfaceName, lportTag, dhcpIpAddress); + } + } + } + } + return null; + }); + } + + public java.util.Optional getSubnetDhcpPortData(String elanInstanceName) { + java.util.Optional optSubnetDhcp = java.util.Optional.empty(); + Uuid nwUuid = new Uuid(elanInstanceName); + List subnets = DhcpServiceUtils.getSubnetIdsFromNetworkId(broker, nwUuid); + for (Uuid subnet : subnets) { + if (DhcpServiceUtils.isIpv4Subnet(broker, subnet)) { + optSubnetDhcp = DhcpServiceUtils.getSubnetDhcpPortData(broker, subnet.getValue()); + return optSubnetDhcp; + } + } + return optSubnetDhcp; + } + + private void installDhcpArpRequestFlows(BigInteger dpnId, BigInteger vni, String dhcpIpAddress, + int lportTag, Long elanTag) { + DhcpServiceUtils.setupDhcpArpRequest(dpnId, NwConstants.EXTERNAL_TUNNEL_TABLE, vni, dhcpIpAddress, + lportTag, elanTag, true, mdsalUtil); + } + + private void installDhcpArpResponderFlows(BigInteger dpnId, String interfaceName, int lportTag, + String elanInstanceName, String dhcpIpAddress, String dhcpMacAddress) { + LOG.trace("Adding SR-IOV DHCP ArpResponder for elan {} Lport {} Port Ip {}.", + elanInstanceName, lportTag, dhcpIpAddress); + ArpResponderInput.ArpReponderInputBuilder builder = new ArpResponderInput.ArpReponderInputBuilder(); + builder.setDpId(dpnId).setInterfaceName(interfaceName).setSpa(dhcpIpAddress).setSha(dhcpMacAddress) + .setLportTag(lportTag); + builder.setInstructions(ArpResponderUtil.getInterfaceInstructions(interfaceManager, interfaceName, + dhcpIpAddress, dhcpMacAddress)); + elanService.addExternalTunnelArpResponderFlow(builder.buildForInstallFlow(), elanInstanceName); + } + + private void uninstallDhcpArpResponderFlows(BigInteger dpnId, String interfaceName, int lportTag, + String dhcpIpAddress) { + LOG.trace("Removing SR-IOV DHCP ArpResponder flow for interface {} on DPN {}", interfaceName, dpnId); + ArpResponderInput arpInput = new ArpResponderInput.ArpReponderInputBuilder().setDpId(dpnId) + .setInterfaceName(interfaceName).setSpa(dhcpIpAddress) + .setLportTag(lportTag).buildForRemoveFlow(); + elanService.removeArpResponderFlow(arpInput); + } + + private void uninstallDhcpArpRequestFlows(BigInteger dpnId, BigInteger vni, String dhcpIpAddress, + int lportTag) { + DhcpServiceUtils.setupDhcpArpRequest(dpnId, NwConstants.EXTERNAL_TUNNEL_TABLE, vni, dhcpIpAddress, + lportTag, null, false, mdsalUtil); + } + + public void unInstallDhcpEntries(BigInteger dpnId, String vmMacAddress, WriteTransaction tx) { DhcpServiceUtils.setupDhcpFlowEntry(dpnId, NwConstants.DHCP_TABLE_EXTERNAL_TUNNEL, vmMacAddress, NwConstants.DEL_FLOW, mdsalUtil, tx); @@ -510,6 +642,7 @@ public class DhcpExternalTunnelManager { return Collections.singletonList(txRunner.callWithNewReadWriteTransactionAndSubmit(tx -> { for (Pair tunnelElanPair : tunnelElanPairSet) { IpAddress tunnelIpInDpn = tunnelElanPair.getLeft(); + String elanInstanceName = tunnelElanPair.getRight(); if (tunnelIpInDpn.equals(tunnelIp)) { if (!checkL2GatewayConnection(tunnelElanPair)) { LOG.trace("Couldn't find device for given tunnelIpElanPair {} in L2GwConnCache", @@ -518,6 +651,12 @@ public class DhcpExternalTunnelManager { List dpns = DhcpServiceUtils.getListOfDpns(broker); dpns.remove(interfaceDpn); changeExistingFlowToDrop(tunnelElanPair, interfaceDpn, tx); + java.util.Optional subnetDhcpData = getSubnetDhcpPortData(elanInstanceName); + if (subnetDhcpData.isPresent()) { + configureDhcpArpRequestResponseFlow(interfaceDpn, elanInstanceName, false, + tunnelIpInDpn, subnetDhcpData.get().getPortFixedip(), + subnetDhcpData.get().getPortMacaddress()); + } updateCacheAndInstallNewFlows(interfaceDpn, dpns, tunnelElanPair, tx); } } @@ -756,7 +895,8 @@ public class DhcpExternalTunnelManager { return Collections.singletonList(txRunner.callWithNewReadWriteTransactionAndSubmit(tx -> { for (Pair pair : tunnelIpElanPair) { if (tunnelIp.equals(pair.getLeft())) { - BigInteger newDesignatedDpn = designateDpnId(tunnelIp, pair.getRight(), dpns); + String elanInstanceName = pair.getRight(); + BigInteger newDesignatedDpn = designateDpnId(tunnelIp, elanInstanceName, dpns); if (newDesignatedDpn != null && !newDesignatedDpn.equals(DhcpMConstants.INVALID_DPID)) { Set vmMacAddress = tunnelIpElanNameToVmMacCache.get(pair); if (vmMacAddress != null && !vmMacAddress.isEmpty()) { @@ -765,6 +905,12 @@ public class DhcpExternalTunnelManager { installDhcpFlowsForVms(newDesignatedDpn, vmMacAddress, tx); } } + java.util.Optional subnetDhcpData = getSubnetDhcpPortData(elanInstanceName); + if (subnetDhcpData.isPresent()) { + configureDhcpArpRequestResponseFlow(newDesignatedDpn, elanInstanceName, + true, tunnelIp, subnetDhcpData.get().getPortFixedip(), + subnetDhcpData.get().getPortMacaddress()); + } } } })); diff --git a/vpnservice/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/netvirt/dhcpservice/DhcpInterfaceEventListener.java b/vpnservice/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/netvirt/dhcpservice/DhcpInterfaceEventListener.java index f43cdc3b4f..af96970426 100644 --- a/vpnservice/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/netvirt/dhcpservice/DhcpInterfaceEventListener.java +++ b/vpnservice/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/netvirt/dhcpservice/DhcpInterfaceEventListener.java @@ -43,17 +43,19 @@ public class DhcpInterfaceEventListener private final JobCoordinator jobCoordinator; private final IInterfaceManager interfaceManager; private final IElanService elanService; + private final DhcpPortCache dhcpPortCache; public DhcpInterfaceEventListener(DhcpManager dhcpManager, DataBroker dataBroker, DhcpExternalTunnelManager dhcpExternalTunnelManager, IInterfaceManager interfaceManager, IElanService elanService, - JobCoordinator jobCoordinator) { + DhcpPortCache dhcpPortCache, JobCoordinator jobCoordinator) { super(Interface.class, DhcpInterfaceEventListener.class); this.dhcpManager = dhcpManager; this.dataBroker = dataBroker; this.dhcpExternalTunnelManager = dhcpExternalTunnelManager; this.interfaceManager = interfaceManager; this.elanService = elanService; + this.dhcpPortCache = dhcpPortCache; this.jobCoordinator = jobCoordinator; registerListener(LogicalDatastoreType.OPERATIONAL, dataBroker); } @@ -74,15 +76,16 @@ public class DhcpInterfaceEventListener return; } String interfaceName = del.getName(); - Port port = dhcpManager.getNeutronPort(interfaceName); + Port port = dhcpPortCache.get(interfaceName); if (NeutronConstants.IS_DHCP_PORT.test(port)) { return; } NodeConnectorId nodeConnectorId = new NodeConnectorId(ofportIds.get(0)); BigInteger dpnId = BigInteger.valueOf(MDSALUtil.getDpnIdFromPortName(nodeConnectorId)); DhcpInterfaceRemoveJob job = new DhcpInterfaceRemoveJob(dhcpManager, dhcpExternalTunnelManager, - dataBroker, del, dpnId, interfaceManager, elanService); + dataBroker, del, dpnId, interfaceManager, elanService, port); jobCoordinator.enqueueJob(DhcpServiceUtils.getJobKey(interfaceName), job, DhcpMConstants.RETRY_COUNT); + dhcpPortCache.remove(interfaceName); } @Override @@ -130,7 +133,7 @@ public class DhcpInterfaceEventListener if (NeutronConstants.IS_DHCP_PORT.test(port)) { return; } - + dhcpPortCache.put(interfaceName, port); NodeConnectorId nodeConnectorId = new NodeConnectorId(ofportIds.get(0)); BigInteger dpnId = BigInteger.valueOf(MDSALUtil.getDpnIdFromPortName(nodeConnectorId)); DhcpInterfaceAddJob job = new DhcpInterfaceAddJob(dhcpManager, dhcpExternalTunnelManager, dataBroker, diff --git a/vpnservice/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/netvirt/dhcpservice/DhcpManager.java b/vpnservice/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/netvirt/dhcpservice/DhcpManager.java index 2639c003d0..6f0f7616f7 100644 --- a/vpnservice/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/netvirt/dhcpservice/DhcpManager.java +++ b/vpnservice/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/netvirt/dhcpservice/DhcpManager.java @@ -52,6 +52,7 @@ public class DhcpManager { private final IInterfaceManager interfaceManager; private final IElanService elanService; private final JobCoordinator jobCoordinator; + private DhcpPortCache dhcpPortCache; private volatile int dhcpOptLeaseTime = 0; private volatile String dhcpOptDefDomainName; @@ -63,7 +64,7 @@ public class DhcpManager { final INeutronVpnManager neutronVpnManager, final DhcpserviceConfig config, final DataBroker dataBroker, final DhcpExternalTunnelManager dhcpExternalTunnelManager, final IInterfaceManager interfaceManager, - final @Named("elanService") IElanService ielanService, + @Named("elanService") IElanService ielanService, final DhcpPortCache dhcpPortCache, final JobCoordinator jobCoordinator) { this.mdsalUtil = mdsalApiManager; this.neutronVpnService = neutronVpnManager; @@ -72,6 +73,7 @@ public class DhcpManager { this.dhcpExternalTunnelManager = dhcpExternalTunnelManager; this.interfaceManager = interfaceManager; this.elanService = ielanService; + this.dhcpPortCache = dhcpPortCache; this.jobCoordinator = jobCoordinator; configureLeaseDuration(DhcpMConstants.DEFAULT_LEASE_TIME); } @@ -81,7 +83,7 @@ public class DhcpManager { LOG.trace("Netvirt DHCP Manager Init .... {}",config.isControllerDhcpEnabled()); if (config.isControllerDhcpEnabled()) { dhcpInterfaceEventListener = new DhcpInterfaceEventListener(this, broker, dhcpExternalTunnelManager, - interfaceManager, elanService, jobCoordinator); + interfaceManager, elanService, dhcpPortCache, jobCoordinator); dhcpInterfaceConfigListener = new DhcpInterfaceConfigListener(broker, dhcpExternalTunnelManager, this, jobCoordinator); LOG.info("DHCP Service initialized"); diff --git a/vpnservice/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/netvirt/dhcpservice/DhcpNeutronPortListener.java b/vpnservice/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/netvirt/dhcpservice/DhcpNeutronPortListener.java index 4ff59dcee2..4042dfb176 100644 --- a/vpnservice/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/netvirt/dhcpservice/DhcpNeutronPortListener.java +++ b/vpnservice/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/netvirt/dhcpservice/DhcpNeutronPortListener.java @@ -98,14 +98,17 @@ public class DhcpNeutronPortListener if (NeutronConstants.IS_ODL_DHCP_PORT.test(del)) { jobCoordinator.enqueueJob(getJobKey(del), () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> { + java.util.Optional ip4Address = DhcpServiceUtils.getIpV4Address(del); + if (ip4Address.isPresent()) { + dhcpExternalTunnelManager.addOrRemoveDhcpArpFlowforElan(del.getNetworkId().getValue(), + false, ip4Address.get(), del.getMacAddress().getValue()); + } DhcpServiceUtils.removeSubnetDhcpPortData(del, subnetDhcpPortIdfr -> tx .delete(LogicalDatastoreType.CONFIGURATION, subnetDhcpPortIdfr)); processArpResponderForElanDpns(del, arpInput -> { - LOG.trace( - "Removing ARP RESPONDER Flows for dhcp port {} with ipaddress {} with mac {} on dpn " - + "{}", - arpInput.getInterfaceName(), arpInput.getSpa(), arpInput.getSha(), - arpInput.getDpId()); + LOG.trace("Removing ARPResponder Flows for dhcp port {} with ipaddress {} with mac {} " + + " on dpn {}. ",arpInput.getInterfaceName(), arpInput.getSpa(), + arpInput.getSha(), arpInput.getDpId()); elanService.removeArpResponderFlow(arpInput); }); }))); @@ -196,6 +199,11 @@ public class DhcpNeutronPortListener elanService.addArpResponderFlow(builder.buildForInstallFlow()); }); }))); + java.util.Optional ip4Address = DhcpServiceUtils.getIpV4Address(add); + if (ip4Address.isPresent()) { + dhcpExternalTunnelManager.addOrRemoveDhcpArpFlowforElan(add.getNetworkId().getValue(), + true, ip4Address.get(), add.getMacAddress().getValue()); + } } if (!isVnicTypeDirectOrMacVtap(add)) { return; diff --git a/vpnservice/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/netvirt/dhcpservice/DhcpPktHandler.java b/vpnservice/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/netvirt/dhcpservice/DhcpPktHandler.java index b214e41a16..0687408069 100644 --- a/vpnservice/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/netvirt/dhcpservice/DhcpPktHandler.java +++ b/vpnservice/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/netvirt/dhcpservice/DhcpPktHandler.java @@ -137,16 +137,20 @@ public class DhcpPktHandler implements PacketProcessingListener { LOG.error("Failed to get interface info for interface name {}", interfaceName); return; } - Port port = getNeutronPort(interfaceName); + Port port; + if (tunnelId != null) { + port = dhcpExternalTunnelManager.readVniMacToPortCache(tunnelId, macAddress); + } else { + port = getNeutronPort(interfaceName); + } Subnet subnet = getNeutronSubnet(port); - //When neutronport-dhcp flag is disabled continue running DHCP Server by hijacking the subnet-gateway-ip String serverMacAddress = interfaceInfo.getMacAddress(); String serverIp = null; if (subnet != null) { java.util.Optional dhcpPortData = DhcpServiceUtils .getSubnetDhcpPortData(broker, subnet.getUuid().getValue()); - /* If neutronport-dhcp flag was enabled and an ODL network DHCP Port data was made available use the - * ports Fixed IP as server IP for DHCP communication. + /* If enable_dhcp_service flag was enabled and an ODL network DHCP Port data was made available use + * the ports Fixed IP as server IP for DHCP communication. */ if (dhcpPortData.isPresent()) { serverIp = dhcpPortData.get().getPortFixedip(); @@ -158,7 +162,11 @@ public class DhcpPktHandler implements PacketProcessingListener { return; } } - DHCP replyPkt = handleDhcpPacket(pktIn, interfaceName, macAddress, tunnelId, port, subnet, serverIp); + DHCP replyPkt = handleDhcpPacket(pktIn, interfaceName, macAddress, port, subnet, serverIp); + if (replyPkt == null) { + LOG.warn("Unable to construct reply packet for interface name {}", interfaceName); + return; + } byte[] pktOut = getDhcpPacketOut(replyPkt, ethPkt, serverMacAddress); sendPacketOut(pktOut, interfaceInfo.getDpId(), interfaceName, tunnelId); } @@ -172,19 +180,13 @@ public class DhcpPktHandler implements PacketProcessingListener { JdkFutures.addErrorLogging(pktService.transmitPacket(output), LOG, "Transmit packet"); } - private DHCP handleDhcpPacket(DHCP dhcpPkt, String interfaceName, String macAddress, BigInteger tunnelId, - Port interfacePort, Subnet subnet, String serverIp) { + private DHCP handleDhcpPacket(DHCP dhcpPkt, String interfaceName, String macAddress, Port interfacePort, + Subnet subnet, String serverIp) { LOG.trace("DHCP pkt rcvd {}", dhcpPkt); byte msgType = dhcpPkt.getMsgType(); - Port port; - if (tunnelId != null) { - port = dhcpExternalTunnelManager.readVniMacToPortCache(tunnelId, macAddress); - } else { - port = interfacePort; - } DhcpInfo dhcpInfo = null; - if (port != null) { - dhcpInfo = handleDhcpNeutronPacket(msgType, port, subnet, serverIp); + if (interfacePort != null) { + dhcpInfo = handleDhcpNeutronPacket(msgType, interfacePort, subnet, serverIp); } else if (config.isDhcpDynamicAllocationPoolEnabled()) { dhcpInfo = handleDhcpAllocationPoolPacket(msgType, dhcpPkt, interfaceName, macAddress); } diff --git a/vpnservice/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/netvirt/dhcpservice/DhcpPortCache.java b/vpnservice/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/netvirt/dhcpservice/DhcpPortCache.java new file mode 100644 index 0000000000..1047b05c17 --- /dev/null +++ b/vpnservice/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/netvirt/dhcpservice/DhcpPortCache.java @@ -0,0 +1,44 @@ +/* + * Copyright © 2015, 2018 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.dhcpservice; + +import java.util.concurrent.ConcurrentHashMap; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import javax.annotation.PostConstruct; +import javax.inject.Singleton; + +import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@Singleton +public class DhcpPortCache { + + private static final Logger LOG = LoggerFactory.getLogger(DhcpPortCache.class); + private final ConcurrentHashMap portMap = new ConcurrentHashMap(); + + @PostConstruct + public void init() { + LOG.trace("Initialize DhcpPortCache. "); + } + + public void put(@Nonnull String interfaceName, Port port) { + portMap.put(interfaceName, port); + LOG.trace("Added the interface {} to DhcpPortCache",interfaceName); + } + + @Nullable + public Port get(@Nonnull String interfaceName) { + return portMap.get(interfaceName); + } + + public void remove(@Nonnull String interfaceName) { + portMap.remove(interfaceName); + } +} diff --git a/vpnservice/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/netvirt/dhcpservice/DhcpServiceUtils.java b/vpnservice/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/netvirt/dhcpservice/DhcpServiceUtils.java index ca82ae64c9..940749304f 100644 --- a/vpnservice/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/netvirt/dhcpservice/DhcpServiceUtils.java +++ b/vpnservice/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/netvirt/dhcpservice/DhcpServiceUtils.java @@ -11,7 +11,10 @@ package org.opendaylight.netvirt.dhcpservice; import com.google.common.base.Optional; import com.google.common.util.concurrent.FutureCallback; import java.math.BigInteger; +import java.net.InetAddress; +import java.net.UnknownHostException; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.LinkedList; import java.util.List; @@ -36,23 +39,29 @@ import org.opendaylight.genius.mdsalutil.InstructionInfo; import org.opendaylight.genius.mdsalutil.MDSALDataStoreUtils; import org.opendaylight.genius.mdsalutil.MDSALUtil; import org.opendaylight.genius.mdsalutil.MatchInfo; +import org.opendaylight.genius.mdsalutil.NWUtil; import org.opendaylight.genius.mdsalutil.NwConstants; import org.opendaylight.genius.mdsalutil.actions.ActionDrop; import org.opendaylight.genius.mdsalutil.actions.ActionPuntToController; import org.opendaylight.genius.mdsalutil.instructions.InstructionApplyActions; import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager; +import org.opendaylight.genius.mdsalutil.matches.MatchArpOp; +import org.opendaylight.genius.mdsalutil.matches.MatchArpTpa; import org.opendaylight.genius.mdsalutil.matches.MatchEthernetSource; import org.opendaylight.genius.mdsalutil.matches.MatchEthernetType; import org.opendaylight.genius.mdsalutil.matches.MatchIpProtocol; +import org.opendaylight.genius.mdsalutil.matches.MatchTunnelId; import org.opendaylight.genius.mdsalutil.matches.MatchUdpDestinationPort; import org.opendaylight.genius.mdsalutil.matches.MatchUdpSourcePort; import org.opendaylight.genius.utils.ServiceIndex; import org.opendaylight.netvirt.dhcpservice.api.DhcpMConstants; +import org.opendaylight.netvirt.elanmanager.api.ElanHelper; import org.opendaylight.netvirt.neutronvpn.api.utils.NeutronUtils; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress; 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.yang.types.rev130715.MacAddress; 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.flow.inventory.rev130819.tables.table.Flow; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceBindings; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceModeIngress; @@ -70,6 +79,11 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.Elan import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.dpn.interfaces.ElanDpnInterfacesList; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.dpn.interfaces.ElanDpnInterfacesListKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.dpn.interfaces.elan.dpn.interfaces.list.DpnInterfaces; +import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NetworkMaps; +import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.networkmaps.NetworkMap; +import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.networkmaps.NetworkMapKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.IpVersionBase; +import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.IpVersionV4; import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.NetworkTypeVxlan; import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.Networks; import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network; @@ -78,6 +92,9 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.por import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports; import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port; import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron; +import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.Subnets; +import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet; +import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.SubnetKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.dhcpservice.api.rev150710.InterfaceNameMacAddresses; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.dhcpservice.api.rev150710.SubnetDhcpPortData; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.dhcpservice.api.rev150710._interface.name.mac.addresses.InterfaceNameMacAddress; @@ -144,6 +161,14 @@ public final class DhcpServiceUtils { .append(vmMacAddress).toString(); } + private static String getDhcpArpFlowRef(BigInteger dpId, long tableId, long lportTag, String ipAddress) { + return new StringBuffer().append(DhcpMConstants.FLOWID_PREFIX) + .append(dpId).append(NwConstants.FLOWID_SEPARATOR) + .append(tableId).append(NwConstants.FLOWID_SEPARATOR) + .append(lportTag).append(NwConstants.FLOWID_SEPARATOR) + .append(ipAddress).toString(); + } + public static void setupDhcpDropAction(BigInteger dpId, short tableId, String vmMacAddress, int addOrRemove, IMdsalApiManager mdsalUtil, WriteTransaction tx) { if (dpId == null || dpId.equals(DhcpMConstants.INVALID_DPID) || vmMacAddress == null) { @@ -174,6 +199,26 @@ public final class DhcpServiceUtils { } } + @SuppressWarnings("checkstyle:IllegalCatch") + public static void setupDhcpArpRequest(BigInteger dpId, short tableId, BigInteger vni, String dhcpIpAddress, + int lportTag, Long elanTag, boolean add, IMdsalApiManager mdsalUtil) { + List matches = getDhcpArpMatch(vni, dhcpIpAddress); + if (add) { + Flow flow = MDSALUtil.buildFlowNew(tableId, getDhcpArpFlowRef(dpId, tableId, lportTag, dhcpIpAddress), + DhcpMConstants.DEFAULT_DHCP_ARP_FLOW_PRIORITY, "DHCPArp", 0, 0, + generateDhcpArpCookie(lportTag, dhcpIpAddress), matches, null); + LOG.trace("Removing DHCP ARP Flow DpId {}, DHCP Port IpAddress {}", dpId, dhcpIpAddress); + mdsalUtil.removeFlow(dpId, flow); + } else { + Flow flow = MDSALUtil.buildFlowNew(tableId, getDhcpArpFlowRef(dpId, tableId, lportTag, dhcpIpAddress), + DhcpMConstants.DEFAULT_DHCP_ARP_FLOW_PRIORITY, "DHCPArp", 0, 0, + generateDhcpArpCookie(lportTag, dhcpIpAddress), matches, + getDhcpArpInstructions(elanTag, lportTag)); + LOG.trace("Adding DHCP ARP Flow DpId {}, DHCPPort IpAddress {}", dpId, dhcpIpAddress); + mdsalUtil.installFlow(dpId, flow); + } + } + public static List getDhcpMatch() { List matches = new ArrayList<>(); matches.add(MatchEthernetType.IPV4); @@ -189,7 +234,32 @@ public final class DhcpServiceUtils { return matches; } - @Nonnull + private static List getDhcpArpMatch(BigInteger vni, String ipAddress) { + return Arrays.asList(MatchEthernetType.ARP, MatchArpOp.REQUEST, new MatchTunnelId(vni), + new MatchArpTpa(ipAddress, "32")); + } + + private static List getDhcpArpInstructions(Long elanTag, int lportTag) { + List mkInstructions = new ArrayList<>(); + int instructionKey = 0; + mkInstructions.add(MDSALUtil.buildAndGetWriteMetadaInstruction( + ElanHelper.getElanMetadataLabel(elanTag, lportTag), ElanHelper.getElanMetadataMask(), + ++instructionKey)); + mkInstructions.add(MDSALUtil.buildAndGetGotoTableInstruction(NwConstants.ARP_RESPONDER_TABLE, + ++instructionKey)); + return mkInstructions; + } + + private static BigInteger generateDhcpArpCookie(int lportTag, String ipAddress) { + try { + BigInteger cookie = NwConstants.TUNNEL_TABLE_COOKIE.add(BigInteger.valueOf(255)) + .add(BigInteger.valueOf(NWUtil.convertInetAddressToLong(InetAddress.getByName(ipAddress)))); + return cookie.add(BigInteger.valueOf(lportTag)); + } catch (UnknownHostException e) { + return NwConstants.TUNNEL_TABLE_COOKIE.add(BigInteger.valueOf(lportTag)); + } + } + public static List getListOfDpns(DataBroker broker) { return extractDpnsFromNodes(MDSALUtil.read(broker, LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.builder(Nodes.class).build())); @@ -455,4 +525,34 @@ public final class DhcpServiceUtils { return null; } + public static List getSubnetIdsFromNetworkId(DataBroker broker, Uuid networkId) { + InstanceIdentifier id = buildNetworkMapIdentifier(networkId); + Optional optionalNetworkMap = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, id); + if (optionalNetworkMap.isPresent()) { + return optionalNetworkMap.get().getSubnetIdList(); + } + return null; + } + + static InstanceIdentifier buildNetworkMapIdentifier(Uuid networkId) { + InstanceIdentifier id = InstanceIdentifier.builder(NetworkMaps.class).child(NetworkMap.class, new + NetworkMapKey(networkId)).build(); + return id; + } + + public static boolean isIpv4Subnet(DataBroker broker, Uuid subnetUuid) { + final SubnetKey subnetkey = new SubnetKey(subnetUuid); + final InstanceIdentifier subnetidentifier = InstanceIdentifier.create(Neutron.class) + .child(Subnets.class).child(Subnet.class, subnetkey); + final Optional subnet = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, subnetidentifier); + if (subnet.isPresent()) { + Class ipVersionBase = subnet.get().getIpVersion(); + if (ipVersionBase.equals(IpVersionV4.class)) { + return true; + } + } + return false; + } + } + diff --git a/vpnservice/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/netvirt/dhcpservice/jobs/DhcpInterfaceRemoveJob.java b/vpnservice/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/netvirt/dhcpservice/jobs/DhcpInterfaceRemoveJob.java index e3771a6dcb..77fcaa6b16 100644 --- a/vpnservice/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/netvirt/dhcpservice/jobs/DhcpInterfaceRemoveJob.java +++ b/vpnservice/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/netvirt/dhcpservice/jobs/DhcpInterfaceRemoveJob.java @@ -63,11 +63,12 @@ public class DhcpInterfaceRemoveJob implements Callable DhcpServiceUtils.unbindDhcpService(interfaceName, tx))); - Port port = dhcpManager.getNeutronPort(interfaceName); java.util.Optional subnetId = DhcpServiceUtils.getNeutronSubnetId(port); if (subnetId.isPresent()) { java.util.Optional subnetToDhcp = DhcpServiceUtils.getSubnetDhcpPortData(dataBroker, diff --git a/vpnservice/elanmanager/elanmanager-api/src/main/java/org/opendaylight/netvirt/elanmanager/api/IElanService.java b/vpnservice/elanmanager/elanmanager-api/src/main/java/org/opendaylight/netvirt/elanmanager/api/IElanService.java index 61d1ff1bb1..b797bc7216 100644 --- a/vpnservice/elanmanager/elanmanager-api/src/main/java/org/opendaylight/netvirt/elanmanager/api/IElanService.java +++ b/vpnservice/elanmanager/elanmanager-api/src/main/java/org/opendaylight/netvirt/elanmanager/api/IElanService.java @@ -93,6 +93,17 @@ public interface IElanService extends IEtreeService { */ void addArpResponderFlow(ArpResponderInput arpResponderInput); + /** + * Add ARP Responder Flow on the given dpn for the SR-IOV VMs ingress interface. + * + * @param arpResponderInput + * ArpResponder Input parameters + * @see ArpResponderInput + * @param elanInstanceName + * The elanInstance corresponding to the interface + */ + void addExternalTunnelArpResponderFlow(ArpResponderInput arpResponderInput, String elanInstanceName); + /** * Remove ARP Responder flow from the given dpn for the ingress interface. * diff --git a/vpnservice/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/netvirt/elan/internal/ElanServiceProvider.java b/vpnservice/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/netvirt/elan/internal/ElanServiceProvider.java index 609816821e..a1504834d4 100644 --- a/vpnservice/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/netvirt/elan/internal/ElanServiceProvider.java +++ b/vpnservice/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/netvirt/elan/internal/ElanServiceProvider.java @@ -854,6 +854,13 @@ public class ElanServiceProvider extends AbstractLifecycle implements IElanServi arpResponderInput.getInstructions()); } + @Override + public void addExternalTunnelArpResponderFlow(ArpResponderInput arpResponderInput, String elanInstanceName) { + elanUtils.addExternalTunnelArpResponderFlow(arpResponderInput.getDpId(), arpResponderInput.getSpa(), + arpResponderInput.getSha(), arpResponderInput.getLportTag(), + arpResponderInput.getInstructions(), elanInstanceName); + } + @Override public void removeArpResponderFlow(ArpResponderInput arpResponderInput) { elanUtils.removeArpResponderFlow(arpResponderInput.getDpId(), arpResponderInput.getInterfaceName(), diff --git a/vpnservice/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/netvirt/elan/utils/ElanUtils.java b/vpnservice/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/netvirt/elan/utils/ElanUtils.java index 98887c1116..453823bece 100755 --- a/vpnservice/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/netvirt/elan/utils/ElanUtils.java +++ b/vpnservice/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/netvirt/elan/utils/ElanUtils.java @@ -1796,6 +1796,18 @@ public class ElanUtils { LOG.info("Installed the ARP Responder flow for Interface {}", ingressInterfaceName); } + public void addExternalTunnelArpResponderFlow(BigInteger dpnId, String ipAddress, String macAddress, + int lportTag, List instructions, String elanInstanceName) { + LOG.trace("Installing the ExternalTunnel ARP responder flow on DPN {} for ElanInstance {} with MAC {} & IP {}", + dpnId, elanInstanceName, macAddress, ipAddress); + ElanInstance elanInstance = getElanInstanceByName(broker, elanInstanceName); + String flowId = ArpResponderUtil.getFlowId(lportTag, ipAddress); + ArpResponderUtil.installFlow(mdsalManager, dpnId, flowId, flowId, NwConstants.DEFAULT_ARP_FLOW_PRIORITY, + ArpResponderUtil.generateCookie(lportTag, ipAddress), + ArpResponderUtil.getMatchCriteria(lportTag, elanInstance, ipAddress), instructions); + LOG.trace("Installed the ExternalTunnel ARP Responder flow for ElanInstance {}", elanInstanceName); + } + public void removeArpResponderFlow(BigInteger dpnId, String ingressInterfaceName, String ipAddress, int lportTag) { LOG.info("Removing the ARP responder flow on DPN {} of Interface {} with IP {}", dpnId, ingressInterfaceName,