Bug 7392: L2 Forwarding Table=110 Flows Missing 53/51653/2
authorhari.pr <hari.pr@hcl.com>
Fri, 3 Feb 2017 18:07:56 +0000 (23:37 +0530)
committerSam Hague <shague@redhat.com>
Mon, 20 Feb 2017 17:20:54 +0000 (17:20 +0000)
 * Problem:  While creation of very first subnet or Vm in CSIT environment,
              respective 110 flow is missing in openstack nodes.
 * Solution: Installed missing table#110 flows as part of Vxlan interface request.

Change-Id: Ie7eb35b50aaaafa79fd8ed0f0893ab37156f431e
Signed-off-by: hari.pr <hari.pr@hcl.com>
(cherry picked from commit afdb2934eeea67006631cd313c6581772ed4230d)

openstack/net-virt/src/main/java/org/opendaylight/netvirt/openstack/netvirt/ConfigActivator.java
openstack/net-virt/src/main/java/org/opendaylight/netvirt/openstack/netvirt/SouthboundHandler.java
openstack/net-virt/src/main/java/org/opendaylight/netvirt/openstack/netvirt/api/Constants.java

index 7102bc29560bd4da9a2f90c0f3ba801c540d0aba..49559d351d62571fc9b8da3791294b982703058f 100644 (file)
@@ -27,6 +27,7 @@ import org.opendaylight.netvirt.openstack.netvirt.api.IcmpEchoProvider;
 import org.opendaylight.netvirt.openstack.netvirt.api.InboundNatProvider;
 import org.opendaylight.netvirt.openstack.netvirt.api.IngressAclProvider;
 import org.opendaylight.netvirt.openstack.netvirt.api.L3ForwardingProvider;
+import org.opendaylight.netvirt.openstack.netvirt.api.L2ForwardingProvider;
 import org.opendaylight.netvirt.openstack.netvirt.api.LoadBalancerProvider;
 import org.opendaylight.netvirt.openstack.netvirt.api.MultiTenantAwareRouter;
 import org.opendaylight.netvirt.openstack.netvirt.api.NetworkingProviderManager;
@@ -256,7 +257,7 @@ public class ConfigActivator implements BundleActivator {
         // addingService may not be called if the service is already available when the ServiceTracker
         // is started
         trackService(context, INeutronNetworkCRUD.class, tenantNetworkManager, networkHandler, lBaaSHandler,
-                lBaaSPoolHandler, lBaaSPoolMemberHandler, neutronL3Adapter, distributedArpService, vlanProvider);
+                lBaaSPoolHandler, lBaaSPoolMemberHandler, neutronL3Adapter, distributedArpService, vlanProvider, southboundHandler);
         trackService(context, INeutronSubnetCRUD.class, lBaaSHandler, lBaaSPoolHandler, lBaaSPoolMemberHandler,
                 securityServices, neutronL3Adapter);
         trackService(context, INeutronPortCRUD.class, tenantNetworkManager, lBaaSHandler, lBaaSPoolHandler,
@@ -265,6 +266,7 @@ public class ConfigActivator implements BundleActivator {
         trackService(context, INeutronLoadBalancerCRUD.class, lBaaSHandler, lBaaSPoolHandler, lBaaSPoolMemberHandler);
         trackService(context, INeutronLoadBalancerPoolCRUD.class, lBaaSHandler, lBaaSPoolMemberHandler);
         trackService(context, LoadBalancerProvider.class, lBaaSHandler, lBaaSPoolHandler, lBaaSPoolMemberHandler);
+        trackService(context, L2ForwardingProvider.class, southboundHandler);
         trackService(context, ArpProvider.class, neutronL3Adapter, distributedArpService);
         trackService(context, VLANProvider.class, neutronL3Adapter, vlanProvider);
         trackService(context, InboundNatProvider.class, neutronL3Adapter);
index 86792895f0ca6e84692b9a77908743525752a8f2..2b33230f514dbf2d184673c47e3d7e564dcbce1d 100644 (file)
@@ -8,13 +8,18 @@
 
 package org.opendaylight.netvirt.openstack.netvirt;
 
+import java.net.InetAddress;
 import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
 
 import org.opendaylight.netvirt.openstack.netvirt.api.Action;
 import org.opendaylight.netvirt.openstack.netvirt.api.BridgeConfigurationManager;
 import org.opendaylight.netvirt.openstack.netvirt.api.ConfigurationService;
 import org.opendaylight.netvirt.openstack.netvirt.api.Constants;
 import org.opendaylight.netvirt.openstack.netvirt.api.EventDispatcher;
+import org.opendaylight.netvirt.openstack.netvirt.api.L2ForwardingProvider;
 import org.opendaylight.netvirt.openstack.netvirt.api.NetworkingProviderManager;
 import org.opendaylight.netvirt.openstack.netvirt.api.NodeCacheListener;
 import org.opendaylight.netvirt.openstack.netvirt.api.NodeCacheManager;
@@ -24,12 +29,15 @@ import org.opendaylight.netvirt.openstack.netvirt.api.Southbound;
 import org.opendaylight.netvirt.openstack.netvirt.api.TenantNetworkManager;
 import org.opendaylight.netvirt.openstack.netvirt.translator.NeutronNetwork;
 import org.opendaylight.netvirt.openstack.netvirt.translator.NeutronPort;
+import org.opendaylight.netvirt.openstack.netvirt.translator.crud.INeutronNetworkCRUD;
 import org.opendaylight.netvirt.openstack.netvirt.impl.DistributedArpService;
 import org.opendaylight.netvirt.openstack.netvirt.impl.NeutronL3Adapter;
 import org.opendaylight.netvirt.utils.servicehelper.ServiceHelper;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeVxlan;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentation;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.Options;
 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.DataObject;
@@ -55,9 +63,11 @@ public class SouthboundHandler extends AbstractHandler
     private volatile NeutronL3Adapter neutronL3Adapter;
     private volatile DistributedArpService distributedArpService;
     private volatile NodeCacheManager nodeCacheManager;
+    private volatile INeutronNetworkCRUD neutronNetworkCache;
     private volatile OvsdbInventoryService ovsdbInventoryService;
     private volatile Southbound southbound;
     private volatile VLANProvider vlanProvider;
+    private volatile L2ForwardingProvider l2ForwardingProvider;
 
     private SouthboundEvent.Type ovsdbTypeToSouthboundEventType(OvsdbType ovsdbType) {
         SouthboundEvent.Type type = SouthboundEvent.Type.NODE;
@@ -346,7 +356,67 @@ public class SouthboundHandler extends AbstractHandler
             } else if (action != null && action.equals(Action.UPDATE)) {
                 programVLANNetworkFlowProvider(node, port, network, neutronPort, true);
             }
+        } else if (null != port.getInterfaceType() && null != port.getOfport()) {
+            // Filter Vxlan interface request and install table#110 unicast flow (Bug 7392).
+            if(port.getInterfaceType().equals(InterfaceTypeVxlan.class)) {
+                List<Options> optionList = port.getOptions();
+                if (null != optionList && !optionList.isEmpty()) {
+                    optionList.stream().filter(option -> isRemoteIp(option)).forEach(option ->
+                            handleTunnelOut(node, option.getValue(), port.getOfport()));
+                }
+            }
+        }
+    }
+
+    private boolean isRemoteIp(Options option) {
+        return option.getOption().equals(Constants.TUNNEL_ENDPOINT_KEY_REMOTE);
+    }
+
+    private void handleTunnelOut(Node node, String remoteIp, Long ofPort) {
+        List<Node> nodes = nodeCacheManager.getBridgeNodes();
+        if (null != nodes && !nodes.isEmpty()) {
+            nodes.stream().filter(dstnode -> isDstNode(node, dstnode, remoteIp)).forEach(dstnode ->
+                    programTunnelOut(node, dstnode, ofPort));
+        }
+    }
+
+    private boolean isDstNode(Node node, Node dstnode, String remoteIp) {
+        if (!(node.getNodeId().getValue().equals(dstnode.getNodeId().getValue()))) {
+            InetAddress dst = configurationService.getTunnelEndPoint(dstnode);
+            String dstIp = dst.getHostAddress();
+            if (remoteIp.equals(dstIp)) {
+                 return true;
+            }
         }
+        return false;
+    }
+
+    private void programTunnelOut(Node node, Node dstnode, Long ofPort) {
+        List<OvsdbTerminationPointAugmentation> ports = southbound.readTerminationPointAugmentations(dstnode);
+        for (OvsdbTerminationPointAugmentation destport : ports) {
+            NeutronPort neutronPort = tenantNetworkManager.getTenantPort(destport);
+            if (neutronPort != null) {
+                final String networkUUID = neutronPort.getNetworkUUID();
+                NeutronNetwork neutronNetwork = neutronNetworkCache.getNetwork(networkUUID);
+                if (null == neutronNetwork) {
+                    neutronNetwork = neutronL3Adapter.getNetworkFromCleanupCache(networkUUID);
+                }
+                final String segmentationId = neutronNetwork != null ? neutronNetwork.getProviderSegmentationID() : null;
+                final String macAddress = neutronPort.getMacAddress();
+                long dpid = getIntegrationBridgeOFDPID(node);
+                if (null != l2ForwardingProvider) {
+                    l2ForwardingProvider.programTunnelOut(dpid, segmentationId, ofPort, macAddress, true);
+                }
+            }
+        }
+    }
+
+    private long getIntegrationBridgeOFDPID(Node node) {
+        long dpid = 0L;
+        if (southbound.getBridgeName(node).equals(configurationService.getIntegrationBridgeName())) {
+            dpid = southbound.getDataPathId(node);
+        }
+        return dpid;
     }
 
     private void programVLANNetworkFlowProvider(final Node node, final OvsdbTerminationPointAugmentation port,
@@ -428,7 +498,6 @@ public class SouthboundHandler extends AbstractHandler
             southbound.deleteBridge(node);
         }
     }
-
     @Override
     public void setDependencies(ServiceReference serviceReference) {
         configurationService =
@@ -456,9 +525,16 @@ public class SouthboundHandler extends AbstractHandler
         ovsdbInventoryService.listenerAdded(this);
         vlanProvider =
                 (VLANProvider) ServiceHelper.getGlobalInstance(VLANProvider.class, this);
+        l2ForwardingProvider =
+                (L2ForwardingProvider) ServiceHelper.getGlobalInstance(L2ForwardingProvider.class, this);
     }
 
     @Override
     public void setDependencies(Object impl) {
+        if (impl instanceof INeutronNetworkCRUD) {
+            neutronNetworkCache = (INeutronNetworkCRUD)impl;
+        } else if (impl instanceof L2ForwardingProvider) {
+            l2ForwardingProvider = (L2ForwardingProvider)impl;
+        }
     }
 }
index b29c623c1d157f100ab5f9bfa2e3f083f4ab0510..a69e712e8e995780c0a5da7476e4ee46a0acae8c 100644 (file)
@@ -25,6 +25,7 @@ public final class Constants {
      * @see http://docs.openstack.org/grizzly/openstack-network/admin/content/ovs_quantum_plugin.html
      */
     public static final String TUNNEL_ENDPOINT_KEY = "local_ip";
+    public static final String TUNNEL_ENDPOINT_KEY_REMOTE = "remote_ip";
     public static final String INTEGRATION_BRIDGE = "br-int";
     public static final String NETWORK_BRIDGE = "br-net";
     public static final String EXTERNAL_BRIDGE = "br-ex";