From: Josh Date: Thu, 10 Mar 2016 18:13:17 +0000 (+0200) Subject: BUG-4417 Program tunnel flows on new Neutron nodes X-Git-Tag: release/boron~435^2 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=commitdiff_plain;h=e374dd2c7a3e0edaeb5b49eef026d9abeb704918;p=netvirt.git BUG-4417 Program tunnel flows on new Neutron nodes Here's how the fix works. 1) In handleInterfaceUpdate, when a bridge comes in that does not have any tap ports on it, we remember that as a "new node" 2) When a tap port comes in for that new node we trigger interfaceUpdates to fill in the missing tunnel flows from *other* ports to this new node - ingress and egress. Change-Id: I872e875f7a1f254f0bd14b7da4ed572ee7e40b9b Signed-off-by: Josh --- diff --git a/openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/OF13Provider.java b/openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/OF13Provider.java index 84665e4c84..dcf6436666 100644 --- a/openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/OF13Provider.java +++ b/openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/OF13Provider.java @@ -9,8 +9,11 @@ package org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13; import java.net.InetAddress; +import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.concurrent.ExecutionException; import org.opendaylight.controller.md.sal.binding.api.DataBroker; @@ -19,6 +22,7 @@ import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction; import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException; +import org.opendaylight.ovsdb.openstack.netvirt.api.OvsdbTables; import org.opendaylight.ovsdb.openstack.netvirt.translator.NeutronNetwork; import org.opendaylight.ovsdb.openstack.netvirt.translator.NeutronPort; import org.opendaylight.ovsdb.openstack.netvirt.translator.NeutronSecurityGroup; @@ -56,12 +60,10 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.acti import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCase; @@ -88,6 +90,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.N import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation; import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceReference; @@ -134,6 +137,9 @@ public class OF13Provider implements ConfigInterface, NetworkingProvider { private volatile BundleContext bundleContext; private volatile Southbound southbound; + private Set + intBridgesWithoutVmPorts = new HashSet<>(); + public OF13Provider() { this.dataBroker = NetvirtProvidersProvider.getDataBroker(); } @@ -815,10 +821,6 @@ public class OF13Provider implements ConfigInterface, NetworkingProvider { } } - // TODO SB_MIGRATION - // Need to handle case where a node comes online after a network and tunnels have - // already been created. The interface update is what triggers creating the l2 forwarding flows - // so we don't see those updates in this case - we only see the new nodes interface updates. private void programTunnelRules (String tunnelType, String segmentationId, InetAddress dst, Node node, OvsdbTerminationPointAugmentation intf, boolean local) { LOG.debug("programTunnelRules: node: {}, intf: {}, local: {}, tunnelType: {}, " @@ -844,7 +846,7 @@ public class OF13Provider implements ConfigInterface, NetworkingProvider { } OvsdbTerminationPointAugmentation tunnelPort= southbound.getTerminationPointOfBridge(node, getTunnelName(tunnelType, dst)); - if(tunnelPort != null){ + if (tunnelPort != null){ long tunnelOFPort = southbound.getOFPort(tunnelPort); if (tunnelOFPort == 0) { LOG.error("programTunnelRules: Could not Identify Tunnel port {} -> OF ({}) on {}", @@ -1064,9 +1066,12 @@ public class OF13Provider implements ConfigInterface, NetworkingProvider { InetAddress src, InetAddress dst, Node srcBridgeNode, Node dstBridgeNode, OvsdbTerminationPointAugmentation intf){ + LOG.debug("programTunnelRulesInNewNode: network {} networkType {} segId {} src {} dst {} srcBridgeNode {} dstBridgeNode {} intf {}", + network.getNetworkName(), networkType, segmentationId, src.getHostAddress(), + dst.getHostAddress(), srcBridgeNode, dstBridgeNode, intf); try { long localPort = southbound.getOFPort(intf); - if(localPort != 0) + if (localPort != 0) { LOG.debug("Interface update details {}", intf); @@ -1077,7 +1082,7 @@ public class OF13Provider implements ConfigInterface, NetworkingProvider { * VM, the tunnelin and broadcast rule will not be present in C1. * So, handling it in the case below to make ping work. */ - if(securityServicesManager.getNeutronPortFromDhcpIntf(intf) == null){ + if (securityServicesManager.getNeutronPortFromDhcpIntf(intf) == null){ programTunnelRules(networkType, segmentationId, src, dstBridgeNode, intf, true); } @@ -1090,7 +1095,19 @@ public class OF13Provider implements ConfigInterface, NetworkingProvider { */ List ports = southbound.getTerminationPointsOfBridge(dstBridgeNode); for (OvsdbTerminationPointAugmentation port : ports) { - if(network == tenantNetworkManager.getTenantNetwork(port)){ + + NeutronNetwork neutronNetwork = tenantNetworkManager.getTenantNetwork(port); + if (neutronNetwork != null) { + String netType = neutronNetwork.getProviderNetworkType(); + String segId = neutronNetwork.getProviderSegmentationID(); + InetAddress dstAddr = configurationService.getTunnelEndPoint(dstBridgeNode); + + if (segId != null && netType != null && dstAddr != null) { + programTunnelRules(netType, segId, dstAddr, srcBridgeNode, port, false); + } + } + + if (network == tenantNetworkManager.getTenantNetwork(port)){ programTunnelRules(networkType, segmentationId, dst, srcBridgeNode, port, false); } else{ @@ -1103,16 +1120,41 @@ public class OF13Provider implements ConfigInterface, NetworkingProvider { } } + private boolean bridgeHasVmPort(Node bridgeNode) { + String intBridgeName = configurationService.getIntegrationBridgeName(); + String extBridgeName = configurationService.getExternalBridgeName(); + List terminationPoints = bridgeNode.getTerminationPoint(); + if (terminationPoints == null) return false; + + for (TerminationPoint tp : terminationPoints) { + String tpName = tp.getTpId().getValue(); + if (tpName != null && !tpName.equals(intBridgeName) && !tpName.equals(extBridgeName)) { + OvsdbTerminationPointAugmentation tpAug = tp.getAugmentation(OvsdbTerminationPointAugmentation.class); + if (tpAug != null && southbound.getOFPort(tpAug) != 0) { + return true; + } + } + } + + return false; + } + @Override - public boolean handleInterfaceUpdate(NeutronNetwork network, Node srcNode, - OvsdbTerminationPointAugmentation intf) { + public boolean handleInterfaceUpdate(NeutronNetwork network, Node srcNode, OvsdbTerminationPointAugmentation intf) { + LOG.debug("handleInterfaceUpdate: network: {} srcNode: {}, intf: {}", + network.getProviderSegmentationID(), srcNode.getNodeId(), intf.getName()); Preconditions.checkNotNull(nodeCacheManager); + + org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId srcNodeId = + srcNode.getNodeId(); Map nodes = nodeCacheManager.getOvsdbNodes(); + nodes.remove(southbound.extractBridgeOvsdbNodeId(srcNode)); String networkType = network.getProviderNetworkType(); String segmentationId = network.getProviderSegmentationID(); Node srcBridgeNode = southbound.getBridgeNode(srcNode, configurationService.getIntegrationBridgeName()); + programLocalRules(networkType, network.getProviderSegmentationID(), srcBridgeNode, intf); if (isVlan(networkType)) { @@ -1130,7 +1172,7 @@ public class OF13Provider implements ConfigInterface, NetworkingProvider { Node dstBridgeNode = southbound.getBridgeNode(dstNode, configurationService.getIntegrationBridgeName()); - if(dstBridgeNode != null){ + if (dstBridgeNode != null){ destTunnelStatus = addTunnelPort(dstBridgeNode, networkType, dst, src); } @@ -1139,8 +1181,12 @@ public class OF13Provider implements ConfigInterface, NetworkingProvider { } if (destTunnelStatus) { programTunnelRules(networkType, segmentationId, src, dstBridgeNode, intf, false); - programTunnelRulesInNewNode(network, networkType, segmentationId, src, dst, - srcBridgeNode, dstBridgeNode, intf); + + if (srcNodeId != null && intBridgesWithoutVmPorts.contains(srcNodeId)) { + programTunnelRulesInNewNode(network, networkType, segmentationId, src, dst, + srcBridgeNode, dstBridgeNode, intf); + intBridgesWithoutVmPorts.remove(srcNodeId); + } } } else { LOG.warn("Tunnel end-point configuration missing. Please configure it in OpenVSwitch Table. " @@ -1151,6 +1197,10 @@ public class OF13Provider implements ConfigInterface, NetworkingProvider { } } + if (srcNodeId != null && !bridgeHasVmPort(srcNode)) { + intBridgesWithoutVmPorts.add(srcNodeId); + } + return true; } @@ -1213,7 +1263,7 @@ public class OF13Provider implements ConfigInterface, NetworkingProvider { removeTunnelRules(tunnelType, network.getProviderSegmentationID(), dst, srcNode, intf, true, isLastInstanceOnNode); Node dstBridgeNode = southbound.getBridgeNode(dstNode, Constants.INTEGRATION_BRIDGE); - if(dstBridgeNode != null){ + if (dstBridgeNode != null){ LOG.info("Remove tunnel rules for interface " + intf.getName() + " on dstNode " + dstNode.getNodeId().getValue()); removeTunnelRules(tunnelType, network.getProviderSegmentationID(), diff --git a/openstack/net-virt/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/impl/SouthboundImpl.java b/openstack/net-virt/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/impl/SouthboundImpl.java index 0f8759154c..43588cb616 100644 --- a/openstack/net-virt/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/impl/SouthboundImpl.java +++ b/openstack/net-virt/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/impl/SouthboundImpl.java @@ -736,4 +736,5 @@ public class SouthboundImpl implements Southbound { } return ovsdbBridgeAugmentation; } + }